duckdb

duckdb
moon add f4ah6o/duckdb@0.6.3
Download zip
Author
Version
0.6.3
License
Apache-2.0
Last updated
3 months ago
Downloads
937

Dependencies

README

#f4ah6o/duckdb

MoonBit bindings for DuckDB on native and JavaScript targets.

#Targets

  • Native: links against libduckdb via the DuckDB C API.
  • JavaScript: compile with the MoonBit JS target and pick a backend at runtime:
    • JsBackend::Node uses @duckdb/node-api.
    • JsBackend::Wasm uses @duckdb/duckdb-wasm in the browser.
  • MoonBit wasm/wasm-gc targets are not supported (they use stub implementations).

#Feature Support Matrix

FeatureNativeJS (Node)JS (WASM)
Connection & Query
Prepared Statements
Streaming Results
Appender✅ (Node only)
Arrow Integration
Advanced Types⚠️⚠️

Legend: ✅ Full support | ⚠️ Partial support | ❌ Not supported

#Advanced Types Detailed Support

TypeNative BindNative AppendNode BindNode AppendWASM Bind
Decimal✅ 128-bit✅ 128-bit✅ 128-bit✅ 128-bit
Interval
Blob
List✅ VARCHAR✅ VARCHAR✅ VARCHAR (Node only)
Struct✅ VARCHAR✅ VARCHAR✅ VARCHAR (Node only)
Map✅ VARCHAR✅ VARCHAR✅ VARCHAR (Node only)

Notes:
  • List/Struct/Map are represented as string arrays (VARCHAR-only) and rely on DuckDB casting.
  • JS (WASM) does not support advanced type bindings; use INSERT statements with type literals instead.
  • Appender date/timestamp helpers are only implemented for native targets.

#Arrow Integration

Basic support is available on all targets:
  • Arrow query result type
  • Schema extraction
  • Column-based data access (native also exposes nullable getters)
  • Supported types: BOOLEAN, INTEGER, VARCHAR, DOUBLE, BIGINT

Note: Complex types (List, Struct, Map) are not yet supported.

#Installation

#Native Target

The native target links against libduckdb using the DuckDB C API.

#Install libduckdb

macOS (Homebrew):
brew install duckdb

Ubuntu/Debian:
# Download a release that matches your platform wget https://github.com/duckdb/duckdb/releases/download/<version>/libduckdb-linux-amd64.zip unzip libduckdb-linux-amd64.zip sudo cp libduckdb.so /usr/local/lib/ sudo ldconfig

From Source:
git clone https://github.com/duckdb/duckdb.git cd duckdb mkdir build && cd build cmake .. make -j$(nproc) sudo make install sudo ldconfig

#Linker Configuration

When compiling, you may need to specify the library path:

moon build --target-native -- -L/usr/local/lib -Wl,-rpath,/usr/local/lib -lduckdb

Or set PKG_CONFIG_PATH if libduckdb provides a pkg-config file. The default src/moon.pkg includes common include/library search paths for both macOS and Ubuntu:

  • Include: /opt/homebrew/include, /usr/local/include, /usr/include
  • Library: /opt/homebrew/lib, /usr/local/lib, /usr/lib

The linker still requires -lduckdb, so libduckdb must be installed on the machine.

If you hit errors like Undefined symbols ... _duckdb_*, check:

  1. duckdb.h exists in one of the include paths above.
  2. libduckdb.dylib (macOS) or libduckdb.so (Linux) exists in one of the library paths above.
  3. moon test --target native runs in an environment where those paths are visible to the linker.

#JavaScript Targets

#Node.js

The Node.js backend uses @duckdb/node-api. Install dependencies:

npm install @duckdb/node-api@^1.4.3-r.3

#Browser (WASM)

The browser backend uses @duckdb/duckdb-wasm. Install dependencies:

npm install @duckdb/duckdb-wasm@^1.33.1-dev18.0

Note: WASM requires browser Worker support. Cross-origin isolation may be required for optimal performance.

