summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--query.zig17
-rw-r--r--sqlite.zig48
2 files changed, 54 insertions, 11 deletions
diff --git a/query.zig b/query.zig
index e12ba6d..31245f7 100644
--- a/query.zig
+++ b/query.zig
@@ -125,11 +125,11 @@ pub fn ParsedQuery(comptime tmp_query: []const u8) type {
125 if (!isNamedIdentifierChar(c)) { 125 if (!isNamedIdentifierChar(c)) {
126 // This marks the end of the named bind marker. 126 // This marks the end of the named bind marker.
127 state = .start; 127 state = .start;
128 const name = buf[hold_pos .. pos - 1]; 128 const name = buf[hold_pos - 1 .. pos];
129 // TODO(vincent): name retains a pointer to a comptime var, FIX ! 129 // TODO(vincent): name retains a pointer to a comptime var, FIX !
130 if (bindMarkerForName(tmp_bind_markers[0..nb_tmp_bind_markers], name) == null) { 130 if (bindMarkerForName(tmp_bind_markers[0..nb_tmp_bind_markers], name) == null) {
131 const new_buf = buf; 131 const new_buf = buf;
132 tmp_bind_markers[nb_tmp_bind_markers].name = new_buf[hold_pos .. pos - 1]; 132 tmp_bind_markers[nb_tmp_bind_markers].name = new_buf[hold_pos - 1 .. pos];
133 nb_tmp_bind_markers += 1; 133 nb_tmp_bind_markers += 1;
134 } 134 }
135 } 135 }
@@ -175,6 +175,8 @@ pub fn ParsedQuery(comptime tmp_query: []const u8) type {
175 nb_tmp_bind_markers += 1; 175 nb_tmp_bind_markers += 1;
176 }, 176 },
177 .bind_marker_identifier => { 177 .bind_marker_identifier => {
178 const new_buf = buf;
179 tmp_bind_markers[nb_tmp_bind_markers].name = @as([]const u8, new_buf[hold_pos - 1 .. pos]);
178 nb_tmp_bind_markers += 1; 180 nb_tmp_bind_markers += 1;
179 }, 181 },
180 .start => {}, 182 .start => {},
@@ -339,15 +341,15 @@ test "parsed query: bind markers identifier" {
339 }, 341 },
340 .{ 342 .{
341 .query = "foobar ?123", 343 .query = "foobar ?123",
342 .expected_marker = .{}, 344 .expected_marker = .{ .typed = null, .name = "123" },
343 }, 345 },
344 .{ 346 .{
345 .query = "foobar :hola", 347 .query = "foobar :hola",
346 .expected_marker = .{}, 348 .expected_marker = .{ .typed = null, .name = "hola" },
347 }, 349 },
348 .{ 350 .{
349 .query = "foobar @foo", 351 .query = "foobar @foo",
350 .expected_marker = .{}, 352 .expected_marker = .{ .typed = null, .name = "foo" },
351 }, 353 },
352 }; 354 };
353 355
@@ -357,7 +359,10 @@ test "parsed query: bind markers identifier" {
357 try testing.expectEqual(@as(usize, 1), parsed_query.bind_markers.len); 359 try testing.expectEqual(@as(usize, 1), parsed_query.bind_markers.len);
358 360
359 const bind_marker = parsed_query.bind_markers[0]; 361 const bind_marker = parsed_query.bind_markers[0];
360 try testing.expectEqual(tc.expected_marker, bind_marker); 362 if (bind_marker.name) |name| {
363 try testing.expectEqualStrings(tc.expected_marker.name.?, name);
364 }
365 try testing.expectEqual(tc.expected_marker.typed, bind_marker.typed);
361 } 366 }
362} 367}
363 368
diff --git a/sqlite.zig b/sqlite.zig
index 4d7457b..62950c8 100644
--- a/sqlite.zig
+++ b/sqlite.zig
@@ -2069,11 +2069,26 @@ pub fn Statement(comptime opts: StatementOptions, comptime query: anytype) type
2069 2069
2070 const StructTypeInfo = @typeInfo(StructType).@"struct"; 2070 const StructTypeInfo = @typeInfo(StructType).@"struct";
2071 2071
2072 if (comptime query.bind_markers.len != StructTypeInfo.fields.len) { 2072 comptime marker_len_check: {
2073 @compileError(std.fmt.comptimePrint("expected {d} bind parameters but got {d}", .{ 2073 if (query.bind_markers.len != StructTypeInfo.fields.len) {
2074 query.bind_markers.len, 2074 if (query.bind_markers.len > StructTypeInfo.fields.len) {
2075 StructTypeInfo.fields.len, 2075 var found_markers = 0;
2076 })); 2076 for (query.bind_markers) |bind_marker| {
2077 if (bind_marker.name) |name| {
2078 if (@hasField(StructType, name)) {
2079 found_markers += 1;
2080 }
2081 }
2082 }
2083 if (found_markers == query.bind_markers.len) {
2084 break :marker_len_check;
2085 }
2086 }
2087 @compileError(std.fmt.comptimePrint("expected {d} bind parameters but got {d}", .{
2088 query.bind_markers.len,
2089 StructTypeInfo.fields.len,
2090 }));
2091 }
2077 } 2092 }
2078 2093
2079 inline for (StructTypeInfo.fields, 0..) |struct_field, _i| { 2094 inline for (StructTypeInfo.fields, 0..) |struct_field, _i| {
@@ -4021,3 +4036,26 @@ test "tagged union" {
4021 try testing.expectEqual(foobar.age, result.?.value); 4036 try testing.expectEqual(foobar.age, result.?.value);
4022 } 4037 }
4023} 4038}
4039
4040test "reuse same field twice in query string" {
4041 var db = try getTestDb();
4042 defer db.deinit();
4043 try addTestData(&db);
4044
4045 const update_name = "NewUpdatedName";
4046
4047 const update_name_query = "UPDATE user SET id = $id, name = $name WHERE id = $id";
4048 try db.exec(update_name_query, .{}, .{ .id = 20, .name = update_name });
4049
4050 const fetch_name_query = "SELECT name FROM user WHERE id = $id";
4051 const name = try db.oneAlloc(
4052 []const u8,
4053 testing.allocator,
4054 fetch_name_query,
4055 .{},
4056 .{ .id = 20 },
4057 );
4058 try testing.expect(name != null);
4059 defer testing.allocator.free(name.?);
4060 try testing.expectEqualStrings(name.?, update_name);
4061}