From 9bfa1324e55bb7d80dff69114e7d77be403671ed Mon Sep 17 00:00:00 2001 From: TastyHeadphones <76083688+TastyHeadphones@users.noreply.github.com> Date: Fri, 16 Oct 2026 10:39:13 +0900 Subject: [PATCH] test(feed): regression for backtick identifiers containing quotes Adds a MySQL Syntax.Backticks case for xo/usql#587: an identifier such as `we'ird` must not open a phantom string, or the following literal's \\ escapes collapse before the server sees them. The transit grammar already honors Backticks; this locks the behavior in. Disclosure: drafted with Grok assistance; I reviewed and tested the change. --- feed/backtick_quote_test.go | 46 +++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 feed/backtick_quote_test.go diff --git a/feed/backtick_quote_test.go b/feed/backtick_quote_test.go new file mode 100644 index 0000000000..4076876b26 --- /dev/null +++ b/feed/backtick_quote_test.go @@ -0,0 +1,46 @@ +package feed + +import ( + "strings" + "testing" + + "github.com/xo/dbmeta" +) + +// TestBacktickIdentifierWithQuoteKeepsStringEscapes is the regression for +// xo/usql#587. Before the transit grammar honored Syntax.Backticks, a MySQL +// identifier such as `we'ird` opened a phantom string and the following +// literal's \\ escapes were collapsed before the server saw them. +func TestBacktickIdentifierWithQuoteKeepsStringEscapes(t *testing.T) { + t.Parallel() + const q = "select 1 as `we'ird`, hex('a\\\\b');" + mysql := dbmeta.Syntax{BlockComments: true, HashComments: true, Backticks: true} + p, err := NewParser(Language(mysql, false)) + if err != nil { + t.Fatal(err) + } + items, err := p.Parse(q) + if err != nil { + t.Fatal(err) + } + if len(items) != 1 { + t.Fatalf("items=%d summary=%s", len(items), summary(items)) + } + got := items[0].Expand(func(string) (string, bool) { return "", false }) + if !strings.Contains(got, `a\\b`) { + t.Fatalf("expected a\\\\b preserved in %q", got) + } + var sawIdent bool + for _, part := range items[0].Parts { + if part.Kind == QuotedIdentifier { + sawIdent = true + text := items[0].Text[part.Start:part.End] + if !strings.Contains(text, "'") { + t.Fatalf("quoted ident missing embedded quote: %q", text) + } + } + } + if !sawIdent { + t.Fatalf("expected QuotedIdentifier part, parts=%+v", items[0].Parts) + } +}