(sql string)
| 112 | } |
| 113 | |
| 114 | func splitStatement(sql string) ([]string, error) { |
| 115 | var stmts []string |
| 116 | const singleQuote = '\'' |
| 117 | const doubleQuote = '"' |
| 118 | const backtick = '`' |
| 119 | const delimiter = ';' |
| 120 | isInQuoted := false |
| 121 | var startQuote rune |
| 122 | lastCharWasEscapeChar := false |
| 123 | isTripleQuoted := false |
| 124 | res := strings.Builder{} |
| 125 | res.Grow(len(sql)) |
| 126 | index := 0 |
| 127 | runes := []rune(sql) |
| 128 | for index < len(runes) { |
| 129 | c := runes[index] |
| 130 | if isInQuoted { |
| 131 | if (c == '\n' || c == '\r') && !isTripleQuoted { |
| 132 | return nil, spanner.ToSpannerError(connect.NewError(connect.CodeInvalidArgument, errors.Errorf("statement contains an unclosed literal: %s", sql))) |
| 133 | } else if c == startQuote { |
| 134 | if lastCharWasEscapeChar { |
| 135 | lastCharWasEscapeChar = false |
| 136 | } else if isTripleQuoted { |
| 137 | if len(runes) > index+2 && runes[index+1] == startQuote && runes[index+2] == startQuote { |
| 138 | isInQuoted = false |
| 139 | startQuote = 0 |
| 140 | isTripleQuoted = false |
| 141 | _, _ = res.WriteRune(c) |
| 142 | _, _ = res.WriteRune(c) |
| 143 | index += 2 |
| 144 | } |
| 145 | } else { |
| 146 | isInQuoted = false |
| 147 | startQuote = 0 |
| 148 | } |
| 149 | } else if c == '\\' { |
| 150 | lastCharWasEscapeChar = true |
| 151 | } else { |
| 152 | lastCharWasEscapeChar = false |
| 153 | } |
| 154 | _, _ = res.WriteRune(c) |
| 155 | } else { |
| 156 | // We are not in a quoted string. |
| 157 | switch c { |
| 158 | case singleQuote, doubleQuote, backtick: |
| 159 | isInQuoted = true |
| 160 | startQuote = c |
| 161 | // Check whether it is a triple-quote. |
| 162 | if len(runes) > index+2 && runes[index+1] == startQuote && runes[index+2] == startQuote { |
| 163 | isTripleQuoted = true |
| 164 | _, _ = res.WriteRune(c) |
| 165 | _, _ = res.WriteRune(c) |
| 166 | index += 2 |
| 167 | } |
| 168 | _, _ = res.WriteRune(c) |
| 169 | case delimiter: |
| 170 | stmt := strings.Trim(res.String(), " \n\t") |
| 171 | if stmt != "" { |
no test coverage detected