sqlglot 27.7.0__py3-none-any.whl → 27.8.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
@@ -1,7 +1,14 @@
1
1
  # file generated by setuptools-scm
2
2
  # don't change, don't track in version control
3
3
 
4
- __all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
5
12
 
6
13
  TYPE_CHECKING = False
7
14
  if TYPE_CHECKING:
@@ -9,13 +16,19 @@ if TYPE_CHECKING:
9
16
  from typing import Union
10
17
 
11
18
  VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
12
20
  else:
13
21
  VERSION_TUPLE = object
22
+ COMMIT_ID = object
14
23
 
15
24
  version: str
16
25
  __version__: str
17
26
  __version_tuple__: VERSION_TUPLE
18
27
  version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
19
30
 
20
- __version__ = version = '27.7.0'
21
- __version_tuple__ = version_tuple = (27, 7, 0)
31
+ __version__ = version = '27.8.0'
32
+ __version_tuple__ = version_tuple = (27, 8, 0)
33
+
34
+ __commit_id__ = commit_id = None
@@ -4,7 +4,7 @@ import logging
4
4
  import re
5
5
  import typing as t
6
6
 
7
- from sqlglot import exp, generator, parser, tokens, transforms
7
+ from sqlglot import exp, generator, jsonpath, parser, tokens, transforms
8
8
  from sqlglot._typing import E
9
9
  from sqlglot.dialects.dialect import (
10
10
  Dialect,
@@ -30,7 +30,6 @@ from sqlglot.dialects.dialect import (
30
30
  unit_to_var,
31
31
  strposition_sql,
32
32
  groupconcat_sql,
33
- space_sql,
34
33
  )
35
34
  from sqlglot.helper import seq_get, split_num_words
36
35
  from sqlglot.tokens import TokenType
@@ -474,6 +473,8 @@ class BigQuery(Dialect):
474
473
  exp.Substring,
475
474
  )
476
475
  },
476
+ exp.ArgMax: lambda self, e: self._annotate_by_args(e, "this"),
477
+ exp.ArgMin: lambda self, e: self._annotate_by_args(e, "this"),
477
478
  exp.Array: _annotate_array,
478
479
  exp.ArrayConcat: lambda self, e: self._annotate_by_args(e, "this", "expressions"),
479
480
  exp.Ascii: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BIGINT),
@@ -495,6 +496,7 @@ class BigQuery(Dialect):
495
496
  exp.GenerateTimestampArray: lambda self, e: self._annotate_with_type(
496
497
  e, exp.DataType.build("ARRAY<TIMESTAMP>", dialect="bigquery")
497
498
  ),
499
+ exp.Grouping: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BIGINT),
498
500
  exp.JSONArray: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.JSON),
499
501
  exp.JSONExtractScalar: lambda self, e: self._annotate_with_type(
500
502
  e, exp.DataType.Type.VARCHAR
@@ -504,9 +506,13 @@ class BigQuery(Dialect):
504
506
  ),
505
507
  exp.JSONType: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.VARCHAR),
506
508
  exp.Lag: lambda self, e: self._annotate_by_args(e, "this", "default"),
509
+ exp.MD5Digest: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BINARY),
507
510
  exp.ParseTime: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.TIME),
508
511
  exp.ParseDatetime: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.DATETIME),
512
+ exp.RegexpExtractAll: lambda self, e: self._annotate_by_args(e, "this", array=True),
513
+ exp.Replace: lambda self, e: self._annotate_by_args(e, "this"),
509
514
  exp.Reverse: lambda self, e: self._annotate_by_args(e, "this"),
515
+ exp.Soundex: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.VARCHAR),
510
516
  exp.SHA: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BINARY),
511
517
  exp.SHA2: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BINARY),
512
518
  exp.Sign: lambda self, e: self._annotate_by_args(e, "this"),
@@ -518,6 +524,7 @@ class BigQuery(Dialect):
518
524
  exp.TimeFromParts: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.TIME),
519
525
  exp.TsOrDsToTime: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.TIME),
520
526
  exp.TimeTrunc: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.TIME),
527
+ exp.Translate: lambda self, e: self._annotate_by_args(e, "this"),
521
528
  exp.Unicode: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.BIGINT),
522
529
  }
523
530
 
@@ -550,6 +557,12 @@ class BigQuery(Dialect):
550
557
 
551
558
  return super().normalize_identifier(expression)
552
559
 
560
+ class JSONPathTokenizer(jsonpath.JSONPathTokenizer):
561
+ VAR_TOKENS = {
562
+ TokenType.DASH,
563
+ TokenType.VAR,
564
+ }
565
+
553
566
  class Tokenizer(tokens.Tokenizer):
554
567
  QUOTES = ["'", '"', '"""', "'''"]
555
568
  COMMENTS = ["--", "#", ("/*", "*/")]
@@ -1019,6 +1032,8 @@ class BigQuery(Dialect):
1019
1032
  EXCEPT_INTERSECT_SUPPORT_ALL_CLAUSE = False
1020
1033
  SUPPORTS_UNIX_SECONDS = True
1021
1034
 
1035
+ SAFE_JSON_PATH_KEY_RE = re.compile(r"^[_\-a-zA-Z][\-\w]*$")
1036
+
1022
1037
  TS_OR_DS_TYPES = (
1023
1038
  exp.TsOrDsToDatetime,
1024
1039
  exp.TsOrDsToTimestamp,
@@ -1107,7 +1122,6 @@ class BigQuery(Dialect):
1107
1122
  ),
1108
1123
  exp.SHA: rename_func("SHA1"),
1109
1124
  exp.SHA2: sha256_sql,
1110
- exp.Space: space_sql,
1111
1125
  exp.StabilityProperty: lambda self, e: (
1112
1126
  "DETERMINISTIC" if e.name == "IMMUTABLE" else "NOT DETERMINISTIC"
1113
1127
  ),
@@ -99,7 +99,11 @@ class Databricks(Spark):
99
99
  exp.JSONExtract: _jsonextract_sql,
100
100
  exp.JSONExtractScalar: _jsonextract_sql,
101
101
  exp.JSONPathRoot: lambda *_: "",
102
- exp.ToChar: lambda self, e: self.function_fallback_sql(e),
102
+ exp.ToChar: lambda self, e: (
103
+ self.cast_sql(exp.Cast(this=e.this, to=exp.DataType(this="STRING")))
104
+ if e.args.get("is_numeric")
105
+ else self.function_fallback_sql(e)
106
+ ),
103
107
  }
104
108
 
105
109
  TRANSFORMS.pop(exp.TryCast)
@@ -35,8 +35,18 @@ DATE_ADD_OR_DIFF = t.Union[
35
35
  exp.TsOrDsDiff,
36
36
  ]
37
37
  DATE_ADD_OR_SUB = t.Union[exp.DateAdd, exp.TsOrDsAdd, exp.DateSub]
38
- JSON_EXTRACT_TYPE = t.Union[exp.JSONExtract, exp.JSONExtractScalar]
39
-
38
+ JSON_EXTRACT_TYPE = t.Union[
39
+ exp.JSONExtract, exp.JSONExtractScalar, exp.JSONBExtract, exp.JSONBExtractScalar
40
+ ]
41
+ DATETIME_DELTA = t.Union[
42
+ exp.DateAdd,
43
+ exp.DatetimeAdd,
44
+ exp.DatetimeSub,
45
+ exp.TimeAdd,
46
+ exp.TimeSub,
47
+ exp.TimestampSub,
48
+ exp.TsOrDsAdd,
49
+ ]
40
50
 
41
51
  if t.TYPE_CHECKING:
42
52
  from sqlglot._typing import B, E, F
@@ -1059,7 +1069,9 @@ class Dialect(metaclass=_Dialect):
1059
1069
  try:
1060
1070
  return parse_json_path(path_text, self)
1061
1071
  except ParseError as e:
1062
- if self.STRICT_JSON_PATH_SYNTAX:
1072
+ if self.STRICT_JSON_PATH_SYNTAX and not path_text.lstrip().startswith(
1073
+ ("lax", "strict")
1074
+ ):
1063
1075
  logger.warning(f"Invalid JSON path syntax. {str(e)}")
1064
1076
 
1065
1077
  return path
@@ -1643,14 +1655,49 @@ def date_delta_sql(name: str, cast: bool = False) -> t.Callable[[Generator, DATE
1643
1655
  return _delta_sql
1644
1656
 
1645
1657
 
1658
+ def date_delta_to_binary_interval_op(
1659
+ cast: bool = True,
1660
+ ) -> t.Callable[[Generator, DATETIME_DELTA], str]:
1661
+ def date_delta_to_binary_interval_op_sql(self: Generator, expression: DATETIME_DELTA) -> str:
1662
+ this = expression.this
1663
+ unit = unit_to_var(expression)
1664
+ op = (
1665
+ "+"
1666
+ if isinstance(expression, (exp.DateAdd, exp.TimeAdd, exp.DatetimeAdd, exp.TsOrDsAdd))
1667
+ else "-"
1668
+ )
1669
+
1670
+ to_type: t.Optional[exp.DATA_TYPE] = None
1671
+ if cast:
1672
+ if isinstance(expression, exp.TsOrDsAdd):
1673
+ to_type = expression.return_type
1674
+ elif this.is_string:
1675
+ # Cast string literals (i.e function parameters) to the appropriate type for +/- interval to work
1676
+ to_type = (
1677
+ exp.DataType.Type.DATETIME
1678
+ if isinstance(expression, (exp.DatetimeAdd, exp.DatetimeSub))
1679
+ else exp.DataType.Type.DATE
1680
+ )
1681
+
1682
+ this = exp.cast(this, to_type) if to_type else this
1683
+
1684
+ expr = expression.expression
1685
+ interval = expr if isinstance(expr, exp.Interval) else exp.Interval(this=expr, unit=unit)
1686
+
1687
+ return f"{self.sql(this)} {op} {self.sql(interval)}"
1688
+
1689
+ return date_delta_to_binary_interval_op_sql
1690
+
1691
+
1646
1692
  def unit_to_str(expression: exp.Expression, default: str = "DAY") -> t.Optional[exp.Expression]:
1647
1693
  unit = expression.args.get("unit")
1694
+ if not unit:
1695
+ return exp.Literal.string(default) if default else None
1648
1696
 
1649
- if isinstance(unit, exp.Placeholder):
1697
+ if isinstance(unit, exp.Placeholder) or type(unit) not in (exp.Var, exp.Literal):
1650
1698
  return unit
1651
- if unit:
1652
- return exp.Literal.string(unit.name)
1653
- return exp.Literal.string(default) if default else None
1699
+
1700
+ return exp.Literal.string(unit.name)
1654
1701
 
1655
1702
 
1656
1703
  def unit_to_var(expression: exp.Expression, default: str = "DAY") -> t.Optional[exp.Expression]:
@@ -1730,7 +1777,10 @@ def merge_without_target_sql(self: Generator, expression: exp.Merge) -> str:
1730
1777
 
1731
1778
 
1732
1779
  def build_json_extract_path(
1733
- expr_type: t.Type[F], zero_based_indexing: bool = True, arrow_req_json_type: bool = False
1780
+ expr_type: t.Type[F],
1781
+ zero_based_indexing: bool = True,
1782
+ arrow_req_json_type: bool = False,
1783
+ json_type: t.Optional[str] = None,
1734
1784
  ) -> t.Callable[[t.List], F]:
1735
1785
  def _builder(args: t.List) -> F:
1736
1786
  segments: t.List[exp.JSONPathPart] = [exp.JSONPathRoot()]
@@ -1750,11 +1800,19 @@ def build_json_extract_path(
1750
1800
 
1751
1801
  # This is done to avoid failing in the expression validator due to the arg count
1752
1802
  del args[2:]
1753
- return expr_type(
1754
- this=seq_get(args, 0),
1755
- expression=exp.JSONPath(expressions=segments),
1756
- only_json_types=arrow_req_json_type,
1757
- )
1803
+ kwargs = {
1804
+ "this": seq_get(args, 0),
1805
+ "expression": exp.JSONPath(expressions=segments),
1806
+ }
1807
+
1808
+ is_jsonb = issubclass(expr_type, (exp.JSONBExtract, exp.JSONBExtractScalar))
1809
+ if not is_jsonb:
1810
+ kwargs["only_json_types"] = arrow_req_json_type
1811
+
1812
+ if json_type is not None:
1813
+ kwargs["json_type"] = json_type
1814
+
1815
+ return expr_type(**kwargs)
1758
1816
 
1759
1817
  return _builder
1760
1818
 
@@ -1962,7 +2020,7 @@ def groupconcat_sql(
1962
2020
  return self.sql(listagg)
1963
2021
 
1964
2022
 
1965
- def build_timetostr_or_tochar(args: t.List, dialect: Dialect) -> exp.TimeToStr | exp.ToChar:
2023
+ def build_timetostr_or_tochar(args: t.List, dialect: DialectType) -> exp.TimeToStr | exp.ToChar:
1966
2024
  if len(args) == 2:
1967
2025
  this = args[0]
1968
2026
  if not this.type:
@@ -1983,12 +2041,3 @@ def build_replace_with_optional_replacement(args: t.List) -> exp.Replace:
1983
2041
  expression=seq_get(args, 1),
1984
2042
  replacement=seq_get(args, 2) or exp.Literal.string(""),
1985
2043
  )
1986
-
1987
-
1988
- def space_sql(self: Generator, expression: exp.Space) -> str:
1989
- return self.sql(
1990
- exp.Repeat(
1991
- this=exp.Literal.string(" "),
1992
- times=expression.this,
1993
- )
1994
- )
@@ -1,14 +1,22 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import typing as t
4
+
3
5
  from sqlglot import expressions as exp
4
6
  from sqlglot import parser, generator, tokens
5
- from sqlglot.dialects.dialect import Dialect, build_formatted_time, unit_to_var
6
- import typing as t
7
+ from sqlglot.dialects.dialect import (
8
+ Dialect,
9
+ build_timetostr_or_tochar,
10
+ build_formatted_time,
11
+ rename_func,
12
+ unit_to_var,
13
+ )
14
+ from sqlglot.helper import seq_get
15
+
16
+ if t.TYPE_CHECKING:
17
+ from sqlglot.dialects.dialect import DialectType
7
18
 
8
- DATE_DELTA = t.Union[
9
- exp.DateAdd,
10
- exp.DateSub,
11
- ]
19
+ DATE_DELTA = t.Union[exp.DateAdd, exp.DateSub]
12
20
 
13
21
 
14
22
  def _date_delta_sql(name: str) -> t.Callable[[Dremio.Generator, DATE_DELTA], str]:
@@ -31,6 +39,17 @@ def _date_delta_sql(name: str) -> t.Callable[[Dremio.Generator, DATE_DELTA], str
31
39
  return _delta_sql
32
40
 
33
41
 
42
+ def to_char_is_numeric_handler(args: t.List, dialect: DialectType) -> exp.TimeToStr | exp.ToChar:
43
+ expression = build_timetostr_or_tochar(args, dialect)
44
+ fmt = seq_get(args, 1)
45
+
46
+ if fmt and isinstance(expression, exp.ToChar) and fmt.is_string and "#" in fmt.name:
47
+ # Only mark as numeric if format is a literal containing #
48
+ expression.set("is_numeric", True)
49
+
50
+ return expression
51
+
52
+
34
53
  class Dremio(Dialect):
35
54
  SUPPORTS_USER_DEFINED_TYPES = False
36
55
  CONCAT_COALESCE = True
@@ -94,7 +113,9 @@ class Dremio(Dialect):
94
113
 
95
114
  FUNCTIONS = {
96
115
  **parser.Parser.FUNCTIONS,
97
- "TO_CHAR": build_formatted_time(exp.TimeToStr, "dremio"),
116
+ "TO_CHAR": to_char_is_numeric_handler,
117
+ "DATE_FORMAT": build_formatted_time(exp.TimeToStr, "dremio"),
118
+ "TO_DATE": build_formatted_time(exp.TsOrDsToDate, "dremio"),
98
119
  }
99
120
 
100
121
  class Generator(generator.Generator):
@@ -123,8 +144,8 @@ class Dremio(Dialect):
123
144
 
124
145
  TRANSFORMS = {
125
146
  **generator.Generator.TRANSFORMS,
147
+ exp.ToChar: rename_func("TO_CHAR"),
126
148
  exp.TimeToStr: lambda self, e: self.func("TO_CHAR", e.this, self.format_time(e)),
127
- exp.ToChar: lambda self, e: self.function_fallback_sql(e),
128
149
  exp.DateAdd: _date_delta_sql("DATE_ADD"),
129
150
  exp.DateSub: _date_delta_sql("DATE_SUB"),
130
151
  }
@@ -4,7 +4,6 @@ import typing as t
4
4
 
5
5
  from sqlglot import exp, generator, parser, tokens, transforms
6
6
 
7
- from sqlglot.expressions import DATA_TYPE
8
7
  from sqlglot.dialects.dialect import (
9
8
  Dialect,
10
9
  JSON_EXTRACT_TYPE,
@@ -16,6 +15,7 @@ from sqlglot.dialects.dialect import (
16
15
  bool_xor_sql,
17
16
  build_default_decimal_type,
18
17
  count_if_to_sum,
18
+ date_delta_to_binary_interval_op,
19
19
  date_trunc_to_time,
20
20
  datestrtodate_sql,
21
21
  no_datetime_sql,
@@ -32,7 +32,6 @@ from sqlglot.dialects.dialect import (
32
32
  str_to_time_sql,
33
33
  timestamptrunc_sql,
34
34
  timestrtotime_sql,
35
- unit_to_var,
36
35
  unit_to_str,
37
36
  sha256_sql,
38
37
  build_regexp_extract,
@@ -45,38 +44,6 @@ from sqlglot.helper import seq_get
45
44
  from sqlglot.tokens import TokenType
46
45
  from sqlglot.parser import binary_range_parser
47
46
 
48
- DATETIME_DELTA = t.Union[
49
- exp.DateAdd, exp.TimeAdd, exp.DatetimeAdd, exp.TsOrDsAdd, exp.DateSub, exp.DatetimeSub
50
- ]
51
-
52
-
53
- def _date_delta_sql(self: DuckDB.Generator, expression: DATETIME_DELTA) -> str:
54
- this = expression.this
55
- unit = unit_to_var(expression)
56
- op = (
57
- "+"
58
- if isinstance(expression, (exp.DateAdd, exp.TimeAdd, exp.DatetimeAdd, exp.TsOrDsAdd))
59
- else "-"
60
- )
61
-
62
- to_type: t.Optional[DATA_TYPE] = None
63
- if isinstance(expression, exp.TsOrDsAdd):
64
- to_type = expression.return_type
65
- elif this.is_string:
66
- # Cast string literals (i.e function parameters) to the appropriate type for +/- interval to work
67
- to_type = (
68
- exp.DataType.Type.DATETIME
69
- if isinstance(expression, (exp.DatetimeAdd, exp.DatetimeSub))
70
- else exp.DataType.Type.DATE
71
- )
72
-
73
- this = exp.cast(this, to_type) if to_type else this
74
-
75
- expr = expression.expression
76
- interval = expr if isinstance(expr, exp.Interval) else exp.Interval(this=expr, unit=unit)
77
-
78
- return f"{self.sql(this)} {op} {self.sql(interval)}"
79
-
80
47
 
81
48
  # BigQuery -> DuckDB conversion for the DATE function
82
49
  def _date_sql(self: DuckDB.Generator, expression: exp.Date) -> str:
@@ -687,14 +654,14 @@ class DuckDB(Dialect):
687
654
  exp.DayOfYear: rename_func("DAYOFYEAR"),
688
655
  exp.DataType: _datatype_sql,
689
656
  exp.Date: _date_sql,
690
- exp.DateAdd: _date_delta_sql,
657
+ exp.DateAdd: date_delta_to_binary_interval_op(),
691
658
  exp.DateFromParts: rename_func("MAKE_DATE"),
692
- exp.DateSub: _date_delta_sql,
659
+ exp.DateSub: date_delta_to_binary_interval_op(),
693
660
  exp.DateDiff: _date_diff_sql,
694
661
  exp.DateStrToDate: datestrtodate_sql,
695
662
  exp.Datetime: no_datetime_sql,
696
- exp.DatetimeSub: _date_delta_sql,
697
- exp.DatetimeAdd: _date_delta_sql,
663
+ exp.DatetimeSub: date_delta_to_binary_interval_op(),
664
+ exp.DatetimeAdd: date_delta_to_binary_interval_op(),
698
665
  exp.DateToDi: lambda self,
699
666
  e: f"CAST(STRFTIME({self.sql(e, 'this')}, {DuckDB.DATEINT_FORMAT}) AS INT)",
700
667
  exp.Decode: lambda self, e: encode_decode_sql(self, e, "DECODE", replace=False),
@@ -756,7 +723,7 @@ class DuckDB(Dialect):
756
723
  ),
757
724
  exp.Struct: _struct_sql,
758
725
  exp.Transform: rename_func("LIST_TRANSFORM"),
759
- exp.TimeAdd: _date_delta_sql,
726
+ exp.TimeAdd: date_delta_to_binary_interval_op(),
760
727
  exp.Time: no_time_sql,
761
728
  exp.TimeDiff: _timediff_sql,
762
729
  exp.Timestamp: no_timestamp_sql,
@@ -773,7 +740,7 @@ class DuckDB(Dialect):
773
740
  exp.TimeToUnix: rename_func("EPOCH"),
774
741
  exp.TsOrDiToDi: lambda self,
775
742
  e: f"CAST(SUBSTR(REPLACE(CAST({self.sql(e, 'this')} AS TEXT), '-', ''), 1, 8) AS INT)",
776
- exp.TsOrDsAdd: _date_delta_sql,
743
+ exp.TsOrDsAdd: date_delta_to_binary_interval_op(),
777
744
  exp.TsOrDsDiff: lambda self, e: self.func(
778
745
  "DATE_DIFF",
779
746
  f"'{e.args.get('unit') or 'DAY'}'",
@@ -109,6 +109,7 @@ class Exasol(Dialect):
109
109
  "ENDIF": TokenType.END,
110
110
  "LONG VARCHAR": TokenType.TEXT,
111
111
  }
112
+ KEYWORDS.pop("DIV")
112
113
 
113
114
  class Parser(parser.Parser):
114
115
  FUNCTIONS = {
@@ -131,6 +132,7 @@ class Exasol(Dialect):
131
132
  "DATE_TRUNC": lambda args: exp.TimestampTrunc(
132
133
  this=seq_get(args, 1), unit=seq_get(args, 0)
133
134
  ),
135
+ "DIV": binary_from_function(exp.IntDiv),
134
136
  "EVERY": lambda args: exp.All(this=seq_get(args, 0)),
135
137
  "EDIT_DISTANCE": exp.Levenshtein.from_arg_list,
136
138
  "HASH_SHA": exp.SHA.from_arg_list,
@@ -228,6 +230,8 @@ class Exasol(Dialect):
228
230
  # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/bit_xor.htm
229
231
  exp.BitwiseXor: rename_func("BIT_XOR"),
230
232
  exp.DateDiff: _date_diff_sql,
233
+ # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/div.htm#DIV
234
+ exp.IntDiv: rename_func("DIV"),
231
235
  exp.TsOrDsDiff: _date_diff_sql,
232
236
  exp.DateTrunc: lambda self, e: self.func("TRUNC", e.this, unit_to_str(e)),
233
237
  exp.DatetimeTrunc: timestamptrunc_sql(),
@@ -280,6 +284,7 @@ class Exasol(Dialect):
280
284
  exp.MD5Digest: rename_func("HASHTYPE_MD5"),
281
285
  # https://docs.exasol.com/db/latest/sql/create_view.htm
282
286
  exp.CommentColumnConstraint: lambda self, e: f"COMMENT IS {self.sql(e, 'this')}",
287
+ exp.WeekOfYear: rename_func("WEEK"),
283
288
  }
284
289
 
285
290
  def converttimezone_sql(self, expression: exp.ConvertTimezone) -> str:
sqlglot/dialects/mysql.py CHANGED
@@ -709,21 +709,6 @@ class MySQL(Dialect):
709
709
 
710
710
  return self.expression(exp.GroupConcat, this=this, separator=separator)
711
711
 
712
- def _parse_json_value(self) -> exp.JSONValue:
713
- this = self._parse_bitwise()
714
- self._match(TokenType.COMMA)
715
- path = self._parse_bitwise()
716
-
717
- returning = self._match(TokenType.RETURNING) and self._parse_type()
718
-
719
- return self.expression(
720
- exp.JSONValue,
721
- this=this,
722
- path=self.dialect.to_json_path(path),
723
- returning=returning,
724
- on_condition=self._parse_on_condition(),
725
- )
726
-
727
712
  def _parse_alter_table_alter_index(self) -> exp.AlterIndex:
728
713
  index = self._parse_field(any_token=True)
729
714
 
@@ -31,7 +31,6 @@ from sqlglot.dialects.dialect import (
31
31
  sequence_sql,
32
32
  build_regexp_extract,
33
33
  explode_to_unnest_sql,
34
- space_sql,
35
34
  )
36
35
  from sqlglot.dialects.hive import Hive
37
36
  from sqlglot.dialects.mysql import MySQL
@@ -506,7 +505,6 @@ class Presto(Dialect):
506
505
  amend_exploded_column_table,
507
506
  ]
508
507
  ),
509
- exp.Space: space_sql,
510
508
  exp.SortArray: _no_sort_array,
511
509
  exp.StrPosition: lambda self, e: strposition_sql(self, e, supports_occurrence=True),
512
510
  exp.StrToDate: lambda self, e: f"CAST({_str_to_time_sql(self, e)} AS DATE)",
@@ -2,7 +2,13 @@ from sqlglot import TokenType
2
2
  import typing as t
3
3
 
4
4
  from sqlglot import exp
5
- from sqlglot.dialects.dialect import build_formatted_time, rename_func
5
+ from sqlglot.dialects.dialect import (
6
+ build_formatted_time,
7
+ build_json_extract_path,
8
+ json_extract_segments,
9
+ json_path_key_only_name,
10
+ rename_func,
11
+ )
6
12
  from sqlglot.dialects.mysql import MySQL
7
13
  from sqlglot.generator import unsupported_args
8
14
  from sqlglot.helper import seq_get
@@ -66,6 +72,27 @@ class SingleStore(MySQL):
66
72
  ),
67
73
  "UNIX_TIMESTAMP": exp.StrToUnix.from_arg_list,
68
74
  "FROM_UNIXTIME": build_formatted_time(exp.UnixToTime, "mysql"),
75
+ "BSON_EXTRACT_BSON": build_json_extract_path(exp.JSONBExtract),
76
+ "BSON_EXTRACT_STRING": build_json_extract_path(
77
+ exp.JSONBExtractScalar, json_type="STRING"
78
+ ),
79
+ "BSON_EXTRACT_DOUBLE": build_json_extract_path(
80
+ exp.JSONBExtractScalar, json_type="DOUBLE"
81
+ ),
82
+ "BSON_EXTRACT_BIGINT": build_json_extract_path(
83
+ exp.JSONBExtractScalar, json_type="BIGINT"
84
+ ),
85
+ "JSON_EXTRACT_JSON": build_json_extract_path(exp.JSONExtract),
86
+ "JSON_EXTRACT_STRING": build_json_extract_path(
87
+ exp.JSONExtractScalar, json_type="STRING"
88
+ ),
89
+ "JSON_EXTRACT_DOUBLE": build_json_extract_path(
90
+ exp.JSONExtractScalar, json_type="DOUBLE"
91
+ ),
92
+ "JSON_EXTRACT_BIGINT": build_json_extract_path(
93
+ exp.JSONExtractScalar, json_type="BIGINT"
94
+ ),
95
+ "DATE": exp.Date.from_arg_list,
69
96
  }
70
97
 
71
98
  CAST_COLUMN_OPERATORS = {TokenType.COLON_GT, TokenType.NCOLON_GT}
@@ -81,9 +108,24 @@ class SingleStore(MySQL):
81
108
  this=this,
82
109
  to=to,
83
110
  ),
111
+ TokenType.DCOLON: lambda self, this, path: build_json_extract_path(exp.JSONExtract)(
112
+ [this, exp.Literal.string(path.name)]
113
+ ),
114
+ TokenType.DCOLONDOLLAR: lambda self, this, path: build_json_extract_path(
115
+ exp.JSONExtractScalar, json_type="STRING"
116
+ )([this, exp.Literal.string(path.name)]),
117
+ TokenType.DCOLONPERCENT: lambda self, this, path: build_json_extract_path(
118
+ exp.JSONExtractScalar, json_type="DOUBLE"
119
+ )([this, exp.Literal.string(path.name)]),
84
120
  }
85
121
 
86
122
  class Generator(MySQL.Generator):
123
+ SUPPORTED_JSON_PATH_PARTS = {
124
+ exp.JSONPathKey,
125
+ exp.JSONPathRoot,
126
+ exp.JSONPathSubscript,
127
+ }
128
+
87
129
  TRANSFORMS = {
88
130
  **MySQL.Generator.TRANSFORMS,
89
131
  exp.TsOrDsToDate: lambda self, e: self.func("TO_DATE", e.this, self.format_time(e)),
@@ -107,6 +149,7 @@ class SingleStore(MySQL):
107
149
  inverse_time_trie=MySQL.INVERSE_TIME_TRIE,
108
150
  ),
109
151
  ),
152
+ exp.Date: unsupported_args("zone", "expressions")(rename_func("DATE")),
110
153
  exp.Cast: unsupported_args("format", "action", "default")(
111
154
  lambda self, e: f"{self.sql(e, 'this')} :> {self.sql(e, 'to')}"
112
155
  ),
@@ -138,7 +181,29 @@ class SingleStore(MySQL):
138
181
  ),
139
182
  ),
140
183
  exp.UnixToTimeStr: lambda self, e: f"FROM_UNIXTIME({self.sql(e, 'this')}) :> TEXT",
184
+ exp.JSONExtract: unsupported_args(
185
+ "only_json_types",
186
+ "expressions",
187
+ "variant_extract",
188
+ "json_query",
189
+ "option",
190
+ "quote",
191
+ "on_condition",
192
+ "requires_json",
193
+ )(json_extract_segments("JSON_EXTRACT_JSON")),
194
+ exp.JSONBExtract: json_extract_segments("BSON_EXTRACT_BSON"),
195
+ exp.JSONPathKey: json_path_key_only_name,
196
+ exp.JSONPathSubscript: lambda self, e: self.json_path_part(e.this),
197
+ exp.JSONPathRoot: lambda *_: "",
141
198
  }
199
+ TRANSFORMS.pop(exp.JSONExtractScalar)
200
+ TRANSFORMS.pop(exp.JSONPathFilter)
201
+ TRANSFORMS.pop(exp.JSONPathRecursive)
202
+ TRANSFORMS.pop(exp.JSONPathScript)
203
+ TRANSFORMS.pop(exp.JSONPathSelector)
204
+ TRANSFORMS.pop(exp.JSONPathSlice)
205
+ TRANSFORMS.pop(exp.JSONPathUnion)
206
+ TRANSFORMS.pop(exp.JSONPathWildcard)
142
207
 
143
208
  # https://docs.singlestore.com/cloud/reference/sql-reference/restricted-keywords/list-of-restricted-keywords/
144
209
  RESERVED_KEYWORDS = {
@@ -1193,3 +1258,31 @@ class SingleStore(MySQL):
1193
1258
  "zerofill",
1194
1259
  "zone",
1195
1260
  }
1261
+
1262
+ def jsonextractscalar_sql(self, expression: exp.JSONExtractScalar) -> str:
1263
+ json_type = expression.args.get("json_type")
1264
+ func_name = "JSON_EXTRACT_JSON" if json_type is None else f"JSON_EXTRACT_{json_type}"
1265
+ return json_extract_segments(func_name)(self, expression)
1266
+
1267
+ def jsonbextractscalar_sql(self, expression: exp.JSONBExtractScalar) -> str:
1268
+ json_type = expression.args.get("json_type")
1269
+ func_name = "BSON_EXTRACT_BSON" if json_type is None else f"BSON_EXTRACT_{json_type}"
1270
+ return json_extract_segments(func_name)(self, expression)
1271
+
1272
+ def jsonextractarray_sql(self, expression: exp.JSONExtractArray) -> str:
1273
+ self.unsupported("Arrays are not supported in SingleStore")
1274
+ return self.function_fallback_sql(expression)
1275
+
1276
+ @unsupported_args("on_condition")
1277
+ def jsonvalue_sql(self, expression: exp.JSONValue) -> str:
1278
+ res: exp.Expression = exp.JSONExtractScalar(
1279
+ this=expression.this,
1280
+ expression=expression.args.get("path"),
1281
+ json_type="STRING",
1282
+ )
1283
+
1284
+ returning = expression.args.get("returning")
1285
+ if returning is not None:
1286
+ res = exp.Cast(this=res, to=returning)
1287
+
1288
+ return self.sql(res)
sqlglot/dialects/spark.py CHANGED
@@ -9,6 +9,7 @@ from sqlglot.dialects.dialect import (
9
9
  unit_to_var,
10
10
  timestampdiff_sql,
11
11
  build_date_delta,
12
+ date_delta_to_binary_interval_op,
12
13
  groupconcat_sql,
13
14
  )
14
15
  from sqlglot.dialects.hive import _build_with_ignore_nulls
@@ -195,13 +196,18 @@ class Spark(Spark2):
195
196
  ]
196
197
  ),
197
198
  exp.DateFromUnixDate: rename_func("DATE_FROM_UNIX_DATE"),
199
+ exp.DatetimeAdd: date_delta_to_binary_interval_op(cast=False),
200
+ exp.DatetimeSub: date_delta_to_binary_interval_op(cast=False),
198
201
  exp.GroupConcat: _groupconcat_sql,
199
202
  exp.EndsWith: rename_func("ENDSWITH"),
200
203
  exp.PartitionedByProperty: lambda self,
201
204
  e: f"PARTITIONED BY {self.wrap(self.expressions(sqls=[_normalize_partition(e) for e in e.this.expressions], skip_first=True))}",
202
205
  exp.StartsWith: rename_func("STARTSWITH"),
206
+ exp.TimeAdd: date_delta_to_binary_interval_op(cast=False),
207
+ exp.TimeSub: date_delta_to_binary_interval_op(cast=False),
203
208
  exp.TsOrDsAdd: _dateadd_sql,
204
209
  exp.TimestampAdd: _dateadd_sql,
210
+ exp.TimestampSub: date_delta_to_binary_interval_op(cast=False),
205
211
  exp.DatetimeDiff: timestampdiff_sql,
206
212
  exp.TimestampDiff: timestampdiff_sql,
207
213
  exp.TryCast: lambda self, e: (
sqlglot/dialects/trino.py CHANGED
@@ -21,6 +21,7 @@ class Trino(Presto):
21
21
  **Presto.Parser.FUNCTION_PARSERS,
22
22
  "TRIM": lambda self: self._parse_trim(),
23
23
  "JSON_QUERY": lambda self: self._parse_json_query(),
24
+ "JSON_VALUE": lambda self: self._parse_json_value(),
24
25
  "LISTAGG": lambda self: self._parse_string_agg(),
25
26
  }
26
27
 
sqlglot/expressions.py CHANGED
@@ -5301,7 +5301,7 @@ class TimeUnit(Expression):
5301
5301
 
5302
5302
  def __init__(self, **args):
5303
5303
  unit = args.get("unit")
5304
- if isinstance(unit, self.VAR_LIKE):
5304
+ if type(unit) in self.VAR_LIKE:
5305
5305
  args["unit"] = Var(
5306
5306
  this=(self.UNABBREVIATED_UNIT_NAME.get(unit.name) or unit.name).upper()
5307
5307
  )
@@ -5464,6 +5464,15 @@ class Transform(Func):
5464
5464
  arg_types = {"this": True, "expression": True}
5465
5465
 
5466
5466
 
5467
+ class Translate(Func):
5468
+ arg_types = {"this": True, "from": True, "to": True}
5469
+
5470
+
5471
+ class Grouping(AggFunc):
5472
+ arg_types = {"expressions": True}
5473
+ is_var_len_args = True
5474
+
5475
+
5467
5476
  class Anonymous(Func):
5468
5477
  arg_types = {"this": True, "expressions": False}
5469
5478
  is_var_len_args = True
@@ -5531,7 +5540,12 @@ class Pad(Func):
5531
5540
  # https://docs.snowflake.com/en/sql-reference/functions/to_char
5532
5541
  # https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/TO_CHAR-number.html
5533
5542
  class ToChar(Func):
5534
- arg_types = {"this": True, "format": False, "nlsparam": False}
5543
+ arg_types = {
5544
+ "this": True,
5545
+ "format": False,
5546
+ "nlsparam": False,
5547
+ "is_numeric": False,
5548
+ }
5535
5549
 
5536
5550
 
5537
5551
  # https://docs.snowflake.com/en/sql-reference/functions/to_decimal
@@ -6508,7 +6522,13 @@ class JSONExtractArray(Func):
6508
6522
 
6509
6523
 
6510
6524
  class JSONExtractScalar(Binary, Func):
6511
- arg_types = {"this": True, "expression": True, "only_json_types": False, "expressions": False}
6525
+ arg_types = {
6526
+ "this": True,
6527
+ "expression": True,
6528
+ "only_json_types": False,
6529
+ "expressions": False,
6530
+ "json_type": False,
6531
+ }
6512
6532
  _sql_names = ["JSON_EXTRACT_SCALAR"]
6513
6533
  is_var_len_args = True
6514
6534
 
@@ -6522,6 +6542,7 @@ class JSONBExtract(Binary, Func):
6522
6542
 
6523
6543
 
6524
6544
  class JSONBExtractScalar(Binary, Func):
6545
+ arg_types = {"this": True, "expression": True, "json_type": False}
6525
6546
  _sql_names = ["JSONB_EXTRACT_SCALAR"]
6526
6547
 
6527
6548
 
@@ -6841,6 +6862,10 @@ class SortArray(Func):
6841
6862
  arg_types = {"this": True, "asc": False}
6842
6863
 
6843
6864
 
6865
+ class Soundex(Func):
6866
+ pass
6867
+
6868
+
6844
6869
  class Split(Func):
6845
6870
  arg_types = {"this": True, "expression": True, "limit": False}
6846
6871
 
sqlglot/generator.py CHANGED
@@ -692,6 +692,8 @@ class Generator(metaclass=_Generator):
692
692
 
693
693
  RESPECT_IGNORE_NULLS_UNSUPPORTED_EXPRESSIONS: t.Tuple[t.Type[exp.Expression], ...] = ()
694
694
 
695
+ SAFE_JSON_PATH_KEY_RE = exp.SAFE_IDENTIFIER_RE
696
+
695
697
  SENTINEL_LINE_BREAK = "__SQLGLOT__LB__"
696
698
 
697
699
  __slots__ = (
@@ -4362,7 +4364,7 @@ class Generator(metaclass=_Generator):
4362
4364
  this = self.json_path_part(this)
4363
4365
  return f".{this}" if this else ""
4364
4366
 
4365
- if exp.SAFE_IDENTIFIER_RE.match(this):
4367
+ if self.SAFE_JSON_PATH_KEY_RE.match(this):
4366
4368
  return f".{this}"
4367
4369
 
4368
4370
  this = self.json_path_part(this)
@@ -5146,3 +5148,6 @@ class Generator(metaclass=_Generator):
5146
5148
  unit=exp.var("DAY"),
5147
5149
  )
5148
5150
  )
5151
+
5152
+ def space_sql(self: Generator, expression: exp.Space) -> str:
5153
+ return self.sql(exp.Repeat(this=exp.Literal.string(" "), times=expression.this))
sqlglot/jsonpath.py CHANGED
@@ -36,6 +36,10 @@ class JSONPathTokenizer(Tokenizer):
36
36
  IDENTIFIER_ESCAPES = ["\\"]
37
37
  STRING_ESCAPES = ["\\"]
38
38
 
39
+ VAR_TOKENS = {
40
+ TokenType.VAR,
41
+ }
42
+
39
43
 
40
44
  def parse(path: str, dialect: DialectType = None) -> exp.JSONPath:
41
45
  """Takes in a JSON path string and parses it into a JSONPath expression."""
@@ -76,6 +80,9 @@ def parse(path: str, dialect: DialectType = None) -> exp.JSONPath:
76
80
  raise ParseError(_error(f"Expected {token_type}"))
77
81
  return None
78
82
 
83
+ def _match_set(types: t.Collection[TokenType]) -> t.Optional[Token]:
84
+ return _advance() if _curr() in types else None
85
+
79
86
  def _parse_literal() -> t.Any:
80
87
  token = _match(TokenType.STRING) or _match(TokenType.IDENTIFIER)
81
88
  if token:
@@ -155,7 +162,7 @@ def parse(path: str, dialect: DialectType = None) -> exp.JSONPath:
155
162
  """
156
163
  prev_index = i - 2
157
164
 
158
- while _match(TokenType.VAR):
165
+ while _match_set(jsonpath_tokenizer.VAR_TOKENS):
159
166
  pass
160
167
 
161
168
  start = 0 if prev_index < 0 else tokens[prev_index].end + 1
@@ -177,7 +184,7 @@ def parse(path: str, dialect: DialectType = None) -> exp.JSONPath:
177
184
  if _match(TokenType.DOT) or _match(TokenType.COLON):
178
185
  recursive = _prev().text == ".."
179
186
 
180
- if _match(TokenType.VAR):
187
+ if _match_set(jsonpath_tokenizer.VAR_TOKENS):
181
188
  value: t.Optional[str | exp.JSONPathWildcard] = _parse_var_text()
182
189
  elif _match(TokenType.IDENTIFIER):
183
190
  value = _prev().text
@@ -194,7 +201,7 @@ def parse(path: str, dialect: DialectType = None) -> exp.JSONPath:
194
201
  raise ParseError(_error("Expected key name or * after DOT"))
195
202
  elif _match(TokenType.L_BRACKET):
196
203
  expressions.append(_parse_bracket())
197
- elif _match(TokenType.VAR):
204
+ elif _match_set(jsonpath_tokenizer.VAR_TOKENS):
198
205
  expressions.append(exp.JSONPathKey(this=_parse_var_text()))
199
206
  elif _match(TokenType.IDENTIFIER):
200
207
  expressions.append(exp.JSONPathKey(this=_prev().text))
sqlglot/parser.py CHANGED
@@ -577,7 +577,6 @@ class Parser(metaclass=_Parser):
577
577
 
578
578
  TABLE_ALIAS_TOKENS = ID_VAR_TOKENS - {
579
579
  TokenType.ANTI,
580
- TokenType.APPLY,
581
580
  TokenType.ASOF,
582
581
  TokenType.FULL,
583
582
  TokenType.LEFT,
@@ -8708,3 +8707,18 @@ class Parser(metaclass=_Parser):
8708
8707
  kwargs["requires_string"] = self.dialect.TRY_CAST_REQUIRES_STRING
8709
8708
 
8710
8709
  return self.expression(exp_class, **kwargs)
8710
+
8711
+ def _parse_json_value(self) -> exp.JSONValue:
8712
+ this = self._parse_bitwise()
8713
+ self._match(TokenType.COMMA)
8714
+ path = self._parse_bitwise()
8715
+
8716
+ returning = self._match(TokenType.RETURNING) and self._parse_type()
8717
+
8718
+ return self.expression(
8719
+ exp.JSONValue,
8720
+ this=this,
8721
+ path=self.dialect.to_json_path(path),
8722
+ returning=returning,
8723
+ on_condition=self._parse_on_condition(),
8724
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlglot
3
- Version: 27.7.0
3
+ Version: 27.8.0
4
4
  Summary: An easily customizable SQL parser and transpiler
5
5
  Author-email: Toby Mao <toby.mao@gmail.com>
6
6
  Project-URL: Homepage, https://sqlglot.com/
@@ -256,7 +256,7 @@ sqlglot.errors.ParseError: Expecting ). Line 1, Col: 34.
256
256
  Structured syntax errors are accessible for programmatic use:
257
257
 
258
258
  ```python
259
- import sqlglot
259
+ import sqlglot.errors
260
260
  try:
261
261
  sqlglot.transpile("SELECT foo FROM (SELECT baz FROM t")
262
262
  except sqlglot.errors.ParseError as e:
@@ -1,15 +1,15 @@
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=5PUg50O7n_si_pQEvZg7Hxhtah6hzWUX8K6MSHG_oxc,513
4
+ sqlglot/_version.py,sha256=6Bcdz-xEd_4XJzvpG14av5V0A6AT1_hYMo5MIczQYNw,706
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=Odk7emY-OtfIxyqDdhqgHM4m7AEvKGLo7nCDML2Y3Dw,247140
8
- sqlglot/generator.py,sha256=hXFm8cL3QTVHrUKz0vNK0PnymYHWxHk4Gzy_4bepjxg,219142
7
+ sqlglot/expressions.py,sha256=qtKgdbejSFXnsDcIZ8XT6wR6EXrtru7U2G4edUyVzU4,247540
8
+ sqlglot/generator.py,sha256=KXHnyJQKSq2Xy5RBDC-6GAW_zJqcNsHhZFV4P13l_iU,219354
9
9
  sqlglot/helper.py,sha256=9nZjFVRBtMKFC3EdzpDQ6jkazFO19po6BF8xHiNGZIo,15111
10
- sqlglot/jsonpath.py,sha256=jneO-A57n4ojVT2drCn2HBlx_Ka8wLcGpemW1JgvbjA,7666
10
+ sqlglot/jsonpath.py,sha256=SQgaxzaEYBN7At9dkTK4N1Spk6xHxvHL6QtCIP6iM30,7905
11
11
  sqlglot/lineage.py,sha256=Qj5ykuDNcATppb9vOjoIKBqRVLbu3OMPiZk9f3iyv40,15312
12
- sqlglot/parser.py,sha256=Pt0uy-MgeTNYqwLMgiLhgB_hk2HlOJMFV1rDC-JrmlQ,328778
12
+ sqlglot/parser.py,sha256=3DexBAzFLyrg4eEgNffcHB9d1ugwsxrFoZBWttRnmto,329221
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
@@ -20,36 +20,36 @@ sqlglot/transforms.py,sha256=utNDsCBsA7hPUK3-aby3DDgiY_XVMAKQqeoLm1EyihI,41218
20
20
  sqlglot/trie.py,sha256=v27uXMrHfqrXlJ6GmeTSMovsB_3o0ctnlKhdNt7W6fI,2245
21
21
  sqlglot/dialects/__init__.py,sha256=BQUv9EuMmvhP_wVitGLo0PlCi15atvfXgvREpsTsxeQ,3799
22
22
  sqlglot/dialects/athena.py,sha256=ofArmayYLev4qZQ15GM8mevG04qqR5WGFb2ZcuYm6x4,10966
23
- sqlglot/dialects/bigquery.py,sha256=d9RdAVLTIgHaOYi6INMNQL38S_zagdl9vNbIL_Ds21c,58896
23
+ sqlglot/dialects/bigquery.py,sha256=OAzuqTOGti3_US_oa0s0LWP56LjBaxTJ1B8tVZBgwVY,59733
24
24
  sqlglot/dialects/clickhouse.py,sha256=ygkVXh8fAxQ2sPvsDIP3y-1bUxV2PSLeS-983MI1uKs,57780
25
- sqlglot/dialects/databricks.py,sha256=mJN2lFpqgH95x3mtry3qWbuRf4q7NV5jbRAOspqclzY,4548
26
- sqlglot/dialects/dialect.py,sha256=g6gUxzNFXJYFDYkDJY314pup63-2OvGek2kdufEn59g,71267
25
+ sqlglot/dialects/databricks.py,sha256=761qPlGOFHa9V8mdQYNAEw0pv4HUJYMkGEuFsdsLC7s,4714
26
+ sqlglot/dialects/dialect.py,sha256=QXis6e9a0jX02QbtqpEKGXDY-gWa46EWOv14k9TE_zE,73001
27
27
  sqlglot/dialects/doris.py,sha256=HT3NyPORz8E1Kk6nNT00CEe4cwz1CfXGhhBcg8Hht1s,21709
28
- sqlglot/dialects/dremio.py,sha256=vOVu-L9QYLMV8gkbY6vfDh_iffhw3D58IKk0yqvd0Lo,4512
28
+ sqlglot/dialects/dremio.py,sha256=opJ6QbsJJwhJRH4josxwkw28M_ABgP6zMY30-A6JFdg,5189
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=kZ1LkGEtztkYwxh8Oad2GHUpmeM226h_uxSoCQ114Bo,52892
31
+ sqlglot/dialects/duckdb.py,sha256=YUne3dZOD-nRlf_JGK5EcT_DJt9I0w7byeYuPcXvKvo,51894
32
32
  sqlglot/dialects/dune.py,sha256=gALut-fFfN2qMsr8LvZ1NQK3F3W9z2f4PwMvTMXVVVg,375
33
- sqlglot/dialects/exasol.py,sha256=w73rFG7jQVkBm2plWR8I12LMkHQVPofsEgWRf6VmiI8,14269
33
+ sqlglot/dialects/exasol.py,sha256=vvoL5QcPF6eBoXuZF_iRc_VpF0OviRNjtWD0ER59xqI,14554
34
34
  sqlglot/dialects/fabric.py,sha256=4Sng2ZhQSaf6eK3ituR9DqDZERaVwYS_UfdpusjsISg,10220
35
35
  sqlglot/dialects/hive.py,sha256=bAZz0qnaOH9f5FyIMkqBu3XB2Cj7y-xnCPbxPsk8U9I,31959
36
36
  sqlglot/dialects/materialize.py,sha256=LD2q1kTRrCwkIu1BfoBvnjTGbupDtoQ8JQMDCIYAXHg,3533
37
- sqlglot/dialects/mysql.py,sha256=J_88qeXxC_oD09yMiNgw_so3x2QlaqL5l7CRku1R6wo,49280
37
+ sqlglot/dialects/mysql.py,sha256=ds_dsTw1ZzsoW0tRbxpKOB9fVaIpXb9t1Hqa9n5MGX0,48764
38
38
  sqlglot/dialects/oracle.py,sha256=DpckKjR3FauVmXDIDaNTFqJE0KzXnW4sUlnZjQC8z0Y,15735
39
39
  sqlglot/dialects/postgres.py,sha256=8QF9uEXXFAGCXQah1n8mv4fonF58o0n59Il66hOZYqI,33942
40
- sqlglot/dialects/presto.py,sha256=Tm3Bx9AJilT1xlgunTpF0wUhIZBOPS-rB5Iwitnygxc,33462
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=MXI9W7CgKCtMNjNRPcZPxO8NBA9_PxZx14HB52o-aUc,15822
43
43
  sqlglot/dialects/risingwave.py,sha256=BqWwW1iT_OIVMwfRamaww79snnBwIgCfr22Go-ggO68,3289
44
- sqlglot/dialects/singlestore.py,sha256=dJp28vf7e9j87U7wnJF7cmXul9sypY1dU0vjZx63Fkc,31363
44
+ sqlglot/dialects/singlestore.py,sha256=FQzHqeFQd_nBisCIcUK4-4cbLr8bjnAcbVNN7LI7HPk,35533
45
45
  sqlglot/dialects/snowflake.py,sha256=XPsqYGBjn3dfddF2dcuM7Ur-4sYdthjW7cSPnptWq_s,70542
46
- sqlglot/dialects/spark.py,sha256=qVZ96NqRnj2YhphWoJhRJTcwmrmNfXD2g442tL3MTrs,8956
46
+ sqlglot/dialects/spark.py,sha256=5dKMb9cGl0GMreEyFfjClvW1Cwm1JEx3W-hFnxjqW8E,9362
47
47
  sqlglot/dialects/spark2.py,sha256=aCwPqLduLRSUSPtbI1VtBjydK6haKgEy3iahmueGRo4,14742
48
48
  sqlglot/dialects/sqlite.py,sha256=XIDmiNTswWcrDwlFm8gOODCrJ_rPmXQKkm9U_-YAlVs,13183
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
52
- sqlglot/dialects/trino.py,sha256=wgLsiX1NQvjGny_rgrU1e2r6kK1LD0KgaSdIDrYmjD0,4285
52
+ sqlglot/dialects/trino.py,sha256=Z7prRhCxIBh0KCxIQpWmVOIGHCJM9Xl5oRlqySxln4Y,4350
53
53
  sqlglot/dialects/tsql.py,sha256=sz1t79iCcsMXw8PKYnKldZJbAQ2iobNsqLPVAj-QTXk,54036
54
54
  sqlglot/executor/__init__.py,sha256=FslewzYQtQdDNg_0Ju2UaiP4vo4IMUgkfkmFsYUhcN0,2958
55
55
  sqlglot/executor/context.py,sha256=WJHJdYQCOeVXwLw0uSSrWSc25eBMn5Ix108RCvdsKRQ,3386
@@ -76,8 +76,8 @@ sqlglot/optimizer/qualify_tables.py,sha256=dA4ZazL7ShQh2JgBwpHuG-4c5lBw1TNzCnuN7
76
76
  sqlglot/optimizer/scope.py,sha256=T6iVYnYwubt-WB1BOFsFYdJ-D7WtWZGL37SuCRQK23s,31154
77
77
  sqlglot/optimizer/simplify.py,sha256=-_yus42OYwqjQ9a2TSGhtG2G0pSkInUry1z7hEMz2pY,51062
78
78
  sqlglot/optimizer/unnest_subqueries.py,sha256=kzWUVDlxs8z9nmRx-8U-pHXPtVZhEIwkKqmKhr2QLvc,10908
79
- sqlglot-27.7.0.dist-info/licenses/LICENSE,sha256=p1Yk0B4oa0l8Rh-_dYyy75d8spjPd_vTloXfz4FWxys,1065
80
- sqlglot-27.7.0.dist-info/METADATA,sha256=hzW8lPG_bNI-kTX-iNRWj2ntlxyQRdHI-O3vUQU0_64,19437
81
- sqlglot-27.7.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
82
- sqlglot-27.7.0.dist-info/top_level.txt,sha256=5kRskCGA_gVADF9rSfSzPdLHXqvfMusDYeHePfNY2nQ,8
83
- sqlglot-27.7.0.dist-info/RECORD,,
79
+ sqlglot-27.8.0.dist-info/licenses/LICENSE,sha256=p1Yk0B4oa0l8Rh-_dYyy75d8spjPd_vTloXfz4FWxys,1065
80
+ sqlglot-27.8.0.dist-info/METADATA,sha256=wmjTJpMM7ieiqzI1z-VsjfHD7NH6NzBycgCo0Of-OgY,19444
81
+ sqlglot-27.8.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
82
+ sqlglot-27.8.0.dist-info/top_level.txt,sha256=5kRskCGA_gVADF9rSfSzPdLHXqvfMusDYeHePfNY2nQ,8
83
+ sqlglot-27.8.0.dist-info/RECORD,,