sqlglot 27.6.0__py3-none-any.whl → 27.8.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -90,6 +90,7 @@ class Teradata(Dialect):
90
90
  "HELP": TokenType.COMMAND,
91
91
  "INS": TokenType.INSERT,
92
92
  "LE": TokenType.LTE,
93
+ "LOCKING": TokenType.LOCK,
93
94
  "LT": TokenType.LT,
94
95
  "MINUS": TokenType.EXCEPT,
95
96
  "MOD": TokenType.MOD,
@@ -155,6 +156,26 @@ class Teradata(Dialect):
155
156
  exp.Use, this=self._parse_table(schema=False)
156
157
  ),
157
158
  TokenType.REPLACE: lambda self: self._parse_create(),
159
+ TokenType.LOCK: lambda self: self._parse_locking_statement(),
160
+ }
161
+
162
+ def _parse_locking_statement(self) -> exp.LockingStatement:
163
+ # Reuse exp.LockingProperty parsing for the lock kind, type etc
164
+ locking_property = self._parse_locking()
165
+ wrapped_query = self._parse_select()
166
+
167
+ if not wrapped_query:
168
+ self.raise_error("Expected SELECT statement after LOCKING clause")
169
+
170
+ return self.expression(
171
+ exp.LockingStatement,
172
+ this=locking_property,
173
+ expression=wrapped_query,
174
+ )
175
+
176
+ SET_PARSERS = {
177
+ **parser.Parser.SET_PARSERS,
178
+ "QUERY_BAND": lambda self: self._parse_query_band(),
158
179
  }
159
180
 
160
181
  FUNCTION_PARSERS = {
@@ -210,6 +231,36 @@ class Teradata(Dialect):
210
231
 
211
232
  return self.expression(exp.RangeN, this=this, expressions=expressions, each=each)
212
233
 
234
+ def _parse_query_band(self) -> exp.QueryBand:
235
+ # Parse: SET QUERY_BAND = 'key=value;key2=value2;' FOR SESSION|TRANSACTION
236
+ # Also supports: SET QUERY_BAND = 'key=value;' UPDATE FOR SESSION|TRANSACTION
237
+ # Also supports: SET QUERY_BAND = NONE FOR SESSION|TRANSACTION
238
+ self._match(TokenType.EQ)
239
+
240
+ # Handle both string literals and NONE keyword
241
+ if self._match_text_seq("NONE"):
242
+ query_band_string: t.Optional[exp.Expression] = exp.Var(this="NONE")
243
+ else:
244
+ query_band_string = self._parse_string()
245
+
246
+ update = self._match_text_seq("UPDATE")
247
+ self._match_text_seq("FOR")
248
+
249
+ # Handle scope - can be SESSION, TRANSACTION, VOLATILE, or SESSION VOLATILE
250
+ if self._match_text_seq("SESSION", "VOLATILE"):
251
+ scope = "SESSION VOLATILE"
252
+ elif self._match_texts(("SESSION", "TRANSACTION")):
253
+ scope = self._prev.text.upper()
254
+ else:
255
+ scope = None
256
+
257
+ return self.expression(
258
+ exp.QueryBand,
259
+ this=query_band_string,
260
+ scope=scope,
261
+ update=update,
262
+ )
263
+
213
264
  def _parse_index_params(self) -> exp.IndexParameters:
214
265
  this = super()._parse_index_params()
215
266
 
@@ -358,6 +409,13 @@ class Teradata(Dialect):
358
409
 
359
410
  return f"RANGE_N({this} BETWEEN {expressions_sql}{each_sql})"
360
411
 
412
+ def lockingstatement_sql(self, expression: exp.LockingStatement) -> str:
413
+ """Generate SQL for LOCKING statement"""
414
+ locking_clause = self.sql(expression, "this")
415
+ query_sql = self.sql(expression, "expression")
416
+
417
+ return f"{locking_clause} {query_sql}"
418
+
361
419
  def createable_sql(self, expression: exp.Create, locations: t.DefaultDict) -> str:
362
420
  kind = self.sql(expression, "kind").upper()
363
421
  if kind == "TABLE" and locations.get(exp.Properties.Location.POST_NAME):
sqlglot/dialects/trino.py CHANGED
@@ -21,6 +21,7 @@ class Trino(Presto):
21
21
  **Presto.Parser.FUNCTION_PARSERS,
22
22
  "TRIM": lambda self: self._parse_trim(),
23
23
  "JSON_QUERY": lambda self: self._parse_json_query(),
24
+ "JSON_VALUE": lambda self: self._parse_json_value(),
24
25
  "LISTAGG": lambda self: self._parse_string_agg(),
25
26
  }
