Find the last sql keyword in an SQL statement Returns the value of the last keyword, and the text of the query with everything after the last keyword stripped
(sql: str)
| 305 | |
| 306 | |
| 307 | def find_prev_keyword(sql: str) -> tuple[Token | None, str]: |
| 308 | """Find the last sql keyword in an SQL statement |
| 309 | |
| 310 | Returns the value of the last keyword, and the text of the query with |
| 311 | everything after the last keyword stripped |
| 312 | """ |
| 313 | if not sql.strip(): |
| 314 | return None, "" |
| 315 | |
| 316 | parsed = sqlparse.parse(sql)[0] |
| 317 | flattened = list(parsed.flatten()) |
| 318 | |
| 319 | logical_operators = ("AND", "OR", "NOT", "BETWEEN") |
| 320 | |
| 321 | for t in reversed(flattened): |
| 322 | if t.value == "(" or (t.is_keyword and (t.value.upper() not in logical_operators)): |
| 323 | # Find the location of token t in the original parsed statement |
| 324 | # We can't use parsed.token_index(t) because t may be a child token |
| 325 | # inside a TokenList, in which case token_index thows an error |
| 326 | # Minimal example: |
| 327 | # p = sqlparse.parse('select * from foo where bar') |
| 328 | # t = list(p.flatten())[-3] # The "Where" token |
| 329 | # p.token_index(t) # Throws ValueError: not in list |
| 330 | idx = flattened.index(t) |
| 331 | |
| 332 | # Combine the string values of all tokens in the original list |
| 333 | # up to and including the target keyword token t, to produce a |
| 334 | # query string with everything after the keyword token removed |
| 335 | text = "".join(tok.value for tok in flattened[: idx + 1]) |
| 336 | return t, text |
| 337 | |
| 338 | return None, "" |
| 339 | |
| 340 | |
| 341 | def query_starts_with(query: str, prefixes: list[str]) -> bool: |