Skip to content

Commit e8ae45d

Browse files
Andreas AlbrechtAndreas Albrecht
authored andcommitted
Restrict detection of alias names (fixes andialbrecht#455).
This change adopts some parts of the pull request andialbrecht#509 by john-bodley. Thanks!
1 parent 91cfc1b commit e8ae45d

File tree

4 files changed

+35
-20
lines changed

4 files changed

+35
-20
lines changed

CHANGELOG

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ Bug Fixes
1616
* Remove support for parsing double slash comments introduced in
1717
0.3.0 (issue456) as it had some side-effects with other dialects and
1818
doesn't seem to be widely used (issue476).
19+
* Restrict detection of alias names to objects that acutally could
20+
have an alias (issue455, adopted some parts of pr509 by john-bodley).
1921

2022

2123
Release 0.3.0 (Mar 11, 2019)

sqlparse/sql.py

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,29 @@
1616
from sqlparse.utils import imt, remove_quotes
1717

1818

19+
class NameAliasMixin:
20+
"""Implements get_real_name and get_alias."""
21+
22+
def get_real_name(self):
23+
"""Returns the real name (object name) of this identifier."""
24+
# a.b
25+
dot_idx, _ = self.token_next_by(m=(T.Punctuation, '.'))
26+
return self._get_first_name(dot_idx, real_name=True)
27+
28+
def get_alias(self):
29+
"""Returns the alias for this identifier or ``None``."""
30+
31+
# "name AS alias"
32+
kw_idx, kw = self.token_next_by(m=(T.Keyword, 'AS'))
33+
if kw is not None:
34+
return self._get_first_name(kw_idx + 1, keywords=True)
35+
36+
# "name alias" or "complicated column expression alias"
37+
_, ws = self.token_next_by(t=T.Whitespace)
38+
if len(self.tokens) > 2 and ws is not None:
39+
return self._get_first_name(reverse=True)
40+
41+
1942
@unicode_compatible
2043
class Token(object):
2144
"""Base class for all other classes in this module.
@@ -341,16 +364,7 @@ def has_alias(self):
341364

342365
def get_alias(self):
343366
"""Returns the alias for this identifier or ``None``."""
344-
345-
# "name AS alias"
346-
kw_idx, kw = self.token_next_by(m=(T.Keyword, 'AS'))
347-
if kw is not None:
348-
return self._get_first_name(kw_idx + 1, keywords=True)
349-
350-
# "name alias" or "complicated column expression alias"
351-
_, ws = self.token_next_by(t=T.Whitespace)
352-
if len(self.tokens) > 2 and ws is not None:
353-
return self._get_first_name(reverse=True)
367+
return None
354368

355369
def get_name(self):
356370
"""Returns the name of this identifier.
@@ -363,9 +377,7 @@ def get_name(self):
363377

364378
def get_real_name(self):
365379
"""Returns the real name (object name) of this identifier."""
366-
# a.b
367-
dot_idx, _ = self.token_next_by(m=(T.Punctuation, '.'))
368-
return self._get_first_name(dot_idx, real_name=True)
380+
return None
369381

370382
def get_parent_name(self):
371383
"""Return name of the parent object if any.
@@ -433,7 +445,7 @@ def get_type(self):
433445
return 'UNKNOWN'
434446

435447

436-
class Identifier(TokenList):
448+
class Identifier(NameAliasMixin, TokenList):
437449
"""Represents an identifier.
438450
439451
Identifiers may have aliases or typecasts.
@@ -599,7 +611,7 @@ def get_cases(self, skip_ws=False):
599611
return ret
600612

601613

602-
class Function(TokenList):
614+
class Function(NameAliasMixin, TokenList):
603615
"""A function or procedure call."""
604616

605617
def get_parameters(self):

tests/test_grouping.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -294,9 +294,10 @@ def test_grouping_subquery_no_parens():
294294
assert isinstance(p.tokens[0], sql.Case)
295295

296296

297-
def test_grouping_alias_returns_none():
298-
# see issue185
299-
p = sqlparse.parse('foo.bar')[0]
297+
@pytest.mark.parametrize('s', ['foo.bar', 'x, y', 'x > y', 'x / y'])
298+
def test_grouping_alias_returns_none(s):
299+
# see issue185 and issue445
300+
p = sqlparse.parse(s)[0]
300301
assert len(p.tokens) == 1
301302
assert p.tokens[0].get_alias() is None
302303

tests/test_parse.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -431,8 +431,8 @@ def test_get_real_name():
431431
s = u"update a t set t.b=1"
432432
stmts = sqlparse.parse(s)
433433
assert len(stmts) == 1
434-
assert 'a' == stmts[0].get_real_name()
435-
assert 't' == stmts[0].get_alias()
434+
assert 'a' == stmts[0].tokens[2].get_real_name()
435+
assert 't' == stmts[0].tokens[2].get_alias()
436436

437437

438438
def test_from_subquery():

0 commit comments

Comments
 (0)