summaryrefslogtreecommitdiff
path: root/query.zig
diff options
context:
space:
mode:
Diffstat (limited to 'query.zig')
-rw-r--r--query.zig24
1 files changed, 21 insertions, 3 deletions
diff --git a/query.zig b/query.zig
index 0f3bcd3..647dc3e 100644
--- a/query.zig
+++ b/query.zig
@@ -6,6 +6,8 @@ const Blob = @import("sqlite.zig").Blob;
6const Text = @import("sqlite.zig").Text; 6const Text = @import("sqlite.zig").Text;
7 7
8const BindMarker = struct { 8const 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
22fn 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
20pub fn ParsedQuery(comptime query: []const u8) ParsedQueryState(query.len) { 30pub 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;