sqlglot 27.11.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 CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '27.11.0'
32
- __version_tuple__ = version_tuple = (27, 11, 0)
31
+ __version__ = version = '27.12.0'
32
+ __version_tuple__ = version_tuple = (27, 12, 0)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -310,17 +310,16 @@ def _annotate_math_functions(self: TypeAnnotator, expression: E) -> E:
310
310
  return expression
311
311
 
312
312
 
313
- def _annotate_perncentile_cont(
314
- self: TypeAnnotator, expression: exp.PercentileCont
315
- ) -> exp.PercentileCont:
313
+ def _annotate_by_args_with_coerce(self: TypeAnnotator, expression: E) -> E:
316
314
  """
317
- +------------+-----------+------------+---------+
318
- | INPUT | NUMERIC | BIGNUMERIC | FLOAT64 |
319
- +------------+-----------+------------+---------+
320
- | NUMERIC | NUMERIC | BIGNUMERIC | FLOAT64 |
321
- | BIGNUMERIC | BIGNUMERIC| BIGNUMERIC | FLOAT64 |
322
- | FLOAT64 | FLOAT64 | FLOAT64 | FLOAT64 |
323
- +------------+-----------+------------+---------+
315
+ +------------+------------+------------+-------------+---------+
316
+ | INPUT | INT64 | NUMERIC | BIGNUMERIC | FLOAT64 |
317
+ +------------+------------+------------+-------------+---------+
318
+ | INT64 | INT64 | NUMERIC | BIGNUMERIC | FLOAT64 |
319
+ | NUMERIC | NUMERIC | NUMERIC | BIGNUMERIC | FLOAT64 |
320
+ | BIGNUMERIC | BIGNUMERIC | BIGNUMERIC | BIGNUMERIC | FLOAT64 |
321
+ | FLOAT64 | FLOAT64 | FLOAT64 | FLOAT64 | FLOAT64 |
322
+ +------------+------------+------------+-------------+---------+
324
323
  """
325
324
  self._annotate_args(expression)
326
325
 
@@ -492,6 +491,7 @@ class BigQuery(Dialect):
492
491
  exp.DataType.Type.BIGDECIMAL: {exp.DataType.Type.DOUBLE},
493
492
  }
494
493
  COERCES_TO[exp.DataType.Type.DECIMAL] |= {exp.DataType.Type.BIGDECIMAL}
494
+ COERCES_TO[exp.DataType.Type.BIGINT] |= {exp.DataType.Type.BIGDECIMAL}
495
495
 
496
496
  # BigQuery maps Type.TIMESTAMP to DATETIME, so we need to amend the inferred types
497
497
  TYPE_TO_EXPRESSIONS = {
@@ -514,23 +514,47 @@ class BigQuery(Dialect):
514
514
  **{
515
515
  expr_type: lambda self, e: self._annotate_by_args(e, "this")
516
516
  for expr_type in (
517
+ exp.Abs,
518
+ exp.ArgMax,
519
+ exp.ArgMin,
520
+ exp.DateTrunc,
521
+ exp.DatetimeTrunc,
522
+ exp.FirstValue,
523
+ exp.GroupConcat,
524
+ exp.IgnoreNulls,
525
+ exp.JSONExtract,
526
+ exp.Lead,
517
527
  exp.Left,
518
- exp.Right,
519
528
  exp.Lower,
520
- exp.Upper,
529
+ exp.NthValue,
521
530
  exp.Pad,
522
- exp.Trim,
531
+ exp.PercentileDisc,
523
532
  exp.RegexpExtract,
524
533
  exp.RegexpReplace,
525
534
  exp.Repeat,
535
+ exp.Replace,
536
+ exp.RespectNulls,
537
+ exp.Reverse,
538
+ exp.Right,
539
+ exp.SafeNegate,
540
+ exp.Sign,
526
541
  exp.Substring,
542
+ exp.TimestampTrunc,
543
+ exp.Translate,
544
+ exp.Trim,
545
+ exp.Upper,
527
546
  )
528
547
  },
548
+ exp.Acos: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
549
+ exp.Acosh: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
550
+ exp.Asin: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
551
+ exp.Asinh: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
552
+ exp.Atan: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
553
+ exp.Atanh: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
554
+ exp.Atan2: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
529
555
  exp.ApproxTopSum: lambda self, e: _annotate_by_args_approx_top(self, e),
530
556
  exp.ApproxTopK: lambda self, e: _annotate_by_args_approx_top(self, e),
531
557
  exp.ApproxQuantiles: lambda self, e: self._annotate_by_args(e, "this", array=True),
532
- exp.ArgMax: lambda self, e: self._annotate_by_args(e, "this"),
533
- exp.ArgMin: lambda self, e: self._annotate_by_args(e, "this"),
534
558
  exp.Array: _annotate_array,
535
559
  exp.ArrayConcat: lambda self, e: self._annotate_by_args(e, "this", "expressions"),
536
560
  exp.Ascii: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BIGINT),
@@ -540,6 +564,7 @@ class BigQuery(Dialect):
540
564
  exp.BitwiseCountAgg: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BIGINT),
541
565
  exp.ByteLength: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BIGINT),
542
566
  exp.ByteString: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BINARY),
567
+ exp.Cbrt: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
543
568
  exp.CodePointsToBytes: lambda self, e: self._annotate_with_type(
544
569
  e, exp.DataType.Type.BINARY
545
570
  ),
@@ -549,14 +574,20 @@ class BigQuery(Dialect):
549
574
  exp.Concat: _annotate_concat,
550
575
  exp.Contains: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BOOLEAN),
551
576
  exp.Corr: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
577
+ exp.Cot: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
578
+ exp.CosineDistance: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
579
+ exp.Coth: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
552
580
  exp.CovarPop: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
553
581
  exp.CovarSamp: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
582
+ exp.Csc: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
583
+ exp.Csch: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
554
584
  exp.CumeDist: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
555
585
  exp.DateFromUnixDate: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DATE),
556
- exp.DateTrunc: lambda self, e: self._annotate_by_args(e, "this"),
557
586
  exp.DenseRank: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BIGINT),
587
+ exp.EuclideanDistance: lambda self, e: self._annotate_with_type(
588
+ e, exp.DataType.Type.DOUBLE
589
+ ),
558
590
  exp.FarmFingerprint: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BIGINT),
559
- exp.FirstValue: lambda self, e: self._annotate_by_args(e, "this"),
560
591
  exp.Unhex: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BINARY),
561
592
  exp.Float64: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
562
593
  exp.Format: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.VARCHAR),
@@ -564,7 +595,8 @@ class BigQuery(Dialect):
564
595
  e, exp.DataType.build("ARRAY<TIMESTAMP>", dialect="bigquery")
565
596
  ),
566
597
  exp.Grouping: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BIGINT),
567
- exp.IgnoreNulls: lambda self, e: self._annotate_by_args(e, "this"),
598
+ exp.IsInf: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BOOLEAN),
599
+ exp.IsNan: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BOOLEAN),
568
600
  exp.JSONArray: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.JSON),
569
601
  exp.JSONArrayAppend: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.JSON),
570
602
  exp.JSONArrayInsert: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.JSON),
@@ -572,9 +604,10 @@ class BigQuery(Dialect):
572
604
  exp.JSONExtractScalar: lambda self, e: self._annotate_with_type(
573
605
  e, exp.DataType.Type.VARCHAR
574
606
  ),
575
- exp.JSONExtract: lambda self, e: self._annotate_by_args(e, "this"),
576
607
  exp.JSONExtractArray: lambda self, e: self._annotate_by_args(e, "this", array=True),
577
- exp.JSONFormat: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.VARCHAR),
608
+ exp.JSONFormat: lambda self, e: self._annotate_with_type(
609
+ e, exp.DataType.Type.JSON if e.args.get("to_json") else exp.DataType.Type.VARCHAR
610
+ ),
578
611
  exp.JSONKeysAtDepth: lambda self, e: self._annotate_with_type(
579
612
  e, exp.DataType.build("ARRAY<VARCHAR>", dialect="bigquery")
580
613
  ),
@@ -587,7 +620,6 @@ class BigQuery(Dialect):
587
620
  e, exp.DataType.build("ARRAY<VARCHAR>", dialect="bigquery")
588
621
  ),
589
622
  exp.Lag: lambda self, e: self._annotate_by_args(e, "this", "default"),
590
- exp.Lead: lambda self, e: self._annotate_by_args(e, "this"),
591
623
  exp.LowerHex: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.VARCHAR),
592
624
  exp.LaxBool: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BOOLEAN),
593
625
  exp.LaxFloat64: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
@@ -595,7 +627,6 @@ class BigQuery(Dialect):
595
627
  exp.LaxString: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.VARCHAR),
596
628
  exp.MD5Digest: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BINARY),
597
629
  exp.Normalize: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.VARCHAR),
598
- exp.NthValue: lambda self, e: self._annotate_by_args(e, "this"),
599
630
  exp.Ntile: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BIGINT),
600
631
  exp.ParseTime: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.TIME),
601
632
  exp.ParseDatetime: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DATETIME),
@@ -603,36 +634,39 @@ class BigQuery(Dialect):
603
634
  e, exp.DataType.Type.BIGDECIMAL
604
635
  ),
605
636
  exp.ParseNumeric: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DECIMAL),
606
- exp.PercentileCont: lambda self, e: _annotate_perncentile_cont(self, e),
607
- exp.PercentileDisc: lambda self, e: self._annotate_by_args(e, "this"),
637
+ exp.PercentileCont: lambda self, e: _annotate_by_args_with_coerce(self, e),
608
638
  exp.PercentRank: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
609
639
  exp.Rank: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BIGINT),
640
+ exp.RangeBucket: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BIGINT),
610
641
  exp.RegexpExtractAll: lambda self, e: self._annotate_by_args(e, "this", array=True),
611
642
  exp.RegexpInstr: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BIGINT),
612
- exp.Replace: lambda self, e: self._annotate_by_args(e, "this"),
613
- exp.RespectNulls: lambda self, e: self._annotate_by_args(e, "this"),
614
- exp.Reverse: lambda self, e: self._annotate_by_args(e, "this"),
615
643
  exp.RowNumber: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BIGINT),
644
+ exp.Rand: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
616
645
  exp.SafeConvertBytesToString: lambda self, e: self._annotate_with_type(
617
646
  e, exp.DataType.Type.VARCHAR
618
647
  ),