#JavaScript Limitations

  • WASM Appender - Not supported for WASM backend (use INSERT statements instead)
  • WASM Advanced Types - Blob, Decimal, Interval, List, Struct, Map are not supported for WASM backend
  • Node.js Advanced Types - Decimal, Interval, Blob are supported for bind/append; List/Struct/Map are VARCHAR-only
  • JS Appender Date/Timestamp - Not implemented (native only)

#Usage

connect(on_ready=fn (result) {
match result {
Ok(conn) => {
conn.query(
"select 1 as a, NULL as b, 'duck' as c",
on_done=fn (query_result) {
match query_result {
Ok(result) => {
println("columns: \{result.columns}")
println("rows: \{result.rows}")
println("nulls: \{result.nulls}")
}
Err(err) => println("query failed: \{err}")
}
},
)
conn.close(on_done=fn (closed) {
match closed {
Ok(_) => ()
Err(err) => println("close failed: \{err}")
}
})
}
Err(err) => println("connect failed: \{err}")
}
})

#Typed Results

QueryResult stores rows as strings plus a null mask. Use the typed helpers for convenience, or convert to a TypedQueryResult for repeated access:

conn.query("select 1 as a, 2.5 as b, NULL as c", on_done=fn (query_result) {
match query_result {
Ok(result) => {
let value = result.get_int(0, 0) // Some(1)
let typed = result.to_typed()
let b0 = typed.get_double(0, 1)
let c0 = typed.get_string(0, 2) // None
println("\{value} \{b0} \{c0}")
}
Err(err) => println("query failed: \{err}")
}
})

#Streaming Results

Use query_stream to process large datasets in chunks without materializing the full result in MoonBit memory:

#Basic Streaming (Count Rows)

connect(on_ready=fn (result) {
match result {
Ok(conn) => {
conn.query_stream(
"SELECT i FROM RANGE(1000000) tbl(i)",
on_done=fn (stream_result) {
match stream_result {
Ok(stream) => {
let mut total = 0
let done = Ref::new(false)
while !done.val {
stream.next(on_done=fn (chunk_result) {
match chunk_result {
Ok(Some(chunk)) => total = total + chunk.row_count()
Ok(None) => done.val = true
Err(err) => {
done.val = true
println("stream failed: \{err}")
}
}
})
}
stream.close(on_done=fn (_) { () })
println("rows: \{total}")
}
Err(err) => println("stream failed: \{err}")
}
},
)
}
Err(err) => println("connect failed: \{err}")
}
})

#Aggregation Example

For more advanced use cases, you can aggregate data while streaming:

// Aggregate state to track running totals
pub struct Aggregates {
mut total_rows : Int
mut sum_values : Int
mut min_value : Int?
mut max_value : Int?
}

let agg_ref = Ref::new({ total_rows: 0, sum_values: 0, min_value: None, max_value: None })
let done_ref = Ref::new(false)

conn.query_stream(
"SELECT value FROM measurements",
on_done=fn (stream_result) {
match stream_result {
Ok(stream) => {
while !done_ref.val {
stream.next(on_done=fn (chunk_result) {
match chunk_result {
Ok(Some(chunk)) => {
// Process each row in the chunk
for row = 0; row < chunk.row_count(); row = row + 1 {
match chunk.cell(row, 0) {
Some(v) => {
let value = parse_int(v)
agg_ref.val.total_rows = agg_ref.val.total_rows + 1
agg_ref.val.sum_values = agg_ref.val.sum_values + value
// Update min/max...
}
None => ()
}
}
}
Ok(None) => done_ref.val = true
Err(err) => { done_ref.val = true; println("error: \{err}") }
}
})
}
stream.close(on_done=fn (_) {
println("Total: \{agg_ref.val.total_rows}")
println("Sum: \{agg_ref.val.sum_values}")
})
}
Err(err) => println("stream failed: \{err}")
}
},
)

#Streaming Limitations

  • Streamed DataChunk values are strings plus a null mask, consistent with QueryResult.
  • Always call ResultStream::close when finished to release resources.

#JS Backend Selection

Use JsBackend::Auto (default), JsBackend::Node, or JsBackend::Wasm:

connect(
on_ready=fn (result) { /* ... */ },
backend=JsBackend::Wasm,
)

  • Auto - Detects environment (Node.js uses Node, browser uses WASM)
  • Node - Forces @duckdb/node-api
  • Wasm - Forces @duckdb/duckdb-wasm

#Configuration

Configuration is only available on native/JS targets (not wasm/wasm-gc). Create a config, set options, then connect with it:

let config = Config::create()
match config.set("memory_limit", "1GB") {
Ok(_) => ()
Err(err) => println("config set failed: \{err}")
}

connect_with_config(
on_ready=fn (result) { /* ... */ },
config=Some(config),
path=":memory:",
)

#Error Handling

All bind_* methods and Config::set return Result[Unit, DuckDBError] on both native and JS targets:
  • Success: Returns Ok(())
  • Failure: Returns Err(DuckDBError::Message(reason))

On JS targets, bind operations are synchronous and errors are properly propagated. Use pattern matching to handle errors:

match stmt.bind_int(1, 42) {
Ok(_) =>
match stmt.bind_varchar(2, "hello") {
Ok(_) => ()
Err(e) => println("bind failed: \{e}")
}
Err(e) => println("bind failed: \{e}")
}

#
DuckDBError

pub suberror DuckDBError {
Message(String)
}

DuckDB error wrapper.

#
Appender

#external
pub type Appender

#
Appender::append_bigint

fn Appender::append_bigint(self : Appender, value : Int) -> Result[Unit, DuckDBError]

#
Appender::append_blob

fn Appender::append_blob(self : Appender, value : Bytes) -> Result[Unit, DuckDBError]

#
Appender::append_bool

fn Appender::append_bool(self : Appender, value : Bool) -> Result[Unit, DuckDBError]

#
Appender::append_date

fn Appender::append_date(self : Appender, days : Int) -> Result[Unit, DuckDBError]

#
Appender::append_decimal

fn Appender::append_decimal(self : Appender, value : Decimal) -> Result[Unit, DuckDBError]

#
Appender::append_double

fn Appender::append_double(self : Appender, value : Double) -> Result[Unit, DuckDBError]

#
Appender::append_int

fn Appender::append_int(self : Appender, value : Int) -> Result[Unit, DuckDBError]

#
Appender::append_interval

fn Appender::append_interval(self : Appender, value : Interval) -> Result[Unit, DuckDBError]

#
Appender::append_null

fn Appender::append_null(self : Appender) -> Result[Unit, DuckDBError]

#
Appender::append_timestamp

fn Appender::append_timestamp(self : Appender, micros : Int64) -> Result[Unit, DuckDBError]

#
Appender::append_varchar

fn Appender::append_varchar(self : Appender, value : String) -> Result[Unit, DuckDBError]

#
Appender::begin_row

fn Appender::begin_row(self : Appender) -> Result[Unit, DuckDBError]

#
Appender::end_row

fn Appender::end_row(self : Appender) -> Result[Unit, DuckDBError]

#
Appender::flush

fn Appender::flush(self : Appender) -> Result[Unit, DuckDBError]

#
ArrowField

pub struct ArrowField {
name : String
nullable : Bool
type_id : String
}

#
ArrowResult

#external
pub type ArrowResult

#
ArrowResult::close

fn ArrowResult::close(self : ArrowResult, on_done~ : (Result[Unit, DuckDBError]) -> Unit) -> Unit

#
ArrowResult::column_count

fn ArrowResult::column_count(self : ArrowResult) -> Int

#
ArrowResult::get_column_bool

fn ArrowResult::get_column_bool(self : ArrowResult, col : Int) -> Array[Bool]

#
ArrowResult::get_column_double

fn ArrowResult::get_column_double(self : ArrowResult, col : Int) -> Array[Double]

#
ArrowResult::get_column_int32

fn ArrowResult::get_column_int32(self : ArrowResult, col : Int) -> Array[Int]

#
ArrowResult::get_column_int64

fn ArrowResult::get_column_int64(self : ArrowResult, col : Int) -> Array[Int]

#
ArrowResult::get_column_string

