1
0
Fork 0

Merging upstream version 7.1.3.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-13 14:46:58 +01:00
parent 964bd62de9
commit e6b3d2fe54
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
42 changed files with 1430 additions and 253 deletions

View file

@ -1,3 +1,4 @@
import datetime
import numbers
import re
from collections import deque
@ -508,7 +509,7 @@ class DerivedTable(Expression):
return [select.alias_or_name for select in self.selects]
class Unionable:
class Unionable(Expression):
def union(self, expression, distinct=True, dialect=None, **opts):
"""
Builds a UNION expression.
@ -614,6 +615,10 @@ class Create(Expression):
}
class Describe(Expression):
pass
class UserDefinedFunction(Expression):
arg_types = {"this": True, "expressions": False}
@ -741,6 +746,11 @@ class Check(Expression):
pass
class Directory(Expression):
# https://spark.apache.org/docs/3.0.0-preview/sql-ref-syntax-dml-insert-overwrite-directory-hive.html
arg_types = {"this": True, "local": False, "row_format": False}
class ForeignKey(Expression):
arg_types = {
"expressions": True,
@ -804,6 +814,18 @@ class Introducer(Expression):
arg_types = {"this": True, "expression": True}
class LoadData(Expression):
arg_types = {
"this": True,
"local": False,
"overwrite": False,
"inpath": True,
"partition": False,
"input_format": False,
"serde": False,
}
class Partition(Expression):
pass
@ -1037,6 +1059,18 @@ class Reference(Expression):
arg_types = {"this": True, "expressions": True}
class RowFormat(Expression):
# https://cwiki.apache.org/confluence/display/hive/languagemanual+dml
arg_types = {
"fields": False,
"escaped": False,
"collection_items": False,
"map_keys": False,
"lines": False,
"null": False,
}
class Tuple(Expression):
arg_types = {"expressions": False}
@ -1071,6 +1105,14 @@ class Subqueryable(Unionable):
return []
return with_.expressions
@property
def selects(self):
raise NotImplementedError("Subqueryable objects must implement `selects`")
@property
def named_selects(self):
raise NotImplementedError("Subqueryable objects must implement `named_selects`")
def with_(
self,
alias,
@ -1158,7 +1200,7 @@ class Table(Expression):
}
class Union(Subqueryable, Expression):
class Union(Subqueryable):
arg_types = {
"with": False,
"this": True,
@ -1169,7 +1211,11 @@ class Union(Subqueryable, Expression):
@property
def named_selects(self):
return self.args["this"].unnest().named_selects
return self.this.unnest().named_selects
@property
def selects(self):
return self.this.unnest().selects
@property
def left(self):
@ -1222,7 +1268,7 @@ class Schema(Expression):
arg_types = {"this": False, "expressions": True}
class Select(Subqueryable, Expression):
class Select(Subqueryable):
arg_types = {
"with": False,
"expressions": False,
@ -2075,7 +2121,7 @@ class Bracket(Condition):
class Distinct(Expression):
arg_types = {"this": False, "on": False}
arg_types = {"expressions": False, "on": False}
class In(Predicate):
@ -2233,6 +2279,14 @@ class Case(Func):
class Cast(Func):
arg_types = {"this": True, "to": True}
@property
def name(self):
return self.this.name
@property
def to(self):
return self.args["to"]
class TryCast(Cast):
pass
@ -2666,7 +2720,7 @@ def _norm_args(expression):
else:
arg = _norm_arg(arg)
if arg is not None:
if arg is not None and arg is not False:
args[k] = arg
return args
@ -3012,6 +3066,30 @@ def update(table, properties, where=None, from_=None, dialect=None, **opts):
return update
def delete(table, where=None, dialect=None, **opts):
"""
Builds a delete statement.
Example:
>>> delete("my_table", where="id > 1").sql()
'DELETE FROM my_table WHERE id > 1'
Args:
where (str|Condition): sql conditional parsed into a WHERE statement
dialect (str): the dialect used to parse the input expressions.
**opts: other options to use to parse the input expressions.
Returns:
Delete: the syntax tree for the DELETE statement.
"""
return Delete(
this=maybe_parse(table, into=Table, dialect=dialect, **opts),
where=Where(this=where)
if isinstance(where, Condition)
else maybe_parse(where, into=Where, dialect=dialect, prefix="WHERE", **opts),
)
def condition(expression, dialect=None, **opts):
"""
Initialize a logical condition expression.
@ -3131,6 +3209,25 @@ def to_identifier(alias, quoted=None):
return identifier
def to_table(sql_path, **kwargs):
"""
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'
Args:
sql_path(str): `[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
]
return Table(this=table_name, db=db, catalog=catalog, **kwargs)
def alias_(expression, alias, table=False, dialect=None, quoted=None, **opts):
"""
Create an Alias expression.
@ -3216,6 +3313,28 @@ def table_(table, db=None, catalog=None, quoted=None):
)
def values(values, alias=None):
"""Build VALUES statement.
Example:
>>> values([(1, '2')]).sql()
"VALUES (1, '2')"
Args:
values (list[tuple[str | Expression]]): values statements that will be converted to SQL
alias (str): optional alias
dialect (str): the dialect used to parse the input expression.
**opts: other options to use to parse the input expressions.
Returns:
Values: the Values expression object
"""
return Values(
expressions=[convert(tup) for tup in values],
alias=to_identifier(alias) if alias else None,
)
def convert(value):
"""Convert a python value into an expression object.
@ -3246,6 +3365,12 @@ def convert(value):
keys=[convert(k) for k in value.keys()],
values=[convert(v) for v in value.values()],
)
if isinstance(value, datetime.datetime):
datetime_literal = Literal.string(value.strftime("%Y-%m-%d %H:%M:%S"))
return TimeStrToTime(this=datetime_literal)
if isinstance(value, datetime.date):
date_literal = Literal.string(value.strftime("%Y-%m-%d"))
return DateStrToDate(this=date_literal)
raise ValueError(f"Cannot convert {value}")