Merging upstream version 11.1.3.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
8c1c1864c5
commit
fb546b57e5
95 changed files with 32569 additions and 30081 deletions
|
@ -1,19 +1,16 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import re
|
||||
import typing as t
|
||||
|
||||
from sqlglot import exp
|
||||
from sqlglot.errors import ErrorLevel, UnsupportedError, concat_messages
|
||||
from sqlglot.helper import apply_index_offset, csv
|
||||
from sqlglot.helper import apply_index_offset, csv, seq_get
|
||||
from sqlglot.time import format_time
|
||||
from sqlglot.tokens import TokenType
|
||||
|
||||
logger = logging.getLogger("sqlglot")
|
||||
|
||||
BACKSLASH_RE = re.compile(r"\\(?!b|f|n|r|t|0)")
|
||||
|
||||
|
||||
class Generator:
|
||||
"""
|
||||
|
@ -59,10 +56,14 @@ class Generator:
|
|||
"""
|
||||
|
||||
TRANSFORMS = {
|
||||
exp.DateAdd: lambda self, e: f"DATE_ADD({self.format_args(e.this, e.expression, e.args.get('unit'))})",
|
||||
exp.DateDiff: lambda self, e: f"DATEDIFF({self.format_args(e.this, e.expression)})",
|
||||
exp.TsOrDsAdd: lambda self, e: f"TS_OR_DS_ADD({self.format_args(e.this, e.expression, e.args.get('unit'))})",
|
||||
exp.VarMap: lambda self, e: f"MAP({self.format_args(e.args['keys'], e.args['values'])})",
|
||||
exp.DateAdd: lambda self, e: self.func(
|
||||
"DATE_ADD", e.this, e.expression, e.args.get("unit")
|
||||
),
|
||||
exp.DateDiff: lambda self, e: self.func("DATEDIFF", e.this, e.expression),
|
||||
exp.TsOrDsAdd: lambda self, e: self.func(
|
||||
"TS_OR_DS_ADD", e.this, e.expression, e.args.get("unit")
|
||||
),
|
||||
exp.VarMap: lambda self, e: self.func("MAP", e.args["keys"], e.args["values"]),
|
||||
exp.CharacterSetProperty: lambda self, e: f"{'DEFAULT ' if e.args['default'] else ''}CHARACTER SET={self.sql(e, 'this')}",
|
||||
exp.LanguageProperty: lambda self, e: self.naked_property(e),
|
||||
exp.LocationProperty: lambda self, e: self.naked_property(e),
|
||||
|
@ -72,6 +73,17 @@ class Generator:
|
|||
exp.WithJournalTableProperty: lambda self, e: f"WITH JOURNAL TABLE={self.sql(e, 'this')}",
|
||||
exp.LogProperty: lambda self, e: f"{'NO ' if e.args.get('no') else ''}LOG",
|
||||
exp.SqlSecurityProperty: lambda self, e: f"SQL SECURITY {'DEFINER' if e.args.get('definer') else 'INVOKER'}",
|
||||
exp.CaseSpecificColumnConstraint: lambda self, e: f"{'NOT ' if e.args.get('not_') else ''}CASESPECIFIC",
|
||||
exp.CharacterSetColumnConstraint: lambda self, e: f"CHARACTER SET {self.sql(e, 'this')}",
|
||||
exp.DateFormatColumnConstraint: lambda self, e: f"FORMAT {self.sql(e, 'this')}",
|
||||
exp.UppercaseColumnConstraint: lambda self, e: f"UPPERCASE",
|
||||
exp.TitleColumnConstraint: lambda self, e: f"TITLE {self.sql(e, 'this')}",
|
||||
exp.PathColumnConstraint: lambda self, e: f"PATH {self.sql(e, 'this')}",
|
||||
exp.CheckColumnConstraint: lambda self, e: f"CHECK ({self.sql(e, 'this')})",
|
||||
exp.CommentColumnConstraint: lambda self, e: f"COMMENT {self.sql(e, 'this')}",
|
||||
exp.CollateColumnConstraint: lambda self, e: f"COLLATE {self.sql(e, 'this')}",
|
||||
exp.EncodeColumnConstraint: lambda self, e: f"ENCODE {self.sql(e, 'this')}",
|
||||
exp.DefaultColumnConstraint: lambda self, e: f"DEFAULT {self.sql(e, 'this')}",
|
||||
}
|
||||
|
||||
# Whether 'CREATE ... TRANSIENT ... TABLE' is allowed
|
||||
|
@ -89,8 +101,8 @@ class Generator:
|
|||
# Wrap derived values in parens, usually standard but spark doesn't support it
|
||||
WRAP_DERIVED_VALUES = True
|
||||
|
||||
# Whether or not create function uses an AS before the def.
|
||||
CREATE_FUNCTION_AS = True
|
||||
# Whether or not create function uses an AS before the RETURN
|
||||
CREATE_FUNCTION_RETURN_AS = True
|
||||
|
||||
TYPE_MAPPING = {
|
||||
exp.DataType.Type.NCHAR: "CHAR",
|
||||
|
@ -110,42 +122,46 @@ class Generator:
|
|||
|
||||
STRUCT_DELIMITER = ("<", ">")
|
||||
|
||||
PARAMETER_TOKEN = "@"
|
||||
|
||||
PROPERTIES_LOCATION = {
|
||||
exp.AfterJournalProperty: exp.Properties.Location.PRE_SCHEMA,
|
||||
exp.AfterJournalProperty: exp.Properties.Location.POST_NAME,
|
||||
exp.AlgorithmProperty: exp.Properties.Location.POST_CREATE,
|
||||
exp.AutoIncrementProperty: exp.Properties.Location.POST_SCHEMA_ROOT,
|
||||
exp.BlockCompressionProperty: exp.Properties.Location.PRE_SCHEMA,
|
||||
exp.CharacterSetProperty: exp.Properties.Location.POST_SCHEMA_ROOT,
|
||||
exp.ChecksumProperty: exp.Properties.Location.PRE_SCHEMA,
|
||||
exp.CollateProperty: exp.Properties.Location.POST_SCHEMA_ROOT,
|
||||
exp.DataBlocksizeProperty: exp.Properties.Location.PRE_SCHEMA,
|
||||
exp.AutoIncrementProperty: exp.Properties.Location.POST_SCHEMA,
|
||||
exp.BlockCompressionProperty: exp.Properties.Location.POST_NAME,
|
||||
exp.CharacterSetProperty: exp.Properties.Location.POST_SCHEMA,
|
||||
exp.ChecksumProperty: exp.Properties.Location.POST_NAME,
|
||||
exp.CollateProperty: exp.Properties.Location.POST_SCHEMA,
|
||||
exp.Cluster: exp.Properties.Location.POST_SCHEMA,
|
||||
exp.DataBlocksizeProperty: exp.Properties.Location.POST_NAME,
|
||||
exp.DefinerProperty: exp.Properties.Location.POST_CREATE,
|
||||
exp.DistKeyProperty: exp.Properties.Location.POST_SCHEMA_ROOT,
|
||||
exp.DistStyleProperty: exp.Properties.Location.POST_SCHEMA_ROOT,
|
||||
exp.EngineProperty: exp.Properties.Location.POST_SCHEMA_ROOT,
|
||||
exp.ExecuteAsProperty: exp.Properties.Location.POST_SCHEMA_ROOT,
|
||||
exp.FallbackProperty: exp.Properties.Location.PRE_SCHEMA,
|
||||
exp.FileFormatProperty: exp.Properties.Location.POST_SCHEMA_WITH,
|
||||
exp.FreespaceProperty: exp.Properties.Location.PRE_SCHEMA,
|
||||
exp.IsolatedLoadingProperty: exp.Properties.Location.PRE_SCHEMA,
|
||||
exp.JournalProperty: exp.Properties.Location.PRE_SCHEMA,
|
||||
exp.LanguageProperty: exp.Properties.Location.POST_SCHEMA_ROOT,
|
||||
exp.LikeProperty: exp.Properties.Location.POST_SCHEMA_ROOT,
|
||||
exp.LocationProperty: exp.Properties.Location.POST_SCHEMA_ROOT,
|
||||
exp.LogProperty: exp.Properties.Location.PRE_SCHEMA,
|
||||
exp.MergeBlockRatioProperty: exp.Properties.Location.PRE_SCHEMA,
|
||||
exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA_WITH,
|
||||
exp.Property: exp.Properties.Location.POST_SCHEMA_WITH,
|
||||
exp.ReturnsProperty: exp.Properties.Location.POST_SCHEMA_ROOT,
|
||||
exp.RowFormatDelimitedProperty: exp.Properties.Location.POST_SCHEMA_ROOT,
|
||||
exp.RowFormatSerdeProperty: exp.Properties.Location.POST_SCHEMA_ROOT,
|
||||
exp.SchemaCommentProperty: exp.Properties.Location.POST_SCHEMA_ROOT,
|
||||
exp.SerdeProperties: exp.Properties.Location.POST_SCHEMA_ROOT,
|
||||
exp.SortKeyProperty: exp.Properties.Location.POST_SCHEMA_ROOT,
|
||||
exp.DistKeyProperty: exp.Properties.Location.POST_SCHEMA,
|
||||
exp.DistStyleProperty: exp.Properties.Location.POST_SCHEMA,
|
||||
exp.EngineProperty: exp.Properties.Location.POST_SCHEMA,
|
||||
exp.ExecuteAsProperty: exp.Properties.Location.POST_SCHEMA,
|
||||
exp.FallbackProperty: exp.Properties.Location.POST_NAME,
|
||||
exp.FileFormatProperty: exp.Properties.Location.POST_WITH,
|
||||
exp.FreespaceProperty: exp.Properties.Location.POST_NAME,
|
||||
exp.IsolatedLoadingProperty: exp.Properties.Location.POST_NAME,
|
||||
exp.JournalProperty: exp.Properties.Location.POST_NAME,
|
||||
exp.LanguageProperty: exp.Properties.Location.POST_SCHEMA,
|
||||
exp.LikeProperty: exp.Properties.Location.POST_SCHEMA,
|
||||
exp.LocationProperty: exp.Properties.Location.POST_SCHEMA,
|
||||
exp.LockingProperty: exp.Properties.Location.POST_ALIAS,
|
||||
exp.LogProperty: exp.Properties.Location.POST_NAME,
|
||||
exp.MergeBlockRatioProperty: exp.Properties.Location.POST_NAME,
|
||||
exp.PartitionedByProperty: exp.Properties.Location.POST_WITH,
|
||||
exp.Property: exp.Properties.Location.POST_WITH,
|
||||
exp.ReturnsProperty: exp.Properties.Location.POST_SCHEMA,
|
||||
exp.RowFormatDelimitedProperty: exp.Properties.Location.POST_SCHEMA,
|
||||
exp.RowFormatSerdeProperty: exp.Properties.Location.POST_SCHEMA,
|
||||
exp.SchemaCommentProperty: exp.Properties.Location.POST_SCHEMA,
|
||||
exp.SerdeProperties: exp.Properties.Location.POST_SCHEMA,
|
||||
exp.SortKeyProperty: exp.Properties.Location.POST_SCHEMA,
|
||||
exp.SqlSecurityProperty: exp.Properties.Location.POST_CREATE,
|
||||
exp.TableFormatProperty: exp.Properties.Location.POST_SCHEMA_WITH,
|
||||
exp.VolatilityProperty: exp.Properties.Location.POST_SCHEMA_ROOT,
|
||||
exp.WithJournalTableProperty: exp.Properties.Location.PRE_SCHEMA,
|
||||
exp.TableFormatProperty: exp.Properties.Location.POST_WITH,
|
||||
exp.VolatilityProperty: exp.Properties.Location.POST_SCHEMA,
|
||||
exp.WithJournalTableProperty: exp.Properties.Location.POST_NAME,
|
||||
}
|
||||
|
||||
WITH_SEPARATED_COMMENTS = (exp.Select, exp.From, exp.Where, exp.Binary)
|
||||
|
@ -173,7 +189,6 @@ class Generator:
|
|||
"null_ordering",
|
||||
"max_unsupported",
|
||||
"_indent",
|
||||
"_replace_backslash",
|
||||
"_escaped_quote_end",
|
||||
"_escaped_identifier_end",
|
||||
"_leading_comma",
|
||||
|
@ -230,7 +245,6 @@ class Generator:
|
|||
self.max_unsupported = max_unsupported
|
||||
self.null_ordering = null_ordering
|
||||
self._indent = indent
|
||||
self._replace_backslash = self.string_escape == "\\"
|
||||
self._escaped_quote_end = self.string_escape + self.quote_end
|
||||
self._escaped_identifier_end = self.identifier_escape + self.identifier_end
|
||||
self._leading_comma = leading_comma
|
||||
|
@ -403,12 +417,13 @@ class Generator:
|
|||
|
||||
def column_sql(self, expression: exp.Column) -> str:
|
||||
return ".".join(
|
||||
part
|
||||
for part in [
|
||||
self.sql(expression, "db"),
|
||||
self.sql(expression, "table"),
|
||||
self.sql(expression, "this"),
|
||||
]
|
||||
self.sql(part)
|
||||
for part in (
|
||||
expression.args.get("catalog"),
|
||||
expression.args.get("db"),
|
||||
expression.args.get("table"),
|
||||
expression.args.get("this"),
|
||||
)
|
||||
if part
|
||||
)
|
||||
|
||||
|
@ -430,26 +445,6 @@ class Generator:
|
|||
def autoincrementcolumnconstraint_sql(self, _) -> str:
|
||||
return self.token_sql(TokenType.AUTO_INCREMENT)
|
||||
|
||||
def checkcolumnconstraint_sql(self, expression: exp.CheckColumnConstraint) -> str:
|
||||
this = self.sql(expression, "this")
|
||||
return f"CHECK ({this})"
|
||||
|
||||
def commentcolumnconstraint_sql(self, expression: exp.CommentColumnConstraint) -> str:
|
||||
comment = self.sql(expression, "this")
|
||||
return f"COMMENT {comment}"
|
||||
|
||||
def collatecolumnconstraint_sql(self, expression: exp.CollateColumnConstraint) -> str:
|
||||
collate = self.sql(expression, "this")
|
||||
return f"COLLATE {collate}"
|
||||
|
||||
def encodecolumnconstraint_sql(self, expression: exp.EncodeColumnConstraint) -> str:
|
||||
encode = self.sql(expression, "this")
|
||||
return f"ENCODE {encode}"
|
||||
|
||||
def defaultcolumnconstraint_sql(self, expression: exp.DefaultColumnConstraint) -> str:
|
||||
default = self.sql(expression, "this")
|
||||
return f"DEFAULT {default}"
|
||||
|
||||
def generatedasidentitycolumnconstraint_sql(
|
||||
self, expression: exp.GeneratedAsIdentityColumnConstraint
|
||||
) -> str:
|
||||
|
@ -459,10 +454,19 @@ class Generator:
|
|||
start = expression.args.get("start")
|
||||
start = f"START WITH {start}" if start else ""
|
||||
increment = expression.args.get("increment")
|
||||
increment = f"INCREMENT BY {increment}" if increment else ""
|
||||
increment = f" INCREMENT BY {increment}" if increment else ""
|
||||
minvalue = expression.args.get("minvalue")
|
||||
minvalue = f" MINVALUE {minvalue}" if minvalue else ""
|
||||
maxvalue = expression.args.get("maxvalue")
|
||||
maxvalue = f" MAXVALUE {maxvalue}" if maxvalue else ""
|
||||
cycle = expression.args.get("cycle")
|
||||
cycle_sql = ""
|
||||
if cycle is not None:
|
||||
cycle_sql = f"{' NO' if not cycle else ''} CYCLE"
|
||||
cycle_sql = cycle_sql.strip() if not start and not increment else cycle_sql
|
||||
sequence_opts = ""
|
||||
if start or increment:
|
||||
sequence_opts = f"{start} {increment}"
|
||||
if start or increment or cycle_sql:
|
||||
sequence_opts = f"{start}{increment}{minvalue}{maxvalue}{cycle_sql}"
|
||||
sequence_opts = f" ({sequence_opts.strip()})"
|
||||
return f"GENERATED{this}AS IDENTITY{sequence_opts}"
|
||||
|
||||
|
@ -483,22 +487,22 @@ class Generator:
|
|||
properties = expression.args.get("properties")
|
||||
properties_exp = expression.copy()
|
||||
properties_locs = self.locate_properties(properties) if properties else {}
|
||||
if properties_locs.get(exp.Properties.Location.POST_SCHEMA_ROOT) or properties_locs.get(
|
||||
exp.Properties.Location.POST_SCHEMA_WITH
|
||||
if properties_locs.get(exp.Properties.Location.POST_SCHEMA) or properties_locs.get(
|
||||
exp.Properties.Location.POST_WITH
|
||||
):
|
||||
properties_exp.set(
|
||||
"properties",
|
||||
exp.Properties(
|
||||
expressions=[
|
||||
*properties_locs[exp.Properties.Location.POST_SCHEMA_ROOT],
|
||||
*properties_locs[exp.Properties.Location.POST_SCHEMA_WITH],
|
||||
*properties_locs[exp.Properties.Location.POST_SCHEMA],
|
||||
*properties_locs[exp.Properties.Location.POST_WITH],
|
||||
]
|
||||
),
|
||||
)
|
||||
if kind == "TABLE" and properties_locs.get(exp.Properties.Location.PRE_SCHEMA):
|
||||
if kind == "TABLE" and properties_locs.get(exp.Properties.Location.POST_NAME):
|
||||
this_name = self.sql(expression.this, "this")
|
||||
this_properties = self.properties(
|
||||
exp.Properties(expressions=properties_locs[exp.Properties.Location.PRE_SCHEMA]),
|
||||
exp.Properties(expressions=properties_locs[exp.Properties.Location.POST_NAME]),
|
||||
wrapped=False,
|
||||
)
|
||||
this_schema = f"({self.expressions(expression.this)})"
|
||||
|
@ -512,8 +516,17 @@ class Generator:
|
|||
if expression_sql:
|
||||
expression_sql = f"{begin}{self.sep()}{expression_sql}"
|
||||
|
||||
if self.CREATE_FUNCTION_AS or kind != "FUNCTION":
|
||||
expression_sql = f" AS{expression_sql}"
|
||||
if self.CREATE_FUNCTION_RETURN_AS or not isinstance(expression.expression, exp.Return):
|
||||
if properties_locs.get(exp.Properties.Location.POST_ALIAS):
|
||||
postalias_props_sql = self.properties(
|
||||
exp.Properties(
|
||||
expressions=properties_locs[exp.Properties.Location.POST_ALIAS]
|
||||
),
|
||||
wrapped=False,
|
||||
)
|
||||
expression_sql = f" AS {postalias_props_sql}{expression_sql}"
|
||||
else:
|
||||
expression_sql = f" AS{expression_sql}"
|
||||
|
||||
temporary = " TEMPORARY" if expression.args.get("temporary") else ""
|
||||
transient = (
|
||||
|
@ -736,9 +749,9 @@ class Generator:
|
|||
|
||||
for p in expression.expressions:
|
||||
p_loc = self.PROPERTIES_LOCATION[p.__class__]
|
||||
if p_loc == exp.Properties.Location.POST_SCHEMA_WITH:
|
||||
if p_loc == exp.Properties.Location.POST_WITH:
|
||||
with_properties.append(p)
|
||||
elif p_loc == exp.Properties.Location.POST_SCHEMA_ROOT:
|
||||
elif p_loc == exp.Properties.Location.POST_SCHEMA:
|
||||
root_properties.append(p)
|
||||
|
||||
return self.root_properties(
|
||||
|
@ -776,16 +789,18 @@ class Generator:
|
|||
|
||||
for p in properties.expressions:
|
||||
p_loc = self.PROPERTIES_LOCATION[p.__class__]
|
||||
if p_loc == exp.Properties.Location.PRE_SCHEMA:
|
||||
properties_locs[exp.Properties.Location.PRE_SCHEMA].append(p)
|
||||
if p_loc == exp.Properties.Location.POST_NAME:
|
||||
properties_locs[exp.Properties.Location.POST_NAME].append(p)
|
||||
elif p_loc == exp.Properties.Location.POST_INDEX:
|
||||
properties_locs[exp.Properties.Location.POST_INDEX].append(p)
|
||||
elif p_loc == exp.Properties.Location.POST_SCHEMA_ROOT:
|
||||
properties_locs[exp.Properties.Location.POST_SCHEMA_ROOT].append(p)
|
||||
elif p_loc == exp.Properties.Location.POST_SCHEMA_WITH:
|
||||
properties_locs[exp.Properties.Location.POST_SCHEMA_WITH].append(p)
|
||||
elif p_loc == exp.Properties.Location.POST_SCHEMA:
|
||||
properties_locs[exp.Properties.Location.POST_SCHEMA].append(p)
|
||||
elif p_loc == exp.Properties.Location.POST_WITH:
|
||||
properties_locs[exp.Properties.Location.POST_WITH].append(p)
|
||||
elif p_loc == exp.Properties.Location.POST_CREATE:
|
||||
properties_locs[exp.Properties.Location.POST_CREATE].append(p)
|
||||
elif p_loc == exp.Properties.Location.POST_ALIAS:
|
||||
properties_locs[exp.Properties.Location.POST_ALIAS].append(p)
|
||||
elif p_loc == exp.Properties.Location.UNSUPPORTED:
|
||||
self.unsupported(f"Unsupported property {p.key}")
|
||||
|
||||
|
@ -899,6 +914,14 @@ class Generator:
|
|||
for_ = " FOR NONE"
|
||||
return f"WITH{no}{concurrent} ISOLATED LOADING{for_}"
|
||||
|
||||
def lockingproperty_sql(self, expression: exp.LockingProperty) -> str:
|
||||
kind = expression.args.get("kind")
|
||||
this: str = f" {this}" if expression.this else ""
|
||||
for_or_in = expression.args.get("for_or_in")
|
||||
lock_type = expression.args.get("lock_type")
|
||||
override = " OVERRIDE" if expression.args.get("override") else ""
|
||||
return f"LOCKING {kind}{this} {for_or_in} {lock_type}{override}"
|
||||
|
||||
def insert_sql(self, expression: exp.Insert) -> str:
|
||||
overwrite = expression.args.get("overwrite")
|
||||
|
||||
|
@ -907,14 +930,17 @@ class Generator:
|
|||
else:
|
||||
this = "OVERWRITE TABLE " if overwrite else "INTO "
|
||||
|
||||
alternative = expression.args.get("alternative")
|
||||
alternative = f" OR {alternative} " if alternative else " "
|
||||
this = f"{this}{self.sql(expression, 'this')}"
|
||||
|
||||
exists = " IF EXISTS " if expression.args.get("exists") else " "
|
||||
partition_sql = (
|
||||
self.sql(expression, "partition") if expression.args.get("partition") else ""
|
||||
)
|
||||
expression_sql = self.sql(expression, "expression")
|
||||
sep = self.sep() if partition_sql else ""
|
||||
sql = f"INSERT {this}{exists}{partition_sql}{sep}{expression_sql}"
|
||||
sql = f"INSERT{alternative}{this}{exists}{partition_sql}{sep}{expression_sql}"
|
||||
return self.prepend_ctes(expression, sql)
|
||||
|
||||
def intersect_sql(self, expression: exp.Intersect) -> str:
|
||||
|
@ -1046,21 +1072,26 @@ class Generator:
|
|||
f"{self.seg('GROUPING SETS')} {self.wrap(grouping_sets)}" if grouping_sets else ""
|
||||
)
|
||||
|
||||
cube = expression.args.get("cube")
|
||||
if cube is True:
|
||||
cube = self.seg("WITH CUBE")
|
||||
cube = expression.args.get("cube", [])
|
||||
if seq_get(cube, 0) is True:
|
||||
return f"{group_by}{self.seg('WITH CUBE')}"
|
||||
else:
|
||||
cube = self.expressions(expression, key="cube", indent=False)
|
||||
cube = f"{self.seg('CUBE')} {self.wrap(cube)}" if cube else ""
|
||||
cube_sql = self.expressions(expression, key="cube", indent=False)
|
||||
cube_sql = f"{self.seg('CUBE')} {self.wrap(cube_sql)}" if cube_sql else ""
|
||||
|
||||
rollup = expression.args.get("rollup")
|
||||
if rollup is True:
|
||||
rollup = self.seg("WITH ROLLUP")
|
||||
rollup = expression.args.get("rollup", [])
|
||||
if seq_get(rollup, 0) is True:
|
||||
return f"{group_by}{self.seg('WITH ROLLUP')}"
|
||||
else:
|
||||
rollup = self.expressions(expression, key="rollup", indent=False)
|
||||
rollup = f"{self.seg('ROLLUP')} {self.wrap(rollup)}" if rollup else ""
|
||||
rollup_sql = self.expressions(expression, key="rollup", indent=False)
|
||||
rollup_sql = f"{self.seg('ROLLUP')} {self.wrap(rollup_sql)}" if rollup_sql else ""
|
||||
|
||||
return f"{group_by}{csv(grouping_sets, cube, rollup, sep=',')}"
|
||||
groupings = csv(grouping_sets, cube_sql, rollup_sql, sep=",")
|
||||
|
||||
if expression.args.get("expressions") and groupings:
|
||||
group_by = f"{group_by},"
|
||||
|
||||
return f"{group_by}{groupings}"
|
||||
|
||||
def having_sql(self, expression: exp.Having) -> str:
|
||||
this = self.indent(self.sql(expression, "this"))
|
||||
|
@ -1139,8 +1170,6 @@ class Generator:
|
|||
def literal_sql(self, expression: exp.Literal) -> str:
|
||||
text = expression.this or ""
|
||||
if expression.is_string:
|
||||
if self._replace_backslash:
|
||||
text = BACKSLASH_RE.sub(r"\\\\", text)
|
||||
text = text.replace(self.quote_end, self._escaped_quote_end)
|
||||
if self.pretty:
|
||||
text = text.replace("\n", self.SENTINEL_LINE_BREAK)
|
||||
|
@ -1291,7 +1320,9 @@ class Generator:
|
|||
return f"{self.sql(expression, 'this')} {self.sql(expression, 'expression')}"
|
||||
|
||||
def parameter_sql(self, expression: exp.Parameter) -> str:
|
||||
return f"@{self.sql(expression, 'this')}"
|
||||
this = self.sql(expression, "this")
|
||||
this = f"{{{this}}}" if expression.args.get("wrapped") else f"{this}"
|
||||
return f"{self.PARAMETER_TOKEN}{this}"
|
||||
|
||||
def sessionparameter_sql(self, expression: exp.SessionParameter) -> str:
|
||||
this = self.sql(expression, "this")
|
||||
|
@ -1405,7 +1436,10 @@ class Generator:
|
|||
return f"ALL {self.wrap(expression)}"
|
||||
|
||||
def any_sql(self, expression: exp.Any) -> str:
|
||||
return f"ANY {self.wrap(expression)}"
|
||||
this = self.sql(expression, "this")
|
||||
if isinstance(expression.this, exp.Subqueryable):
|
||||
this = self.wrap(this)
|
||||
return f"ANY {this}"
|
||||
|
||||
def exists_sql(self, expression: exp.Exists) -> str:
|
||||
return f"EXISTS{self.wrap(expression)}"
|
||||
|
@ -1444,11 +1478,11 @@ class Generator:
|
|||
trim_type = self.sql(expression, "position")
|
||||
|
||||
if trim_type == "LEADING":
|
||||
return f"{self.normalize_func('LTRIM')}({self.format_args(expression.this)})"
|
||||
return self.func("LTRIM", expression.this)
|
||||
elif trim_type == "TRAILING":
|
||||
return f"{self.normalize_func('RTRIM')}({self.format_args(expression.this)})"
|
||||
return self.func("RTRIM", expression.this)
|
||||
else:
|
||||
return f"{self.normalize_func('TRIM')}({self.format_args(expression.this, expression.expression)})"
|
||||
return self.func("TRIM", expression.this, expression.expression)
|
||||
|
||||
def concat_sql(self, expression: exp.Concat) -> str:
|
||||
if len(expression.expressions) == 1:
|
||||
|
@ -1530,8 +1564,7 @@ class Generator:
|
|||
return f"REFERENCES {this}{expressions}{options}"
|
||||
|
||||
def anonymous_sql(self, expression: exp.Anonymous) -> str:
|
||||
args = self.format_args(*expression.expressions)
|
||||
return f"{self.normalize_func(self.sql(expression, 'this'))}({args})"
|
||||
return self.func(expression.name, *expression.expressions)
|
||||
|
||||
def paren_sql(self, expression: exp.Paren) -> str:
|
||||
if isinstance(expression.unnest(), exp.Select):
|
||||
|
@ -1792,7 +1825,10 @@ class Generator:
|
|||
else:
|
||||
args.append(arg_value)
|
||||
|
||||
return f"{self.normalize_func(expression.sql_name())}({self.format_args(*args)})"
|
||||
return self.func(expression.sql_name(), *args)
|
||||
|
||||
def func(self, name: str, *args: t.Optional[exp.Expression | str]) -> str:
|
||||
return f"{self.normalize_func(name)}({self.format_args(*args)})"
|
||||
|
||||
def format_args(self, *args: t.Optional[str | exp.Expression]) -> str:
|
||||
arg_sqls = tuple(self.sql(arg) for arg in args if arg is not None)
|
||||
|
@ -1848,6 +1884,7 @@ class Generator:
|
|||
return self.indent(result_sql, skip_first=False) if indent else result_sql
|
||||
|
||||
def op_expressions(self, op: str, expression: exp.Expression, flat: bool = False) -> str:
|
||||
flat = flat or isinstance(expression.parent, exp.Properties)
|
||||
expressions_sql = self.expressions(expression, flat=flat)
|
||||
if flat:
|
||||
return f"{op} {expressions_sql}"
|
||||
|
@ -1880,11 +1917,6 @@ class Generator:
|
|||
)
|
||||
return f"{this}{expressions}"
|
||||
|
||||
def userdefinedfunctionkwarg_sql(self, expression: exp.UserDefinedFunctionKwarg) -> str:
|
||||
this = self.sql(expression, "this")
|
||||
kind = self.sql(expression, "kind")
|
||||
return f"{this} {kind}"
|
||||
|
||||
def joinhint_sql(self, expression: exp.JoinHint) -> str:
|
||||
this = self.sql(expression, "this")
|
||||
expressions = self.expressions(expression, flat=True)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue