summaryrefslogtreecommitdiff
path: root/sqlite.zig
diff options
context:
space:
mode:
authorGravatar Vincent Rischmann2021-10-18 19:39:42 +0200
committerGravatar Vincent Rischmann2021-10-18 21:26:06 +0200
commit7c22eb1507fd3dc3a33c7f4926b0e99e3762a291 (patch)
tree82797bfca1ae28495e999474db6c8f757835cf4d /sqlite.zig
parentno need for comptimePrint here (diff)
downloadzig-sqlite-7c22eb1507fd3dc3a33c7f4926b0e99e3762a291.tar.gz
zig-sqlite-7c22eb1507fd3dc3a33c7f4926b0e99e3762a291.tar.xz
zig-sqlite-7c22eb1507fd3dc3a33c7f4926b0e99e3762a291.zip
make bindField clearer
Be less clever with comptime reflection. This has the advantage of making the code a lot clearer, clearly identifying which case are converting an sqlite int result to an error. This also makes it easier to follow the error trace if there is an error while binding a field.
Diffstat (limited to '')
-rw-r--r--sqlite.zig86
1 files changed, 52 insertions, 34 deletions
diff --git a/sqlite.zig b/sqlite.zig
index 337ea90..4f25aa3 100644
--- a/sqlite.zig
+++ b/sqlite.zig
@@ -1130,17 +1130,9 @@ pub const DynamicStatement = struct {
1130 } 1130 }
1131 } 1131 }
1132 1132
1133 fn translateError(value: anytype) !void { 1133 fn convertResultToError(result: c_int) !void {
1134 if (@TypeOf(value) != void) { 1134 if (result != c.SQLITE_OK) {
1135 if (@typeInfo(@TypeOf(value)) == .ErrorUnion and @typeInfo(@TypeOf(value)).ErrorUnion.payload == void) { 1135 return errors.errorFromResultCode(result);
1136 return value;
1137 } else if (@TypeOf(value) == c_int and value == c.SQLITE_OK) {
1138 return;
1139 } else {
1140 return errors.errorFromResultCode(value);
1141 }
1142 } else {
1143 return;
1144 } 1136 }
1145 } 1137 }
1146 1138
@@ -1148,53 +1140,79 @@ pub const DynamicStatement = struct {
1148 const field_type_info = @typeInfo(FieldType); 1140 const field_type_info = @typeInfo(FieldType);
1149 const column = i + 1; 1141 const column = i + 1;
1150 1142
1151 const val = switch (FieldType) { 1143 switch (FieldType) {
1152 Text => c.sqlite3_bind_text(self.stmt, column, field.data.ptr, @intCast(c_int, field.data.len), null), 1144 Text => {
1153 Blob => c.sqlite3_bind_blob(self.stmt, column, field.data.ptr, @intCast(c_int, field.data.len), null), 1145 const result = c.sqlite3_bind_text(self.stmt, column, field.data.ptr, @intCast(c_int, field.data.len), null);
1154 ZeroBlob => c.sqlite3_bind_zeroblob64(self.stmt, column, field.length), 1146 return convertResultToError(result);
1147 },
1148 Blob => {
1149 const result = c.sqlite3_bind_blob(self.stmt, column, field.data.ptr, @intCast(c_int, field.data.len), null);
1150 return convertResultToError(result);
1151 },
1152 ZeroBlob => {
1153 const result = c.sqlite3_bind_zeroblob64(self.stmt, column, field.length);
1154 return convertResultToError(result);
1155 },
1155 else => switch (field_type_info) { 1156 else => switch (field_type_info) {
1156 .Int, .ComptimeInt => c.sqlite3_bind_int64(self.stmt, column, @intCast(c_longlong, field)), 1157 .Int, .ComptimeInt => {
1157 .Float, .ComptimeFloat => c.sqlite3_bind_double(self.stmt, column, field), 1158 const result = c.sqlite3_bind_int64(self.stmt, column, @intCast(c_longlong, field));
1158 .Bool => c.sqlite3_bind_int64(self.stmt, column, @boolToInt(field)), 1159 return convertResultToError(result);
1160 },
1161 .Float, .ComptimeFloat => {
1162 const result = c.sqlite3_bind_double(self.stmt, column, field);
1163 return convertResultToError(result);
1164 },
1165 .Bool => {
1166 const result = c.sqlite3_bind_int64(self.stmt, column, @boolToInt(field));
1167 return convertResultToError(result);
1168 },
1159 .Pointer => |ptr| switch (ptr.size) { 1169 .Pointer => |ptr| switch (ptr.size) {
1160 .One => self.bindField(ptr.child, options, field_name, i, field.*), 1170 .One => {
1171 try self.bindField(ptr.child, options, field_name, i, field.*);
1172 },
1161 .Slice => switch (ptr.child) { 1173 .Slice => switch (ptr.child) {
1162 u8 => c.sqlite3_bind_text(self.stmt, column, field.ptr, @intCast(c_int, field.len), null), 1174 u8 => {
1175 const result = c.sqlite3_bind_text(self.stmt, column, field.ptr, @intCast(c_int, field.len), null);
1176 return convertResultToError(result);
1177 },
1163 else => @compileError("cannot bind field " ++ field_name ++ " of type " ++ @typeName(FieldType)), 1178 else => @compileError("cannot bind field " ++ field_name ++ " of type " ++ @typeName(FieldType)),
1164 }, 1179 },
1165 else => @compileError("cannot bind field " ++ field_name ++ " of type " ++ @typeName(FieldType)), 1180 else => @compileError("cannot bind field " ++ field_name ++ " of type " ++ @typeName(FieldType)),
1166 }, 1181 },
1167 .Array => |arr| switch (arr.child) { 1182 .Array => |arr| switch (arr.child) {
1168 u8 => u8arr: { 1183 u8 => {
1169 const data: []const u8 = field[0..field.len]; 1184 const data: []const u8 = field[0..field.len];
1170 1185
1171 break :u8arr c.sqlite3_bind_text(self.stmt, column, data.ptr, @intCast(c_int, data.len), null); 1186 const result = c.sqlite3_bind_text(self.stmt, column, data.ptr, @intCast(c_int, data.len), null);
1187 return convertResultToError(result);
1172 }, 1188 },
1173 else => @compileError("cannot bind field " ++ field_name ++ " of type array of " ++ @typeName(arr.child)), 1189 else => @compileError("cannot bind field " ++ field_name ++ " of type array of " ++ @typeName(arr.child)),
1174 }, 1190 },
1175 .Optional => |opt| if (field) |non_null_field| { 1191 .Optional => |opt| if (field) |non_null_field| {
1176 return try self.bindField(opt.child, options, field_name, i, non_null_field); 1192 try self.bindField(opt.child, options, field_name, i, non_null_field);
1177 } else optional_null: { 1193 } else {
1178 break :optional_null c.sqlite3_bind_null(self.stmt, column); 1194 const result = c.sqlite3_bind_null(self.stmt, column);
1195 return convertResultToError(result);
1196 },
1197 .Null => {
1198 const result = c.sqlite3_bind_null(self.stmt, column);
1199 return convertResultToError(result);
1179 }, 1200 },
1180 .Null => c.sqlite3_bind_null(self.stmt, column),
1181 .Enum => { 1201 .Enum => {
1182 if (comptime std.meta.trait.isZigString(FieldType.BaseType)) { 1202 if (comptime std.meta.trait.isZigString(FieldType.BaseType)) {
1183 return try self.bindField(FieldType.BaseType, options, field_name, i, @tagName(field)); 1203 try self.bindField(FieldType.BaseType, options, field_name, i, @tagName(field));
1184 } else if (@typeInfo(FieldType.BaseType) == .Int) { 1204 } else if (@typeInfo(FieldType.BaseType) == .Int) {
1185 return try self.bindField(FieldType.BaseType, options, field_name, i, @enumToInt(field)); 1205 try self.bindField(FieldType.BaseType, options, field_name, i, @enumToInt(field));
1206 } else {
1207 @compileError("enum column " ++ @typeName(FieldType) ++ " must have a BaseType of either string or int to bind");
1186 } 1208 }
1187 // Above if-else tree should have return to bypass @compileError below.
1188 @compileError("enum column " ++ @typeName(FieldType) ++ " must have a BaseType of either string or int to bind");
1189 }, 1209 },
1190 .Struct => { 1210 .Struct => {
1191 return try self.bindField(FieldType.BaseType, options, field_name, i, try field.bindField(options.allocator)); 1211 try self.bindField(FieldType.BaseType, options, field_name, i, try field.bindField(options.allocator));
1192 }, 1212 },
1193 else => @compileError("cannot bind field " ++ field_name ++ " of type " ++ @typeName(FieldType)), 1213 else => @compileError("cannot bind field " ++ field_name ++ " of type " ++ @typeName(FieldType)),
1194 }, 1214 },
1195 }; 1215 }
1196
1197 return translateError(val);
1198 } 1216 }
1199 1217
1200 fn bind(self: *Self, options: anytype, values: anytype) !void { 1218 fn bind(self: *Self, options: anytype, values: anytype) !void {