Home

Awesome

duckdb-extension-template-zig

A Zig & Nix toolkit template for building extensions against multiple versions of DuckDB using Zig, C or C++.

Usage

> nix develop -c $SHELL
> duckdb -unsigned
D LOAD 'zig-out/lib/quack.duckdb_extension';
D FROM duckdb_extensions();
┌──────────────────┬─────────┬───────────┬──────────────┬────────────────────────────────────────────────────────────────────────────────────┬───────────────────┐
│  extension_name  │ loaded  │ installed │ install_path │                                    description                                     │      aliases      │
│     varchar      │ boolean │  boolean  │   varchar    │                                      varchar                                       │     varchar[]     │
├──────────────────┼─────────┼───────────┼──────────────┼────────────────────────────────────────────────────────────────────────────────────┼───────────────────┤
│ arrow            │ false   │ false     │              │ A zero-copy data integration between Apache Arrow and DuckDB                       │ []                │
...
│ quack            │ true    │           │              │                                                                                    │ []                │
...
│ visualizer       │ true    │           │              │ Creates an HTML-based visualization of the query plan                              │ []                │
├──────────────────┴─────────┴───────────┴──────────────┴────────────────────────────────────────────────────────────────────────────────────┴───────────────────┤
│ 24 rows                                                                                                                                              6 columns │
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
D FROM duckdb_extensions();
> WHERE function_name ILIKE '%quack%';
┌───────────────┬─────────────┬───────────────┬───────────────┬─────────────┬─────────────┬───┬─────────┬──────────────────┬──────────────────┬──────────┬──────────────┬─────────┐
│ database_name │ schema_name │ function_name │ function_type │ description │ return_type │ … │ varargs │ macro_definition │ has_side_effects │ internal │ function_oid │ example │
│    varchar    │   varchar   │    varchar    │    varchar    │   varchar   │   varchar   │   │ varchar │     varchar      │     boolean      │ boolean  │    int64     │ varchar │
├───────────────┼─────────────┼───────────────┼───────────────┼─────────────┼─────────────┼───┼─────────┼──────────────────┼──────────────────┼──────────┼──────────────┼─────────┤
│ system        │ main        │ quack         │ scalar        │             │ VARCHAR     │ … │         │                  │ false            │ true     │         1473 │         │
├───────────────┴─────────────┴───────────────┴───────────────┴─────────────┴─────────────┴───┴─────────┴──────────────────┴──────────────────┴──────────┴──────────────┴─────────┤
│ 1 rows                                                                                                                                                    14 columns (12 shown) │
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
D SELECT quack('howdy');
┌────────────────┐
│ quack('howdy') │
│    varchar     │
├────────────────┤
│ Quack howdy 🐥 │
└────────────────┘

How it Works

DuckDB is a fast in-process analytical database written in C++ that can be extended by creating and loading a dynamically linked library using the extension API. Typically extensions are written in C++ using the officially supported extension template.

But you're one of the cool kids and want to write your extension in Zig! Fortunately the Zig build system ships with a Zig, C & C++ compiler.

1. Create a project directory initialized with the multi flake template

The Nix environment generated by the flake.nix template provides a self contained Linux & MacOS development toolchain:

> mkdir myextension && cd myextension
> nix flake init -t github:rupurt/duckdb-extension-template-zig#multi
> nix develop -c $SHELL

2. Implement 2 extension loader functions

When a DuckDB extension is loaded via LOAD 'myextension.duckdb_extension'; it requires 2 symbols to be defined (myextension_version & myextension_init). The value returned from *_init must match the version of DuckDB loading the extension.

We create a simple header file to expose these 2 symbols in our built extension.

3. Create a C++ bridge that calls DuckDB::ExtensionUtil

The extension utils helper plugs into DuckDB internals such as:

The example in this repository registers a simple scalar function called quack

4. Configure the Zig build system and compile the extension

The Zig build system is configured in build.zig.

Limitations

Currently this template can only build extensions using versions of duckdb provided by the duckdb-nix flake. The derivation built by the flake includes header files for duckdb third_party dependencies.

I have opened a Github issue to include those libraries in the nixpkgs derivation.

Development

This repository assumes you have Nix installed

> nix develop -c $SHELL
> nix develop .#v0-10-0 -c $SHELL
> nix develop .#v0-9-2 -c $SHELL
> nix develop .#main -c $SHELL
> make

Run the Zig test suite

> make test

Delete artifacts from previous builds

> make clean

Build extension binary with Zig

> make build

Run duckdb cli allowing -unsigned extensions

> make run

License

duckdb-extension-template-zig is released under the MIT license