diff options
Diffstat (limited to '')
| -rw-r--r-- | query.zig | 40 | ||||
| -rw-r--r-- | sqlite.zig | 8 |
2 files changed, 37 insertions, 11 deletions
| @@ -10,8 +10,8 @@ pub const Blob = struct { data: []const u8 }; | |||
| 10 | pub const Text = struct { data: []const u8 }; | 10 | pub const Text = struct { data: []const u8 }; |
| 11 | 11 | ||
| 12 | const BindMarker = union(enum) { | 12 | const BindMarker = union(enum) { |
| 13 | Type: type, | 13 | Typed: type, |
| 14 | None: void, | 14 | Untyped: void, |
| 15 | }; | 15 | }; |
| 16 | 16 | ||
| 17 | pub const ParsedQuery = struct { | 17 | pub const ParsedQuery = struct { |
| @@ -59,7 +59,14 @@ pub const ParsedQuery = struct { | |||
| 59 | current_bind_marker_type_pos = 0; | 59 | current_bind_marker_type_pos = 0; |
| 60 | }, | 60 | }, |
| 61 | else => { | 61 | else => { |
| 62 | @compileError("a bind marker start (the character ?) must be followed by a bind marker type, eg {integer}"); | 62 | // This is a bind marker without a type. |
| 63 | state = .Start; | ||
| 64 | |||
| 65 | parsed_query.bind_markers[parsed_query.nb_bind_markers] = BindMarker{ .Untyped = {} }; | ||
| 66 | parsed_query.nb_bind_markers += 1; | ||
| 67 | |||
| 68 | buf[pos] = c; | ||
| 69 | pos += 1; | ||
| 63 | }, | 70 | }, |
| 64 | }, | 71 | }, |
| 65 | .BindMarkerType => switch (c) { | 72 | .BindMarkerType => switch (c) { |
| @@ -68,7 +75,7 @@ pub const ParsedQuery = struct { | |||
| 68 | 75 | ||
| 69 | const typ = parsed_query.parseType(current_bind_marker_type[0..current_bind_marker_type_pos]); | 76 | const typ = parsed_query.parseType(current_bind_marker_type[0..current_bind_marker_type_pos]); |
| 70 | 77 | ||
| 71 | parsed_query.bind_markers[parsed_query.nb_bind_markers] = BindMarker{ .Type = typ }; | 78 | parsed_query.bind_markers[parsed_query.nb_bind_markers] = BindMarker{ .Typed = typ }; |
| 72 | parsed_query.nb_bind_markers += 1; | 79 | parsed_query.nb_bind_markers += 1; |
| 73 | }, | 80 | }, |
| 74 | else => { | 81 | else => { |
| @@ -81,9 +88,13 @@ pub const ParsedQuery = struct { | |||
| 81 | }, | 88 | }, |
| 82 | } | 89 | } |
| 83 | } | 90 | } |
| 91 | |||
| 92 | // The last character was ? so this must be an untyped bind marker. | ||
| 84 | if (state == .BindMarker) { | 93 | if (state == .BindMarker) { |
| 85 | @compileError("invalid final state " ++ @tagName(state) ++ ", this means you wrote a ? in last position without a bind marker type"); | 94 | parsed_query.bind_markers[parsed_query.nb_bind_markers] = BindMarker{ .Untyped = {} }; |
| 95 | parsed_query.nb_bind_markers += 1; | ||
| 86 | } | 96 | } |
| 97 | |||
| 87 | if (state == .BindMarkerType) { | 98 | if (state == .BindMarkerType) { |
| 88 | @compileError("invalid final state " ++ @tagName(state) ++ ", this means you wrote an incomplete bind marker type"); | 99 | @compileError("invalid final state " ++ @tagName(state) ++ ", this means you wrote an incomplete bind marker type"); |
| 89 | } | 100 | } |
| @@ -148,6 +159,10 @@ test "parsed query: query" { | |||
| 148 | .query = "SELECT id, name, age FROM user WHER age > ?{u32} AND age < ?{u32}", | 159 | .query = "SELECT id, name, age FROM user WHER age > ?{u32} AND age < ?{u32}", |
| 149 | .expected_query = "SELECT id, name, age FROM user WHER age > ? AND age < ?", | 160 | .expected_query = "SELECT id, name, age FROM user WHER age > ? AND age < ?", |
| 150 | }, | 161 | }, |
| 162 | .{ | ||
| 163 | .query = "SELECT id, name, age FROM user WHER age > ? AND age < ?", | ||
| 164 | .expected_query = "SELECT id, name, age FROM user WHER age > ? AND age < ?", | ||
| 165 | }, | ||
| 151 | }; | 166 | }; |
| 152 | 167 | ||
| 153 | inline for (testCases) |tc| { | 168 | inline for (testCases) |tc| { |
| @@ -166,15 +181,19 @@ test "parsed query: bind markers types" { | |||
| 166 | const testCases = &[_]testCase{ | 181 | const testCases = &[_]testCase{ |
| 167 | .{ | 182 | .{ |
| 168 | .query = "foobar ?{usize}", | 183 | .query = "foobar ?{usize}", |
| 169 | .expected_marker = .{ .Type = usize }, | 184 | .expected_marker = .{ .Typed = usize }, |
| 170 | }, | 185 | }, |
| 171 | .{ | 186 | .{ |
| 172 | .query = "foobar ?{text}", | 187 | .query = "foobar ?{text}", |
| 173 | .expected_marker = .{ .Type = Text }, | 188 | .expected_marker = .{ .Typed = Text }, |
| 174 | }, | 189 | }, |
| 175 | .{ | 190 | .{ |
| 176 | .query = "foobar ?{blob}", | 191 | .query = "foobar ?{blob}", |
| 177 | .expected_marker = .{ .Type = Blob }, | 192 | .expected_marker = .{ .Typed = Blob }, |
| 193 | }, | ||
| 194 | .{ | ||
| 195 | .query = "foobar ?", | ||
| 196 | .expected_marker = .{ .Untyped = {} }, | ||
| 178 | }, | 197 | }, |
| 179 | }; | 198 | }; |
| 180 | 199 | ||
| @@ -185,6 +204,9 @@ test "parsed query: bind markers types" { | |||
| 185 | testing.expectEqual(1, parsed_query.nb_bind_markers); | 204 | testing.expectEqual(1, parsed_query.nb_bind_markers); |
| 186 | 205 | ||
| 187 | const bind_marker = parsed_query.bind_markers[0]; | 206 | const bind_marker = parsed_query.bind_markers[0]; |
| 188 | testing.expectEqual(tc.expected_marker.Type, bind_marker.Type); | 207 | switch (tc.expected_marker) { |
| 208 | .Typed => |typ| testing.expectEqual(typ, bind_marker.Typed), | ||
| 209 | .Untyped => |typ| testing.expectEqual(typ, bind_marker.Untyped), | ||
| 210 | } | ||
| 189 | } | 211 | } |
| 190 | } | 212 | } |
| @@ -202,8 +202,12 @@ pub fn Statement(comptime opts: StatementOptions, comptime query: ParsedQuery) t | |||
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | inline for (StructTypeInfo.fields) |struct_field, _i| { | 204 | inline for (StructTypeInfo.fields) |struct_field, _i| { |
| 205 | if (struct_field.field_type != query.bind_markers[_i].Type) { | 205 | const bind_marker = query.bind_markers[_i]; |
| 206 | @compileError("value type " ++ @typeName(struct_field.field_type) ++ " is not the bind marker type " ++ @typeName(query.bind_markers[_i].Type)); | 206 | switch (bind_marker) { |
| 207 | .Typed => |typ| if (struct_field.field_type != typ) { | ||
| 208 | @compileError("value type " ++ @typeName(struct_field.field_type) ++ " is not the bind marker type " ++ @typeName(typ)); | ||
| 209 | }, | ||
| 210 | .Untyped => {}, | ||
| 207 | } | 211 | } |
| 208 | 212 | ||
| 209 | const i = @as(usize, _i); | 213 | const i = @as(usize, _i); |