Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions build.zig
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
const std = @import("std");

const Translator = @import("translate_c").Translator;

pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
Expand Down Expand Up @@ -57,24 +59,29 @@ pub fn build(b: *std.Build) void {
flags.append(b.allocator, "-DSQLITE_USE_URI") catch @panic("OOM");

const sqlite_amalgamation = b.dependency("sqlite_amalgamation", .{});
const translate_c_dep = b.dependency("translate_c", .{});

// Translate sqlite3.h to a Zig module via the build system (replaces @cImport)
const translate_c = b.addTranslateC(.{
.root_source_file = sqlite_amalgamation.path("sqlite3.h"),
// Translate sqlite3.h to a Zig module via translate-c dep (replaces build system impl).
const t: Translator = .init(translate_c_dep, .{
.c_source_file = sqlite_amalgamation.path("sqlite3.h"),
.target = target,
.optimize = optimize,
.link_libc = true,
});
translate_c.addIncludePath(sqlite_amalgamation.path("."));
const c_module = translate_c.createModule();
t.addIncludePath(sqlite_amalgamation.path("."));

const c_module = t.mod;

const sqlite = b.addModule("sqlite", .{
.root_source_file = b.path("src/sqlite.zig"),
.imports = &.{
.{ .name = "c", .module = c_module },
},
});
sqlite.addCSourceFile(.{ .file = sqlite_amalgamation.path("sqlite3.c"), .flags = flags.items });
sqlite.addCSourceFile(.{
.file = sqlite_amalgamation.path("sqlite3.c"),
.flags = flags.items,
});

// Tests
const tests = b.addTest(.{
Expand All @@ -88,7 +95,10 @@ pub fn build(b: *std.Build) void {
}),
});

tests.root_module.addCSourceFile(.{ .file = sqlite_amalgamation.path("sqlite3.c"), .flags = flags.items });
tests.root_module.addCSourceFile(.{
.file = sqlite_amalgamation.path("sqlite3.c"),
.flags = flags.items,
});

const run_tests = b.addRunArtifact(tests);

Expand Down
4 changes: 4 additions & 0 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,9 @@
.url = "https://sqlite.org/2026/sqlite-amalgamation-3530100.zip",
.hash = "N-V-__8AAK_4rQDqNybRFADVHf986hCbR9ln5ez1iWpmBV5L",
},
.translate_c = .{
.url = "git+https://codeberg.org/ziglang/translate-c#d67f0a5821b0c5ad16f60c425ad2af3499e7995f",
.hash = "translate_c-0.0.0-Q_BUWho9BwAx1Nyc_gDzXBjXZg62qETbgze15f50x29Y",
},
},
}
34 changes: 27 additions & 7 deletions src/sqlite.zig
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ pub fn Statement(comptime Params: type, comptime Result: type) type {
const Self = @This();

ptr: ?*c.sqlite3_stmt = null,
param_index_map: [param_count]c_int = .{placeholder} ** param_count,
column_index_map: [column_count]c_int = .{placeholder} ** column_count,
param_index_map: [param_count]c_int = @splat(placeholder),
column_index_map: [column_count]c_int = @splat(placeholder),

pub fn prepare(db: Database, sql: []const u8) !Self {
var stmt = Self{};
Expand Down Expand Up @@ -453,21 +453,41 @@ const Binding = struct {
}
};

field: std.builtin.Type.StructField,
/// This is pulled from builtin.zig/lang.zig in the std library since they
/// are moving towards using a struct of arrays pattern in 0.17.0.
///
/// Alignment and comptime status are not read so I dropped that field.
const StructField = struct {
name: [:0]const u8,
type: type,
/// The type of the default value is the type of this struct field, which
/// is the value of the `type` field in this struct. However there is no
/// way to refer to that type here, so we use `*const anyopaque`.
/// See also: `defaultValue`.
default_value_ptr: ?*const anyopaque,
};

field: StructField,
type: Type,
nullable: bool,
default_value_ptr: ?*const anyopaque,

pub fn parseStruct(comptime info: std.builtin.Type.Struct) [info.fields.len]Binding {
var bindings: [info.fields.len]Binding = undefined;
inline for (info.fields, 0..) |field, i| {
pub fn parseStruct(comptime info: std.builtin.Type.Struct) [info.field_names.len]Binding {
var bindings: [info.field_names.len]Binding = undefined;
inline for (0..info.field_names.len) |i| {
const field = StructField{
.name = info.field_names[i],
.type = info.field_types[i],
.default_value_ptr = info.field_attrs[i].default_value_ptr,
};

bindings[i] = parseField(field);
}

return bindings;
}

pub fn parseField(comptime field: std.builtin.Type.StructField) Binding {
pub fn parseField(comptime field: StructField) Binding {
return switch (@typeInfo(field.type)) {
.optional => |field_type| Binding{
.field = field,
Expand Down
8 changes: 6 additions & 2 deletions src/test.zig
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,12 @@ test "deserialize" {

// Construct a CWD-relative path for sqlite to open
var path_buf: [std.Io.Dir.max_path_bytes]u8 = undefined;
const db_path = std.fmt.bufPrintZ(&path_buf, ".zig-cache/tmp/{s}/db.sqlite", .{&tmp.sub_path}) catch @panic("path too long");
const db_path = std.fmt.bufPrintSentinel(
&path_buf,
".zig-cache/tmp/{s}/db.sqlite",
.{&tmp.sub_path},
0,
) catch @panic("path too long");

const db1 = try sqlite.Database.open(.{ .path = db_path });
defer db1.close();
Expand Down Expand Up @@ -214,4 +219,3 @@ test "errmsg" {
\\near "FJDKLSFJDKSL": syntax error
, std.mem.span(errmsg));
}