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 b3e5957..6174d1c 100644
--- a/sqlite.zig
+++ b/sqlite.zig
@@ -2078,11 +2078,26 @@ pub fn Statement(comptime opts: StatementOptions, comptime query: anytype) type
2078 2078
2079 const StructTypeInfo = @typeInfo(StructType).@"struct"; 2079 const StructTypeInfo = @typeInfo(StructType).@"struct";
2080 2080
2081 if (comptime query.bind_markers.len != StructTypeInfo.fields.len) { 2081 comptime marker_len_check: {
2082 @compileError(std.fmt.comptimePrint("expected {d} bind parameters but got {d}", .{ 2082 if (query.bind_markers.len != StructTypeInfo.fields.len) {
2083 query.bind_markers.len, 2083 if (query.bind_markers.len > StructTypeInfo.fields.len) {
2084 StructTypeInfo.fields.len, 2084 var found_markers = 0;
2085 })); 2085 for (query.bind_markers) |bind_marker| {
2086 if (bind_marker.name) |name| {
2087 if (@hasField(StructType, name)) {
2088 found_markers += 1;
2089 }
2090 }
2091 }
2092 if (found_markers == query.bind_markers.len) {
2093 break :marker_len_check;
2094 }
2095 }
2096 @compileError(std.fmt.comptimePrint("expected {d} bind parameters but got {d}", .{
2097 query.bind_markers.len,
2098 StructTypeInfo.fields.len,
2099 }));
2100 }
2086 } 2101 }
2087 2102
2088 inline for (StructTypeInfo.fields, 0..) |struct_field, _i| { 2103 inline for (StructTypeInfo.fields, 0..) |struct_field, _i| {
@@ -4030,3 +4045,26 @@ test "tagged union" {
4030 try testing.expectEqual(foobar.age, result.?.value); 4045 try testing.expectEqual(foobar.age, result.?.value);
4031 } 4046 }
4032} 4047}
4048
4049test "reuse same field twice in query string" {
4050 var db = try getTestDb();
4051 defer db.deinit();
4052 try addTestData(&db);
4053
4054 const update_name = "NewUpdatedName";
4055
4056 const update_name_query = "UPDATE user SET id = $id, name = $name WHERE id = $id";
4057 try db.exec(update_name_query, .{}, .{ .id = 20, .name = update_name });
4058
4059 const fetch_name_query = "SELECT name FROM user WHERE id = $id";
4060 const name = try db.oneAlloc(
4061 []const u8,
4062 testing.allocator,
4063 fetch_name_query,
4064 .{},
4065 .{ .id = 20 },
4066 );
4067 try testing.expect(name != null);
4068 defer testing.allocator.free(name.?);
4069 try testing.expectEqualStrings(name.?, update_name);
4070}