mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-07-05 18:11:32 +08:00
🐛 fix(sql-editor): 修复存储过程定义执行截断
This commit is contained in:
@@ -6,7 +6,7 @@ import "strings"
|
||||
// 正确处理单引号/双引号/反引号字符串、行注释(-- / #)、块注释(/* */)、
|
||||
// PostgreSQL/Kingbase 的 $$...$$ dollar-quoting,以及 Oracle PL/SQL 匿名块,
|
||||
// 避免在这些上下文中错误拆分。
|
||||
// 同时支持 SQL 标准的转义单引号(两个连续单引号 '' 表示字面量引号)。
|
||||
// 同时支持 SQL 标准的转义单引号(两个连续单引号 ” 表示字面量引号)。
|
||||
func splitSQLStatements(sql string) []string {
|
||||
text := strings.ReplaceAll(sql, "\r\n", "\n")
|
||||
var statements []string
|
||||
@@ -129,6 +129,10 @@ func splitSQLStatements(sql string) []string {
|
||||
plsqlDepth++
|
||||
plsqlDeclareBeginSkips++
|
||||
justClosedPLSQLBlock = false
|
||||
} else if plsqlDepth == 0 && shouldEnterPLSQLCreateRoutineBlock(text, cur.String(), token, tokenEnd) {
|
||||
plsqlDepth++
|
||||
plsqlDeclareBeginSkips++
|
||||
justClosedPLSQLBlock = false
|
||||
} else if token == "end" && plsqlDepth > 0 && !isPLSQLControlEnd(text, tokenEnd) {
|
||||
plsqlDepth--
|
||||
if plsqlDeclareBeginSkips > plsqlDepth {
|
||||
@@ -297,10 +301,10 @@ func isPLSQLBlockStatement(stmt string) bool {
|
||||
if token == "declare" {
|
||||
return shouldEnterPLSQLDeclareBlock(text, len("declare"))
|
||||
}
|
||||
if token != "begin" {
|
||||
return false
|
||||
if token == "begin" {
|
||||
return shouldEnterPLSQLBlock(text, len("begin"))
|
||||
}
|
||||
return shouldEnterPLSQLBlock(text, len("begin"))
|
||||
return isCreateRoutineHeaderPrefix(text)
|
||||
}
|
||||
|
||||
func shouldEnterPLSQLDeclareBlock(text string, tokenEnd int) bool {
|
||||
@@ -316,6 +320,54 @@ func isPLSQLControlEnd(text string, tokenEnd int) bool {
|
||||
}
|
||||
}
|
||||
|
||||
func isCreateRoutineHeaderPrefix(text string) bool {
|
||||
currentToken, currentEnd := nextSQLSignificantTokenSpan(text, 0)
|
||||
if currentToken != "create" {
|
||||
return false
|
||||
}
|
||||
|
||||
currentToken, currentEnd = nextSQLSignificantTokenSpan(text, currentEnd)
|
||||
if currentToken == "or" {
|
||||
currentToken, currentEnd = nextSQLSignificantTokenSpan(text, currentEnd)
|
||||
if currentToken != "replace" {
|
||||
return false
|
||||
}
|
||||
currentToken, currentEnd = nextSQLSignificantTokenSpan(text, currentEnd)
|
||||
}
|
||||
|
||||
for currentToken == "editionable" || currentToken == "noneditionable" {
|
||||
currentToken, currentEnd = nextSQLSignificantTokenSpan(text, currentEnd)
|
||||
}
|
||||
|
||||
return currentToken == "procedure" || currentToken == "function"
|
||||
}
|
||||
|
||||
func nextSQLSignificantTokenSpan(text string, pos int) (string, int) {
|
||||
i := skipSQLWhitespaceAndComments(text, pos)
|
||||
if i >= len(text) || !isSQLIdentifierStart(text[i]) {
|
||||
return "", i
|
||||
}
|
||||
end := i + 1
|
||||
for end < len(text) && isSQLIdentifierPart(text[end]) {
|
||||
end++
|
||||
}
|
||||
return strings.ToLower(text[i:end]), end
|
||||
}
|
||||
|
||||
func shouldEnterPLSQLCreateRoutineBlock(text string, currentStatementPrefix string, token string, tokenEnd int) bool {
|
||||
if token != "is" && token != "as" {
|
||||
return false
|
||||
}
|
||||
nextChar := nextSQLSignificantByte(text, tokenEnd)
|
||||
if nextChar == 0 {
|
||||
return false
|
||||
}
|
||||
if token == "as" && (nextChar == '$' || nextChar == '\'' || nextChar == '"') {
|
||||
return false
|
||||
}
|
||||
return isCreateRoutineHeaderPrefix(currentStatementPrefix)
|
||||
}
|
||||
|
||||
// parseSQLDollarTag 解析 PostgreSQL/Kingbase 的 dollar-quoting 标签。
|
||||
func parseSQLDollarTag(s string) string {
|
||||
if len(s) < 2 || s[0] != '$' {
|
||||
|
||||
Reference in New Issue
Block a user