Skip to content

Commit

Permalink
Add OVER clause, and group it into Function (fixes andialbrecht#701)
Browse files Browse the repository at this point in the history
  • Loading branch information
r33s3n6 committed Mar 26, 2024
1 parent d8f8147 commit 608824d
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 1 deletion.
18 changes: 17 additions & 1 deletion sqlparse/engine/grouping.py
Expand Up @@ -235,6 +235,16 @@ def group_identifier(tlist):
tidx, token = tlist.token_next_by(t=ttypes, idx=tidx)


@recurse(sql.Over)
def group_over(tlist):
tidx, token = tlist.token_next_by(m=sql.Over.M_OPEN)
while token:
nidx, next_ = tlist.token_next(tidx)
if imt(next_, i=sql.Parenthesis, t=T.Name):
tlist.group_tokens(sql.Over, tidx, nidx)
tidx, token = tlist.token_next_by(m=sql.Over.M_OPEN, idx=tidx)


def group_arrays(tlist):
sqlcls = sql.SquareBrackets, sql.Identifier, sql.Function
ttypes = T.Name, T.String.Symbol
Expand Down Expand Up @@ -361,7 +371,12 @@ def group_functions(tlist):
while token:
nidx, next_ = tlist.token_next(tidx)
if isinstance(next_, sql.Parenthesis):
tlist.group_tokens(sql.Function, tidx, nidx)
over_idx, over = tlist.token_next(nidx)
if over and isinstance(over, sql.Over):
eidx = over_idx
else:
eidx = nidx
tlist.group_tokens(sql.Function, tidx, eidx)
tidx, token = tlist.token_next_by(t=T.Name, idx=tidx)


Expand Down Expand Up @@ -412,6 +427,7 @@ def group(stmt):
group_for,
group_begin,

group_over,
group_functions,
group_where,
group_period,
Expand Down
5 changes: 5 additions & 0 deletions sqlparse/sql.py
Expand Up @@ -554,6 +554,11 @@ class Where(TokenList):
'HAVING', 'RETURNING', 'INTO')


class Over(TokenList):
"""An OVER clause."""
M_OPEN = T.Keyword, 'OVER'


class Having(TokenList):
"""A HAVING clause."""
M_OPEN = T.Keyword, 'HAVING'
Expand Down
14 changes: 14 additions & 0 deletions tests/test_grouping.py
Expand Up @@ -185,6 +185,20 @@ def test_grouping_identifier_function():
assert isinstance(p.tokens[0], sql.Identifier)
assert isinstance(p.tokens[0].tokens[0], sql.Operation)
assert isinstance(p.tokens[0].tokens[0].tokens[0], sql.Function)
p = sqlparse.parse('foo(c1) over win1 as bar')[0]
assert isinstance(p.tokens[0], sql.Identifier)
assert isinstance(p.tokens[0].tokens[0], sql.Function)
assert len(p.tokens[0].tokens[0].tokens) == 4
assert isinstance(p.tokens[0].tokens[0].tokens[3], sql.Over)
assert isinstance(p.tokens[0].tokens[0].tokens[3].tokens[2],
sql.Identifier)
p = sqlparse.parse('foo(c1) over (partition by c2 order by c3) as bar')[0]
assert isinstance(p.tokens[0], sql.Identifier)
assert isinstance(p.tokens[0].tokens[0], sql.Function)
assert len(p.tokens[0].tokens[0].tokens) == 4
assert isinstance(p.tokens[0].tokens[0].tokens[3], sql.Over)
assert isinstance(p.tokens[0].tokens[0].tokens[3].tokens[2],
sql.Parenthesis)


@pytest.mark.parametrize('s', ['foo+100', 'foo + 100', 'foo*100'])
Expand Down

0 comments on commit 608824d

Please sign in to comment.