fn ArrowResult::get_column_string(self : ArrowResult, col : Int) -> Array[String]

#
ArrowResult::get_schema

fn ArrowResult::get_schema(self : ArrowResult) -> Result[ArrowSchemaInfo, DuckDBError]

#
ArrowResult::row_count

fn ArrowResult::row_count(self : ArrowResult) -> Int

#
ArrowSchemaInfo

pub struct ArrowSchemaInfo {
fields : Array[ArrowField]
}

#
ColumnType

pub enum ColumnType {
Invalid
Boolean
TinyInt
SmallInt
Integer
BigInt
UTinyInt
USmallInt
UInteger
UBigInt
Float
Double
Timestamp
Date
Time
Interval
HugeInt
UHugeInt
Varchar
Blob
Decimal
TimestampS
TimestampMs
TimestampNs
Enum
List
Struct
Map
Array
Uuid
Union
Bit
TimeTz
TimestampTz
Any
Bignum
SqlNull
StringLiteral
IntegerLiteral
TimeNs
Unknown(Int)
}

DuckDB column type identifiers.

#
Config

#external
pub type Config

#
Config::set

fn Config::set(self : Config, key : String, value : String) -> Result[Unit, DuckDBError]

#
Connection

#external
pub type Connection

#
Connection::close

fn Connection::close(self : Connection, on_done~ : (Result[Unit, DuckDBError]) -> Unit) -> Unit

#
Connection::create_appender

fn Connection::create_appender(self : Connection, schema : String, table : String, on_done~ : (Result[Appender, DuckDBError]) -> Unit) -> Unit

#
Connection::prepare

fn Connection::prepare(self : Connection, sql : String, on_done~ : (Result[PreparedStatement, DuckDBError]) -> Unit) -> Unit

#
Connection::query

fn Connection::query(self : Connection, sql : String, on_done~ : (Result[QueryResult, DuckDBError]) -> Unit) -> Unit

#
Connection::query_arrow

fn Connection::query_arrow(self : Connection, sql : String, on_done~ : (Result[ArrowResult, DuckDBError]) -> Unit) -> Unit

#
Connection::query_stream

fn Connection::query_stream(self : Connection, sql : String, on_done~ : (Result[ResultStream, DuckDBError]) -> Unit) -> Unit

#
DataChunk

pub struct DataChunk {
columns : Array[String]
rows : Array[Array[String]]
nulls : Array[Array[Bool]]
}

Chunked query data with column metadata.

#
DataChunk::cell

fn DataChunk::cell(self : DataChunk, row : Int, col : Int) -> String?

#
DataChunk::column_count

fn DataChunk::column_count(self : DataChunk) -> Int

#
DataChunk::row_count

fn DataChunk::row_count(self : DataChunk) -> Int

#
Decimal

pub struct Decimal {
width : Int
scale : Int
lower : Int
upper : Int
}

Fixed-point decimal type for financial calculations. Uses 128-bit integer representation (lower/upper parts).

#
FixtureCase

pub struct FixtureCase {
name : String
sql : String
columns : Array[String]
rows : Array[Array[String]]
nulls : Array[Array[Bool]]
}

#
Interval

pub struct Interval {
months : Int
days : Int
micros : Int64
}

Date/time interval type. Represents a span of time in months, days, and microseconds.

#
JsBackend

pub(all) enum JsBackend {
Auto
Node
Wasm
}

JS backend selection for connect.

#
List

pub struct List {
elements : Array[String]
}

List/array type. Elements are stored as strings and converted on demand.

#
LogicalType

#external
pub type LogicalType

#
Map

pub struct Map {
keys : Array[String]
values : Array[String]
}

Key-value pair map type. DuckDB maps are implemented as lists of key-value structs.

#
NativeDataChunk

#external
pub type NativeDataChunk

#
PreparedStatement

#external
pub type PreparedStatement

#
PreparedStatement::bind_bigint

fn PreparedStatement::bind_bigint(self : PreparedStatement, index : Int, value : Int) -> Result[Unit, DuckDBError]

#
PreparedStatement::bind_blob

fn PreparedStatement::bind_blob(self : PreparedStatement, index : Int, value : Bytes) -> Result[Unit, DuckDBError]

#
PreparedStatement::bind_bool

fn PreparedStatement::bind_bool(self : PreparedStatement, index : Int, value : Bool) -> Result[Unit, DuckDBError]

#
PreparedStatement::bind_date

fn PreparedStatement::bind_date(self : PreparedStatement, index : Int, days : Int) -> Result[Unit, DuckDBError]

#
PreparedStatement::bind_decimal

fn PreparedStatement::bind_decimal(self : PreparedStatement, index : Int, value : Decimal) -> Result[Unit, DuckDBError]

#
PreparedStatement::bind_double

fn PreparedStatement::bind_double(self : PreparedStatement, index : Int, value : Double) -> Result[Unit, DuckDBError]

#
PreparedStatement::bind_int

fn PreparedStatement::bind_int(self : PreparedStatement, index : Int, value : Int) -> Result[Unit, DuckDBError]

#
PreparedStatement::bind_interval

fn PreparedStatement::bind_interval(self : PreparedStatement, index : Int, value : Interval) -> Result[Unit, DuckDBError]

#
PreparedStatement::bind_list_varchar

fn PreparedStatement::bind_list_varchar(self : PreparedStatement, index : Int, values : Array[String]) -> Result[Unit, DuckDBError]

#
PreparedStatement::bind_map

fn PreparedStatement::bind_map(self : PreparedStatement, index : Int, map : Map) -> Result[Unit, DuckDBError]

#
PreparedStatement::bind_null

fn PreparedStatement::bind_null(self : PreparedStatement, index : Int) -> Result[Unit, DuckDBError]

#
PreparedStatement::bind_struct

fn PreparedStatement::bind_struct(self : PreparedStatement, index : Int, value : Struct) -> Result[Unit, DuckDBError]

#
PreparedStatement::bind_timestamp

fn PreparedStatement::bind_timestamp(self : PreparedStatement, index : Int, micros : Int64) -> Result[Unit, DuckDBError]

#
PreparedStatement::bind_varchar

fn PreparedStatement::bind_varchar(self : PreparedStatement, index : Int, value : String) -> Result[Unit, DuckDBError]

#
PreparedStatement::clear_bindings

fn PreparedStatement::clear_bindings(self : PreparedStatement) -> Result[Unit, DuckDBError]

#
PreparedStatement::close

fn PreparedStatement::close(self : PreparedStatement, on_done~ : (Result[Unit, DuckDBError]) -> Unit) -> Unit

#
PreparedStatement::execute

fn PreparedStatement::execute(self : PreparedStatement, on_done~ : (Result[QueryResult, DuckDBError]) -> Unit) -> Unit

#
PreparedStatement::execute_stream

fn PreparedStatement::execute_stream(self : PreparedStatement, on_done~ : (Result[ResultStream, DuckDBError]) -> Unit) -> Unit

#
QueryResult

pub struct QueryResult {
columns : Array[String]
column_types : Array[ColumnType]
rows : Array[Array[String]]
nulls : Array[Array[Bool]]
}

Query result data is represented as strings plus a null mask.

#
QueryResult::cell

fn QueryResult::cell(self : QueryResult, row : Int, col : Int) -> String?

#
QueryResult::column_count

fn QueryResult::column_count(self : QueryResult) -> Int

#
QueryResult::get_blob

fn QueryResult::get_blob(self : QueryResult, row : Int, col : Int) -> Bytes?

Get the blob value at the specified row and column. Returns None if the value is null or not a blob.

#
QueryResult::get_bool

fn QueryResult::get_bool(self : QueryResult, row : Int, col : Int) -> Bool?

Get the boolean value at the specified row and column. Returns None if the value is null or not a boolean.

#
QueryResult::get_date

fn QueryResult::get_date(self : QueryResult, row : Int, col : Int) -> Int?

Get the date value at the specified row and column. Returns None if the value is null or not a date.

#
QueryResult::get_decimal

fn QueryResult::get_decimal(self : QueryResult, row : Int, col : Int) -> Decimal?

Get the decimal value at the specified row and column. Returns None if the value is null or not a decimal.

#
QueryResult::get_double

fn QueryResult::get_double(self : QueryResult, row : Int, col : Int) -> Double?

Get the double value at the specified row and column. Returns None if the value is null or not a double.

#
QueryResult::get_int

fn QueryResult::get_int(self : QueryResult, row : Int, col : Int) -> Int?

Get the integer value at the specified row and column. Returns None if the value is null or not an integer.

#
QueryResult::get_string

fn QueryResult::get_string(self : QueryResult, row : Int, col : Int) -> String?

Get the string value at the specified row and column. Returns None if the value is null.

#
QueryResult::get_timestamp

fn QueryResult::get_timestamp(self : QueryResult, row : Int, col : Int) -> Int64?

Get the timestamp value at the specified row and column. Returns None if the value is null or not a timestamp.

#
QueryResult::get_value

fn QueryResult::get_value(self : QueryResult, row : Int, col : Int) -> Value?

Get the typed value at the specified row and column. Returns the Value directly without requiring to_typed() conversion.

#
QueryResult::row_count

fn QueryResult::row_count(self : QueryResult) -> Int

#
QueryResult::to_typed

fn QueryResult::to_typed(self : QueryResult) -> TypedQueryResult

Convert a QueryResult to a TypedQueryResult by parsing string values.

#
ResultStream

#external
pub type ResultStream

#
ResultStream::close

fn ResultStream::close(self : ResultStream, on_done~ : (Result[Unit, DuckDBError]) -> Unit) -> Unit

#
ResultStream::column_count

fn ResultStream::column_count(self : ResultStream) -> Int

#
ResultStream::columns

fn ResultStream::columns(self : ResultStream) -> Array[String]

#
ResultStream::next

fn ResultStream::next(self : ResultStream, on_done~ : (Result[DataChunk?, DuckDBError]) -> Unit) -> Unit

#
Struct

pub struct Struct {
fields : Array[String]
values : Array[String]
}

Composite type with named fields. Represents a DuckDB STRUCT type.

#
TypedQueryResult

pub struct TypedQueryResult {
columns : Array[String]
data : Array[Array[Value]]
}

Type-safe query result with typed value access. Stores data column-wise for efficient columnar access.

#
TypedQueryResult::column_count

fn TypedQueryResult::column_count(self : TypedQueryResult) -> Int

Get the number of columns in the result.

#
TypedQueryResult::get_blob

fn TypedQueryResult::get_blob(self : TypedQueryResult, row : Int, col : Int) -> Bytes?

Get a Blob value at the specified position.

#
TypedQueryResult::get_bool

fn TypedQueryResult::get_bool(self : TypedQueryResult, row : Int, col : Int) -> Bool?

Get a Bool value at the specified position.

#
TypedQueryResult::get_bool_column

fn TypedQueryResult::get_bool_column(self : TypedQueryResult, col : Int) -> Array[Bool?]?

Get an entire column as Option[Bool] values.

#
TypedQueryResult::get_column

fn TypedQueryResult::get_column(self : TypedQueryResult, col : Int) -> Array[Value]?

Get an entire column as typed values.

#
TypedQueryResult::get_date

fn TypedQueryResult::get_date(self : TypedQueryResult, row : Int, col : Int) -> Int?

Get a Date value (days since epoch) at the specified position.

#
TypedQueryResult::get_date_column

fn TypedQueryResult::get_date_column(self : TypedQueryResult, col : Int) -> Array[Int?]?

Get an entire column as Option[Int] date values.

#
TypedQueryResult::get_decimal

fn TypedQueryResult::get_decimal(self : TypedQueryResult, row : Int, col : Int) -> Decimal?

Get a Decimal value at the specified position.

#
TypedQueryResult::get_decimal_column

fn TypedQueryResult::get_decimal_column(self : TypedQueryResult, col : Int) -> Array[Decimal?]?

Get an entire column as Option[Decimal] values.

#
TypedQueryResult::get_double

fn TypedQueryResult::get_double(self : TypedQueryResult, row : Int, col : Int) -> Double?

Get a Double value at the specified position.

#
TypedQueryResult::get_double_column

fn TypedQueryResult::get_double_column(self : TypedQueryResult, col : Int) -> Array[Double?]?

Get an entire column as Option[Double] values.

#
TypedQueryResult::get_int

fn TypedQueryResult::get_int(self : TypedQueryResult, row : Int, col : Int) -> Int?

Get an Int value at the specified position.

#
TypedQueryResult::get_int_column

fn TypedQueryResult::get_int_column(self : TypedQueryResult, col : Int) -> Array[Int?]?

Get an entire column as Option[Int] values.

#
TypedQueryResult::get_string

fn TypedQueryResult::get_string(self : TypedQueryResult, row : Int, col : Int) -> String?

Get a String value at the specified position.

#
TypedQueryResult::get_string_column

fn TypedQueryResult::get_string_column(self : TypedQueryResult, col : Int) -> Array[String?]?

Get an entire column as Option[String] values.

#
TypedQueryResult::get_timestamp

fn TypedQueryResult::get_timestamp(self : TypedQueryResult, row : Int, col : Int) -> Int64?

Get a Timestamp value (microseconds since epoch) at the specified position.

#
TypedQueryResult::get_timestamp_column

fn TypedQueryResult::get_timestamp_column(self : TypedQueryResult, col : Int) -> Array[Int64?]?

Get an entire column as Option[Int64] timestamp values.

#
TypedQueryResult::get_value

fn TypedQueryResult::get_value(self : TypedQueryResult, row : Int, col : Int) -> Value?

Get a value at the specified row and column.

#
TypedQueryResult::is_null

fn TypedQueryResult::is_null(self : TypedQueryResult, row : Int, col : Int) -> Bool

Check if the value at the specified position is NULL.

#
TypedQueryResult::row_count

fn TypedQueryResult::row_count(self : TypedQueryResult) -> Int

Get the number of rows in the result.

#
Value

pub enum Value {
Int(Int)
Double(Double)
Bool(Bool)
String(String)
Date(Int)
Timestamp(Int64)
Decimal(Decimal)
Blob(Bytes)
Null
}

Typed value representing a single DuckDB cell.

#
Value::as_blob

fn Value::as_blob(self : Value) -> Bytes?

Get the blob value if present, None otherwise.

#
Value::as_bool

fn Value::as_bool(self : Value) -> Bool?

Get the boolean value if present, None otherwise.

#
Value::as_date

fn Value::as_date(self : Value) -> Int?

Get the date value if present, None otherwise.

#
Value::as_decimal

fn Value::as_decimal(self : Value) -> Decimal?

Get the decimal value if present, None otherwise.

#
Value::as_double

fn Value::as_double(self : Value) -> Double?

Get the double value if present, None otherwise.

#
Value::as_int

fn Value::as_int(self : Value) -> Int?

Get the integer value if present, None otherwise.

#
Value::as_string

fn Value::as_string(self : Value) -> String?

Get the string value if present, None otherwise.

#
Value::as_timestamp

fn Value::as_timestamp(self : Value) -> Int64?

Get the timestamp value if present, None otherwise.

#
Value::is_null

fn Value::is_null(self : Value) -> Bool

Check if the value is null.

#
Value::to_string

fn Value::to_string(self : Value) -> String

Convert a Value to its string representation.

#
Vector

#external
pub type Vector

#
column_type_from_id

fn column_type_from_id(id : Int) -> ColumnType

Map DuckDB type id to ColumnType.

#
connect

fn connect(on_ready~ : (Result[Connection, DuckDBError]) -> Unit, path? : String, backend? : JsBackend) -> Unit

#
date_from_ymd

fn date_from_ymd(year : Int, month : Int, day : Int) -> Int

#
date_to_days

fn date_to_days(year : Int, month : Int, day : Int) -> Int

Convert year, month, day to days since epoch (1970-01-01).

#
date_to_ymd

fn date_to_ymd(days : Int) -> (Int, Int, Int)

#
days_in_month

fn days_in_month(year : Int, month : Int) -> Int

