diff options
Diffstat (limited to 'sqlite.zig')
| -rw-r--r-- | sqlite.zig | 100 |
1 files changed, 99 insertions, 1 deletions
| @@ -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 | ||
| 1684 | test "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 | |||
| 1729 | test "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 | |||
| 1655 | test "sqlite: read a single value into void" { | 1753 | test "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); |