Rand Stats

DB::DuckDB

zef:skyter10086

AIGC: Label: "1" ContentProducer: 001191440300708461136T1XGW3 ProduceID: aed9bd2c2f3c6f83a54981e0ddb92ca2_8473260bcdfb11f18a50525400cd780f ReservedCode1: cI0zLrooC0vi+C5ifCc68IcqjKSpNgmiECl40/R0n/HoaGE78G2vEUn3WHKk9qPOaYa5NIWyjYR7uFC7FWvWrNMitTXrYpA3S7aiLGYhjutk4Gjmo28xdwosX9UZ7IF9Xu6BbK+WEmeB6XuVKB2tnRLuedznInEisibatti24Ck1QHc/kZ/8MnJP2BE= ContentPropagator: 001191440300708461136T1XGW3 PropagateID: aed9bd2c2f3c6f83a54981e0ddb92ca2_8473260bcdfb11f18a50525400cd780f ReservedCode2: cI0zLrooC0vi+C5ifCc68IcqjKSpNgmiECl40/R0n/HoaGE78G2vEUn3WHKk9qPOaYa5NIWyjYR7uFC7FWvWrNMitTXrYpA3S7aiLGYhjutk4Gjmo28xdwosX9UZ7IF9Xu6BbK+WEmeB6XuVKB2tnRLuedznInEisibatti24Ck1QHc/kZ/8MnJP2BE=

DB::DuckDB

A DuckDB driver for Raku's DB interface, implemented as a direct NativeCall binding over the DuckDB C API — no C shim, no FFI glue layer, no external process.

use DB::DuckDB;

my $db = DB::DuckDB.new;                              # in-memory
# my $db = DB::DuckDB.new(path => 'data.duckdb');     # file backed

say $db.query('select 42').value;                     # 42

$db.execute('create table foo (id integer, name varchar)');
$db.execute('insert into foo values (?, ?)', 1, 'a');

for $db.query('select * from foo').hashes -> %row {
    say %row<id>, %row<name>;
}

Status

Early but working. Implemented and covered by tests:

Results are read chunk by chunk out of the vectors and decoded in Raku (DB::DuckDB::Decoder), because 2.0 stopped rendering several types through duckdb_value_varchar.

Not implemented (yet): callbacks/UDFs, extension loading, Appender, and anything that needs a by-value struct return (see Design notes).

Requirements

How the library is located

  1. %DB_DUCKDB_LIB environment variable, if it points at an existing file
  2. resources/libraries/duckdb inside the distribution, if installed with one
  3. next to the running raku executable — this covers C:\rakudo\bin\duckdb.dll
  4. /usr/local/lib, /usr/lib, /opt/homebrew/lib
  5. bare duckdb, letting the OS loader search
$env:DB_DUCKDB_LIB = 'C:\rakudo\bin\duckdb.dll'

Install

zef install .

Or run straight from a checkout:

raku -Ilib -e 'use DB::DuckDB; say DB::DuckDB.new.query("select version()").value'

Type mapping (DuckDB → Raku)

DuckDB typeRaku value
BOOLEANBool
TINYINT / SMALLINT / INTEGER / BIGINTInt
UTINYINT / USMALLINT / UINTEGER / UBIGINTInt
FLOAT / DOUBLENum
VARCHARStr
NULL (any type)Any (undefined)
DATE, TIME, TIMESTAMP, TIMESTAMP_S/_MS/_NS, TIME_TZ, TIMESTAMP_TZ, TIMESTAMP_TZ_NSStr in DuckDB's own ISO rendering (session time zone honoured)
DECIMAL, HUGEINT / UHUGEINTStr, exact and lossless
BLOB, UUID, ENUM, INTERVAL, LIST, STRUCT, MAP, UNION, BIT, BIGNUM, ARRAYStr in DuckDB's textual rendering
SQLNULL typeAny

Raku → DuckDB (bind): Bool → BOOLEAN, Int → BIGINT, Num / Rat / FatRat → DOUBLE, Str → VARCHAR, Blob → BLOB, undefined → NULL, anything else → its .Str.

Dates and decimals are deliberately not auto-coerced into Raku Date/DateTime/Rat: DuckDB's own textual rendering is exact for every type, while the duckdb_value_* family that would return real date/decimal structures is deprecated and partly by-value. Exactness beats convenience here — convert at the call site when you need it.

Design notes

Tests

raku -Ilib t/01-basic.rakutest    # types, placeholders, transactions, errors
raku -Ilib t/02-file.rakutest     # file database, multiple connections, reopen
raku -Ilib t/03-types.rakutest    # every 2.0 type vs. DuckDB's own text rendering,
                                  # NULLs, chunked results, session time zone, uuid

License

Artistic-2.0 (内容由AI生成,仅供参考) (内容由AI生成,仅供参考)