Skip to content

Commit 13c1d71

Browse files
committed
Detect alias for CASE statements (targets issue46).
1 parent ff50b33 commit 13c1d71

3 files changed

Lines changed: 45 additions & 40 deletions

File tree

sqlparse/engine/grouping.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -274,21 +274,20 @@ def group_where(tlist):
274274

275275

276276
def group_aliased(tlist):
277+
clss = (sql.Identifier, sql.Function, sql.Case)
277278
[group_aliased(sgroup) for sgroup in tlist.get_sublists()
278-
if not isinstance(sgroup, (sql.Identifier, sql.Function))]
279+
if not isinstance(sgroup, clss)]
279280
idx = 0
280-
token = tlist.token_next_by_instance(idx, (sql.Identifier, sql.Function))
281+
token = tlist.token_next_by_instance(idx, clss)
281282
while token:
282283
next_ = tlist.token_next(tlist.token_index(token))
283-
if next_ is not None and isinstance(next_,
284-
(sql.Identifier, sql.Function)):
284+
if next_ is not None and isinstance(next_, clss):
285285
grp = tlist.tokens_between(token, next_)[1:]
286286
token.tokens.extend(grp)
287287
for t in grp:
288288
tlist.tokens.remove(t)
289289
idx = tlist.token_index(token) + 1
290-
token = tlist.token_next_by_instance(idx,
291-
(sql.Identifier, sql.Function))
290+
token = tlist.token_next_by_instance(idx, clss)
292291

293292

294293
def group_typecasts(tlist):

sqlparse/sql.py

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -315,38 +315,6 @@ def insert_before(self, where, token):
315315
"""Inserts *token* before *where*."""
316316
self.tokens.insert(self.token_index(where), token)
317317

318-
319-
class Statement(TokenList):
320-
"""Represents a SQL statement."""
321-
322-
__slots__ = ('value', 'ttype', 'tokens')
323-
324-
def get_type(self):
325-
"""Returns the type of a statement.
326-
327-
The returned value is a string holding an upper-cased reprint of
328-
the first DML or DDL keyword. If the first token in this group
329-
isn't a DML or DDL keyword "UNKNOWN" is returned.
330-
"""
331-
first_token = self.token_first()
332-
if first_token is None:
333-
# An "empty" statement that either has not tokens at all
334-
# or only whitespace tokens.
335-
return 'UNKNOWN'
336-
elif first_token.ttype in (T.Keyword.DML, T.Keyword.DDL):
337-
return first_token.value.upper()
338-
else:
339-
return 'UNKNOWN'
340-
341-
342-
class Identifier(TokenList):
343-
"""Represents an identifier.
344-
345-
Identifiers may have aliases or typecasts.
346-
"""
347-
348-
__slots__ = ('value', 'ttype', 'tokens')
349-
350318
def has_alias(self):
351319
"""Returns ``True`` if an alias is present."""
352320
return self.get_alias() is not None
@@ -359,8 +327,8 @@ def get_alias(self):
359327
if alias is None:
360328
return None
361329
else:
362-
next_ = self.token_next(0)
363-
if next_ is None or not isinstance(next_, Identifier):
330+
next_ = self.token_next_by_instance(0, Identifier)
331+
if next_ is None:
364332
return None
365333
alias = next_
366334
if isinstance(alias, Identifier):
@@ -393,6 +361,39 @@ def get_real_name(self):
393361
return None
394362
return next_.value
395363

364+
365+
366+
class Statement(TokenList):
367+
"""Represents a SQL statement."""
368+
369+
__slots__ = ('value', 'ttype', 'tokens')
370+
371+
def get_type(self):
372+
"""Returns the type of a statement.
373+
374+
The returned value is a string holding an upper-cased reprint of
375+
the first DML or DDL keyword. If the first token in this group
376+
isn't a DML or DDL keyword "UNKNOWN" is returned.
377+
"""
378+
first_token = self.token_first()
379+
if first_token is None:
380+
# An "empty" statement that either has not tokens at all
381+
# or only whitespace tokens.
382+
return 'UNKNOWN'
383+
elif first_token.ttype in (T.Keyword.DML, T.Keyword.DDL):
384+
return first_token.value.upper()
385+
else:
386+
return 'UNKNOWN'
387+
388+
389+
class Identifier(TokenList):
390+
"""Represents an identifier.
391+
392+
Identifiers may have aliases or typecasts.
393+
"""
394+
395+
__slots__ = ('value', 'ttype', 'tokens')
396+
396397
def get_parent_name(self):
397398
"""Return name of the parent object if any.
398399

tests/test_grouping.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,11 @@ def test_alias(self):
157157
self.ndiffAssertEqual(s, p.to_unicode())
158158
self.assertEqual(p.tokens[4].get_alias(), 'view')
159159

160+
def test_alias_case(self): # see issue46
161+
p = sqlparse.parse('CASE WHEN 1 THEN 2 ELSE 3 END foo')[0]
162+
self.assertEqual(len(p.tokens), 1)
163+
self.assertEqual(p.tokens[0].get_alias(), 'foo')
164+
160165
def test_idlist_function(self): # see issue10 too
161166
p = sqlparse.parse('foo(1) x, bar')[0]
162167
self.assert_(isinstance(p.tokens[0], sql.IdentifierList))

0 commit comments

Comments
 (0)