26
27
 
sqlglot/expressions.py CHANGED
@@ -1458,6 +1458,11 @@ class DDL(Expression):
1458
1458
  return self.expression.named_selects if isinstance(self.expression, Query) else []
1459
1459
 
1460
1460
 
1461
+ # https://docs.teradata.com/r/Enterprise_IntelliFlex_VMware/SQL-Data-Manipulation-Language/Statement-Syntax/LOCKING-Request-Modifier/LOCKING-Request-Modifier-Syntax
1462
+ class LockingStatement(Expression):
1463
+ arg_types = {"this": True, "expression": True}
1464
+
1465
+
1461
1466
  class DML(Expression):
1462
1467
  def returning(
1463
1468
  self,
@@ -1613,6 +1618,10 @@ class SetItem(Expression):
1613
1618
  }
1614
1619
 
1615
1620
 
1621
+ class QueryBand(Expression):
1622
+ arg_types = {"this": True, "scope": False, "update": False}
1623
+
1624
+
1616
1625
  class Show(Expression):
1617
1626
  arg_types = {
1618
1627
  "this": True,
@@ -1680,7 +1689,7 @@ class ProjectionDef(Expression):
1680
1689
 
1681
1690
 
1682
1691
  class TableAlias(Expression):
1683
- arg_types = {"this": False, "columns": False, "column_only": False}
1692
+ arg_types = {"this": False, "columns": False}
1684
1693
 
1685
1694
  @property
1686
1695
  def columns(self):
@@ -5292,7 +5301,7 @@ class TimeUnit(Expression):
5292
5301
 
5293
5302
  def __init__(self, **args):
5294
5303
  unit = args.get("unit")
5295
- if isinstance(unit, self.VAR_LIKE):
5304
+ if type(unit) in self.VAR_LIKE:
5296
5305
  args["unit"] = Var(
5297
5306
  this=(self.UNABBREVIATED_UNIT_NAME.get(unit.name) or unit.name).upper()
5298
5307
  )
@@ -5416,6 +5425,10 @@ class BitwiseCountAgg(AggFunc):
5416
5425
  _sql_names = ["BIT_COUNT"]
5417
5426
 
5418
5427
 
5428
+ class ByteLength(Func):
5429
+ pass
5430
+
5431
+
5419
5432
  class ArrayRemove(Func):
5420
5433
  arg_types = {"this": True, "expression": True}
5421
5434
 
@@ -5451,6 +5464,15 @@ class Transform(Func):
5451
5464
  arg_types = {"this": True, "expression": True}
5452
5465
 
5453
5466
 
5467
+ class Translate(Func):
5468
+ arg_types = {"this": True, "from": True, "to": True}
5469
+
5470
+
5471
+ class Grouping(AggFunc):
5472
+ arg_types = {"expressions": True}
5473
+ is_var_len_args = True
5474
+
5475
+
5454
5476
  class Anonymous(Func):
5455
5477
  arg_types = {"this": True, "expressions": False}
5456
5478
  is_var_len_args = True
@@ -5518,7 +5540,12 @@ class Pad(Func):
5518
5540
  # https://docs.snowflake.com/en/sql-reference/functions/to_char
5519
5541
  # https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/TO_CHAR-number.html
5520
5542
  class ToChar(Func):
5521
- arg_types = {"this": True, "format": False, "nlsparam": False}
5543
+ arg_types = {
5544
+ "this": True,
5545
+ "format": False,
5546
+ "nlsparam": False,
5547
+ "is_numeric": False,
5548
+ }
5522
5549
 
5523
5550
 
5524
5551
  # https://docs.snowflake.com/en/sql-reference/functions/to_decimal
@@ -5564,6 +5591,10 @@ class ConvertTimezone(Func):
5564
5591
  }
