sqlglot 27.11.0__py3-none-any.whl → 27.13.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sqlglot/_version.py +2 -2
- sqlglot/dialects/bigquery.py +80 -32
- sqlglot/dialects/clickhouse.py +4 -0
- sqlglot/dialects/databricks.py +1 -0
- sqlglot/dialects/dialect.py +13 -1
- sqlglot/dialects/doris.py +2 -0
- sqlglot/dialects/dremio.py +4 -0
- sqlglot/dialects/duckdb.py +4 -1
- sqlglot/dialects/hive.py +11 -5
- sqlglot/dialects/mysql.py +11 -1
- sqlglot/dialects/oracle.py +4 -0
- sqlglot/dialects/postgres.py +1 -2
- sqlglot/dialects/singlestore.py +137 -2
- sqlglot/dialects/snowflake.py +34 -4
- sqlglot/dialects/spark.py +14 -0
- sqlglot/expressions.py +111 -7
- sqlglot/generator.py +36 -4
- sqlglot/optimizer/qualify_columns.py +18 -3
- sqlglot/parser.py +56 -22
- sqlglot/tokens.py +5 -0
- {sqlglot-27.11.0.dist-info → sqlglot-27.13.0.dist-info}/METADATA +1 -1
- {sqlglot-27.11.0.dist-info → sqlglot-27.13.0.dist-info}/RECORD +25 -25
- {sqlglot-27.11.0.dist-info → sqlglot-27.13.0.dist-info}/WHEEL +0 -0
- {sqlglot-27.11.0.dist-info → sqlglot-27.13.0.dist-info}/licenses/LICENSE +0 -0
- {sqlglot-27.11.0.dist-info → sqlglot-27.13.0.dist-info}/top_level.txt +0 -0
sqlglot/dialects/singlestore.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
1
3
|
from sqlglot import TokenType
|
|
2
4
|
import typing as t
|
|
3
5
|
|
|
@@ -20,11 +22,13 @@ from sqlglot.generator import unsupported_args
|
|
|
20
22
|
from sqlglot.helper import seq_get
|
|
21
23
|
|
|
22
24
|
|
|
23
|
-
def cast_to_time6(
|
|
25
|
+
def cast_to_time6(
|
|
26
|
+
expression: t.Optional[exp.Expression], time_type: DataType.Type = exp.DataType.Type.TIME
|
|
27
|
+
) -> exp.Cast:
|
|
24
28
|
return exp.Cast(
|
|
25
29
|
this=expression,
|
|
26
30
|
to=exp.DataType.build(
|
|
27
|
-
|
|
31
|
+
time_type,
|
|
28
32
|
expressions=[exp.DataTypeParam(this=exp.Literal.number(6))],
|
|
29
33
|
),
|
|
30
34
|
)
|
|
@@ -59,6 +63,9 @@ class SingleStore(MySQL):
|
|
|
59
63
|
"BSON": TokenType.JSONB,
|
|
60
64
|
"GEOGRAPHYPOINT": TokenType.GEOGRAPHYPOINT,
|
|
61
65
|
"TIMESTAMP": TokenType.TIMESTAMP,
|
|
66
|
+
"UTC_DATE": TokenType.UTC_DATE,
|
|
67
|
+
"UTC_TIME": TokenType.UTC_TIME,
|
|
68
|
+
"UTC_TIMESTAMP": TokenType.UTC_TIMESTAMP,
|
|
62
69
|
":>": TokenType.COLON_GT,
|
|
63
70
|
"!:>": TokenType.NCOLON_GT,
|
|
64
71
|
"::$": TokenType.DCOLONDOLLAR,
|
|
@@ -158,6 +165,8 @@ class SingleStore(MySQL):
|
|
|
158
165
|
json_type="JSON",
|
|
159
166
|
),
|
|
160
167
|
"JSON_PRETTY": exp.JSONFormat.from_arg_list,
|
|
168
|
+
"JSON_BUILD_ARRAY": lambda args: exp.JSONArray(expressions=args),
|
|
169
|
+
"JSON_BUILD_OBJECT": lambda args: exp.JSONObject(expressions=args),
|
|
161
170
|
"DATE": exp.Date.from_arg_list,
|
|
162
171
|
"DAYNAME": lambda args: exp.TimeToStr(
|
|
163
172
|
this=seq_get(args, 0),
|
|
@@ -195,6 +204,21 @@ class SingleStore(MySQL):
|
|
|
195
204
|
),
|
|
196
205
|
}
|
|
197
206
|
|
|
207
|
+
FUNCTION_PARSERS: t.Dict[str, t.Callable] = {
|
|
208
|
+
**MySQL.Parser.FUNCTION_PARSERS,
|
|
209
|
+
"JSON_AGG": lambda self: exp.JSONArrayAgg(
|
|
210
|
+
this=self._parse_term(),
|
|
211
|
+
order=self._parse_order(),
|
|
212
|
+
),
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
NO_PAREN_FUNCTIONS = {
|
|
216
|
+
**MySQL.Parser.NO_PAREN_FUNCTIONS,
|
|
217
|
+
TokenType.UTC_DATE: exp.UtcDate,
|
|
218
|
+
TokenType.UTC_TIME: exp.UtcTime,
|
|
219
|
+
TokenType.UTC_TIMESTAMP: exp.UtcTimestamp,
|
|
220
|
+
}
|
|
221
|
+
|
|
198
222
|
CAST_COLUMN_OPERATORS = {TokenType.COLON_GT, TokenType.NCOLON_GT}
|
|
199
223
|
|
|
200
224
|
COLUMN_OPERATORS = {
|
|
@@ -226,6 +250,17 @@ class SingleStore(MySQL):
|
|
|
226
250
|
COLUMN_OPERATORS.pop(TokenType.PLACEHOLDER)
|
|
227
251
|
|
|
228
252
|
class Generator(MySQL.Generator):
|
|
253
|
+
SUPPORTS_UESCAPE = False
|
|
254
|
+
NULL_ORDERING_SUPPORTED = True
|
|
255
|
+
MATCH_AGAINST_TABLE_PREFIX = "TABLE "
|
|
256
|
+
|
|
257
|
+
@staticmethod
|
|
258
|
+
def _unicode_substitute(m: re.Match[str]) -> str:
|
|
259
|
+
# Interpret the number as hex and convert it to the Unicode string
|
|
260
|
+
return chr(int(m.group(1), 16))
|
|
261
|
+
|
|
262
|
+
UNICODE_SUBSTITUTE: t.Optional[t.Callable[[re.Match[str]], str]] = _unicode_substitute
|
|
263
|
+
|
|
229
264
|
SUPPORTED_JSON_PATH_PARTS = {
|
|
230
265
|
exp.JSONPathKey,
|
|
231
266
|
exp.JSONPathRoot,
|
|
@@ -264,6 +299,9 @@ class SingleStore(MySQL):
|
|
|
264
299
|
exp.TryCast: unsupported_args("format", "action", "default")(
|
|
265
300
|
lambda self, e: f"{self.sql(e, 'this')} !:> {self.sql(e, 'to')}"
|
|
266
301
|
),
|
|
302
|
+
exp.CastToStrType: lambda self, e: self.sql(
|
|
303
|
+
exp.cast(e.this, DataType.build(e.args["to"].name))
|
|
304
|
+
),
|
|
267
305
|
exp.StrToUnix: unsupported_args("format")(rename_func("UNIX_TIMESTAMP")),
|
|
268
306
|
exp.TimeToUnix: rename_func("UNIX_TIMESTAMP"),
|
|
269
307
|
exp.TimeStrToUnix: rename_func("UNIX_TIMESTAMP"),
|
|
@@ -313,7 +351,15 @@ class SingleStore(MySQL):
|
|
|
313
351
|
if e.unit is not None
|
|
314
352
|
else self.func("DATEDIFF", e.this, e.expression)
|
|
315
353
|
),
|
|
354
|
+
exp.TsOrDsDiff: lambda self, e: timestampdiff_sql(self, e)
|
|
355
|
+
if e.unit is not None
|
|
356
|
+
else self.func("DATEDIFF", e.this, e.expression),
|
|
316
357
|
exp.TimestampTrunc: unsupported_args("zone")(timestamptrunc_sql()),
|
|
358
|
+
exp.CurrentDatetime: lambda self, e: self.sql(
|
|
359
|
+
cast_to_time6(
|
|
360
|
+
exp.CurrentTimestamp(this=exp.Literal.number(6)), exp.DataType.Type.DATETIME
|
|
361
|
+
)
|
|
362
|
+
),
|
|
317
363
|
exp.JSONExtract: unsupported_args(
|
|
318
364
|
"only_json_types",
|
|
319
365
|
"expressions",
|
|
@@ -329,6 +375,21 @@ class SingleStore(MySQL):
|
|
|
329
375
|
exp.JSONPathSubscript: lambda self, e: self.json_path_part(e.this),
|
|
330
376
|
exp.JSONPathRoot: lambda *_: "",
|
|
331
377
|
exp.JSONFormat: unsupported_args("options", "is_json")(rename_func("JSON_PRETTY")),
|
|
378
|
+
exp.JSONArrayAgg: unsupported_args("null_handling", "return_type", "strict")(
|
|
379
|
+
lambda self, e: self.func("JSON_AGG", e.this, suffix=f"{self.sql(e, 'order')})")
|
|
380
|
+
),
|
|
381
|
+
exp.JSONArray: unsupported_args("null_handling", "return_type", "strict")(
|
|
382
|
+
rename_func("JSON_BUILD_ARRAY")
|
|
383
|
+
),
|
|
384
|
+
exp.JSONBExists: lambda self, e: self.func(
|
|
385
|
+
"BSON_MATCH_ANY_EXISTS", e.this, e.args.get("path")
|
|
386
|
+
),
|
|
387
|
+
exp.JSONExists: unsupported_args("passing", "on_condition")(
|
|
388
|
+
lambda self, e: self.func("JSON_MATCH_ANY_EXISTS", e.this, e.args.get("path"))
|
|
389
|
+
),
|
|
390
|
+
exp.JSONObject: unsupported_args(
|
|
391
|
+
"null_handling", "unique_keys", "return_type", "encoding"
|
|
392
|
+
)(rename_func("JSON_BUILD_OBJECT")),
|
|
332
393
|
exp.DayOfWeekIso: lambda self, e: f"(({self.func('DAYOFWEEK', e.this)} % 7) + 1)",
|
|
333
394
|
exp.DayOfMonth: rename_func("DAY"),
|
|
334
395
|
exp.Hll: rename_func("APPROX_COUNT_DISTINCT"),
|
|
@@ -347,6 +408,9 @@ class SingleStore(MySQL):
|
|
|
347
408
|
exp.Variance: rename_func("VAR_SAMP"),
|
|
348
409
|
exp.VariancePop: rename_func("VAR_POP"),
|
|
349
410
|
exp.Xor: bool_xor_sql,
|
|
411
|
+
exp.Cbrt: lambda self, e: self.sql(
|
|
412
|
+
exp.Pow(this=e.this, expression=exp.Literal.number(1) / exp.Literal.number(3))
|
|
413
|
+
),
|
|
350
414
|
exp.RegexpLike: lambda self, e: self.binary(e, "RLIKE"),
|
|
351
415
|
exp.Repeat: lambda self, e: self.func(
|
|
352
416
|
"LPAD",
|
|
@@ -382,13 +446,30 @@ class SingleStore(MySQL):
|
|
|
382
446
|
exp.FromBase: lambda self, e: self.func(
|
|
383
447
|
"CONV", e.this, e.expression, exp.Literal.number(10)
|
|
384
448
|
),
|
|
449
|
+
exp.RegexpILike: lambda self, e: self.binary(
|
|
450
|
+
exp.RegexpLike(
|
|
451
|
+
this=exp.Lower(this=e.this),
|
|
452
|
+
expression=exp.Lower(this=e.expression),
|
|
453
|
+
),
|
|
454
|
+
"RLIKE",
|
|
455
|
+
),
|
|
456
|
+
exp.Stuff: lambda self, e: self.func(
|
|
457
|
+
"CONCAT",
|
|
458
|
+
self.func("SUBSTRING", e.this, exp.Literal.number(1), e.args.get("start") - 1),
|
|
459
|
+
e.expression,
|
|
460
|
+
self.func("SUBSTRING", e.this, e.args.get("start") + e.args.get("length")),
|
|
461
|
+
),
|
|
385
462
|
exp.Reduce: unsupported_args("finish")(
|
|
386
463
|
lambda self, e: self.func(
|
|
387
464
|
"REDUCE", e.args.get("initial"), e.this, e.args.get("merge")
|
|
388
465
|
)
|
|
389
466
|
),
|
|
467
|
+
exp.MatchAgainst: unsupported_args("modifier")(
|
|
468
|
+
lambda self, e: super().matchagainst_sql(e)
|
|
469
|
+
),
|
|
390
470
|
}
|
|
391
471
|
TRANSFORMS.pop(exp.JSONExtractScalar)
|
|
472
|
+
TRANSFORMS.pop(exp.CurrentDate)
|
|
392
473
|
|
|
393
474
|
UNSUPPORTED_TYPES = {
|
|
394
475
|
exp.DataType.Type.ARRAY,
|
|
@@ -1606,3 +1687,57 @@ class SingleStore(MySQL):
|
|
|
1606
1687
|
return f"DECIMAL({precision})"
|
|
1607
1688
|
|
|
1608
1689
|
return super().datatype_sql(expression)
|
|
1690
|
+
|
|
1691
|
+
def collate_sql(self, expression: exp.Collate) -> str:
|
|
1692
|
+
# SingleStore does not support setting a collation for column in the SELECT query,
|
|
1693
|
+
# so we cast column to a LONGTEXT type with specific collation
|
|
1694
|
+
return self.binary(expression, ":> LONGTEXT COLLATE")
|
|
1695
|
+
|
|
1696
|
+
def currentdate_sql(self, expression: exp.CurrentDate) -> str:
|
|
1697
|
+
timezone = expression.this
|
|
1698
|
+
if timezone:
|
|
1699
|
+
if isinstance(timezone, exp.Literal) and timezone.name.lower() == "utc":
|
|
1700
|
+
return self.func("UTC_DATE")
|
|
1701
|
+
self.unsupported("CurrentDate with timezone is not supported in SingleStore")
|
|
1702
|
+
|
|
1703
|
+
return self.func("CURRENT_DATE")
|
|
1704
|
+
|
|
1705
|
+
def currenttime_sql(self, expression: exp.CurrentTime) -> str:
|
|
1706
|
+
arg = expression.this
|
|
1707
|
+
if arg:
|
|
1708
|
+
if isinstance(arg, exp.Literal) and arg.name.lower() == "utc":
|
|
1709
|
+
return self.func("UTC_TIME")
|
|
1710
|
+
if isinstance(arg, exp.Literal) and arg.is_number:
|
|
1711
|
+
return self.func("CURRENT_TIME", arg)
|
|
1712
|
+
self.unsupported("CurrentTime with timezone is not supported in SingleStore")
|
|
1713
|
+
|
|
1714
|
+
return self.func("CURRENT_TIME")
|
|
1715
|
+
|
|
1716
|
+
def currenttimestamp_sql(self, expression: exp.CurrentTimestamp) -> str:
|
|
1717
|
+
arg = expression.this
|
|
1718
|
+
if arg:
|
|
1719
|
+
if isinstance(arg, exp.Literal) and arg.name.lower() == "utc":
|
|
1720
|
+
return self.func("UTC_TIMESTAMP")
|
|
1721
|
+
if isinstance(arg, exp.Literal) and arg.is_number:
|
|
1722
|
+
return self.func("CURRENT_TIMESTAMP", arg)
|
|
1723
|
+
self.unsupported("CurrentTimestamp with timezone is not supported in SingleStore")
|
|
1724
|
+
|
|
1725
|
+
return self.func("CURRENT_TIMESTAMP")
|
|
1726
|
+
|
|
1727
|
+
def standardhash_sql(self, expression: exp.StandardHash) -> str:
|
|
1728
|
+
hash_function = expression.expression
|
|
1729
|
+
if hash_function is None:
|
|
1730
|
+
return self.func("SHA", expression.this)
|
|
1731
|
+
if isinstance(hash_function, exp.Literal):
|
|
1732
|
+
if hash_function.name.lower() == "sha":
|
|
1733
|
+
return self.func("SHA", expression.this)
|
|
1734
|
+
if hash_function.name.lower() == "md5":
|
|
1735
|
+
return self.func("MD5", expression.this)
|
|
1736
|
+
|
|
1737
|
+
self.unsupported(
|
|
1738
|
+
f"{hash_function.this} hash method is not supported in SingleStore"
|
|
1739
|
+
)
|
|
1740
|
+
return self.func("SHA", expression.this)
|
|
1741
|
+
|
|
1742
|
+
self.unsupported("STANDARD_HASH function is not supported in SingleStore")
|
|
1743
|
+
return self.func("SHA", expression.this)
|
sqlglot/dialects/snowflake.py
CHANGED
|
@@ -496,6 +496,15 @@ class Snowflake(Dialect):
|
|
|
496
496
|
ALTER_TABLE_ADD_REQUIRED_FOR_EACH_COLUMN = False
|
|
497
497
|
TRY_CAST_REQUIRES_STRING = True
|
|
498
498
|
|
|
499
|
+
ANNOTATORS = {
|
|
500
|
+
**Dialect.ANNOTATORS,
|
|
501
|
+
**{
|
|
502
|
+
expr_type: lambda self, e: self._annotate_by_args(e, "this")
|
|
503
|
+
for expr_type in (exp.Reverse,)
|
|
504
|
+
},
|
|
505
|
+
exp.ConcatWs: lambda self, e: self._annotate_by_args(e, "expressions"),
|
|
506
|
+
}
|
|
507
|
+
|
|
499
508
|
TIME_MAPPING = {
|
|
500
509
|
"YYYY": "%Y",
|
|
501
510
|
"yyyy": "%Y",
|
|
@@ -574,6 +583,7 @@ class Snowflake(Dialect):
|
|
|
574
583
|
end=exp.Sub(this=seq_get(args, 1), expression=exp.Literal.number(1)),
|
|
575
584
|
step=seq_get(args, 2),
|
|
576
585
|
),
|
|
586
|
+
"ARRAY_SORT": exp.SortArray.from_arg_list,
|
|
577
587
|
"BITXOR": _build_bitwise(exp.BitwiseXor, "BITXOR"),
|
|
578
588
|
"BIT_XOR": _build_bitwise(exp.BitwiseXor, "BITXOR"),
|
|
579
589
|
"BITOR": _build_bitwise(exp.BitwiseOr, "BITOR"),
|
|
@@ -582,6 +592,18 @@ class Snowflake(Dialect):
|
|
|
582
592
|
"BIT_SHIFTLEFT": _build_bitwise(exp.BitwiseLeftShift, "BIT_SHIFTLEFT"),
|
|
583
593
|
"BITSHIFTRIGHT": _build_bitwise(exp.BitwiseRightShift, "BITSHIFTRIGHT"),
|
|
584
594
|
"BIT_SHIFTRIGHT": _build_bitwise(exp.BitwiseRightShift, "BIT_SHIFTRIGHT"),
|
|
595
|
+
"BITANDAGG": exp.BitwiseAndAgg.from_arg_list,
|
|
596
|
+
"BITAND_AGG": exp.BitwiseAndAgg.from_arg_list,
|
|
597
|
+
"BIT_AND_AGG": exp.BitwiseAndAgg.from_arg_list,
|
|
598
|
+
"BIT_ANDAGG": exp.BitwiseAndAgg.from_arg_list,
|
|
599
|
+
"BITORAGG": exp.BitwiseOrAgg.from_arg_list,
|
|
600
|
+
"BITOR_AGG": exp.BitwiseOrAgg.from_arg_list,
|
|
601
|
+
"BIT_OR_AGG": exp.BitwiseOrAgg.from_arg_list,
|
|
602
|
+
"BIT_ORAGG": exp.BitwiseOrAgg.from_arg_list,
|
|
603
|
+
"BITXORAGG": exp.BitwiseXorAgg.from_arg_list,
|
|
604
|
+
"BITXOR_AGG": exp.BitwiseXorAgg.from_arg_list,
|
|
605
|
+
"BIT_XOR_AGG": exp.BitwiseXorAgg.from_arg_list,
|
|
606
|
+
"BIT_XORAGG": exp.BitwiseXorAgg.from_arg_list,
|
|
585
607
|
"BOOLXOR": _build_bitwise(exp.Xor, "BOOLXOR"),
|
|
586
608
|
"DATE": _build_datetime("DATE", exp.DataType.Type.DATE),
|
|
587
609
|
"DATE_TRUNC": _date_trunc_to_time,
|
|
@@ -643,6 +665,7 @@ class Snowflake(Dialect):
|
|
|
643
665
|
"TO_TIMESTAMP_NTZ": _build_datetime("TO_TIMESTAMP_NTZ", exp.DataType.Type.TIMESTAMP),
|
|
644
666
|
"TO_TIMESTAMP_TZ": _build_datetime("TO_TIMESTAMP_TZ", exp.DataType.Type.TIMESTAMPTZ),
|
|
645
667
|
"TO_VARCHAR": exp.ToChar.from_arg_list,
|
|
668
|
+
"VECTOR_L2_DISTANCE": exp.EuclideanDistance.from_arg_list,
|
|
646
669
|
"ZEROIFNULL": _build_if_from_zeroifnull,
|
|
647
670
|
}
|
|
648
671
|
|
|
@@ -659,6 +682,7 @@ class Snowflake(Dialect):
|
|
|
659
682
|
|
|
660
683
|
ALTER_PARSERS = {
|
|
661
684
|
**parser.Parser.ALTER_PARSERS,
|
|
685
|
+
"SESSION": lambda self: self._parse_alter_session(),
|
|
662
686
|
"UNSET": lambda self: self.expression(
|
|
663
687
|
exp.Set,
|
|
664
688
|
tag=self._match_text_seq("TAG"),
|
|
@@ -1124,9 +1148,8 @@ class Snowflake(Dialect):
|
|
|
1124
1148
|
|
|
1125
1149
|
KEYWORDS = {
|
|
1126
1150
|
**tokens.Tokenizer.KEYWORDS,
|
|
1127
|
-
"FILE://": TokenType.URI_START,
|
|
1128
1151
|
"BYTEINT": TokenType.INT,
|
|
1129
|
-
"
|
|
1152
|
+
"FILE://": TokenType.URI_START,
|
|
1130
1153
|
"FILE FORMAT": TokenType.FILE_FORMAT,
|
|
1131
1154
|
"GET": TokenType.GET,
|
|
1132
1155
|
"MATCH_CONDITION": TokenType.MATCH_CONDITION,
|
|
@@ -1138,15 +1161,16 @@ class Snowflake(Dialect):
|
|
|
1138
1161
|
"RM": TokenType.COMMAND,
|
|
1139
1162
|
"SAMPLE": TokenType.TABLE_SAMPLE,
|
|
1140
1163
|
"SEMANTIC VIEW": TokenType.SEMANTIC_VIEW,
|
|
1164
|
+
"SESSION": TokenType.SESSION,
|
|
1141
1165
|
"SQL_DOUBLE": TokenType.DOUBLE,
|
|
1142
1166
|
"SQL_VARCHAR": TokenType.VARCHAR,
|
|
1167
|
+
"STAGE": TokenType.STAGE,
|
|
1143
1168
|
"STORAGE INTEGRATION": TokenType.STORAGE_INTEGRATION,
|
|
1169
|
+
"STREAMLIT": TokenType.STREAMLIT,
|
|
1144
1170
|
"TAG": TokenType.TAG,
|
|
1145
1171
|
"TIMESTAMP_TZ": TokenType.TIMESTAMPTZ,
|
|
1146
1172
|
"TOP": TokenType.TOP,
|
|
1147
1173
|
"WAREHOUSE": TokenType.WAREHOUSE,
|
|
1148
|
-
"STAGE": TokenType.STAGE,
|
|
1149
|
-
"STREAMLIT": TokenType.STREAMLIT,
|
|
1150
1174
|
}
|
|
1151
1175
|
KEYWORDS.pop("/*+")
|
|
1152
1176
|
|
|
@@ -1198,6 +1222,10 @@ class Snowflake(Dialect):
|
|
|
1198
1222
|
),
|
|
1199
1223
|
exp.BitwiseOr: rename_func("BITOR"),
|
|
1200
1224
|
exp.BitwiseXor: rename_func("BITXOR"),
|
|
1225
|
+
exp.BitwiseAnd: rename_func("BITAND"),
|
|
1226
|
+
exp.BitwiseAndAgg: rename_func("BITANDAGG"),
|
|
1227
|
+
exp.BitwiseOrAgg: rename_func("BITORAGG"),
|
|
1228
|
+
exp.BitwiseXorAgg: rename_func("BITXORAGG"),
|
|
1201
1229
|
exp.BitwiseLeftShift: rename_func("BITSHIFTLEFT"),
|
|
1202
1230
|
exp.BitwiseRightShift: rename_func("BITSHIFTRIGHT"),
|
|
1203
1231
|
exp.Create: transforms.preprocess([_flatten_structured_types_unless_iceberg]),
|
|
@@ -1214,6 +1242,7 @@ class Snowflake(Dialect):
|
|
|
1214
1242
|
exp.Extract: lambda self, e: self.func(
|
|
1215
1243
|
"DATE_PART", map_date_part(e.this, self.dialect), e.expression
|
|
1216
1244
|
),
|
|
1245
|
+
exp.EuclideanDistance: rename_func("VECTOR_L2_DISTANCE"),
|
|
1217
1246
|
exp.FileFormatProperty: lambda self,
|
|
1218
1247
|
e: f"FILE_FORMAT=({self.expressions(e, 'expressions', sep=' ')})",
|
|
1219
1248
|
exp.FromTimeZone: lambda self, e: self.func(
|
|
@@ -1269,6 +1298,7 @@ class Snowflake(Dialect):
|
|
|
1269
1298
|
]
|
|
1270
1299
|
),
|
|
1271
1300
|
exp.SHA: rename_func("SHA1"),
|
|
1301
|
+
exp.SortArray: rename_func("ARRAY_SORT"),
|
|
1272
1302
|
exp.StarMap: rename_func("OBJECT_CONSTRUCT"),
|
|
1273
1303
|
exp.StartsWith: rename_func("STARTSWITH"),
|
|
1274
1304
|
exp.EndsWith: rename_func("ENDSWITH"),
|
sqlglot/dialects/spark.py
CHANGED
|
@@ -125,10 +125,17 @@ class Spark(Spark2):
|
|
|
125
125
|
FUNCTIONS = {
|
|
126
126
|
**Spark2.Parser.FUNCTIONS,
|
|
127
127
|
"ANY_VALUE": _build_with_ignore_nulls(exp.AnyValue),
|
|
128
|
+
"BIT_AND": exp.BitwiseAndAgg.from_arg_list,
|
|
129
|
+
"BIT_OR": exp.BitwiseOrAgg.from_arg_list,
|
|
130
|
+
"BIT_XOR": exp.BitwiseXorAgg.from_arg_list,
|
|
131
|
+
"BIT_COUNT": exp.BitwiseCountAgg.from_arg_list,
|
|
128
132
|
"DATE_ADD": _build_dateadd,
|
|
129
133
|
"DATEADD": _build_dateadd,
|
|
130
134
|
"TIMESTAMPADD": _build_dateadd,
|
|
131
135
|
"TIMESTAMPDIFF": build_date_delta(exp.TimestampDiff),
|
|
136
|
+
"TRY_ADD": exp.SafeAdd.from_arg_list,
|
|
137
|
+
"TRY_MULTIPLY": exp.SafeMultiply.from_arg_list,
|
|
138
|
+
"TRY_SUBTRACT": exp.SafeSubtract.from_arg_list,
|
|
132
139
|
"DATEDIFF": _build_datediff,
|
|
133
140
|
"DATE_DIFF": _build_datediff,
|
|
134
141
|
"LISTAGG": exp.GroupConcat.from_arg_list,
|
|
@@ -186,6 +193,10 @@ class Spark(Spark2):
|
|
|
186
193
|
exp.ArrayConstructCompact: lambda self, e: self.func(
|
|
187
194
|
"ARRAY_COMPACT", self.func("ARRAY", *e.expressions)
|
|
188
195
|
),
|
|
196
|
+
exp.BitwiseAndAgg: rename_func("BIT_AND"),
|
|
197
|
+
exp.BitwiseOrAgg: rename_func("BIT_OR"),
|
|
198
|
+
exp.BitwiseXorAgg: rename_func("BIT_XOR"),
|
|
199
|
+
exp.BitwiseCountAgg: rename_func("BIT_COUNT"),
|
|
189
200
|
exp.Create: preprocess(
|
|
190
201
|
[
|
|
191
202
|
remove_unique_constraints,
|
|
@@ -202,6 +213,9 @@ class Spark(Spark2):
|
|
|
202
213
|
exp.EndsWith: rename_func("ENDSWITH"),
|
|
203
214
|
exp.PartitionedByProperty: lambda self,
|
|
204
215
|
e: f"PARTITIONED BY {self.wrap(self.expressions(sqls=[_normalize_partition(e) for e in e.this.expressions], skip_first=True))}",
|
|
216
|
+
exp.SafeAdd: rename_func("TRY_ADD"),
|
|
217
|
+
exp.SafeMultiply: rename_func("TRY_MULTIPLY"),
|
|
218
|
+
exp.SafeSubtract: rename_func("TRY_SUBTRACT"),
|
|
205
219
|
exp.StartsWith: rename_func("STARTSWITH"),
|
|
206
220
|
exp.TimeAdd: date_delta_to_binary_interval_op(cast=False),
|
|
207
221
|
exp.TimeSub: date_delta_to_binary_interval_op(cast=False),
|
sqlglot/expressions.py
CHANGED
|
@@ -4905,7 +4905,7 @@ class Rollback(Expression):
|
|
|
4905
4905
|
|
|
4906
4906
|
class Alter(Expression):
|
|
4907
4907
|
arg_types = {
|
|
4908
|
-
"this":
|
|
4908
|
+
"this": False,
|
|
4909
4909
|
"kind": True,
|
|
4910
4910
|
"actions": True,
|
|
4911
4911
|
"exists": False,
|
|
@@ -4926,6 +4926,10 @@ class Alter(Expression):
|
|
|
4926
4926
|
return self.args.get("actions") or []
|
|
4927
4927
|
|
|
4928
4928
|
|
|
4929
|
+
class AlterSession(Expression):
|
|
4930
|
+
arg_types = {"expressions": True, "unset": False}
|
|
4931
|
+
|
|
4932
|
+
|
|
4929
4933
|
class Analyze(Expression):
|
|
4930
4934
|
arg_types = {
|
|
4931
4935
|
"kind": False,
|
|
@@ -5443,24 +5447,92 @@ class Typeof(Func):
|
|
|
5443
5447
|
pass
|
|
5444
5448
|
|
|
5445
5449
|
|
|
5450
|
+
class Acos(Func):
|
|
5451
|
+
pass
|
|
5452
|
+
|
|
5453
|
+
|
|
5454
|
+
class Acosh(Func):
|
|
5455
|
+
pass
|
|
5456
|
+
|
|
5457
|
+
|
|
5458
|
+
class Asin(Func):
|
|
5459
|
+
pass
|
|
5460
|
+
|
|
5461
|
+
|
|
5462
|
+
class Asinh(Func):
|
|
5463
|
+
pass
|
|
5464
|
+
|
|
5465
|
+
|
|
5466
|
+
class Atan(Func):
|
|
5467
|
+
arg_types = {"this": True, "expression": False}
|
|
5468
|
+
|
|
5469
|
+
|
|
5470
|
+
class Atanh(Func):
|
|
5471
|
+
pass
|
|
5472
|
+
|
|
5473
|
+
|
|
5474
|
+
class Atan2(Func):
|
|
5475
|
+
arg_types = {"this": True, "expression": True}
|
|
5476
|
+
|
|
5477
|
+
|
|
5478
|
+
class Cot(Func):
|
|
5479
|
+
pass
|
|
5480
|
+
|
|
5481
|
+
|
|
5482
|
+
class Coth(Func):
|
|
5483
|
+
pass
|
|
5484
|
+
|
|
5485
|
+
|
|
5486
|
+
class Csc(Func):
|
|
5487
|
+
pass
|
|
5488
|
+
|
|
5489
|
+
|
|
5490
|
+
class Csch(Func):
|
|
5491
|
+
pass
|
|
5492
|
+
|
|
5493
|
+
|
|
5494
|
+
class Sec(Func):
|
|
5495
|
+
pass
|
|
5496
|
+
|
|
5497
|
+
|
|
5498
|
+
class Sech(Func):
|
|
5499
|
+
pass
|
|
5500
|
+
|
|
5501
|
+
|
|
5502
|
+
class Sin(Func):
|
|
5503
|
+
pass
|
|
5504
|
+
|
|
5505
|
+
|
|
5506
|
+
class Sinh(Func):
|
|
5507
|
+
pass
|
|
5508
|
+
|
|
5509
|
+
|
|
5510
|
+
class CosineDistance(Func):
|
|
5511
|
+
arg_types = {"this": True, "expression": True}
|
|
5512
|
+
|
|
5513
|
+
|
|
5514
|
+
class EuclideanDistance(Func):
|
|
5515
|
+
arg_types = {"this": True, "expression": True}
|
|
5516
|
+
|
|
5517
|
+
|
|
5446
5518
|
class AggFunc(Func):
|
|
5447
5519
|
pass
|
|
5448
5520
|
|
|
5449
5521
|
|
|
5450
5522
|
class BitwiseAndAgg(AggFunc):
|
|
5451
|
-
|
|
5523
|
+
pass
|
|
5452
5524
|
|
|
5453
5525
|
|
|
5454
5526
|
class BitwiseOrAgg(AggFunc):
|
|
5455
|
-
|
|
5527
|
+
pass
|
|
5456
5528
|
|
|
5457
5529
|
|
|
5458
5530
|
class BitwiseXorAgg(AggFunc):
|
|
5459
|
-
|
|
5531
|
+
pass
|
|
5460
5532
|
|
|
5461
5533
|
|
|
5462
5534
|
class BitwiseCountAgg(AggFunc):
|
|
5463
|
-
|
|
5535
|
+
pass
|
|
5464
5536
|
|
|
5465
5537
|
|
|
5466
5538
|
class ByteLength(Func):
|
|
@@ -5998,6 +6070,18 @@ class CurrentUser(Func):
|
|
|
5998
6070
|
arg_types = {"this": False}
|
|
5999
6071
|
|
|
6000
6072
|
|
|
6073
|
+
class UtcDate(Func):
|
|
6074
|
+
arg_types = {}
|
|
6075
|
+
|
|
6076
|
+
|
|
6077
|
+
class UtcTime(Func):
|
|
6078
|
+
arg_types = {"this": False}
|
|
6079
|
+
|
|
6080
|
+
|
|
6081
|
+
class UtcTimestamp(Func):
|
|
6082
|
+
arg_types = {"this": False}
|
|
6083
|
+
|
|
6084
|
+
|
|
6001
6085
|
class DateAdd(Func, IntervalOp):
|
|
6002
6086
|
arg_types = {"this": True, "expression": True, "unit": False}
|
|
6003
6087
|
|
|
@@ -6675,7 +6759,7 @@ class JSONBExtractScalar(Binary, Func):
|
|
|
6675
6759
|
|
|
6676
6760
|
|
|
6677
6761
|
class JSONFormat(Func):
|
|
6678
|
-
arg_types = {"this": False, "options": False, "is_json": False}
|
|
6762
|
+
arg_types = {"this": False, "options": False, "is_json": False, "to_json": False}
|
|
6679
6763
|
_sql_names = ["JSON_FORMAT"]
|
|
6680
6764
|
|
|
6681
6765
|
|
|
@@ -6952,6 +7036,10 @@ class RangeN(Func):
|
|
|
6952
7036
|
arg_types = {"this": True, "expressions": True, "each": False}
|
|
6953
7037
|
|
|
6954
7038
|
|
|
7039
|
+
class RangeBucket(Func):
|
|
7040
|
+
arg_types = {"this": True, "expression": True}
|
|
7041
|
+
|
|
7042
|
+
|
|
6955
7043
|
class Rank(AggFunc):
|
|
6956
7044
|
arg_types = {"expressions": False}
|
|
6957
7045
|
is_var_len_args = True
|
|
@@ -7045,10 +7133,26 @@ class RowNumber(Func):
|
|
|
7045
7133
|
arg_types = {"this": False}
|
|
7046
7134
|
|
|
7047
7135
|
|
|
7136
|
+
class SafeAdd(Func):
|
|
7137
|
+
arg_types = {"this": True, "expression": True}
|
|
7138
|
+
|
|
7139
|
+
|
|
7048
7140
|
class SafeDivide(Func):
|
|
7049
7141
|
arg_types = {"this": True, "expression": True}
|
|
7050
7142
|
|
|
7051
7143
|
|
|
7144
|
+
class SafeMultiply(Func):
|
|
7145
|
+
arg_types = {"this": True, "expression": True}
|
|
7146
|
+
|
|
7147
|
+
|
|
7148
|
+
class SafeNegate(Func):
|
|
7149
|
+
pass
|
|
7150
|
+
|
|
7151
|
+
|
|
7152
|
+
class SafeSubtract(Func):
|
|
7153
|
+
arg_types = {"this": True, "expression": True}
|
|
7154
|
+
|
|
7155
|
+
|
|
7052
7156
|
class SafeConvertBytesToString(Func):
|
|
7053
7157
|
pass
|
|
7054
7158
|
|
|
@@ -7067,7 +7171,7 @@ class Sign(Func):
|
|
|
7067
7171
|
|
|
7068
7172
|
|
|
7069
7173
|
class SortArray(Func):
|
|
7070
|
-
arg_types = {"this": True, "asc": False}
|
|
7174
|
+
arg_types = {"this": True, "asc": False, "nulls_first": False}
|
|
7071
7175
|
|
|
7072
7176
|
|
|
7073
7177
|
class Soundex(Func):
|
sqlglot/generator.py
CHANGED
|
@@ -216,6 +216,11 @@ class Generator(metaclass=_Generator):
|
|
|
216
216
|
exp.UsingData: lambda self, e: f"USING DATA {self.sql(e, 'this')}",
|
|
217
217
|
exp.Uuid: lambda *_: "UUID()",
|
|
218
218
|
exp.UppercaseColumnConstraint: lambda *_: "UPPERCASE",
|
|
219
|
+
exp.UtcDate: lambda self, e: self.sql(exp.CurrentDate(this=exp.Literal.string("UTC"))),
|
|
220
|
+
exp.UtcTime: lambda self, e: self.sql(exp.CurrentTime(this=exp.Literal.string("UTC"))),
|
|
221
|
+
exp.UtcTimestamp: lambda self, e: self.sql(
|
|
222
|
+
exp.CurrentTimestamp(this=exp.Literal.string("UTC"))
|
|
223
|
+
),
|
|
219
224
|
exp.VarMap: lambda self, e: self.func("MAP", e.args["keys"], e.args["values"]),
|
|
220
225
|
exp.ViewAttributeProperty: lambda self, e: f"WITH {self.sql(e, 'this')}",
|
|
221
226
|
exp.VolatileProperty: lambda *_: "VOLATILE",
|
|
@@ -433,6 +438,9 @@ class Generator(metaclass=_Generator):
|
|
|
433
438
|
# Whether the UESCAPE syntax in unicode strings is supported
|
|
434
439
|
SUPPORTS_UESCAPE = True
|
|
435
440
|
|
|
441
|
+
# Function used to replace escaped unicode codes in unicode strings
|
|
442
|
+
UNICODE_SUBSTITUTE: t.Optional[t.Callable[[re.Match[str]], str]] = None
|
|
443
|
+
|
|
436
444
|
# The keyword to use when generating a star projection with excluded columns
|
|
437
445
|
STAR_EXCEPT = "EXCEPT"
|
|
438
446
|
|
|
@@ -495,6 +503,9 @@ class Generator(metaclass=_Generator):
|
|
|
495
503
|
# Whether LIKE and ILIKE support quantifiers such as LIKE ANY/ALL/SOME
|
|
496
504
|
SUPPORTS_LIKE_QUANTIFIERS = True
|
|
497
505
|
|
|
506
|
+
# Prefix which is appended to exp.Table expressions in MATCH AGAINST
|
|
507
|
+
MATCH_AGAINST_TABLE_PREFIX: t.Optional[str] = None
|
|
508
|
+
|
|
498
509
|
TYPE_MAPPING = {
|
|
499
510
|
exp.DataType.Type.DATETIME2: "TIMESTAMP",
|
|
500
511
|
exp.DataType.Type.NCHAR: "CHAR",
|
|
@@ -1384,7 +1395,7 @@ class Generator(metaclass=_Generator):
|
|
|
1384
1395
|
escape_sql = ""
|
|
1385
1396
|
|
|
1386
1397
|
if not self.dialect.UNICODE_START or (escape and not self.SUPPORTS_UESCAPE):
|
|
1387
|
-
this = escape_pattern.sub(escape_substitute, this)
|
|
1398
|
+
this = escape_pattern.sub(self.UNICODE_SUBSTITUTE or escape_substitute, this)
|
|
1388
1399
|
|
|
1389
1400
|
return f"{left_quote}{this}{right_quote}{escape_sql}"
|
|
1390
1401
|
|
|
@@ -3063,9 +3074,21 @@ class Generator(metaclass=_Generator):
|
|
|
3063
3074
|
return self.case_sql(exp.Case(ifs=[expression], default=expression.args.get("false")))
|
|
3064
3075
|
|
|
3065
3076
|
def matchagainst_sql(self, expression: exp.MatchAgainst) -> str:
|
|
3077
|
+
if self.MATCH_AGAINST_TABLE_PREFIX:
|
|
3078
|
+
expressions = []
|
|
3079
|
+
for expr in expression.expressions:
|
|
3080
|
+
if isinstance(expr, exp.Table):
|
|
3081
|
+
expressions.append(f"TABLE {self.sql(expr)}")
|
|
3082
|
+
else:
|
|
3083
|
+
expressions.append(expr)
|
|
3084
|
+
else:
|
|
3085
|
+
expressions = expression.expressions
|
|
3086
|
+
|
|
3066
3087
|
modifier = expression.args.get("modifier")
|
|
3067
3088
|
modifier = f" {modifier}" if modifier else ""
|
|
3068
|
-
return
|
|
3089
|
+
return (
|
|
3090
|
+
f"{self.func('MATCH', *expressions)} AGAINST({self.sql(expression, 'this')}{modifier})"
|
|
3091
|
+
)
|
|
3069
3092
|
|
|
3070
3093
|
def jsonkeyvalue_sql(self, expression: exp.JSONKeyValue) -> str:
|
|
3071
3094
|
return f"{self.sql(expression, 'this')}{self.JSON_KEY_VALUE_PAIR_SEP} {self.sql(expression, 'expression')}"
|
|
@@ -3444,7 +3467,9 @@ class Generator(metaclass=_Generator):
|
|
|
3444
3467
|
return f"TTL{self.seg(self.expressions(expression))}{where}{group}{aggregates}"
|
|
3445
3468
|
|
|
3446
3469
|
def transaction_sql(self, expression: exp.Transaction) -> str:
|
|
3447
|
-
|
|
3470
|
+
modes = self.expressions(expression, key="modes")
|
|
3471
|
+
modes = f" {modes}" if modes else ""
|
|
3472
|
+
return f"BEGIN{modes}"
|
|
3448
3473
|
|
|
3449
3474
|
def commit_sql(self, expression: exp.Commit) -> str:
|
|
3450
3475
|
chain = expression.args.get("chain")
|
|
@@ -3569,8 +3594,15 @@ class Generator(metaclass=_Generator):
|
|
|
3569
3594
|
kind = self.sql(expression, "kind")
|
|
3570
3595
|
not_valid = " NOT VALID" if expression.args.get("not_valid") else ""
|
|
3571
3596
|
check = " WITH CHECK" if expression.args.get("check") else ""
|
|
3597
|
+
this = self.sql(expression, "this")
|
|
3598
|
+
this = f" {this}" if this else ""
|
|
3599
|
+
|
|
3600
|
+
return f"ALTER {kind}{exists}{only}{this}{on_cluster}{check}{self.sep()}{actions_sql}{not_valid}{options}"
|
|
3572
3601
|
|
|
3573
|
-
|
|
3602
|
+
def altersession_sql(self, expression: exp.AlterSession) -> str:
|
|
3603
|
+
items_sql = self.expressions(expression, flat=True)
|
|
3604
|
+
keyword = "UNSET" if expression.args.get("unset") else "SET"
|
|
3605
|
+
return f"{keyword} {items_sql}"
|
|
3574
3606
|
|
|
3575
3607
|
def add_column_sql(self, expression: exp.Expression) -> str:
|
|
3576
3608
|
sql = self.sql(expression)
|