Skip to main content

DuckDB Type Support

Foundations JDBC provides comprehensive support for DuckDB's rich type system, including nested types (LIST, STRUCT, MAP, UNION) and extended integer types.

Integer Types (Signed)

DuckDB TypeJava TypeRange
TINYINTByte-128 to 127
SMALLINTShort-32,768 to 32,767
INTEGER / INTInteger-2^31 to 2^31-1
BIGINTLong-2^63 to 2^63-1
HUGEINTBigInteger-2^127 to 2^127-1
val tinyType: DuckDbType<Byte> = DuckDbTypes.tinyint
val intType: DuckDbType<Int> = DuckDbTypes.integer
val hugeType: DuckDbType<BigInteger> = DuckDbTypes.hugeint

Integer Types (Unsigned)

DuckDB TypeJava TypeRange
UTINYINTUint10 to 255
USMALLINTUint20 to 65,535
UINTEGERUint40 to 2^32-1
UBIGINTUint80 to 2^64-1
UHUGEINTBigInteger0 to 2^128-1
val utinyType: DuckDbType<Uint1> = DuckDbTypes.utinyint
val uintType: DuckDbType<Uint4> = DuckDbTypes.uinteger
val uhugeType: DuckDbType<BigInteger> = DuckDbTypes.uhugeint

Floating-Point Types

DuckDB TypeJava TypeNotes
FLOAT / FLOAT4 / REALFloat32-bit IEEE 754
DOUBLE / FLOAT8Double64-bit IEEE 754
val floatType: DuckDbType<Float> = DuckDbTypes.float_
val doubleType: DuckDbType<Double> = DuckDbTypes.double_

Fixed-Point Types

DuckDB TypeJava TypeNotes
DECIMAL(p,s)BigDecimalArbitrary precision
NUMERIC(p,s)BigDecimalAlias for DECIMAL
val decimalType: DuckDbType<BigDecimal> = DuckDbTypes.decimal
val precise: DuckDbType<BigDecimal> = DuckDbTypes.decimal(18, 6) // DECIMAL(18,6)

Boolean Type

DuckDB TypeJava Type
BOOLEAN / BOOLBoolean
val boolType: DuckDbType<Boolean> = DuckDbTypes.boolean_

String Types

DuckDB TypeJava TypeNotes
VARCHAR / STRING / TEXTStringVariable length
CHAR(n)StringFixed length
val varcharType: DuckDbType<String> = DuckDbTypes.varchar
val charType: DuckDbType<String> = DuckDbTypes.char_(10)

Binary Types

DuckDB TypeJava Type
BLOB / BYTEA / BINARY / VARBINARYbyte[]
val blobType: DuckDbType<ByteArray> = DuckDbTypes.blob

Bit String Type

DuckDB TypeJava TypeNotes
BIT / BITSTRINGStringString of 0s and 1s
val bitType: DuckDbType<String> = DuckDbTypes.bit
val bit8: DuckDbType<String> = DuckDbTypes.bit(8) // BIT(8)

Date/Time Types

DuckDB TypeJava TypeNotes
DATELocalDateDate only
TIMELocalTimeTime only
TIMESTAMP / DATETIMELocalDateTimeDate and time
TIMESTAMP WITH TIME ZONEOffsetDateTimeWith timezone
TIME WITH TIME ZONEOffsetDateTimeTime with timezone
INTERVALDurationTime duration
val dateType: DuckDbType<LocalDate> = DuckDbTypes.date
val tsType: DuckDbType<LocalDateTime> = DuckDbTypes.timestamp
val tstzType: DuckDbType<OffsetDateTime> = DuckDbTypes.timestamptz
val intervalType: DuckDbType<Duration> = DuckDbTypes.interval

Timestamp Precision Variants

