sql-metadata
sql-metadata copied to clipboard
`Parser(sql).tables` hangs for some cases
version: 2.15.0
This is a demo which can reproduce this bug.
def test_hang(self):
from sql_metadata import Parser
s = """WITH a AS (SELECT MAX(b) AS c
FROM d
WHERE domain =e''$.f') AS g
FROM h;"""
Parser(s).tables
With some debug, I find that it seems stuck in the while self._is_in_with_block and token.next_token: loop.
A quick "fix" for someone who also meets this bug. (Actually, it's not a fix, it just prevents the infinite while loop.)
class StuckFixedParser(Parser):
@property
def with_names(self) -> List[str]:
"""
Returns with statements aliases list from a given query
E.g. WITH database1.tableFromWith AS (SELECT * FROM table3)
SELECT "xxxxx" FROM database1.tableFromWith alias
LEFT JOIN database2.table2 ON ("tt"."ttt"."fff" = "xx"."xxx")
will return ["database1.tableFromWith"]
"""
if self._with_names is not None:
return self._with_names
with_names = UniqueList()
for token in self._not_parsed_tokens:
if token.previous_token.normalized == "WITH":
self._is_in_with_block = True
while self._is_in_with_block and token.next_token:
if token.next_token.is_as_keyword:
self._handle_with_name_save(token=token, with_names=with_names)
while token.next_token and not token.is_with_query_end:
token = token.next_token
is_end_of_with_block = (
token.next_token_not_comment is None
or token.next_token_not_comment.normalized in WITH_ENDING_KEYWORDS
)
if is_end_of_with_block:
self._is_in_with_block = False
elif token.next_token and token.next_token.is_as_keyword:
break
else:
token = token.next_token
self._with_names = with_names
return self._with_names
Notice the else branch after the if is_end_of_with_block: condition.