sqlglot 27.10.0__py3-none-any.whl → 27.12.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 +136 -15
- sqlglot/dialects/clickhouse.py +4 -0
- sqlglot/dialects/databricks.py +1 -0
- sqlglot/dialects/doris.py +2 -0
- sqlglot/dialects/dremio.py +29 -4
- sqlglot/dialects/duckdb.py +4 -1
- sqlglot/dialects/hive.py +11 -5
- sqlglot/dialects/oracle.py +2 -0
- sqlglot/dialects/singlestore.py +216 -1
- sqlglot/dialects/snowflake.py +8 -4
- sqlglot/dialects/spark.py +6 -0
- sqlglot/dialects/spark2.py +2 -0
- sqlglot/dialects/sqlite.py +1 -0
- sqlglot/expressions.py +200 -2
- sqlglot/generator.py +26 -4
- sqlglot/optimizer/qualify_columns.py +18 -3
- sqlglot/parser.py +34 -10
- sqlglot/tokens.py +5 -1
- {sqlglot-27.10.0.dist-info → sqlglot-27.12.0.dist-info}/METADATA +2 -2
- {sqlglot-27.10.0.dist-info → sqlglot-27.12.0.dist-info}/RECORD +24 -24
- {sqlglot-27.10.0.dist-info → sqlglot-27.12.0.dist-info}/WHEEL +0 -0
- {sqlglot-27.10.0.dist-info → sqlglot-27.12.0.dist-info}/licenses/LICENSE +0 -0
- {sqlglot-27.10.0.dist-info → sqlglot-27.12.0.dist-info}/top_level.txt +0 -0
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,6 +5447,74 @@ 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
|
|
|
@@ -5998,6 +6070,14 @@ 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 = {}
|
|
6079
|
+
|
|
6080
|
+
|
|
6001
6081
|
class DateAdd(Func, IntervalOp):
|
|
6002
6082
|
arg_types = {"this": True, "expression": True, "unit": False}
|
|
6003
6083
|
|
|
@@ -6110,6 +6190,22 @@ class LastDay(Func, TimeUnit):
|
|
|
6110
6190
|
arg_types = {"this": True, "unit": False}
|
|
6111
6191
|
|
|
6112
6192
|
|
|
6193
|
+
class LaxBool(Func):
|
|
6194
|
+
pass
|
|
6195
|
+
|
|
6196
|
+
|
|
6197
|
+
class LaxFloat64(Func):
|
|
6198
|
+
pass
|
|
6199
|
+
|
|
6200
|
+
|
|
6201
|
+
class LaxInt64(Func):
|
|
6202
|
+
pass
|
|
6203
|
+
|
|
6204
|
+
|
|
6205
|
+
class LaxString(Func):
|
|
6206
|
+
pass
|
|
6207
|
+
|
|
6208
|
+
|
|
6113
6209
|
class Extract(Func):
|
|
6114
6210
|
arg_types = {"this": True, "expression": True}
|
|
6115
6211
|
|
|
@@ -6203,6 +6299,11 @@ class DecodeCase(Func):
|
|
|
6203
6299
|
is_var_len_args = True
|
|
6204
6300
|
|
|
6205
6301
|
|
|
6302
|
+
class DenseRank(AggFunc):
|
|
6303
|
+
arg_types = {"expressions": False}
|
|
6304
|
+
is_var_len_args = True
|
|
6305
|
+
|
|
6306
|
+
|
|
6206
6307
|
class DiToDate(Func):
|
|
6207
6308
|
pass
|
|
6208
6309
|
|
|
@@ -6438,10 +6539,20 @@ class FormatJson(Expression):
|
|
|
6438
6539
|
pass
|
|
6439
6540
|
|
|
6440
6541
|
|
|
6542
|
+
class Format(Func):
|
|
6543
|
+
arg_types = {"this": True, "expressions": True}
|
|
6544
|
+
is_var_len_args = True
|
|
6545
|
+
|
|
6546
|
+
|
|
6441
6547
|
class JSONKeyValue(Expression):
|
|
6442
6548
|
arg_types = {"this": True, "expression": True}
|
|
6443
6549
|
|
|
6444
6550
|
|
|
6551
|
+
# https://cloud.google.com/bigquery/docs/reference/standard-sql/json_functions#json_keys
|
|
6552
|
+
class JSONKeysAtDepth(Func):
|
|
6553
|
+
arg_types = {"this": True, "expression": False, "mode": False}
|
|
6554
|
+
|
|
6555
|
+
|
|
6445
6556
|
class JSONObject(Func):
|
|
6446
6557
|
arg_types = {
|
|
6447
6558
|
"expressions": False,
|
|
@@ -6502,6 +6613,23 @@ class JSONSchema(Expression):
|
|
|
6502
6613
|
arg_types = {"expressions": True}
|
|
6503
6614
|
|
|
6504
6615
|
|
|
6616
|
+
class JSONSet(Func):
|
|
6617
|
+
arg_types = {"this": True, "expressions": True}
|
|
6618
|
+
is_var_len_args = True
|
|
6619
|
+
_sql_names = ["JSON_SET"]
|
|
6620
|
+
|
|
6621
|
+
|
|
6622
|
+
# https://cloud.google.com/bigquery/docs/reference/standard-sql/json_functions#json_strip_nulls
|
|
6623
|
+
class JSONStripNulls(Func):
|
|
6624
|
+
arg_types = {
|
|
6625
|
+
"this": True,
|
|
6626
|
+
"expression": False,
|
|
6627
|
+
"include_arrays": False,
|
|
6628
|
+
"remove_empty": False,
|
|
6629
|
+
}
|
|
6630
|
+
_sql_names = ["JSON_STRIP_NULLS"]
|
|
6631
|
+
|
|
6632
|
+
|
|
6505
6633
|
# https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html#function_json-value
|
|
6506
6634
|
class JSONValue(Expression):
|
|
6507
6635
|
arg_types = {
|
|
@@ -6516,6 +6644,12 @@ class JSONValueArray(Func):
|
|
|
6516
6644
|
arg_types = {"this": True, "expression": False}
|
|
6517
6645
|
|
|
6518
6646
|
|
|
6647
|
+
class JSONRemove(Func):
|
|
6648
|
+
arg_types = {"this": True, "expressions": True}
|
|
6649
|
+
is_var_len_args = True
|
|
6650
|
+
_sql_names = ["JSON_REMOVE"]
|
|
6651
|
+
|
|
6652
|
+
|
|
6519
6653
|
# https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/JSON_TABLE.html
|
|
6520
6654
|
class JSONTable(Func):
|
|
6521
6655
|
arg_types = {
|
|
@@ -6621,16 +6755,28 @@ class JSONBExtractScalar(Binary, Func):
|
|
|
6621
6755
|
|
|
6622
6756
|
|
|
6623
6757
|
class JSONFormat(Func):
|
|
6624
|
-
arg_types = {"this": False, "options": False, "is_json": False}
|
|
6758
|
+
arg_types = {"this": False, "options": False, "is_json": False, "to_json": False}
|
|
6625
6759
|
_sql_names = ["JSON_FORMAT"]
|
|
6626
6760
|
|
|
6627
6761
|
|
|
6762
|
+
class JSONArrayAppend(Func):
|
|
6763
|
+
arg_types = {"this": True, "expressions": True}
|
|
6764
|
+
is_var_len_args = True
|
|
6765
|
+
_sql_names = ["JSON_ARRAY_APPEND"]
|
|
6766
|
+
|
|
6767
|
+
|
|
6628
6768
|
# https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#operator_member-of
|
|
6629
6769
|
class JSONArrayContains(Binary, Predicate, Func):
|
|
6630
6770
|
arg_types = {"this": True, "expression": True, "json_type": False}
|
|
6631
6771
|
_sql_names = ["JSON_ARRAY_CONTAINS"]
|
|
6632
6772
|
|
|
6633
6773
|
|
|
6774
|
+
class JSONArrayInsert(Func):
|
|
6775
|
+
arg_types = {"this": True, "expressions": True}
|
|
6776
|
+
is_var_len_args = True
|
|
6777
|
+
_sql_names = ["JSON_ARRAY_INSERT"]
|
|
6778
|
+
|
|
6779
|
+
|
|
6634
6780
|
class ParseBignumeric(Func):
|
|
6635
6781
|
pass
|
|
6636
6782
|
|
|
@@ -6796,6 +6942,10 @@ class Nvl2(Func):
|
|
|
6796
6942
|
arg_types = {"this": True, "true": True, "false": False}
|
|
6797
6943
|
|
|
6798
6944
|
|
|
6945
|
+
class Ntile(AggFunc):
|
|
6946
|
+
arg_types = {"this": False}
|
|
6947
|
+
|
|
6948
|
+
|
|
6799
6949
|
class Normalize(Func):
|
|
6800
6950
|
arg_types = {"this": True, "form": False, "is_casefold": False}
|
|
6801
6951
|
|
|
@@ -6844,6 +6994,11 @@ class PercentileDisc(AggFunc):
|
|
|
6844
6994
|
arg_types = {"this": True, "expression": False}
|
|
6845
6995
|
|
|
6846
6996
|
|
|
6997
|
+
class PercentRank(AggFunc):
|
|
6998
|
+
arg_types = {"expressions": False}
|
|
6999
|
+
is_var_len_args = True
|
|
7000
|
+
|
|
7001
|
+
|
|
6847
7002
|
class Quantile(AggFunc):
|
|
6848
7003
|
arg_types = {"this": True, "quantile": True}
|
|
6849
7004
|
|
|
@@ -6877,6 +7032,15 @@ class RangeN(Func):
|
|
|
6877
7032
|
arg_types = {"this": True, "expressions": True, "each": False}
|
|
6878
7033
|
|
|
6879
7034
|
|
|
7035
|
+
class RangeBucket(Func):
|
|
7036
|
+
arg_types = {"this": True, "expression": True}
|
|
7037
|
+
|
|
7038
|
+
|
|
7039
|
+
class Rank(AggFunc):
|
|
7040
|
+
arg_types = {"expressions": False}
|
|
7041
|
+
is_var_len_args = True
|
|
7042
|
+
|
|
7043
|
+
|
|
6880
7044
|
class ReadCSV(Func):
|
|
6881
7045
|
_sql_names = ["READ_CSV"]
|
|
6882
7046
|
is_var_len_args = True
|
|
@@ -6928,6 +7092,18 @@ class RegexpILike(Binary, Func):
|
|
|
6928
7092
|
arg_types = {"this": True, "expression": True, "flag": False}
|
|
6929
7093
|
|
|
6930
7094
|
|
|
7095
|
+
class RegexpInstr(Func):
|
|
7096
|
+
arg_types = {
|
|
7097
|
+
"this": True,
|
|
7098
|
+
"expression": True,
|
|
7099
|
+
"position": False,
|
|
7100
|
+
"occurrence": False,
|
|
7101
|
+
"option": False,
|
|
7102
|
+
"parameters": False,
|
|
7103
|
+
"group": False,
|
|
7104
|
+
}
|
|
7105
|
+
|
|
7106
|
+
|
|
6931
7107
|
# https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.split.html
|
|
6932
7108
|
# limit is the number of times a pattern is applied
|
|
6933
7109
|
class RegexpSplit(Func):
|
|
@@ -6953,10 +7129,26 @@ class RowNumber(Func):
|
|
|
6953
7129
|
arg_types = {"this": False}
|
|
6954
7130
|
|
|
6955
7131
|
|
|
7132
|
+
class SafeAdd(Func):
|
|
7133
|
+
arg_types = {"this": True, "expression": True}
|
|
7134
|
+
|
|
7135
|
+
|
|
6956
7136
|
class SafeDivide(Func):
|
|
6957
7137
|
arg_types = {"this": True, "expression": True}
|
|
6958
7138
|
|
|
6959
7139
|
|
|
7140
|
+
class SafeMultiply(Func):
|
|
7141
|
+
arg_types = {"this": True, "expression": True}
|
|
7142
|
+
|
|
7143
|
+
|
|
7144
|
+
class SafeNegate(Func):
|
|
7145
|
+
pass
|
|
7146
|
+
|
|
7147
|
+
|
|
7148
|
+
class SafeSubtract(Func):
|
|
7149
|
+
arg_types = {"this": True, "expression": True}
|
|
7150
|
+
|
|
7151
|
+
|
|
6960
7152
|
class SafeConvertBytesToString(Func):
|
|
6961
7153
|
pass
|
|
6962
7154
|
|
|
@@ -7270,6 +7462,12 @@ class Corr(Binary, AggFunc):
|
|
|
7270
7462
|
pass
|
|
7271
7463
|
|
|
7272
7464
|
|
|
7465
|
+
# https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/CUME_DIST.html
|
|
7466
|
+
class CumeDist(AggFunc):
|
|
7467
|
+
arg_types = {"expressions": False}
|
|
7468
|
+
is_var_len_args = True
|
|
7469
|
+
|
|
7470
|
+
|
|
7273
7471
|
class Variance(AggFunc):
|
|
7274
7472
|
_sql_names = ["VARIANCE", "VARIANCE_SAMP", "VAR_SAMP"]
|
|
7275
7473
|
|
sqlglot/generator.py
CHANGED
|
@@ -216,6 +216,8 @@ 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"))),
|
|
219
221
|
exp.VarMap: lambda self, e: self.func("MAP", e.args["keys"], e.args["values"]),
|
|
220
222
|
exp.ViewAttributeProperty: lambda self, e: f"WITH {self.sql(e, 'this')}",
|
|
221
223
|
exp.VolatileProperty: lambda *_: "VOLATILE",
|
|
@@ -433,6 +435,9 @@ class Generator(metaclass=_Generator):
|
|
|
433
435
|
# Whether the UESCAPE syntax in unicode strings is supported
|
|
434
436
|
SUPPORTS_UESCAPE = True
|
|
435
437
|
|
|
438
|
+
# Function used to replace escaped unicode codes in unicode strings
|
|
439
|
+
UNICODE_SUBSTITUTE: t.Optional[t.Callable[[re.Match[str]], str]] = None
|
|
440
|
+
|
|
436
441
|
# The keyword to use when generating a star projection with excluded columns
|
|
437
442
|
STAR_EXCEPT = "EXCEPT"
|
|
438
443
|
|
|
@@ -511,6 +516,8 @@ class Generator(metaclass=_Generator):
|
|
|
511
516
|
exp.DataType.Type.SMALLDATETIME: "TIMESTAMP",
|
|
512
517
|
}
|
|
513
518
|
|
|
519
|
+
UNSUPPORTED_TYPES: set[exp.DataType.Type] = set()
|
|
520
|
+
|
|
514
521
|
TIME_PART_SINGULARS = {
|
|
515
522
|
"MICROSECONDS": "MICROSECOND",
|
|
516
523
|
"SECONDS": "SECOND",
|
|
@@ -1382,7 +1389,7 @@ class Generator(metaclass=_Generator):
|
|
|
1382
1389
|
escape_sql = ""
|
|
1383
1390
|
|
|
1384
1391
|
if not self.dialect.UNICODE_START or (escape and not self.SUPPORTS_UESCAPE):
|
|
1385
|
-
this = escape_pattern.sub(escape_substitute, this)
|
|
1392
|
+
this = escape_pattern.sub(self.UNICODE_SUBSTITUTE or escape_substitute, this)
|
|
1386
1393
|
|
|
1387
1394
|
return f"{left_quote}{this}{right_quote}{escape_sql}"
|
|
1388
1395
|
|
|
@@ -1406,6 +1413,11 @@ class Generator(metaclass=_Generator):
|
|
|
1406
1413
|
interior = self.expressions(expression, flat=True)
|
|
1407
1414
|
|
|
1408
1415
|
type_value = expression.this
|
|
1416
|
+
if type_value in self.UNSUPPORTED_TYPES:
|
|
1417
|
+
self.unsupported(
|
|
1418
|
+
f"Data type {type_value.value} is not supported when targeting {self.dialect.__class__.__name__}"
|
|
1419
|
+
)
|
|
1420
|
+
|
|
1409
1421
|
if type_value == exp.DataType.Type.USERDEFINED and expression.args.get("kind"):
|
|
1410
1422
|
type_sql = self.sql(expression, "kind")
|
|
1411
1423
|
else:
|
|
@@ -3562,8 +3574,15 @@ class Generator(metaclass=_Generator):
|
|
|
3562
3574
|
kind = self.sql(expression, "kind")
|
|
3563
3575
|
not_valid = " NOT VALID" if expression.args.get("not_valid") else ""
|
|
3564
3576
|
check = " WITH CHECK" if expression.args.get("check") else ""
|
|
3577
|
+
this = self.sql(expression, "this")
|
|
3578
|
+
this = f" {this}" if this else ""
|
|
3565
3579
|
|
|
3566
|
-
return f"ALTER {kind}{exists}{only}
|
|
3580
|
+
return f"ALTER {kind}{exists}{only}{this}{on_cluster}{check}{self.sep()}{actions_sql}{not_valid}{options}"
|
|
3581
|
+
|
|
3582
|
+
def altersession_sql(self, expression: exp.AlterSession) -> str:
|
|
3583
|
+
items_sql = self.expressions(expression, flat=True)
|
|
3584
|
+
keyword = "UNSET" if expression.args.get("unset") else "SET"
|
|
3585
|
+
return f"{keyword} {items_sql}"
|
|
3567
3586
|
|
|
3568
3587
|
def add_column_sql(self, expression: exp.Expression) -> str:
|
|
3569
3588
|
sql = self.sql(expression)
|
|
@@ -4660,9 +4679,12 @@ class Generator(metaclass=_Generator):
|
|
|
4660
4679
|
def arrayconcat_sql(self, expression: exp.ArrayConcat, name: str = "ARRAY_CONCAT") -> str:
|
|
4661
4680
|
exprs = expression.expressions
|
|
4662
4681
|
if not self.ARRAY_CONCAT_IS_VAR_LEN:
|
|
4663
|
-
|
|
4682
|
+
if len(exprs) == 0:
|
|
4683
|
+
rhs: t.Union[str, exp.Expression] = exp.Array(expressions=[])
|
|
4684
|
+
else:
|
|
4685
|
+
rhs = reduce(lambda x, y: exp.ArrayConcat(this=x, expressions=[y]), exprs)
|
|
4664
4686
|
else:
|
|
4665
|
-
rhs = self.expressions(expression)
|
|
4687
|
+
rhs = self.expressions(expression) # type: ignore
|
|
4666
4688
|
|
|
4667
4689
|
return self.func(name, expression.this, rhs or None)
|
|
4668
4690
|
|
|
@@ -279,6 +279,7 @@ def _expand_alias_refs(
|
|
|
279
279
|
|
|
280
280
|
alias_to_expression: t.Dict[str, t.Tuple[exp.Expression, int]] = {}
|
|
281
281
|
projections = {s.alias_or_name for s in expression.selects}
|
|
282
|
+
is_bigquery = dialect == "bigquery"
|
|
282
283
|
|
|
283
284
|
def replace_columns(
|
|
284
285
|
node: t.Optional[exp.Expression], resolve_table: bool = False, literal_index: bool = False
|
|
@@ -312,17 +313,30 @@ def _expand_alias_refs(
|
|
|
312
313
|
|
|
313
314
|
# BigQuery's having clause gets confused if an alias matches a source.
|
|
314
315
|
# SELECT x.a, max(x.b) as x FROM x GROUP BY 1 HAVING x > 1;
|
|
315
|
-
# If HAVING x is expanded to max(x.b),
|
|
316
|
-
|
|
316
|
+
# If "HAVING x" is expanded to "HAVING max(x.b)", BQ would blindly replace the "x" reference with the projection MAX(x.b)
|
|
317
|
+
# i.e HAVING MAX(MAX(x.b).b), resulting in the error: "Aggregations of aggregations are not allowed"
|
|
318
|
+
if is_having and is_bigquery:
|
|
317
319
|
skip_replace = skip_replace or any(
|
|
318
320
|
node.parts[0].name in projections
|
|
319
321
|
for node in alias_expr.find_all(exp.Column)
|
|
320
322
|
)
|
|
323
|
+
elif is_bigquery and (is_group_by or is_having):
|
|
324
|
+
column_table = table.name if table else column.table
|
|
325
|
+
if column_table in projections:
|
|
326
|
+
# BigQuery's GROUP BY and HAVING clauses get confused if the column name
|
|
327
|
+
# matches a source name and a projection. For instance:
|
|
328
|
+
# SELECT id, ARRAY_AGG(col) AS custom_fields FROM custom_fields GROUP BY id HAVING id >= 1
|
|
329
|
+
# We should not qualify "id" with "custom_fields" in either clause, since the aggregation shadows the actual table
|
|
330
|
+
# and we'd get the error: "Column custom_fields contains an aggregation function, which is not allowed in GROUP BY clause"
|
|
331
|
+
column.replace(exp.to_identifier(column.name))
|
|
332
|
+
return
|
|
321
333
|
|
|
322
334
|
if table and (not alias_expr or skip_replace):
|
|
323
335
|
column.set("table", table)
|
|
324
336
|
elif not column.table and alias_expr and not skip_replace:
|
|
325
|
-
if isinstance(alias_expr, exp.Literal) and (
|
|
337
|
+
if (isinstance(alias_expr, exp.Literal) or alias_expr.is_number) and (
|
|
338
|
+
literal_index or resolve_table
|
|
339
|
+
):
|
|
326
340
|
if literal_index:
|
|
327
341
|
column.replace(exp.Literal.number(i))
|
|
328
342
|
else:
|
|
@@ -442,6 +456,7 @@ def _expand_positional_references(
|
|
|
442
456
|
|
|
443
457
|
if (
|
|
444
458
|
isinstance(select, exp.CONSTANTS)
|
|
459
|
+
or select.is_number
|
|
445
460
|
or select.find(exp.Explode, exp.Unnest)
|
|
446
461
|
or ambiguous
|
|
447
462
|
):
|
sqlglot/parser.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import itertools
|
|
3
4
|
import logging
|
|
4
5
|
import re
|
|
5
6
|
import typing as t
|
|
6
|
-
import itertools
|
|
7
7
|
from collections import defaultdict
|
|
8
8
|
|
|
9
9
|
from sqlglot import exp
|
|
@@ -479,6 +479,7 @@ class Parser(metaclass=_Parser):
|
|
|
479
479
|
TokenType.INDEX,
|
|
480
480
|
TokenType.TABLE,
|
|
481
481
|
TokenType.VIEW,
|
|
482
|
+
TokenType.SESSION,
|
|
482
483
|
}
|
|
483
484
|
|
|
484
485
|
# Tokens that can represent identifiers
|
|
@@ -641,6 +642,8 @@ class Parser(metaclass=_Parser):
|
|
|
641
642
|
TokenType.TIMESTAMP,
|
|
642
643
|
TokenType.TIMESTAMPTZ,
|
|
643
644
|
TokenType.TRUNCATE,
|
|
645
|
+
TokenType.UTC_DATE,
|
|
646
|
+
TokenType.UTC_TIME,
|
|
644
647
|
TokenType.WINDOW,
|
|
645
648
|
TokenType.XOR,
|
|
646
649
|
*TYPE_TOKENS,
|
|
@@ -7316,10 +7319,13 @@ class Parser(metaclass=_Parser):
|
|
|
7316
7319
|
return self._parse_csv(self._parse_expression)
|
|
7317
7320
|
|
|
7318
7321
|
def _parse_select_or_expression(self, alias: bool = False) -> t.Optional[exp.Expression]:
|
|
7319
|
-
return
|
|
7320
|
-
self.
|
|
7321
|
-
|
|
7322
|
-
|
|
7322
|
+
return (
|
|
7323
|
+
self._parse_set_operations(
|
|
7324
|
+
self._parse_alias(self._parse_assignment(), explicit=True)
|
|
7325
|
+
if alias
|
|
7326
|
+
else self._parse_assignment()
|
|
7327
|
+
)
|
|
7328
|
+
or self._parse_select()
|
|
7323
7329
|
)
|
|
7324
7330
|
|
|
7325
7331
|
def _parse_ddl_select(self) -> t.Optional[exp.Expression]:
|
|
@@ -7580,6 +7586,18 @@ class Parser(metaclass=_Parser):
|
|
|
7580
7586
|
|
|
7581
7587
|
return alter_set
|
|
7582
7588
|
|
|
7589
|
+
def _parse_alter_session(self) -> exp.AlterSession:
|
|
7590
|
+
"""Parse ALTER SESSION SET/UNSET statements."""
|
|
7591
|
+
if self._match(TokenType.SET):
|
|
7592
|
+
expressions = self._parse_csv(lambda: self._parse_set_item_assignment())
|
|
7593
|
+
return self.expression(exp.AlterSession, expressions=expressions, unset=False)
|
|
7594
|
+
|
|
7595
|
+
self._match_text_seq("UNSET")
|
|
7596
|
+
expressions = self._parse_csv(
|
|
7597
|
+
lambda: self.expression(exp.SetItem, this=self._parse_id_var(any_token=True))
|
|
7598
|
+
)
|
|
7599
|
+
return self.expression(exp.AlterSession, expressions=expressions, unset=True)
|
|
7600
|
+
|
|
7583
7601
|
def _parse_alter(self) -> exp.Alter | exp.Command:
|
|
7584
7602
|
start = self._prev
|
|
7585
7603
|
|
|
@@ -7589,12 +7607,18 @@ class Parser(metaclass=_Parser):
|
|
|
7589
7607
|
|
|
7590
7608
|
exists = self._parse_exists()
|
|
7591
7609
|
only = self._match_text_seq("ONLY")
|
|
7592
|
-
this = self._parse_table(schema=True)
|
|
7593
|
-
check = self._match_text_seq("WITH", "CHECK")
|
|
7594
|
-
cluster = self._parse_on_property() if self._match(TokenType.ON) else None
|
|
7595
7610
|
|
|
7596
|
-
if
|
|
7597
|
-
|
|
7611
|
+
if alter_token.token_type == TokenType.SESSION:
|
|
7612
|
+
this = None
|
|
7613
|
+
check = None
|
|
7614
|
+
cluster = None
|
|
7615
|
+
else:
|
|
7616
|
+
this = self._parse_table(schema=True)
|
|
7617
|
+
check = self._match_text_seq("WITH", "CHECK")
|
|
7618
|
+
cluster = self._parse_on_property() if self._match(TokenType.ON) else None
|
|
7619
|
+
|
|
7620
|
+
if self._next:
|
|
7621
|
+
self._advance()
|
|
7598
7622
|
|
|
7599
7623
|
parser = self.ALTER_PARSERS.get(self._prev.text.upper()) if self._prev else None
|
|
7600
7624
|
if parser:
|
sqlglot/tokens.py
CHANGED
|
@@ -80,6 +80,7 @@ class TokenType(AutoName):
|
|
|
80
80
|
AT_GT = auto()
|
|
81
81
|
DOLLAR = auto()
|
|
82
82
|
PARAMETER = auto()
|
|
83
|
+
SESSION = auto()
|
|
83
84
|
SESSION_PARAMETER = auto()
|
|
84
85
|
DAMP = auto()
|
|
85
86
|
XOR = auto()
|
|
@@ -423,6 +424,8 @@ class TokenType(AutoName):
|
|
|
423
424
|
WINDOW = auto()
|
|
424
425
|
WITH = auto()
|
|
425
426
|
UNIQUE = auto()
|
|
427
|
+
UTC_DATE = auto()
|
|
428
|
+
UTC_TIME = auto()
|
|
426
429
|
VERSION_SNAPSHOT = auto()
|
|
427
430
|
TIMESTAMP_SNAPSHOT = auto()
|
|
428
431
|
OPTION = auto()
|
|
@@ -835,6 +838,7 @@ class Tokenizer(metaclass=_Tokenizer):
|
|
|
835
838
|
"SCHEMA": TokenType.SCHEMA,
|
|
836
839
|
"SELECT": TokenType.SELECT,
|
|
837
840
|
"SEMI": TokenType.SEMI,
|
|
841
|
+
"SESSION": TokenType.SESSION,
|
|
838
842
|
"SET": TokenType.SET,
|
|
839
843
|
"SETTINGS": TokenType.SETTINGS,
|
|
840
844
|
"SHOW": TokenType.SHOW,
|
|
@@ -1427,7 +1431,7 @@ class Tokenizer(metaclass=_Tokenizer):
|
|
|
1427
1431
|
self._advance(len(start))
|
|
1428
1432
|
text = self._extract_string(end, raw_string=token_type == TokenType.RAW_STRING)
|
|
1429
1433
|
|
|
1430
|
-
if base:
|
|
1434
|
+
if base and text:
|
|
1431
1435
|
try:
|
|
1432
1436
|
int(text, base)
|
|
1433
1437
|
except Exception:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlglot
|
|
3
|
-
Version: 27.
|
|
3
|
+
Version: 27.12.0
|
|
4
4
|
Summary: An easily customizable SQL parser and transpiler
|
|
5
5
|
Author-email: Toby Mao <toby.mao@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -33,7 +33,7 @@ Requires-Dist: typing_extensions; extra == "dev"
|
|
|
33
33
|
Requires-Dist: maturin<2.0,>=1.4; extra == "dev"
|
|
34
34
|
Requires-Dist: pyperf; extra == "dev"
|
|
35
35
|
Provides-Extra: rs
|
|
36
|
-
Requires-Dist: sqlglotrs==0.6.
|
|
36
|
+
Requires-Dist: sqlglotrs==0.6.2; extra == "rs"
|
|
37
37
|
Dynamic: license-file
|
|
38
38
|
Dynamic: provides-extra
|
|
39
39
|
|
|
@@ -1,51 +1,51 @@
|
|
|
1
1
|
sqlglot/__init__.py,sha256=za08rtdPh2v7dOpGdNomttlIVGgTrKja7rPd6sQwaTg,5391
|
|
2
2
|
sqlglot/__main__.py,sha256=022c173KqxsiABWTEpUIq_tJUxuNiW7a7ABsxBXqvu8,2069
|
|
3
3
|
sqlglot/_typing.py,sha256=-1HPyr3w5COlSJWqlgt8jhFk2dyMvBuvVBqIX1wyVCM,642
|
|
4
|
-
sqlglot/_version.py,sha256=
|
|
4
|
+
sqlglot/_version.py,sha256=pbMJ-il-pWtz_20YYeCzDhngpKNC-V0g18Eaoow3758,708
|
|
5
5
|
sqlglot/diff.py,sha256=PtOllQMQa1Sw1-V2Y8eypmDqGujXYPaTOp_WLsWkAWk,17314
|
|
6
6
|
sqlglot/errors.py,sha256=QNKMr-pzLUDR-tuMmn_GK6iMHUIVdb_YSJ_BhGEvuso,2126
|
|
7
|
-
sqlglot/expressions.py,sha256=
|
|
8
|
-
sqlglot/generator.py,sha256=
|
|
7
|
+
sqlglot/expressions.py,sha256=sECexwmvrQTKzuFzmPDeC_FezaQ1Hc9bg24TTKC0Jew,253741
|
|
8
|
+
sqlglot/generator.py,sha256=jJkQGBy0q6hOm6oFw-0LlA6McSqFHLIozsoceJBARM4,223908
|
|
9
9
|
sqlglot/helper.py,sha256=9nZjFVRBtMKFC3EdzpDQ6jkazFO19po6BF8xHiNGZIo,15111
|
|
10
10
|
sqlglot/jsonpath.py,sha256=SQgaxzaEYBN7At9dkTK4N1Spk6xHxvHL6QtCIP6iM30,7905
|
|
11
11
|
sqlglot/lineage.py,sha256=Qj5ykuDNcATppb9vOjoIKBqRVLbu3OMPiZk9f3iyv40,15312
|
|
12
|
-
sqlglot/parser.py,sha256=
|
|
12
|
+
sqlglot/parser.py,sha256=QSBr7HWlDPpJ039_p4fcWV4FA2-_HtDDCXXMBAhoPuo,332586
|
|
13
13
|
sqlglot/planner.py,sha256=ql7Li-bWJRcyXzNaZy_n6bQ6B2ZfunEIB8Ztv2xaxq4,14634
|
|
14
14
|
sqlglot/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
15
|
sqlglot/schema.py,sha256=13H2qKQs27EKdTpDLOvcNnSTDAUbYNKjWtJs4aQCSOA,20509
|
|
16
16
|
sqlglot/serde.py,sha256=DQVJ95WrIvhYfe02Ytb4NQug2aMwDCEwpMBW1LKDqzE,2031
|
|
17
17
|
sqlglot/time.py,sha256=Q62gv6kL40OiRBF6BMESxKJcMVn7ZLNw7sv8H34z5FI,18400
|
|
18
|
-
sqlglot/tokens.py,sha256=
|
|
18
|
+
sqlglot/tokens.py,sha256=rqOMcjPDNa_35xC5zdUqPHgILNJUYxMC5N00NsOC8ps,49105
|
|
19
19
|
sqlglot/transforms.py,sha256=utNDsCBsA7hPUK3-aby3DDgiY_XVMAKQqeoLm1EyihI,41218
|
|
20
20
|
sqlglot/trie.py,sha256=v27uXMrHfqrXlJ6GmeTSMovsB_3o0ctnlKhdNt7W6fI,2245
|
|
21
21
|
sqlglot/dialects/__init__.py,sha256=e3K2NHrZO7oXfBzEpRsvgWAgJ_UCEyg7SlUCRqvnPj4,3799
|
|
22
22
|
sqlglot/dialects/athena.py,sha256=ofArmayYLev4qZQ15GM8mevG04qqR5WGFb2ZcuYm6x4,10966
|
|
23
|
-
sqlglot/dialects/bigquery.py,sha256=
|
|
24
|
-
sqlglot/dialects/clickhouse.py,sha256=
|
|
25
|
-
sqlglot/dialects/databricks.py,sha256=
|
|
23
|
+
sqlglot/dialects/bigquery.py,sha256=z9R-xVAxFxkwu4NkrgO9LI6NVTiUm9hr09et13LyU_U,71724
|
|
24
|
+
sqlglot/dialects/clickhouse.py,sha256=YLY8s7oCfdCoD0X2iOIltivXXjtT_nJdb3931P0TDeU,58553
|
|
25
|
+
sqlglot/dialects/databricks.py,sha256=H4QTq7gg6tJylKc_YWsGp6049KydoI_wlQUHM7iCJtI,4753
|
|
26
26
|
sqlglot/dialects/dialect.py,sha256=02W-j8nYJduA78_BMxMTMGXv2i9mcAGAmXBt1YsH0CQ,73055
|
|
27
|
-
sqlglot/dialects/doris.py,sha256=
|
|
28
|
-
sqlglot/dialects/dremio.py,sha256=
|
|
27
|
+
sqlglot/dialects/doris.py,sha256=CFnF955Oav3IjZWA80ickOI8tPpCjxk7BN5R4Z6pA1U,25263
|
|
28
|
+
sqlglot/dialects/dremio.py,sha256=D2YwjqbTjJ8VZ94GQs7GBRCKUiizwggcEaR_drKpnoc,8242
|
|
29
29
|
sqlglot/dialects/drill.py,sha256=FOh7_KjPx_77pv0DiHKZog0CcmzqeF9_PEmGnJ1ESSM,5825
|
|
30
30
|
sqlglot/dialects/druid.py,sha256=kh3snZtneehNOWqs3XcPjsrhNaRbkCQ8E4hHbWJ1fHM,690
|
|
31
|
-
sqlglot/dialects/duckdb.py,sha256=
|
|
31
|
+
sqlglot/dialects/duckdb.py,sha256=ANzn5L5KS5pe9hn81Ta_4h5ngdPxMS1k_LdMuYGiff8,52470
|
|
32
32
|
sqlglot/dialects/dune.py,sha256=gALut-fFfN2qMsr8LvZ1NQK3F3W9z2f4PwMvTMXVVVg,375
|
|
33
33
|
sqlglot/dialects/exasol.py,sha256=ay3g_VyT5WvHTgNyJuCQu0nBt4bpllLZ9IdMBizEgYM,15761
|
|
34
34
|
sqlglot/dialects/fabric.py,sha256=4Sng2ZhQSaf6eK3ituR9DqDZERaVwYS_UfdpusjsISg,10220
|
|
35
|
-
sqlglot/dialects/hive.py,sha256=
|
|
35
|
+
sqlglot/dialects/hive.py,sha256=zFr6WmNZXw5C0m3nFc9ynrbzk8Wtb5gyzmJ0tPlMge8,32014
|
|
36
36
|
sqlglot/dialects/materialize.py,sha256=LD2q1kTRrCwkIu1BfoBvnjTGbupDtoQ8JQMDCIYAXHg,3533
|
|
37
37
|
sqlglot/dialects/mysql.py,sha256=tQHedJthtXdjgHi3cDfdt71kJ4w6ju6J8kD4_MYFwyE,47308
|
|
38
|
-
sqlglot/dialects/oracle.py,sha256=
|
|
38
|
+
sqlglot/dialects/oracle.py,sha256=RXwJ82VLRaPfxb-OI0Bjd8KNaXs0XghyAJO4Bm0msYk,15862
|
|
39
39
|
sqlglot/dialects/postgres.py,sha256=RAwAhrp_Gbz5Oi8OEuLcmHKnYXydvczYexd81Co0N9Y,33901
|
|
40
40
|
sqlglot/dialects/presto.py,sha256=XVeYr2NP86x5enlRqI7MYR6le85_ucYg_BBRocGN3jM,33413
|
|
41
41
|
sqlglot/dialects/prql.py,sha256=fwN-SPEGx-drwf1K0U2MByN-PkW3C_rOgQ3xeJeychg,7908
|
|
42
42
|
sqlglot/dialects/redshift.py,sha256=_sQTom4CGozFDZXW9y6bHQcZ-KiQ7QJjjQqM5rVagSc,15889
|
|
43
43
|
sqlglot/dialects/risingwave.py,sha256=BqWwW1iT_OIVMwfRamaww79snnBwIgCfr22Go-ggO68,3289
|
|
44
|
-
sqlglot/dialects/singlestore.py,sha256=
|
|
45
|
-
sqlglot/dialects/snowflake.py,sha256=
|
|
46
|
-
sqlglot/dialects/spark.py,sha256=
|
|
47
|
-
sqlglot/dialects/spark2.py,sha256=
|
|
48
|
-
sqlglot/dialects/sqlite.py,sha256=
|
|
44
|
+
sqlglot/dialects/singlestore.py,sha256=3iSunYKjG9PYr4jnZmqa9E3MJxs1-ZvCRHejaYjGU2U,52201
|
|
45
|
+
sqlglot/dialects/snowflake.py,sha256=PrpCq4BL8jzxQ9EnpZc-AJN4IZ_g5BJf4DU0RYFcyko,70779
|
|
46
|
+
sqlglot/dialects/spark.py,sha256=XJbQq5d-tvCKYfmOG5rtf4ROS9rTqKJsmQVp6JjlFp0,9699
|
|
47
|
+
sqlglot/dialects/spark2.py,sha256=qz36FT9k4iuiqboRpyG4VpKGkPR0P2fifmqgZ9gNUEU,14851
|
|
48
|
+
sqlglot/dialects/sqlite.py,sha256=UIQ66shIt2bQoLd7tYG4NVzh4HwCfERgAaLyukz8HjE,13231
|
|
49
49
|
sqlglot/dialects/starrocks.py,sha256=2gav0PSNgRdAGXzawdznZliBpglJoQ0wBxPI7ZIMsRw,11314
|
|
50
50
|
sqlglot/dialects/tableau.py,sha256=oIawDzUITxGCWaEMB8OaNMPWhbC3U-2y09pYPm4eazc,2190
|
|
51
51
|
sqlglot/dialects/teradata.py,sha256=7LxCcRwP0Idd_OnCzA57NCdheVjHcKC2aFAKG5N49IU,18202
|
|
@@ -71,13 +71,13 @@ sqlglot/optimizer/optimizer.py,sha256=vXEXDWHvbO-vJmSI7UqJuydM2WrD1xko7rETq2EtVJ
|
|
|
71
71
|
sqlglot/optimizer/pushdown_predicates.py,sha256=HGjs3Z4V3-X2d1VTfWhyByY3aL5SmKnVvt3aDXiiBM0,8414
|
|
72
72
|
sqlglot/optimizer/pushdown_projections.py,sha256=7NoK5NAUVYVhs0YnYyo6WuXfaO-BShSwS6lA8Y-ATQ4,6668
|
|
73
73
|
sqlglot/optimizer/qualify.py,sha256=oAPfwub7dEkrlCrsptcJWpLya4BgKhN6M5SwIs_86LY,4002
|
|
74
|
-
sqlglot/optimizer/qualify_columns.py,sha256=
|
|
74
|
+
sqlglot/optimizer/qualify_columns.py,sha256=LUlHSSyKshgWIhn4es2PzR1iAvMoSkwHY2t8h07Y32I,45037
|
|
75
75
|
sqlglot/optimizer/qualify_tables.py,sha256=dA4ZazL7ShQh2JgBwpHuG-4c5lBw1TNzCnuN7m0iVTA,6645
|
|
76
76
|
sqlglot/optimizer/scope.py,sha256=UOTrbwqcTc5iRQf0WStgYWXpE24w6riZy-tJYA18yTw,31229
|
|
77
77
|
sqlglot/optimizer/simplify.py,sha256=-_yus42OYwqjQ9a2TSGhtG2G0pSkInUry1z7hEMz2pY,51062
|
|
78
78
|
sqlglot/optimizer/unnest_subqueries.py,sha256=kzWUVDlxs8z9nmRx-8U-pHXPtVZhEIwkKqmKhr2QLvc,10908
|
|
79
|
-
sqlglot-27.
|
|
80
|
-
sqlglot-27.
|
|
81
|
-
sqlglot-27.
|
|
82
|
-
sqlglot-27.
|
|
83
|
-
sqlglot-27.
|
|
79
|
+
sqlglot-27.12.0.dist-info/licenses/LICENSE,sha256=p1Yk0B4oa0l8Rh-_dYyy75d8spjPd_vTloXfz4FWxys,1065
|
|
80
|
+
sqlglot-27.12.0.dist-info/METADATA,sha256=ggllRKer1u6zYd5tvnxmMCJ30mNdFtI_tnwImwE7Z4M,20682
|
|
81
|
+
sqlglot-27.12.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
82
|
+
sqlglot-27.12.0.dist-info/top_level.txt,sha256=5kRskCGA_gVADF9rSfSzPdLHXqvfMusDYeHePfNY2nQ,8
|
|
83
|
+
sqlglot-27.12.0.dist-info/RECORD,,
|