5565
5592
 
5566
5593
 
5594
+ class CodePointsToString(Func):
5595
+ pass
5596
+
5597
+
5567
5598
  class GenerateSeries(Func):
5568
5599
  arg_types = {"start": True, "end": True, "step": False, "is_end_exclusive": False}
5569
5600
 
@@ -5791,6 +5822,18 @@ class JSONCast(Cast):
5791
5822
  pass
5792
5823
 
5793
5824
 
5825
+ class JustifyDays(Func):
5826
+ pass
5827
+
5828
+
5829
+ class JustifyHours(Func):
5830
+ pass
5831
+
5832
+
5833
+ class JustifyInterval(Func):
5834
+ pass
5835
+
5836
+
5794
5837
  class Try(Func):
5795
5838
  pass
5796
5839
 
@@ -5947,6 +5990,10 @@ class DatetimeTrunc(Func, TimeUnit):
5947
5990
  arg_types = {"this": True, "unit": True, "zone": False}
5948
5991
 
5949
5992
 
5993
+ class DateFromUnixDate(Func):
5994
+ pass
5995
+
5996
+
5950
5997
  class DayOfWeek(Func):
5951
5998
  _sql_names = ["DAY_OF_WEEK", "DAYOFWEEK"]
5952
5999
 
@@ -6475,7 +6522,13 @@ class JSONExtractArray(Func):
6475
6522
 
6476
6523
 
6477
6524
  class JSONExtractScalar(Binary, Func):
6478
- arg_types = {"this": True, "expression": True, "only_json_types": False, "expressions": False}
6525
+ arg_types = {
6526
+ "this": True,
6527
+ "expression": True,
6528
+ "only_json_types": False,
6529
+ "expressions": False,
6530
+ "json_type": False,
6531
+ }
6479
6532
  _sql_names = ["JSON_EXTRACT_SCALAR"]
6480
6533
  is_var_len_args = True
6481
6534
 
@@ -6489,6 +6542,7 @@ class JSONBExtract(Binary, Func):
6489
6542
 
6490
6543
 
6491
6544
  class JSONBExtractScalar(Binary, Func):
6545
+ arg_types = {"this": True, "expression": True, "json_type": False}
6492
6546
  _sql_names = ["JSONB_EXTRACT_SCALAR"]
6493
6547
 
6494
6548
 
@@ -6509,6 +6563,14 @@ class ParseJSON(Func):
6509
6563
  arg_types = {"this": True, "expression": False, "safe": False}
6510
6564
 
6511
6565
 
6566
+ class ParseTime(Func):
6567
+ arg_types = {"this": True, "format": True}
6568
+
6569
+
6570
+ class ParseDatetime(Func):
6571
+ arg_types = {"this": True, "format": False, "zone": False}
6572
+
6573
+
6512
6574
  class Least(Func):
6513
6575
  arg_types = {"this": True, "expressions": False}
6514
6576
  is_var_len_args = True
@@ -6522,6 +6584,10 @@ class Right(Func):
6522
6584
  arg_types = {"this": True, "expression": True}
6523
6585
 
6524
6586
 
6587
+ class Reverse(Func):
6588
+ pass
6589
+
6590
+
6525
6591
  class Length(Func):
6526
6592
  arg_types = {"this": True, "binary": False, "encoding": False}
6527
6593
  _sql_names = ["LENGTH", "LEN", "CHAR_LENGTH", "CHARACTER_LENGTH"]
@@ -6796,6 +6862,10 @@ class SortArray(Func):
6796
6862
  arg_types = {"this": True, "asc": False}
6797
6863
 
6798
6864
 
6865
+ class Soundex(Func):
6866
+ pass
6867
+
6868
+
6799
6869
  class Split(Func):
