// STRYKE-DUCKDB — ENGINEERING REPORT

Opt-in stryke connector package · cdylib libstryke_duckdb.{dylib,so} (crate-type = cdylib) · dlopen'd in-process on use DuckDB · JSON-over-FFI envelope

>_EXECUTIVE SUMMARY

stryke-duckdb is one of the opt-in connector packages in the stryke ecosystem. Embedded DuckDB SQL engine for stryke. Direct-query parquet / CSV / JSON from disk or URL without loading, persistent .duckdb files when you need them, full standard SQL on top. Opt-in package, kept out of the stryke core binary so the daily-driver install stays slim; ships as a Rust cdylib that stryke dlopens in-process on first use DuckDB.

DuckDB is an in-process analytical SQL engine; the duckdb crate with bundled compiles libduckdb from source into one static cdylib — no system .so dep at runtime. Single-shot opt-in install.

cdylib
Crate type
opt-in
Tier
dlopen
Load model
JSON-over-FFI
Envelope
91
Public DuckDB:: fns
33
FFI exports (duckdb__*)
v0.19.0
Package version
MIT
License

~ARCHITECTURE

In-process cdylib design: the stryke side is a thin .stk wrapper that calls FFI symbols on the dlopen'd library. No subprocess, no pipe — calls return on the same thread that made them.

LayerImplementation
stryke wrappers (lib/*.stk)Thin .stk wrapper (DuckDB); exposes typed helpers that serialize args to JSON and parse the response
cdylib (libstryke_duckdb.{dylib,so})Single Rust cdylib crate; every public surface fn is an extern "C" fn duckdb__<verb>(*const c_char) -> *mut c_char
Process modelLibrary is dlopen'd once per stryke session on first use DuckDB; caches one duckdb::Connection per (db, session, read_only) tuple in OnceCell<Mutex<HashMap>>; lives until the runtime exits
BuildCargo with [lib] crate-type = ["cdylib"]; publish = false; the package itself ships via s pkg install -g .
Install path~/.stryke/store/duckdb@<version>/ after make install; use DuckDB from any stryke script resolves it
Testszunit-style under t/ with live-service variants when applicable
CIGitHub Actions .github/workflows/ci.yml — cargo fmt + clippy + test, plus stryke pkg install verification

$WHY OPT-IN (NOT BUILTIN)

DuckDB is an in-process analytical SQL engine; the duckdb crate with bundled compiles libduckdb from source into one static binary. Single-shot opt-in install.

The trade-off is intentional. The core stryke binary stays under ~40 MB precisely because each connector ships separately. Daily-driver work (one-liners, awk replacement, data scripting) doesn't need MongoDB drivers, AWS SDKs, or Spark Connect bindings linked in.


&FFI ENVELOPE

JSON in / JSON out across the FFI boundary. Each DuckDB::* wrapper serializes its args to a JSON dict and calls the matching duckdb__* symbol on the dlopen'd libstryke_duckdb.{dylib,so}; the cdylib returns a JSON CString the wrapper parses. catch_unwind on every call converts panics to JSON errors. The returned CString is freed via the cdylib-exported stryke_free_cstring, wired automatically by rust_ffi::load_cdylib.

# request shape (built by the .stk wrapper)
{"verb": "<op>", "...": ...}

# response shape
{"result": ...}            # success — per-fn shape
{"error": "<msg>"}        # failure — wrapper die()s with the message

Per-verb success shapes returned by the cdylib (the .stk wrapper unwraps each into the stryke-native type):

VerbWire shape
query, dump{"columns": [...], "rows": [{col: val, ...}, ...]}
execute{"affected": <n>}
exec{"ok": true}
import{"table": ..., "rows": <n>}
export{"path": ..., "kind": ...}
tables{"tables": [...]}
schema{"table": ..., "columns": [{name, type, nullable}, ...]}
attach{"alias": ..., "attach_path": ..., "read_only": <bool>}
detach{"alias": ..., "detached": true}
copy_from{"table": ..., "path": ..., "copied": <n>}
create_index{"index": ..., "table": ..., "columns": [...]}
drop{"dropped": ..., "kind": ...}
appender_columns{"table": ..., "columns": [...], "appended": <n>}
indexes, constraints, table_info, database_size, columns, schemas, memory, describe_query{"columns": [...], "rows": [...]}
checkpoint{"ok": true, "force": <bool>}
inspect, ping{...}
any error{"error": "<msg>"} — the wrapper dies with it

+SURFACE INVENTORY

The package exposes 91 public DuckDB::* functions from lib/DuckDB.stk. Of these, 33 cross the FFI boundary to a duckdb__* symbol in the cdylib; the remainder are pure-stryke helpers composed over query / execute (CRUD, analytics, quote/parse). The cdylib's extern "C" exports are declared in stryke.toml under [ffi].exports and matched by extern "C" fn duckdb__<verb> definitions in src/lib.rs.

CategorySurface
Read pathsquery, query_stream, query_one, query_col, query_scalar, dump
DDL / DMLexecute, exec_file, explain, insert_many, appender, appender_columns, import, export, copy_from, create_index, drop, drop_index, attach, detach, update, delete, truncate, upsert
Transactionsbegin, commit, rollback, transaction
Metadataversion, server_version, ping, inspect, tables, databases, views, functions, settings, extensions, schema, count, exists, table_exists, table_info, indexes, constraints, database_size, all_columns, schemas, memory_usage, describe_query
Analytics & readersdescribe, columns, column_types, summarize, head, sample, distinct, aggregate, sum_, avg_, min_, max_, group_count, create_table_as, read_parquet, read_csv, read_json, copy_to, install_extension, load_extension, pragma, set, get_setting, vacuum, checkpoint
Quote / parse (pure)quote_ident, unquote_ident, quote_identifier, quote_literal, unquote_literal, quote_like, unquote_like, quote_qualified_ident, parse_qualified_ident, format_list, parse_list, format_in_list, parse_in_list, format_struct, parse_struct, format_map

The full per-function signature listing (return shapes, option keys) is in the Docs API reference and the README's API reference section.


=CONNECTION CACHE

The cdylib caches one duckdb::Connection keyed on the (db, session, read_only) tuple in a OnceCell<Mutex<HashMap>> that lives for the life of the stryke process. Two consequences:

Named sessions (session => "name") give distinct in-memory instances; the default session name is "_default". A file-backed db => "app.duckdb" shares its cached connection across every call with that same path.


%CI GATES

GitHub Actions .github/workflows/ci.yml runs: cargo check / fmt --check / clippy -D warnings / test (ubuntu + macOS), cargo doc -D warnings, a cross-target release build (linux x86_64, macOS x86_64 + aarch64), and a stryke-test job that downloads the latest strykelang release, syntax-checks every .stk file, installs the package, and runs s test t/. Documentation is pinned by shell gates under tests/ (docs HTML structure, target=_blank/rel=noopener, no inline handlers, no http:// links, no placeholder hrefs, final-newline, README/man-page structure).


/SCOPE

See the README's "Why this is a package" + "API reference" sections for the authoritative scope. The package is intentionally narrower than its underlying SDK / driver — the goal is "useful from a shell pipeline", not "complete API coverage".


#PROJECT METADATA

ItemValue
LicenseMIT
AuthorMenkeTechnologies
Repositorygithub.com/MenkeTechnologies/stryke-duckdb
Parent languagestrykelang
Meta umbrellaMenkeTechnologiesMeta
Issuesgithub.com/MenkeTechnologies/stryke-duckdb/issues