648
+ exp.SafeAdd: lambda self, e: _annotate_by_args_with_coerce(self, e),
649
+ exp.SafeMultiply: lambda self, e: _annotate_by_args_with_coerce(self, e),
650
+ exp.SafeSubtract: lambda self, e: _annotate_by_args_with_coerce(self, e),
651
+ exp.Sec: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
652
+ exp.Sech: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
619
653
  exp.Soundex: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.VARCHAR),
620
654
  exp.SHA: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BINARY),
621
655
  exp.SHA2: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BINARY),
622
- exp.Sign: lambda self, e: self._annotate_by_args(e, "this"),
656
+ exp.Sin: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
657
+ exp.Sinh: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DOUBLE),
623
658
  exp.Split: lambda self, e: self._annotate_by_args(e, "this", array=True),
624
659
  exp.TimestampFromParts: lambda self, e: self._annotate_with_type(
625
660
  e, exp.DataType.Type.DATETIME
626
661
  ),
627
- exp.TimestampTrunc: lambda self, e: self._annotate_by_args(e, "this"),
628
662
  exp.TimeFromParts: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.TIME),
629
663
  exp.TimeTrunc: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.TIME),
630
664
  exp.ToCodePoints: lambda self, e: self._annotate_with_type(
631
665
  e, exp.DataType.build("ARRAY<BIGINT>", dialect="bigquery")
632
666
  ),
633
667
  exp.TsOrDsToTime: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.TIME),
634
- exp.Translate: lambda self, e: self._annotate_by_args(e, "this"),
635
668
  exp.Unicode: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BIGINT),
669
+ exp.Uuid: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.VARCHAR),
636
670
  }
637
671
 
638
672
  def normalize_identifier(self, expression: E) -> E:
@@ -804,6 +838,9 @@ class BigQuery(Dialect):
804
838
  this=seq_get(args, 0), scale=exp.UnixToTime.MILLIS
805
839
  ),
806
840
  "TIMESTAMP_SECONDS": lambda args: exp.UnixToTime(this=seq_get(args, 0)),
841
+ "TO_JSON": lambda args: exp.JSONFormat(
842
+ this=seq_get(args, 0), options=seq_get(args, 1), to_json=True
843
+ ),
807
844
  "TO_JSON_STRING": exp.JSONFormat.from_arg_list,
808
845
  "FORMAT_DATETIME": _build_format_time(exp.TsOrDsToDatetime),
809
846
  "FORMAT_TIMESTAMP": _build_format_time(exp.TsOrDsToTimestamp),
@@ -1274,7 +1311,11 @@ class BigQuery(Dialect):
1274
1311
  exp.JSONExtract: _json_extract_sql,
1275
1312
  exp.JSONExtractArray: _json_extract_sql,
1276
1313
  exp.JSONExtractScalar: _json_extract_sql,
1277
- exp.JSONFormat: rename_func("TO_JSON_STRING"),
1314
+ exp.JSONFormat: lambda self, e: self.func(
1315
+ "TO_JSON" if e.args.get("to_json") else "TO_JSON_STRING",
1316
+ e.this,
1317
+ e.args.get("options"),
1318
+ ),
1278
1319
  exp.JSONKeysAtDepth: rename_func("JSON_KEYS"),
1279
1320
  exp.JSONValueArray: rename_func("JSON_VALUE_ARRAY"),
1280
1321
  exp.Levenshtein: _levenshtein_sql,
@@ -312,6 +312,7 @@ class ClickHouse(Dialect):
312
312
  "ARRAYREVERSE": exp.ArrayReverse.from_arg_list,
313
313
  "ARRAYSLICE": exp.ArraySlice.from_arg_list,
314
314
  "COUNTIF": _build_count_if,
315
+ "COSINEDISTANCE": exp.CosineDistance.from_arg_list,
315
316
  "DATE_ADD": build_date_delta(exp.DateAdd, default_unit=None),
316
317
  "DATEADD": build_date_delta(exp.DateAdd, default_unit=None),
317
318
  "DATE_DIFF": build_date_delta(exp.DateDiff, default_unit=None, supports_timezone=True),
@@ -324,6 +325,7 @@ class ClickHouse(Dialect):
324
325
  exp.JSONExtractScalar, zero_based_indexing=False
325
326
  ),
326
327
  "LENGTH": lambda args: exp.Length(this=seq_get(args, 0), binary=True),
328
+ "L2Distance": exp.EuclideanDistance.from_arg_list,
327
329
  "MAP": parser.build_var_map,
328
330
  "MATCH": exp.RegexpLike.from_arg_list,
329
331
  "PARSEDATETIME": _build_datetime_format(exp.ParseDatetime),
@@ -1094,6 +1096,7 @@ class ClickHouse(Dialect):
1094
1096
  exp.Array: inline_array_sql,
1095
1097
  exp.CastToStrType: rename_func("CAST"),
1096
1098
  exp.CountIf: rename_func("countIf"),
1099
+ exp.CosineDistance: rename_func("cosineDistance"),
1097
1100
  exp.CompressColumnConstraint: lambda self,
1098
1101
  e: f"CODEC({self.expressions(e, key='this', flat=True)})",
1099
1102
  exp.ComputedColumnConstraint: lambda self,
@@ -1123,6 +1126,7 @@ class ClickHouse(Dialect):
1123
1126
  exp.Rand: rename_func("randCanonical"),
1124
1127
  exp.StartsWith: rename_func("startsWith"),
1125
1128
  exp.EndsWith: rename_func("endsWith"),
1129
+ exp.EuclideanDistance: rename_func("L2Distance"),
1126
1130
  exp.StrPosition: lambda self, e: strposition_sql(
1127
1131
  self,
1128
1132
  e,
@@ -106,6 +106,7 @@ class Databricks(Spark):
106
106
  ),
107
107
  }
108
108
 
109
+ TRANSFORMS.pop(exp.RegexpLike)
109
110
  TRANSFORMS.pop(exp.TryCast)
110
111
 
111
112
  TYPE_MAPPING = {
sqlglot/dialects/doris.py CHANGED
@@ -50,6 +50,7 @@ class Doris(MySQL):
50
50
  **MySQL.Parser.FUNCTIONS,
51
51
  "COLLECT_SET": exp.ArrayUniqueAgg.from_arg_list,
52
52
  "DATE_TRUNC": _build_date_trunc,
53
+ "L2_DISTANCE": exp.EuclideanDistance.from_arg_list,
53
54
  "MONTHS_ADD": exp.AddMonths.from_arg_list,
54
55
  "REGEXP": exp.RegexpLike.from_arg_list,
55
56
  "TO_DATE": exp.TsOrDsToDate.from_arg_list,
@@ -210,6 +211,7 @@ class Doris(MySQL):
210
211
  exp.CurrentDate: lambda self, _: self.func("CURRENT_DATE"),
211
212
  exp.CurrentTimestamp: lambda self, _: self.func("NOW"),
212
213
  exp.DateTrunc: lambda self, e: self.func("DATE_TRUNC", e.this, unit_to_str(e)),
214
+ exp.EuclideanDistance: rename_func("L2_DISTANCE"),
213
215
  exp.GroupConcat: lambda self, e: self.func(
214
216
  "GROUP_CONCAT", e.this, e.args.get("separator") or exp.Literal.string(",")
215
217
  ),
@@ -304,7 +304,6 @@ class DuckDB(Dialect):
304
304
  "CHAR": TokenType.TEXT,
305
305
  "DATETIME": TokenType.TIMESTAMPNTZ,
306
306
  "DETACH": TokenType.DETACH,
307
- "EXCLUDE": TokenType.EXCEPT,
308
307
  "LOGICAL": TokenType.BOOLEAN,
309
308
  "ONLY": TokenType.ONLY,
310
309
  "PIVOT_WIDER": TokenType.PIVOT,
@@ -386,6 +385,8 @@ class DuckDB(Dialect):
386
385
  "JSON_EXTRACT_PATH": parser.build_extract_json_with_path(exp.JSONExtract),
387
386
  "JSON_EXTRACT_STRING": parser.build_extract_json_with_path(exp.JSONExtractScalar),
388
387
  "LIST_CONTAINS": exp.ArrayContains.from_arg_list,
388
+ "LIST_COSINE_DISTANCE": exp.CosineDistance.from_arg_list,
389
+ "LIST_DISTANCE": exp.EuclideanDistance.from_arg_list,
389
390
  "LIST_FILTER": exp.ArrayFilter.from_arg_list,
390
391
  "LIST_HAS": exp.ArrayContains.from_arg_list,
391
392
  "LIST_HAS_ANY": exp.ArrayOverlaps.from_arg_list,
@@ -650,6 +651,7 @@ class DuckDB(Dialect):
650
651
  ),
651
652
  exp.BitwiseXor: rename_func("XOR"),
652
653
  exp.CommentColumnConstraint: no_comment_column_constraint_sql,
654
+ exp.CosineDistance: rename_func("LIST_COSINE_DISTANCE"),
653
655
  exp.CurrentDate: lambda *_: "CURRENT_DATE",
654
656
  exp.CurrentTime: lambda *_: "CURRENT_TIME",
655
657
  exp.CurrentTimestamp: lambda *_: "CURRENT_TIMESTAMP",
@@ -673,6 +675,7 @@ class DuckDB(Dialect):
673
675
  exp.DiToDate: lambda self,
674
676
  e: f"CAST(STRPTIME(CAST({self.sql(e, 'this')} AS TEXT), {DuckDB.DATEINT_FORMAT}) AS DATE)",
675
677
  exp.Encode: lambda self, e: encode_decode_sql(self, e, "ENCODE", replace=False),
678
+ exp.EuclideanDistance: rename_func("LIST_DISTANCE"),
676
679
  exp.GenerateDateArray: _generate_datetime_array_sql,
677
680
  exp.GenerateTimestampArray: _generate_datetime_array_sql,
678
681
  exp.GroupConcat: lambda self, e: groupconcat_sql(self, e, within_group=False),
sqlglot/dialects/hive.py CHANGED
@@ -194,6 +194,16 @@ def _build_to_date(args: t.List) -> exp.TsOrDsToDate:
194
194
  return expr
195
195
 
196
196
 
197
+ def _build_date_add(args: t.List) -> exp.TsOrDsAdd:
198
+ expression = seq_get(args, 1)
199
+ if expression:
200
+ expression = expression * -1
201
+
202
+ return exp.TsOrDsAdd(
203
+ this=seq_get(args, 0), expression=expression, unit=exp.Literal.string("DAY")
204
+ )
205
+
206
+
197
207
  class Hive(Dialect):
198
208
  ALIAS_POST_TABLESAMPLE = True
199
209
  IDENTIFIERS_CAN_START_WITH_DIGIT = True
@@ -314,11 +324,7 @@ class Hive(Dialect):
314
324
  seq_get(args, 1),
315
325
  ]
316
326
  ),
317
- "DATE_SUB": lambda args: exp.TsOrDsAdd(
318
- this=seq_get(args, 0),
319
- expression=exp.Mul(this=seq_get(args, 1), expression=exp.Literal.number(-1)),
320
- unit=exp.Literal.string("DAY"),
321
- ),
327
+ "DATE_SUB": _build_date_add,
322
328
  "DATEDIFF": lambda args: exp.DateDiff(
323
329
  this=exp.TsOrDsToDate(this=seq_get(args, 0)),
324
330
  expression=exp.TsOrDsToDate(this=seq_get(args, 1)),
@@ -107,6 +107,7 @@ class Oracle(Dialect):
107
107
  FUNCTIONS = {
108
108
  **parser.Parser.FUNCTIONS,
109
109
  "CONVERT": exp.ConvertToCharset.from_arg_list,
110
+ "L2_DISTANCE": exp.EuclideanDistance.from_arg_list,
110
111
  "NVL": lambda args: build_coalesce(args, is_nvl=True),
111
112
  "SQUARE": lambda args: exp.Pow(this=seq_get(args, 0), expression=exp.Literal.number(2)),
112
113
  "TO_CHAR": build_timetostr_or_tochar,
@@ -305,6 +306,7 @@ class Oracle(Dialect):
305
306
  "TO_DATE", e.this, exp.Literal.string("YYYY-MM-DD")
306
307
  ),
307
308
  exp.DateTrunc: lambda self, e: self.func("TRUNC", e.this, e.unit),
309
+ exp.EuclideanDistance: rename_func("L2_DISTANCE"),
308
310
  exp.Group: transforms.preprocess([transforms.unalias_group]),
309
311
  exp.ILike: no_ilike_sql,
310
312
  exp.LogicalOr: rename_func("MAX"),
@@ -1,3 +1,5 @@
1
+ import re
2
+
1
3
  from sqlglot import TokenType
2
4
  import typing as t
3
5
 
@@ -59,6 +61,8 @@ class SingleStore(MySQL):
59
61
  "BSON": TokenType.JSONB,
60
62
  "GEOGRAPHYPOINT": TokenType.GEOGRAPHYPOINT,
61
63
  "TIMESTAMP": TokenType.TIMESTAMP,
64
+ "UTC_DATE": TokenType.UTC_DATE,
65
+ "UTC_TIME": TokenType.UTC_TIME,
62
66
  ":>": TokenType.COLON_GT,
63
67
  "!:>": TokenType.NCOLON_GT,
64
68
  "::$": TokenType.DCOLONDOLLAR,
@@ -195,6 +199,12 @@ class SingleStore(MySQL):
195
199
  ),
196
200
  }
197
201
 
202
+ NO_PAREN_FUNCTIONS = {
203
+ **MySQL.Parser.NO_PAREN_FUNCTIONS,
204
+ TokenType.UTC_DATE: exp.UtcDate,
205
+ TokenType.UTC_TIME: exp.UtcTime,
206
+ }
207
+
198
208
  CAST_COLUMN_OPERATORS = {TokenType.COLON_GT, TokenType.NCOLON_GT}
199
209
 
200
210
  COLUMN_OPERATORS = {
@@ -226,6 +236,15 @@ class SingleStore(MySQL):
226
236
  COLUMN_OPERATORS.pop(TokenType.PLACEHOLDER)
227
237
 
228
238
  class Generator(MySQL.Generator):
239
+ SUPPORTS_UESCAPE = False
240
+
241
+ @staticmethod
242
+ def _unicode_substitute(m: re.Match[str]) -> str:
243
+ # Interpret the number as hex and convert it to the Unicode string
244
+ return chr(int(m.group(1), 16))
245
+
246
+ UNICODE_SUBSTITUTE: t.Optional[t.Callable[[re.Match[str]], str]] = _unicode_substitute
247
+
229
248
  SUPPORTED_JSON_PATH_PARTS = {
230
249
  exp.JSONPathKey,
231
250
  exp.JSONPathRoot,
@@ -264,6 +283,9 @@ class SingleStore(MySQL):
264
283
  exp.TryCast: unsupported_args("format", "action", "default")(
265
284
  lambda self, e: f"{self.sql(e, 'this')} !:> {self.sql(e, 'to')}"
266
285
  ),
286
+ exp.CastToStrType: lambda self, e: self.sql(
287
+ exp.cast(e.this, DataType.build(e.args["to"].name))
288
+ ),
267
289
  exp.StrToUnix: unsupported_args("format")(rename_func("UNIX_TIMESTAMP")),
268
290
  exp.TimeToUnix: rename_func("UNIX_TIMESTAMP"),
269
291
  exp.TimeStrToUnix: rename_func("UNIX_TIMESTAMP"),
@@ -313,6 +335,9 @@ class SingleStore(MySQL):
313
335
  if e.unit is not None
314
336
  else self.func("DATEDIFF", e.this, e.expression)
315
337
  ),
338
+ exp.TsOrDsDiff: lambda self, e: timestampdiff_sql(self, e)
339
+ if e.unit is not None
340
+ else self.func("DATEDIFF", e.this, e.expression),
316
341
  exp.TimestampTrunc: unsupported_args("zone")(timestamptrunc_sql()),
317
342
  exp.JSONExtract: unsupported_args(
318
343
  "only_json_types",
@@ -347,6 +372,9 @@ class SingleStore(MySQL):
347
372
  exp.Variance: rename_func("VAR_SAMP"),
348
373
  exp.VariancePop: rename_func("VAR_POP"),
349
374
  exp.Xor: bool_xor_sql,
375
+ exp.Cbrt: lambda self, e: self.sql(
376
+ exp.Pow(this=e.this, expression=exp.Literal.number(1) / exp.Literal.number(3))
377
+ ),
350
378
  exp.RegexpLike: lambda self, e: self.binary(e, "RLIKE"),
351
379
  exp.Repeat: lambda self, e: self.func(
352
380
  "LPAD",
@@ -382,6 +410,13 @@ class SingleStore(MySQL):
382
410
  exp.FromBase: lambda self, e: self.func(
383
411
  "CONV", e.this, e.expression, exp.Literal.number(10)
384
412
  ),
413
+ exp.RegexpILike: lambda self, e: self.binary(
414
+ exp.RegexpLike(
415
+ this=exp.Lower(this=e.this),
416
+ expression=exp.Lower(this=e.expression),
417
+ ),
418
+ "RLIKE",
419
+ ),
385
420
  exp.Reduce: unsupported_args("finish")(
386
421
  lambda self, e: self.func(
387
422
  "REDUCE", e.args.get("initial"), e.this, e.args.get("merge")
@@ -389,6 +424,7 @@ class SingleStore(MySQL):
389
424
  ),
390
425
  }
391
426
  TRANSFORMS.pop(exp.JSONExtractScalar)
427
+ TRANSFORMS.pop(exp.CurrentDate)
392
428
 
393
429
  UNSUPPORTED_TYPES = {
394
430
  exp.DataType.Type.ARRAY,
@@ -1606,3 +1642,28 @@ class SingleStore(MySQL):
1606
1642
  return f"DECIMAL({precision})"
1607
1643
 
1608
1644
  return super().datatype_sql(expression)
1645
+
1646
+ def collate_sql(self, expression: exp.Collate) -> str:
1647
+ # SingleStore does not support setting a collation for column in the SELECT query,
1648
+ # so we cast column to a LONGTEXT type with specific collation
1649
+ return self.binary(expression, ":> LONGTEXT COLLATE")
1650
+
1651
+ def currentdate_sql(self, expression: exp.CurrentDate) -> str:
1652
+ timezone = expression.this
1653
+ if timezone:
1654
+ if isinstance(timezone, exp.Literal) and timezone.name.lower() == "utc":
1655
+ return self.func("UTC_DATE")
1656
+ self.unsupported("CurrentDate with timezone is not supported in SingleStore")
1657
+
1658
+ return self.func("CURRENT_DATE")
1659
+
1660
+ def currenttime_sql(self, expression: exp.CurrentTime) -> str:
1661
+ arg = expression.this
1662
+ if arg:
1663
+ if isinstance(arg, exp.Literal) and arg.name.lower() == "utc":
1664
+ return self.func("UTC_TIME")
1665
+ if isinstance(arg, exp.Literal) and arg.is_number:
1666
+ return self.func("CURRENT_TIME", arg)
1667
+ self.unsupported("CurrentTime with timezone is not supported in SingleStore")
1668
+
1669
+ return self.func("CURRENT_TIME")
@@ -643,6 +643,7 @@ class Snowflake(Dialect):
643
643
  "TO_TIMESTAMP_NTZ": _build_datetime("TO_TIMESTAMP_NTZ", exp.DataType.Type.TIMESTAMP),
644
644
  "TO_TIMESTAMP_TZ": _build_datetime("TO_TIMESTAMP_TZ", exp.DataType.Type.TIMESTAMPTZ),
645
645
  "TO_VARCHAR": exp.ToChar.from_arg_list,
646
+ "VECTOR_L2_DISTANCE": exp.EuclideanDistance.from_arg_list,
646
647
  "ZEROIFNULL": _build_if_from_zeroifnull,
647
648
  }
648
649
 
@@ -659,6 +660,7 @@ class Snowflake(Dialect):
659
660
 
660
661
  ALTER_PARSERS = {
661
662
  **parser.Parser.ALTER_PARSERS,
663
+ "SESSION": lambda self: self._parse_alter_session(),
662
664
  "UNSET": lambda self: self.expression(
663
665
  exp.Set,
664
666
  tag=self._match_text_seq("TAG"),
@@ -1124,9 +1126,8 @@ class Snowflake(Dialect):
1124
1126
 
1125
1127
  KEYWORDS = {
1126
1128
  **tokens.Tokenizer.KEYWORDS,
1127
- "FILE://": TokenType.URI_START,
1128
1129
  "BYTEINT": TokenType.INT,
1129
- "EXCLUDE": TokenType.EXCEPT,
1130
+ "FILE://": TokenType.URI_START,
1130
1131
  "FILE FORMAT": TokenType.FILE_FORMAT,
1131
1132
  "GET": TokenType.GET,
1132
1133
  "MATCH_CONDITION": TokenType.MATCH_CONDITION,
@@ -1138,15 +1139,16 @@ class Snowflake(Dialect):
1138
1139
  "RM": TokenType.COMMAND,
1139
1140
  "SAMPLE": TokenType.TABLE_SAMPLE,
1140
1141
  "SEMANTIC VIEW": TokenType.SEMANTIC_VIEW,
1142
+ "SESSION": TokenType.SESSION,
1141
1143
  "SQL_DOUBLE": TokenType.DOUBLE,
1142
1144
  "SQL_VARCHAR": TokenType.VARCHAR,
1145
+ "STAGE": TokenType.STAGE,
1143
1146
  "STORAGE INTEGRATION": TokenType.STORAGE_INTEGRATION,
1147
+ "STREAMLIT": TokenType.STREAMLIT,
1144
1148
  "TAG": TokenType.TAG,
1145
1149
  "TIMESTAMP_TZ": TokenType.TIMESTAMPTZ,
1146
1150
  "TOP": TokenType.TOP,
1147
1151
  "WAREHOUSE": TokenType.WAREHOUSE,
1148
- "STAGE": TokenType.STAGE,
1149
- "STREAMLIT": TokenType.STREAMLIT,
1150
1152
  }
1151
1153
  KEYWORDS.pop("/*+")
1152
1154
 
@@ -1214,6 +1216,7 @@ class Snowflake(Dialect):
1214
1216
  exp.Extract: lambda self, e: self.func(
1215
1217
  "DATE_PART", map_date_part(e.this, self.dialect), e.expression
1216
1218
  ),
1219
+ exp.EuclideanDistance: rename_func("VECTOR_L2_DISTANCE"),
1217
1220
  exp.FileFormatProperty: lambda self,
1218
1221
  e: f"FILE_FORMAT=({self.expressions(e, 'expressions', sep=' ')})",
1219
1222
  exp.FromTimeZone: lambda self, e: self.func(
sqlglot/dialects/spark.py CHANGED
@@ -129,6 +129,9 @@ class Spark(Spark2):
129
129
  "DATEADD": _build_dateadd,
130
130
  "TIMESTAMPADD": _build_dateadd,
131
131
  "TIMESTAMPDIFF": build_date_delta(exp.TimestampDiff),
132
+ "TRY_ADD": exp.SafeAdd.from_arg_list,
133
+ "TRY_MULTIPLY": exp.SafeMultiply.from_arg_list,
134
+ "TRY_SUBTRACT": exp.SafeSubtract.from_arg_list,
132
135
  "DATEDIFF": _build_datediff,
133
136
  "DATE_DIFF": _build_datediff,
134
137
  "LISTAGG": exp.GroupConcat.from_arg_list,
@@ -202,6 +205,9 @@ class Spark(Spark2):
202
205
  exp.EndsWith: rename_func("ENDSWITH"),
203
206
  exp.PartitionedByProperty: lambda self,
204
207
  e: f"PARTITIONED BY {self.wrap(self.expressions(sqls=[_normalize_partition(e) for e in e.this.expressions], skip_first=True))}",
208
+ exp.SafeAdd: rename_func("TRY_ADD"),
209
+ exp.SafeMultiply: rename_func("TRY_MULTIPLY"),
210
+ exp.SafeSubtract: rename_func("TRY_SUBTRACT"),
205
211
  exp.StartsWith: rename_func("STARTSWITH"),
206
212
  exp.TimeAdd: date_delta_to_binary_interval_op(cast=False),
207
213
  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": True,
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
 
@@ -6675,7 +6755,7 @@ class JSONBExtractScalar(Binary, Func):
6675
6755
 
6676
6756
 
6677
6757
  class JSONFormat(Func):
6678
- arg_types = {"this": False, "options": False, "is_json": False}
6758
+ arg_types = {"this": False, "options": False, "is_json": False, "to_json": False}
6679
6759
  _sql_names = ["JSON_FORMAT"]
6680
6760
 
6681
6761
 
@@ -6952,6 +7032,10 @@ class RangeN(Func):
6952
7032
  arg_types = {"this": True, "expressions": True, "each": False}
6953
7033
 
6954
7034
 
7035
+ class RangeBucket(Func):
7036
+ arg_types = {"this": True, "expression": True}
7037
+
7038
+
6955
7039
  class Rank(AggFunc):
6956
7040
  arg_types = {"expressions": False}
6957
7041
  is_var_len_args = True
@@ -7045,10 +7129,26 @@ class RowNumber(Func):
7045
7129
  arg_types = {"this": False}
7046
7130
 
7047
7131
 
7132
+ class SafeAdd(Func):
7133
+ arg_types = {"this": True, "expression": True}
7134
+
7135
+
7048
7136
  class SafeDivide(Func):
7049
7137
  arg_types = {"this": True, "expression": True}
7050
7138
 
7051
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
+
7052
7152
  class SafeConvertBytesToString(Func):
7053
7153
  pass
7054
7154
 
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
 
@@ -1384,7 +1389,7 @@ class Generator(metaclass=_Generator):
1384
1389
  escape_sql = ""
1385
1390
 
1386
1391
  if not self.dialect.UNICODE_START or (escape and not self.SUPPORTS_UESCAPE):
1387
- this = escape_pattern.sub(escape_substitute, this)
1392
+ this = escape_pattern.sub(self.UNICODE_SUBSTITUTE or escape_substitute, this)
1388
1393
 
1389
1394
  return f"{left_quote}{this}{right_quote}{escape_sql}"
1390
1395
 
@@ -3569,8 +3574,15 @@ class Generator(metaclass=_Generator):
3569
3574
  kind = self.sql(expression, "kind")
3570
3575
  not_valid = " NOT VALID" if expression.args.get("not_valid") else ""
3571
3576
  check = " WITH CHECK" if expression.args.get("check") else ""
3577
+ this = self.sql(expression, "this")
3578
+ this = f" {this}" if this else ""
3579
+
3580
+ return f"ALTER {kind}{exists}{only}{this}{on_cluster}{check}{self.sep()}{actions_sql}{not_valid}{options}"
3572
3581
 
3573
- return f"ALTER {kind}{exists}{only} {self.sql(expression, 'this')}{on_cluster}{check}{self.sep()}{actions_sql}{not_valid}{options}"
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}"
3574
3586
 
3575
3587
  def add_column_sql(self, expression: exp.Expression) -> str:
3576
3588
  sql = self.sql(expression)
@@ -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), bigquery treats x as the new projection x instead of the table
316
- if is_having and dialect == "bigquery":
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 (literal_index or resolve_table):
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 self._parse_select() or self._parse_set_operations(
7320
- self._parse_alias(self._parse_assignment(), explicit=True)
7321
- if alias
7322
- else self._parse_assignment()
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 self._next:
7597
- self._advance()
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,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlglot
3
- Version: 27.11.0
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
@@ -1,49 +1,49 @@
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=oM65QlZoKN_nkllGdqeZbvnaN1K37Ouzx2i0_B4cs3k,708
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=u7_1s9-VxVvo4SAqC84nktRr-3lw00OwU-_rmGiFm-c,252520
8
- sqlglot/generator.py,sha256=69I3fUEnnE_-JPrqf56B3x12VsN99PRlWIC_QAiFo3E,223240
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=QL4ELtwIv8acNgQ3eFQOfMA-q7N7reAalvvtBb8JIGU,331692
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=gRIc8NnZJcLPdXmsjRysoGWKrM8Fse8sLF7b-uHc6Do,49002
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=fp1uAPhRHOh5yeFtR8NbrpyJFpM-IJ8PsxzTMvSqvnk,69316
24
- sqlglot/dialects/clickhouse.py,sha256=OuaDWpvVrHCF9N-u3ZmHZUCs7DSKq_aaRt8yOh2CtaY,58301
25
- sqlglot/dialects/databricks.py,sha256=761qPlGOFHa9V8mdQYNAEw0pv4HUJYMkGEuFsdsLC7s,4714
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=NvDGHIKGJDVp0b4oOnMu1fyAprJPOiC8J6M85V75iuU,25136
27
+ sqlglot/dialects/doris.py,sha256=CFnF955Oav3IjZWA80ickOI8tPpCjxk7BN5R4Z6pA1U,25263
28
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=vCIjZV9lszyXt-hNylVyUdHHlD_F9zsYznzcZLaqGDg,52241
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=bAZz0qnaOH9f5FyIMkqBu3XB2Cj7y-xnCPbxPsk8U9I,31959
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=DpckKjR3FauVmXDIDaNTFqJE0KzXnW4sUlnZjQC8z0Y,15735
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=YxBHLKOyinFbXSZ720XDzgA7g9KrI5aAnjEl0JBA01w,49592
45
- sqlglot/dialects/snowflake.py,sha256=QvsWQzhabC6zG7QfrBBVc_Dv6E70-xAwTjMg5ExrPeM,70572
46
- sqlglot/dialects/spark.py,sha256=5dKMb9cGl0GMreEyFfjClvW1Cwm1JEx3W-hFnxjqW8E,9362
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
47
  sqlglot/dialects/spark2.py,sha256=qz36FT9k4iuiqboRpyG4VpKGkPR0P2fifmqgZ9gNUEU,14851
48
48
  sqlglot/dialects/sqlite.py,sha256=UIQ66shIt2bQoLd7tYG4NVzh4HwCfERgAaLyukz8HjE,13231
49
49
  sqlglot/dialects/starrocks.py,sha256=2gav0PSNgRdAGXzawdznZliBpglJoQ0wBxPI7ZIMsRw,11314
@@ -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=EweCIUeb9iDuv3Lo0iYHCrqva4G31CwCfrOg_N3IV_8,43936
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.11.0.dist-info/licenses/LICENSE,sha256=p1Yk0B4oa0l8Rh-_dYyy75d8spjPd_vTloXfz4FWxys,1065
80
- sqlglot-27.11.0.dist-info/METADATA,sha256=GoUJQsTzum00ctJVKTRCOnO1d19dqBDV7ptg1MKksWE,20682
81
- sqlglot-27.11.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
82
- sqlglot-27.11.0.dist-info/top_level.txt,sha256=5kRskCGA_gVADF9rSfSzPdLHXqvfMusDYeHePfNY2nQ,8
83
- sqlglot-27.11.0.dist-info/RECORD,,
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,,