Adding upstream version 25.21.3.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
0b78a18345
commit
cfe8a51f10
105 changed files with 50314 additions and 49385 deletions
|
@ -4,7 +4,7 @@ import logging
|
|||
import re
|
||||
import typing as t
|
||||
from collections import defaultdict
|
||||
from functools import reduce
|
||||
from functools import reduce, wraps
|
||||
|
||||
from sqlglot import exp
|
||||
from sqlglot.errors import ErrorLevel, UnsupportedError, concat_messages
|
||||
|
@ -17,9 +17,47 @@ if t.TYPE_CHECKING:
|
|||
from sqlglot._typing import E
|
||||
from sqlglot.dialects.dialect import DialectType
|
||||
|
||||
G = t.TypeVar("G", bound="Generator")
|
||||
GeneratorMethod = t.Callable[[G, E], str]
|
||||
|
||||
logger = logging.getLogger("sqlglot")
|
||||
|
||||
ESCAPED_UNICODE_RE = re.compile(r"\\(\d+)")
|
||||
UNSUPPORTED_TEMPLATE = "Argument '{}' is not supported for expression '{}' when targeting {}."
|
||||
|
||||
|
||||
def unsupported_args(
|
||||
*args: t.Union[str, t.Tuple[str, str]],
|
||||
) -> t.Callable[[GeneratorMethod], GeneratorMethod]:
|
||||
"""
|
||||
Decorator that can be used to mark certain args of an `Expression` subclass as unsupported.
|
||||
It expects a sequence of argument names or pairs of the form (argument_name, diagnostic_msg).
|
||||
"""
|
||||
diagnostic_by_arg: t.Dict[str, t.Optional[str]] = {}
|
||||
for arg in args:
|
||||
if isinstance(arg, str):
|
||||
diagnostic_by_arg[arg] = None
|
||||
else:
|
||||
diagnostic_by_arg[arg[0]] = arg[1]
|
||||
|
||||
def decorator(func: GeneratorMethod) -> GeneratorMethod:
|
||||
@wraps(func)
|
||||
def _func(generator: G, expression: E) -> str:
|
||||
expression_name = expression.__class__.__name__
|
||||
dialect_name = generator.dialect.__class__.__name__
|
||||
|
||||
for arg_name, diagnostic in diagnostic_by_arg.items():
|
||||
if expression.args.get(arg_name):
|
||||
diagnostic = diagnostic or UNSUPPORTED_TEMPLATE.format(
|
||||
arg_name, expression_name, dialect_name
|
||||
)
|
||||
generator.unsupported(diagnostic)
|
||||
|
||||
return func(generator, expression)
|
||||
|
||||
return _func
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
class _Generator(type):
|
||||
|
@ -154,6 +192,8 @@ class Generator(metaclass=_Generator):
|
|||
exp.TransientProperty: lambda *_: "TRANSIENT",
|
||||
exp.Union: lambda self, e: self.set_operations(e),
|
||||
exp.UnloggedProperty: lambda *_: "UNLOGGED",
|
||||
exp.UnpackColumns: lambda self, e: f"*{self.sql(e.this)}",
|
||||
exp.Uuid: lambda *_: "UUID()",
|
||||
exp.UppercaseColumnConstraint: lambda *_: "UPPERCASE",
|
||||
exp.VarMap: lambda self, e: self.func("MAP", e.args["keys"], e.args["values"]),
|
||||
exp.ViewAttributeProperty: lambda self, e: f"WITH {self.sql(e, 'this')}",
|
||||
|
@ -389,9 +429,6 @@ class Generator(metaclass=_Generator):
|
|||
# Whether CONVERT_TIMEZONE() is supported; if not, it will be generated as exp.AtTimeZone
|
||||
SUPPORTS_CONVERT_TIMEZONE = False
|
||||
|
||||
# Whether nullable types can be constructed, e.g. `Nullable(Int64)`
|
||||
SUPPORTS_NULLABLE_TYPES = True
|
||||
|
||||
# The name to generate for the JSONPath expression. If `None`, only `this` will be generated
|
||||
PARSE_JSON_NAME: t.Optional[str] = "PARSE_JSON"
|
||||
|
||||
|
@ -1238,14 +1275,12 @@ class Generator(metaclass=_Generator):
|
|||
type_value = expression.this
|
||||
if type_value == exp.DataType.Type.USERDEFINED and expression.args.get("kind"):
|
||||
type_sql = self.sql(expression, "kind")
|
||||
elif type_value != exp.DataType.Type.NULLABLE or self.SUPPORTS_NULLABLE_TYPES:
|
||||
else:
|
||||
type_sql = (
|
||||
self.TYPE_MAPPING.get(type_value, type_value.value)
|
||||
if isinstance(type_value, exp.DataType.Type)
|
||||
else type_value
|
||||
)
|
||||
else:
|
||||
return interior
|
||||
|
||||
if interior:
|
||||
if expression.args.get("nested"):
|
||||
|
@ -1279,15 +1314,17 @@ class Generator(metaclass=_Generator):
|
|||
this = f" FROM {this}" if this else ""
|
||||
using = self.sql(expression, "using")
|
||||
using = f" USING {using}" if using else ""
|
||||
cluster = self.sql(expression, "cluster")
|
||||
cluster = f" {cluster}" if cluster else ""
|
||||
where = self.sql(expression, "where")
|
||||
returning = self.sql(expression, "returning")
|
||||
limit = self.sql(expression, "limit")
|
||||
tables = self.expressions(expression, key="tables")
|
||||
tables = f" {tables}" if tables else ""
|
||||
if self.RETURNING_END:
|
||||
expression_sql = f"{this}{using}{where}{returning}{limit}"
|
||||
expression_sql = f"{this}{using}{cluster}{where}{returning}{limit}"
|
||||
else:
|
||||
expression_sql = f"{returning}{this}{using}{where}{limit}"
|
||||
expression_sql = f"{returning}{this}{using}{cluster}{where}{limit}"
|
||||
return self.prepend_ctes(expression, f"DELETE{tables}{expression_sql}")
|
||||
|
||||
def drop_sql(self, expression: exp.Drop) -> str:
|
||||
|
@ -1920,8 +1957,6 @@ class Generator(metaclass=_Generator):
|
|||
direction = self.seg("UNPIVOT" if expression.unpivot else "PIVOT")
|
||||
|
||||
field = self.sql(expression, "field")
|
||||
if field and isinstance(expression.args.get("field"), exp.PivotAny):
|
||||
field = f"IN ({field})"
|
||||
|
||||
include_nulls = expression.args.get("include_nulls")
|
||||
if include_nulls is not None:
|
||||
|
@ -2742,6 +2777,10 @@ class Generator(metaclass=_Generator):
|
|||
|
||||
def jsonpath_sql(self, expression: exp.JSONPath) -> str:
|
||||
path = self.expressions(expression, sep="", flat=True).lstrip(".")
|
||||
|
||||
if expression.args.get("escape"):
|
||||
path = self.escape_str(path)
|
||||
|
||||
if self.QUOTE_JSON_PATH:
|
||||
path = f"{self.dialect.QUOTE_START}{path}{self.dialect.QUOTE_END}"
|
||||
|
||||
|
@ -3587,15 +3626,16 @@ class Generator(metaclass=_Generator):
|
|||
on = f"ON {self.sql(expression, 'on')}"
|
||||
expressions = self.expressions(expression, sep=" ", indent=False)
|
||||
sep = self.sep()
|
||||
returning = self.expressions(expression, key="returning", indent=False)
|
||||
returning = f"RETURNING {returning}" if returning else ""
|
||||
|
||||
return self.prepend_ctes(
|
||||
expression, f"MERGE INTO {this}{table_alias}{sep}{using}{sep}{on}{sep}{expressions}"
|
||||
expression,
|
||||
f"MERGE INTO {this}{table_alias}{sep}{using}{sep}{on}{sep}{expressions}{sep}{returning}",
|
||||
)
|
||||
|
||||
@unsupported_args("format")
|
||||
def tochar_sql(self, expression: exp.ToChar) -> str:
|
||||
if expression.args.get("format"):
|
||||
self.unsupported("Format argument unsupported for TO_CHAR/TO_VARCHAR function")
|
||||
|
||||
return self.sql(exp.cast(expression.this, exp.DataType.Type.TEXT))
|
||||
|
||||
def tonumber_sql(self, expression: exp.ToNumber) -> str:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue