🐛 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

@@ -34,7 +34,7 @@ func splitSQLStatementsForDialect(dbType, sql string) []string {
push := func() {
s := strings.TrimSpace(cur.String())
if s != "" {
if s != "" && hasExecutableSQLStatementContent(dbType, s) {
statements = append(statements, s)
}
cur.Reset()
@@ -255,9 +255,65 @@ func splitSQLStatementsForDialect(dbType, sql string) []string {
return statements
}
func hasExecutableSQLStatementContent(dbType, statement string) bool {
for i := 0; i < len(statement); {
switch statement[i] {
case ' ', '\t', '\n', '\r', '\f':
i++
continue
case '-':
if i+1 < len(statement) && statement[i+1] == '-' && isSQLDashLineCommentStart(dbType, statement, i) {
i = scanSQLLineCommentEnd(statement, i+2)
continue
}
case '#':
if supportsSQLHashLineComment(dbType) {
i = scanSQLLineCommentEnd(statement, i+1)
continue
}
case '/':
if i+1 < len(statement) && statement[i+1] == '*' {
remaining := statement[i:]
if supportsSQLExecutableBlockComment(dbType, remaining) {
return true
}
blockEnd := strings.Index(remaining[2:], "*/")
if blockEnd < 0 {
return false
}
i += blockEnd + 4
continue
}
}
return true
}
return false
}
func supportsSQLExecutableBlockComment(dbType, remaining string) bool {
isMySQLVersionComment := strings.HasPrefix(remaining, "/*!")
isMariaDBVersionComment := len(remaining) >= 4 && strings.EqualFold(remaining[:4], "/*m!")
if !isMySQLVersionComment && !isMariaDBVersionComment {
return false
}
normalized := normalizeExplainLexicalDBType(dbType)
if normalized == "" {
return true
}
if isMariaDBVersionComment {
return normalized == "mariadb"
}
switch normalized {
case "mysql", "mariadb", "oceanbase", "diros", "starrocks", "goldendb", "sphinx", "tidb":
return true
default:
return false
}
}
func isSQLDashLineCommentStart(dbType, text string, index int) bool {
switch normalizeExplainLexicalDBType(dbType) {
case "mysql", "mariadb", "oceanbase", "diros", "starrocks", "goldendb":
case "mysql", "mariadb", "oceanbase", "diros", "starrocks", "goldendb", "sphinx", "tidb":
return isMySQLDashCommentStart(text, index)
default:
return true
@@ -270,7 +326,7 @@ func supportsSQLHashLineComment(dbType string) bool {
return true
}
switch normalized {
case "mysql", "mariadb", "oceanbase", "diros", "starrocks", "goldendb", "clickhouse":
case "mysql", "mariadb", "oceanbase", "diros", "starrocks", "goldendb", "sphinx", "tidb", "clickhouse":
return true
default:
return false