Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions sqlparse/filters/aligned_indent.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ def _process_case(self, tlist):
cases = tlist.get_cases(skip_ws=True)
# align the end as well
end_token = tlist.token_next_by(m=(T.Keyword, 'END'))[1]
if end_token is None:
# A malformed CASE expression can leave END nested inside a
# sibling group instead of being a direct child of this token
# list (get_cases and token_next_by only look at direct
# children), so there's nothing valid to align it against.
return
cases.append((None, [end_token]))

condition_width = [len(' '.join(map(str, cond))) if cond else 0
Expand Down
10 changes: 7 additions & 3 deletions sqlparse/filters/others.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,15 @@ def _stripws_identifierlist(self, tlist):
return self._stripws_default(tlist)

def _stripws_parenthesis(self, tlist):
while tlist.tokens[1].is_whitespace:
# A malformed parenthesis can end up with only one or two direct
# children once grouping is done (e.g. the whole inside collapses
# into a single nested group), so don't assume tokens[1]/tokens[-2]
# are always there.
while len(tlist.tokens) > 2 and tlist.tokens[1].is_whitespace:
tlist.tokens.pop(1)
while tlist.tokens[-2].is_whitespace:
while len(tlist.tokens) > 2 and tlist.tokens[-2].is_whitespace:
tlist.tokens.pop(-2)
if tlist.tokens[-2].is_group:
if len(tlist.tokens) > 1 and tlist.tokens[-2].is_group:
# save to remove the last whitespace
while tlist.tokens[-2].tokens[-1].is_whitespace:
tlist.tokens[-2].tokens.pop(-1)
Expand Down
16 changes: 16 additions & 0 deletions tests/test_regressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -516,3 +516,19 @@ def limit_recursion():
def test_max_recursion(limit_recursion):
with pytest.raises(SQLParseError):
sqlparse.parse('[' * 1000 + ']' * 1000)


def test_stripws_parenthesis_with_no_direct_children_issue885():
# Malformed input can collapse the whole parenthesis body into a single
# nested group, leaving fewer than two direct children of the
# Parenthesis token list. This used to raise IndexError.
assert sqlparse.format('( AS )', strip_whitespace=True) == '( AS )'


def test_aligned_indent_case_without_direct_end_issue886():
# Malformed CASE expressions can end up with the END keyword nested
# inside a sibling group rather than being a direct child of the Case
# token list, so token_next_by can't find it and used to raise
# ValueError when that None was later used as an insertion point.
sql = "CASE 'a' := WHERE END SELECT GO # ->>"
assert sqlparse.format(sql, reindent_aligned=True) == sql