44f892fddc
This should solve #1954 and adds some tests for it. I will note I'm not 100% clear on whether there are other edge cases that should be covered here. From what I understand the only standard SQL way to escape single quotes is to double them, which shouldn't cause any problems with this, but if some SQL flavors allow other kinds of escaping, for instance, that would probably need to be covered too for ideal results. Co-authored-by: Hlín Önnudóttir <hlin@nanitor.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Reviewed-on: xorm/xorm#1955 Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: antialiasis <antialiasis@noreply.gitea.io> Co-committed-by: antialiasis <antialiasis@noreply.gitea.io>
77 lines
1.7 KiB
Go
77 lines
1.7 KiB
Go
// Copyright 2019 The Xorm Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package dialects
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// Filter is an interface to filter SQL
|
|
type Filter interface {
|
|
Do(sql string) string
|
|
}
|
|
|
|
// SeqFilter filter SQL replace ?, ? ... to $1, $2 ...
|
|
type SeqFilter struct {
|
|
Prefix string
|
|
Start int
|
|
}
|
|
|
|
func convertQuestionMark(sql, prefix string, start int) string {
|
|
var buf strings.Builder
|
|
var beginSingleQuote bool
|
|
var isLineComment bool
|
|
var isComment bool
|
|
var isMaybeLineComment bool
|
|
var isMaybeComment bool
|
|
var isMaybeCommentEnd bool
|
|
var index = start
|
|
for _, c := range sql {
|
|
if !beginSingleQuote && !isLineComment && !isComment && c == '?' {
|
|
buf.WriteString(fmt.Sprintf("%s%v", prefix, index))
|
|
index++
|
|
} else {
|
|
if isMaybeLineComment {
|
|
if c == '-' {
|
|
isLineComment = true
|
|
}
|
|
isMaybeLineComment = false
|
|
} else if isMaybeComment {
|
|
if c == '*' {
|
|
isComment = true
|
|
}
|
|
isMaybeComment = false
|
|
} else if isMaybeCommentEnd {
|
|
if c == '/' {
|
|
isComment = false
|
|
}
|
|
isMaybeCommentEnd = false
|
|
} else if isLineComment {
|
|
if c == '\n' {
|
|
isLineComment = false
|
|
}
|
|
} else if isComment {
|
|
if c == '*' {
|
|
isMaybeCommentEnd = true
|
|
}
|
|
} else if !beginSingleQuote && c == '-' {
|
|
isMaybeLineComment = true
|
|
} else if !beginSingleQuote && c == '/' {
|
|
isMaybeComment = true
|
|
} else if c == '\'' {
|
|
beginSingleQuote = !beginSingleQuote
|
|
}
|
|
buf.WriteRune(c)
|
|
}
|
|
}
|
|
return buf.String()
|
|
}
|
|
|
|
// Do implements Filter
|
|
func (s *SeqFilter) Do(sql string) string {
|
|
return convertQuestionMark(sql, s.Prefix, s.Start)
|
|
}
|