summaryrefslogtreecommitdiff
path: root/sqlite.zig
diff options
context:
space:
mode:
authorGravatar Vincent Rischmann2022-04-23 00:28:41 +0200
committerGravatar Vincent Rischmann2022-04-23 15:05:54 +0200
commit889a52c021d566b3bc7f16a1808ebaf37bc8abdb (patch)
treee85936ec2bbdd0f0505d791f3120a5bd499fd0c6 /sqlite.zig
parentreadme: add note about complex allocations (diff)
downloadzig-sqlite-889a52c021d566b3bc7f16a1808ebaf37bc8abdb.tar.gz
zig-sqlite-889a52c021d566b3bc7f16a1808ebaf37bc8abdb.tar.xz
zig-sqlite-889a52c021d566b3bc7f16a1808ebaf37bc8abdb.zip
handle tagged union when binding parameters
Diffstat (limited to '')
-rw-r--r--sqlite.zig87
1 files changed, 87 insertions, 0 deletions
diff --git a/sqlite.zig b/sqlite.zig
index 1d32880..2927dca 100644
--- a/sqlite.zig
+++ b/sqlite.zig
@@ -1675,6 +1675,24 @@ pub const DynamicStatement = struct {
1675 1675
1676 try self.bindField(FieldType.BaseType, options, field_name, i, field_value); 1676 try self.bindField(FieldType.BaseType, options, field_name, i, field_value);
1677 }, 1677 },
1678 .Union => |info| {
1679 if (info.tag_type) |UnionTagType| {
1680 inline for (info.fields) |u_field| {
1681 // This wasn't entirely obvious when I saw code like this elsewhere, it works because of type coercion.
1682 // See https://ziglang.org/documentation/master/#Type-Coercion-unions-and-enums
1683 const field_tag: std.meta.Tag(FieldType) = field;
1684 const this_tag: std.meta.Tag(FieldType) = @field(UnionTagType, u_field.name);
1685
1686 if (field_tag == this_tag) {
1687 const field_value = @field(field, u_field.name);
1688
1689 try self.bindField(u_field.field_type, options, u_field.name, i, field_value);
1690 }
1691 }
1692 } else {
1693 @compileError("cannot bind field " ++ field_name ++ " of type " ++ @typeName(FieldType));
1694 }
1695 },
1678 else => @compileError("cannot bind field " ++ field_name ++ " of type " ++ @typeName(FieldType)), 1696 else => @compileError("cannot bind field " ++ field_name ++ " of type " ++ @typeName(FieldType)),
1679 }, 1697 },
1680 } 1698 }
@@ -3782,3 +3800,72 @@ test "sqlite: fuzzer found crashes" {
3782 try testing.expectError(tc.exp_error, db.execDynamic(tc.input, .{}, .{})); 3800 try testing.expectError(tc.exp_error, db.execDynamic(tc.input, .{}, .{}));
3783 } 3801 }
3784} 3802}
3803
3804test "tagged union" {
3805 var db = try getTestDb();
3806 defer db.deinit();
3807 try addTestData(&db);
3808
3809 const Foobar = union(enum) {
3810 name: []const u8,
3811 age: usize,
3812 };
3813
3814 try db.exec("CREATE TABLE foobar(key TEXT, value ANY)", .{}, .{});
3815
3816 var foobar = Foobar{ .name = "hello" };
3817
3818 {
3819 try db.exec("INSERT INTO foobar(key, value) VALUES($key, $value)", .{}, .{
3820 .key = std.meta.tagName(std.meta.activeTag(foobar)),
3821 .value = foobar,
3822 });
3823
3824 var arena = heap.ArenaAllocator.init(testing.allocator);
3825 defer arena.deinit();
3826
3827 const result = try db.oneAlloc(
3828 struct {
3829 key: []const u8,
3830 value: []const u8,
3831 },
3832 arena.allocator(),
3833 "SELECT key, value FROM foobar WHERE key = $key",
3834 .{},
3835 .{
3836 std.meta.tagName(std.meta.activeTag(foobar)),
3837 },
3838 );
3839 try testing.expect(result != null);
3840 try testing.expectEqualStrings("name", result.?.key);
3841 try testing.expectEqualStrings(foobar.name, result.?.value);
3842 }
3843
3844 {
3845 foobar = Foobar{ .age = 204 };
3846
3847 try db.exec("INSERT INTO foobar(key, value) VALUES($key, $value)", .{}, .{
3848 .key = std.meta.tagName(std.meta.activeTag(foobar)),
3849 .value = foobar,
3850 });
3851
3852 var arena = heap.ArenaAllocator.init(testing.allocator);
3853 defer arena.deinit();
3854
3855 const result = try db.oneAlloc(
3856 struct {
3857 key: []const u8,
3858 value: usize,
3859 },
3860 arena.allocator(),
3861 "SELECT key, value FROM foobar WHERE key = $key",
3862 .{},
3863 .{
3864 std.meta.tagName(std.meta.activeTag(foobar)),
3865 },
3866 );
3867 try testing.expect(result != null);
3868 try testing.expectEqualStrings("age", result.?.key);
3869 try testing.expectEqual(foobar.age, result.?.value);
3870 }
3871}