summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Vincent Rischmann2021-09-07 01:16:21 +0200
committerGravatar GitHub2021-09-07 01:16:21 +0200
commit658f9fab1f61ee207d1951f93c5ab3e242828e08 (patch)
treebd63753b6489e99482ebdb49a1b298720316c7f8
parentMerge pull request #47 from vrischmann/fix-usingnamespace (diff)
parentmore minor cleanups (diff)
downloadzig-sqlite-658f9fab1f61ee207d1951f93c5ab3e242828e08.tar.gz
zig-sqlite-658f9fab1f61ee207d1951f93c5ab3e242828e08.tar.xz
zig-sqlite-658f9fab1f61ee207d1951f93c5ab3e242828e08.zip
Merge pull request #48 from vrischmann/clarify-options
stop using anytype for options
-rw-r--r--sqlite.zig94
1 files changed, 54 insertions, 40 deletions
diff --git a/sqlite.zig b/sqlite.zig
index 5aef124..04a3b24 100644
--- a/sqlite.zig
+++ b/sqlite.zig
@@ -410,7 +410,7 @@ pub const Db = struct {
410 /// 410 ///
411 /// const journal_mode = try db.pragma([]const u8, allocator, .{}, "journal_mode", null); 411 /// const journal_mode = try db.pragma([]const u8, allocator, .{}, "journal_mode", null);
412 /// 412 ///
413 pub fn pragmaAlloc(self: *Self, comptime Type: type, allocator: *mem.Allocator, options: anytype, comptime name: []const u8, comptime arg: ?[]const u8) !?Type { 413 pub fn pragmaAlloc(self: *Self, comptime Type: type, allocator: *mem.Allocator, options: QueryOptions, comptime name: []const u8, comptime arg: ?[]const u8) !?Type {
414 comptime var buf: [1024]u8 = undefined; 414 comptime var buf: [1024]u8 = undefined;
415 comptime var query = getPragmaQuery(&buf, name, arg); 415 comptime var query = getPragmaQuery(&buf, name, arg);
416 416
@@ -433,7 +433,7 @@ pub const Db = struct {
433 /// The pragma name must be known at comptime. 433 /// The pragma name must be known at comptime.
434 /// 434 ///
435 /// This cannot allocate memory. If your pragma command returns text you must use an array or call `pragmaAlloc`. 435 /// This cannot allocate memory. If your pragma command returns text you must use an array or call `pragmaAlloc`.
436 pub fn pragma(self: *Self, comptime Type: type, options: anytype, comptime name: []const u8, comptime arg: ?[]const u8) !?Type { 436 pub fn pragma(self: *Self, comptime Type: type, options: QueryOptions, comptime name: []const u8, comptime arg: ?[]const u8) !?Type {
437 comptime var buf: [1024]u8 = undefined; 437 comptime var buf: [1024]u8 = undefined;
438 comptime var query = getPragmaQuery(&buf, name, arg); 438 comptime var query = getPragmaQuery(&buf, name, arg);
439 439
@@ -615,7 +615,7 @@ pub fn Iterator(comptime Type: type) type {
615 } 615 }
616 616
617 if (@typeInfo(Type.BaseType) == .Int) { 617 if (@typeInfo(Type.BaseType) == .Int) {
618 const innervalue = try self.readField(Type.BaseType, 0, options); 618 const innervalue = try self.readField(Type.BaseType, options, 0);
619 return @intToEnum(Type, @intCast(TI.tag_type, innervalue)); 619 return @intToEnum(Type, @intCast(TI.tag_type, innervalue));
620 } 620 }
621 621
@@ -683,14 +683,16 @@ pub fn Iterator(comptime Type: type) type {
683 }, 683 },
684 .Pointer => { 684 .Pointer => {
685 debug.assert(columns == 1); 685 debug.assert(columns == 1);
686 return try self.readPointer(Type, allocator, 0); 686 return try self.readPointer(Type, .{
687 .allocator = allocator,
688 }, 0);
687 }, 689 },
688 .Enum => |TI| { 690 .Enum => |TI| {
689 debug.assert(columns == 1); 691 debug.assert(columns == 1);
690 692
691 const innervalue = try self.readField(Type.BaseType, 0, .{ 693 const innervalue = try self.readField(Type.BaseType, .{
692 .allocator = allocator, 694 .allocator = allocator,
693 }); 695 }, 0);
694 696
695 if (comptime std.meta.trait.isZigString(Type.BaseType)) { 697 if (comptime std.meta.trait.isZigString(Type.BaseType)) {
696 return std.meta.stringToEnum(Type, innervalue) orelse unreachable; 698 return std.meta.stringToEnum(Type, innervalue) orelse unreachable;
@@ -779,8 +781,7 @@ pub fn Iterator(comptime Type: type) type {
779 781
780 // dupeWithSentinel is like dupe/dupeZ but allows for any sentinel value. 782 // dupeWithSentinel is like dupe/dupeZ but allows for any sentinel value.
781 fn dupeWithSentinel(comptime SliceType: type, allocator: *mem.Allocator, data: []const u8) !SliceType { 783 fn dupeWithSentinel(comptime SliceType: type, allocator: *mem.Allocator, data: []const u8) !SliceType {
782 const type_info = @typeInfo(SliceType); 784 switch (@typeInfo(SliceType)) {
783 switch (type_info) {
784 .Pointer => |ptr_info| { 785 .Pointer => |ptr_info| {
785 if (ptr_info.sentinel) |sentinel| { 786 if (ptr_info.sentinel) |sentinel| {
786 const slice = try allocator.alloc(u8, data.len + 1); 787 const slice = try allocator.alloc(u8, data.len + 1);
@@ -847,21 +848,26 @@ pub fn Iterator(comptime Type: type) type {
847 } 848 }
848 } 849 }
849 850
850 fn readPointer(self: *Self, comptime PointerType: type, allocator: *mem.Allocator, i: usize) !PointerType { 851 fn readPointer(self: *Self, comptime PointerType: type, options: anytype, i: usize) !PointerType {
851 const type_info = @typeInfo(PointerType); 852 if (!comptime std.meta.trait.is(.Struct)(@TypeOf(options))) {
853 @compileError("options passed to readPointer must be a struct");
854 }
855 if (!comptime std.meta.trait.hasField("allocator")(@TypeOf(options))) {
856 @compileError("options passed to readPointer must have an allocator field");
857 }
852 858
853 var ret: PointerType = undefined; 859 var ret: PointerType = undefined;
854 switch (type_info) { 860 switch (@typeInfo(PointerType)) {
855 .Pointer => |ptr| { 861 .Pointer => |ptr| {
856 switch (ptr.size) { 862 switch (ptr.size) {
857 .One => { 863 .One => {
858 ret = try allocator.create(ptr.child); 864 ret = try options.allocator.create(ptr.child);
859 errdefer allocator.destroy(ret); 865 errdefer options.allocator.destroy(ret);
860 866
861 ret.* = try self.readField(ptr.child, i, .{ .allocator = allocator }); 867 ret.* = try self.readField(ptr.child, options, i);
862 }, 868 },
863 .Slice => switch (ptr.child) { 869 .Slice => switch (ptr.child) {
864 u8 => ret = try self.readBytes(PointerType, allocator, i, .Text), 870 u8 => ret = try self.readBytes(PointerType, options.allocator, i, .Text),
865 else => @compileError("cannot read pointer of type " ++ @typeName(PointerType)), 871 else => @compileError("cannot read pointer of type " ++ @typeName(PointerType)),
866 }, 872 },
867 else => @compileError("cannot read pointer of type " ++ @typeName(PointerType)), 873 else => @compileError("cannot read pointer of type " ++ @typeName(PointerType)),
@@ -874,20 +880,21 @@ pub fn Iterator(comptime Type: type) type {
874 } 880 }
875 881
876 fn readOptional(self: *Self, comptime OptionalType: type, options: anytype, _i: usize) !OptionalType { 882 fn readOptional(self: *Self, comptime OptionalType: type, options: anytype, _i: usize) !OptionalType {
877 const i = @intCast(c_int, _i); 883 if (!comptime std.meta.trait.is(.Struct)(@TypeOf(options))) {
878 const type_info = @typeInfo(OptionalType); 884 @compileError("options passed to readOptional must be a struct");
885 }
879 886
880 var ret: OptionalType = undefined; 887 var ret: OptionalType = undefined;
881 switch (type_info) { 888 switch (@typeInfo(OptionalType)) {
882 .Optional => |opt| { 889 .Optional => |opt| {
883 // Easy way to know if the column represents a null value. 890 // Easy way to know if the column represents a null value.
884 const value = c.sqlite3_column_value(self.stmt, i); 891 const value = c.sqlite3_column_value(self.stmt, @intCast(c_int, _i));
885 const datatype = c.sqlite3_value_type(value); 892 const datatype = c.sqlite3_value_type(value);
886 893
887 if (datatype == c.SQLITE_NULL) { 894 if (datatype == c.SQLITE_NULL) {
888 return null; 895 return null;
889 } else { 896 } else {
890 const val = try self.readField(opt.child, _i, options); 897 const val = try self.readField(opt.child, options, _i);
891 ret = val; 898 ret = val;
892 return ret; 899 return ret;
893 } 900 }
@@ -918,12 +925,16 @@ pub fn Iterator(comptime Type: type) type {
918 // 925 //
919 // TODO(vincent): add comptime checks for the fields/columns. 926 // TODO(vincent): add comptime checks for the fields/columns.
920 fn readStruct(self: *Self, options: anytype) !Type { 927 fn readStruct(self: *Self, options: anytype) !Type {
928 if (!comptime std.meta.trait.is(.Struct)(@TypeOf(options))) {
929 @compileError("options passed to readStruct must be a struct");
930 }
931
921 var value: Type = undefined; 932 var value: Type = undefined;
922 933
923 inline for (@typeInfo(Type).Struct.fields) |field, _i| { 934 inline for (@typeInfo(Type).Struct.fields) |field, _i| {
924 const i = @as(usize, _i); 935 const i = @as(usize, _i);
925 936
926 const ret = try self.readField(field.field_type, i, options); 937 const ret = try self.readField(field.field_type, options, i);
927 938
928 @field(value, field.name) = ret; 939 @field(value, field.name) = ret;
929 } 940 }
@@ -931,22 +942,36 @@ pub fn Iterator(comptime Type: type) type {
931 return value; 942 return value;
932 } 943 }
933 944
934 fn readField(self: *Self, comptime FieldType: type, i: usize, options: anytype) !FieldType { 945 fn readField(self: *Self, comptime FieldType: type, options: anytype, i: usize) !FieldType {
946 if (!comptime std.meta.trait.is(.Struct)(@TypeOf(options))) {
947 @compileError("options passed to readField must be a struct");
948 }
949
935 const field_type_info = @typeInfo(FieldType); 950 const field_type_info = @typeInfo(FieldType);
936 951
937 return switch (FieldType) { 952 return switch (FieldType) {
938 Blob => try self.readBytes(Blob, options.allocator, i, .Blob), 953 Blob => blk: {
939 Text => try self.readBytes(Text, options.allocator, i, .Text), 954 if (!comptime std.meta.trait.hasField("allocator")(@TypeOf(options))) {
955 @compileError("options passed to readPointer must have an allocator field when reading a Blob");
956 }
957 break :blk try self.readBytes(Blob, options.allocator, i, .Blob);
958 },
959 Text => blk: {
960 if (!comptime std.meta.trait.hasField("allocator")(@TypeOf(options))) {
961 @compileError("options passed to readField must have an allocator field when reading a Text");
962 }
963 break :blk try self.readBytes(Text, options.allocator, i, .Text);
964 },
940 else => switch (field_type_info) { 965 else => switch (field_type_info) {
941 .Int => try self.readInt(FieldType, i), 966 .Int => try self.readInt(FieldType, i),
942 .Float => try self.readFloat(FieldType, i), 967 .Float => try self.readFloat(FieldType, i),
943 .Bool => try self.readBool(i), 968 .Bool => try self.readBool(i),
944 .Void => {}, 969 .Void => {},
945 .Array => try self.readArray(FieldType, i), 970 .Array => try self.readArray(FieldType, i),
946 .Pointer => try self.readPointer(FieldType, options.allocator, i), 971 .Pointer => try self.readPointer(FieldType, options, i),
947 .Optional => try self.readOptional(FieldType, options, i), 972 .Optional => try self.readOptional(FieldType, options, i),
948 .Enum => |TI| { 973 .Enum => |TI| {
949 const innervalue = try self.readField(FieldType.BaseType, i, options); 974 const innervalue = try self.readField(FieldType.BaseType, options, i);
950 975
951 if (comptime std.meta.trait.isZigString(FieldType.BaseType)) { 976 if (comptime std.meta.trait.isZigString(FieldType.BaseType)) {
952 return std.meta.stringToEnum(FieldType, innervalue) orelse unreachable; 977 return std.meta.stringToEnum(FieldType, innervalue) orelse unreachable;
@@ -1242,11 +1267,7 @@ pub fn Statement(comptime opts: StatementOptions, comptime query: ParsedQuery) t
1242 /// in the input query string. 1267 /// in the input query string.
1243 /// 1268 ///
1244 /// This cannot allocate memory. If you need to read TEXT or BLOB columns you need to use arrays or alternatively call `oneAlloc`. 1269 /// This cannot allocate memory. If you need to read TEXT or BLOB columns you need to use arrays or alternatively call `oneAlloc`.
1245 pub fn one(self: *Self, comptime Type: type, options: anytype, values: anytype) !?Type { 1270 pub fn one(self: *Self, comptime Type: type, options: QueryOptions, values: anytype) !?Type {
1246 if (!comptime std.meta.trait.is(.Struct)(@TypeOf(options))) {
1247 @compileError("options passed to iterator must be a struct");
1248 }
1249
1250 var iter = try self.iterator(Type, values); 1271 var iter = try self.iterator(Type, values);
1251 1272
1252 const row = (try iter.next(options)) orelse return null; 1273 const row = (try iter.next(options)) orelse return null;
@@ -1254,11 +1275,7 @@ pub fn Statement(comptime opts: StatementOptions, comptime query: ParsedQuery) t
1254 } 1275 }
1255 1276
1256 /// oneAlloc is like `one` but can allocate memory. 1277 /// oneAlloc is like `one` but can allocate memory.
1257 pub fn oneAlloc(self: *Self, comptime Type: type, allocator: *mem.Allocator, options: anytype, values: anytype) !?Type { 1278 pub fn oneAlloc(self: *Self, comptime Type: type, allocator: *mem.Allocator, options: QueryOptions, values: anytype) !?Type {
1258 if (!comptime std.meta.trait.is(.Struct)(@TypeOf(options))) {
1259 @compileError("options passed to iterator must be a struct");
1260 }
1261
1262 var iter = try self.iterator(Type, values); 1279 var iter = try self.iterator(Type, values);
1263 1280
1264 const row = (try iter.nextAlloc(allocator, options)) orelse return null; 1281 const row = (try iter.nextAlloc(allocator, options)) orelse return null;
@@ -1291,10 +1308,7 @@ pub fn Statement(comptime opts: StatementOptions, comptime query: ParsedQuery) t
1291 /// in the input query string. 1308 /// in the input query string.
1292 /// 1309 ///
1293 /// Note that this allocates all rows into a single slice: if you read a lot of data this can use a lot of memory. 1310 /// Note that this allocates all rows into a single slice: if you read a lot of data this can use a lot of memory.
1294 pub fn all(self: *Self, comptime Type: type, allocator: *mem.Allocator, options: anytype, values: anytype) ![]Type { 1311 pub fn all(self: *Self, comptime Type: type, allocator: *mem.Allocator, options: QueryOptions, values: anytype) ![]Type {
1295 if (!comptime std.meta.trait.is(.Struct)(@TypeOf(options))) {
1296 @compileError("options passed to iterator must be a struct");
1297 }
1298 var iter = try self.iterator(Type, values); 1312 var iter = try self.iterator(Type, values);
1299 1313
1300 var rows = std.ArrayList(Type).init(allocator); 1314 var rows = std.ArrayList(Type).init(allocator);