6800
6870
  arg_types = {"this": True, "expression": True, "limit": False}
6801
6871
 
@@ -7047,6 +7117,14 @@ class UnixSeconds(Func):
7047
7117
  pass
7048
7118
 
7049
7119
 
7120
+ class UnixMicros(Func):
7121
+ pass
7122
+
7123
+
7124
+ class UnixMillis(Func):
7125
+ pass
7126
+
7127
+
7050
7128
  class Uuid(Func):
7051
7129
  _sql_names = ["UUID", "GEN_RANDOM_UUID", "GENERATE_UUID", "UUID_STRING"]
7052
7130
 
@@ -7096,6 +7174,10 @@ class Week(Func):
7096
7174
  arg_types = {"this": True, "mode": False}
7097
7175
 
7098
7176
 
7177
+ class WeekStart(Expression):
7178
+ pass
7179
+
7180
+
7099
7181
  class XMLElement(Func):
7100
7182
  _sql_names = ["XMLELEMENT"]
7101
7183
  arg_types = {"this": True, "expressions": False}
sqlglot/generator.py CHANGED
@@ -219,6 +219,7 @@ class Generator(metaclass=_Generator):
219
219
  exp.VarMap: lambda self, e: self.func("MAP", e.args["keys"], e.args["values"]),
220
220
  exp.ViewAttributeProperty: lambda self, e: f"WITH {self.sql(e, 'this')}",
221
221
  exp.VolatileProperty: lambda *_: "VOLATILE",
222
+ exp.WeekStart: lambda self, e: f"WEEK({self.sql(e, 'this')})",
222
223
  exp.WithJournalTableProperty: lambda self, e: f"WITH JOURNAL TABLE={self.sql(e, 'this')}",
223
224
  exp.WithProcedureOptions: lambda self, e: f"WITH {self.expressions(e, flat=True)}",
224
225
  exp.WithSchemaBindingProperty: lambda self, e: f"WITH SCHEMA {self.sql(e, 'this')}",
@@ -691,6 +692,8 @@ class Generator(metaclass=_Generator):
691
692
 
692
693
  RESPECT_IGNORE_NULLS_UNSUPPORTED_EXPRESSIONS: t.Tuple[t.Type[exp.Expression], ...] = ()
693
694
 
695
+ SAFE_JSON_PATH_KEY_RE = exp.SAFE_IDENTIFIER_RE
696
+
694
697
  SENTINEL_LINE_BREAK = "__SQLGLOT__LB__"
695
698
 
