From de348a27f67e5b57125f0c837e9d1262d924fd42 Mon Sep 17 00:00:00 2001 From: Vincent Rischmann Date: Wed, 6 Jan 2021 01:43:11 +0100 Subject: fix compile error in readField --- sqlite.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sqlite.zig') diff --git a/sqlite.zig b/sqlite.zig index f68d13f..1338cbf 100644 --- a/sqlite.zig +++ b/sqlite.zig @@ -596,7 +596,7 @@ pub fn Iterator(comptime Type: type) type { .Void => {}, .Array => try self.readArray(FieldType, i), .Pointer => try self.readPointer(FieldType, options.allocator, i), - else => @compileError("cannot populate field " ++ field.name ++ " of type " ++ @typeName(FieldType)), + else => @compileError("cannot populate field of type " ++ @typeName(FieldType)), }, }; } -- cgit v1.2.3 From 51d558ed2455f9b19aebe1e497eb4bd37c1a7b70 Mon Sep 17 00:00:00 2001 From: Vincent Rischmann Date: Wed, 6 Jan 2021 01:43:21 +0100 Subject: add a test for optionals --- sqlite.zig | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'sqlite.zig') diff --git a/sqlite.zig b/sqlite.zig index 1338cbf..d96c956 100644 --- a/sqlite.zig +++ b/sqlite.zig @@ -1380,6 +1380,33 @@ test "sqlite: read pointers" { } } +test "sqlite: optional" { + var arena = std.heap.ArenaAllocator.init(testing.allocator); + defer arena.deinit(); + + var db: Db = undefined; + try db.init(initOptions()); + try addTestData(&db); + + try db.exec("INSERT INTO article(author_id, data, is_published) VALUES(?, ?, ?)", .{ 1, null, true }); + + var stmt = try db.prepare("SELECT data, is_published FROM article"); + defer stmt.deinit(); + + const row = try stmt.one( + struct { + data: ?[128:0]u8, + is_published: ?bool, + }, + .{}, + .{}, + ); + + testing.expect(row != null); + testing.expect(row.data == null); + testing.expectEqual(true, row.is_published.?); +} + test "sqlite: statement reset" { var db: Db = undefined; try db.init(initOptions()); -- cgit v1.2.3 From 22d087fcc09b932b41ec5eacece4f722ef41ee06 Mon Sep 17 00:00:00 2001 From: Vincent Rischmann Date: Wed, 6 Jan 2021 02:02:24 +0100 Subject: allow binding and reading optionals Also allow binding the '(null)' value. --- sqlite.zig | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) (limited to 'sqlite.zig') diff --git a/sqlite.zig b/sqlite.zig index d96c956..2600ee2 100644 --- a/sqlite.zig +++ b/sqlite.zig @@ -548,6 +548,29 @@ pub fn Iterator(comptime Type: type) type { return ret; } + fn readOptional(self: *Self, comptime OptionalType: type, options: anytype, _i: usize) !OptionalType { + const i = @intCast(c_int, _i); + const type_info = @typeInfo(OptionalType); + + var ret: OptionalType = undefined; + switch (type_info) { + .Optional => |opt| { + // Easy way to know if the column represents a null value. + const value = c.sqlite3_column_value(self.stmt, i); + const datatype = c.sqlite3_value_type(value); + + if (datatype == c.SQLITE_NULL) { + return null; + } else { + const val = try self.readField(opt.child, _i, options); + ret = val; + return ret; + } + }, + else => @compileError("cannot read optional of type " ++ @typeName(OptionalType)), + } + } + // readStruct reads an entire sqlite row into a struct. // // Each field correspond to a column; its position in the struct determines the column used for it. @@ -596,6 +619,7 @@ pub fn Iterator(comptime Type: type) type { .Void => {}, .Array => try self.readArray(FieldType, i), .Pointer => try self.readPointer(FieldType, options.allocator, i), + .Optional => try self.readOptional(FieldType, options, i), else => @compileError("cannot populate field of type " ++ @typeName(FieldType)), }, }; @@ -758,6 +782,12 @@ pub fn Statement(comptime opts: StatementOptions, comptime query: ParsedQuery) t else => @compileError("cannot bind field " ++ field_name ++ " of type array of " ++ @typeName(arr.child)), } }, + .Optional => |opt| if (field) |non_null_field| { + self.bindField(opt.child, field_name, i, non_null_field); + } else { + _ = c.sqlite3_bind_null(self.stmt, column); + }, + .Null => _ = c.sqlite3_bind_null(self.stmt, column), else => @compileError("cannot bind field " ++ field_name ++ " of type " ++ @typeName(FieldType)), }, } @@ -1403,8 +1433,8 @@ test "sqlite: optional" { ); testing.expect(row != null); - testing.expect(row.data == null); - testing.expectEqual(true, row.is_published.?); + testing.expect(row.?.data == null); + testing.expectEqual(true, row.?.is_published.?); } test "sqlite: statement reset" { -- cgit v1.2.3