RemoveCommentsAndTrim removes any comments in the query string and trims any spaces at the beginning and end of the query. This makes checking what type of query a string is a lot easier, as only the first word(s) need to be checked after this has been removed. source: https://github.com/googleapis/
(sql string)
| 18 | // checked after this has been removed. |
| 19 | // source: https://github.com/googleapis/go-sql-spanner/blob/e33bd23e1ebfa2fe1b947bced9eacdc6454595eb/statement_parser.go |
| 20 | func removeCommentsAndTrim(sql string) (string, error) { |
| 21 | const singleQuote = '\'' |
| 22 | const doubleQuote = '"' |
| 23 | const backtick = '`' |
| 24 | const hyphen = '-' |
| 25 | const dash = '#' |
| 26 | const slash = '/' |
| 27 | const asterisk = '*' |
| 28 | isInQuoted := false |
| 29 | isInSingleLineComment := false |
| 30 | isInMultiLineComment := false |
| 31 | var startQuote rune |
| 32 | lastCharWasEscapeChar := false |
| 33 | isTripleQuoted := false |
| 34 | res := strings.Builder{} |
| 35 | res.Grow(len(sql)) |
| 36 | index := 0 |
| 37 | runes := []rune(sql) |
| 38 | for index < len(runes) { |
| 39 | c := runes[index] |
| 40 | if isInQuoted { |
| 41 | if (c == '\n' || c == '\r') && !isTripleQuoted { |
| 42 | return "", spanner.ToSpannerError(connect.NewError(connect.CodeInvalidArgument, errors.Errorf("statement contains an unclosed literal: %s", sql))) |
| 43 | } else if c == startQuote { |
| 44 | if lastCharWasEscapeChar { |
| 45 | lastCharWasEscapeChar = false |
| 46 | } else if isTripleQuoted { |
| 47 | if len(runes) > index+2 && runes[index+1] == startQuote && runes[index+2] == startQuote { |
| 48 | isInQuoted = false |
| 49 | startQuote = 0 |
| 50 | isTripleQuoted = false |
| 51 | _, _ = res.WriteRune(c) |
| 52 | _, _ = res.WriteRune(c) |
| 53 | index += 2 |
| 54 | } |
| 55 | } else { |
| 56 | isInQuoted = false |
| 57 | startQuote = 0 |
| 58 | } |
| 59 | } else if c == '\\' { |
| 60 | lastCharWasEscapeChar = true |
| 61 | } else { |
| 62 | lastCharWasEscapeChar = false |
| 63 | } |
| 64 | _, _ = res.WriteRune(c) |
| 65 | } else { |
| 66 | // We are not in a quoted string. |
| 67 | if isInSingleLineComment { |
| 68 | if c == '\n' { |
| 69 | isInSingleLineComment = false |
| 70 | // Include the line feed in the result. |
| 71 | _, _ = res.WriteRune(c) |
| 72 | } |
| 73 | } else if isInMultiLineComment { |
| 74 | if len(runes) > index+1 && c == asterisk && runes[index+1] == slash { |
| 75 | isInMultiLineComment = false |
| 76 | index++ |
| 77 | } |