mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-05-30 15:19:59 +08:00
🐛 fix(batch-truncate/query): 修复批量清空表安全隐患并优化多语句执行错误反馈
- 安全加固:TruncateTables 增加审计日志(Warnf 级别)和参数校验(上限 200 张) - 容错增强:批量清空部分失败时返回已执行 SQL 列表并提示已清空表不可恢复 - 错误优化:DBQueryMulti 逐条执行失败时附带语句序号和已成功条数 - 性能优化:splitSQLStatements 从 string 拼接改为 strings.Builder,消除 O(n²) 分配 - 转义修复:splitSQLStatements 支持 SQL 标准转义单引号 '' 防止误拆分 - 前端修复:handleBatchClear 统一取消判断字符串为 '已取消' 并移除冗余变量声明 - refs #244
This commit is contained in:
@@ -5,11 +5,12 @@ import "strings"
|
||||
// splitSQLStatements 按分号拆分 SQL 文本为独立语句。
|
||||
// 正确处理单引号/双引号/反引号字符串、行注释(-- / #)、块注释(/* */)和
|
||||
// PostgreSQL/Kingbase 的 $$...$$ dollar-quoting,避免在这些上下文中错误拆分。
|
||||
// 同时支持 SQL 标准的转义单引号(两个连续单引号 '' 表示字面量引号)。
|
||||
func splitSQLStatements(sql string) []string {
|
||||
text := strings.ReplaceAll(sql, "\r\n", "\n")
|
||||
var statements []string
|
||||
|
||||
cur := ""
|
||||
var cur strings.Builder
|
||||
inSingle := false
|
||||
inDouble := false
|
||||
inBacktick := false
|
||||
@@ -19,11 +20,11 @@ func splitSQLStatements(sql string) []string {
|
||||
var dollarTag string // postgres/kingbase: $$...$$ or $tag$...$tag$
|
||||
|
||||
push := func() {
|
||||
s := strings.TrimSpace(cur)
|
||||
s := strings.TrimSpace(cur.String())
|
||||
if s != "" {
|
||||
statements = append(statements, s)
|
||||
}
|
||||
cur = ""
|
||||
cur.Reset()
|
||||
}
|
||||
|
||||
for i := 0; i < len(text); i++ {
|
||||
@@ -38,15 +39,15 @@ func splitSQLStatements(sql string) []string {
|
||||
if ch == '\n' {
|
||||
inLineComment = false
|
||||
}
|
||||
cur += string(ch)
|
||||
cur.WriteByte(ch)
|
||||
continue
|
||||
}
|
||||
|
||||
// 块注释
|
||||
if inBlockComment {
|
||||
cur += string(ch)
|
||||
cur.WriteByte(ch)
|
||||
if ch == '*' && next == '/' {
|
||||
cur += "/"
|
||||
cur.WriteByte('/')
|
||||
i++
|
||||
inBlockComment = false
|
||||
}
|
||||
@@ -56,66 +57,73 @@ func splitSQLStatements(sql string) []string {
|
||||
// Dollar-quoting
|
||||
if dollarTag != "" {
|
||||
if strings.HasPrefix(text[i:], dollarTag) {
|
||||
cur += dollarTag
|
||||
cur.WriteString(dollarTag)
|
||||
i += len(dollarTag) - 1
|
||||
dollarTag = ""
|
||||
} else {
|
||||
cur += string(ch)
|
||||
cur.WriteByte(ch)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// 转义字符
|
||||
// 转义字符(反斜杠转义,MySQL 风格)
|
||||
if escaped {
|
||||
escaped = false
|
||||
cur += string(ch)
|
||||
cur.WriteByte(ch)
|
||||
continue
|
||||
}
|
||||
if (inSingle || inDouble) && ch == '\\' {
|
||||
escaped = true
|
||||
cur += string(ch)
|
||||
cur.WriteByte(ch)
|
||||
continue
|
||||
}
|
||||
|
||||
// 字符串开闭
|
||||
if !inDouble && !inBacktick && ch == '\'' {
|
||||
if inSingle && next == '\'' {
|
||||
// SQL 标准转义:两个连续单引号 '' 表示字面量引号,保持在引号内
|
||||
cur.WriteByte(ch)
|
||||
cur.WriteByte(next)
|
||||
i++
|
||||
continue
|
||||
}
|
||||
inSingle = !inSingle
|
||||
cur += string(ch)
|
||||
cur.WriteByte(ch)
|
||||
continue
|
||||
}
|
||||
if !inSingle && !inBacktick && ch == '"' {
|
||||
inDouble = !inDouble
|
||||
cur += string(ch)
|
||||
cur.WriteByte(ch)
|
||||
continue
|
||||
}
|
||||
if !inSingle && !inDouble && ch == '`' {
|
||||
inBacktick = !inBacktick
|
||||
cur += string(ch)
|
||||
cur.WriteByte(ch)
|
||||
continue
|
||||
}
|
||||
|
||||
// 在引号/反引号内部不做任何判断
|
||||
if inSingle || inDouble || inBacktick {
|
||||
cur += string(ch)
|
||||
cur.WriteByte(ch)
|
||||
continue
|
||||
}
|
||||
|
||||
// 行注释开始
|
||||
if ch == '-' && next == '-' {
|
||||
inLineComment = true
|
||||
cur += string(ch)
|
||||
cur.WriteByte(ch)
|
||||
continue
|
||||
}
|
||||
if ch == '#' {
|
||||
inLineComment = true
|
||||
cur += string(ch)
|
||||
cur.WriteByte(ch)
|
||||
continue
|
||||
}
|
||||
|
||||
// 块注释开始
|
||||
if ch == '/' && next == '*' {
|
||||
inBlockComment = true
|
||||
cur += "/*"
|
||||
cur.WriteString("/*")
|
||||
i++
|
||||
continue
|
||||
}
|
||||
@@ -124,7 +132,7 @@ func splitSQLStatements(sql string) []string {
|
||||
if ch == '$' {
|
||||
if tag := parseSQLDollarTag(text[i:]); tag != "" {
|
||||
dollarTag = tag
|
||||
cur += tag
|
||||
cur.WriteString(tag)
|
||||
i += len(tag) - 1
|
||||
continue
|
||||
}
|
||||
@@ -142,7 +150,7 @@ func splitSQLStatements(sql string) []string {
|
||||
continue
|
||||
}
|
||||
|
||||
cur += string(ch)
|
||||
cur.WriteByte(ch)
|
||||
}
|
||||
|
||||
push()
|
||||
|
||||
Reference in New Issue
Block a user