| 12 | |
| 13 | |
| 14 | class DelimiterCommand: |
| 15 | def __init__(self) -> None: |
| 16 | self._delimiter = ";" |
| 17 | |
| 18 | def _split(self, sql: str) -> list[str]: |
| 19 | """Temporary workaround until sqlparse.split() learns about custom |
| 20 | delimiters.""" |
| 21 | |
| 22 | placeholder = "\ufffc" # unicode object replacement character |
| 23 | |
| 24 | if self._delimiter == ";": |
| 25 | return sqlparse.split(sql) |
| 26 | |
| 27 | # We must find a string that original sql does not contain. |
| 28 | # Most likely, our placeholder is enough, but if not, keep looking |
| 29 | while placeholder in sql: |
| 30 | placeholder += placeholder[0] |
| 31 | sql = sql.replace(";", placeholder) |
| 32 | sql = sql.replace(self._delimiter, ";") |
| 33 | |
| 34 | split = sqlparse.split(sql) |
| 35 | |
| 36 | return [stmt.replace(";", self._delimiter).replace(placeholder, ";") for stmt in split] |
| 37 | |
| 38 | def queries_iter(self, input_str: str) -> Generator[str, None, None]: |
| 39 | """Iterate over queries in the input string.""" |
| 40 | |
| 41 | queries = self._split(input_str) |
| 42 | while queries: |
| 43 | for sql in queries: |
| 44 | delimiter = self._delimiter |
| 45 | sql = queries.pop(0) |
| 46 | if sql.endswith(delimiter): |
| 47 | trailing_delimiter = True |
| 48 | sql = sql[: -len(delimiter)] |
| 49 | else: |
| 50 | trailing_delimiter = False |
| 51 | |
| 52 | yield sql |
| 53 | |
| 54 | # if the delimiter was changed by the last command, |
| 55 | # re-split everything, and if we previously stripped |
| 56 | # the delimiter, append it to the end |
| 57 | if self._delimiter != delimiter: |
| 58 | combined_statement = " ".join([sql] + queries) |
| 59 | if trailing_delimiter: |
| 60 | combined_statement += delimiter |
| 61 | queries = self._split(combined_statement)[1:] |
| 62 | |
| 63 | def set(self, arg: str, **_) -> list[SQLResult]: |
| 64 | """Change delimiter. |
| 65 | |
| 66 | Since `arg` is everything that follows the DELIMITER token |
| 67 | after sqlparse (it may include other statements separated by |
| 68 | the new delimiter), we want to set the delimiter to the first |
| 69 | word of it. |
| 70 | |
| 71 | """ |
no outgoing calls