🐛 fix(sql-parser): 修复尾随注释导致事务与只读判定异常

- 过滤分号后的纯注释语句并保留数据库可执行版本注释
- 前后端按数据库方言统一处理双横线、井号与块注释
- 修复事务选择、只读保护、SQL 审计及 AI 风险分析误判
- 补充流式 SQL、事务执行与方言解析回归测试
This commit is contained in:
Syngnat
2026-07-13 12:52:56 +08:00
parent 00473e7ac0
commit 1ae2b74279
21 changed files with 559 additions and 72 deletions

View File

@@ -32,6 +32,65 @@ func TestSplitSQLStatements_LineComment(t *testing.T) {
}
}
func TestSplitSQLStatements_DropsCommentOnlyTail(t *testing.T) {
t.Parallel()
statement := "DELETE FROM users WHERE id = 1"
tests := []struct {
name string
query string
}{
{name: "bare line comment marker", query: statement + ";--"},
{name: "line comment", query: statement + "; -- keep this operation pending"},
{name: "hash comment", query: statement + ";\n# keep this operation pending"},
{name: "block comment", query: statement + ";\n/* keep this operation pending */"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := splitSQLStatementsForDialect("mysql", tt.query)
want := []string{statement}
if !reflect.DeepEqual(got, want) {
t.Fatalf("splitSQLStatementsForDialect(mysql, %q) = %#v, want %#v", tt.query, got, want)
}
})
}
}
func TestSplitSQLStatements_PreservesExecutableMySQLComment(t *testing.T) {
t.Parallel()
query := "/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;"
got := splitSQLStatementsForDialect("mysql", query)
want := []string{"/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */"}
if !reflect.DeepEqual(got, want) {
t.Fatalf("splitSQLStatementsForDialect(mysql, %q) = %#v, want %#v", query, got, want)
}
}
func TestSplitSQLStatements_UsesDialectSpecificExecutableCommentRules(t *testing.T) {
t.Parallel()
mysqlComment := "/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;"
mariaDBComment := "/*M!100100 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;"
if got := splitSQLStatementsForDialect("postgres", mysqlComment); len(got) != 0 {
t.Fatalf("expected PostgreSQL to drop MySQL-only executable comment, got %#v", got)
}
if got := splitSQLStatementsForDialect("mysql", mariaDBComment); len(got) != 0 {
t.Fatalf("expected MySQL to drop MariaDB-only executable comment, got %#v", got)
}
want := []string{"/*M!100100 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */"}
if got := splitSQLStatementsForDialect("mariadb", mariaDBComment); !reflect.DeepEqual(got, want) {
t.Fatalf("expected MariaDB statements %#v, got %#v", want, got)
}
statement := "DELETE FROM users WHERE id = 1"
want = []string{statement, "#comment"}
if got := splitSQLStatementsForDialect("postgres", statement+"; #comment"); !reflect.DeepEqual(got, want) {
t.Fatalf("expected PostgreSQL statements %#v, got %#v", want, got)
}
}
func TestSplitSQLStatements_BlockComment(t *testing.T) {
input := "SELECT /* ; */ 1; SELECT 2"
got := splitSQLStatements(input)