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

VariantSQL nameC API constantNotes
TypeId::BooleanBOOLEANDUCKDB_TYPE_BOOLEANtrue/false, stored as a u8
TypeId::TinyIntTINYINTDUCKDB_TYPE_TINYINT8-bit signed
TypeId::SmallIntSMALLINTDUCKDB_TYPE_SMALLINT16-bit signed
TypeId::IntegerINTEGERDUCKDB_TYPE_INTEGER32-bit signed
TypeId::BigIntBIGINTDUCKDB_TYPE_BIGINT64-bit signed
TypeId::UTinyIntUTINYINTDUCKDB_TYPE_UTINYINT8-bit unsigned
TypeId::USmallIntUSMALLINTDUCKDB_TYPE_USMALLINT16-bit unsigned
TypeId::UIntegerUINTEGERDUCKDB_TYPE_UINTEGER32-bit unsigned
TypeId::UBigIntUBIGINTDUCKDB_TYPE_UBIGINT64-bit unsigned
TypeId::HugeIntHUGEINTDUCKDB_TYPE_HUGEINT128-bit signed
TypeId::FloatFLOATDUCKDB_TYPE_FLOAT32-bit IEEE 754
TypeId::DoubleDOUBLEDUCKDB_TYPE_DOUBLE64-bit IEEE 754
TypeId::TimestampTIMESTAMPDUCKDB_TYPE_TIMESTAMPµs since Unix epoch
TypeId::TimestampTzTIMESTAMPTZDUCKDB_TYPE_TIMESTAMP_TZtimezone-aware timestamp
TypeId::DateDATEDUCKDB_TYPE_DATEdays since epoch
TypeId::TimeTIMEDUCKDB_TYPE_TIMEµs since midnight
TypeId::IntervalINTERVALDUCKDB_TYPE_INTERVALmonths + days + µs
TypeId::VarcharVARCHARDUCKDB_TYPE_VARCHARUTF-8 string
TypeId::BlobBLOBDUCKDB_TYPE_BLOBbinary data
TypeId::DecimalDECIMALDUCKDB_TYPE_DECIMALfixed-point decimal
TypeId::TimestampSTIMESTAMP_SDUCKDB_TYPE_TIMESTAMP_Sseconds since epoch
TypeId::TimestampMsTIMESTAMP_MSDUCKDB_TYPE_TIMESTAMP_MSmilliseconds since epoch
TypeId::TimestampNsTIMESTAMP_NSDUCKDB_TYPE_TIMESTAMP_NSnanoseconds since epoch
TypeId::EnumENUMDUCKDB_TYPE_ENUMenumeration type
TypeId::ListLISTDUCKDB_TYPE_LISTvariable-length list
TypeId::StructSTRUCTDUCKDB_TYPE_STRUCTnamed fields (row type)
TypeId::MapMAPDUCKDB_TYPE_MAPkey-value pairs
TypeId::UuidUUIDDUCKDB_TYPE_UUID128-bit UUID
TypeId::UnionUNIONDUCKDB_TYPE_UNIONtagged union of types
TypeId::BitBITDUCKDB_TYPE_BITbitstring
TypeId::TimeTzTIMETZDUCKDB_TYPE_TIME_TZtimezone-aware time
TypeId::UHugeIntUHUGEINTDUCKDB_TYPE_UHUGEINT128-bit unsigned
TypeId::ArrayARRAYDUCKDB_TYPE_ARRAYfixed-length array
TypeId::TimeNsTIME_NSDUCKDB_TYPE_TIME_NSnanosecond-precision time
TypeId::AnyANYDUCKDB_TYPE_ANYwildcard for function signatures
TypeId::VarintBIGNUMDUCKDB_TYPE_BIGNUMarbitrary-precision integer (VARINT before DuckDB 1.4)
TypeId::SqlNullSQLNULLDUCKDB_TYPE_SQLNULLexplicit SQL NULL type
TypeId::IntegerLiteralINTEGER_LITERALDUCKDB_TYPE_INTEGER_LITERALunresolved integer literal
TypeId::StringLiteralSTRING_LITERALDUCKDB_TYPE_STRING_LITERALunresolved string literal
TypeId::GeometryGEOMETRYDUCKDB_TYPE_GEOMETRYspatial geometry value (duckdb-1-5-3)
TypeId::VariantVARIANTDUCKDB_TYPE_VARIANTself-describing nested value, e.g. Iceberg v3 (duckdb-1-5-3)

Feature gate for Geometry / Variant: DUCKDB_TYPE_GEOMETRY (40) and DUCKDB_TYPE_VARIANT (41) require the duckdb-1-5-3 feature, which layers on top of duckdb-1-5 and needs libduckdb-sys >= 1.10503.0 (DuckDB 1.5.3). VARIANT entered the C type enum in DuckDB 1.5.3, after the duckdb-1-5 feature's 1.5.0 floor, and GEOMETRY is 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:

TypeIdRead methodWrite methodRust type
Booleanread_boolwrite_boolbool
TinyIntread_i8write_i8i8
SmallIntread_i16write_i16i16
Integerread_i32write_i32i32
BigIntread_i64write_i64i64
UTinyIntread_u8write_u8u8
USmallIntread_u16write_u16u16
UIntegerread_u32write_u32u32
UBigIntread_u64write_u64u64
Floatread_f32write_f32f32
Doubleread_f64write_f64f64
Varcharread_strwrite_varchar&str
Intervalread_intervalwrite_intervalDuckInterval
HugeIntread_i128write_i128i128
UHugeIntread_u128write_u128u128
Blobread_blobwrite_blob&[u8]
Uuidread_uuidwrite_uuidu128 (textual bits)
Dateread_datewrite_datei32 (days since epoch)
Timeread_timewrite_timei64 (µs since midnight)
TimeTzread_time_tzwrite_time_tzu64 (packed)
Timestampread_timestampwrite_timestampi64 (µs since epoch)
TimestampTzread_timestamp_tzwrite_timestamp_tzi64 (µs since epoch)
TimestampSread_timestamp_swrite_timestamp_si64 (s since epoch)
TimestampMsread_timestamp_mswrite_timestamp_msi64 (ms since epoch)
TimestampNsread_timestamp_nswrite_timestamp_nsi64 (ns since epoch)
Decimalread_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

ConstructorCreates
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.