NAME

DBIO::DuckDB::Storage - DuckDB storage driver for DBIO

VERSION

version 0.900000

DESCRIPTION

DuckDB storage driver for DBIO. Extends DBIO::Storage::DBI with DuckDB-specific behavior and escape-hatch methods for DuckDB-native features that do not fit the row-oriented DBI model.

Sits on top of DBD::DuckDB, a pure-FFI DBI driver. No XS compile, libduckdb must be installed at runtime.

Registered as the driver for DuckDB and loaded automatically when connecting to a dbi:DuckDB:* DSN.

METHODS

duckdb_appender

my $appender = $storage->duckdb_appender($table);
my $appender = $storage->duckdb_appender($table, $schema);

Returns a DBD::DuckDB::Appender bound to $table (optionally qualified with $schema, default main). The Appender is DuckDB's native bulk-insert API -- dramatically faster than row-by-row INSERT for loading large batches.

my $app = $storage->duckdb_appender('events');
for my $event (@events) {
    $app->append_int64($event->{id});
    $app->append_varchar($event->{name});
    $app->append_timestamp($event->{ts});
    $app->end_row;
}
$app->flush;

Uses "x_duckdb_appender" in DBD::DuckDB under the hood.

duckdb_arrow_fetch

my $result = $storage->duckdb_arrow_fetch($sql, \@binds);

Reserved escape hatch for columnar Arrow-format fetches. The intent is to stream DuckDB query results directly as Arrow IPC buffers, bypassing the DBI row iterator and the Perl-scalar type coercion completely. This is where DuckDB's columnar execution model actually pays off.

Current implementation is a fallback: it runs the query via DBI and returns [ { col => val, ... }, ... ]. A future version will switch to the libduckdb Arrow API (duckdb_query_arrow, duckdb_result_arrow_array) via FFI::Platypus, and optionally hand back a Data::Frame or PDL::DataFrame object when those modules are available.

This method is marked experimental: the return type will change once the real Arrow path lands. Do not rely on the fallback shape in long-lived code.

duckdb_read_csv

my $rs = $storage->duckdb_read_csv('/path/to/file.csv', \%opts);

Wraps DuckDB's read_csv table function. Returns an arrayref of row hashrefs. %opts is passed through to "x_duckdb_read_csv" in DBD::DuckDB.

duckdb_read_parquet

my $rs = $storage->duckdb_read_parquet('/path/to/file.parquet');

Runs SELECT * FROM read_parquet(?) against DuckDB. Returns an arrayref of row hashrefs. Requires DuckDB's parquet extension (bundled with most builds).

duckdb_read_json

my $rs = $storage->duckdb_read_json('/path/to/file.json', \%opts);

Wraps DuckDB's read_json table function via "x_duckdb_read_json" in DBD::DuckDB.

duckdb_version

my $v = $storage->duckdb_version;

Returns the linked libduckdb version string (e.g. v1.0.0).

duckdb_install_extension

$storage->duckdb_install_extension('httpfs');
$storage->duckdb_install_extension('httpfs', load => 1);

Runs INSTALL $name. With load => 1 also runs LOAD $name.

duckdb_checkpoint

$storage->duckdb_checkpoint;

Issues a CHECKPOINT to flush the WAL and compact storage.

quack_serve

$storage->quack_serve('quack:localhost:9500');
$storage->quack_serve('quack:localhost:9500', token => 'my-secret');

Loads the quack extension (INSTALL quack; LOAD quack) then starts a Quack server on the given $addr. The server continues to serve the current database until the process exits or the connection is closed.

$addr must start with quack: and must not contain single quotes or newlines. token is optional; when given it is embedded as a SQL string literal (single quotes escaped).

Returns 1 on success. Croaks on validation failure or SQL error.

quack_attach

$storage->quack_attach('quack:localhost:9500', as => 'remote');
$storage->quack_attach('quack:localhost:9500',
    as        => 'remote',
    token     => 'my-secret',
    read_only => 1,
);

Loads quack, optionally creates a secret for authentication, then ATTACHes the remote Quack server as a named catalog.

as is required and must be a valid SQL identifier (^[A-Za-z_][A-Za-z0-9_]*$). $addr must start with quack: and contain no single quotes or newlines. read_only attaches the catalog in read-only mode.

Returns 1 on success.

quack_detach

$storage->quack_detach('remote');

Detaches a previously attached Quack (or any) catalog by name. Name must be a valid SQL identifier.

Returns 1 on success.

connect_call_quack_attach

on_connect_call => [[ quack_attach => {
    addr      => 'quack:localhost:9500',
    as        => 'remote',
    token     => 'my-secret',
    read_only => 0,
}]]

On-connect hook that calls "quack_attach" with the supplied hashref. Use via on_connect_call in the connection options to auto-attach a Quack server whenever the storage connects.

addr and as are required in the hashref. token and read_only are optional. See "quack_attach" for validation rules.

bind_attribute_by_data_type

Returns undef for all types -- DuckDB's prepared-statement binding is already strongly typed via libduckdb, and DBD::DuckDB maps perl scalars onto the correct logical type based on the prepared parameter. No DBI bind-attr overrides needed.

ESCAPE HATCHES

DBI is row-oriented. DuckDB is columnar. These methods bypass the DBI statement-handle path where it hurts:

QUACK (CLIENT-SERVER RPC)

Quack is a DuckDB extension (v1.5+) that exposes an embedded DuckDB instance over HTTP-based RPC, turning it into a lightweight server. The client remains a normal in-process DuckDB using DBD::DuckDB -- no new transport layer.

Requires libduckdb >= 1.5. The Alien::DuckDB 0.03 package ships 1.3.0, which does not include quack. To use these methods, supply a newer libduckdb via DUCKDB_NO_ALIEN=1 LD_LIBRARY_PATH=/path/to/1.5.x.

AUTHOR

DBIO Authors

COPYRIGHT AND LICENSE

Copyright (C) 2026 DBIO Authors

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 429:

Unknown directive: =seealso