From 2f3206c4159f2b31b6b8c29e4bceb94c5fd770d8 Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Thu, 19 Dec 2024 16:58:37 +0900 Subject: [PATCH 1/8] Fix literals format --- testdata/result/expr/cast_as_typename.sql.txt | 2 +- testdata/result/expr/json_literal.sql.txt | 2 +- .../result/query/select_literals_all.sql.txt | 2 +- .../query/select_literals_bytes.sql.txt | 2 +- .../query/select_literals_string.sql.txt | 2 +- .../query/select_subscript_operators.sql.txt | 2 +- .../statement/select_literals_all.sql.txt | 2 +- .../statement/select_literals_bytes.sql.txt | 2 +- .../statement/select_literals_string.sql.txt | 2 +- .../select_subscript_operators.sql.txt | 2 +- token/quote.go | 79 ++++++++++++------- token/quote_test.go | 14 ++-- 12 files changed, 67 insertions(+), 46 deletions(-) diff --git a/testdata/result/expr/cast_as_typename.sql.txt b/testdata/result/expr/cast_as_typename.sql.txt index 6f45397d..295f0ef1 100644 --- a/testdata/result/expr/cast_as_typename.sql.txt +++ b/testdata/result/expr/cast_as_typename.sql.txt @@ -30,4 +30,4 @@ CAST('order_number: "123"' AS examples.shipping.`Order`) } --- SQL -CAST("order_number: \"123\"" AS examples.shipping.`Order`) +CAST('order_number: "123"' AS examples.shipping.`Order`) diff --git a/testdata/result/expr/json_literal.sql.txt b/testdata/result/expr/json_literal.sql.txt index 6e358b4a..ade4d746 100644 --- a/testdata/result/expr/json_literal.sql.txt +++ b/testdata/result/expr/json_literal.sql.txt @@ -10,4 +10,4 @@ JSON '{"s": "foo", "n": 42}' } --- SQL -JSON "{\"s\": \"foo\", \"n\": 42}" +JSON '{"s": "foo", "n": 42}' diff --git a/testdata/result/query/select_literals_all.sql.txt b/testdata/result/query/select_literals_all.sql.txt index da902945..371cad18 100644 --- a/testdata/result/query/select_literals_all.sql.txt +++ b/testdata/result/query/select_literals_all.sql.txt @@ -597,4 +597,4 @@ lines''', } --- SQL -SELECT "abc", "it\'s", "it\'s", "Title: \"Boy\"", "abc", "it\'s", "Title:\"Boy\"", "two\nlines", "why\?", "abc+", "abc+", "abc+", "f\\(abc,(.*),def\\)", B"abc", B"abc", B"abc", B"abc+", B"abc+", B"abc", 123, 0xABC, -123, -0xABC, 123.456e-67, .1E4, 58., 4e2, [1, 2, 3], ["x", "y", "xy"], ARRAY[1, 2, 3], ARRAY<STRING>["x", "y", "xy"], ARRAY<INT64>[], ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT (1, 2, 3)), DATE "2014-09-27", DATE("2014-09-27"), TIMESTAMP "2014-09-27 12:30:00.45-08", TIMESTAMP "2014-09-27 12:30:00.45 America/Los_Angeles", TIMESTAMP "2014-09-27", TIMESTAMP("2014-09-27"), JSON "1", JSON "[1, 2]", JSON "{}", NUMERIC "0", NUMERIC "0", TRUE, FALSE +SELECT "abc", "it's", "it's", 'Title: "Boy"', "abc", "it's", 'Title:"Boy"', "two\nlines", "why\?", "abc+", "abc+", "abc+", "f\\(abc,(.*),def\\)", b"abc", b"abc", b"abc", b"abc+", b"abc+", b"abc", 123, 0xABC, -123, -0xABC, 123.456e-67, .1E4, 58., 4e2, [1, 2, 3], ["x", "y", "xy"], ARRAY[1, 2, 3], ARRAY<STRING>["x", "y", "xy"], ARRAY<INT64>[], ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT (1, 2, 3)), DATE "2014-09-27", DATE("2014-09-27"), TIMESTAMP "2014-09-27 12:30:00.45-08", TIMESTAMP "2014-09-27 12:30:00.45 America/Los_Angeles", TIMESTAMP "2014-09-27", TIMESTAMP("2014-09-27"), JSON "1", JSON "[1, 2]", JSON "{}", NUMERIC "0", NUMERIC "0", TRUE, FALSE diff --git a/testdata/result/query/select_literals_bytes.sql.txt b/testdata/result/query/select_literals_bytes.sql.txt index 498b1214..c4803601 100644 --- a/testdata/result/query/select_literals_bytes.sql.txt +++ b/testdata/result/query/select_literals_bytes.sql.txt @@ -110,4 +110,4 @@ SELECT } --- SQL -SELECT B"abc", B"abc", B"abc", B"abc\n", B"abc+", B"abc+", B"abc", B"abc\\n", B"\x00", B"\?\?\?" +SELECT b"abc", b"abc", b"abc", b"abc\n", b"abc+", b"abc+", b"abc", b"abc\\n", b"\x00", b"\?\?\?" diff --git a/testdata/result/query/select_literals_string.sql.txt b/testdata/result/query/select_literals_string.sql.txt index 8686fd58..2f76d240 100644 --- a/testdata/result/query/select_literals_string.sql.txt +++ b/testdata/result/query/select_literals_string.sql.txt @@ -179,4 +179,4 @@ lines''', } --- SQL -SELECT "abc!", "a\nb!", "=!", "=!", "=!", "=!", "=!", "‼!", "🐈!", "it\'s", "it\'s", "Title: \"Boy\"", "abc", "it\'s", "Title:\"Boy\"", "two\nlines", "why\?", "abc+", "abc+", "abc+", "f\\(abc,(.*),def\\)" +SELECT "abc!", "a\nb!", "=!", "=!", "=!", "=!", "=!", "‼!", "🐈!", "it's", "it's", 'Title: "Boy"', "abc", "it's", 'Title:"Boy"', "two\nlines", "why\?", "abc+", "abc+", "abc+", "f\\(abc,(.*),def\\)" diff --git a/testdata/result/query/select_subscript_operators.sql.txt b/testdata/result/query/select_subscript_operators.sql.txt index 0ee39c7b..54276770 100644 --- a/testdata/result/query/select_subscript_operators.sql.txt +++ b/testdata/result/query/select_subscript_operators.sql.txt @@ -492,4 +492,4 @@ select } --- SQL -SELECT [1, 2, 3][OFFSET(1)], [1, 2, 3][ORDINAL(1)], [1, 2, 3][SAFE_OFFSET(1)], [1, 2, 3][ORDINAL(1)], [1, 2, 3][1], STRUCT(1, 2, 3)[OFFSET(1)], STRUCT(1, 2, 3)[ORDINAL(1)], STRUCT(1, 2, 3)[SAFE_OFFSET(1)], STRUCT(1, 2, 3)[ORDINAL(1)], STRUCT(1, 2, 3)[1], JSON "[1, 2, 3]"[1], JSON "{\"a\": 1, \"b\": 2, \"c\": 3}"["a"] +SELECT [1, 2, 3][OFFSET(1)], [1, 2, 3][ORDINAL(1)], [1, 2, 3][SAFE_OFFSET(1)], [1, 2, 3][ORDINAL(1)], [1, 2, 3][1], STRUCT(1, 2, 3)[OFFSET(1)], STRUCT(1, 2, 3)[ORDINAL(1)], STRUCT(1, 2, 3)[SAFE_OFFSET(1)], STRUCT(1, 2, 3)[ORDINAL(1)], STRUCT(1, 2, 3)[1], JSON "[1, 2, 3]"[1], JSON '{"a": 1, "b": 2, "c": 3}'["a"] diff --git a/testdata/result/statement/select_literals_all.sql.txt b/testdata/result/statement/select_literals_all.sql.txt index da902945..371cad18 100644 --- a/testdata/result/statement/select_literals_all.sql.txt +++ b/testdata/result/statement/select_literals_all.sql.txt @@ -597,4 +597,4 @@ lines''', } --- SQL -SELECT "abc", "it\'s", "it\'s", "Title: \"Boy\"", "abc", "it\'s", "Title:\"Boy\"", "two\nlines", "why\?", "abc+", "abc+", "abc+", "f\\(abc,(.*),def\\)", B"abc", B"abc", B"abc", B"abc+", B"abc+", B"abc", 123, 0xABC, -123, -0xABC, 123.456e-67, .1E4, 58., 4e2, [1, 2, 3], ["x", "y", "xy"], ARRAY[1, 2, 3], ARRAY<STRING>["x", "y", "xy"], ARRAY<INT64>[], ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT (1, 2, 3)), DATE "2014-09-27", DATE("2014-09-27"), TIMESTAMP "2014-09-27 12:30:00.45-08", TIMESTAMP "2014-09-27 12:30:00.45 America/Los_Angeles", TIMESTAMP "2014-09-27", TIMESTAMP("2014-09-27"), JSON "1", JSON "[1, 2]", JSON "{}", NUMERIC "0", NUMERIC "0", TRUE, FALSE +SELECT "abc", "it's", "it's", 'Title: "Boy"', "abc", "it's", 'Title:"Boy"', "two\nlines", "why\?", "abc+", "abc+", "abc+", "f\\(abc,(.*),def\\)", b"abc", b"abc", b"abc", b"abc+", b"abc+", b"abc", 123, 0xABC, -123, -0xABC, 123.456e-67, .1E4, 58., 4e2, [1, 2, 3], ["x", "y", "xy"], ARRAY[1, 2, 3], ARRAY<STRING>["x", "y", "xy"], ARRAY<INT64>[], ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT (1, 2, 3)), DATE "2014-09-27", DATE("2014-09-27"), TIMESTAMP "2014-09-27 12:30:00.45-08", TIMESTAMP "2014-09-27 12:30:00.45 America/Los_Angeles", TIMESTAMP "2014-09-27", TIMESTAMP("2014-09-27"), JSON "1", JSON "[1, 2]", JSON "{}", NUMERIC "0", NUMERIC "0", TRUE, FALSE diff --git a/testdata/result/statement/select_literals_bytes.sql.txt b/testdata/result/statement/select_literals_bytes.sql.txt index 498b1214..c4803601 100644 --- a/testdata/result/statement/select_literals_bytes.sql.txt +++ b/testdata/result/statement/select_literals_bytes.sql.txt @@ -110,4 +110,4 @@ SELECT } --- SQL -SELECT B"abc", B"abc", B"abc", B"abc\n", B"abc+", B"abc+", B"abc", B"abc\\n", B"\x00", B"\?\?\?" +SELECT b"abc", b"abc", b"abc", b"abc\n", b"abc+", b"abc+", b"abc", b"abc\\n", b"\x00", b"\?\?\?" diff --git a/testdata/result/statement/select_literals_string.sql.txt b/testdata/result/statement/select_literals_string.sql.txt index 8686fd58..2f76d240 100644 --- a/testdata/result/statement/select_literals_string.sql.txt +++ b/testdata/result/statement/select_literals_string.sql.txt @@ -179,4 +179,4 @@ lines''', } --- SQL -SELECT "abc!", "a\nb!", "=!", "=!", "=!", "=!", "=!", "‼!", "🐈!", "it\'s", "it\'s", "Title: \"Boy\"", "abc", "it\'s", "Title:\"Boy\"", "two\nlines", "why\?", "abc+", "abc+", "abc+", "f\\(abc,(.*),def\\)" +SELECT "abc!", "a\nb!", "=!", "=!", "=!", "=!", "=!", "‼!", "🐈!", "it's", "it's", 'Title: "Boy"', "abc", "it's", 'Title:"Boy"', "two\nlines", "why\?", "abc+", "abc+", "abc+", "f\\(abc,(.*),def\\)" diff --git a/testdata/result/statement/select_subscript_operators.sql.txt b/testdata/result/statement/select_subscript_operators.sql.txt index 0ee39c7b..54276770 100644 --- a/testdata/result/statement/select_subscript_operators.sql.txt +++ b/testdata/result/statement/select_subscript_operators.sql.txt @@ -492,4 +492,4 @@ select } --- SQL -SELECT [1, 2, 3][OFFSET(1)], [1, 2, 3][ORDINAL(1)], [1, 2, 3][SAFE_OFFSET(1)], [1, 2, 3][ORDINAL(1)], [1, 2, 3][1], STRUCT(1, 2, 3)[OFFSET(1)], STRUCT(1, 2, 3)[ORDINAL(1)], STRUCT(1, 2, 3)[SAFE_OFFSET(1)], STRUCT(1, 2, 3)[ORDINAL(1)], STRUCT(1, 2, 3)[1], JSON "[1, 2, 3]"[1], JSON "{\"a\": 1, \"b\": 2, \"c\": 3}"["a"] +SELECT [1, 2, 3][OFFSET(1)], [1, 2, 3][ORDINAL(1)], [1, 2, 3][SAFE_OFFSET(1)], [1, 2, 3][ORDINAL(1)], [1, 2, 3][1], STRUCT(1, 2, 3)[OFFSET(1)], STRUCT(1, 2, 3)[ORDINAL(1)], STRUCT(1, 2, 3)[SAFE_OFFSET(1)], STRUCT(1, 2, 3)[ORDINAL(1)], STRUCT(1, 2, 3)[1], JSON "[1, 2, 3]"[1], JSON '{"a": 1, "b": 2, "c": 3}'["a"] diff --git a/token/quote.go b/token/quote.go index 6ded3213..9f510510 100644 --- a/token/quote.go +++ b/token/quote.go @@ -10,30 +10,53 @@ import ( // QuoteSQLString returns quoted string with SQL string escaping. func QuoteSQLString(s string) string { + quote := suitableQuote([]byte(s)) + var buf bytes.Buffer - buf.WriteByte('"') - quoteSQLStringContent(s, &buf) - buf.WriteByte('"') + buf.WriteRune(quote) + quoteSQLStringContent(quote, s, &buf) + buf.WriteRune(quote) return buf.String() } +func suitableQuote(b []byte) rune { + var hasSingle, hasDouble bool + for _, b := range b { + switch b { + case '\'': + hasSingle = true + case '"': + hasDouble = true + } + } + if !hasSingle && hasDouble { + return '\'' + } + return '"' +} + // QuoteSQLString returns quoted string with SQL bytes escaping. func QuoteSQLBytes(bs []byte) string { + quote := suitableQuote(bs) + var buf bytes.Buffer - buf.WriteString("B\"") + buf.WriteString("b") + buf.WriteRune(quote) for _, b := range bs { - q := quoteSingleEscape(rune(b)) + q := quoteSingleEscape(quote, rune(b)) if q != "" { buf.WriteString(q) continue } - if char.IsPrint(b) { + + // Note: char.IsPrint(' ') is false + if b == ' ' || char.IsPrint(b) { buf.WriteByte(b) continue } - fmt.Fprintf(&buf, "\\x%02X", uint64(b)) + fmt.Fprintf(&buf, `\x%02x`, uint64(b)) } - buf.WriteRune('"') + buf.WriteRune(quote) return buf.String() } @@ -46,14 +69,14 @@ func QuoteSQLIdent(s string) string { var buf bytes.Buffer buf.WriteByte('`') - quoteSQLStringContent(s, &buf) + quoteSQLStringContent('`', s, &buf) buf.WriteByte('`') return buf.String() } -func quoteSQLStringContent(s string, buf *bytes.Buffer) { +func quoteSQLStringContent(quote rune, s string, buf *bytes.Buffer) { for _, r := range s { - q := quoteSingleEscape(r) + q := quoteSingleEscape(quote, r) if q != "" { buf.WriteString(q) continue @@ -63,39 +86,37 @@ func quoteSQLStringContent(s string, buf *bytes.Buffer) { continue } if r > 0xFFFF { - fmt.Fprintf(buf, "\\U%08X", uint64(r)) + fmt.Fprintf(buf, `\U%08x`, uint64(r)) } else { - fmt.Fprintf(buf, "\\u%04X", uint64(r)) + fmt.Fprintf(buf, `\u%04x`, uint64(r)) } } } -func quoteSingleEscape(r rune) string { +func quoteSingleEscape(quote, r rune) string { + if quote == r { + return `\` + string(r) + } + switch r { case '\a': - return "\\a" + return `\a` case '\b': - return "\\b" + return `\b` case '\f': - return "\\f" + return `\f` case '\n': - return "\\n" + return `\n` case '\r': - return "\\r" + return `\r` case '\t': - return "\\t" + return `\t` case '\v': - return "\\v" - case '"': - return "\\\"" - case '\'': - return "\\'" - case '`': - return "\\`" + return `\v` case '?': - return "\\?" + return `\?` case '\\': - return "\\\\" + return `\\` } return "" } diff --git a/token/quote_test.go b/token/quote_test.go index 051f4973..00bea4fd 100644 --- a/token/quote_test.go +++ b/token/quote_test.go @@ -8,13 +8,13 @@ var quoteTestCases = []struct { input string str, bytes, id string }{ - {"foo", `"foo"`, `B"foo"`, "foo"}, - {"if", `"if"`, `B"if"`, "`if`"}, - {"\u0000", `"\u0000"`, `B"\x00"`, "`\\u0000`"}, - {"\U0010FFFF", `"\U0010FFFF"`, `B"\xF4\x8F\xBF\xBF"`, "`\\U0010FFFF`"}, - {"a\u2060b", `"a\u2060b"`, `B"a\xE2\x81\xA0b"`, "`a\\u2060b`"}, - {"\a\b\f\n\r\t\v\"'?\\", `"\a\b\f\n\r\t\v\"\'\?\\"`, `B"\a\b\f\n\r\t\v\"\'\?\\"`, "`\\a\\b\\f\\n\\r\\t\\v\\\"\\'\\?\\\\`"}, - {"`", "\"\\`\"", "B\"\\`\"", "`\\``"}, + {"foo", `"foo"`, `b"foo"`, "foo"}, + {"if", `"if"`, `b"if"`, "`if`"}, + {"\u0000", `"\u0000"`, `b"\x00"`, "`\\u0000`"}, + {"\U0010FFFF", `"\U0010ffff"`, `b"\xf4\x8f\xbf\xbf"`, "`\\U0010ffff`"}, + {"a\u2060b", `"a\u2060b"`, `b"a\xe2\x81\xa0b"`, "`a\\u2060b`"}, + {"\a\b\f\n\r\t\v\"'?\\", `"\a\b\f\n\r\t\v\"'\?\\"`, `b"\a\b\f\n\r\t\v\"'\?\\"`, "`\\a\\b\\f\\n\\r\\t\\v\"'\\?\\\\`"}, + {"`", "\"`\"", "b\"`\"", "`\\``"}, } func TestQuote(t *testing.T) { From a95f042ae2cb4db17614fe2eb4ab07f84e8fadc7 Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Thu, 19 Dec 2024 18:25:46 +0900 Subject: [PATCH 2/8] Fit to align FORMAT("%T", input) --- char/is.go | 2 +- token/quote.go | 41 +++++++++++++++++------------------------ 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/char/is.go b/char/is.go index b5944e18..71bd9883 100644 --- a/char/is.go +++ b/char/is.go @@ -1,7 +1,7 @@ package char func IsPrint(b byte) bool { - return 0x21 <= b && b <= 0x7D + return 0x20 <= b && b <= 0x7E // ' ' to '~' } func IsDigit(c byte) bool { diff --git a/token/quote.go b/token/quote.go index 9f510510..642b7700 100644 --- a/token/quote.go +++ b/token/quote.go @@ -43,14 +43,13 @@ func QuoteSQLBytes(bs []byte) string { buf.WriteString("b") buf.WriteRune(quote) for _, b := range bs { - q := quoteSingleEscape(quote, rune(b)) + q := quoteSingleEscape(rune(b), quote, false) if q != "" { buf.WriteString(q) continue } - // Note: char.IsPrint(' ') is false - if b == ' ' || char.IsPrint(b) { + if char.IsPrint(b) { buf.WriteByte(b) continue } @@ -60,7 +59,7 @@ func QuoteSQLBytes(bs []byte) string { return buf.String() } -// QuoteSQLString returns quoted string with SQL bytes escaping if needed, +// QuoteSQLIdent returns quoted identifier if needed, // otherwise it returns the input string. func QuoteSQLIdent(s string) string { if !needQuoteSQLIdent(s) { @@ -76,7 +75,7 @@ func QuoteSQLIdent(s string) string { func quoteSQLStringContent(quote rune, s string, buf *bytes.Buffer) { for _, r := range s { - q := quoteSingleEscape(quote, r) + q := quoteSingleEscape(r, quote, /* isString */ true) if q != "" { buf.WriteString(q) continue @@ -85,37 +84,31 @@ func quoteSQLStringContent(quote rune, s string, buf *bytes.Buffer) { buf.WriteRune(r) continue } - if r > 0xFFFF { + switch { + case r < 0x80: + fmt.Fprintf(buf, `\x%02x`, uint64(r)) + case r > 0xFFFF: fmt.Fprintf(buf, `\U%08x`, uint64(r)) - } else { + default: fmt.Fprintf(buf, `\u%04x`, uint64(r)) } } } -func quoteSingleEscape(quote, r rune) string { +func quoteSingleEscape(r, quote rune, isString bool) string { if quote == r { - return `\` + string(r) } - switch r { - case '\a': - return `\a` - case '\b': - return `\b` - case '\f': - return `\f` - case '\n': + switch { + case r == quote: + return `\` + string(r) + case isString && r == '\n': return `\n` - case '\r': + case isString && r == '\r': return `\r` - case '\t': + case isString && r == '\t': return `\t` - case '\v': - return `\v` - case '?': - return `\?` - case '\\': + case isString && r == '\\': return `\\` } return "" From acb26ea5e2159f6ff9a935ed085a9356207afa44 Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Thu, 19 Dec 2024 18:26:06 +0900 Subject: [PATCH 3/8] Update testdata --- .../input/expr/bytes_literal_seven_bits.sql | 1 + .../input/expr/string_literal_seven_bits.sql | 1 + .../ddl/create_table_for_format_test.sql.txt | 8 ++++---- ...create_table_with_identity_columns.sql.txt | 7 ++++++- .../expr/bytes_literal_seven_bits.sql.txt | 19 +++++++++++++++++++ .../expr/string_literal_seven_bits.sql.txt | 10 ++++++++++ .../query/select_from_ml_predict_hint.sql.txt | 2 +- .../select_from_ml_predict_textbison.sql.txt | 2 +- .../result/query/select_literals_all.sql.txt | 2 +- .../query/select_literals_bytes.sql.txt | 2 +- .../query/select_literals_string.sql.txt | 2 +- .../create_table_for_format_test.sql.txt | 8 ++++---- ...create_table_with_identity_columns.sql.txt | 7 ++++++- .../select_from_ml_predict_hint.sql.txt | 2 +- .../select_from_ml_predict_textbison.sql.txt | 2 +- .../statement/select_literals_all.sql.txt | 2 +- .../statement/select_literals_bytes.sql.txt | 2 +- .../statement/select_literals_string.sql.txt | 2 +- 18 files changed, 61 insertions(+), 20 deletions(-) create mode 100644 testdata/input/expr/bytes_literal_seven_bits.sql create mode 100644 testdata/input/expr/string_literal_seven_bits.sql create mode 100644 testdata/result/expr/bytes_literal_seven_bits.sql.txt create mode 100644 testdata/result/expr/string_literal_seven_bits.sql.txt diff --git a/testdata/input/expr/bytes_literal_seven_bits.sql b/testdata/input/expr/bytes_literal_seven_bits.sql new file mode 100644 index 00000000..e6edb149 --- /dev/null +++ b/testdata/input/expr/bytes_literal_seven_bits.sql @@ -0,0 +1 @@ +b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f" \ No newline at end of file diff --git a/testdata/input/expr/string_literal_seven_bits.sql b/testdata/input/expr/string_literal_seven_bits.sql new file mode 100644 index 00000000..799f906a --- /dev/null +++ b/testdata/input/expr/string_literal_seven_bits.sql @@ -0,0 +1 @@ +"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f" \ No newline at end of file diff --git a/testdata/result/ddl/create_table_for_format_test.sql.txt b/testdata/result/ddl/create_table_for_format_test.sql.txt index fe292d4f..bba51007 100644 --- a/testdata/result/ddl/create_table_for_format_test.sql.txt +++ b/testdata/result/ddl/create_table_for_format_test.sql.txt @@ -109,8 +109,8 @@ create table if not exists foo ( Value: "255", }, }, - NotNull: true, - GeneratedExpr: &ast.GeneratedColumnExpr{ + NotNull: true, + DefaultSemantics: &ast.GeneratedColumnExpr{ As: 172, Stored: 194, Rparen: 192, @@ -152,8 +152,8 @@ create table if not exists foo ( NamePos: 394, Name: "TIMESTAMP", }, - NotNull: true, - DefaultExpr: &ast.ColumnDefaultExpr{ + NotNull: true, + DefaultSemantics: &ast.ColumnDefaultExpr{ Default: 413, Rparen: 441, Expr: &ast.CallExpr{ diff --git a/testdata/result/ddl/create_table_with_identity_columns.sql.txt b/testdata/result/ddl/create_table_with_identity_columns.sql.txt index a88f5ba6..41dbf3eb 100644 --- a/testdata/result/ddl/create_table_with_identity_columns.sql.txt +++ b/testdata/result/ddl/create_table_with_identity_columns.sql.txt @@ -176,4 +176,9 @@ create table foo ( } --- SQL -CREATE TABLE foo (id INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE START COUNTER WITH 1000 SKIP RANGE 1, 12345), startCount INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE START COUNTER WITH 1000), skipRange INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE SKIP RANGE 1000, 2000), simple INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE)) PRIMARY KEY (id) +CREATE TABLE foo ( + id INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE START COUNTER WITH 1000 SKIP RANGE 1, 12345), + startCount INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE START COUNTER WITH 1000), + skipRange INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE SKIP RANGE 1000, 2000), + simple INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE) +) PRIMARY KEY (id) diff --git a/testdata/result/expr/bytes_literal_seven_bits.sql.txt b/testdata/result/expr/bytes_literal_seven_bits.sql.txt new file mode 100644 index 00000000..e8e4aaf8 --- /dev/null +++ b/testdata/result/expr/bytes_literal_seven_bits.sql.txt @@ -0,0 +1,19 @@ +--- bytes_literal_seven_bits.sql +b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f" +--- AST +&ast.BytesLiteral{ + ValueEnd: 232, + Value: []uint8{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + }, +} + +--- SQL +b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f" diff --git a/testdata/result/expr/string_literal_seven_bits.sql.txt b/testdata/result/expr/string_literal_seven_bits.sql.txt new file mode 100644 index 00000000..04fee57c --- /dev/null +++ b/testdata/result/expr/string_literal_seven_bits.sql.txt @@ -0,0 +1,10 @@ +--- string_literal_seven_bits.sql +"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f" +--- AST +&ast.StringLiteral{ + ValueEnd: 225, + Value: "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f", +} + +--- SQL +"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f" diff --git a/testdata/result/query/select_from_ml_predict_hint.sql.txt b/testdata/result/query/select_from_ml_predict_hint.sql.txt index cc99b9a8..78b338b2 100644 --- a/testdata/result/query/select_from_ml_predict_hint.sql.txt +++ b/testdata/result/query/select_from_ml_predict_hint.sql.txt @@ -172,4 +172,4 @@ FROM ML.PREDICT( } --- SQL -SELECT content FROM ML.PREDICT(MODEL TextBison, (SELECT "Is 13 prime\?" AS prompt), STRUCT(256 AS maxOutputTokens, 0.2 AS temperature, 40 AS topK, 0.95 AS topP)) @{remote_udf_max_rows_per_rpc=1} +SELECT content FROM ML.PREDICT(MODEL TextBison, (SELECT "Is 13 prime?" AS prompt), STRUCT(256 AS maxOutputTokens, 0.2 AS temperature, 40 AS topK, 0.95 AS topP)) @{remote_udf_max_rows_per_rpc=1} diff --git a/testdata/result/query/select_from_ml_predict_textbison.sql.txt b/testdata/result/query/select_from_ml_predict_textbison.sql.txt index 1d267c79..9d2cd598 100644 --- a/testdata/result/query/select_from_ml_predict_textbison.sql.txt +++ b/testdata/result/query/select_from_ml_predict_textbison.sql.txt @@ -367,4 +367,4 @@ FROM ML.PREDICT( } --- SQL -SELECT product_id, product_name, content FROM ML.PREDICT(MODEL TextBison, (SELECT product.id AS product_id, product.name AS product_name, CONCAT("Is this product safe for infants\?", "\n", "Product Name: ", product.name, "\n", "Category Name: ", category.name, "\n", "Product Description:", product.description) AS prompt FROM Products AS product INNER JOIN Categories AS category ON product.category_id = category.id), STRUCT(100 AS maxOutputTokens)) @{remote_udf_max_rows_per_rpc=1} +SELECT product_id, product_name, content FROM ML.PREDICT(MODEL TextBison, (SELECT product.id AS product_id, product.name AS product_name, CONCAT("Is this product safe for infants?", "\n", "Product Name: ", product.name, "\n", "Category Name: ", category.name, "\n", "Product Description:", product.description) AS prompt FROM Products AS product INNER JOIN Categories AS category ON product.category_id = category.id), STRUCT(100 AS maxOutputTokens)) @{remote_udf_max_rows_per_rpc=1} diff --git a/testdata/result/query/select_literals_all.sql.txt b/testdata/result/query/select_literals_all.sql.txt index 371cad18..2e488079 100644 --- a/testdata/result/query/select_literals_all.sql.txt +++ b/testdata/result/query/select_literals_all.sql.txt @@ -597,4 +597,4 @@ lines''', } --- SQL -SELECT "abc", "it's", "it's", 'Title: "Boy"', "abc", "it's", 'Title:"Boy"', "two\nlines", "why\?", "abc+", "abc+", "abc+", "f\\(abc,(.*),def\\)", b"abc", b"abc", b"abc", b"abc+", b"abc+", b"abc", 123, 0xABC, -123, -0xABC, 123.456e-67, .1E4, 58., 4e2, [1, 2, 3], ["x", "y", "xy"], ARRAY[1, 2, 3], ARRAY<STRING>["x", "y", "xy"], ARRAY<INT64>[], ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT (1, 2, 3)), DATE "2014-09-27", DATE("2014-09-27"), TIMESTAMP "2014-09-27 12:30:00.45-08", TIMESTAMP "2014-09-27 12:30:00.45 America/Los_Angeles", TIMESTAMP "2014-09-27", TIMESTAMP("2014-09-27"), JSON "1", JSON "[1, 2]", JSON "{}", NUMERIC "0", NUMERIC "0", TRUE, FALSE +SELECT "abc", "it's", "it's", 'Title: "Boy"', "abc", "it's", 'Title:"Boy"', "two\nlines", "why?", "abc+", "abc+", "abc+", "f\\(abc,(.*),def\\)", b"abc", b"abc", b"abc", b"abc+", b"abc+", b"abc", 123, 0xABC, -123, -0xABC, 123.456e-67, .1E4, 58., 4e2, [1, 2, 3], ["x", "y", "xy"], ARRAY[1, 2, 3], ARRAY<STRING>["x", "y", "xy"], ARRAY<INT64>[], ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT (1, 2, 3)), DATE "2014-09-27", DATE("2014-09-27"), TIMESTAMP "2014-09-27 12:30:00.45-08", TIMESTAMP "2014-09-27 12:30:00.45 America/Los_Angeles", TIMESTAMP "2014-09-27", TIMESTAMP("2014-09-27"), JSON "1", JSON "[1, 2]", JSON "{}", NUMERIC "0", NUMERIC "0", TRUE, FALSE diff --git a/testdata/result/query/select_literals_bytes.sql.txt b/testdata/result/query/select_literals_bytes.sql.txt index c4803601..e7d8c8d7 100644 --- a/testdata/result/query/select_literals_bytes.sql.txt +++ b/testdata/result/query/select_literals_bytes.sql.txt @@ -110,4 +110,4 @@ SELECT } --- SQL -SELECT b"abc", b"abc", b"abc", b"abc\n", b"abc+", b"abc+", b"abc", b"abc\\n", b"\x00", b"\?\?\?" +SELECT b"abc", b"abc", b"abc", b"abc\x0a", b"abc+", b"abc+", b"abc", b"abc\n", b"\x00", b"???" diff --git a/testdata/result/query/select_literals_string.sql.txt b/testdata/result/query/select_literals_string.sql.txt index 2f76d240..3ee18903 100644 --- a/testdata/result/query/select_literals_string.sql.txt +++ b/testdata/result/query/select_literals_string.sql.txt @@ -179,4 +179,4 @@ lines''', } --- SQL -SELECT "abc!", "a\nb!", "=!", "=!", "=!", "=!", "=!", "‼!", "🐈!", "it's", "it's", 'Title: "Boy"', "abc", "it's", 'Title:"Boy"', "two\nlines", "why\?", "abc+", "abc+", "abc+", "f\\(abc,(.*),def\\)" +SELECT "abc!", "a\nb!", "=!", "=!", "=!", "=!", "=!", "‼!", "🐈!", "it's", "it's", 'Title: "Boy"', "abc", "it's", 'Title:"Boy"', "two\nlines", "why?", "abc+", "abc+", "abc+", "f\\(abc,(.*),def\\)" diff --git a/testdata/result/statement/create_table_for_format_test.sql.txt b/testdata/result/statement/create_table_for_format_test.sql.txt index fe292d4f..bba51007 100644 --- a/testdata/result/statement/create_table_for_format_test.sql.txt +++ b/testdata/result/statement/create_table_for_format_test.sql.txt @@ -109,8 +109,8 @@ create table if not exists foo ( Value: "255", }, }, - NotNull: true, - GeneratedExpr: &ast.GeneratedColumnExpr{ + NotNull: true, + DefaultSemantics: &ast.GeneratedColumnExpr{ As: 172, Stored: 194, Rparen: 192, @@ -152,8 +152,8 @@ create table if not exists foo ( NamePos: 394, Name: "TIMESTAMP", }, - NotNull: true, - DefaultExpr: &ast.ColumnDefaultExpr{ + NotNull: true, + DefaultSemantics: &ast.ColumnDefaultExpr{ Default: 413, Rparen: 441, Expr: &ast.CallExpr{ diff --git a/testdata/result/statement/create_table_with_identity_columns.sql.txt b/testdata/result/statement/create_table_with_identity_columns.sql.txt index a88f5ba6..41dbf3eb 100644 --- a/testdata/result/statement/create_table_with_identity_columns.sql.txt +++ b/testdata/result/statement/create_table_with_identity_columns.sql.txt @@ -176,4 +176,9 @@ create table foo ( } --- SQL -CREATE TABLE foo (id INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE START COUNTER WITH 1000 SKIP RANGE 1, 12345), startCount INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE START COUNTER WITH 1000), skipRange INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE SKIP RANGE 1000, 2000), simple INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE)) PRIMARY KEY (id) +CREATE TABLE foo ( + id INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE START COUNTER WITH 1000 SKIP RANGE 1, 12345), + startCount INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE START COUNTER WITH 1000), + skipRange INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE SKIP RANGE 1000, 2000), + simple INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE) +) PRIMARY KEY (id) diff --git a/testdata/result/statement/select_from_ml_predict_hint.sql.txt b/testdata/result/statement/select_from_ml_predict_hint.sql.txt index cc99b9a8..78b338b2 100644 --- a/testdata/result/statement/select_from_ml_predict_hint.sql.txt +++ b/testdata/result/statement/select_from_ml_predict_hint.sql.txt @@ -172,4 +172,4 @@ FROM ML.PREDICT( } --- SQL -SELECT content FROM ML.PREDICT(MODEL TextBison, (SELECT "Is 13 prime\?" AS prompt), STRUCT(256 AS maxOutputTokens, 0.2 AS temperature, 40 AS topK, 0.95 AS topP)) @{remote_udf_max_rows_per_rpc=1} +SELECT content FROM ML.PREDICT(MODEL TextBison, (SELECT "Is 13 prime?" AS prompt), STRUCT(256 AS maxOutputTokens, 0.2 AS temperature, 40 AS topK, 0.95 AS topP)) @{remote_udf_max_rows_per_rpc=1} diff --git a/testdata/result/statement/select_from_ml_predict_textbison.sql.txt b/testdata/result/statement/select_from_ml_predict_textbison.sql.txt index 1d267c79..9d2cd598 100644 --- a/testdata/result/statement/select_from_ml_predict_textbison.sql.txt +++ b/testdata/result/statement/select_from_ml_predict_textbison.sql.txt @@ -367,4 +367,4 @@ FROM ML.PREDICT( } --- SQL -SELECT product_id, product_name, content FROM ML.PREDICT(MODEL TextBison, (SELECT product.id AS product_id, product.name AS product_name, CONCAT("Is this product safe for infants\?", "\n", "Product Name: ", product.name, "\n", "Category Name: ", category.name, "\n", "Product Description:", product.description) AS prompt FROM Products AS product INNER JOIN Categories AS category ON product.category_id = category.id), STRUCT(100 AS maxOutputTokens)) @{remote_udf_max_rows_per_rpc=1} +SELECT product_id, product_name, content FROM ML.PREDICT(MODEL TextBison, (SELECT product.id AS product_id, product.name AS product_name, CONCAT("Is this product safe for infants?", "\n", "Product Name: ", product.name, "\n", "Category Name: ", category.name, "\n", "Product Description:", product.description) AS prompt FROM Products AS product INNER JOIN Categories AS category ON product.category_id = category.id), STRUCT(100 AS maxOutputTokens)) @{remote_udf_max_rows_per_rpc=1} diff --git a/testdata/result/statement/select_literals_all.sql.txt b/testdata/result/statement/select_literals_all.sql.txt index 371cad18..2e488079 100644 --- a/testdata/result/statement/select_literals_all.sql.txt +++ b/testdata/result/statement/select_literals_all.sql.txt @@ -597,4 +597,4 @@ lines''', } --- SQL -SELECT "abc", "it's", "it's", 'Title: "Boy"', "abc", "it's", 'Title:"Boy"', "two\nlines", "why\?", "abc+", "abc+", "abc+", "f\\(abc,(.*),def\\)", b"abc", b"abc", b"abc", b"abc+", b"abc+", b"abc", 123, 0xABC, -123, -0xABC, 123.456e-67, .1E4, 58., 4e2, [1, 2, 3], ["x", "y", "xy"], ARRAY[1, 2, 3], ARRAY<STRING>["x", "y", "xy"], ARRAY<INT64>[], ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT (1, 2, 3)), DATE "2014-09-27", DATE("2014-09-27"), TIMESTAMP "2014-09-27 12:30:00.45-08", TIMESTAMP "2014-09-27 12:30:00.45 America/Los_Angeles", TIMESTAMP "2014-09-27", TIMESTAMP("2014-09-27"), JSON "1", JSON "[1, 2]", JSON "{}", NUMERIC "0", NUMERIC "0", TRUE, FALSE +SELECT "abc", "it's", "it's", 'Title: "Boy"', "abc", "it's", 'Title:"Boy"', "two\nlines", "why?", "abc+", "abc+", "abc+", "f\\(abc,(.*),def\\)", b"abc", b"abc", b"abc", b"abc+", b"abc+", b"abc", 123, 0xABC, -123, -0xABC, 123.456e-67, .1E4, 58., 4e2, [1, 2, 3], ["x", "y", "xy"], ARRAY[1, 2, 3], ARRAY<STRING>["x", "y", "xy"], ARRAY<INT64>[], ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT (1, 2, 3)), DATE "2014-09-27", DATE("2014-09-27"), TIMESTAMP "2014-09-27 12:30:00.45-08", TIMESTAMP "2014-09-27 12:30:00.45 America/Los_Angeles", TIMESTAMP "2014-09-27", TIMESTAMP("2014-09-27"), JSON "1", JSON "[1, 2]", JSON "{}", NUMERIC "0", NUMERIC "0", TRUE, FALSE diff --git a/testdata/result/statement/select_literals_bytes.sql.txt b/testdata/result/statement/select_literals_bytes.sql.txt index c4803601..e7d8c8d7 100644 --- a/testdata/result/statement/select_literals_bytes.sql.txt +++ b/testdata/result/statement/select_literals_bytes.sql.txt @@ -110,4 +110,4 @@ SELECT } --- SQL -SELECT b"abc", b"abc", b"abc", b"abc\n", b"abc+", b"abc+", b"abc", b"abc\\n", b"\x00", b"\?\?\?" +SELECT b"abc", b"abc", b"abc", b"abc\x0a", b"abc+", b"abc+", b"abc", b"abc\n", b"\x00", b"???" diff --git a/testdata/result/statement/select_literals_string.sql.txt b/testdata/result/statement/select_literals_string.sql.txt index 2f76d240..3ee18903 100644 --- a/testdata/result/statement/select_literals_string.sql.txt +++ b/testdata/result/statement/select_literals_string.sql.txt @@ -179,4 +179,4 @@ lines''', } --- SQL -SELECT "abc!", "a\nb!", "=!", "=!", "=!", "=!", "=!", "‼!", "🐈!", "it's", "it's", 'Title: "Boy"', "abc", "it's", 'Title:"Boy"', "two\nlines", "why\?", "abc+", "abc+", "abc+", "f\\(abc,(.*),def\\)" +SELECT "abc!", "a\nb!", "=!", "=!", "=!", "=!", "=!", "‼!", "🐈!", "it's", "it's", 'Title: "Boy"', "abc", "it's", 'Title:"Boy"', "two\nlines", "why?", "abc+", "abc+", "abc+", "f\\(abc,(.*),def\\)" From c78c0996847267225367a62e7b427e493d376598 Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Thu, 19 Dec 2024 18:33:34 +0900 Subject: [PATCH 4/8] Fix bug --- testdata/result/expr/bytes_literal_seven_bits.sql.txt | 2 +- testdata/result/query/select_literals_bytes.sql.txt | 2 +- testdata/result/statement/select_literals_bytes.sql.txt | 2 +- token/quote.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/testdata/result/expr/bytes_literal_seven_bits.sql.txt b/testdata/result/expr/bytes_literal_seven_bits.sql.txt index e8e4aaf8..24dd8a7a 100644 --- a/testdata/result/expr/bytes_literal_seven_bits.sql.txt +++ b/testdata/result/expr/bytes_literal_seven_bits.sql.txt @@ -16,4 +16,4 @@ b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x } --- SQL -b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f" +b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f" diff --git a/testdata/result/query/select_literals_bytes.sql.txt b/testdata/result/query/select_literals_bytes.sql.txt index e7d8c8d7..75cc4af4 100644 --- a/testdata/result/query/select_literals_bytes.sql.txt +++ b/testdata/result/query/select_literals_bytes.sql.txt @@ -110,4 +110,4 @@ SELECT } --- SQL -SELECT b"abc", b"abc", b"abc", b"abc\x0a", b"abc+", b"abc+", b"abc", b"abc\n", b"\x00", b"???" +SELECT b"abc", b"abc", b"abc", b"abc\x0a", b"abc+", b"abc+", b"abc", b"abc\\n", b"\x00", b"???" diff --git a/testdata/result/statement/select_literals_bytes.sql.txt b/testdata/result/statement/select_literals_bytes.sql.txt index e7d8c8d7..75cc4af4 100644 --- a/testdata/result/statement/select_literals_bytes.sql.txt +++ b/testdata/result/statement/select_literals_bytes.sql.txt @@ -110,4 +110,4 @@ SELECT } --- SQL -SELECT b"abc", b"abc", b"abc", b"abc\x0a", b"abc+", b"abc+", b"abc", b"abc\n", b"\x00", b"???" +SELECT b"abc", b"abc", b"abc", b"abc\x0a", b"abc+", b"abc+", b"abc", b"abc\\n", b"\x00", b"???" diff --git a/token/quote.go b/token/quote.go index 642b7700..fef88549 100644 --- a/token/quote.go +++ b/token/quote.go @@ -108,7 +108,7 @@ func quoteSingleEscape(r, quote rune, isString bool) string { return `\r` case isString && r == '\t': return `\t` - case isString && r == '\\': + case r == '\\': return `\\` } return "" From 6dc994c780d133dbab12ba2c2a7a514afd6b5eae Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Thu, 19 Dec 2024 18:35:55 +0900 Subject: [PATCH 5/8] Add comments --- token/quote.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/token/quote.go b/token/quote.go index fef88549..5e946cae 100644 --- a/token/quote.go +++ b/token/quote.go @@ -35,7 +35,7 @@ func suitableQuote(b []byte) rune { return '"' } -// QuoteSQLString returns quoted string with SQL bytes escaping. +// QuoteSQLBytes returns quoted string with SQL bytes escaping. func QuoteSQLBytes(bs []byte) string { quote := suitableQuote(bs) @@ -43,7 +43,7 @@ func QuoteSQLBytes(bs []byte) string { buf.WriteString("b") buf.WriteRune(quote) for _, b := range bs { - q := quoteSingleEscape(rune(b), quote, false) + q := quoteSingleEscape(rune(b), quote, /* isString */ false) if q != "" { buf.WriteString(q) continue From 6b776492b38e7c13c8702c2d8b5385c1a5275900 Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Thu, 19 Dec 2024 18:37:08 +0900 Subject: [PATCH 6/8] Fix argument order --- token/quote.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/token/quote.go b/token/quote.go index 5e946cae..8b1a0462 100644 --- a/token/quote.go +++ b/token/quote.go @@ -14,7 +14,7 @@ func QuoteSQLString(s string) string { var buf bytes.Buffer buf.WriteRune(quote) - quoteSQLStringContent(quote, s, &buf) + quoteSQLStringContent(s, quote, &buf) buf.WriteRune(quote) return buf.String() } @@ -68,12 +68,12 @@ func QuoteSQLIdent(s string) string { var buf bytes.Buffer buf.WriteByte('`') - quoteSQLStringContent('`', s, &buf) + quoteSQLStringContent(s, '`', &buf) buf.WriteByte('`') return buf.String() } -func quoteSQLStringContent(quote rune, s string, buf *bytes.Buffer) { +func quoteSQLStringContent(s string, quote rune, buf *bytes.Buffer) { for _, r := range s { q := quoteSingleEscape(r, quote, /* isString */ true) if q != "" { From 5f338e68f906802a200b2c34fbc071f5dd6bf0a4 Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Thu, 19 Dec 2024 18:45:00 +0900 Subject: [PATCH 7/8] Fix tests --- char/is_test.go | 8 ++++++-- token/quote_test.go | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/char/is_test.go b/char/is_test.go index c3738e01..73ddc70f 100644 --- a/char/is_test.go +++ b/char/is_test.go @@ -5,8 +5,12 @@ import ( ) func TestIsPrint(t *testing.T) { - if IsPrint(' ') { - t.Errorf("IsPrint(' ') != false") + if IsPrint('\x19') { + t.Errorf(`IsPrint('\x19') != false`) + } + + if IsPrint('\x80') { + t.Errorf(`IsPrint('\x80') != false`) } if !IsPrint('a') { diff --git a/token/quote_test.go b/token/quote_test.go index 00bea4fd..adcad8c5 100644 --- a/token/quote_test.go +++ b/token/quote_test.go @@ -10,10 +10,10 @@ var quoteTestCases = []struct { }{ {"foo", `"foo"`, `b"foo"`, "foo"}, {"if", `"if"`, `b"if"`, "`if`"}, - {"\u0000", `"\u0000"`, `b"\x00"`, "`\\u0000`"}, + {"\u0000", `"\x00"`, `b"\x00"`, "`\\x00`"}, {"\U0010FFFF", `"\U0010ffff"`, `b"\xf4\x8f\xbf\xbf"`, "`\\U0010ffff`"}, {"a\u2060b", `"a\u2060b"`, `b"a\xe2\x81\xa0b"`, "`a\\u2060b`"}, - {"\a\b\f\n\r\t\v\"'?\\", `"\a\b\f\n\r\t\v\"'\?\\"`, `b"\a\b\f\n\r\t\v\"'\?\\"`, "`\\a\\b\\f\\n\\r\\t\\v\"'\\?\\\\`"}, + {"\a\b\f\n\r\t\v\"'?\\", `"\x07\x08\x0c\n\r\t\x0b\"'?\\"`, `b"\x07\x08\x0c\x0a\x0d\x09\x0b\"'?\\"`, "`\\x07\\x08\\x0c\\n\\r\\t\\x0b\"'?\\\\`"}, {"`", "\"`\"", "b\"`\"", "`\\``"}, } From 395981c61dfe6cdcd509fbc62019af90bcf884f7 Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Thu, 19 Dec 2024 18:50:58 +0900 Subject: [PATCH 8/8] Remove empty branch --- token/quote.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/token/quote.go b/token/quote.go index 8b1a0462..78187b2f 100644 --- a/token/quote.go +++ b/token/quote.go @@ -96,9 +96,6 @@ func quoteSQLStringContent(s string, quote rune, buf *bytes.Buffer) { } func quoteSingleEscape(r, quote rune, isString bool) string { - if quote == r { - } - switch { case r == quote: return `\` + string(r)