Merging upstream version 9.0.1.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
ebb36a5fc5
commit
4483b8ff47
87 changed files with 7994 additions and 421 deletions
|
@ -11,6 +11,7 @@ from sqlglot.helper import (
|
|||
camel_to_snake_case,
|
||||
ensure_list,
|
||||
list_get,
|
||||
split_num_words,
|
||||
subclasses,
|
||||
)
|
||||
|
||||
|
@ -108,6 +109,8 @@ class Expression(metaclass=_Expression):
|
|||
|
||||
@property
|
||||
def alias_or_name(self):
|
||||
if isinstance(self, Null):
|
||||
return "NULL"
|
||||
return self.alias or self.name
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
|
@ -659,6 +662,10 @@ class HexString(Condition):
|
|||
pass
|
||||
|
||||
|
||||
class ByteString(Condition):
|
||||
pass
|
||||
|
||||
|
||||
class Column(Condition):
|
||||
arg_types = {"this": True, "table": False}
|
||||
|
||||
|
@ -725,7 +732,7 @@ class Constraint(Expression):
|
|||
|
||||
|
||||
class Delete(Expression):
|
||||
arg_types = {"with": False, "this": True, "where": False}
|
||||
arg_types = {"with": False, "this": True, "using": False, "where": False}
|
||||
|
||||
|
||||
class Drop(Expression):
|
||||
|
@ -1192,6 +1199,7 @@ QUERY_MODIFIERS = {
|
|||
class Table(Expression):
|
||||
arg_types = {
|
||||
"this": True,
|
||||
"alias": False,
|
||||
"db": False,
|
||||
"catalog": False,
|
||||
"laterals": False,
|
||||
|
@ -1323,6 +1331,7 @@ class Select(Subqueryable):
|
|||
*expressions (str or Expression): the SQL code strings to parse.
|
||||
If a `Group` instance is passed, this is used as-is.
|
||||
If another `Expression` instance is passed, it will be wrapped in a `Group`.
|
||||
If nothing is passed in then a group by is not applied to the expression
|
||||
append (bool): if `True`, add to any existing expressions.
|
||||
Otherwise, this flattens all the `Group` expression into a single expression.
|
||||
dialect (str): the dialect used to parse the input expression.
|
||||
|
@ -1332,6 +1341,8 @@ class Select(Subqueryable):
|
|||
Returns:
|
||||
Select: the modified expression.
|
||||
"""
|
||||
if not expressions:
|
||||
return self if not copy else self.copy()
|
||||
return _apply_child_list_builder(
|
||||
*expressions,
|
||||
instance=self,
|
||||
|
@ -2239,6 +2250,11 @@ class ArrayAny(Func):
|
|||
arg_types = {"this": True, "expression": True}
|
||||
|
||||
|
||||
class ArrayConcat(Func):
|
||||
arg_types = {"this": True, "expressions": False}
|
||||
is_var_len_args = True
|
||||
|
||||
|
||||
class ArrayContains(Func):
|
||||
arg_types = {"this": True, "expression": True}
|
||||
|
||||
|
@ -2570,7 +2586,7 @@ class SortArray(Func):
|
|||
|
||||
|
||||
class Split(Func):
|
||||
arg_types = {"this": True, "expression": True}
|
||||
arg_types = {"this": True, "expression": True, "limit": False}
|
||||
|
||||
|
||||
# Start may be omitted in the case of postgres
|
||||
|
@ -3209,29 +3225,49 @@ def to_identifier(alias, quoted=None):
|
|||
return identifier
|
||||
|
||||
|
||||
def to_table(sql_path, **kwargs):
|
||||
def to_table(sql_path: str, **kwargs) -> Table:
|
||||
"""
|
||||
Create a table expression from a `[catalog].[schema].[table]` sql path. Catalog and schema are optional.
|
||||
Example:
|
||||
>>> to_table('catalog.db.table_name').sql()
|
||||
'catalog.db.table_name'
|
||||
|
||||
If a table is passed in then that table is returned.
|
||||
|
||||
Args:
|
||||
sql_path(str): `[catalog].[schema].[table]` string
|
||||
sql_path(str|Table): `[catalog].[schema].[table]` string
|
||||
Returns:
|
||||
Table: A table expression
|
||||
"""
|
||||
table_parts = sql_path.split(".")
|
||||
catalog, db, table_name = [
|
||||
to_identifier(x) if x is not None else x for x in [None] * (3 - len(table_parts)) + table_parts
|
||||
]
|
||||
if sql_path is None or isinstance(sql_path, Table):
|
||||
return sql_path
|
||||
if not isinstance(sql_path, str):
|
||||
raise ValueError(f"Invalid type provided for a table: {type(sql_path)}")
|
||||
|
||||
catalog, db, table_name = [to_identifier(x) for x in split_num_words(sql_path, ".", 3)]
|
||||
return Table(this=table_name, db=db, catalog=catalog, **kwargs)
|
||||
|
||||
|
||||
def to_column(sql_path: str, **kwargs) -> Column:
|
||||
"""
|
||||
Create a column from a `[table].[column]` sql path. Schema is optional.
|
||||
|
||||
If a column is passed in then that column is returned.
|
||||
|
||||
Args:
|
||||
sql_path: `[table].[column]` string
|
||||
Returns:
|
||||
Table: A column expression
|
||||
"""
|
||||
if sql_path is None or isinstance(sql_path, Column):
|
||||
return sql_path
|
||||
if not isinstance(sql_path, str):
|
||||
raise ValueError(f"Invalid type provided for column: {type(sql_path)}")
|
||||
table_name, column_name = [to_identifier(x) for x in split_num_words(sql_path, ".", 2)]
|
||||
return Column(this=column_name, table=table_name, **kwargs)
|
||||
|
||||
|
||||
def alias_(expression, alias, table=False, dialect=None, quoted=None, **opts):
|
||||
"""
|
||||
Create an Alias expression.
|
||||
Expample:
|
||||
Example:
|
||||
>>> alias_('foo', 'bar').sql()
|
||||
'foo AS bar'
|
||||
|
||||
|
@ -3249,7 +3285,16 @@ def alias_(expression, alias, table=False, dialect=None, quoted=None, **opts):
|
|||
"""
|
||||
exp = maybe_parse(expression, dialect=dialect, **opts)
|
||||
alias = to_identifier(alias, quoted=quoted)
|
||||
alias = TableAlias(this=alias) if table else alias
|
||||
|
||||
if table:
|
||||
expression.set("alias", TableAlias(this=alias))
|
||||
return expression
|
||||
|
||||
# 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
|
||||
# for the complete Window expression.
|
||||
#
|
||||
# [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls
|
||||
|
||||
if "alias" in exp.arg_types and not isinstance(exp, Window):
|
||||
exp = exp.copy()
|
||||
|
@ -3295,7 +3340,7 @@ def column(col, table=None, quoted=None):
|
|||
)
|
||||
|
||||
|
||||
def table_(table, db=None, catalog=None, quoted=None):
|
||||
def table_(table, db=None, catalog=None, quoted=None, alias=None):
|
||||
"""Build a Table.
|
||||
|
||||
Args:
|
||||
|
@ -3310,6 +3355,7 @@ def table_(table, db=None, catalog=None, quoted=None):
|
|||
this=to_identifier(table, quoted=quoted),
|
||||
db=to_identifier(db, quoted=quoted),
|
||||
catalog=to_identifier(catalog, quoted=quoted),
|
||||
alias=TableAlias(this=to_identifier(alias)) if alias else None,
|
||||
)
|
||||
|
||||
|
||||
|
@ -3453,7 +3499,7 @@ def replace_tables(expression, mapping):
|
|||
Examples:
|
||||
>>> from sqlglot import exp, parse_one
|
||||
>>> replace_tables(parse_one("select * from a.b"), {"a.b": "c"}).sql()
|
||||
'SELECT * FROM "c"'
|
||||
'SELECT * FROM c'
|
||||
|
||||
Returns:
|
||||
The mapped expression
|
||||
|
@ -3463,7 +3509,10 @@ def replace_tables(expression, mapping):
|
|||
if isinstance(node, Table):
|
||||
new_name = mapping.get(table_name(node))
|
||||
if new_name:
|
||||
return table_(*reversed(new_name.split(".")), quoted=True)
|
||||
return to_table(
|
||||
new_name,
|
||||
**{k: v for k, v in node.args.items() if k not in ("this", "db", "catalog")},
|
||||
)
|
||||
return node
|
||||
|
||||
return expression.transform(_replace_tables)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue