sqlglotc 30.8.0__tar.gz → 30.11.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 (113) hide show
  1. {sqlglotc-30.8.0/sqlglotc.egg-info → sqlglotc-30.11.0}/PKG-INFO +4 -2
  2. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/pyproject.toml +3 -3
  3. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/setup.py +33 -0
  4. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/expressions/aggregate.py +1 -1
  5. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/expressions/builders.py +6 -1
  6. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/expressions/core.py +41 -12
  7. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/expressions/datatypes.py +17 -5
  8. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/expressions/ddl.py +8 -0
  9. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/expressions/dml.py +1 -0
  10. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/expressions/functions.py +10 -1
  11. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/expressions/properties.py +4 -0
  12. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/expressions/query.py +12 -4
  13. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/expressions/string.py +1 -0
  14. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generator.py +168 -15
  15. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/bigquery.py +9 -3
  16. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/clickhouse.py +1 -1
  17. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/databricks.py +14 -12
  18. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/duckdb.py +60 -0
  19. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/exasol.py +6 -0
  20. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/mysql.py +37 -0
  21. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/oracle.py +10 -2
  22. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/presto.py +2 -6
  23. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/snowflake.py +0 -3
  24. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/sqlite.py +39 -10
  25. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/starrocks.py +5 -2
  26. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/tsql.py +27 -7
  27. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/lineage.py +124 -20
  28. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/optimizer/annotate_types.py +14 -4
  29. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/optimizer/normalize_identifiers.py +4 -3
  30. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/optimizer/qualify_columns.py +25 -13
  31. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/optimizer/resolver.py +6 -4
  32. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/optimizer/scope.py +32 -8
  33. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/optimizer/simplify.py +50 -15
  34. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parser.py +134 -23
  35. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/bigquery.py +33 -6
  36. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/clickhouse.py +9 -3
  37. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/databricks.py +5 -0
  38. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/duckdb.py +1 -0
  39. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/oracle.py +21 -0
  40. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/snowflake.py +16 -1
  41. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/spark2.py +1 -0
  42. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/tsql.py +72 -10
  43. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/serde.py +1 -1
  44. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/tokenizer_core.py +1 -0
  45. {sqlglotc-30.8.0 → sqlglotc-30.11.0/sqlglotc.egg-info}/PKG-INFO +4 -2
  46. sqlglotc-30.11.0/sqlglotc.egg-info/requires.txt +6 -0
  47. sqlglotc-30.8.0/sqlglotc.egg-info/requires.txt +0 -5
  48. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/MANIFEST.in +0 -0
  49. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/setup.cfg +0 -0
  50. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/errors.py +0 -0
  51. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/executor/table.py +0 -0
  52. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/expressions/array.py +0 -0
  53. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/expressions/constraints.py +0 -0
  54. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/expressions/json.py +0 -0
  55. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/expressions/math.py +0 -0
  56. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/expressions/temporal.py +0 -0
  57. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/athena.py +0 -0
  58. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/doris.py +0 -0
  59. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/dremio.py +0 -0
  60. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/drill.py +0 -0
  61. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/druid.py +0 -0
  62. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/dune.py +0 -0
  63. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/fabric.py +0 -0
  64. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/hive.py +0 -0
  65. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/materialize.py +0 -0
  66. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/postgres.py +0 -0
  67. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/prql.py +0 -0
  68. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/python.py +0 -0
  69. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/redshift.py +0 -0
  70. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/risingwave.py +0 -0
  71. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/singlestore.py +0 -0
  72. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/solr.py +0 -0
  73. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/spark.py +0 -0
  74. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/spark2.py +0 -0
  75. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/tableau.py +0 -0
  76. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/teradata.py +0 -0
  77. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/generators/trino.py +0 -0
  78. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/helper.py +0 -0
  79. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/optimizer/canonicalize_internal_names.py +0 -0
  80. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/optimizer/isolate_table_selects.py +0 -0
  81. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/optimizer/qualify.py +0 -0
  82. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/optimizer/qualify_tables.py +0 -0
  83. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/athena.py +0 -0
  84. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/base.py +0 -0
  85. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/doris.py +0 -0
  86. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/dremio.py +0 -0
  87. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/drill.py +0 -0
  88. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/druid.py +0 -0
  89. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/dune.py +0 -0
  90. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/exasol.py +0 -0
  91. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/fabric.py +0 -0
  92. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/hive.py +0 -0
  93. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/materialize.py +0 -0
  94. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/mysql.py +0 -0
  95. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/postgres.py +0 -0
  96. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/presto.py +0 -0
  97. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/prql.py +0 -0
  98. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/redshift.py +0 -0
  99. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/risingwave.py +0 -0
  100. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/singlestore.py +0 -0
  101. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/solr.py +0 -0
  102. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/spark.py +0 -0
  103. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/sqlite.py +0 -0
  104. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/starrocks.py +0 -0
  105. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/tableau.py +0 -0
  106. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/teradata.py +0 -0
  107. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/parsers/trino.py +0 -0
  108. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/schema.py +0 -0
  109. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/time.py +0 -0
  110. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglot/trie.py +0 -0
  111. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglotc.egg-info/SOURCES.txt +0 -0
  112. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglotc.egg-info/dependency_links.txt +0 -0
  113. {sqlglotc-30.8.0 → sqlglotc-30.11.0}/sqlglotc.egg-info/top_level.txt +0 -0
@@ -1,13 +1,15 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlglotc
3
- Version: 30.8.0
3
+ Version: 30.11.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.11.0
10
11
  Provides-Extra: dev
11
12
  Requires-Dist: setuptools>=61.0; extra == "dev"
12
13
  Requires-Dist: setuptools_scm; extra == "dev"
13
- Requires-Dist: sqlglot-mypy>=1.20.0.post6; extra == "dev"
14
+ Requires-Dist: sqlglot-mypy>=2.1.0.post2; extra == "dev"
15
+ Dynamic: requires-dist
@@ -1,13 +1,13 @@
1
1
  [project]
2
2
  name = "sqlglotc"
3
- dynamic = ["version"]
3
+ dynamic = ["version", "dependencies"]
4
4
  description = "mypyc-compiled extensions for sqlglot"
5
5
  authors = [{ name = "Toby Mao", email = "toby.mao@gmail.com" }]
6
6
  license = "MIT"
7
7
  requires-python = ">= 3.10"
8
8
 
9
9
  [project.optional-dependencies]
10
- dev = ["setuptools >= 61.0", "setuptools_scm", "sqlglot-mypy >= 1.20.0.post6"]
10
+ dev = ["setuptools >= 61.0", "setuptools_scm", "sqlglot-mypy >= 2.1.0.post2"]
11
11
 
12
12
  [project.urls]
13
13
  Homepage = "https://sqlglot.com/"
@@ -17,7 +17,7 @@ Repository = "https://github.com/tobymao/sqlglot"
17
17
  requires = [
18
18
  "setuptools >= 61.0",
19
19
  "setuptools_scm",
20
- "sqlglot-mypy >= 1.20.0.post6",
20
+ "sqlglot-mypy >= 2.1.0.post2",
21
21
  "types-python-dateutil",
22
22
  "sqlglot",
23
23
  ]
@@ -128,9 +128,42 @@ class sdist(_sdist):
128
128
  shutil.rmtree(local_sqlglot, ignore_errors=True)
129
129
 
130
130
 
131
+ def _sqlglot_requirement():
132
+ """Pin sqlglot to the matching version so resolvers keep the two packages in lockstep."""
133
+ try:
134
+ pkg_info = os.path.join(os.path.dirname(os.path.abspath(__file__)), "PKG-INFO")
135
+ if os.path.isfile(pkg_info):
136
+ # Building from an sdist: no git metadata; the released version is frozen in PKG-INFO.
137
+ with open(pkg_info, encoding="utf-8") as fd:
138
+ version = next(
139
+ (line.split(":", 1)[1].strip() for line in fd if line.startswith("Version:")),
140
+ "",
141
+ )
142
+ else:
143
+ from setuptools_scm import get_version
144
+
145
+ version = get_version(
146
+ root="..",
147
+ relative_to=__file__,
148
+ local_scheme="no-local-version",
149
+ fallback_version="0.0.0",
150
+ )
151
+ except Exception as e:
152
+ print(f"sqlglotc: failed to determine the sqlglot version to pin: {e}")
153
+ version = ""
154
+
155
+ # Dev and fallback (no git metadata) builds have no matching sqlglot release on PyPI;
156
+ # depend on sqlglot unpinned since the extensions can't be imported without it.
157
+ if version in ("", "0.0.0") or ".dev" in version:
158
+ return ["sqlglot"]
159
+
160
+ return [f"sqlglot=={version}"]
161
+
162
+
131
163
  setup(
132
164
  name="sqlglotc",
133
165
  packages=[],
166
+ install_requires=_sqlglot_requirement(),
134
167
  ext_modules=mypycify(
135
168
  _source_paths(), opt_level=os.environ.get("MYPYC_OPT", "2"), separate=True, verbose=True
136
169
  ),
@@ -208,7 +208,7 @@ class NthValue(Expression, AggFunc):
208
208
 
209
209
 
210
210
  class ObjectAgg(Expression, AggFunc):
211
- arg_types = {"this": True, "expression": True}
211
+ arg_types = {"this": True, "expression": False}
212
212
 
213
213
 
214
214
  class PercentileCont(Expression, AggFunc):
@@ -319,6 +319,11 @@ def parse_identifier(name: str | Identifier, dialect: DialectType = None) -> Ide
319
319
  Returns:
320
320
  The identifier ast node.
321
321
  """
322
+ if isinstance(name, str) and SAFE_IDENTIFIER_RE.match(name):
323
+ # Simple names parse to a single unquoted identifier in all dialects, so we can
324
+ # avoid the tokenizer/parser round-trip for them.
325
+ return Identifier(this=name, quoted=False)
326
+
322
327
  try:
323
328
  expression = maybe_parse(name, dialect=dialect, into=Identifier)
324
329
  except (ParseError, TokenError):
@@ -822,7 +827,7 @@ def replace_tables(
822
827
  mapping = {normalize_table_name(k, dialect=dialect): v for k, v in mapping.items()}
823
828
 
824
829
  def _replace_tables(node: Expr) -> Expr:
825
- if isinstance(node, Table) and node.meta.get("replace") is not False:
830
+ if isinstance(node, Table) and node.meta_get("replace") is not False:
826
831
  original = normalize_table_name(node, dialect=dialect)
827
832
  new_name = mapping.get(original)
828
833
 
@@ -88,6 +88,7 @@ class Expr:
88
88
  _hash_raw_args: t.ClassVar[bool] = False
89
89
  is_subquery: t.ClassVar[bool] = False
90
90
  is_cast: t.ClassVar[bool] = False
91
+ is_data_type: t.ClassVar[bool] = False
91
92
 
92
93
  args: dict[str, t.Any]
93
94
  parent: Expr | None
@@ -239,6 +240,9 @@ class Expr:
239
240
  def meta(self) -> dict[str, t.Any]:
240
241
  raise NotImplementedError
241
242
 
243
+ def meta_get(self, key: str, default: t.Any = None) -> t.Any:
244
+ raise NotImplementedError
245
+
242
246
  def __deepcopy__(self, memo: t.Any) -> Expr:
243
247
  raise NotImplementedError
244
248
 
@@ -837,26 +841,35 @@ class Expression(Expr):
837
841
  def __hash__(self) -> int:
838
842
  if self._hash is None:
839
843
  nodes: list[Expr] = []
840
- queue: deque[Expr] = deque()
841
- queue.append(self)
844
+ stack: list[Expr] = [self]
842
845
 
843
- while queue:
844
- node = queue.popleft()
846
+ # Collect nodes, finding child expressions inline instead of via the
847
+ # iter_expressions generator (whose per-node generator object dominates the
848
+ # hash's cost). reversed(nodes) is a valid post-order regardless of DFS/BFS.
849
+ while stack:
850
+ node = stack.pop()
845
851
  nodes.append(node)
846
852
 
847
- for child in node.iter_expressions():
848
- if child._hash is None:
849
- queue.append(child)
853
+ for v in node.args.values():
854
+ if isinstance(v, Expr):
855
+ if v._hash is None:
856
+ stack.append(v)
857
+ elif type(v) is list:
858
+ for x in v:
859
+ if isinstance(x, Expr) and x._hash is None:
860
+ stack.append(x)
850
861
 
851
862
  for node in reversed(nodes):
852
863
  hash_ = hash(node.key)
853
864
 
854
865
  if node._hash_raw_args:
855
- for k, v in sorted(node.args.items()):
866
+ for k in sorted(node.args):
867
+ v = node.args[k]
856
868
  if v:
857
869
  hash_ = hash((hash_, k, v))
858
870
  else:
859
- for k, v in sorted(node.args.items()):
871
+ for k in sorted(node.args):
872
+ v = node.args[k]
860
873
  vt = type(v)
861
874
 
862
875
  if vt is list:
@@ -953,6 +966,8 @@ class Expression(Expr):
953
966
 
954
967
  @property
955
968
  def type(self) -> DataType | None:
969
+ if self.is_data_type:
970
+ return self # type: ignore[return-value]
956
971
  if self.is_cast:
957
972
  return self._type or self.to # type: ignore[attr-defined]
958
973
  return self._type
@@ -978,6 +993,11 @@ class Expression(Expr):
978
993
  self._meta = {}
979
994
  return self._meta
980
995
 
996
+ def meta_get(self, key: str, default: t.Any = None) -> t.Any:
997
+ """Reads a meta value without allocating the meta dict (unlike the `meta` property)."""
998
+ meta = self._meta
999
+ return meta.get(key, default) if meta is not None else default
1000
+
981
1001
  def __deepcopy__(self, memo: t.Any) -> Expr:
982
1002
  root = self.__class__()
983
1003
  stack: list[tuple[Expr, Expr]] = [(self, root)]
@@ -1039,6 +1059,11 @@ class Expression(Expr):
1039
1059
  return comments
1040
1060
 
1041
1061
  def append(self, arg_key: str, value: t.Any) -> None:
1062
+ node: Expr | None = self
1063
+ while node and node._hash is not None:
1064
+ node._hash = None
1065
+ node = node.parent
1066
+
1042
1067
  if type(self.args.get(arg_key)) is not list:
1043
1068
  self.args[arg_key] = []
1044
1069
  self._set_parent(arg_key, value)
@@ -2118,6 +2143,10 @@ class Distance(Expression, Binary):
2118
2143
  pass
2119
2144
 
2120
2145
 
2146
+ class DistanceNd(Expression, Binary):
2147
+ pass
2148
+
2149
+
2121
2150
  class Escape(Expression, Binary):
2122
2151
  pass
2123
2152
 
@@ -2269,8 +2298,7 @@ class Or(Expression, Connector, Func):
2269
2298
 
2270
2299
 
2271
2300
  class Xor(Expression, Connector, Func):
2272
- arg_types = {"this": False, "expression": False, "expressions": False, "round_input": False}
2273
- is_var_len_args = True
2301
+ arg_types = {"this": True, "expression": True, "round_input": False}
2274
2302
 
2275
2303
 
2276
2304
  class Pow(Expression, Binary, Func):
@@ -2428,6 +2456,7 @@ QUERY_MODIFIERS = {
2428
2456
  "settings": False,
2429
2457
  "format": False,
2430
2458
  "options": False,
2459
+ "for_": False,
2431
2460
  }
2432
2461
 
2433
2462
 
@@ -2534,7 +2563,7 @@ def _to_s(node: t.Any, verbose: bool = False, level: int = 0, repr_str: bool = F
2534
2563
  if isinstance(node, Expr):
2535
2564
  args = {k: v for k, v in node.args.items() if (v is not None and v != []) or verbose}
2536
2565
 
2537
- if (node.type or verbose) and type(node).__name__ != "DataType":
2566
+ if (node.type or verbose) and not node.is_data_type:
2538
2567
  args["_type"] = node.type
2539
2568
  if node.comments or verbose:
2540
2569
  args["_comments"] = node.comments
@@ -8,6 +8,7 @@ from enum import auto
8
8
  from sqlglot.helper import AutoName
9
9
  from sqlglot.errors import ErrorLevel, ParseError
10
10
  from sqlglot.expressions.core import (
11
+ Expr,
11
12
  Expression,
12
13
  _TimeUnit,
13
14
  Identifier,
@@ -17,13 +18,18 @@ from sqlglot.expressions.core import (
17
18
  from builtins import type as Type
18
19
 
19
20
  if t.TYPE_CHECKING:
21
+ from sqlglot._typing import DataTypeArgs
20
22
  from sqlglot.dialects.dialect import DialectType
21
- from typing_extensions import Self
23
+ from typing_extensions import Self, Unpack
22
24
 
23
25
 
24
26
  class DataTypeParam(Expression):
25
27
  arg_types = {"this": True, "expression": False}
26
28
 
29
+ @property
30
+ def this(self) -> Expr:
31
+ return self.args["this"]
32
+
27
33
  @property
28
34
  def name(self) -> str:
29
35
  return self.this.name
@@ -181,6 +187,8 @@ class DataType(Expression):
181
187
  "collate": False,
182
188
  }
183
189
 
190
+ is_data_type: t.ClassVar[bool] = True
191
+
184
192
  Type: t.ClassVar[Type[DType]] = DType
185
193
 
186
194
  STRUCT_TYPES: t.ClassVar[set[DType]] = {
@@ -331,7 +339,7 @@ class DataType(Expression):
331
339
  dialect: DialectType = None,
332
340
  udt: bool = False,
333
341
  copy: bool = True,
334
- **kwargs: object,
342
+ **kwargs: Unpack[DataTypeArgs],
335
343
  ) -> Self:
336
344
  """
337
345
  Constructs a DataType object.
@@ -364,7 +372,11 @@ class DataType(Expression):
364
372
 
365
373
  @classmethod
366
374
  def from_str(
367
- cls, dtype: str, dialect: DialectType = None, udt: bool = False, **kwargs: object
375
+ cls,
376
+ dtype: str,
377
+ dialect: DialectType = None,
378
+ udt: bool = False,
379
+ **kwargs: Unpack[DataTypeArgs],
368
380
  ) -> Self:
369
381
  """
370
382
  Constructs a `DataType` object from a `str` representation.
@@ -405,10 +417,10 @@ class DataType(Expression):
405
417
  Returns:
406
418
  True, if and only if there is a type in `dtypes` which is equal to this DataType.
407
419
  """
408
- self_is_nullable = self.args.get("nullable")
420
+ self_is_nullable: bool | None = self.args.get("nullable")
409
421
  for dtype in dtypes:
410
422
  other_type = DataType.build(dtype, copy=False, udt=True)
411
- other_is_nullable = other_type.args.get("nullable")
423
+ other_is_nullable: bool | None = other_type.args.get("nullable")
412
424
  if (
413
425
  other_type.expressions
414
426
  or (check_nullable and (self_is_nullable or other_is_nullable))
@@ -226,6 +226,14 @@ class UserDefinedFunction(Expression):
226
226
  arg_types = {"this": True, "expressions": False, "wrapped": False}
227
227
 
228
228
 
229
+ class MacroOverloads(Expression):
230
+ arg_types = {"expressions": True}
231
+
232
+
233
+ class MacroOverload(Expression):
234
+ arg_types = {"this": True, "expressions": False, "is_table": False}
235
+
236
+
229
237
  class CharacterSet(Expression):
230
238
  arg_types = {"this": True, "default": False}
231
239
 
@@ -283,6 +283,7 @@ class LoadData(Expression):
283
283
  "this": True,
284
284
  "local": False,
285
285
  "overwrite": False,
286
+ "temp": False,
286
287
  "inpath": False,
287
288
  "files": False,
288
289
  "partition": False,
@@ -70,7 +70,12 @@ class Cast(Expression, Func):
70
70
 
71
71
 
72
72
  class TryCast(Cast):
73
- arg_types = {**Cast.arg_types, "requires_string": False}
73
+ arg_types = {
74
+ **Cast.arg_types,
75
+ "requires_string": False,
76
+ "null_on_text_overflow": False,
77
+ "probe_date_format": False,
78
+ }
74
79
 
75
80
 
76
81
  class JSONCast(Cast):
@@ -436,6 +441,10 @@ class XMLElement(Expression, Func):
436
441
  arg_types = {"this": True, "expressions": False, "evalname": False}
437
442
 
438
443
 
444
+ class GetIgnoreCase(Expression, Func):
445
+ arg_types = {"this": True, "expression": True}
446
+
447
+
439
448
  class XMLGet(Expression, Func):
440
449
  _sql_names = ["XMLGET"]
441
450
  arg_types = {"this": True, "expression": True, "instance": False}
@@ -75,6 +75,10 @@ class ChecksumProperty(Property):
75
75
  arg_types = {"on": False, "default": False}
76
76
 
77
77
 
78
+ class ClusterProperty(Property):
79
+ arg_types = {"this": False, "expressions": False}
80
+
81
+
78
82
  class CollateProperty(Property):
79
83
  arg_types = {"this": True, "default": False}
80
84
 
@@ -859,8 +859,8 @@ class SkipJSONColumn(Expression):
859
859
  arg_types = {"regexp": False, "expression": True}
860
860
 
861
861
 
862
- class Cluster(Order):
863
- pass
862
+ class Cluster(Expression):
863
+ arg_types = {"expressions": True}
864
864
 
865
865
 
866
866
  class Distribute(Order):
@@ -915,6 +915,11 @@ class QueryOption(Expression):
915
915
  arg_types = {"this": True, "expression": False}
916
916
 
917
917
 
918
+ # FOR { XML | JSON } query modifier; `kind` is the discriminant ("XML" or "JSON").
919
+ class ForClause(Expression):
920
+ arg_types = {"kind": True, "expressions": False}
921
+
922
+
918
923
  class WithTableHint(Expression):
919
924
  arg_types = {"expressions": True}
920
925
 
@@ -1266,8 +1271,8 @@ class Select(Expression, Query):
1266
1271
  Set the CLUSTER BY expression.
1267
1272
 
1268
1273
  Example:
1269
- >>> Select().from_("tbl").select("x").cluster_by("x DESC").sql(dialect="hive")
1270
- 'SELECT x FROM tbl CLUSTER BY x DESC'
1274
+ >>> Select().from_("tbl").select("x").cluster_by("x").sql(dialect="hive")
1275
+ 'SELECT x FROM tbl CLUSTER BY x'
1271
1276
 
1272
1277
  Args:
1273
1278
  *expressions: the SQL code strings to parse.
@@ -1753,6 +1758,9 @@ class Pivot(Expression):
1753
1758
  "default_on_null": False,
1754
1759
  "into": False,
1755
1760
  "with_": False,
1761
+ "identify_pivot_strings": False,
1762
+ "prefixed_pivot_columns": False,
1763
+ "pivot_column_naming": False,
1756
1764
  }
1757
1765
 
1758
1766
  @property
@@ -375,6 +375,7 @@ class ToNumber(Expression, Func):
375
375
  "scale": False,
376
376
  "safe": False,
377
377
  "safe_name": False,
378
+ "default": False,
378
379
  }
379
380
 
380
381