Type Mapping
These tables describe release 0.1.8 and were checked against the published xqdb wheel and the @xbbg/xqdb package. For nulls and infinities, see Values, Nulls, and Text.
q to Python
| q type | Type number | Python value | Notes |
|---|---|---|---|
| boolean | -1 | bool | |
| guid | -2 | str | Hyphenated form, for example 12345678-1234-5678-1234-567812345678 |
| byte | -4 | int | |
| short, int, long | -5, -6, -7 | int | Null and infinity atoms come back as their raw integer values |
| real, float | -8, -9 | float | |
| char | -10 | str | One character |
| symbol | -11 | str | Follows symbol_encoding |
| timestamp | -12 | datetime.datetime, naive | ValueError if the value has digits below a microsecond |
| month | -13 | datetime.date | The first day of the month |
| date | -14 | datetime.date | OverflowError outside the years 1 to 9999 |
| datetime | -15 | datetime.datetime, naive | |
| timespan | -16 | datetime.timedelta | ValueError if the value has digits below a microsecond |
| minute, second, time | -17, -18, -19 | datetime.time | |
| string (char vector) | 10 | str, or bytes if the bytes are not valid UTF-8 | Not affected by symbol_encoding |
| Typed list | 1 to 19, except 10 | narwhals.Series | The column types are in q columns to Arrow. month lists are not supported. |
| General list | 0 | tuple | Converted element by element |
| Dictionary | 99 | dict | Keys must be symbols. An empty dictionary, including ()!(), becomes {}. |
| Table | 98 | narwhals.DataFrame | |
| Keyed table | 99 | narwhals.DataFrame | Key columns first, then value columns |
| Lambda | 100 | xqdb.XqdbQLambda | .source and .context |
| Primitive | 101 to 103 | xqdb.XqdbQOperator | .name, for example "+" |
Generic null :: | 101 | () | An empty tuple, not None |
| Error | -128 | Raises xqdb.XqdbError | The message reads Internal Server Error - "<q error>" |
A dictionary whose keys are not symbols raises XqdbError.
q columns to Arrow
Table columns and typed lists are decoded into Arrow. The Arrow types that Python sees through PyArrow and that Node.js sees through apache-arrow differ slightly, because Node.js receives them over Arrow IPC:
| q column | PyArrow type (Python) | apache-arrow type (Node.js) | Nulls |
|---|---|---|---|
| boolean | bool | Bool | |
| guid | binary_view, 16 bytes per value | LargeBinary | |
| byte | uint8 | Uint8 | |
| short, int, long | int16, int32, int64 | Int16, Int32, Int64 | 0N and ±0W become null |
| real, float | float, double | Float32, Float64 | 0n becomes null; ±0w stays ±inf |
| char | string_view | LargeUtf8 | |
| string (general list of char vectors) | string_view | LargeUtf8 | |
| symbol | dictionary<values=string_view, indices=uint32> | Dictionary<Uint32, LargeUtf8> | |
| timestamp | timestamp[ns] | Timestamp<NANOSECOND> | 0Np becomes null |
| month | Not supported | Not supported | |
| date | date32[day] | Date32<DAY> | 0Nd becomes null |
| datetime | timestamp[ns] | Timestamp<NANOSECOND> | 0Nz becomes null |
| timespan | duration[ns] | Duration<NANOSECOND> | 0Nn becomes null |
| minute, second, time | time64[ns] | Time64<NANOSECOND> | 0Nu, 0Nv, 0Nt become null |
| Nested typed lists, for example a float list per row | large_list<…> | LargeList<…> |
With the pandas or Polars backend, Narwhals builds the backend's own types from these Arrow columns. Symbols become pandas category or Polars Categorical, for example. See DataFrames and Arrow.
Python to q
| Python value | q value | Notes |
|---|---|---|
None | generic null :: | |
bool | boolean | |
int | long | OverflowError outside the signed 64-bit range |
float | float | |
str | symbol | XqdbError if it contains a NUL character |
bytes | string (char vector) | Every byte is kept |
datetime.datetime | timestamp | A naive value is sent as-is. An aware value is converted to UTC. |
pandas.Timestamp | timestamp | Keeps the extra digits in .nanosecond |
datetime.date | date | |
datetime.time | time | Must be whole milliseconds, otherwise ValueError |
datetime.timedelta | timespan | |
dict with str keys | dictionary with symbol keys | {} becomes (`symbol$())!(). Other key types raise TypeError. |
list, tuple | general list | |
xqdb.XqdbQOperator | primitive | |
xqdb.XqdbQLambda | lambda | |
Eager DataFrame: pyarrow.Table, pandas, Polars, Narwhals | table | Columns follow the table below |
Eager Series: pyarrow.ChunkedArray, pandas, Polars, Narwhals | typed list | |
| Lazy frame | TypeError | Collect it first |
Anything else, including set and a bare pyarrow.Array | TypeError |
Values can nest at most 64 levels deep, and cyclic containers raise ValueError.
Arrow columns to q
The same rules apply to Node.js Table and Vector arguments, which reach the core as Arrow IPC.
| Arrow type | q type |
|---|---|
bool | boolean |
uint8 | byte |
int16, int32, int64 | short, int, long |
float32, float64 | real, float |
string, large_string, string_view | general list of strings |
dictionary<string> (pandas category, Polars Categorical) | symbol |
fixed_size_binary(16), or binary values that are all 16 bytes | guid |
date32 | date |
timestamp[ms] | datetime |
timestamp[us], timestamp[ns], with or without a time zone | timestamp |
duration | timespan |
time32, time64 | time, whole milliseconds only |
list or fixed_size_list of booleans or numbers | general list of typed lists |
Other Arrow types, such as int8, uint16, uint32, and uint64, raise an error. Arrow nulls become the q null of the column's type.
q to JavaScript
| q type | JavaScript value |
|---|---|
| boolean | boolean |
| guid | string |
| byte, short, int | number |
| long | bigint |
| real, float | number |
| char | number, the byte value |
| symbol | string |
| timestamp, datetime | XqdbTimestamp, nanoseconds since the Unix epoch |
| month | XqdbDate, the first day of the month |
| date | XqdbDate |
| timespan | XqdbTimespan |
| minute, second, time | XqdbTime, nanoseconds since midnight |
| string (char vector) | Buffer, holding the raw bytes |
| Typed list | Arrow Vector. month lists are not supported. |
| General list | Array |
| Dictionary | Plain object. An empty dictionary becomes {}. |
| Table, keyed table | Arrow Table, with key columns first for a keyed table |
| Lambda | XqdbQLambda |
| Primitive | XqdbQOperator |
Generic null :: | null |
| Error | Rejects with XqdbError, code XQDB_SERVER |
JavaScript to q
| JavaScript value | q value | Notes |
|---|---|---|
null | generic null :: | |
boolean | boolean | |
number | float | Use bigint for a long |
bigint | long | |
string | symbol | Rejected if it contains NUL |
Buffer, Uint8Array | string (char vector) | Every byte is kept |
| Array | general list | |
| Plain object with string keys | dictionary with symbol keys | {} becomes (`symbol$())!() |
Arrow Vector | typed list | Columns follow Arrow columns to q |
Arrow Table | table | |
XqdbTimestamp | timestamp | |
XqdbDate | date | YYYY-MM-DD |
XqdbTime | time | Whole milliseconds, less than one day |
XqdbTimespan | timespan | |
XqdbQOperator | primitive | |
XqdbQLambda | lambda |
Anything else, such as undefined, a Date, a Map, a class instance, or a cyclic structure, rejects with XQDB_CONVERSION. Values can nest at most 64 levels deep.
Operators and lambdas
XqdbQOperator(name) accepts these q primitive names. Each group is listed in wire order.
- Unary (type 101):
+:-:*:%:&:|:^:=:<:>:$:,:#:_:~:!:?:@:.:0::1::2::avglastsumprdminmaxexitgetenvabssqrtlogexpsinasincosacostanatanenlist - Binary (type 102):
:+-*%&|^=<>$,#_~!?@.0:1:2:inwithinlikebinssinsertwsumwavgdivxexpsetenv - Ternary (type 103):
'/\
XqdbQLambda(source, context) sends a q lambda. source must be enclosed in braces, optionally prefixed with k). context is a namespace name without its leading dot, such as "analytics" for .analytics. Neither field may contain NUL. Both classes are immutable and are also what xqdb returns when q sends back a primitive or a function. See Queries and Subscriptions.
