From 04eb910d7662e7cd5b3351f10d07322e25e0ae18 Mon Sep 17 00:00:00 2001 From: Vincent Rischmann Date: Thu, 26 Aug 2021 22:39:55 +0200 Subject: implement reading an integer column into an enum value directly one/next can't alloc so they are limited to integer values. --- sqlite.zig | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) (limited to 'sqlite.zig') diff --git a/sqlite.zig b/sqlite.zig index ba895a5..ffff45b 100644 --- a/sqlite.zig +++ b/sqlite.zig @@ -604,11 +604,25 @@ pub fn Iterator(comptime Type: type) type { debug.assert(columns == 1); return try self.readArray(Type, 0); }, + .Enum => |TI| { + debug.assert(columns == 1); + + if (comptime std.meta.trait.isZigString(Type.BaseType)) { + @compileError("cannot read into type " ++ @typeName(Type) ++ " ; BaseType " ++ @typeName(Type.BaseType) ++ " requires allocation, use nextAlloc or oneAlloc"); + } + + if (@typeInfo(Type.BaseType) == .Int) { + const innervalue = try self.readField(Type.BaseType, 0, options); + return @intToEnum(Type, @intCast(TI.tag_type, innervalue)); + } + + @compileError("enum column " ++ @typeName(Type) ++ " must have a BaseType of either string or int"); + }, .Struct => { std.debug.assert(columns == TypeInfo.Struct.fields.len); return try self.readStruct(options); }, - else => @compileError("cannot read into type " ++ @typeName(Type) ++ " ; if dynamic memory allocation is required use nextAlloc"), + else => @compileError("cannot read into type " ++ @typeName(Type) ++ " ; if dynamic memory allocation is required use nextAlloc or oneAlloc"), } } @@ -1652,6 +1666,51 @@ test "sqlite: read a single integer value" { } } +test "sqlite: read a single value into an enum backed by an integer" { + var arena = std.heap.ArenaAllocator.init(testing.allocator); + defer arena.deinit(); + + var db = try getTestDb(); + try createTestTables(&db); + + try db.exec("INSERT INTO user(id, age) VALUES(?{usize}, ?{usize})", .{}, .{ + .id = @as(usize, 10), + .age = @as(usize, 0), + }); + + const query = "SELECT age FROM user WHERE id = ?{usize}"; + + const IntColor = enum { + violet, + + pub const BaseType = u1; + }; + + // Use one + { + var stmt: Statement(.{}, ParsedQuery.from(query)) = try db.prepare(query); + defer stmt.deinit(); + + const b = try stmt.one(IntColor, .{}, .{ + .id = @as(usize, 10), + }); + try testing.expect(b != null); + try testing.expectEqual(IntColor.violet, b.?); + } + + // Use oneAlloc + { + var stmt: Statement(.{}, ParsedQuery.from(query)) = try db.prepare(query); + defer stmt.deinit(); + + const b = try stmt.oneAlloc(IntColor, &arena.allocator, .{}, .{ + .id = @as(usize, 10), + }); + try testing.expect(b != null); + try testing.expectEqual(IntColor.violet, b.?); + } +} + test "sqlite: read a single value into void" { var db = try getTestDb(); try addTestData(&db); -- cgit v1.2.3