TypeId Reference
quack_rs::types::TypeId is the enum of DuckDB column types that the quack-rs
builder APIs accept. Each variant names one of the C API's DUCKDB_TYPE_*
integer constants, which libduckdb-sys exposes as
DUCKDB_TYPE_DUCKDB_TYPE_* (for example
libduckdb_sys::DUCKDB_TYPE_DUCKDB_TYPE_BIGINT).
Full variant table
| Variant | SQL name | C API constant | Notes |
|---|---|---|---|
TypeId::Boolean | BOOLEAN | DUCKDB_TYPE_BOOLEAN | true/false, stored as a u8 |
TypeId::TinyInt | TINYINT | DUCKDB_TYPE_TINYINT | 8-bit signed |
TypeId::SmallInt | SMALLINT | DUCKDB_TYPE_SMALLINT | 16-bit signed |
TypeId::Integer | INTEGER | DUCKDB_TYPE_INTEGER | 32-bit signed |
TypeId::BigInt | BIGINT | DUCKDB_TYPE_BIGINT | 64-bit signed |
TypeId::UTinyInt | UTINYINT | DUCKDB_TYPE_UTINYINT | 8-bit unsigned |
TypeId::USmallInt | USMALLINT | DUCKDB_TYPE_USMALLINT | 16-bit unsigned |
TypeId::UInteger | UINTEGER | DUCKDB_TYPE_UINTEGER | 32-bit unsigned |
TypeId::UBigInt | UBIGINT | DUCKDB_TYPE_UBIGINT | 64-bit unsigned |
TypeId::HugeInt | HUGEINT | DUCKDB_TYPE_HUGEINT | 128-bit signed |
TypeId::Float | FLOAT | DUCKDB_TYPE_FLOAT | 32-bit IEEE 754 |
TypeId::Double | DOUBLE | DUCKDB_TYPE_DOUBLE | 64-bit IEEE 754 |
TypeId::Timestamp | TIMESTAMP | DUCKDB_TYPE_TIMESTAMP | µs since Unix epoch |
TypeId::TimestampTz | TIMESTAMPTZ | DUCKDB_TYPE_TIMESTAMP_TZ | timezone-aware timestamp |
TypeId::Date | DATE | DUCKDB_TYPE_DATE | days since epoch |
TypeId::Time | TIME | DUCKDB_TYPE_TIME | µs since midnight |
TypeId::Interval | INTERVAL | DUCKDB_TYPE_INTERVAL | months + days + µs |
TypeId::Varchar | VARCHAR | DUCKDB_TYPE_VARCHAR | UTF-8 string |
TypeId::Blob | BLOB | DUCKDB_TYPE_BLOB | binary data |
TypeId::Decimal | DECIMAL | DUCKDB_TYPE_DECIMAL | fixed-point decimal |
TypeId::TimestampS | TIMESTAMP_S | DUCKDB_TYPE_TIMESTAMP_S | seconds since epoch |
TypeId::TimestampMs | TIMESTAMP_MS | DUCKDB_TYPE_TIMESTAMP_MS | milliseconds since epoch |
TypeId::TimestampNs | TIMESTAMP_NS | DUCKDB_TYPE_TIMESTAMP_NS | nanoseconds since epoch |
TypeId::Enum | ENUM | DUCKDB_TYPE_ENUM | enumeration type |
TypeId::List | LIST | DUCKDB_TYPE_LIST | variable-length list |
TypeId::Struct | STRUCT | DUCKDB_TYPE_STRUCT | named fields (row type) |
TypeId::Map | MAP | DUCKDB_TYPE_MAP | key-value pairs |
TypeId::Uuid | UUID | DUCKDB_TYPE_UUID | 128-bit UUID |
TypeId::Union | UNION | DUCKDB_TYPE_UNION | tagged union of types |
TypeId::Bit | BIT | DUCKDB_TYPE_BIT | bitstring |
TypeId::TimeTz | TIMETZ | DUCKDB_TYPE_TIME_TZ | timezone-aware time |
TypeId::UHugeInt | UHUGEINT | DUCKDB_TYPE_UHUGEINT | 128-bit unsigned |
TypeId::Array | ARRAY | DUCKDB_TYPE_ARRAY | fixed-length array |
TypeId::TimeNs | TIME_NS | DUCKDB_TYPE_TIME_NS | nanosecond-precision time |
TypeId::Any | ANY | DUCKDB_TYPE_ANY | wildcard for function signatures |
TypeId::Varint | BIGNUM | DUCKDB_TYPE_BIGNUM | arbitrary-precision integer (VARINT before DuckDB 1.4) |
TypeId::SqlNull | SQLNULL | DUCKDB_TYPE_SQLNULL | explicit SQL NULL type |
TypeId::IntegerLiteral | INTEGER_LITERAL | DUCKDB_TYPE_INTEGER_LITERAL | unresolved integer literal |
TypeId::StringLiteral | STRING_LITERAL | DUCKDB_TYPE_STRING_LITERAL | unresolved string literal |
TypeId::Geometry | GEOMETRY | DUCKDB_TYPE_GEOMETRY | spatial geometry value (duckdb-1-5-3) |
TypeId::Variant | VARIANT | DUCKDB_TYPE_VARIANT | self-describing nested value, e.g. Iceberg v3 (duckdb-1-5-3) |
Feature gate for
Geometry/Variant:DUCKDB_TYPE_GEOMETRY(40) andDUCKDB_TYPE_VARIANT(41) require theduckdb-1-5-3feature, which layers on top ofduckdb-1-5and needslibduckdb-sys >= 1.10503.0(DuckDB 1.5.3).VARIANTentered the C type enum in DuckDB 1.5.3, after theduckdb-1-5feature's 1.5.0 floor, andGEOMETRYis gated with it so that one feature covers both. Gating them separately avoids breaking consumers pinned to libduckdb-sys 1.10500–1.10502 (DuckDB 1.5.0–1.5.2). See Known Limitations.
Methods
to_duckdb_type() → DUCKDB_TYPE
Converts to the raw C API integer constant. Used internally by the builder APIs.
#![allow(unused)] fn main() { use quack_rs::types::TypeId; let raw: libduckdb_sys::DUCKDB_TYPE = TypeId::BigInt.to_duckdb_type(); }
from_duckdb_type(raw) → TypeId
Converts a raw DUCKDB_TYPE constant back into a TypeId. Recognizes every
variant available in the active feature set, including TIME_NS, ANY,
BIGNUM, SQLNULL, INTEGER_LITERAL and STRING_LITERAL (no feature needed:
all six exist in every DuckDB this crate supports) and the duckdb-1-5-3
values (GEOMETRY, VARIANT) when that feature is enabled.
Panics if the value does not correspond to any variant available in the current
feature configuration; try_from_duckdb_type returns None instead.
#![allow(unused)] fn main() { use quack_rs::types::TypeId; let type_id = TypeId::from_duckdb_type(libduckdb_sys::DUCKDB_TYPE_DUCKDB_TYPE_BIGINT); assert_eq!(type_id, TypeId::BigInt); assert_eq!(TypeId::try_from_duckdb_type(9_999), None); }
is_composite() and composite_constructor_hint()
DECIMAL, ENUM, LIST, STRUCT, MAP, ARRAY and UNION carry parameters
that a bare type id cannot express, so duckdb_create_logical_type cannot build
them. is_composite() returns true for these seven, and
composite_constructor_hint() names the LogicalType constructor to use
instead:
#![allow(unused)] fn main() { use quack_rs::types::TypeId; assert!(TypeId::List.is_composite()); assert_eq!( TypeId::List.composite_constructor_hint(), Some("LogicalType::list(element_type)") ); assert_eq!(TypeId::BigInt.composite_constructor_hint(), None); }
sql_name() → &'static str
Returns the SQL type name as a static string.
#![allow(unused)] fn main() { use quack_rs::types::TypeId; assert_eq!(TypeId::BigInt.sql_name(), "BIGINT"); assert_eq!(TypeId::Varchar.sql_name(), "VARCHAR"); assert_eq!(TypeId::TimestampTz.sql_name(), "TIMESTAMPTZ"); }
Display
TypeId implements Display, which outputs the SQL name:
#![allow(unused)] fn main() { use quack_rs::types::TypeId; println!("{}", TypeId::Interval); // prints: INTERVAL let s = format!("{}", TypeId::UBigInt); // "UBIGINT" assert_eq!(s, "UBIGINT"); assert_eq!(TypeId::Interval.to_string(), "INTERVAL"); }
VectorReader/VectorWriter mapping
The read and write methods on VectorReader/VectorWriter map to TypeId
variants as follows:
| TypeId | Read method | Write method | Rust type |
|---|---|---|---|
Boolean | read_bool | write_bool | bool |
TinyInt | read_i8 | write_i8 | i8 |
SmallInt | read_i16 | write_i16 | i16 |
Integer | read_i32 | write_i32 | i32 |
BigInt | read_i64 | write_i64 | i64 |
UTinyInt | read_u8 | write_u8 | u8 |
USmallInt | read_u16 | write_u16 | u16 |
UInteger | read_u32 | write_u32 | u32 |
UBigInt | read_u64 | write_u64 | u64 |
Float | read_f32 | write_f32 | f32 |
Double | read_f64 | write_f64 | f64 |
Varchar | read_str | write_varchar | &str |
Interval | read_interval | write_interval | DuckInterval |
HugeInt | read_i128 | write_i128 | i128 |
UHugeInt | read_u128 | write_u128 | u128 |
Blob | read_blob | write_blob | &[u8] |
Uuid | read_uuid | write_uuid | u128 (textual bits) |
Date | read_date | write_date | i32 (days since epoch) |
Time | read_time | write_time | i64 (µs since midnight) |
TimeTz | read_time_tz | write_time_tz | u64 (packed) |
Timestamp | read_timestamp | write_timestamp | i64 (µs since epoch) |
TimestampTz | read_timestamp_tz | write_timestamp_tz | i64 (µs since epoch) |
TimestampS | read_timestamp_s | write_timestamp_s | i64 (s since epoch) |
TimestampMs | read_timestamp_ms | write_timestamp_ms | i64 (ms since epoch) |
TimestampNs | read_timestamp_ns | write_timestamp_ns | i64 (ns since epoch) |
Decimal | read_decimal(row, width) | write_decimal(row, width, v) | i128 (unscaled) |
List, Map, Struct and Array are nested vectors: use the helpers in
Complex Types (ListVector, MapVector,
StructVector, ArrayVector, StructReader / StructWriter, ListBuilder).
Enum, Union, Bit, TimeNs, Any, Varint, SqlNull, IntegerLiteral,
StringLiteral, Geometry and Variant do not yet have dedicated read/write
helpers. Access these via the raw data pointer from duckdb_vector_get_data.
Properties
TypeId implements Debug, Clone, Copy, PartialEq, Eq, and Hash, so
it can be used as a map key or set element and compared in match expressions:
#![allow(unused)] fn main() { use std::collections::HashMap; use quack_rs::types::TypeId; let mut type_names: HashMap<TypeId, &str> = HashMap::new(); type_names.insert(TypeId::BigInt, "count"); type_names.insert(TypeId::Varchar, "label"); }
#[non_exhaustive]
TypeId is marked #[non_exhaustive], so quack-rs can add variants for new
DuckDB types without a breaking change. A match on TypeId outside quack-rs
needs a wildcard arm:
#![allow(unused)] fn main() { use quack_rs::types::TypeId; fn demo(type_id: TypeId) { match type_id { TypeId::BigInt => { /* ... */ } TypeId::Varchar => { /* ... */ } _ => { /* handle future types */ } } } }
LogicalType
For types that require parameters (such as DECIMAL(p, s) or LIST(INTEGER)),
use quack_rs::types::LogicalType:
#![allow(unused)] fn main() { use quack_rs::types::{LogicalType, TypeId}; let lt = LogicalType::new(TypeId::BigInt); // or use the From impl: let lt: LogicalType = TypeId::BigInt.into(); // LogicalType implements Drop → calls duckdb_destroy_logical_type automatically }
LogicalType wraps duckdb_logical_type with RAII cleanup, preventing the
memory leak described in Pitfall L7.
Constructors
| Constructor | Creates |
|---|---|
new(type_id) | Simple type from a TypeId |
from_raw(ptr) | Takes ownership of a raw handle (unsafe) |
decimal(width, scale) | DECIMAL(width, scale) |
list(element_type) | LIST<T> from a TypeId |
list_from_logical(element) | LIST<T> from an existing LogicalType |
map(key, value) | MAP<K, V> from TypeIds |
map_from_logical(key, value) | MAP<K, V> from existing LogicalTypes |
struct_type(fields) | STRUCT from &[(&str, TypeId)] |
struct_type_from_logical(fields) | STRUCT from &[(&str, LogicalType)] |
union_type(members) | UNION from &[(&str, TypeId)] |
union_type_from_logical(members) | UNION from &[(&str, LogicalType)] |
enum_type(members) | ENUM from &[&str] |
array(element_type, size) | ARRAY<T>[size] from a TypeId |
array_from_logical(element, size) | ARRAY<T>[size] from an existing LogicalType |
Each constructor except from_raw has a try_ form (try_new,
try_decimal, try_list, …) that returns an error instead of panicking on
invalid input, such as a composite TypeId passed to new, a DECIMAL width
above 38, or a UNION with more than MAX_UNION_MEMBERS (255) members.
Introspection methods
The introspection methods are all unsafe, because they call into a loaded
DuckDB:
get_type_id, get_alias, set_alias, decimal_width, decimal_scale,
decimal_internal_type, enum_internal_type, enum_dictionary_size,
enum_dictionary_value, list_child_type, map_key_type, map_value_type,
struct_child_count, struct_child_name, struct_child_type,
union_member_count, union_member_name, union_member_type,
array_size, array_child_type.
See Type System for the full introspection table.