@@ -390,21 +390,17 @@ def has_alias(self):
390390
391391 def get_alias (self ):
392392 """Returns the alias for this identifier or ``None``."""
393+
394+ # "name AS alias"
393395 kw = self .token_next_match (0 , T .Keyword , 'AS' )
394396 if kw is not None :
395- alias = self .token_next (self .token_index (kw ))
396- if alias is None :
397- return None
398- else :
399- next_ = self .token_next_by_instance (0 , Identifier )
400- if next_ is None :
401- next_ = self .token_next_by_type (0 , T .String .Symbol )
402- if next_ is None :
403- return None
404- alias = next_
405- if isinstance (alias , Identifier ):
406- return alias .get_name ()
407- return self ._remove_quotes (unicode (alias ))
397+ return self ._get_first_name (kw , keywords = True )
398+
399+ # "name alias" or "complicated column expression alias"
400+ if len (self .tokens ) > 2 :
401+ return self ._get_first_name (reverse = True )
402+
403+ return None
408404
409405 def get_name (self ):
410406 """Returns the name of this identifier.
@@ -422,18 +418,43 @@ def get_real_name(self):
422418 """Returns the real name (object name) of this identifier."""
423419 # a.b
424420 dot = self .token_next_match (0 , T .Punctuation , '.' )
421+ if dot is not None :
422+ return self ._get_first_name (self .token_index (dot ))
423+
424+ return self ._get_first_name ()
425+
426+ def get_parent_name (self ):
427+ """Return name of the parent object if any.
428+
429+ A parent object is identified by the first occuring dot.
430+ """
431+ dot = self .token_next_match (0 , T .Punctuation , '.' )
425432 if dot is None :
426- next_ = self .token_next_by_type (0 , T .Name )
427- if next_ is not None :
428- return self ._remove_quotes (next_ .value )
429433 return None
430-
431- next_ = self .token_next_by_type (self .token_index (dot ),
432- (T .Name , T .Wildcard , T .String .Symbol ))
433- if next_ is None : # invalid identifier, e.g. "a."
434+ prev_ = self .token_prev (self .token_index (dot ))
435+ if prev_ is None : # something must be verry wrong here..
434436 return None
435- return self ._remove_quotes (next_ .value )
437+ return self ._remove_quotes (prev_ .value )
438+
439+ def _get_first_name (self , idx = None , reverse = False , keywords = False ):
440+ """Returns the name of the first token with a name"""
436441
442+ if idx and not isinstance (idx , int ):
443+ idx = self .token_index (idx ) + 1
444+
445+ tokens = self .tokens [idx :] if idx else self .tokens
446+ tokens = reversed (tokens ) if reverse else tokens
447+ types = [T .Name , T .Wildcard , T .String .Symbol ]
448+
449+ if keywords :
450+ types .append (T .Keyword )
451+
452+ for tok in tokens :
453+ if tok .ttype in types :
454+ return self ._remove_quotes (tok .value )
455+ elif isinstance (tok , Identifier ) or isinstance (tok , Function ):
456+ return tok .get_name ()
457+ return None
437458
438459class Statement (TokenList ):
439460 """Represents a SQL statement."""
@@ -467,19 +488,6 @@ class Identifier(TokenList):
467488
468489 __slots__ = ('value' , 'ttype' , 'tokens' )
469490
470- def get_parent_name (self ):
471- """Return name of the parent object if any.
472-
473- A parent object is identified by the first occuring dot.
474- """
475- dot = self .token_next_match (0 , T .Punctuation , '.' )
476- if dot is None :
477- return None
478- prev_ = self .token_prev (self .token_index (dot ))
479- if prev_ is None : # something must be verry wrong here..
480- return None
481- return self ._remove_quotes (prev_ .value )
482-
483491 def is_wildcard (self ):
484492 """Return ``True`` if this identifier contains a wildcard."""
485493 token = self .token_next_by_type (0 , T .Wildcard )
0 commit comments