Skip to content

Commit 341143e

Browse files
committed
Add order criterion to identifier in ORDER BY clause (fixes andialbrecht#89).
1 parent bd53069 commit 341143e

File tree

6 files changed

+48
-3
lines changed

6 files changed

+48
-3
lines changed

CHANGES

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ Bug Fixes
99
invalid SQL statements.
1010

1111
Enhancements
12-
* Improve parsing speed when SQL contains CLOBs or BLOBs (issue86).
1312
* Top-level API functions now accept encoding keyword to parse
1413
statements in certain encodings more reliable (issue20).
14+
* Improve parsing speed when SQL contains CLOBs or BLOBs (issue86).
15+
* Improve formatting of ORDER BY clauses (issue89).
1516

1617
Other
1718
* Documentation updates.

sqlparse/engine/grouping.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,20 @@ def group_functions(tlist):
332332
token = tlist.token_next_by_type(idx, T.Name)
333333

334334

335+
def group_order(tlist):
336+
idx = 0
337+
token = tlist.token_next_by_type(idx, T.Keyword.Order)
338+
while token:
339+
prev = tlist.token_prev(token)
340+
if isinstance(prev, sql.Identifier):
341+
ido = tlist.group_tokens(sql.Identifier,
342+
tlist.tokens_between(prev, token))
343+
idx = tlist.token_index(ido) + 1
344+
else:
345+
idx = tlist.token_index(token) + 1
346+
token = tlist.token_next_by_type(idx, T.Keyword.Order)
347+
348+
335349
def group(tlist):
336350
for func in [
337351
group_comments,
@@ -340,6 +354,7 @@ def group(tlist):
340354
group_where,
341355
group_case,
342356
group_identifier,
357+
group_order,
343358
group_typecasts,
344359
group_as,
345360
group_aliased,

sqlparse/keywords.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
'ANALYZE': tokens.Keyword,
1818
'ANY': tokens.Keyword,
1919
'ARE': tokens.Keyword,
20-
'ASC': tokens.Keyword,
20+
'ASC': tokens.Keyword.Order,
2121
'ASENSITIVE': tokens.Keyword,
2222
'ASSERTION': tokens.Keyword,
2323
'ASSIGNMENT': tokens.Keyword,
@@ -124,7 +124,7 @@
124124
'DELIMITER': tokens.Keyword,
125125
'DELIMITERS': tokens.Keyword,
126126
'DEREF': tokens.Keyword,
127-
'DESC': tokens.Keyword,
127+
'DESC': tokens.Keyword.Order,
128128
'DESCRIBE': tokens.Keyword,
129129
'DESCRIPTOR': tokens.Keyword,
130130
'DESTROY': tokens.Keyword,

sqlparse/sql.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,13 @@ def get_typecast(self):
495495
return None
496496
return unicode(next_)
497497

498+
def get_ordering(self):
499+
"""Returns the ordering or ``None`` as uppercase string."""
500+
ordering = self.token_next_by_type(0, T.Keyword.Order)
501+
if ordering is None:
502+
return None
503+
return ordering.value.upper()
504+
498505

499506
class IdentifierList(TokenList):
500507
"""A list of :class:`~sqlparse.sql.Identifier`\'s."""

tests/test_format.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,3 +267,14 @@ def test_sql(self): # "sql" is an allowed option but has no effect
267267
sql = 'select * from foo;'
268268
f = lambda sql: sqlparse.format(sql, output_format='sql')
269269
self.ndiffAssertEqual(f(sql), 'select * from foo;')
270+
271+
272+
def test_format_column_ordering(): # issue89
273+
sql = 'select * from foo order by c1 desc, c2, c3;'
274+
formatted = sqlparse.format(sql, reindent=True)
275+
expected = '\n'.join(['select *',
276+
'from foo',
277+
'order by c1 desc,',
278+
' c2,',
279+
' c3;'])
280+
assert formatted == expected

tests/test_grouping.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,14 @@ def test_identifier_string_concat():
231231
p = sqlparse.parse('\'foo\' || bar')[0]
232232
assert len(p.tokens) == 1
233233
assert isinstance(p.tokens[0], sql.Identifier)
234+
235+
236+
def test_identifier_consumes_ordering(): # issue89
237+
p = sqlparse.parse('select * from foo order by c1 desc, c2, c3')[0]
238+
assert isinstance(p.tokens[-1], sql.IdentifierList)
239+
ids = list(p.tokens[-1].get_identifiers())
240+
assert len(ids) == 3
241+
assert ids[0].get_name() == 'c1'
242+
assert ids[0].get_ordering() == 'DESC'
243+
assert ids[1].get_name() == 'c2'
244+
assert ids[1].get_ordering() is None

0 commit comments

Comments
 (0)