sqlglot 28.4.1__py3-none-any.whl → 28.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 +2 -2
- sqlglot/dialects/bigquery.py +20 -23
- sqlglot/dialects/clickhouse.py +2 -0
- sqlglot/dialects/dialect.py +355 -18
- sqlglot/dialects/doris.py +38 -90
- sqlglot/dialects/druid.py +1 -0
- sqlglot/dialects/duckdb.py +1739 -163
- sqlglot/dialects/exasol.py +17 -1
- sqlglot/dialects/hive.py +27 -2
- sqlglot/dialects/mysql.py +103 -11
- sqlglot/dialects/oracle.py +38 -1
- sqlglot/dialects/postgres.py +142 -33
- sqlglot/dialects/presto.py +6 -2
- sqlglot/dialects/redshift.py +7 -1
- sqlglot/dialects/singlestore.py +13 -3
- sqlglot/dialects/snowflake.py +271 -21
- sqlglot/dialects/spark.py +25 -0
- sqlglot/dialects/spark2.py +4 -3
- sqlglot/dialects/starrocks.py +152 -17
- sqlglot/dialects/trino.py +1 -0
- sqlglot/dialects/tsql.py +5 -0
- sqlglot/diff.py +1 -1
- sqlglot/expressions.py +239 -47
- sqlglot/generator.py +173 -44
- sqlglot/optimizer/annotate_types.py +129 -60
- sqlglot/optimizer/merge_subqueries.py +13 -2
- sqlglot/optimizer/qualify_columns.py +7 -0
- sqlglot/optimizer/resolver.py +19 -0
- sqlglot/optimizer/scope.py +12 -0
- sqlglot/optimizer/unnest_subqueries.py +7 -0
- sqlglot/parser.py +251 -58
- sqlglot/schema.py +186 -14
- sqlglot/tokens.py +36 -6
- sqlglot/transforms.py +6 -5
- sqlglot/typing/__init__.py +29 -10
- sqlglot/typing/bigquery.py +5 -10
- sqlglot/typing/duckdb.py +39 -0
- sqlglot/typing/hive.py +50 -1
- sqlglot/typing/mysql.py +32 -0
- sqlglot/typing/presto.py +0 -1
- sqlglot/typing/snowflake.py +80 -17
- sqlglot/typing/spark.py +29 -0
- sqlglot/typing/spark2.py +9 -1
- sqlglot/typing/tsql.py +21 -0
- {sqlglot-28.4.1.dist-info → sqlglot-28.8.0.dist-info}/METADATA +47 -2
- sqlglot-28.8.0.dist-info/RECORD +95 -0
- {sqlglot-28.4.1.dist-info → sqlglot-28.8.0.dist-info}/WHEEL +1 -1
- sqlglot-28.4.1.dist-info/RECORD +0 -92
- {sqlglot-28.4.1.dist-info → sqlglot-28.8.0.dist-info}/licenses/LICENSE +0 -0
- {sqlglot-28.4.1.dist-info → sqlglot-28.8.0.dist-info}/top_level.txt +0 -0
sqlglot/dialects/doris.py
CHANGED
|
@@ -68,11 +68,36 @@ class Doris(MySQL):
|
|
|
68
68
|
"UNIQUE": lambda self: self._parse_composite_key_property(exp.UniqueKeyProperty),
|
|
69
69
|
# Plain KEY without UNIQUE/DUPLICATE/AGGREGATE prefixes should be treated as UniqueKeyProperty with unique=False
|
|
70
70
|
"KEY": lambda self: self._parse_composite_key_property(exp.UniqueKeyProperty),
|
|
71
|
-
"PARTITION BY": lambda self: self._parse_partition_by_opt_range(),
|
|
72
71
|
"BUILD": lambda self: self._parse_build_property(),
|
|
73
72
|
"REFRESH": lambda self: self._parse_refresh_property(),
|
|
74
73
|
}
|
|
75
74
|
|
|
75
|
+
def _parse_partition_property(
|
|
76
|
+
self,
|
|
77
|
+
) -> t.Optional[exp.Expression] | t.List[exp.Expression]:
|
|
78
|
+
expr = super()._parse_partition_property()
|
|
79
|
+
|
|
80
|
+
if not expr:
|
|
81
|
+
return self._parse_partitioned_by()
|
|
82
|
+
|
|
83
|
+
if isinstance(expr, exp.Property):
|
|
84
|
+
return expr
|
|
85
|
+
|
|
86
|
+
self._match_l_paren()
|
|
87
|
+
|
|
88
|
+
if self._match_text_seq("FROM", advance=False):
|
|
89
|
+
create_expressions = self._parse_csv(self._parse_partitioning_granularity_dynamic)
|
|
90
|
+
else:
|
|
91
|
+
create_expressions = None
|
|
92
|
+
|
|
93
|
+
self._match_r_paren()
|
|
94
|
+
|
|
95
|
+
return self.expression(
|
|
96
|
+
exp.PartitionByRangeProperty,
|
|
97
|
+
partition_expressions=expr,
|
|
98
|
+
create_expressions=create_expressions,
|
|
99
|
+
)
|
|
100
|
+
|
|
76
101
|
def _parse_partitioning_granularity_dynamic(self) -> exp.PartitionByRangePropertyDynamic:
|
|
77
102
|
self._match_text_seq("FROM")
|
|
78
103
|
start = self._parse_wrapped(self._parse_string)
|
|
@@ -86,20 +111,16 @@ class Doris(MySQL):
|
|
|
86
111
|
exp.PartitionByRangePropertyDynamic, start=start, end=end, every=every
|
|
87
112
|
)
|
|
88
113
|
|
|
89
|
-
def
|
|
90
|
-
|
|
114
|
+
def _parse_partition_range_value(self) -> exp.Partition:
|
|
115
|
+
expr = super()._parse_partition_range_value()
|
|
91
116
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if self._match_text_seq("LESS", "THAN"):
|
|
96
|
-
values = self._parse_wrapped_csv(self._parse_expression)
|
|
97
|
-
if len(values) == 1 and values[0].name.upper() == "MAXVALUE":
|
|
98
|
-
values = [exp.var("MAXVALUE")]
|
|
117
|
+
if isinstance(expr, exp.Partition):
|
|
118
|
+
return expr
|
|
99
119
|
|
|
100
|
-
|
|
101
|
-
|
|
120
|
+
self._match_text_seq("VALUES")
|
|
121
|
+
name = expr
|
|
102
122
|
|
|
123
|
+
# Doris-specific bracket syntax: VALUES [(...), (...))
|
|
103
124
|
self._match(TokenType.L_BRACKET)
|
|
104
125
|
values = self._parse_csv(lambda: self._parse_wrapped_csv(self._parse_expression))
|
|
105
126
|
|
|
@@ -109,48 +130,6 @@ class Doris(MySQL):
|
|
|
109
130
|
part_range = self.expression(exp.PartitionRange, this=name, expressions=values)
|
|
110
131
|
return self.expression(exp.Partition, expressions=[part_range])
|
|
111
132
|
|
|
112
|
-
def _parse_partition_definition_list(self) -> exp.Partition:
|
|
113
|
-
# PARTITION <name> VALUES IN (<value_csv>)
|
|
114
|
-
self._match_text_seq("PARTITION")
|
|
115
|
-
name = self._parse_id_var()
|
|
116
|
-
self._match_text_seq("VALUES", "IN")
|
|
117
|
-
values = self._parse_wrapped_csv(self._parse_expression)
|
|
118
|
-
part_list = self.expression(exp.PartitionList, this=name, expressions=values)
|
|
119
|
-
return self.expression(exp.Partition, expressions=[part_list])
|
|
120
|
-
|
|
121
|
-
def _parse_partition_by_opt_range(
|
|
122
|
-
self,
|
|
123
|
-
) -> exp.PartitionedByProperty | exp.PartitionByRangeProperty | exp.PartitionByListProperty:
|
|
124
|
-
if self._match_text_seq("LIST"):
|
|
125
|
-
return self.expression(
|
|
126
|
-
exp.PartitionByListProperty,
|
|
127
|
-
partition_expressions=self._parse_wrapped_id_vars(),
|
|
128
|
-
create_expressions=self._parse_wrapped_csv(
|
|
129
|
-
self._parse_partition_definition_list
|
|
130
|
-
),
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
if not self._match_text_seq("RANGE"):
|
|
134
|
-
return super()._parse_partitioned_by()
|
|
135
|
-
|
|
136
|
-
partition_expressions = self._parse_wrapped_id_vars()
|
|
137
|
-
self._match_l_paren()
|
|
138
|
-
|
|
139
|
-
if self._match_text_seq("FROM", advance=False):
|
|
140
|
-
create_expressions = self._parse_csv(self._parse_partitioning_granularity_dynamic)
|
|
141
|
-
elif self._match_text_seq("PARTITION", advance=False):
|
|
142
|
-
create_expressions = self._parse_csv(self._parse_partition_definition)
|
|
143
|
-
else:
|
|
144
|
-
create_expressions = None
|
|
145
|
-
|
|
146
|
-
self._match_r_paren()
|
|
147
|
-
|
|
148
|
-
return self.expression(
|
|
149
|
-
exp.PartitionByRangeProperty,
|
|
150
|
-
partition_expressions=partition_expressions,
|
|
151
|
-
create_expressions=create_expressions,
|
|
152
|
-
)
|
|
153
|
-
|
|
154
133
|
def _parse_build_property(self) -> exp.BuildProperty:
|
|
155
134
|
return self.expression(exp.BuildProperty, this=self._parse_var(upper=True))
|
|
156
135
|
|
|
@@ -178,6 +157,7 @@ class Doris(MySQL):
|
|
|
178
157
|
VARCHAR_REQUIRES_SIZE = False
|
|
179
158
|
WITH_PROPERTIES_PREFIX = "PROPERTIES"
|
|
180
159
|
RENAME_TABLE_WITH_DB = False
|
|
160
|
+
UPDATE_STATEMENT_SUPPORTS_FROM = True
|
|
181
161
|
|
|
182
162
|
TYPE_MAPPING = {
|
|
183
163
|
**MySQL.Generator.TYPE_MAPPING,
|
|
@@ -189,11 +169,8 @@ class Doris(MySQL):
|
|
|
189
169
|
PROPERTIES_LOCATION = {
|
|
190
170
|
**MySQL.Generator.PROPERTIES_LOCATION,
|
|
191
171
|
exp.UniqueKeyProperty: exp.Properties.Location.POST_SCHEMA,
|
|
192
|
-
exp.PartitionByRangeProperty: exp.Properties.Location.POST_SCHEMA,
|
|
193
|
-
exp.PartitionByListProperty: exp.Properties.Location.POST_SCHEMA,
|
|
194
172
|
exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA,
|
|
195
173
|
exp.BuildProperty: exp.Properties.Location.POST_SCHEMA,
|
|
196
|
-
exp.RefreshTriggerProperty: exp.Properties.Location.POST_SCHEMA,
|
|
197
174
|
}
|
|
198
175
|
|
|
199
176
|
CAST_MAPPING = {}
|
|
@@ -720,12 +697,6 @@ class Doris(MySQL):
|
|
|
720
697
|
|
|
721
698
|
return super().uniquekeyproperty_sql(expression)
|
|
722
699
|
|
|
723
|
-
def partition_sql(self, expression: exp.Partition) -> str:
|
|
724
|
-
parent = expression.parent
|
|
725
|
-
if isinstance(parent, (exp.PartitionByRangeProperty, exp.PartitionByListProperty)):
|
|
726
|
-
return ", ".join(self.sql(e) for e in expression.expressions)
|
|
727
|
-
return super().partition_sql(expression)
|
|
728
|
-
|
|
729
700
|
def partitionrange_sql(self, expression: exp.PartitionRange) -> str:
|
|
730
701
|
name = self.sql(expression, "this")
|
|
731
702
|
values = expression.expressions
|
|
@@ -759,31 +730,11 @@ class Doris(MySQL):
|
|
|
759
730
|
|
|
760
731
|
return f"FROM ({start}) TO ({end}) {interval}"
|
|
761
732
|
|
|
762
|
-
def partitionbyrangeproperty_sql(self, expression: exp.PartitionByRangeProperty) -> str:
|
|
763
|
-
partition_expressions = self.expressions(
|
|
764
|
-
expression, key="partition_expressions", indent=False
|
|
765
|
-
)
|
|
766
|
-
create_sql = self.expressions(expression, key="create_expressions", indent=False)
|
|
767
|
-
return f"PARTITION BY RANGE ({partition_expressions}) ({create_sql})"
|
|
768
|
-
|
|
769
|
-
def partitionbylistproperty_sql(self, expression: exp.PartitionByListProperty) -> str:
|
|
770
|
-
partition_expressions = self.expressions(
|
|
771
|
-
expression, key="partition_expressions", indent=False
|
|
772
|
-
)
|
|
773
|
-
create_sql = self.expressions(expression, key="create_expressions", indent=False)
|
|
774
|
-
return f"PARTITION BY LIST ({partition_expressions}) ({create_sql})"
|
|
775
|
-
|
|
776
|
-
def partitionlist_sql(self, expression: exp.PartitionList) -> str:
|
|
777
|
-
name = self.sql(expression, "this")
|
|
778
|
-
values = self.expressions(expression, indent=False)
|
|
779
|
-
return f"PARTITION {name} VALUES IN ({values})"
|
|
780
|
-
|
|
781
733
|
def partitionedbyproperty_sql(self, expression: exp.PartitionedByProperty) -> str:
|
|
782
|
-
|
|
783
|
-
if isinstance(
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
return f"PARTITION BY ({self.sql(node)})"
|
|
734
|
+
this = expression.this
|
|
735
|
+
if isinstance(this, exp.Schema):
|
|
736
|
+
return f"PARTITION BY ({self.expressions(this, flat=True)})"
|
|
737
|
+
return f"PARTITION BY ({self.sql(this)})"
|
|
787
738
|
|
|
788
739
|
def table_sql(self, expression: exp.Table, sep: str = " AS ") -> str:
|
|
789
740
|
"""Override table_sql to avoid AS keyword in UPDATE and DELETE statements."""
|
|
@@ -791,6 +742,3 @@ class Doris(MySQL):
|
|
|
791
742
|
if not isinstance(ancestor, exp.Select):
|
|
792
743
|
sep = " "
|
|
793
744
|
return super().table_sql(expression, sep=sep)
|
|
794
|
-
|
|
795
|
-
def alterrename_sql(self, expression: exp.AlterRename, include_to: bool = True) -> str:
|
|
796
|
-
return super().alterrename_sql(expression, include_to=False)
|