diff options
| -rw-r--r-- | query.zig | 24 |
1 files changed, 21 insertions, 3 deletions
| @@ -6,6 +6,8 @@ const Blob = @import("sqlite.zig").Blob; | |||
| 6 | const Text = @import("sqlite.zig").Text; | 6 | const Text = @import("sqlite.zig").Text; |
| 7 | 7 | ||
| 8 | const BindMarker = struct { | 8 | const BindMarker = struct { |
| 9 | /// Name of the bind parameter in case it's named. | ||
| 10 | name: ?[]const u8 = null, | ||
| 9 | /// Contains the expected type for a bind parameter which will be checked | 11 | /// Contains the expected type for a bind parameter which will be checked |
| 10 | /// at comptime when calling bind on a statement. | 12 | /// at comptime when calling bind on a statement. |
| 11 | /// | 13 | /// |
| @@ -17,6 +19,14 @@ fn isNamedIdentifierChar(c: u8) bool { | |||
| 17 | return std.ascii.isAlphabetic(c) or std.ascii.isDigit(c) or c == '_'; | 19 | return std.ascii.isAlphabetic(c) or std.ascii.isDigit(c) or c == '_'; |
| 18 | } | 20 | } |
| 19 | 21 | ||
| 22 | fn bindMarkerForName(comptime markers: []const BindMarker, comptime name: []const u8) ?BindMarker { | ||
| 23 | for (markers[0..]) |marker| { | ||
| 24 | if (marker.name != null and std.mem.eql(u8, marker.name.?, name)) | ||
| 25 | return marker; | ||
| 26 | } | ||
| 27 | return null; | ||
| 28 | } | ||
| 29 | |||
| 20 | pub fn ParsedQuery(comptime query: []const u8) ParsedQueryState(query.len) { | 30 | pub fn ParsedQuery(comptime query: []const u8) ParsedQueryState(query.len) { |
| 21 | // This contains the final SQL query after parsing with our | 31 | // This contains the final SQL query after parsing with our |
| 22 | // own typed bind markers removed. | 32 | // own typed bind markers removed. |
| @@ -31,6 +41,9 @@ pub fn ParsedQuery(comptime query: []const u8) ParsedQueryState(query.len) { | |||
| 31 | comptime var bind_markers: [128]BindMarker = undefined; | 41 | comptime var bind_markers: [128]BindMarker = undefined; |
| 32 | comptime var nb_bind_markers: usize = 0; | 42 | comptime var nb_bind_markers: usize = 0; |
| 33 | 43 | ||
| 44 | // used for capturing slices, such as bind parameter name | ||
| 45 | comptime var hold_pos = 0; | ||
| 46 | |||
| 34 | inline for (query) |c| { | 47 | inline for (query) |c| { |
| 35 | switch (state) { | 48 | switch (state) { |
| 36 | .start => switch (c) { | 49 | .start => switch (c) { |
| @@ -41,7 +54,7 @@ pub fn ParsedQuery(comptime query: []const u8) ParsedQueryState(query.len) { | |||
| 41 | buf[pos] = c; | 54 | buf[pos] = c; |
| 42 | pos += 1; | 55 | pos += 1; |
| 43 | }, | 56 | }, |
| 44 | '\'', '"' => { | 57 | '\'', '"', '[', '`' => { |
| 45 | state = .inside_string; | 58 | state = .inside_string; |
| 46 | buf[pos] = c; | 59 | buf[pos] = c; |
| 47 | pos += 1; | 60 | pos += 1; |
| @@ -52,7 +65,7 @@ pub fn ParsedQuery(comptime query: []const u8) ParsedQueryState(query.len) { | |||
| 52 | }, | 65 | }, |
| 53 | }, | 66 | }, |
| 54 | .inside_string => switch (c) { | 67 | .inside_string => switch (c) { |
| 55 | '\'', '"' => { | 68 | '\'', '"', ']', '`' => { |
| 56 | state = .start; | 69 | state = .start; |
| 57 | buf[pos] = c; | 70 | buf[pos] = c; |
| 58 | pos += 1; | 71 | pos += 1; |
| @@ -71,6 +84,7 @@ pub fn ParsedQuery(comptime query: []const u8) ParsedQueryState(query.len) { | |||
| 71 | if (isNamedIdentifierChar(c)) { | 84 | if (isNamedIdentifierChar(c)) { |
| 72 | // This is the start of a named bind marker. | 85 | // This is the start of a named bind marker. |
| 73 | state = .bind_marker_identifier; | 86 | state = .bind_marker_identifier; |
| 87 | hold_pos = pos + 1; | ||
| 74 | } else { | 88 | } else { |
| 75 | // This is a unnamed, untyped bind marker. | 89 | // This is a unnamed, untyped bind marker. |
| 76 | state = .start; | 90 | state = .start; |
| @@ -92,7 +106,11 @@ pub fn ParsedQuery(comptime query: []const u8) ParsedQueryState(query.len) { | |||
| 92 | if (!isNamedIdentifierChar(c)) { | 106 | if (!isNamedIdentifierChar(c)) { |
| 93 | // This marks the end of the named bind marker. | 107 | // This marks the end of the named bind marker. |
| 94 | state = .start; | 108 | state = .start; |
| 95 | nb_bind_markers += 1; | 109 | const name = buf[hold_pos..pos - 1]; |
| 110 | if (bindMarkerForName(bind_markers[0..nb_bind_markers], name) == null) { | ||
| 111 | bind_markers[nb_bind_markers].name = name; | ||
| 112 | nb_bind_markers += 1; | ||
| 113 | } | ||
| 96 | } | 114 | } |
| 97 | buf[pos] = c; | 115 | buf[pos] = c; |
| 98 | pos += 1; | 116 | pos += 1; |