Add support for single quotes in search queries, and add a heuristic to avoid consuming unclosed quotes

This commit is contained in:
David Dworken
2023-12-19 15:01:15 -08:00
parent 60f5a222c0
commit 8082bd5a2d
2 changed files with 51 additions and 6 deletions

View File

@ -984,9 +984,10 @@ func splitEscaped(query string, separator rune, maxSplit int) []string {
var tokens []string
splits := 1
runeQuery := []rune(query)
isInQuotedString := false
isInDoubleQuotedString := false
isInSingleQuotedString := false
for i := 0; i < len(runeQuery); i++ {
if (maxSplit < 0 || splits < maxSplit) && runeQuery[i] == separator && !isInQuotedString {
if (maxSplit < 0 || splits < maxSplit) && runeQuery[i] == separator && !isInSingleQuotedString && !isInDoubleQuotedString {
tokens = append(tokens, string(token))
token = token[:0]
splits++
@ -999,8 +1000,10 @@ func splitEscaped(query string, separator rune, maxSplit int) []string {
}
i++
token = append(token, runeQuery[i])
} else if runeQuery[i] == '"' {
isInQuotedString = !isInQuotedString
} else if runeQuery[i] == '"' && !isInSingleQuotedString && !heuristicIgnoreUnclosedQuote(isInDoubleQuotedString, '"', runeQuery, i) {
isInDoubleQuotedString = !isInDoubleQuotedString
} else if runeQuery[i] == '\'' && !isInDoubleQuotedString && !heuristicIgnoreUnclosedQuote(isInSingleQuotedString, '\'', runeQuery, i) {
isInSingleQuotedString = !isInSingleQuotedString
} else {
token = append(token, runeQuery[i])
}
@ -1009,6 +1012,23 @@ func splitEscaped(query string, separator rune, maxSplit int) []string {
return tokens
}
func heuristicIgnoreUnclosedQuote(isCurrentlyInQuotedString bool, quoteType rune, query []rune, idx int) bool {
if isCurrentlyInQuotedString {
// We're already in a quoted string, so the heuristic doesn't apply
return false
}
idx++
for idx < len(query) {
if query[idx] == quoteType {
// There is a close quote, so the heuristic doesn't apply
return false
}
idx++
}
// There is no unclosed quote, so we apply the heuristic and ignore the single quote
return true
}
func containsUnescaped(query string, token string) bool {
runeQuery := []rune(query)
for i := 0; i < len(runeQuery); i++ {