From 4adf799e80b6e820c9860f3b88da825d0d58e9fc Mon Sep 17 00:00:00 2001 From: Antonio Date: Thu, 25 Dec 2025 13:13:08 -0400 Subject: [PATCH 1/4] fix: sqlite single quote interpolations --- interpolate.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interpolate.go b/interpolate.go index c6eb1db..c0f923a 100644 --- a/interpolate.go +++ b/interpolate.go @@ -803,12 +803,12 @@ func quoteStringValue(buf []byte, s string, flavor Flavor) []byte { buf = append(buf, "\\Z"...) case '\'': - if flavor == CQL { + switch flavor { + case SQLite, CQL: buf = append(buf, "''"...) - } else { + default: buf = append(buf, "\\'"...) } - case '"': buf = append(buf, "\\\""...) From 947cd7694a20c110c679177bee1374787b646487 Mon Sep 17 00:00:00 2001 From: Antonio Date: Thu, 25 Dec 2025 14:19:30 -0400 Subject: [PATCH 2/4] fix: factually correct escpaing in sqlite --- interpolate.go | 66 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 17 deletions(-) diff --git a/interpolate.go b/interpolate.go index c0f923a..cadc830 100644 --- a/interpolate.go +++ b/interpolate.go @@ -785,36 +785,68 @@ func quoteStringValue(buf []byte, s string, flavor Flavor) []byte { for ; sz != 0; r, sz = utf8.DecodeRuneInString(s) { switch r { case '\x00': - buf = append(buf, "\\0"...) - + switch flavor { + case SQLite: // SQLite doesn't support \0 + buf = append(buf, `'||char(0)||'`...) + default: + buf = append(buf, `\0`...) + } case '\b': - buf = append(buf, "\\b"...) - + switch flavor { + case SQLite: // SQLite doesn't have any special meaning for back slashes "\" + buf = append(buf, '\b') + default: + buf = append(buf, `\b`...) + } case '\n': - buf = append(buf, "\\n"...) - + switch flavor { + case SQLite: // SQLite doesn't have any special meaning for back slashes "\" + buf = append(buf, '\n') + default: + buf = append(buf, `\n`...) + } case '\r': - buf = append(buf, "\\r"...) - + switch flavor { + case SQLite: // SQLite doesn't have any special meaning for back slashes "\" + buf = append(buf, '\r') + default: + buf = append(buf, `\r`...) + } case '\t': - buf = append(buf, "\\t"...) - + switch flavor { + case SQLite: // SQLite doesn't have any special meaning for back slashes "\" + buf = append(buf, '\t') + default: + buf = append(buf, `\t`...) + } case '\x1a': - buf = append(buf, "\\Z"...) - + switch flavor { + case SQLite: // SQLite doesn't have any special meaning for back slashes "\" + buf = append(buf, '\x1a') + default: + buf = append(buf, `\Z`...) + } case '\'': switch flavor { case SQLite, CQL: buf = append(buf, "''"...) default: - buf = append(buf, "\\'"...) + buf = append(buf, `\'`...) } case '"': - buf = append(buf, "\\\""...) - + switch flavor { + case SQLite: // SQLite Supports direct use of " inside strings + buf = append(buf, '"') + default: + buf = append(buf, `\"`...) + } case '\\': - buf = append(buf, "\\\\"...) - + switch flavor { + case SQLite: // SQLite doesn't have any special meaning for back slashes "\" + buf = append(buf, '\\') + default: + buf = append(buf, `\\`...) + } default: buf = append(buf, s[:sz]...) } From dd48ffdce6728bc849ebf0b9d5a68df2361a42dd Mon Sep 17 00:00:00 2001 From: Antonio Date: Mon, 29 Dec 2025 11:33:43 -0400 Subject: [PATCH 3/4] test: make all tests pass by resolving to correct SQLite syntax --- flavor_test.go | 2 +- interpolate_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/flavor_test.go b/flavor_test.go index ff9520c..3d21d8a 100644 --- a/flavor_test.go +++ b/flavor_test.go @@ -105,7 +105,7 @@ func ExampleFlavor_Interpolate_sqlite() { fmt.Println(err) // Output: - // SELECT name FROM user WHERE id <> 1234 AND name = 'Charmy Liu' AND desc LIKE '%mother\'s day%' + // SELECT name FROM user WHERE id <> 1234 AND name = 'Charmy Liu' AND desc LIKE '%mother''s day%' // } diff --git a/interpolate_test.go b/interpolate_test.go index eafd81c..454dfb4 100644 --- a/interpolate_test.go +++ b/interpolate_test.go @@ -120,12 +120,12 @@ func TestFlavorInterpolate(t *testing.T) { { SQLite, "SELECT * FROM a WHERE name = ? AND state IN (?, ?, ?, ?, ?)", []interface{}{"I'm fine", 42, int8(8), int16(-16), int32(32), int64(64)}, - "SELECT * FROM a WHERE name = 'I\\'m fine' AND state IN (42, 8, -16, 32, 64)", nil, + "SELECT * FROM a WHERE name = 'I''m fine' AND state IN (42, 8, -16, 32, 64)", nil, }, { SQLite, "SELECT * FROM `a?` WHERE name = \"?\" AND state IN (?, '?', ?, ?, ?, ?, ?)", []interface{}{"\r\n\b\t\x1a\x00\\\"'", uint(42), uint8(8), uint16(16), uint32(32), uint64(64), "useless"}, - "SELECT * FROM `a?` WHERE name = \"?\" AND state IN ('\\r\\n\\b\\t\\Z\\0\\\\\\\"\\'', '?', 42, 8, 16, 32, 64)", nil, + "SELECT * FROM `a?` WHERE name = \"?\" AND state IN ('\r\n\b\t\x1a'||char(0)||'\\\"''', '?', 42, 8, 16, 32, 64)", nil, }, { SQLite, From 2994d275275bb0f931ebdd99f96676b4b9c4f8ba Mon Sep 17 00:00:00 2001 From: Antonio Date: Mon, 29 Dec 2025 11:36:09 -0400 Subject: [PATCH 4/4] fix: removed comments --- interpolate.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/interpolate.go b/interpolate.go index cadc830..59abaa6 100644 --- a/interpolate.go +++ b/interpolate.go @@ -786,42 +786,42 @@ func quoteStringValue(buf []byte, s string, flavor Flavor) []byte { switch r { case '\x00': switch flavor { - case SQLite: // SQLite doesn't support \0 + case SQLite: buf = append(buf, `'||char(0)||'`...) default: buf = append(buf, `\0`...) } case '\b': switch flavor { - case SQLite: // SQLite doesn't have any special meaning for back slashes "\" + case SQLite: buf = append(buf, '\b') default: buf = append(buf, `\b`...) } case '\n': switch flavor { - case SQLite: // SQLite doesn't have any special meaning for back slashes "\" + case SQLite: buf = append(buf, '\n') default: buf = append(buf, `\n`...) } case '\r': switch flavor { - case SQLite: // SQLite doesn't have any special meaning for back slashes "\" + case SQLite: buf = append(buf, '\r') default: buf = append(buf, `\r`...) } case '\t': switch flavor { - case SQLite: // SQLite doesn't have any special meaning for back slashes "\" + case SQLite: buf = append(buf, '\t') default: buf = append(buf, `\t`...) } case '\x1a': switch flavor { - case SQLite: // SQLite doesn't have any special meaning for back slashes "\" + case SQLite: buf = append(buf, '\x1a') default: buf = append(buf, `\Z`...) @@ -835,14 +835,14 @@ func quoteStringValue(buf []byte, s string, flavor Flavor) []byte { } case '"': switch flavor { - case SQLite: // SQLite Supports direct use of " inside strings + case SQLite: buf = append(buf, '"') default: buf = append(buf, `\"`...) } case '\\': switch flavor { - case SQLite: // SQLite doesn't have any special meaning for back slashes "\" + case SQLite: buf = append(buf, '\\') default: buf = append(buf, `\\`...)