bug fix:修复可能的panic状态;增加更多功能
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
package sqlplaceholder
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ConvertQuestionToDollarPlaceholders converts '?' to '$1,$2,...' in SQL text.
|
||||
// It skips quoted strings, quoted identifiers and comments.
|
||||
func ConvertQuestionToDollarPlaceholders(query string) string {
|
||||
if query == "" || !strings.Contains(query, "?") {
|
||||
return query
|
||||
}
|
||||
|
||||
const (
|
||||
stateNormal = iota
|
||||
stateSingleQuote
|
||||
stateDoubleQuote
|
||||
stateBacktick
|
||||
stateLineComment
|
||||
stateBlockComment
|
||||
)
|
||||
|
||||
var b strings.Builder
|
||||
b.Grow(len(query) + 8)
|
||||
|
||||
state := stateNormal
|
||||
index := 1
|
||||
|
||||
for i := 0; i < len(query); i++ {
|
||||
c := query[i]
|
||||
|
||||
switch state {
|
||||
case stateNormal:
|
||||
if c == '\'' {
|
||||
state = stateSingleQuote
|
||||
b.WriteByte(c)
|
||||
continue
|
||||
}
|
||||
if c == '"' {
|
||||
state = stateDoubleQuote
|
||||
b.WriteByte(c)
|
||||
continue
|
||||
}
|
||||
if c == '`' {
|
||||
state = stateBacktick
|
||||
b.WriteByte(c)
|
||||
continue
|
||||
}
|
||||
if c == '-' && i+1 < len(query) && query[i+1] == '-' {
|
||||
state = stateLineComment
|
||||
b.WriteByte(c)
|
||||
i++
|
||||
b.WriteByte(query[i])
|
||||
continue
|
||||
}
|
||||
if c == '/' && i+1 < len(query) && query[i+1] == '*' {
|
||||
state = stateBlockComment
|
||||
b.WriteByte(c)
|
||||
i++
|
||||
b.WriteByte(query[i])
|
||||
continue
|
||||
}
|
||||
if c == '?' {
|
||||
b.WriteByte('$')
|
||||
b.WriteString(strconv.Itoa(index))
|
||||
index++
|
||||
continue
|
||||
}
|
||||
b.WriteByte(c)
|
||||
|
||||
case stateSingleQuote:
|
||||
b.WriteByte(c)
|
||||
if c == '\'' {
|
||||
// SQL escaped single quote: ''
|
||||
if i+1 < len(query) && query[i+1] == '\'' {
|
||||
i++
|
||||
b.WriteByte(query[i])
|
||||
continue
|
||||
}
|
||||
state = stateNormal
|
||||
}
|
||||
|
||||
case stateDoubleQuote:
|
||||
b.WriteByte(c)
|
||||
if c == '"' {
|
||||
// escaped double quote: ""
|
||||
if i+1 < len(query) && query[i+1] == '"' {
|
||||
i++
|
||||
b.WriteByte(query[i])
|
||||
continue
|
||||
}
|
||||
state = stateNormal
|
||||
}
|
||||
|
||||
case stateBacktick:
|
||||
b.WriteByte(c)
|
||||
if c == '`' {
|
||||
state = stateNormal
|
||||
}
|
||||
|
||||
case stateLineComment:
|
||||
b.WriteByte(c)
|
||||
if c == '\n' {
|
||||
state = stateNormal
|
||||
}
|
||||
|
||||
case stateBlockComment:
|
||||
b.WriteByte(c)
|
||||
if c == '*' && i+1 < len(query) && query[i+1] == '/' {
|
||||
i++
|
||||
b.WriteByte(query[i])
|
||||
state = stateNormal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return b.String()
|
||||
}
|
||||
Reference in New Issue
Block a user