Merging upstream version 11.0.1.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
fdac67ef7f
commit
ba0f3f0bfa
112 changed files with 126100 additions and 230 deletions
|
@ -6,6 +6,7 @@ Every AST node in SQLGlot is represented by a subclass of `Expression`.
|
|||
This module contains the implementation of all supported `Expression` types. Additionally,
|
||||
it exposes a number of helper functions, which are mainly used to programmatically build
|
||||
SQL expressions, such as `sqlglot.expressions.select`.
|
||||
|
||||
----
|
||||
"""
|
||||
|
||||
|
@ -137,6 +138,8 @@ class Expression(metaclass=_Expression):
|
|||
return field
|
||||
if isinstance(field, (Identifier, Literal, Var)):
|
||||
return field.this
|
||||
if isinstance(field, (Star, Null)):
|
||||
return field.name
|
||||
return ""
|
||||
|
||||
@property
|
||||
|
@ -176,13 +179,11 @@ class Expression(metaclass=_Expression):
|
|||
return self.text("alias")
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
def name(self) -> str:
|
||||
return self.text("this")
|
||||
|
||||
@property
|
||||
def alias_or_name(self):
|
||||
if isinstance(self, Null):
|
||||
return "NULL"
|
||||
return self.alias or self.name
|
||||
|
||||
@property
|
||||
|
@ -589,12 +590,11 @@ class Expression(metaclass=_Expression):
|
|||
return load(obj)
|
||||
|
||||
|
||||
if t.TYPE_CHECKING:
|
||||
IntoType = t.Union[
|
||||
str,
|
||||
t.Type[Expression],
|
||||
t.Collection[t.Union[str, t.Type[Expression]]],
|
||||
]
|
||||
IntoType = t.Union[
|
||||
str,
|
||||
t.Type[Expression],
|
||||
t.Collection[t.Union[str, t.Type[Expression]]],
|
||||
]
|
||||
|
||||
|
||||
class Condition(Expression):
|
||||
|
@ -939,7 +939,7 @@ class EncodeColumnConstraint(ColumnConstraintKind):
|
|||
|
||||
class GeneratedAsIdentityColumnConstraint(ColumnConstraintKind):
|
||||
# this: True -> ALWAYS, this: False -> BY DEFAULT
|
||||
arg_types = {"this": True, "start": False, "increment": False}
|
||||
arg_types = {"this": False, "start": False, "increment": False}
|
||||
|
||||
|
||||
class NotNullColumnConstraint(ColumnConstraintKind):
|
||||
|
@ -2390,7 +2390,7 @@ class Star(Expression):
|
|||
arg_types = {"except": False, "replace": False}
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
def name(self) -> str:
|
||||
return "*"
|
||||
|
||||
@property
|
||||
|
@ -2413,6 +2413,10 @@ class Placeholder(Expression):
|
|||
class Null(Condition):
|
||||
arg_types: t.Dict[str, t.Any] = {}
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return "NULL"
|
||||
|
||||
|
||||
class Boolean(Condition):
|
||||
pass
|
||||
|
@ -2644,7 +2648,9 @@ class Div(Binary):
|
|||
|
||||
|
||||
class Dot(Binary):
|
||||
pass
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return self.expression.name
|
||||
|
||||
|
||||
class DPipe(Binary):
|
||||
|
@ -2961,7 +2967,7 @@ class Cast(Func):
|
|||
arg_types = {"this": True, "to": True}
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
def name(self) -> str:
|
||||
return self.this.name
|
||||
|
||||
@property
|
||||
|
@ -4027,17 +4033,39 @@ def paren(expression) -> Paren:
|
|||
SAFE_IDENTIFIER_RE = re.compile(r"^[_a-zA-Z][\w]*$")
|
||||
|
||||
|
||||
def to_identifier(alias, quoted=None) -> t.Optional[Identifier]:
|
||||
if alias is None:
|
||||
@t.overload
|
||||
def to_identifier(name: None, quoted: t.Optional[bool] = None) -> None:
|
||||
...
|
||||
|
||||
|
||||
@t.overload
|
||||
def to_identifier(name: str | Identifier, quoted: t.Optional[bool] = None) -> Identifier:
|
||||
...
|
||||
|
||||
|
||||
def to_identifier(name, quoted=None):
|
||||
"""Builds an identifier.
|
||||
|
||||
Args:
|
||||
name: The name to turn into an identifier.
|
||||
quoted: Whether or not force quote the identifier.
|
||||
|
||||
Returns:
|
||||
The identifier ast node.
|
||||
"""
|
||||
|
||||
if name is None:
|
||||
return None
|
||||
if isinstance(alias, Identifier):
|
||||
identifier = alias
|
||||
elif isinstance(alias, str):
|
||||
if quoted is None:
|
||||
quoted = not re.match(SAFE_IDENTIFIER_RE, alias)
|
||||
identifier = Identifier(this=alias, quoted=quoted)
|
||||
|
||||
if isinstance(name, Identifier):
|
||||
identifier = name
|
||||
elif isinstance(name, str):
|
||||
identifier = Identifier(
|
||||
this=name,
|
||||
quoted=not re.match(SAFE_IDENTIFIER_RE, name) if quoted is None else quoted,
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"Alias needs to be a string or an Identifier, got: {alias.__class__}")
|
||||
raise ValueError(f"Name needs to be a string or an Identifier, got: {name.__class__}")
|
||||
return identifier
|
||||
|
||||
|
||||
|
@ -4112,20 +4140,31 @@ def to_column(sql_path: str | Column, **kwargs) -> Column:
|
|||
return Column(this=column_name, table=table_name, **kwargs)
|
||||
|
||||
|
||||
def alias_(expression, alias, table=False, dialect=None, quoted=None, **opts):
|
||||
"""
|
||||
Create an Alias expression.
|
||||
def alias_(
|
||||
expression: str | Expression,
|
||||
alias: str | Identifier,
|
||||
table: bool | t.Sequence[str | Identifier] = False,
|
||||
quoted: t.Optional[bool] = None,
|
||||
dialect: DialectType = None,
|
||||
**opts,
|
||||
):
|
||||
"""Create an Alias expression.
|
||||
|
||||
Example:
|
||||
>>> alias_('foo', 'bar').sql()
|
||||
'foo AS bar'
|
||||
|
||||
>>> alias_('(select 1, 2)', 'bar', table=['a', 'b']).sql()
|
||||
'(SELECT 1, 2) AS bar(a, b)'
|
||||
|
||||
Args:
|
||||
expression (str | Expression): the SQL code strings to parse.
|
||||
expression: the SQL code strings to parse.
|
||||
If an Expression instance is passed, this is used as-is.
|
||||
alias (str | Identifier): the alias name to use. If the name has
|
||||
alias: the alias name to use. If the name has
|
||||
special characters it is quoted.
|
||||
table (bool): create a table alias, default false
|
||||
dialect (str): the dialect used to parse the input expression.
|
||||
table: Whether or not to create a table alias, can also be a list of columns.
|
||||
quoted: whether or not to quote the alias
|
||||
dialect: the dialect used to parse the input expression.
|
||||
**opts: other options to use to parse the input expressions.
|
||||
|
||||
Returns:
|
||||
|
@ -4135,8 +4174,14 @@ def alias_(expression, alias, table=False, dialect=None, quoted=None, **opts):
|
|||
alias = to_identifier(alias, quoted=quoted)
|
||||
|
||||
if table:
|
||||
expression.set("alias", TableAlias(this=alias))
|
||||
return expression
|
||||
table_alias = TableAlias(this=alias)
|
||||
exp.set("alias", table_alias)
|
||||
|
||||
if not isinstance(table, bool):
|
||||
for column in table:
|
||||
table_alias.append("columns", to_identifier(column, quoted=quoted))
|
||||
|
||||
return exp
|
||||
|
||||
# We don't set the "alias" arg for Window expressions, because that would add an IDENTIFIER node in
|
||||
# the AST, representing a "named_window" [1] construct (eg. bigquery). What we want is an ALIAS node
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue