Skip to content

Commit 229e59c

Browse files
kyleconroyclaude
andcommitted
Preserve MySQL optimizer hints in stripped query text
Fixes #4353. Hint comments (/*+ ... */) on their own line were being treated as regular block comments and removed from the query string embedded in generated code. Inline hints already survived because the surrounding line did not match the block-comment pattern. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent bba5fc9 commit 229e59c

File tree

8 files changed

+169
-0
lines changed

8 files changed

+169
-0
lines changed

internal/endtoend/testdata/mysql_optimizer_hints/mysql/go/db.go

Lines changed: 31 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/endtoend/testdata/mysql_optimizer_hints/mysql/go/models.go

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/endtoend/testdata/mysql_optimizer_hints/mysql/go/query.sql.go

Lines changed: 37 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-- name: InlineHint :one
2+
SELECT /*+ MAX_EXECUTION_TIME(1000) */ bar FROM foo LIMIT 1;
3+
4+
-- name: MultilineHint :one
5+
SELECT
6+
/*+ MAX_EXECUTION_TIME(1000) */
7+
bar
8+
FROM foo
9+
LIMIT 1;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CREATE TABLE foo (bar text);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"version": "1",
3+
"packages": [
4+
{
5+
"path": "go",
6+
"engine": "mysql",
7+
"name": "querytest",
8+
"schema": "schema.sql",
9+
"queries": "query.sql"
10+
}
11+
]
12+
}

internal/source/code.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ func StripComments(sql string) (string, []string, error) {
115115
continue
116116
}
117117
if strings.HasPrefix(t, "/*") && strings.HasSuffix(t, "*/") {
118+
// Preserve MySQL optimizer hints, which share block-comment
119+
// syntax but are semantically part of the query.
120+
if strings.HasPrefix(t, "/*+") {
121+
lines = append(lines, t)
122+
continue
123+
}
118124
t = strings.TrimPrefix(t, "/*")
119125
t = strings.TrimSuffix(t, "*/")
120126
comments = append(comments, t)

internal/source/code_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package source
2+
3+
import (
4+
"strings"
5+
"testing"
6+
)
7+
8+
func TestStripComments(t *testing.T) {
9+
type test struct {
10+
name string
11+
input string
12+
wantSQL string
13+
wantComment []string
14+
}
15+
16+
tests := []test{
17+
{
18+
name: "plain block comment on its own line is stripped",
19+
input: "SELECT 1\n/* a comment */\nFROM foo",
20+
wantSQL: "SELECT 1\nFROM foo",
21+
wantComment: []string{" a comment "},
22+
},
23+
{
24+
name: "inline optimizer hint is preserved",
25+
input: "SELECT /*+ MAX_EXECUTION_TIME(1000) */ * FROM t1",
26+
wantSQL: "SELECT /*+ MAX_EXECUTION_TIME(1000) */ * FROM t1",
27+
},
28+
{
29+
name: "multi-line optimizer hint is preserved",
30+
input: "SELECT\n/*+ MAX_EXECUTION_TIME(1000) */\n*\nFROM t1",
31+
wantSQL: "SELECT\n/*+ MAX_EXECUTION_TIME(1000) */\n*\nFROM t1",
32+
},
33+
{
34+
name: "query name comment is dropped",
35+
input: "/* name: Foo :one */\nSELECT 1",
36+
wantSQL: "SELECT 1",
37+
},
38+
{
39+
name: "dash comments are collected",
40+
input: "-- helpful note\nSELECT 1",
41+
wantSQL: "SELECT 1",
42+
wantComment: []string{" helpful note"},
43+
},
44+
}
45+
46+
for _, tc := range tests {
47+
t.Run(tc.name, func(t *testing.T) {
48+
gotSQL, gotComments, err := StripComments(tc.input)
49+
if err != nil {
50+
t.Fatalf("unexpected error: %v", err)
51+
}
52+
if gotSQL != tc.wantSQL {
53+
t.Errorf("SQL mismatch\n got: %q\nwant: %q", gotSQL, tc.wantSQL)
54+
}
55+
if strings.Join(gotComments, "|") != strings.Join(tc.wantComment, "|") {
56+
t.Errorf("comments mismatch\n got: %q\nwant: %q", gotComments, tc.wantComment)
57+
}
58+
})
59+
}
60+
}

0 commit comments

Comments
 (0)