XiaoFeiASK commented on code in PR #1146:
URL:
https://github.com/apache/incubator-seata-go/pull/1146#discussion_r3911138758
##########
pkg/datasource/sql/util/placeholders.go:
##########
@@ -108,3 +118,178 @@ func CompactPostgreSQLPlaceholders(query string, args
[]driver.NamedValue) (stri
return builder.String(), compactedArgs, nil
}
+
+// StripPostgreSQLStringCharset removes MySQL charset introducers emitted by
the
+// parser for string literals. PostgreSQL does not accept _UTF8MB4'...', and
the
+// following placeholder compaction must still see the literal quotes.
+func StripPostgreSQLStringCharset(query string) string {
+ const utf8mb4 = "_UTF8MB4"
+ found := false
+ for i := 0; i+len(utf8mb4) < len(query); i++ {
+ if hasPostgreSQLUTF8MB4StringIntroducer(query, i) {
+ found = true
+ break
+ }
+ }
+ if !found {
+ return query
+ }
+
+ var builder strings.Builder
+ builder.Grow(len(query))
+
+ for i := 0; i < len(query); {
+ if next, ok := copyPostgreSQLNonCode(query, i, &builder); ok {
+ i = next
+ continue
+ }
+
+ if hasPostgreSQLUTF8MB4StringIntroducer(query, i) {
+ i += len(utf8mb4)
+ continue
+ }
+
+ builder.WriteByte(query[i])
+ i++
+ }
+
+ return builder.String()
+}
+
+func hasPostgreSQLUTF8MB4StringIntroducer(query string, start int) bool {
+ const utf8mb4 = "_UTF8MB4"
+ end := start + len(utf8mb4)
+ return end < len(query) &&
+ query[end] == '\'' &&
+ (start == 0 || !isPostgreSQLIdentifierPart(query[start-1])) &&
+ strings.EqualFold(query[start:end], utf8mb4)
+}
+
+// copyPostgreSQLNonCode copies a quoted string, quoted identifier, comment,
+// or dollar-quoted string starting at start. Placeholders inside these regions
+// are SQL text and must not be rewritten.
+func copyPostgreSQLNonCode(query string, start int, builder *strings.Builder)
(int, bool) {
+ if start >= len(query) {
+ return start, false
+ }
+
+ var end int
+ switch query[start] {
+ case '\'':
+ end = scanPostgreSQLQuoted(query, start, '\'')
+ case '"':
+ end = scanPostgreSQLQuoted(query, start, '"')
+ case '-':
+ if start+1 >= len(query) || query[start+1] != '-' {
+ return start, false
+ }
+ end = start + 2
+ for end < len(query) && query[end] != '\n' && query[end] !=
'\r' {
+ end++
+ }
+ case '/':
+ if start+1 >= len(query) || query[start+1] != '*' {
+ return start, false
+ }
+ end = scanPostgreSQLBlockComment(query, start)
+ case '$':
+ delimiter, ok := postgreSQLDollarQuoteDelimiter(query, start)
Review Comment:
PostgreSQL 未加引号的标识符允许包含 $,例如 user$tag$。当前未检查 start 前一个字符是否为标识符字符,会把其中的 $tag$
误判为 dollar-quote;若找不到闭合 delimiter,将吞掉后续 SQL,导致后续 ?/$n 占位符无法改写。请增加 token
boundary 判断,并补充该场景测试。
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]