DuckDB TypeJava TypePrecision
TIMESTAMP_SLocalDateTimeSeconds
TIMESTAMP_MSLocalDateTimeMilliseconds
TIMESTAMPLocalDateTimeMicroseconds (default)
TIMESTAMP_NSLocalDateTimeNanoseconds
val tsSeconds: DuckDbType<LocalDateTime> = DuckDbTypes.timestamp_s
val tsMillis: DuckDbType<LocalDateTime> = DuckDbTypes.timestamp_ms
val tsNanos: DuckDbType<LocalDateTime> = DuckDbTypes.timestamp_ns

UUID Type

DuckDB TypeJava Type
UUIDjava.util.UUID
val uuidType: DuckDbType<UUID> = DuckDbTypes.uuid

JSON Type

DuckDB TypeJava Type
JSONJson
val jsonType: DuckDbType<Json> = DuckDbTypes.json

val data: Json = Json("{\"name\": \"DuckDB\"}")

Enum Type

// Define your Kotlin enum
enum class Status { PENDING, ACTIVE, COMPLETED }

// Create DuckDbType for it
val statusType: DuckDbType<Status> = DuckDbTypes.ofEnum("status", Status::valueOf)

Array Types

Any type can be converted to an array type using .array():

DuckDB TypeJava Type
INTEGER[]Integer[]
VARCHAR[]String[]
BOOLEAN[]Boolean[]
......
val intArray: DuckDbType<Array<Int>> = DuckDbTypes.integerArray
val strArray: DuckDbType<Array<String>> = DuckDbTypes.varcharArray
val uuidArray: DuckDbType<Array<UUID>> = DuckDbTypes.uuidArray

// Create array for any type
// val customArray: DuckDbType<Array<MyType>> = myType.array()

LIST Types

DuckDB's LIST type is similar to arrays but with different semantics:

DuckDB TypeJava Type
LIST<INTEGER>List<Integer>
LIST<VARCHAR>List<String>
LIST<DATE>List<LocalDate>
......
// Pre-defined list types with optimized native JNI support
val listInt: DuckDbType<List<Int>> = DuckDbTypes.listInteger
val listStr: DuckDbType<List<String>> = DuckDbTypes.listVarchar
val listDouble: DuckDbType<List<Double>> = DuckDbTypes.listDouble

// Types that use SQL literal conversion (slightly slower but correct)
val listUuid: DuckDbType<List<UUID>> = DuckDbTypes.listUuid
val listDate: DuckDbType<List<LocalDate>> = DuckDbTypes.listDate
val listDecimal: DuckDbType<List<BigDecimal>> = DuckDbTypes.listDecimal

MAP Types

DuckDB's MAP type for key-value pairs:

DuckDB TypeJava Type
MAP(VARCHAR, INTEGER)Map<String, Integer>
MAP(VARCHAR, VARCHAR)Map<String, String>
// Create map types using the mapTo() combinator
val mapStrInt: DuckDbType<Map<String, Int>> = DuckDbTypes.varchar.mapTo(DuckDbTypes.integer)
val mapStrStr: DuckDbType<Map<String, String>> = DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar)
val mapUuidTime: DuckDbType<Map<UUID, LocalTime>> = DuckDbTypes.uuid.mapTo(DuckDbTypes.time)

// Works with any combination of types
val mapStrDate: DuckDbType<Map<String, LocalDate>> = DuckDbTypes.varchar.mapTo(DuckDbTypes.date)

STRUCT Types

DuckDB's STRUCT type for composite values:

// Structs are typically handled via generated code
// The structure is defined by the table schema

UNION Types

DuckDB's UNION type for tagged unions:

// Unions are typically handled via generated code
// The variants are defined by the table schema

Nullable Types

Any type can be made nullable using .opt():

val notNull: DuckDbType<Int> = DuckDbTypes.integer
val nullable: DuckDbType<Int?> = DuckDbTypes.integer.opt()

Custom Domain Types

Wrap base types with custom Java types using transform:

// Wrapper type
data class ProductId(val value: Long)

// Create DuckDbType from bigint
val productIdType: DuckDbType<ProductId> = DuckDbTypes.bigint.transform(::ProductId, ProductId::value)