696
699
  __slots__ = (
@@ -2405,6 +2408,14 @@ class Generator(metaclass=_Generator):
2405
2408
  tag = " TAG" if expression.args.get("tag") else ""
2406
2409
  return f"{'UNSET' if expression.args.get('unset') else 'SET'}{tag}{expressions}"
2407
2410
 
2411
+ def queryband_sql(self, expression: exp.QueryBand) -> str:
2412
+ this = self.sql(expression, "this")
2413
+ update = " UPDATE" if expression.args.get("update") else ""
2414
+ scope = self.sql(expression, "scope")
2415
+ scope = f" FOR {scope}" if scope else ""
2416
+
2417
+ return f"QUERY_BAND = {this}{update}{scope}"
2418
+
2408
2419
  def pragma_sql(self, expression: exp.Pragma) -> str:
2409
2420
  return f"PRAGMA {self.sql(expression, 'this')}"
2410
2421
 
@@ -3479,14 +3490,15 @@ class Generator(metaclass=_Generator):
3479
3490
  expressions = f"({expressions})" if expressions else ""
3480
3491
  return f"ALTER{compound} SORTKEY {this or expressions}"
3481
3492
 
3482
- def alterrename_sql(self, expression: exp.AlterRename) -> str:
3493
+ def alterrename_sql(self, expression: exp.AlterRename, include_to: bool = True) -> str:
3483
3494
  if not self.RENAME_TABLE_WITH_DB:
3484
3495
  # Remove db from tables
3485
3496
  expression = expression.transform(
3486
3497
  lambda n: exp.table_(n.this) if isinstance(n, exp.Table) else n
3487
3498
  ).assert_is(exp.AlterRename)
3488
3499
  this = self.sql(expression, "this")
3489
- return f"RENAME TO {this}"
3500
+ to_kw = " TO" if include_to else ""
3501
+ return f"RENAME{to_kw} {this}"
3490
3502
 
3491
3503
  def renamecolumn_sql(self, expression: exp.RenameColumn) -> str:
3492
3504
  exists = " IF EXISTS" if expression.args.get("exists") else ""
@@ -4352,7 +4364,7 @@ class Generator(metaclass=_Generator):
4352
4364
  this = self.json_path_part(this)
4353
4365
  return f".{this}" if this else ""
4354
4366
 
4355
- if exp.SAFE_IDENTIFIER_RE.match(this):
4367
+ if self.SAFE_JSON_PATH_KEY_RE.match(this):
4356
4368
  return f".{this}"
4357
4369
 
4358
4370
  this = self.json_path_part(this)
@@ -5127,3 +5139,15 @@ class Generator(metaclass=_Generator):
5127
5139
  return self.sql(exp.Bracket(this=this, expressions=[expr]))
5128
5140
 
5129
5141
  return self.sql(exp.JSONExtract(this=this, expression=self.dialect.to_json_path(expr)))
5142
+
5143
+ def datefromunixdate_sql(self, expression: exp.DateFromUnixDate) -> str:
5144
+ return self.sql(
5145
+ exp.DateAdd(
5146
+ this=exp.cast(exp.Literal.string("1970-01-01"), exp.DataType.Type.DATE),
5147
+ expression=expression.this,
5148
+ unit=exp.var("DAY"),
5149
+ )
5150
+ )
5151
+
5152
+ def space_sql(self: Generator, expression: exp.Space) -> str:
5153
+ return self.sql(exp.Repeat(this=exp.Literal.string(" "), times=expression.this))
sqlglot/jsonpath.py CHANGED
@@ -36,6 +36,10 @@ class JSONPathTokenizer(Tokenizer):
36
36
  IDENTIFIER_ESCAPES = ["\\"]
37
37
  STRING_ESCAPES = ["\\"]
38
38
 
39
+ VAR_TOKENS = {
40
+ TokenType.VAR,
41
+ }
42
+
39
43
 
40
44
  def parse(path: str, dialect: DialectType = None) -> exp.JSONPath:
41
45
  """Takes in a JSON path string and parses it into a JSONPath expression."""
@@ -76,6 +80,9 @@ def parse(path: str, dialect: DialectType = None) -> exp.JSONPath:
76
80
  raise ParseError(_error(f"Expected {token_type}"))
77
81
  return None
78
82
 
83
+ def _match_set(types: t.Collection[TokenType]) -> t.Optional[Token]:
84
+ return _advance() if _curr() in types else None
85
+
79
86
  def _parse_literal() -> t.Any:
80
87
  token = _match(TokenType.STRING) or _match(TokenType.IDENTIFIER)
81
88
  if token:
@@ -155,7 +162,7 @@ def parse(path: str, dialect: DialectType = None) -> exp.JSONPath:
155
162
  """
156
163
  prev_index = i - 2
157
164
 
158
- while _match(TokenType.VAR):
165
+ while _match_set(jsonpath_tokenizer.VAR_TOKENS):
159
166
  pass
160
167
 
161
168
  start = 0 if prev_index < 0 else tokens[prev_index].end + 1
@@ -177,7 +184,7 @@ def parse(path: str, dialect: DialectType = None) -> exp.JSONPath:
177
184
  if _match(TokenType.DOT) or _match(TokenType.COLON):
178
185
  recursive = _prev().text == ".."
179
186
 
180
- if _match(TokenType.VAR):
187
+ if _match_set(jsonpath_tokenizer.VAR_TOKENS):
181
188
  value: t.Optional[str | exp.JSONPathWildcard] = _parse_var_text()
182
189
  elif _match(TokenType.IDENTIFIER):
183
190
  value = _prev().text
@@ -194,7 +201,7 @@ def parse(path: str, dialect: DialectType = None) -> exp.JSONPath:
194
201
  raise ParseError(_error("Expected key name or * after DOT"))
195
202
  elif _match(TokenType.L_BRACKET):
196
203
  expressions.append(_parse_bracket())
197
- elif _match(TokenType.VAR):
204
+ elif _match_set(jsonpath_tokenizer.VAR_TOKENS):
198
205
  expressions.append(exp.JSONPathKey(this=_parse_var_text()))
199
206
  elif _match(TokenType.IDENTIFIER):
200
207
  expressions.append(exp.JSONPathKey(this=_prev().text))
@@ -326,7 +326,10 @@ class TypeAnnotator(metaclass=_TypeAnnotator):
326
326
  struct_type = exp.DataType(
327
327
  this=exp.DataType.Type.STRUCT,
328
328
  expressions=[
329
- exp.ColumnDef(this=exp.to_identifier(select.output_name), kind=select.type)
329
+ exp.ColumnDef(
330
+ this=exp.to_identifier(select.output_name),
331
+ kind=select.type.copy() if select.type else None,
332
+ )
330
333
  for select in scope.expression.selects
331
334
  ],
332
335
  nested=True,
@@ -330,6 +330,10 @@ def _merge_expressions(outer_scope: Scope, inner_scope: Scope, alias: str) -> No
330
330
  if isinstance(column.parent, (exp.Unary, exp.Binary)) and must_wrap_expression:
331
331
  expression = exp.paren(expression, copy=False)
332
332
 
333
+ # make sure we do not accidentally change the name of the column
334
+ if isinstance(column.parent, exp.Select) and column.name != expression.name:
335
+ expression = exp.alias_(expression, column.name)
336
+
333
337
  column.replace(expression.copy())
334
338
 
335
339
 
@@ -128,14 +128,6 @@ def qualify_tables(
128
128
  table_alias = udtf.args.get("alias") or exp.TableAlias(
129
129
  this=exp.to_identifier(next_alias_name())
130
130
  )
131
- if (
132
- isinstance(udtf, exp.Unnest)
133
- and dialect.UNNEST_COLUMN_ONLY
134
- and not table_alias.columns
135
- ):
136
- table_alias.set("columns", [table_alias.this.copy()])
137
- table_alias.set("column_only", True)
138
-
139
131
  udtf.set("alias", table_alias)
140
132
 
141
133
  if not table_alias.name:
sqlglot/parser.py CHANGED
@@ -577,7 +577,6 @@ class Parser(metaclass=_Parser):
577
577
 
578
578
  TABLE_ALIAS_TOKENS = ID_VAR_TOKENS - {
579
579
  TokenType.ANTI,
580
- TokenType.APPLY,
581
580
  TokenType.ASOF,
582
581
  TokenType.FULL,
583
582
  TokenType.LEFT,
@@ -2084,7 +2083,24 @@ class Parser(metaclass=_Parser):
2084
2083
 
2085
2084
  if create_token.token_type == TokenType.SEQUENCE:
2086
2085
  expression = self._parse_types()
2087
- extend_props(self._parse_properties())
2086
+ props = self._parse_properties()
2087
+ if props:
2088
+ sequence_props = exp.SequenceProperties()
2089
+ options = []
2090
+ for prop in props:
2091
+ if isinstance(prop, exp.SequenceProperties):
2092
+ for arg, value in prop.args.items():
2093
+ if arg == "options":
2094
+ options.extend(value)
2095
+ else:
2096
+ sequence_props.set(arg, value)
2097
+ prop.pop()
2098
+
2099
+ if options:
2100
+ sequence_props.set("options", options)
2101
+
2102
+ props.append("expressions", sequence_props)
2103
+ extend_props(props)
2088
2104
  else:
2089
2105
  expression = self._parse_ddl_select()
2090
2106
 
@@ -2222,11 +2238,17 @@ class Parser(metaclass=_Parser):
2222
2238
  return self.expression(exp.SqlSecurityProperty, definer=self._match_text_seq("DEFINER"))
2223
2239
 
2224
2240
  index = self._index
2241
+
2242
+ seq_props = self._parse_sequence_properties()
2243
+ if seq_props:
2244
+ return seq_props
2245
+
2246
+ self._retreat(index)
2225
2247
  key = self._parse_column()
2226
2248
 
2227
2249
  if not self._match(TokenType.EQ):
2228
2250
  self._retreat(index)
2229
- return self._parse_sequence_properties()
2251
+ return None
2230
2252
 
2231
2253
  # Transform the key to exp.Dot if it's dotted identifiers wrapped in exp.Column or to exp.Var otherwise
2232
2254
  if isinstance(key, exp.Column):
@@ -3820,7 +3842,8 @@ class Parser(metaclass=_Parser):
3820
3842
  elif self._match(TokenType.USING):
3821
3843
  kwargs["using"] = self._parse_using_identifiers()
3822
3844
  elif (
3823
- not (outer_apply or cross_apply)
3845
+ not method
3846
+ and not (outer_apply or cross_apply)
3824
3847
  and not isinstance(kwargs["this"], exp.Unnest)
3825
3848
  and not (kind and kind.token_type in (TokenType.CROSS, TokenType.ARRAY))
3826
3849
  ):
@@ -5255,7 +5278,7 @@ class Parser(metaclass=_Parser):
5255
5278
  while self._match(TokenType.DOT):
5256
5279
  type_name = f"{type_name}.{self._advance_any() and self._prev.text}"
5257
5280
 
5258
- return exp.DataType.build(type_name, udt=True)
5281
+ return exp.DataType.build(type_name, dialect=self.dialect, udt=True)
5259
5282
 
5260
5283
  def _parse_types(
5261
5284
  self, check_func: bool = False, schema: bool = False, allow_identifiers: bool = True
@@ -6556,7 +6579,7 @@ class Parser(metaclass=_Parser):
6556
6579
  elif not to:
6557
6580
  self.raise_error("Expected TYPE after CAST")
6558
6581
  elif isinstance(to, exp.Identifier):
6559
- to = exp.DataType.build(to.name, udt=True)
6582
+ to = exp.DataType.build(to.name, dialect=self.dialect, udt=True)
6560
6583
  elif to.this == exp.DataType.Type.CHAR:
6561
6584
  if self._match(TokenType.CHARACTER_SET):
6562
6585
  to = self.expression(exp.CharacterSet, this=self._parse_var_or_string())
@@ -8684,3 +8707,18 @@ class Parser(metaclass=_Parser):
8684
8707
  kwargs["requires_string"] = self.dialect.TRY_CAST_REQUIRES_STRING
8685
8708
 
8686
8709
  return self.expression(exp_class, **kwargs)
8710
+
8711
+ def _parse_json_value(self) -> exp.JSONValue:
8712
+ this = self._parse_bitwise()
8713
+ self._match(TokenType.COMMA)
8714
+ path = self._parse_bitwise()
8715
+
8716
+ returning = self._match(TokenType.RETURNING) and self._parse_type()
8717
+
8718
+ return self.expression(
8719
+ exp.JSONValue,
8720
+ this=this,
8721
+ path=self.dialect.to_json_path(path),
8722
+ returning=returning,
8723
+ on_condition=self._parse_on_condition(),
8724
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlglot
3
- Version: 27.6.0
3
+ Version: 27.8.0
4
4
  Summary: An easily customizable SQL parser and transpiler
5
5
  Author-email: Toby Mao <toby.mao@gmail.com>
6
6
  Project-URL: Homepage, https://sqlglot.com/
@@ -256,7 +256,7 @@ sqlglot.errors.ParseError: Expecting ). Line 1, Col: 34.
256
256
  Structured syntax errors are accessible for programmatic use:
257
257
 
258
258
  ```python
259
- import sqlglot
259
+ import sqlglot.errors
260
260
  try:
261
261
  sqlglot.transpile("SELECT foo FROM (SELECT baz FROM t")
262
262
  except sqlglot.errors.ParseError as e: