sqlglot 26.29.0__py3-none-any.whl → 26.30.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/__init__.py +1 -0
- sqlglot/dialects/bigquery.py +1 -0
- sqlglot/dialects/clickhouse.py +2 -0
- sqlglot/dialects/dialect.py +12 -4
- sqlglot/dialects/duckdb.py +1 -0
- sqlglot/dialects/fabric.py +88 -0
- sqlglot/dialects/hive.py +1 -0
- sqlglot/dialects/oracle.py +15 -0
- sqlglot/dialects/presto.py +1 -0
- sqlglot/dialects/prql.py +5 -1
- sqlglot/dialects/redshift.py +1 -0
- sqlglot/dialects/snowflake.py +1 -0
- sqlglot/dialects/spark.py +17 -0
- sqlglot/dialects/sqlite.py +4 -3
- sqlglot/expressions.py +2 -1
- sqlglot/parser.py +96 -75
- {sqlglot-26.29.0.dist-info → sqlglot-26.30.0.dist-info}/METADATA +1 -1
- {sqlglot-26.29.0.dist-info → sqlglot-26.30.0.dist-info}/RECORD +22 -21
- {sqlglot-26.29.0.dist-info → sqlglot-26.30.0.dist-info}/WHEEL +0 -0
- {sqlglot-26.29.0.dist-info → sqlglot-26.30.0.dist-info}/licenses/LICENSE +0 -0
- {sqlglot-26.29.0.dist-info → sqlglot-26.30.0.dist-info}/top_level.txt +0 -0
sqlglot/_version.py
CHANGED
sqlglot/dialects/__init__.py
CHANGED
sqlglot/dialects/bigquery.py
CHANGED
@@ -524,6 +524,7 @@ class BigQuery(Dialect):
|
|
524
524
|
PREFIXED_PIVOT_COLUMNS = True
|
525
525
|
LOG_DEFAULTS_TO_LN = True
|
526
526
|
SUPPORTS_IMPLICIT_UNNEST = True
|
527
|
+
JOINS_HAVE_EQUAL_PRECEDENCE = True
|
527
528
|
|
528
529
|
# BigQuery does not allow ASC/DESC to be used as an identifier
|
529
530
|
ID_VAR_TOKENS = parser.Parser.ID_VAR_TOKENS - {TokenType.ASC, TokenType.DESC}
|
sqlglot/dialects/clickhouse.py
CHANGED
@@ -297,6 +297,7 @@ class ClickHouse(Dialect):
|
|
297
297
|
MODIFIERS_ATTACHED_TO_SET_OP = False
|
298
298
|
INTERVAL_SPANS = False
|
299
299
|
OPTIONAL_ALIAS_TOKEN_CTE = False
|
300
|
+
JOINS_HAVE_EQUAL_PRECEDENCE = True
|
300
301
|
|
301
302
|
FUNCTIONS = {
|
302
303
|
**parser.Parser.FUNCTIONS,
|
@@ -691,6 +692,7 @@ class ClickHouse(Dialect):
|
|
691
692
|
parse_bracket: bool = False,
|
692
693
|
is_db_reference: bool = False,
|
693
694
|
parse_partition: bool = False,
|
695
|
+
consume_pipe: bool = False,
|
694
696
|
) -> t.Optional[exp.Expression]:
|
695
697
|
this = super()._parse_table(
|
696
698
|
schema=schema,
|
sqlglot/dialects/dialect.py
CHANGED
@@ -77,6 +77,7 @@ class Dialects(str, Enum):
|
|
77
77
|
DRUID = "druid"
|
78
78
|
DUCKDB = "duckdb"
|
79
79
|
DUNE = "dune"
|
80
|
+
FABRIC = "fabric"
|
80
81
|
HIVE = "hive"
|
81
82
|
MATERIALIZE = "materialize"
|
82
83
|
MYSQL = "mysql"
|
@@ -1906,12 +1907,19 @@ def groupconcat_sql(
|
|
1906
1907
|
|
1907
1908
|
def build_timetostr_or_tochar(args: t.List, dialect: Dialect) -> exp.TimeToStr | exp.ToChar:
|
1908
1909
|
this = seq_get(args, 0)
|
1910
|
+
format = seq_get(args, 1)
|
1909
1911
|
|
1910
|
-
if this
|
1911
|
-
|
1912
|
+
if this:
|
1913
|
+
if not this.type:
|
1914
|
+
from sqlglot.optimizer.annotate_types import annotate_types
|
1915
|
+
|
1916
|
+
annotate_types(this, dialect=dialect)
|
1912
1917
|
|
1913
|
-
|
1914
|
-
|
1918
|
+
from sqlglot.dialects import Snowflake
|
1919
|
+
|
1920
|
+
if this.is_type(*exp.DataType.TEMPORAL_TYPES) or (
|
1921
|
+
isinstance(format, exp.Literal) and format.name in Snowflake.TIME_MAPPING
|
1922
|
+
):
|
1915
1923
|
dialect_name = dialect.__class__.__name__.lower()
|
1916
1924
|
return build_formatted_time(exp.TimeToStr, dialect_name, default=True)(args)
|
1917
1925
|
|
sqlglot/dialects/duckdb.py
CHANGED
@@ -508,6 +508,7 @@ class DuckDB(Dialect):
|
|
508
508
|
parse_bracket: bool = False,
|
509
509
|
is_db_reference: bool = False,
|
510
510
|
parse_partition: bool = False,
|
511
|
+
consume_pipe: bool = False,
|
511
512
|
) -> t.Optional[exp.Expression]:
|
512
513
|
# DuckDB supports prefix aliases, e.g. FROM foo: bar
|
513
514
|
if self._next and self._next.token_type == TokenType.COLON:
|
@@ -0,0 +1,88 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from sqlglot import exp
|
4
|
+
from sqlglot.dialects.dialect import NormalizationStrategy
|
5
|
+
from sqlglot.dialects.tsql import TSQL
|
6
|
+
|
7
|
+
|
8
|
+
class Fabric(TSQL):
|
9
|
+
"""
|
10
|
+
Microsoft Fabric Data Warehouse dialect that inherits from T-SQL.
|
11
|
+
|
12
|
+
Microsoft Fabric is a cloud-based analytics platform that provides a unified
|
13
|
+
data warehouse experience. While it shares much of T-SQL's syntax, it has
|
14
|
+
specific differences and limitations that this dialect addresses.
|
15
|
+
|
16
|
+
Key differences from T-SQL:
|
17
|
+
- Case-sensitive identifiers (unlike T-SQL which is case-insensitive)
|
18
|
+
- Limited data type support with mappings to supported alternatives
|
19
|
+
- Temporal types (DATETIME2, DATETIMEOFFSET, TIME) limited to 6 digits precision
|
20
|
+
- Certain legacy types (MONEY, SMALLMONEY, etc.) are not supported
|
21
|
+
- Unicode types (NCHAR, NVARCHAR) are mapped to non-unicode equivalents
|
22
|
+
|
23
|
+
References:
|
24
|
+
- Data Types: https://learn.microsoft.com/en-us/fabric/data-warehouse/data-types
|
25
|
+
- T-SQL Surface Area: https://learn.microsoft.com/en-us/fabric/data-warehouse/tsql-surface-area
|
26
|
+
"""
|
27
|
+
|
28
|
+
# Fabric is case-sensitive unlike T-SQL which is case-insensitive
|
29
|
+
NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_SENSITIVE
|
30
|
+
|
31
|
+
class Generator(TSQL.Generator):
|
32
|
+
# Fabric-specific type mappings - override T-SQL types that aren't supported
|
33
|
+
# Reference: https://learn.microsoft.com/en-us/fabric/data-warehouse/data-types
|
34
|
+
TYPE_MAPPING = {
|
35
|
+
**TSQL.Generator.TYPE_MAPPING,
|
36
|
+
# Fabric doesn't support these types, map to alternatives
|
37
|
+
exp.DataType.Type.MONEY: "DECIMAL",
|
38
|
+
exp.DataType.Type.SMALLMONEY: "DECIMAL",
|
39
|
+
exp.DataType.Type.DATETIME: "DATETIME2(6)",
|
40
|
+
exp.DataType.Type.SMALLDATETIME: "DATETIME2(6)",
|
41
|
+
exp.DataType.Type.NCHAR: "CHAR",
|
42
|
+
exp.DataType.Type.NVARCHAR: "VARCHAR",
|
43
|
+
exp.DataType.Type.TEXT: "VARCHAR(MAX)",
|
44
|
+
exp.DataType.Type.IMAGE: "VARBINARY",
|
45
|
+
exp.DataType.Type.TINYINT: "SMALLINT",
|
46
|
+
exp.DataType.Type.UTINYINT: "SMALLINT", # T-SQL parses TINYINT as UTINYINT
|
47
|
+
exp.DataType.Type.JSON: "VARCHAR",
|
48
|
+
exp.DataType.Type.XML: "VARCHAR",
|
49
|
+
exp.DataType.Type.UUID: "VARBINARY(MAX)", # UNIQUEIDENTIFIER has limitations in Fabric
|
50
|
+
# Override T-SQL mappings that use different names in Fabric
|
51
|
+
exp.DataType.Type.DECIMAL: "DECIMAL", # T-SQL uses NUMERIC
|
52
|
+
exp.DataType.Type.DOUBLE: "FLOAT",
|
53
|
+
exp.DataType.Type.INT: "INT", # T-SQL uses INTEGER
|
54
|
+
}
|
55
|
+
|
56
|
+
def datatype_sql(self, expression: exp.DataType) -> str:
|
57
|
+
"""
|
58
|
+
Override datatype generation to handle Fabric-specific precision limitations.
|
59
|
+
|
60
|
+
Fabric limits temporal types (TIME, DATETIME2, DATETIMEOFFSET) to max 6 digits precision.
|
61
|
+
When no precision is specified, we default to 6 digits.
|
62
|
+
"""
|
63
|
+
if expression.is_type(
|
64
|
+
exp.DataType.Type.TIME,
|
65
|
+
exp.DataType.Type.DATETIME2,
|
66
|
+
exp.DataType.Type.TIMESTAMPTZ, # DATETIMEOFFSET in Fabric
|
67
|
+
):
|
68
|
+
# Get the current precision (first expression if it exists)
|
69
|
+
precision = expression.find(exp.DataTypeParam)
|
70
|
+
|
71
|
+
# Determine the target precision
|
72
|
+
if precision is None:
|
73
|
+
# No precision specified, default to 6
|
74
|
+
target_precision = 6
|
75
|
+
elif precision.this.is_int:
|
76
|
+
# Cap precision at 6
|
77
|
+
current_precision = precision.this.to_py()
|
78
|
+
target_precision = min(current_precision, 6)
|
79
|
+
|
80
|
+
# Create a new expression with the target precision
|
81
|
+
new_expression = exp.DataType(
|
82
|
+
this=expression.this,
|
83
|
+
expressions=[exp.DataTypeParam(this=exp.Literal.number(target_precision))],
|
84
|
+
)
|
85
|
+
|
86
|
+
return super().datatype_sql(new_expression)
|
87
|
+
|
88
|
+
return super().datatype_sql(expression)
|
sqlglot/dialects/hive.py
CHANGED
sqlglot/dialects/oracle.py
CHANGED
@@ -128,6 +128,7 @@ class Oracle(Dialect):
|
|
128
128
|
"NEXT": lambda self: self._parse_next_value_for(),
|
129
129
|
"PRIOR": lambda self: self.expression(exp.Prior, this=self._parse_bitwise()),
|
130
130
|
"SYSDATE": lambda self: self.expression(exp.CurrentTimestamp, sysdate=True),
|
131
|
+
"DBMS_RANDOM": lambda self: self._parse_dbms_random(),
|
131
132
|
}
|
132
133
|
|
133
134
|
FUNCTION_PARSERS: t.Dict[str, t.Callable] = {
|
@@ -177,6 +178,19 @@ class Oracle(Dialect):
|
|
177
178
|
),
|
178
179
|
}
|
179
180
|
|
181
|
+
def _parse_dbms_random(self) -> t.Optional[exp.Expression]:
|
182
|
+
if self._match_text_seq(".", "VALUE"):
|
183
|
+
lower, upper = None, None
|
184
|
+
if self._match(TokenType.L_PAREN, advance=False):
|
185
|
+
lower_upper = self._parse_wrapped_csv(self._parse_bitwise)
|
186
|
+
if len(lower_upper) == 2:
|
187
|
+
lower, upper = lower_upper
|
188
|
+
|
189
|
+
return exp.Rand(lower=lower, upper=upper)
|
190
|
+
|
191
|
+
self._retreat(self._index - 1)
|
192
|
+
return None
|
193
|
+
|
180
194
|
def _parse_json_array(self, expr_type: t.Type[E], **kwargs) -> E:
|
181
195
|
return self.expression(
|
182
196
|
expr_type,
|
@@ -299,6 +313,7 @@ class Oracle(Dialect):
|
|
299
313
|
exp.LogicalOr: rename_func("MAX"),
|
300
314
|
exp.LogicalAnd: rename_func("MIN"),
|
301
315
|
exp.Mod: rename_func("MOD"),
|
316
|
+
exp.Rand: rename_func("DBMS_RANDOM.VALUE"),
|
302
317
|
exp.Select: transforms.preprocess(
|
303
318
|
[
|
304
319
|
transforms.eliminate_distinct_on,
|
sqlglot/dialects/presto.py
CHANGED
sqlglot/dialects/prql.py
CHANGED
@@ -189,11 +189,15 @@ class PRQL(Dialect):
|
|
189
189
|
parse_bracket: bool = False,
|
190
190
|
is_db_reference: bool = False,
|
191
191
|
parse_partition: bool = False,
|
192
|
+
consume_pipe: bool = False,
|
192
193
|
) -> t.Optional[exp.Expression]:
|
193
194
|
return self._parse_table_parts()
|
194
195
|
|
195
196
|
def _parse_from(
|
196
|
-
self,
|
197
|
+
self,
|
198
|
+
joins: bool = False,
|
199
|
+
skip_from_token: bool = False,
|
200
|
+
consume_pipe: bool = False,
|
197
201
|
) -> t.Optional[exp.From]:
|
198
202
|
if not skip_from_token and not self._match(TokenType.FROM):
|
199
203
|
return None
|
sqlglot/dialects/redshift.py
CHANGED
@@ -90,6 +90,7 @@ class Redshift(Postgres):
|
|
90
90
|
parse_bracket: bool = False,
|
91
91
|
is_db_reference: bool = False,
|
92
92
|
parse_partition: bool = False,
|
93
|
+
consume_pipe: bool = False,
|
93
94
|
) -> t.Optional[exp.Expression]:
|
94
95
|
# Redshift supports UNPIVOTing SUPER objects, e.g. `UNPIVOT foo.obj[0] AS val AT attr`
|
95
96
|
unpivot = self._match(TokenType.UNPIVOT)
|
sqlglot/dialects/snowflake.py
CHANGED
sqlglot/dialects/spark.py
CHANGED
@@ -7,6 +7,7 @@ from sqlglot.dialects.dialect import rename_func, unit_to_var, timestampdiff_sql
|
|
7
7
|
from sqlglot.dialects.hive import _build_with_ignore_nulls
|
8
8
|
from sqlglot.dialects.spark2 import Spark2, temporary_storage_provider, _build_as_cast
|
9
9
|
from sqlglot.helper import ensure_list, seq_get
|
10
|
+
from sqlglot.tokens import TokenType
|
10
11
|
from sqlglot.transforms import (
|
11
12
|
ctas_with_tmp_tables_to_create_tmp_view,
|
12
13
|
remove_unique_constraints,
|
@@ -121,6 +122,16 @@ class Spark(Spark2):
|
|
121
122
|
),
|
122
123
|
}
|
123
124
|
|
125
|
+
PLACEHOLDER_PARSERS = {
|
126
|
+
**Spark2.Parser.PLACEHOLDER_PARSERS,
|
127
|
+
TokenType.L_BRACE: lambda self: self._parse_query_parameter(),
|
128
|
+
}
|
129
|
+
|
130
|
+
def _parse_query_parameter(self) -> t.Optional[exp.Expression]:
|
131
|
+
this = self._parse_id_var()
|
132
|
+
self._match(TokenType.R_BRACE)
|
133
|
+
return self.expression(exp.Placeholder, this=this, widget=True)
|
134
|
+
|
124
135
|
def _parse_generated_as_identity(
|
125
136
|
self,
|
126
137
|
) -> (
|
@@ -200,3 +211,9 @@ class Spark(Spark2):
|
|
200
211
|
return self.func("DATEDIFF", unit_to_var(expression), start, end)
|
201
212
|
|
202
213
|
return self.func("DATEDIFF", end, start)
|
214
|
+
|
215
|
+
def placeholder_sql(self, expression: exp.Placeholder) -> str:
|
216
|
+
if not expression.args.get("widget"):
|
217
|
+
return super().placeholder_sql(expression)
|
218
|
+
|
219
|
+
return f"{{{expression.name}}}"
|
sqlglot/dialects/sqlite.py
CHANGED
@@ -102,6 +102,10 @@ class SQLite(Dialect):
|
|
102
102
|
COMMANDS = {*tokens.Tokenizer.COMMANDS, TokenType.REPLACE}
|
103
103
|
|
104
104
|
class Parser(parser.Parser):
|
105
|
+
STRING_ALIASES = True
|
106
|
+
ALTER_RENAME_REQUIRES_COLUMN = False
|
107
|
+
JOINS_HAVE_EQUAL_PRECEDENCE = True
|
108
|
+
|
105
109
|
FUNCTIONS = {
|
106
110
|
**parser.Parser.FUNCTIONS,
|
107
111
|
"EDITDIST3": exp.Levenshtein.from_arg_list,
|
@@ -110,9 +114,6 @@ class SQLite(Dialect):
|
|
110
114
|
"TIME": lambda args: exp.Anonymous(this="TIME", expressions=args),
|
111
115
|
}
|
112
116
|
|
113
|
-
STRING_ALIASES = True
|
114
|
-
ALTER_RENAME_REQUIRES_COLUMN = False
|
115
|
-
|
116
117
|
def _parse_unique(self) -> exp.UniqueColumnConstraint:
|
117
118
|
# Do not consume more tokens if UNIQUE is used as a standalone constraint, e.g:
|
118
119
|
# CREATE TABLE foo (bar TEXT UNIQUE REFERENCES baz ...)
|
sqlglot/expressions.py
CHANGED
@@ -4453,8 +4453,9 @@ class SessionParameter(Condition):
|
|
4453
4453
|
arg_types = {"this": True, "kind": False}
|
4454
4454
|
|
4455
4455
|
|
4456
|
+
# https://www.databricks.com/blog/parameterized-queries-pyspark
|
4456
4457
|
class Placeholder(Condition):
|
4457
|
-
arg_types = {"this": False, "kind": False}
|
4458
|
+
arg_types = {"this": False, "kind": False, "widget": False}
|
4458
4459
|
|
4459
4460
|
@property
|
4460
4461
|
def name(self) -> str:
|
sqlglot/parser.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import logging
|
4
|
+
import re
|
4
5
|
import typing as t
|
5
6
|
import itertools
|
6
7
|
from collections import defaultdict
|
@@ -23,6 +24,9 @@ logger = logging.getLogger("sqlglot")
|
|
23
24
|
|
24
25
|
OPTIONS_TYPE = t.Dict[str, t.Sequence[t.Union[t.Sequence[str], str]]]
|
25
26
|
|
27
|
+
# Used to detect alphabetical characters and +/- in timestamp literals
|
28
|
+
TIME_ZONE_RE: t.Pattern[str] = re.compile(r":.*?[a-zA-Z\+\-]")
|
29
|
+
|
26
30
|
|
27
31
|
def build_var_map(args: t.List) -> exp.StarMap | exp.VarMap:
|
28
32
|
if len(args) == 1 and args[0].is_star:
|
@@ -935,7 +939,6 @@ class Parser(metaclass=_Parser):
|
|
935
939
|
"AS": lambda self, query: self._build_pipe_cte(
|
936
940
|
query, [exp.Star()], self._parse_table_alias()
|
937
941
|
),
|
938
|
-
"DROP": lambda self, query: self._parse_pipe_syntax_drop(query),
|
939
942
|
"EXTEND": lambda self, query: self._parse_pipe_syntax_extend(query),
|
940
943
|
"LIMIT": lambda self, query: self._parse_pipe_syntax_limit(query),
|
941
944
|
"ORDER BY": lambda self, query: query.order_by(
|
@@ -943,7 +946,6 @@ class Parser(metaclass=_Parser):
|
|
943
946
|
),
|
944
947
|
"PIVOT": lambda self, query: self._parse_pipe_syntax_pivot(query),
|
945
948
|
"SELECT": lambda self, query: self._parse_pipe_syntax_select(query),
|
946
|
-
"SET": lambda self, query: self._parse_pipe_syntax_set(query),
|
947
949
|
"TABLESAMPLE": lambda self, query: self._parse_pipe_syntax_tablesample(query),
|
948
950
|
"UNPIVOT": lambda self, query: self._parse_pipe_syntax_pivot(query),
|
949
951
|
"WHERE": lambda self, query: query.where(self._parse_where(), copy=False),
|
@@ -1518,6 +1520,15 @@ class Parser(metaclass=_Parser):
|
|
1518
1520
|
# Whether renaming a column with an ALTER statement requires the presence of the COLUMN keyword
|
1519
1521
|
ALTER_RENAME_REQUIRES_COLUMN = True
|
1520
1522
|
|
1523
|
+
# Whether all join types have the same precedence, i.e., they "naturally" produce a left-deep tree.
|
1524
|
+
# In standard SQL, joins that use the JOIN keyword take higher precedence than comma-joins. That is
|
1525
|
+
# to say, JOIN operators happen before comma operators. This is not the case in some dialects, such
|
1526
|
+
# as BigQuery, where all joins have the same precedence.
|
1527
|
+
JOINS_HAVE_EQUAL_PRECEDENCE = False
|
1528
|
+
|
1529
|
+
# Whether TIMESTAMP <literal> can produce a zone-aware timestamp
|
1530
|
+
ZONE_AWARE_TIMESTAMP_CONSTRUCTOR = False
|
1531
|
+
|
1521
1532
|
__slots__ = (
|
1522
1533
|
"error_level",
|
1523
1534
|
"error_message_context",
|
@@ -3142,7 +3153,7 @@ class Parser(metaclass=_Parser):
|
|
3142
3153
|
is_unpivot=self._prev.token_type == TokenType.UNPIVOT
|
3143
3154
|
)
|
3144
3155
|
elif self._match(TokenType.FROM):
|
3145
|
-
from_ = self._parse_from(skip_from_token=True)
|
3156
|
+
from_ = self._parse_from(skip_from_token=True, consume_pipe=True)
|
3146
3157
|
# Support parentheses for duckdb FROM-first syntax
|
3147
3158
|
select = self._parse_select()
|
3148
3159
|
if select:
|
@@ -3152,7 +3163,7 @@ class Parser(metaclass=_Parser):
|
|
3152
3163
|
this = exp.select("*").from_(t.cast(exp.From, from_))
|
3153
3164
|
else:
|
3154
3165
|
this = (
|
3155
|
-
self._parse_table()
|
3166
|
+
self._parse_table(consume_pipe=True)
|
3156
3167
|
if table
|
3157
3168
|
else self._parse_select(nested=True, parse_set_operation=False)
|
3158
3169
|
)
|
@@ -3173,6 +3184,31 @@ class Parser(metaclass=_Parser):
|
|
3173
3184
|
table: bool = False,
|
3174
3185
|
parse_subquery_alias: bool = True,
|
3175
3186
|
parse_set_operation: bool = True,
|
3187
|
+
consume_pipe: bool = True,
|
3188
|
+
) -> t.Optional[exp.Expression]:
|
3189
|
+
query = self._parse_select_query(
|
3190
|
+
nested=nested,
|
3191
|
+
table=table,
|
3192
|
+
parse_subquery_alias=parse_subquery_alias,
|
3193
|
+
parse_set_operation=parse_set_operation,
|
3194
|
+
)
|
3195
|
+
|
3196
|
+
if (
|
3197
|
+
consume_pipe
|
3198
|
+
and self._match(TokenType.PIPE_GT, advance=False)
|
3199
|
+
and isinstance(query, exp.Query)
|
3200
|
+
):
|
3201
|
+
query = self._parse_pipe_syntax_query(query)
|
3202
|
+
query = query.subquery(copy=False) if query and table else query
|
3203
|
+
|
3204
|
+
return query
|
3205
|
+
|
3206
|
+
def _parse_select_query(
|
3207
|
+
self,
|
3208
|
+
nested: bool = False,
|
3209
|
+
table: bool = False,
|
3210
|
+
parse_subquery_alias: bool = True,
|
3211
|
+
parse_set_operation: bool = True,
|
3176
3212
|
) -> t.Optional[exp.Expression]:
|
3177
3213
|
cte = self._parse_with()
|
3178
3214
|
|
@@ -3192,7 +3228,11 @@ class Parser(metaclass=_Parser):
|
|
3192
3228
|
return this
|
3193
3229
|
|
3194
3230
|
# duckdb supports leading with FROM x
|
3195
|
-
from_ =
|
3231
|
+
from_ = (
|
3232
|
+
self._parse_from(consume_pipe=True)
|
3233
|
+
if self._match(TokenType.FROM, advance=False)
|
3234
|
+
else None
|
3235
|
+
)
|
3196
3236
|
|
3197
3237
|
if self._match(TokenType.SELECT):
|
3198
3238
|
comments = self._prev_comments
|
@@ -3260,8 +3300,6 @@ class Parser(metaclass=_Parser):
|
|
3260
3300
|
this = self._parse_derived_table_values()
|
3261
3301
|
elif from_:
|
3262
3302
|
this = exp.select("*").from_(from_.this, copy=False)
|
3263
|
-
if self._match(TokenType.PIPE_GT, advance=False):
|
3264
|
-
return self._parse_pipe_syntax_query(this)
|
3265
3303
|
elif self._match(TokenType.SUMMARIZE):
|
3266
3304
|
table = self._match(TokenType.TABLE)
|
3267
3305
|
this = self._parse_select() or self._parse_string() or self._parse_table()
|
@@ -3521,13 +3559,18 @@ class Parser(metaclass=_Parser):
|
|
3521
3559
|
)
|
3522
3560
|
|
3523
3561
|
def _parse_from(
|
3524
|
-
self,
|
3562
|
+
self,
|
3563
|
+
joins: bool = False,
|
3564
|
+
skip_from_token: bool = False,
|
3565
|
+
consume_pipe: bool = False,
|
3525
3566
|
) -> t.Optional[exp.From]:
|
3526
3567
|
if not skip_from_token and not self._match(TokenType.FROM):
|
3527
3568
|
return None
|
3528
3569
|
|
3529
3570
|
return self.expression(
|
3530
|
-
exp.From,
|
3571
|
+
exp.From,
|
3572
|
+
comments=self._prev_comments,
|
3573
|
+
this=self._parse_table(joins=joins, consume_pipe=consume_pipe),
|
3531
3574
|
)
|
3532
3575
|
|
3533
3576
|
def _parse_match_recognize_measure(self) -> exp.MatchRecognizeMeasure:
|
@@ -3702,9 +3745,12 @@ class Parser(metaclass=_Parser):
|
|
3702
3745
|
) -> t.Optional[exp.Join]:
|
3703
3746
|
if self._match(TokenType.COMMA):
|
3704
3747
|
table = self._try_parse(self._parse_table)
|
3705
|
-
if table
|
3706
|
-
|
3707
|
-
|
3748
|
+
cross_join = self.expression(exp.Join, this=table) if table else None
|
3749
|
+
|
3750
|
+
if cross_join and self.JOINS_HAVE_EQUAL_PRECEDENCE:
|
3751
|
+
cross_join.set("kind", "CROSS")
|
3752
|
+
|
3753
|
+
return cross_join
|
3708
3754
|
|
3709
3755
|
index = self._index
|
3710
3756
|
method, side, kind = self._parse_join_parts()
|
@@ -3953,6 +3999,7 @@ class Parser(metaclass=_Parser):
|
|
3953
3999
|
parse_bracket: bool = False,
|
3954
4000
|
is_db_reference: bool = False,
|
3955
4001
|
parse_partition: bool = False,
|
4002
|
+
consume_pipe: bool = False,
|
3956
4003
|
) -> t.Optional[exp.Expression]:
|
3957
4004
|
lateral = self._parse_lateral()
|
3958
4005
|
if lateral:
|
@@ -3966,7 +4013,7 @@ class Parser(metaclass=_Parser):
|
|
3966
4013
|
if values:
|
3967
4014
|
return values
|
3968
4015
|
|
3969
|
-
subquery = self._parse_select(table=True)
|
4016
|
+
subquery = self._parse_select(table=True, consume_pipe=consume_pipe)
|
3970
4017
|
if subquery:
|
3971
4018
|
if not subquery.args.get("pivots"):
|
3972
4019
|
subquery.set("pivots", self._parse_pivots())
|
@@ -4708,7 +4755,9 @@ class Parser(metaclass=_Parser):
|
|
4708
4755
|
|
4709
4756
|
return locks
|
4710
4757
|
|
4711
|
-
def parse_set_operation(
|
4758
|
+
def parse_set_operation(
|
4759
|
+
self, this: t.Optional[exp.Expression], consume_pipe: bool = False
|
4760
|
+
) -> t.Optional[exp.Expression]:
|
4712
4761
|
start = self._index
|
4713
4762
|
_, side_token, kind_token = self._parse_join_parts()
|
4714
4763
|
|
@@ -4751,7 +4800,9 @@ class Parser(metaclass=_Parser):
|
|
4751
4800
|
if by_name and self._match_texts(("ON", "BY")):
|
4752
4801
|
on_column_list = self._parse_wrapped_csv(self._parse_column)
|
4753
4802
|
|
4754
|
-
expression = self._parse_select(
|
4803
|
+
expression = self._parse_select(
|
4804
|
+
nested=True, parse_set_operation=False, consume_pipe=consume_pipe
|
4805
|
+
)
|
4755
4806
|
|
4756
4807
|
return self.expression(
|
4757
4808
|
operation,
|
@@ -5082,12 +5133,20 @@ class Parser(metaclass=_Parser):
|
|
5082
5133
|
this = self._parse_primary()
|
5083
5134
|
|
5084
5135
|
if isinstance(this, exp.Literal):
|
5136
|
+
literal = this.name
|
5085
5137
|
this = self._parse_column_ops(this)
|
5086
5138
|
|
5087
5139
|
parser = self.TYPE_LITERAL_PARSERS.get(data_type.this)
|
5088
5140
|
if parser:
|
5089
5141
|
return parser(self, this, data_type)
|
5090
5142
|
|
5143
|
+
if (
|
5144
|
+
self.ZONE_AWARE_TIMESTAMP_CONSTRUCTOR
|
5145
|
+
and data_type.is_type(exp.DataType.Type.TIMESTAMP)
|
5146
|
+
and TIME_ZONE_RE.search(literal)
|
5147
|
+
):
|
5148
|
+
data_type = exp.DataType.build("TIMESTAMPTZ")
|
5149
|
+
|
5091
5150
|
return self.expression(exp.Cast, this=this, to=data_type)
|
5092
5151
|
|
5093
5152
|
# The expressions arg gets set by the parser when we have something like DECIMAL(38, 0)
|
@@ -8361,34 +8420,14 @@ class Parser(metaclass=_Parser):
|
|
8361
8420
|
|
8362
8421
|
return new_select.with_(new_cte, as_=query, copy=False)
|
8363
8422
|
|
8364
|
-
def _build_pipe_ctes(
|
8365
|
-
self,
|
8366
|
-
query: exp.Select,
|
8367
|
-
expressions: t.List[exp.Expression],
|
8368
|
-
alias_cte: t.Optional[exp.TableAlias] = None,
|
8369
|
-
) -> exp.Select:
|
8370
|
-
select = query.selects[0].assert_is(exp.Star)
|
8371
|
-
if select.args.get("except") or select.args.get("replace"):
|
8372
|
-
query = self._build_pipe_cte(
|
8373
|
-
query=query.select(
|
8374
|
-
*[expr for expr in expressions if not expr.is_star and expr.args.get("alias")],
|
8375
|
-
copy=False,
|
8376
|
-
),
|
8377
|
-
expressions=[
|
8378
|
-
projection.args.get("alias", projection) for projection in expressions
|
8379
|
-
],
|
8380
|
-
)
|
8381
|
-
else:
|
8382
|
-
query.select(*expressions, append=False, copy=False)
|
8383
|
-
|
8384
|
-
return self._build_pipe_cte(query=query, expressions=[exp.Star()], alias_cte=alias_cte)
|
8385
|
-
|
8386
8423
|
def _parse_pipe_syntax_select(self, query: exp.Select) -> exp.Select:
|
8387
|
-
select = self._parse_select()
|
8424
|
+
select = self._parse_select(consume_pipe=False)
|
8388
8425
|
if not select:
|
8389
8426
|
return query
|
8390
8427
|
|
8391
|
-
return self.
|
8428
|
+
return self._build_pipe_cte(
|
8429
|
+
query=query.select(*select.expressions, append=False), expressions=[exp.Star()]
|
8430
|
+
)
|
8392
8431
|
|
8393
8432
|
def _parse_pipe_syntax_limit(self, query: exp.Select) -> exp.Select:
|
8394
8433
|
limit = self._parse_limit()
|
@@ -8437,7 +8476,7 @@ class Parser(metaclass=_Parser):
|
|
8437
8476
|
copy=False,
|
8438
8477
|
)
|
8439
8478
|
else:
|
8440
|
-
query.select(*aggregates_or_groups, copy=False)
|
8479
|
+
query.select(*aggregates_or_groups, append=False, copy=False)
|
8441
8480
|
|
8442
8481
|
if orders:
|
8443
8482
|
return query.order_by(*orders, append=False, copy=False)
|
@@ -8453,11 +8492,9 @@ class Parser(metaclass=_Parser):
|
|
8453
8492
|
):
|
8454
8493
|
query = self._parse_pipe_syntax_aggregate_group_order_by(query)
|
8455
8494
|
|
8456
|
-
return self.
|
8457
|
-
query=query, expressions=[expr for expr in query.selects if not expr.is_star]
|
8458
|
-
)
|
8495
|
+
return self._build_pipe_cte(query=query, expressions=[exp.Star()])
|
8459
8496
|
|
8460
|
-
def _parse_pipe_syntax_set_operator(self, query: exp.Query) -> t.Optional[exp.
|
8497
|
+
def _parse_pipe_syntax_set_operator(self, query: exp.Query) -> t.Optional[exp.Query]:
|
8461
8498
|
first_setop = self.parse_set_operation(this=query)
|
8462
8499
|
if not first_setop:
|
8463
8500
|
return None
|
@@ -8488,12 +8525,15 @@ class Parser(metaclass=_Parser):
|
|
8488
8525
|
|
8489
8526
|
return self._build_pipe_cte(query=query, expressions=[exp.Star()])
|
8490
8527
|
|
8491
|
-
def _parse_pipe_syntax_join(self, query: exp.
|
8528
|
+
def _parse_pipe_syntax_join(self, query: exp.Query) -> t.Optional[exp.Query]:
|
8492
8529
|
join = self._parse_join()
|
8493
8530
|
if not join:
|
8494
8531
|
return None
|
8495
8532
|
|
8496
|
-
|
8533
|
+
if isinstance(query, exp.Select):
|
8534
|
+
return query.join(join, copy=False)
|
8535
|
+
|
8536
|
+
return query
|
8497
8537
|
|
8498
8538
|
def _parse_pipe_syntax_pivot(self, query: exp.Select) -> exp.Select:
|
8499
8539
|
pivots = self._parse_pivots()
|
@@ -8504,37 +8544,12 @@ class Parser(metaclass=_Parser):
|
|
8504
8544
|
if from_:
|
8505
8545
|
from_.this.set("pivots", pivots)
|
8506
8546
|
|
8507
|
-
return self.
|
8547
|
+
return self._build_pipe_cte(query=query, expressions=[exp.Star()])
|
8508
8548
|
|
8509
8549
|
def _parse_pipe_syntax_extend(self, query: exp.Select) -> exp.Select:
|
8510
8550
|
self._match_text_seq("EXTEND")
|
8511
|
-
|
8512
|
-
|
8513
|
-
expressions=[query.selects[0].assert_is(exp.Star), *self._parse_expressions()],
|
8514
|
-
)
|
8515
|
-
|
8516
|
-
def _parse_pipe_syntax_drop(self, query: exp.Select) -> exp.Select:
|
8517
|
-
self._match_text_seq("DROP")
|
8518
|
-
dropped_columns = self._parse_csv(self._parse_assignment)
|
8519
|
-
|
8520
|
-
select = query.selects[0].assert_is(exp.Star)
|
8521
|
-
except_ = select.args.get("except") or []
|
8522
|
-
select.set("except", [*except_, *dropped_columns])
|
8523
|
-
|
8524
|
-
return query
|
8525
|
-
|
8526
|
-
def _parse_pipe_syntax_set(self, query: exp.Select) -> exp.Select:
|
8527
|
-
self._match_text_seq("SET")
|
8528
|
-
replaced_columns = [
|
8529
|
-
self.expression(exp.Alias, this=expr.expression, alias=expr.this)
|
8530
|
-
for expr in self._parse_csv(self._parse_assignment)
|
8531
|
-
]
|
8532
|
-
|
8533
|
-
select = query.selects[0].assert_is(exp.Star)
|
8534
|
-
replace_ = select.args.get("replace") or []
|
8535
|
-
select.set("replace", [*replace_, *replaced_columns])
|
8536
|
-
|
8537
|
-
return query
|
8551
|
+
query.select(*[exp.Star(), *self._parse_expressions()], append=False, copy=False)
|
8552
|
+
return self._build_pipe_cte(query=query, expressions=[exp.Star()])
|
8538
8553
|
|
8539
8554
|
def _parse_pipe_syntax_tablesample(self, query: exp.Select) -> exp.Select:
|
8540
8555
|
sample = self._parse_table_sample()
|
@@ -8547,7 +8562,13 @@ class Parser(metaclass=_Parser):
|
|
8547
8562
|
|
8548
8563
|
return query
|
8549
8564
|
|
8550
|
-
def _parse_pipe_syntax_query(self, query: exp.
|
8565
|
+
def _parse_pipe_syntax_query(self, query: exp.Query) -> t.Optional[exp.Query]:
|
8566
|
+
if isinstance(query, exp.Subquery):
|
8567
|
+
query = exp.select("*").from_(query, copy=False)
|
8568
|
+
|
8569
|
+
if not query.args.get("from"):
|
8570
|
+
query = exp.select("*").from_(query.subquery(copy=False), copy=False)
|
8571
|
+
|
8551
8572
|
while self._match(TokenType.PIPE_GT):
|
8552
8573
|
start = self._curr
|
8553
8574
|
parser = self.PIPE_SYNTAX_TRANSFORM_PARSERS.get(self._curr.text.upper())
|
@@ -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=
|
4
|
+
sqlglot/_version.py,sha256=FTiVUaTaSWoKVYxiizmUH00aN8nwszEzKZ3Dh2gUm7s,515
|
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=
|
7
|
+
sqlglot/expressions.py,sha256=QTf40Yu04Ar6en5_Ncv0bpER5PRlNYtB7S7Ocr2vScw,243330
|
8
8
|
sqlglot/generator.py,sha256=E1LjyN49nX9XfK-hysHWvpw7-qtws4xeb85sZi5x3M0,213345
|
9
9
|
sqlglot/helper.py,sha256=9nZjFVRBtMKFC3EdzpDQ6jkazFO19po6BF8xHiNGZIo,15111
|
10
10
|
sqlglot/jsonpath.py,sha256=dKdI3PNINNGimmSse2IIv-GbPN_3lXncXh_70QH7Lss,7664
|
11
11
|
sqlglot/lineage.py,sha256=kXBDSErmZZluZx_kkrMj4MPEOAbkvcbX1tbOW7Bpl-U,15303
|
12
|
-
sqlglot/parser.py,sha256=
|
12
|
+
sqlglot/parser.py,sha256=xWm01SCq3tSHr7WIVz-h2taaf_JW5JvADsNufE8OAEw,324529
|
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
|
@@ -18,30 +18,31 @@ sqlglot/time.py,sha256=Q62gv6kL40OiRBF6BMESxKJcMVn7ZLNw7sv8H34z5FI,18400
|
|
18
18
|
sqlglot/tokens.py,sha256=R0B8GQSbQ9GoDc0NlaT5Tc8RjgEOx2IYIkYU5rY8Rg8,48742
|
19
19
|
sqlglot/transforms.py,sha256=3jpbHeVTLK9hmQi5f3_vmK-5jZB32_ittCkO7poxCs4,40631
|
20
20
|
sqlglot/trie.py,sha256=v27uXMrHfqrXlJ6GmeTSMovsB_3o0ctnlKhdNt7W6fI,2245
|
21
|
-
sqlglot/dialects/__init__.py,sha256=
|
21
|
+
sqlglot/dialects/__init__.py,sha256=Rcmnv_D8xjCrEPObi4R2_cs3upbfc5OrDKMIJhQTt4k,3513
|
22
22
|
sqlglot/dialects/athena.py,sha256=gPE9ybRcbd6dVa1mrTFB_eVjsjQG36hErq5EpHyQmXo,6344
|
23
|
-
sqlglot/dialects/bigquery.py,sha256=
|
24
|
-
sqlglot/dialects/clickhouse.py,sha256=
|
23
|
+
sqlglot/dialects/bigquery.py,sha256=Dw_ZOCv_rCDiUqMBJbmkb6b_R2t9ZemiRmvqu9YLBmY,52756
|
24
|
+
sqlglot/dialects/clickhouse.py,sha256=Dc0aXwEgN8b6coXKM6P8zh3IsyrXjBajNGB-cVhnu1Y,56603
|
25
25
|
sqlglot/dialects/databricks.py,sha256=8PoaiP8PfiBjpheRiua-rO_HzX2TRUXqc3DnlQ8zYrg,4481
|
26
|
-
sqlglot/dialects/dialect.py,sha256
|
26
|
+
sqlglot/dialects/dialect.py,sha256=-u8403azEMX3F9KrLQnv7xOU6IaHpxL4pJH733oQlqs,68747
|
27
27
|
sqlglot/dialects/doris.py,sha256=eC7Ct-iz7p4Usz659NkelUFhm-GmVolIZy5uaBvgjaA,14397
|
28
28
|
sqlglot/dialects/drill.py,sha256=FOh7_KjPx_77pv0DiHKZog0CcmzqeF9_PEmGnJ1ESSM,5825
|
29
29
|
sqlglot/dialects/druid.py,sha256=kh3snZtneehNOWqs3XcPjsrhNaRbkCQ8E4hHbWJ1fHM,690
|
30
|
-
sqlglot/dialects/duckdb.py,sha256=
|
30
|
+
sqlglot/dialects/duckdb.py,sha256=oGCgK0KjwJcCKy-YOZeiQnEo4v7Zc1r5AK0tCXO2VIc,48005
|
31
31
|
sqlglot/dialects/dune.py,sha256=gALut-fFfN2qMsr8LvZ1NQK3F3W9z2f4PwMvTMXVVVg,375
|
32
|
-
sqlglot/dialects/
|
32
|
+
sqlglot/dialects/fabric.py,sha256=RfRvQq7AVcr7yT30rqsTk-QILmhTJHECXZXMOotmL6I,4104
|
33
|
+
sqlglot/dialects/hive.py,sha256=yKCsVN4R8pIB2Lmx1YGiSR9b8Me3li6rsGuZrKjHTo4,31771
|
33
34
|
sqlglot/dialects/materialize.py,sha256=_DPLPt8YrdQIIXNrGJw1IMcGOoAEJ9NO9X9pDfy4hxs,3494
|
34
35
|
sqlglot/dialects/mysql.py,sha256=prZecn3zeoifZX7l54UuLG64ar7I-or_z9lF-rT8bds,49233
|
35
|
-
sqlglot/dialects/oracle.py,sha256=
|
36
|
+
sqlglot/dialects/oracle.py,sha256=o6On1cYWFt6TpQYKuzo4kCz5vKb8jQr8WSwc619h3Lg,15967
|
36
37
|
sqlglot/dialects/postgres.py,sha256=KUyMoLkm1_sZKUbdjn6bjXx9xz7sbEMKa-fl5Mzfrsk,31025
|
37
|
-
sqlglot/dialects/presto.py,sha256=
|
38
|
-
sqlglot/dialects/prql.py,sha256=
|
39
|
-
sqlglot/dialects/redshift.py,sha256=
|
38
|
+
sqlglot/dialects/presto.py,sha256=xsbYSc_1-z-jSOsG85z9Pw7pd_V_BX0Dila7KsMsS04,33203
|
39
|
+
sqlglot/dialects/prql.py,sha256=fwN-SPEGx-drwf1K0U2MByN-PkW3C_rOgQ3xeJeychg,7908
|
40
|
+
sqlglot/dialects/redshift.py,sha256=UwfntKCfPpX63G6ow4vjadFpfmfaKrmFOGLoOuWN8Yg,15406
|
40
41
|
sqlglot/dialects/risingwave.py,sha256=hwEOPjMw0ZM_3fjQcBUE00oy6I8V6mzYOOYmcwwS8mw,2898
|
41
|
-
sqlglot/dialects/snowflake.py,sha256=
|
42
|
-
sqlglot/dialects/spark.py,sha256=
|
42
|
+
sqlglot/dialects/snowflake.py,sha256=kpoWQ_w3SJyb605QWSvr-BxBR3pP9tmlDbT4ix8p484,63438
|
43
|
+
sqlglot/dialects/spark.py,sha256=bOUSXUoWtLfWaQ9fIjWaw4zLBJY6N7vxajdMbAxLdOk,8307
|
43
44
|
sqlglot/dialects/spark2.py,sha256=8er7nHDm5Wc57m9AOxKN0sd_DVzbhAL44H_udlFh9O8,14258
|
44
|
-
sqlglot/dialects/sqlite.py,sha256=
|
45
|
+
sqlglot/dialects/sqlite.py,sha256=fwqmopeuoupD_2dh2q6rT3UFxWtFHkskZ1OXAYnPT9Q,12483
|
45
46
|
sqlglot/dialects/starrocks.py,sha256=fHNgvq5Nz7dI4QUWCTOO5VDOYjasBxRRlcg9TbY0UZE,11235
|
46
47
|
sqlglot/dialects/tableau.py,sha256=oIawDzUITxGCWaEMB8OaNMPWhbC3U-2y09pYPm4eazc,2190
|
47
48
|
sqlglot/dialects/teradata.py,sha256=xWa-9kSTsT-eM1NePi_oIM1dPHmXW89GLU5Uda3_6Ao,14036
|
@@ -72,8 +73,8 @@ sqlglot/optimizer/qualify_tables.py,sha256=5f5enBAh-bpNB9ewF97W9fx9h1TGXj1Ih5fnc
|
|
72
73
|
sqlglot/optimizer/scope.py,sha256=r-2PaO7-woaIWaWrKC88J9eTgdQardNYQ1rIXXaPr1w,30501
|
73
74
|
sqlglot/optimizer/simplify.py,sha256=S0Blqg5Mq2KRRWhWz-Eivch9sBjBhg9fRJA6EdBzj2g,50704
|
74
75
|
sqlglot/optimizer/unnest_subqueries.py,sha256=kzWUVDlxs8z9nmRx-8U-pHXPtVZhEIwkKqmKhr2QLvc,10908
|
75
|
-
sqlglot-26.
|
76
|
-
sqlglot-26.
|
77
|
-
sqlglot-26.
|
78
|
-
sqlglot-26.
|
79
|
-
sqlglot-26.
|
76
|
+
sqlglot-26.30.0.dist-info/licenses/LICENSE,sha256=AI3__mHZfOtzY3EluR_pIYBm3_pE7TbVx7qaHxoZ114,1065
|
77
|
+
sqlglot-26.30.0.dist-info/METADATA,sha256=rIvq32wg6apWdTgqTkYe5mYgGj5XTwMQ8rvqjoTQruI,20732
|
78
|
+
sqlglot-26.30.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
79
|
+
sqlglot-26.30.0.dist-info/top_level.txt,sha256=5kRskCGA_gVADF9rSfSzPdLHXqvfMusDYeHePfNY2nQ,8
|
80
|
+
sqlglot-26.30.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|