summaryrefslogtreecommitdiff
path: root/sqlite.zig
diff options
context:
space:
mode:
Diffstat (limited to 'sqlite.zig')
-rw-r--r--sqlite.zig100
1 files changed, 99 insertions, 1 deletions
diff --git a/sqlite.zig b/sqlite.zig
index ba895a5..6f8705b 100644
--- a/sqlite.zig
+++ b/sqlite.zig
@@ -604,11 +604,25 @@ pub fn Iterator(comptime Type: type) type {
604 debug.assert(columns == 1); 604 debug.assert(columns == 1);
605 return try self.readArray(Type, 0); 605 return try self.readArray(Type, 0);
606 }, 606 },
607 .Enum => |TI| {
608 debug.assert(columns == 1);
609
610 if (comptime std.meta.trait.isZigString(Type.BaseType)) {
611 @compileError("cannot read into type " ++ @typeName(Type) ++ " ; BaseType " ++ @typeName(Type.BaseType) ++ " requires allocation, use nextAlloc or oneAlloc");
612 }
613
614 if (@typeInfo(Type.BaseType) == .Int) {
615 const innervalue = try self.readField(Type.BaseType, 0, options);
616 return @intToEnum(Type, @intCast(TI.tag_type, innervalue));
617 }
618
619 @compileError("enum column " ++ @typeName(Type) ++ " must have a BaseType of either string or int");
620 },
607 .Struct => { 621 .Struct => {
608 std.debug.assert(columns == TypeInfo.Struct.fields.len); 622 std.debug.assert(columns == TypeInfo.Struct.fields.len);
609 return try self.readStruct(options); 623 return try self.readStruct(options);
610 }, 624 },
611 else => @compileError("cannot read into type " ++ @typeName(Type) ++ " ; if dynamic memory allocation is required use nextAlloc"), 625 else => @compileError("cannot read into type " ++ @typeName(Type) ++ " ; if dynamic memory allocation is required use nextAlloc or oneAlloc"),
612 } 626 }
613 } 627 }
614 628
@@ -668,6 +682,21 @@ pub fn Iterator(comptime Type: type) type {
668 debug.assert(columns == 1); 682 debug.assert(columns == 1);
669 return try self.readPointer(Type, allocator, 0); 683 return try self.readPointer(Type, allocator, 0);
670 }, 684 },
685 .Enum => |TI| {
686 debug.assert(columns == 1);
687
688 const innervalue = try self.readField(Type.BaseType, 0, .{
689 .allocator = allocator,
690 });
691
692 if (comptime std.meta.trait.isZigString(Type.BaseType)) {
693 return std.meta.stringToEnum(Type, innervalue) orelse unreachable;
694 }
695 if (@typeInfo(Type.BaseType) == .Int) {
696 return @intToEnum(Type, @intCast(TI.tag_type, innervalue));
697 }
698 @compileError("enum column " ++ @typeName(Type) ++ " must have a BaseType of either string or int");
699 },
671 .Struct => { 700 .Struct => {
672 std.debug.assert(columns == TypeInfo.Struct.fields.len); 701 std.debug.assert(columns == TypeInfo.Struct.fields.len);
673 return try self.readStruct(.{ 702 return try self.readStruct(.{
@@ -1652,6 +1681,75 @@ test "sqlite: read a single integer value" {
1652 } 1681 }
1653} 1682}
1654 1683
1684test "sqlite: read a single value into an enum backed by an integer" {
1685 var arena = std.heap.ArenaAllocator.init(testing.allocator);
1686 defer arena.deinit();
1687
1688 var db = try getTestDb();
1689 try createTestTables(&db);
1690
1691 try db.exec("INSERT INTO user(id, age) VALUES(?{usize}, ?{usize})", .{}, .{
1692 .id = @as(usize, 10),
1693 .age = @as(usize, 0),
1694 });
1695
1696 const query = "SELECT age FROM user WHERE id = ?{usize}";
1697
1698 const IntColor = enum {
1699 violet,
1700
1701 pub const BaseType = u1;
1702 };
1703
1704 // Use one
1705 {
1706 var stmt: Statement(.{}, ParsedQuery.from(query)) = try db.prepare(query);
1707 defer stmt.deinit();
1708
1709 const b = try stmt.one(IntColor, .{}, .{
1710 .id = @as(usize, 10),
1711 });
1712 try testing.expect(b != null);
1713 try testing.expectEqual(IntColor.violet, b.?);
1714 }
1715
1716 // Use oneAlloc
1717 {
1718 var stmt: Statement(.{}, ParsedQuery.from(query)) = try db.prepare(query);
1719 defer stmt.deinit();
1720
1721 const b = try stmt.oneAlloc(IntColor, &arena.allocator, .{}, .{
1722 .id = @as(usize, 10),
1723 });
1724 try testing.expect(b != null);
1725 try testing.expectEqual(IntColor.violet, b.?);
1726 }
1727}
1728
1729test "sqlite: read a single value into an enum backed by a string" {
1730 var arena = std.heap.ArenaAllocator.init(testing.allocator);
1731 defer arena.deinit();
1732
1733 var db = try getTestDb();
1734 try createTestTables(&db);
1735
1736 try db.exec("INSERT INTO user(id, favorite_color) VALUES(?{usize}, ?{[]const u8})", .{}, .{
1737 .id = @as(usize, 10),
1738 .age = @as([]const u8, "violet"),
1739 });
1740
1741 const query = "SELECT favorite_color FROM user WHERE id = ?{usize}";
1742
1743 var stmt: Statement(.{}, ParsedQuery.from(query)) = try db.prepare(query);
1744 defer stmt.deinit();
1745
1746 const b = try stmt.oneAlloc(TestUser.Color, &arena.allocator, .{}, .{
1747 .id = @as(usize, 10),
1748 });
1749 try testing.expect(b != null);
1750 try testing.expectEqual(TestUser.Color.violet, b.?);
1751}
1752
1655test "sqlite: read a single value into void" { 1753test "sqlite: read a single value into void" {
1656 var db = try getTestDb(); 1754 var db = try getTestDb();
1657 try addTestData(&db); 1755 try addTestData(&db);