Library / SDK
vrischmann/zig-sqlite avatar
vrischmann/zig-sqlite

zig-sqlite wraps SQLite's C API, and the maintainer is on a break

zig-sqlite is a small wrapper around sqlite's C API, making it easier to use with Zig.

622 stars92 forksCMIT

At a glance

What is it?
zig-sqlite is a thin Zig wrapper around SQLite's C API offering prepared statements, comptime checked bind parameters and user defined SQL functions, with the build either linking the system library or compiling the bundled SQLite source. It suits a Zig project that needs SQLite and wants compile-time checking, and the maintainer says the API is still subject to change.
Who is it for?
Adopt zig-sqlite when you are writing Zig and want SQLite with compile-time checked bind parameters and a typed row reader, and you can accept an API the maintainer says will still change. Do not adopt it expecting a maintained feature set, because the maintainer states he is on a break from working with Zig and does not intend to work on new features.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 42 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The maintenance notice is the first thing to read

The README puts a maintainer note immediately after the one-line description, and it is the most decision-relevant text in the repository. The maintainer says he is currently on a break working with Zig and does not intend to work on new features for zig-sqlite, and that he will keep it updated for the latest Zig versions because that does not take too much of his time. The status section says the same thing in a different form: while the core functionality works right now, the API is still subject to changes, and if you use this library, expect to have to make changes when you update the code. Taken together, these two paragraphs describe a stable core with an unstable surface. That is a workable arrangement for a project that is essentially a typed binding over a C API, because the C API does not move and the wrapper only needs to follow Zig's own changes. It is not a good arrangement if you need new SQLite features exposed, or if you need the wrapper to track upstream additions.

Branch structure mirrors Zig's own release cadence

The Zig release support section is brief and follows Zig's release structure. The master branch tracks Zig master, and there is a zig-0.15.1 branch that tracks Zig 0.15.1. The plan is to support releases once Zig 1.0 is released, but the README says this can still change. The reason for the branching is not exotic. Zig has changed its standard library interfaces and its build system repeatedly enough that a binding to a C API is the kind of code that breaks on a language release, and a library that supports both the development branch and the current release needs two sources of truth for exactly that reason. The repository layout reflects that the project has been through this before, since there is both a build.zig and a build.zig.zon alongside a zig.mod and a zigmod.lock, which means the package has been migrated between Zig's two dependency management schemes and the older one is still in the tree. The C sources are split out into a c/ directory with c.zig as the interface to them, alongside sqlite.zig for the main API, query.zig, errors.zig, helpers.zig, test.zig and vtab.zig for virtual tables.

System library or bundled source, and the difference is Windows

The requirements section says Zig master is the only required dependency, and then explains that for SQLite you have options depending on your target. On Windows the only supported way at the moment to build zig-sqlite is with the bundled SQLite source code file. On Linux there are two options, either use the system and development package for SQLite, libsqlite3-dev for Debian and derivatives and sqlite3-devel for Fedora, or use the bundled SQLite source code file. That asymmetry is the practical detail to plan around. The bundled source route means the SQLite version is fixed by the wrapper and compiled as part of your build, which is reproducible but ties you to whatever SQLite version is vendored. The system package route means you pick up the distribution's SQLite, which may be older but is already patched for that distribution. On Windows there is no choice, so a project that wants a specific SQLite version or a particular build has to either use the bundled one or build outside this wrapper.

Adding the dependency and opening a database

Installation is a zig fetch command:

bash
zig fetch --save git+https://github.com/vrischmann/zig-sqlite

and then in your build.zig you access the module the standard way:

zig
const sqlite = b.dependency("sqlite", .{
    .target = target,
    .optimize = optimize,
});
exe.root_module.addImport("sqlite", sqlite.module("sqlite"));

The README notes that features which can only be accessed by setting compile-time options, like FTS5 and R*Tree, are defined as build options at that point, with a section at the end of the document explaining how. At runtime you import the module as const sqlite = @import("sqlite"), then create and initialize an instance of sqlite.Db with the init method, which takes an InitOptions struct. Only the mode field is mandatory and the others have sane defaults, which is a good design, because the mode is a genuine choice between a file, memory and temporary storage while the open flags and threading mode are usually left alone. The example in the README sets a File mode with a path, enables write and create open flags, and selects the MultiThread threading mode.

Prepared statements, typed rows and the allocator split

SQLite works exclusively by using prepared statements, and the wrapper type is sqlite.Statement, obtained with the prepare method, which takes a comptime query string. That comptime requirement is the point of the library, because a query string known at compile time is what makes the bind parameter checking possible. For queries that do not return data you use the exec method, and for queries that do you have three options: Statement.all which takes an allocator and can allocate memory, Statement.one which does not take an allocator and cannot allocate memory aside from what SQLite allocates itself, and Statement.oneAlloc which takes an allocator and can allocate memory. All of these take a type as their first parameter, and that type represents a row. It can be a struct where each field maps to the corresponding column in the result set, so field 0 maps to column 1, or it can be a single type in which case the result set must return only one column. The type can be a pointer, but only when using the methods that take an allocator. The split between the allocating and non-allocating methods is the design decision that lets a Zig programmer keep an arena-free read path where the data is small.

Comptime checks are the reason to use this wrapper at all

The table of contents lists two comptime check sections, and they are the feature the README leads with after the basics. One is checking the number of bind parameters, so a query with two placeholders cannot be executed with three bindings. The other is assigning types to bind markers and checking them, so the value you pass for a marker is checked against the type you declared for it. The feature list names the three capabilities as preparing and executing statements, comptime checked bind parameters, and user defined SQL functions. The user defined functions come in scalar and aggregate flavours, which is what lets you push a Zig function into the SQL engine and call it from a query. The README also carries a note about complex allocations, which is the caveat a Zig reader will care about, since the wrapper has to hand values to C and get them back, and the ownership rules around that are where a wrapper like this usually gets subtle.

Editorial conclusion

Adopt zig-sqlite when you are writing Zig and want SQLite with compile-time checked bind parameters and a typed row reader, and you can accept an API the maintainer says will still change. Do not adopt it expecting a maintained feature set, because the maintainer states he is on a break from working with Zig and does not intend to work on new features. Verify first that your Zig version matches the branch you build from, since master tracks Zig master and a separate branch tracks Zig 0.15.1, that you have the SQLite development package available on Linux or plan to use the bundled source, and that the compile-time options such as FTS5 or R*Tree are enabled at build time if you need them.

Frequently asked questions

Is zig-sqlite actively developed?

Not with new features. The maintainer note says he is on a break working with Zig and does not intend to work on new features for zig-sqlite, but will keep it updated for the latest Zig versions. The status section adds that the core functionality works while the API is still subject to change, so expect to make changes when you update your code.

How do I add zig-sqlite to my Zig project?

Run zig fetch --save git+https://github.com/vrischmann/zig-sqlite, then in build.zig create the dependency with b.dependency("sqlite", .{ .target = target, .optimize = optimize }) and add it to your program with exe.root_module.addImport("sqlite", sqlite.module("sqlite")). Compile-time options such as FTS5 and R*Tree are set as build options.

Which SQLite version does zig-sqlite use on each platform?

On Windows the only supported way to build zig-sqlite is with the bundled SQLite source code file. On Linux you can use the system and development package, libsqlite3-dev for Debian and derivatives and sqlite3-devel for Fedora, or use the bundled SQLite source code file.

What does zig-sqlite give me over calling the C API directly?

Prepared statements with a comptime query string, comptime checks on the number of bind parameters and on the types assigned to bind markers, typed row reading through Statement.all, Statement.one and Statement.oneAlloc, and user defined scalar and aggregate SQL functions written in Zig.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. vrischmann/zig-sqlite on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/vrischmann-zig-sqlite.svg)](https://hysenlabs.com/projects/vrischmann-zig-sqlite)

Was this useful?