Get the number of days in a month.

#
days_to_ymd

fn days_to_ymd(days : Int) -> (Int, Int, Int)

Convert days since epoch to year, month, day.

#
decimal_from_double

fn decimal_from_double(value : Double, width : Int, scale : Int) -> Decimal

#
decimal_from_parts

fn decimal_from_parts(whole : Int, fractional : Int, scale : Int) -> Decimal

#
decimal_to_double

fn decimal_to_double(decimal : Decimal) -> Double

#
decimal_to_parts

fn decimal_to_parts(decimal : Decimal) -> (Int, Int)

#
expect_fixture_case

fn expect_fixture_case(case : FixtureCase, columns : Array[String], rows : Array[Array[String]], nulls : Array[Array[Bool]]) -> Unit raise

#
expect_query_result

fn expect_query_result(case : FixtureCase, result : QueryResult) -> Unit raise

#
fixture_cases

let fixture_cases : Array[FixtureCase]

#
int_pow10

fn int_pow10(n : Int) -> Int64

Compute 10^n for decimal scaling.

#
interval_from_days

fn interval_from_days(days : Int) -> Interval

#
interval_from_hours

fn interval_from_hours(hours : Int) -> Interval

#
interval_from_minutes

fn interval_from_minutes(minutes : Int) -> Interval

#
interval_from_months

fn interval_from_months(months : Int) -> Interval

#
interval_from_parts

fn interval_from_parts(months : Int, days : Int, micros : Int64) -> Interval

#
interval_from_seconds

fn interval_from_seconds(seconds : Int) -> Interval

#
interval_to_micros

fn interval_to_micros(interval : Interval) -> Int64

#
is_double

fn is_double(s : String) -> Bool

Check if string represents a double.

#
is_integer

fn is_integer(s : String) -> Bool

Check if string represents an integer.

#
is_leap_year

fn is_leap_year(year : Int) -> Bool

Check if a year is a leap year.

#
is_special_float_string

fn is_special_float_string(s : String) -> Bool

#
list_from_strings

fn list_from_strings(elements : Array[String]) -> List

#
list_get

fn list_get(list : List, index : Int) -> String?

#
list_length

fn list_length(list : List) -> Int

#
map_from_arrays

fn map_from_arrays(keys : Array[String], values : Array[String]) -> Map

#
map_from_pairs

fn map_from_pairs(pairs : Array[(String, String)]) -> Map

#
map_get

fn map_get(m : Map, key : String) -> String?

#
map_size

fn map_size(m : Map) -> Int

#
parse_date

fn parse_date(s : String) -> Result[Int, String]

Parse ISO date string to days since epoch.

#
parse_double

fn parse_double(s : String) -> Double

Parse string to Double.

#
parse_fraction_to_micros

fn parse_fraction_to_micros(s : String) -> Int

Parse fractional seconds (up to 6 digits) into microseconds.

#
parse_int

fn parse_int(s : String) -> Int

Parse string to Int.

#
parse_time_to_micros

fn parse_time_to_micros(s : String) -> Result[Int64, String]

Parse time string (HH:MM:SS[.sss...]) to microseconds since midnight.

#
parse_timestamp

fn parse_timestamp(s : String) -> Result[Int64, String]

Parse ISO timestamp string to microseconds since epoch.

#
parse_value

fn parse_value(s : String) -> Value

Infer and parse a string value into an appropriate Value type.

#
struct_field_count

fn struct_field_count(s : Struct) -> Int

#
struct_from_arrays

fn struct_from_arrays(fields : Array[String], values : Array[String]) -> Struct

#
struct_from_pairs

fn struct_from_pairs(pairs : Array[(String, String)]) -> Struct

#
struct_get

fn struct_get(s : Struct, field_name : String) -> String?

#
timestamp_from_ymd_hms

fn timestamp_from_ymd_hms(year : Int, month : Int, day : Int, hour : Int, minute : Int, second : Int) -> Int64

#
timestamp_to_ymd_hms

fn timestamp_to_ymd_hms(micros : Int64) -> (Int, Int, Int, Int, Int, Int)