From 204050b9f97d8027642bd41a01b985dc89faba4f Mon Sep 17 00:00:00 2001 From: Vincent Rischmann Date: Sun, 25 Oct 2020 00:47:39 +0200 Subject: add the Bytes type --- sqlite.zig | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) (limited to 'sqlite.zig') diff --git a/sqlite.zig b/sqlite.zig index 46f2e7e..3c9b162 100644 --- a/sqlite.zig +++ b/sqlite.zig @@ -117,6 +117,11 @@ pub const Db = struct { } }; +pub const Bytes = union(enum) { + Blob: []const u8, + Text: []const u8, +}; + /// Statement is a wrapper around a SQLite statement, providing high-level functions to execute /// a statement and retrieve rows for SELECT queries. /// @@ -153,11 +158,17 @@ pub const Statement = struct { stmt: *c.sqlite3_stmt, + const BytesType = enum { + Text, + Blob, + }; + fn prepare(db: *Db, flags: c_uint, comptime query: []const u8, values: anytype) !Self { - const StructType = @typeInfo(@TypeOf(values)).Struct; + const StructType = @TypeOf(values); + const StructTypeInfo = @typeInfo(StructType).Struct; comptime { const bind_parameter_count = std.mem.count(u8, query, "?"); - if (bind_parameter_count != StructType.fields.len) { + if (bind_parameter_count != StructTypeInfo.fields.len) { @compileError("bind parameter count != number of fields in tuple/struct"); } } @@ -183,7 +194,7 @@ pub const Statement = struct { // Bind - inline for (StructType.fields) |struct_field, _i| { + inline for (StructTypeInfo.fields) |struct_field, _i| { const i = @as(usize, _i); const field_type_info = @typeInfo(struct_field.field_type); const field_value = @field(values, struct_field.name); @@ -193,6 +204,10 @@ pub const Statement = struct { []const u8, []u8 => { _ = c.sqlite3_bind_text(stmt, column, field_value.ptr, @intCast(c_int, field_value.len), null); }, + Bytes => switch (field_value) { + .Text => |v| _ = c.sqlite3_bind_text(stmt, column, v.ptr, @intCast(c_int, v.len), null), + .Blob => |v| _ = c.sqlite3_bind_blob(stmt, column, v.ptr, @intCast(c_int, v.len), null), + }, else => switch (field_type_info) { .Int, .ComptimeInt => _ = c.sqlite3_bind_int64(stmt, column, @intCast(c_longlong, field_value)), .Float, .ComptimeFloat => _ = c.sqlite3_bind_double(stmt, column, field_value), @@ -512,6 +527,16 @@ test "sqlite: statement exec" { testing.expectEqual(@as(usize, 33), age.?); } + + // Test with a Bytes struct + + { + // try db.exec("INSERT INTO user(id, name, age) VALUES(?, ?, ?)", .{ + // .id = 200, + // .name = Bytes{ .Text = "hello" }, + // .age = 20, + // }); + } } fn dbMode() Db.Mode { -- cgit v1.2.3 From 1f10f1b5797f18fddce8b47cd00bfcfc800420b1 Mon Sep 17 00:00:00 2001 From: Vincent Rischmann Date: Sun, 25 Oct 2020 01:18:49 +0200 Subject: fix test so that the compiler doesn't crash --- sqlite.zig | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'sqlite.zig') diff --git a/sqlite.zig b/sqlite.zig index 3c9b162..e29977a 100644 --- a/sqlite.zig +++ b/sqlite.zig @@ -531,11 +531,18 @@ test "sqlite: statement exec" { // Test with a Bytes struct { - // try db.exec("INSERT INTO user(id, name, age) VALUES(?, ?, ?)", .{ - // .id = 200, - // .name = Bytes{ .Text = "hello" }, - // .age = 20, - // }); + // NOTE(vincent): can't yet pass an anonymous struct, the compiler crashes. + const Params = struct { + id: usize, + name: Bytes, + age: usize, + }; + + try db.exec("INSERT INTO user(id, name, age) VALUES(?, ?, ?)", Params{ + .id = 200, + .name = .{ .Text = "hello" }, + .age = 20, + }); } } -- cgit v1.2.3 From ec137ad44c1845e83ea62904e3e283ca152b53dc Mon Sep 17 00:00:00 2001 From: Vincent Rischmann Date: Sun, 25 Oct 2020 01:22:18 +0200 Subject: document the Bytes type --- sqlite.zig | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sqlite.zig') diff --git a/sqlite.zig b/sqlite.zig index e29977a..116807a 100644 --- a/sqlite.zig +++ b/sqlite.zig @@ -117,6 +117,12 @@ pub const Db = struct { } }; +/// Bytes is used to represent a byte slice with its SQLite datatype. +/// +/// Since Zig doesn't have strings we can't tell if a []u8 must be stored as a SQLite TEXT or BLOB, +/// this type can be used to communicate this when executing a statement. +/// +/// If a []u8 or []const u8 is passed as bind parameter it will be treated as TEXT. pub const Bytes = union(enum) { Blob: []const u8, Text: []const u8, -- cgit v1.2.3