sqlglotc 30.19.0__tar.gz → 30.20.0__tar.gz

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.
Files changed (118) hide show
  1. {sqlglotc-30.19.0/sqlglotc.egg-info → sqlglotc-30.20.0}/PKG-INFO +2 -2
  2. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/expressions/json.py +1 -1
  3. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generator.py +7 -2
  4. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/bigquery.py +5 -0
  5. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/duckdb.py +7 -5
  6. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/mysql.py +2 -2
  7. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/sqlite.py +13 -6
  8. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/starrocks.py +19 -0
  9. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/optimizer/qualify_columns.py +4 -0
  10. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/optimizer/simplify.py +4 -1
  11. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parser.py +22 -7
  12. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/clickhouse.py +9 -6
  13. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/teradata.py +2 -1
  14. {sqlglotc-30.19.0 → sqlglotc-30.20.0/sqlglotc.egg-info}/PKG-INFO +2 -2
  15. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglotc.egg-info/requires.txt +1 -1
  16. sqlglotc-30.20.0/sqlglotc.egg-info/scm_version.json +8 -0
  17. sqlglotc-30.19.0/sqlglotc.egg-info/scm_version.json +0 -8
  18. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/MANIFEST.in +0 -0
  19. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/pyproject.toml +0 -0
  20. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/setup.cfg +0 -0
  21. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/setup.py +0 -0
  22. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/anonymize.py +0 -0
  23. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/errors.py +0 -0
  24. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/executor/table.py +0 -0
  25. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/expressions/aggregate.py +0 -0
  26. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/expressions/array.py +0 -0
  27. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/expressions/builders.py +0 -0
  28. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/expressions/constraints.py +0 -0
  29. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/expressions/core.py +0 -0
  30. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/expressions/datatypes.py +0 -0
  31. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/expressions/ddl.py +0 -0
  32. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/expressions/dml.py +0 -0
  33. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/expressions/functions.py +0 -0
  34. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/expressions/math.py +0 -0
  35. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/expressions/properties.py +0 -0
  36. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/expressions/query.py +0 -0
  37. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/expressions/string.py +0 -0
  38. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/expressions/temporal.py +0 -0
  39. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/athena.py +0 -0
  40. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/clickhouse.py +0 -0
  41. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/databricks.py +0 -0
  42. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/dax.py +0 -0
  43. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/doris.py +0 -0
  44. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/dremio.py +0 -0
  45. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/drill.py +0 -0
  46. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/druid.py +0 -0
  47. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/dune.py +0 -0
  48. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/exasol.py +0 -0
  49. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/fabric.py +0 -0
  50. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/hive.py +0 -0
  51. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/materialize.py +0 -0
  52. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/oracle.py +0 -0
  53. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/postgres.py +0 -0
  54. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/presto.py +0 -0
  55. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/prql.py +0 -0
  56. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/python.py +0 -0
  57. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/redshift.py +0 -0
  58. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/risingwave.py +0 -0
  59. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/singlestore.py +0 -0
  60. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/snowflake.py +0 -0
  61. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/solr.py +0 -0
  62. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/spark.py +0 -0
  63. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/spark2.py +0 -0
  64. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/tableau.py +0 -0
  65. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/teradata.py +0 -0
  66. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/trino.py +0 -0
  67. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/generators/tsql.py +0 -0
  68. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/helper.py +0 -0
  69. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/lineage.py +0 -0
  70. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/optimizer/annotate_types.py +0 -0
  71. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/optimizer/canonicalize_internal_names.py +0 -0
  72. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/optimizer/isolate_table_selects.py +0 -0
  73. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/optimizer/normalize_identifiers.py +0 -0
  74. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/optimizer/qualify.py +0 -0
  75. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/optimizer/qualify_tables.py +0 -0
  76. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/optimizer/resolver.py +0 -0
  77. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/optimizer/scope.py +0 -0
  78. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/athena.py +0 -0
  79. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/base.py +0 -0
  80. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/bigquery.py +0 -0
  81. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/databricks.py +0 -0
  82. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/dax.py +0 -0
  83. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/doris.py +0 -0
  84. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/dremio.py +0 -0
  85. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/drill.py +0 -0
  86. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/druid.py +0 -0
  87. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/duckdb.py +0 -0
  88. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/dune.py +0 -0
  89. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/exasol.py +0 -0
  90. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/fabric.py +0 -0
  91. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/hive.py +0 -0
  92. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/materialize.py +0 -0
  93. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/mysql.py +0 -0
  94. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/oracle.py +0 -0
  95. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/postgres.py +0 -0
  96. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/presto.py +0 -0
  97. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/prql.py +0 -0
  98. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/redshift.py +0 -0
  99. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/risingwave.py +0 -0
  100. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/singlestore.py +0 -0
  101. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/snowflake.py +0 -0
  102. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/solr.py +0 -0
  103. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/spark.py +0 -0
  104. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/spark2.py +0 -0
  105. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/sqlite.py +0 -0
  106. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/starrocks.py +0 -0
  107. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/tableau.py +0 -0
  108. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/trino.py +0 -0
  109. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/parsers/tsql.py +0 -0
  110. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/schema.py +0 -0
  111. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/serde.py +0 -0
  112. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/time.py +0 -0
  113. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/tokenizer_core.py +0 -0
  114. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglot/trie.py +0 -0
  115. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglotc.egg-info/SOURCES.txt +0 -0
  116. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglotc.egg-info/dependency_links.txt +0 -0
  117. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglotc.egg-info/scm_file_list.json +0 -0
  118. {sqlglotc-30.19.0 → sqlglotc-30.20.0}/sqlglotc.egg-info/top_level.txt +0 -0
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlglotc
3
- Version: 30.19.0
3
+ Version: 30.20.0
4
4
  Summary: mypyc-compiled extensions for sqlglot
5
5
  Author-email: Toby Mao <toby.mao@gmail.com>
6
6
  License-Expression: MIT
7
7
  Project-URL: Homepage, https://sqlglot.com/
8
8
  Project-URL: Repository, https://github.com/tobymao/sqlglot
9
9
  Requires-Python: >=3.10
10
- Requires-Dist: sqlglot==30.19.0
10
+ Requires-Dist: sqlglot==30.20.0
11
11
  Provides-Extra: dev
12
12
  Requires-Dist: setuptools>=61.0; extra == "dev"
13
13
  Requires-Dist: setuptools_scm; extra == "dev"
@@ -248,4 +248,4 @@ class ParseJSON(Expression, Func):
248
248
  # BigQuery, Snowflake have PARSE_JSON, Presto has JSON_PARSE
249
249
  # Snowflake also has TRY_PARSE_JSON, which is represented using `safe`
250
250
  _sql_names = ["PARSE_JSON", "JSON_PARSE"]
251
- arg_types = {"this": True, "expression": False, "safe": False}
251
+ arg_types = {"this": True, "expression": False, "safe": False, "is_literal": False}
@@ -4942,15 +4942,20 @@ class Generator:
4942
4942
  def tonumber_sql(self, expression: exp.ToNumber) -> str:
4943
4943
  if not self.SUPPORTS_TO_NUMBER:
4944
4944
  self.unsupported("Unsupported TO_NUMBER function")
4945
- return self.sql(exp.cast(expression.this, exp.DType.DOUBLE))
4945
+ return self._tonumber_cast_sql(expression)
4946
4946
 
4947
4947
  fmt = expression.args.get("format")
4948
4948
  if not fmt:
4949
4949
  self.unsupported("Conversion format is required for TO_NUMBER")
4950
- return self.sql(exp.cast(expression.this, exp.DType.DOUBLE))
4950
+ return self._tonumber_cast_sql(expression)
4951
4951
 
4952
4952
  return self.func("TO_NUMBER", expression.this, fmt)
4953
4953
 
4954
+ def _tonumber_cast_sql(self, expression: exp.ToNumber) -> str:
4955
+ if expression.args.get("safe"):
4956
+ return self.sql(exp.TryCast(this=expression.this, to=exp.DataType.build("DOUBLE")))
4957
+ return self.sql(exp.cast(expression.this, exp.DType.DOUBLE))
4958
+
4954
4959
  def dictproperty_sql(self, expression: exp.DictProperty) -> str:
4955
4960
  this = self.sql(expression, "this")
4956
4961
  kind = self.sql(expression, "kind")
@@ -713,6 +713,11 @@ class BigQueryGenerator(generator.Generator):
713
713
 
714
714
  return self.func("CONTAINS_SUBSTR", this, expr, expression.args.get("json_scope"))
715
715
 
716
+ def parsejson_sql(self, expression: exp.ParseJSON) -> str:
717
+ if expression.args.get("is_literal"):
718
+ return f"JSON {self.sql(expression, 'this')}"
719
+ return super().parsejson_sql(expression)
720
+
716
721
  def cast_sql(self, expression: exp.Cast, safe_prefix: str | None = None) -> str:
717
722
  this = expression.this
718
723
 
@@ -2577,11 +2577,10 @@ class DuckDBGenerator(generator.Generator):
2577
2577
  scale = expression.args.get("scale")
2578
2578
 
2579
2579
  if not fmt and precision and scale:
2580
- return self.sql(
2581
- exp.cast(
2582
- expression.this, f"DECIMAL({precision.name}, {scale.name})", dialect="duckdb"
2583
- )
2584
- )
2580
+ to = exp.DataType.build(f"DECIMAL({precision.name}, {scale.name})", dialect="duckdb")
2581
+ if expression.args.get("safe"):
2582
+ return self.sql(exp.TryCast(this=expression.this, to=to))
2583
+ return self.sql(exp.cast(expression.this, to, dialect="duckdb"))
2585
2584
 
2586
2585
  return super().tonumber_sql(expression)
2587
2586
 
@@ -3075,6 +3074,9 @@ class DuckDBGenerator(generator.Generator):
3075
3074
  if milli or nano:
3076
3075
  expression.set("sec", sec)
3077
3076
 
3077
+ if zone := expression.args.get("zone"):
3078
+ return self.sql(exp.AtTimeZone(this=expression, zone=zone.pop()))
3079
+
3078
3080
  return rename_func("MAKE_TIMESTAMP")(self, expression)
3079
3081
 
3080
3082
  @unsupported_args("nano")
@@ -154,9 +154,9 @@ class MySQLGenerator(generator.Generator):
154
154
  exp.DateDiff: remove_ts_or_ds_to_date(
155
155
  lambda self, e: self.func("DATEDIFF", e.this, e.expression), ("this", "expression")
156
156
  ),
157
- exp.DateAdd: remove_ts_or_ds_to_date(date_add_sql("ADD")),
157
+ exp.DateAdd: date_add_sql("ADD"),
158
158
  exp.DateStrToDate: datestrtodate_sql,
159
- exp.DateSub: remove_ts_or_ds_to_date(date_add_sql("SUB")),
159
+ exp.DateSub: date_add_sql("SUB"),
160
160
  exp.DateTrunc: _date_trunc_sql,
161
161
  exp.Day: remove_ts_or_ds_to_date(),
162
162
  exp.DayOfMonth: remove_ts_or_ds_to_date(rename_func("DAYOFMONTH")),
@@ -20,7 +20,7 @@ from sqlglot.tokens import TokenType
20
20
 
21
21
 
22
22
  def _transform_create(expression: exp.Expr) -> exp.Expr:
23
- """Move primary key to a column and enforce auto_increment on primary keys."""
23
+ """Move primary key to a column and place auto_increment after it."""
24
24
  schema = expression.this
25
25
 
26
26
  if isinstance(expression, exp.Create) and isinstance(schema, exp.Schema):
@@ -52,12 +52,9 @@ def _transform_create(expression: exp.Expr) -> exp.Expr:
52
52
  auto_increment = constraint
53
53
  auto_increment_index = i
54
54
 
55
- if auto_increment is not None and (
56
- primary_key_index == -1 or auto_increment_index < primary_key_index
57
- ):
55
+ if auto_increment is not None and 0 <= auto_increment_index < primary_key_index:
58
56
  column.constraints.remove(auto_increment)
59
- if primary_key_index != -1:
60
- column.constraints.insert(primary_key_index, auto_increment)
57
+ column.constraints.insert(primary_key_index, auto_increment)
61
58
 
62
59
  return expression
63
60
 
@@ -206,6 +203,16 @@ class SQLiteGenerator(generator.Generator):
206
203
 
207
204
  LIMIT_FETCH = "LIMIT"
208
205
 
206
+ def autoincrementcolumnconstraint_sql(
207
+ self, expression: exp.AutoIncrementColumnConstraint
208
+ ) -> str:
209
+ column = expression.find_ancestor(exp.ColumnDef)
210
+ if column and column.find(exp.PrimaryKeyColumnConstraint):
211
+ return super().autoincrementcolumnconstraint_sql(expression)
212
+
213
+ self.unsupported("SQLite AUTOINCREMENT requires an INTEGER PRIMARY KEY")
214
+ return ""
215
+
209
216
  def insert_sql(self, expression: exp.Insert) -> str:
210
217
  if expression.args.get("ignore"):
211
218
  expression.set("ignore", False)
@@ -12,6 +12,7 @@ from sqlglot.dialects.dialect import (
12
12
  property_sql,
13
13
  var_map_sql,
14
14
  )
15
+ from sqlglot.generator import Generator
15
16
  from sqlglot.generators.mysql import MySQLGenerator
16
17
 
17
18
 
@@ -292,6 +293,24 @@ class StarRocksGenerator(MySQLGenerator):
292
293
  "with",
293
294
  }
294
295
 
296
+ def ignorenulls_sql(self, expression: exp.IgnoreNulls) -> str:
297
+ # IGNORE NULLS follows the first argument, e.g. LAG(x IGNORE NULLS, 1, 0)
298
+ # https://docs.starrocks.io/docs/sql-reference/sql-functions/Window_function/
299
+ func = expression.this
300
+ if isinstance(func, (exp.FirstValue, exp.LastValue, exp.Lag, exp.Lead)):
301
+ return self.func(
302
+ func.sql_name(),
303
+ Generator.ignorenulls_sql(self, exp.IgnoreNulls(this=func.this)),
304
+ func.args.get("offset"),
305
+ func.args.get("default"),
306
+ )
307
+
308
+ return super().ignorenulls_sql(expression)
309
+
310
+ def respectnulls_sql(self, expression: exp.RespectNulls) -> str:
311
+ # RESPECT NULLS is the default behavior, and StarRocks rejects the keyword
312
+ return self.sql(expression, "this")
313
+
295
314
  def create_sql(self, expression: exp.Create) -> str:
296
315
  # Starrocks' primary key is defined outside of the schema, so we need to move it there
297
316
  schema = expression.this
@@ -492,6 +492,10 @@ def _expand_order_by_and_distinct_on(scope: Scope, resolver: Resolver) -> None:
492
492
  if not isinstance(expression, exp.Selectable):
493
493
  return
494
494
 
495
+ names = expression.named_selects
496
+ if len(names) != len(set(names)):
497
+ return
498
+
495
499
  # TODO (mypyc): rebind to exp.Expr to avoid Selectable trait vtable dispatch for .args
496
500
  expr: exp.Expr = expression
497
501
 
@@ -841,7 +841,10 @@ class Simplifier:
841
841
  if complement_subquery_predicate:
842
842
  right = complement_subquery_predicate(this=right.this)
843
843
 
844
- return self.COMPLEMENT_COMPARISONS[this.__class__](this=this.this, expression=right)
844
+ return exp.paren(
845
+ self.COMPLEMENT_COMPARISONS[this.__class__](this=this.this, expression=right),
846
+ copy=False,
847
+ )
845
848
  if isinstance(this, exp.Paren):
846
849
  condition = this.unnest()
847
850
  if isinstance(condition, exp.And):
@@ -1633,7 +1633,9 @@ class Parser:
1633
1633
  SHOW_PARSERS: t.ClassVar[dict[str, t.Callable]] = {}
1634
1634
 
1635
1635
  TYPE_LITERAL_PARSERS: t.ClassVar = {
1636
- exp.DType.JSON: lambda self, this, _: self.expression(exp.ParseJSON(this=this)),
1636
+ exp.DType.JSON: lambda self, this, _: self.expression(
1637
+ exp.ParseJSON(this=this, is_literal=True)
1638
+ ),
1637
1639
  }
1638
1640
 
1639
1641
  TYPE_CONVERTERS: t.ClassVar[dict[exp.DType, t.Callable[[exp.DataType], exp.DataType]]] = {}
@@ -3738,7 +3740,7 @@ class Parser:
3738
3740
  action = self._parse_var_from_options(self.CONFLICT_ACTIONS)
3739
3741
  if self._prev.token_type == TokenType.UPDATE:
3740
3742
  self._match(TokenType.SET)
3741
- expressions = self._parse_csv(self._parse_equality)
3743
+ expressions = self._parse_csv(self._parse_update_assignment)
3742
3744
  else:
3743
3745
  expressions = None
3744
3746
 
@@ -3867,6 +3869,15 @@ class Parser:
3867
3869
  )
3868
3870
  )
3869
3871
 
3872
+ def _parse_update_assignment(self) -> exp.Expr | None:
3873
+ this = self._parse_comparison()
3874
+ if self._match(TokenType.EQ):
3875
+ comments = self._prev_comments
3876
+ this = self.expression(
3877
+ exp.EQ(this=this, expression=self._parse_disjunction()), comments=comments
3878
+ )
3879
+ return this
3880
+
3870
3881
  def _parse_update(self) -> exp.Update:
3871
3882
  hint = self._parse_hint()
3872
3883
  kwargs: dict[str, object] = {
@@ -3875,7 +3886,7 @@ class Parser:
3875
3886
  }
3876
3887
  while self._curr:
3877
3888
  if self._match(TokenType.SET):
3878
- kwargs["expressions"] = self._parse_csv(self._parse_equality)
3889
+ kwargs["expressions"] = self._parse_csv(self._parse_update_assignment)
3879
3890
  elif self._match(TokenType.RETURNING, advance=False):
3880
3891
  kwargs["returning"] = self._parse_returning()
3881
3892
  elif self._match(TokenType.FROM, advance=False):
@@ -5766,7 +5777,7 @@ class Parser:
5766
5777
 
5767
5778
  def _parse_limit_options(self) -> exp.LimitOptions | None:
5768
5779
  percent = self._match_set((TokenType.PERCENT, TokenType.MOD))
5769
- rows = self._match_set((TokenType.ROW, TokenType.ROWS))
5780
+ rows = self._match_texts(("ROW", "ROWS"))
5770
5781
  self._match_text_seq("ONLY")
5771
5782
  with_ties = self._match_text_seq("WITH", "TIES")
5772
5783
 
@@ -5830,7 +5841,11 @@ class Parser:
5830
5841
  else "FIRST"
5831
5842
  )
5832
5843
 
5833
- count = self._parse_field(tokens=self.FETCH_TOKENS)
5844
+ count = (
5845
+ None
5846
+ if self._match_texts(("ROW", "ROWS"), advance=False)
5847
+ else self._parse_field(tokens=self.FETCH_TOKENS)
5848
+ )
5834
5849
 
5835
5850
  return self.expression(
5836
5851
  exp.Fetch(
@@ -5845,7 +5860,7 @@ class Parser:
5845
5860
  return this
5846
5861
 
5847
5862
  count = self._parse_term()
5848
- self._match_set((TokenType.ROW, TokenType.ROWS))
5863
+ self._match_texts(("ROW", "ROWS"))
5849
5864
 
5850
5865
  return self.expression(
5851
5866
  exp.Offset(this=this, expression=count, expressions=self._parse_limit_by())
@@ -9577,7 +9592,7 @@ class Parser:
9577
9592
  then = self.expression(
9578
9593
  exp.Update(
9579
9594
  expressions=self._match(TokenType.SET)
9580
- and self._parse_csv(self._parse_equality),
9595
+ and self._parse_csv(self._parse_update_assignment),
9581
9596
  where=self._parse_where(),
9582
9597
  )
9583
9598
  )
@@ -633,13 +633,16 @@ class ClickHouseParser(parser.Parser):
633
633
 
634
634
  return bracket
635
635
 
636
- def _parse_global_in(self, this: exp.Expr | None) -> exp.Not | exp.In:
636
+ def _parse_global_in(self, this: exp.Expr | None) -> exp.Not | exp.In | None:
637
+ index = self._index - 1
637
638
  is_negated = self._match(TokenType.NOT)
638
- in_expr: exp.In | None = None
639
- if self._match(TokenType.IN):
640
- in_expr = self._parse_in(this)
641
- in_expr.set("is_global", True)
642
- return self.expression(exp.Not(this=in_expr)) if is_negated else t.cast(exp.In, in_expr)
639
+ if not self._match(TokenType.IN):
640
+ self._retreat(index)
641
+ return None
642
+
643
+ in_expr = self._parse_in(this)
644
+ in_expr.set("is_global", True)
645
+ return self.expression(exp.Not(this=in_expr)) if is_negated else in_expr
643
646
 
644
647
  def _parse_table(
645
648
  self,
@@ -120,7 +120,8 @@ class TeradataParser(parser.Parser):
120
120
  exp.Update(
121
121
  this=self._parse_table(alias_tokens=self.UPDATE_ALIAS_TOKENS),
122
122
  from_=self._parse_from(joins=True),
123
- expressions=self._match(TokenType.SET) and self._parse_csv(self._parse_equality),
123
+ expressions=self._match(TokenType.SET)
124
+ and self._parse_csv(self._parse_update_assignment),
124
125
  where=self._parse_where(),
125
126
  )
126
127
  )
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlglotc
3
- Version: 30.19.0
3
+ Version: 30.20.0
4
4
  Summary: mypyc-compiled extensions for sqlglot
5
5
  Author-email: Toby Mao <toby.mao@gmail.com>
6
6
  License-Expression: MIT
7
7
  Project-URL: Homepage, https://sqlglot.com/
8
8
  Project-URL: Repository, https://github.com/tobymao/sqlglot
9
9
  Requires-Python: >=3.10
10
- Requires-Dist: sqlglot==30.19.0
10
+ Requires-Dist: sqlglot==30.20.0
11
11
  Provides-Extra: dev
12
12
  Requires-Dist: setuptools>=61.0; extra == "dev"
13
13
  Requires-Dist: setuptools_scm; extra == "dev"
@@ -1,4 +1,4 @@
1
- sqlglot==30.19.0
1
+ sqlglot==30.20.0
2
2
 
3
3
  [dev]
4
4
  setuptools>=61.0
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "30.20.0",
3
+ "distance": 0,
4
+ "node": "g8bd768664197fbd0ed86158c0eca955c14f43328",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-09-26"
8
+ }
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "30.19.0",
3
- "distance": 0,
4
- "node": "g02562228357e7d933ef66e27c56e257b88faad8f",
5
- "dirty": false,
6
- "branch": "HEAD",
7
- "node_date": "2026-09-22"
8
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes