sqlglot 27.8.0__py3-none-any.whl → 27.9.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.
@@ -5,8 +5,10 @@ import typing as t
5
5
  from sqlglot import exp, generator, parser, tokens
6
6
  from sqlglot.dialects.dialect import (
7
7
  Dialect,
8
+ NormalizationStrategy,
8
9
  binary_from_function,
9
10
  build_formatted_time,
11
+ groupconcat_sql,
10
12
  rename_func,
11
13
  strposition_sql,
12
14
  timestrtotime_sql,
@@ -73,6 +75,17 @@ DATE_UNITS = {"DAY", "WEEK", "MONTH", "YEAR", "HOUR", "MINUTE", "SECOND"}
73
75
 
74
76
 
75
77
  class Exasol(Dialect):
78
+ # https://docs.exasol.com/db/latest/sql_references/basiclanguageelements.htm#SQLidentifier
79
+ NORMALIZATION_STRATEGY = NormalizationStrategy.UPPERCASE
80
+ # https://docs.exasol.com/db/latest/sql_references/data_types/datatypesoverview.htm
81
+ SUPPORTS_USER_DEFINED_TYPES = False
82
+ # https://docs.exasol.com/db/latest/sql/select.htm
83
+ SUPPORTS_SEMI_ANTI_JOIN = False
84
+ SUPPORTS_COLUMN_JOIN_MARKS = True
85
+ NULL_ORDERING = "nulls_are_last"
86
+ # https://docs.exasol.com/db/latest/sql_references/literals.htm#StringLiterals
87
+ CONCAT_COALESCE = True
88
+
76
89
  TIME_MAPPING = {
77
90
  "yyyy": "%Y",
78
91
  "YYYY": "%Y",
@@ -108,6 +121,7 @@ class Exasol(Dialect):
108
121
  # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/if.htm
109
122
  "ENDIF": TokenType.END,
110
123
  "LONG VARCHAR": TokenType.TEXT,
124
+ "SEPARATOR": TokenType.SEPARATOR,
111
125
  }
112
126
  KEYWORDS.pop("DIV")
113
127
 
@@ -176,6 +190,12 @@ class Exasol(Dialect):
176
190
  this=self._match(TokenType.IS) and self._parse_string(),
177
191
  ),
178
192
  }
193
+ FUNCTION_PARSERS = {
194
+ **parser.Parser.FUNCTION_PARSERS,
195
+ # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/listagg.htm
196
+ # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/group_concat.htm
197
+ **dict.fromkeys(("GROUP_CONCAT", "LISTAGG"), lambda self: self._parse_group_concat()),
198
+ }
179
199
 
180
200
  class Generator(generator.Generator):
181
201
  # https://docs.exasol.com/db/latest/sql_references/data_types/datatypedetails.htm#StringDataType
@@ -235,6 +255,9 @@ class Exasol(Dialect):
235
255
  exp.TsOrDsDiff: _date_diff_sql,
236
256
  exp.DateTrunc: lambda self, e: self.func("TRUNC", e.this, unit_to_str(e)),
237
257
  exp.DatetimeTrunc: timestamptrunc_sql(),
258
+ exp.GroupConcat: lambda self, e: groupconcat_sql(
259
+ self, e, func_name="LISTAGG", within_group=True
260
+ ),
238
261
  # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/edit_distance.htm#EDIT_DISTANCE
239
262
  exp.Levenshtein: unsupported_args("ins_cost", "del_cost", "sub_cost", "max_dist")(
240
263
  rename_func("EDIT_DISTANCE")
sqlglot/dialects/mysql.py CHANGED
@@ -676,39 +676,6 @@ class MySQL(Dialect):
676
676
  parse_interval=parse_interval, fallback_to_identifier=fallback_to_identifier
677
677
  )
678
678
 
679
- def _parse_group_concat(self) -> t.Optional[exp.Expression]:
680
- def concat_exprs(
681
- node: t.Optional[exp.Expression], exprs: t.List[exp.Expression]
682
- ) -> exp.Expression:
683
- if isinstance(node, exp.Distinct) and len(node.expressions) > 1:
684
- concat_exprs = [
685
- self.expression(exp.Concat, expressions=node.expressions, safe=True)
686
- ]
687
- node.set("expressions", concat_exprs)
688
- return node
689
- if len(exprs) == 1:
690
- return exprs[0]
691
- return self.expression(exp.Concat, expressions=args, safe=True)
692
-
693
- args = self._parse_csv(self._parse_lambda)
694
-
695
- if args:
696
- order = args[-1] if isinstance(args[-1], exp.Order) else None
697
-
698
- if order:
699
- # Order By is the last (or only) expression in the list and has consumed the 'expr' before it,
700
- # remove 'expr' from exp.Order and add it back to args
701
- args[-1] = order.this
702
- order.set("this", concat_exprs(order.this, args))
703
-
704
- this = order or concat_exprs(args[0], args)
705
- else:
706
- this = None
707
-
708
- separator = self._parse_field() if self._match(TokenType.SEPARATOR) else None
709
-
710
- return self.expression(exp.GroupConcat, this=this, separator=separator)
711
-
712
679
  def _parse_alter_table_alter_index(self) -> exp.AlterIndex:
713
680
  index = self._parse_field(any_token=True)
714
681
 
@@ -192,6 +192,7 @@ class Redshift(Postgres):
192
192
  exp.DistKeyProperty: lambda self, e: self.func("DISTKEY", e.this),
193
193
  exp.DistStyleProperty: lambda self, e: self.naked_property(e),
194
194
  exp.Explode: lambda self, e: self.explode_sql(e),
195
+ exp.FarmFingerprint: rename_func("FARMFINGERPRINT64"),
195
196
  exp.FromBase: rename_func("STRTOL"),
196
197
  exp.GeneratedAsIdentityColumnConstraint: generatedasidentitycolumnconstraint_sql,
197
198
  exp.JSONExtract: json_extract_segments("JSON_EXTRACT_PATH_TEXT"),
@@ -8,12 +8,25 @@ from sqlglot.dialects.dialect import (
8
8
  json_extract_segments,
9
9
  json_path_key_only_name,
10
10
  rename_func,
11
+ bool_xor_sql,
12
+ count_if_to_sum,
11
13
  )
12
14
  from sqlglot.dialects.mysql import MySQL
15
+ from sqlglot.expressions import DataType
13
16
  from sqlglot.generator import unsupported_args
14
17
  from sqlglot.helper import seq_get
15
18
 
16
19
 
20
+ def cast_to_time6(expression: t.Optional[exp.Expression]) -> exp.Cast:
21
+ return exp.Cast(
22
+ this=expression,
23
+ to=exp.DataType.build(
24
+ exp.DataType.Type.TIME,
25
+ expressions=[exp.DataTypeParam(this=exp.Literal.number(6))],
26
+ ),
27
+ )
28
+
29
+
17
30
  class SingleStore(MySQL):
18
31
  SUPPORTS_ORDER_BY_ALL = True
19
32
 
@@ -56,20 +69,48 @@ class SingleStore(MySQL):
56
69
  "TO_CHAR": build_formatted_time(exp.ToChar, "singlestore"),
57
70
  "STR_TO_DATE": build_formatted_time(exp.StrToDate, "mysql"),
58
71
  "DATE_FORMAT": build_formatted_time(exp.TimeToStr, "mysql"),
72
+ # The first argument of following functions is converted to TIME(6)
73
+ # This is needed because exp.TimeToStr is converted to DATE_FORMAT
74
+ # which interprets the first argument as DATETIME and fails to parse
75
+ # string literals like '12:05:47' without a date part.
59
76
  "TIME_FORMAT": lambda args: exp.TimeToStr(
60
- # The first argument is converted to TIME(6)
61
- # This is needed because exp.TimeToStr is converted to DATE_FORMAT
62
- # which interprets the first argument as DATETIME and fails to parse
63
- # string literals like '12:05:47' without a date part.
64
- this=exp.Cast(
65
- this=seq_get(args, 0),
66
- to=exp.DataType.build(
67
- exp.DataType.Type.TIME,
68
- expressions=[exp.DataTypeParam(this=exp.Literal.number(6))],
69
- ),
70
- ),
77
+ this=cast_to_time6(seq_get(args, 0)),
71
78
  format=MySQL.format_time(seq_get(args, 1)),
72
79
  ),
80
+ "HOUR": lambda args: exp.cast(
81
+ exp.TimeToStr(
82
+ this=cast_to_time6(seq_get(args, 0)),
83
+ format=MySQL.format_time(exp.Literal.string("%k")),
84
+ ),
85
+ DataType.Type.INT,
86
+ ),
87
+ "MICROSECOND": lambda args: exp.cast(
88
+ exp.TimeToStr(
89
+ this=cast_to_time6(seq_get(args, 0)),
90
+ format=MySQL.format_time(exp.Literal.string("%f")),
91
+ ),
92
+ DataType.Type.INT,
93
+ ),
94
+ "SECOND": lambda args: exp.cast(
95
+ exp.TimeToStr(
96
+ this=cast_to_time6(seq_get(args, 0)),
97
+ format=MySQL.format_time(exp.Literal.string("%s")),
98
+ ),
99
+ DataType.Type.INT,
100
+ ),
101
+ "MINUTE": lambda args: exp.cast(
102
+ exp.TimeToStr(
103
+ this=cast_to_time6(seq_get(args, 0)),
104
+ format=MySQL.format_time(exp.Literal.string("%i")),
105
+ ),
106
+ DataType.Type.INT,
107
+ ),
108
+ "MONTHNAME": lambda args: exp.TimeToStr(
109
+ this=seq_get(args, 0),
110
+ format=MySQL.format_time(exp.Literal.string("%M")),
111
+ ),
112
+ "WEEKDAY": lambda args: exp.paren(exp.DayOfWeek(this=seq_get(args, 0)) + 5, copy=False)
113
+ % 7,
73
114
  "UNIX_TIMESTAMP": exp.StrToUnix.from_arg_list,
74
115
  "FROM_UNIXTIME": build_formatted_time(exp.UnixToTime, "mysql"),
75
116
  "BSON_EXTRACT_BSON": build_json_extract_path(exp.JSONBExtract),
@@ -92,7 +133,46 @@ class SingleStore(MySQL):
92
133
  "JSON_EXTRACT_BIGINT": build_json_extract_path(
93
134
  exp.JSONExtractScalar, json_type="BIGINT"
94
135
  ),
136
+ "JSON_ARRAY_CONTAINS_STRING": lambda args: exp.JSONArrayContains(
137
+ this=seq_get(args, 1),
138
+ expression=seq_get(args, 0),
139
+ json_type="STRING",
140
+ ),
141
+ "JSON_ARRAY_CONTAINS_DOUBLE": lambda args: exp.JSONArrayContains(
142
+ this=seq_get(args, 1),
143
+ expression=seq_get(args, 0),
144
+ json_type="DOUBLE",
145
+ ),
146
+ "JSON_ARRAY_CONTAINS_JSON": lambda args: exp.JSONArrayContains(
147
+ this=seq_get(args, 1),
148
+ expression=seq_get(args, 0),
149
+ json_type="JSON",
150
+ ),
95
151
  "DATE": exp.Date.from_arg_list,
152
+ "DAYNAME": lambda args: exp.TimeToStr(
153
+ this=seq_get(args, 0),
154
+ format=MySQL.format_time(exp.Literal.string("%W")),
155
+ ),
156
+ "APPROX_COUNT_DISTINCT": exp.Hll.from_arg_list,
157
+ "APPROX_PERCENTILE": lambda args, dialect: exp.ApproxQuantile(
158
+ this=seq_get(args, 0),
159
+ quantile=seq_get(args, 1),
160
+ error_tolerance=seq_get(args, 2),
161
+ ),
162
+ "VARIANCE": exp.VariancePop.from_arg_list,
163
+ "INSTR": exp.Contains.from_arg_list,
164
+ "REGEXP_MATCH": lambda args: exp.RegexpExtractAll(
165
+ this=seq_get(args, 0),
166
+ expression=seq_get(args, 1),
167
+ parameters=seq_get(args, 2),
168
+ ),
169
+ "REGEXP_SUBSTR": lambda args: exp.RegexpExtract(
170
+ this=seq_get(args, 0),
171
+ expression=seq_get(args, 1),
172
+ position=seq_get(args, 2),
173
+ occurrence=seq_get(args, 3),
174
+ parameters=seq_get(args, 4),
175
+ ),
96
176
  }
97
177
 
98
178
  CAST_COLUMN_OPERATORS = {TokenType.COLON_GT, TokenType.NCOLON_GT}
@@ -128,7 +208,9 @@ class SingleStore(MySQL):
128
208
 
129
209
  TRANSFORMS = {
130
210
  **MySQL.Generator.TRANSFORMS,
131
- exp.TsOrDsToDate: lambda self, e: self.func("TO_DATE", e.this, self.format_time(e)),
211
+ exp.TsOrDsToDate: lambda self, e: self.func("TO_DATE", e.this, self.format_time(e))
212
+ if e.args.get("format")
213
+ else self.func("DATE", e.this),
132
214
  exp.StrToTime: lambda self, e: self.func("TO_TIMESTAMP", e.this, self.format_time(e)),
133
215
  exp.ToChar: lambda self, e: self.func("TO_CHAR", e.this, self.format_time(e)),
134
216
  exp.StrToDate: lambda self, e: self.func(
@@ -195,15 +277,61 @@ class SingleStore(MySQL):
195
277
  exp.JSONPathKey: json_path_key_only_name,
196
278
  exp.JSONPathSubscript: lambda self, e: self.json_path_part(e.this),
197
279
  exp.JSONPathRoot: lambda *_: "",
280
+ exp.DayOfWeekIso: lambda self, e: f"(({self.func('DAYOFWEEK', e.this)} % 7) + 1)",
281
+ exp.DayOfMonth: rename_func("DAY"),
282
+ exp.Hll: rename_func("APPROX_COUNT_DISTINCT"),
283
+ exp.ApproxDistinct: rename_func("APPROX_COUNT_DISTINCT"),
284
+ exp.CountIf: count_if_to_sum,
285
+ exp.LogicalOr: lambda self, e: f"MAX(ABS({self.sql(e, 'this')}))",
286
+ exp.LogicalAnd: lambda self, e: f"MIN(ABS({self.sql(e, 'this')}))",
287
+ exp.ApproxQuantile: unsupported_args("accuracy", "weight")(
288
+ lambda self, e: self.func(
289
+ "APPROX_PERCENTILE",
290
+ e.this,
291
+ e.args.get("quantile"),
292
+ e.args.get("error_tolerance"),
293
+ )
294
+ ),
295
+ exp.Variance: rename_func("VAR_SAMP"),
296
+ exp.VariancePop: rename_func("VAR_POP"),
297
+ exp.Xor: bool_xor_sql,
298
+ exp.RegexpLike: lambda self, e: self.binary(e, "RLIKE"),
299
+ exp.Repeat: lambda self, e: self.func(
300
+ "LPAD",
301
+ exp.Literal.string(""),
302
+ exp.Mul(this=self.func("LENGTH", e.this), expression=e.args.get("times")),
303
+ e.this,
304
+ ),
305
+ exp.IsAscii: lambda self, e: f"({self.sql(e, 'this')} RLIKE '^[\x00-\x7f]*$')",
306
+ exp.MD5Digest: lambda self, e: self.func("UNHEX", self.func("MD5", e.this)),
307
+ exp.Chr: rename_func("CHAR"),
308
+ exp.Contains: rename_func("INSTR"),
309
+ exp.RegexpExtractAll: unsupported_args("position", "occurrence", "group")(
310
+ lambda self, e: self.func(
311
+ "REGEXP_MATCH",
312
+ e.this,
313
+ e.expression,
314
+ e.args.get("parameters"),
315
+ )
316
+ ),
317
+ exp.RegexpExtract: unsupported_args("group")(
318
+ lambda self, e: self.func(
319
+ "REGEXP_SUBSTR",
320
+ e.this,
321
+ e.expression,
322
+ e.args.get("position"),
323
+ e.args.get("occurrence"),
324
+ e.args.get("parameters"),
325
+ )
326
+ ),
327
+ exp.StartsWith: lambda self, e: self.func(
328
+ "REGEXP_INSTR", e.this, self.func("CONCAT", exp.Literal.string("^"), e.expression)
329
+ ),
330
+ exp.FromBase: lambda self, e: self.func(
331
+ "CONV", e.this, e.expression, exp.Literal.number(10)
332
+ ),
198
333
  }
199
334
  TRANSFORMS.pop(exp.JSONExtractScalar)
200
- TRANSFORMS.pop(exp.JSONPathFilter)
201
- TRANSFORMS.pop(exp.JSONPathRecursive)
202
- TRANSFORMS.pop(exp.JSONPathScript)
203
- TRANSFORMS.pop(exp.JSONPathSelector)
204
- TRANSFORMS.pop(exp.JSONPathSlice)
205
- TRANSFORMS.pop(exp.JSONPathUnion)
206
- TRANSFORMS.pop(exp.JSONPathWildcard)
207
335
 
208
336
  # https://docs.singlestore.com/cloud/reference/sql-reference/restricted-keywords/list-of-restricted-keywords/
209
337
  RESERVED_KEYWORDS = {
@@ -1286,3 +1414,21 @@ class SingleStore(MySQL):
1286
1414
  res = exp.Cast(this=res, to=returning)
1287
1415
 
1288
1416
  return self.sql(res)
1417
+
1418
+ def all_sql(self, expression: exp.All) -> str:
1419
+ self.unsupported("ALL subquery predicate is not supported in SingleStore")
1420
+ return super().all_sql(expression)
1421
+
1422
+ def jsonarraycontains_sql(self, expression: exp.JSONArrayContains) -> str:
1423
+ json_type = expression.text("json_type").upper()
1424
+
1425
+ if json_type:
1426
+ return self.func(
1427
+ f"JSON_ARRAY_CONTAINS_{json_type}", expression.expression, expression.this
1428
+ )
1429
+
1430
+ return self.func(
1431
+ "JSON_ARRAY_CONTAINS_JSON",
1432
+ expression.expression,
1433
+ self.func("TO_JSON", expression.this),
1434
+ )
sqlglot/dialects/tsql.py CHANGED
@@ -658,6 +658,8 @@ class TSQL(Dialect):
658
658
  else self.expression(exp.ScopeResolution, this=this, expression=to),
659
659
  }
660
660
 
661
+ SET_OP_MODIFIERS = {"offset"}
662
+
661
663
  def _parse_alter_table_set(self) -> exp.AlterSet:
662
664
  return self._parse_wrapped(super()._parse_alter_table_set)
663
665
 
sqlglot/expressions.py CHANGED
@@ -2790,6 +2790,11 @@ class BackupProperty(Property):
2790
2790
  arg_types = {"this": True}
2791
2791
 
2792
2792
 
2793
+ # https://doris.apache.org/docs/sql-manual/sql-statements/table-and-view/async-materialized-view/CREATE-ASYNC-MATERIALIZED-VIEW/
2794
+ class BuildProperty(Property):
2795
+ arg_types = {"this": True}
2796
+
2797
+
2793
2798
  class BlockCompressionProperty(Property):
2794
2799
  arg_types = {
2795
2800
  "autotemp": False,
@@ -3031,6 +3036,27 @@ class PartitionByRangePropertyDynamic(Expression):
3031
3036
  arg_types = {"this": False, "start": True, "end": True, "every": True}
3032
3037
 
3033
3038
 
3039
+ # https://doris.apache.org/docs/table-design/data-partitioning/manual-partitioning
3040
+ class PartitionByListProperty(Property):
3041
+ arg_types = {"partition_expressions": True, "create_expressions": True}
3042
+
3043
+
3044
+ # https://doris.apache.org/docs/table-design/data-partitioning/manual-partitioning
3045
+ class PartitionList(Expression):
3046
+ arg_types = {"this": True, "expressions": True}
3047
+
3048
+
3049
+ # https://doris.apache.org/docs/sql-manual/sql-statements/table-and-view/async-materialized-view/CREATE-ASYNC-MATERIALIZED-VIEW
3050
+ class RefreshTriggerProperty(Property):
3051
+ arg_types = {
3052
+ "method": True,
3053
+ "kind": False,
3054
+ "every": False,
3055
+ "unit": False,
3056
+ "starts": False,
3057
+ }
3058
+
3059
+
3034
3060
  # https://docs.starrocks.io/docs/sql-reference/sql-statements/table_bucket_part_index/CREATE_TABLE/
3035
3061
  class UniqueKeyProperty(Property):
3036
3062
  arg_types = {"expressions": True}
@@ -4304,7 +4330,14 @@ class Select(Query):
4304
4330
 
4305
4331
  @property
4306
4332
  def named_selects(self) -> t.List[str]:
4307
- return [e.output_name for e in self.expressions if e.alias_or_name]
4333
+ selects = []
4334
+
4335
+ for e in self.expressions:
4336
+ if e.alias_or_name:
4337
+ selects.append(e.output_name)
4338
+ elif isinstance(e, Aliases):
4339
+ selects.extend([a.name for a in e.aliases])
4340
+ return selects
4308
4341
 
4309
4342
  @property
4310
4343
  def is_star(self) -> bool:
@@ -4876,6 +4909,7 @@ class Alter(Expression):
4876
4909
  "options": False,
4877
4910
  "cluster": False,
4878
4911
  "not_valid": False,
4912
+ "check": False,
4879
4913
  }
4880
4914
 
4881
4915
  @property
@@ -5429,6 +5463,11 @@ class ByteLength(Func):
5429
5463
  pass
5430
5464
 
5431
5465
 
5466
+ # https://cloud.google.com/bigquery/docs/reference/standard-sql/json_functions#bool_for_json
5467
+ class JSONBool(Func):
5468
+ pass
5469
+
5470
+
5432
5471
  class ArrayRemove(Func):
5433
5472
  arg_types = {"this": True, "expression": True}
5434
5473
 
@@ -5455,10 +5494,28 @@ class ApproxTopK(AggFunc):
5455
5494
  arg_types = {"this": True, "expression": False, "counters": False}
5456
5495
 
5457
5496
 
5497
+ class ApproxTopSum(AggFunc):
5498
+ arg_types = {"this": True, "expression": True, "count": True}
5499
+
5500
+
5501
+ class ApproxQuantiles(AggFunc):
5502
+ arg_types = {"this": True, "expression": False}
5503
+
5504
+
5505
+ class FarmFingerprint(Func):
5506
+ arg_types = {"expressions": True}
5507
+ is_var_len_args = True
5508
+ _sql_names = ["FARM_FINGERPRINT", "FARMFINGERPRINT64"]
5509
+
5510
+
5458
5511
  class Flatten(Func):
5459
5512
  pass
5460
5513
 
5461
5514
 
5515
+ class Float64(Func):
5516
+ arg_types = {"this": True, "expression": False}
5517
+
5518
+
5462
5519
  # https://spark.apache.org/docs/latest/api/sql/index.html#transform
5463
5520
  class Transform(Func):
5464
5521
  arg_types = {"this": True, "expression": True}
@@ -5548,6 +5605,10 @@ class ToChar(Func):
5548
5605
  }
5549
5606
 
5550
5607
 
5608
+ class ToCodePoints(Func):
5609
+ pass
5610
+
5611
+
5551
5612
  # https://docs.snowflake.com/en/sql-reference/functions/to_decimal
5552
5613
  # https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/TO_NUMBER.html
5553
5614
  class ToNumber(Func):
@@ -5568,6 +5629,10 @@ class ToDouble(Func):
5568
5629
  }
5569
5630
 
5570
5631
 
5632
+ class CodePointsToBytes(Func):
5633
+ pass
5634
+
5635
+
5571
5636
  class Columns(Func):
5572
5637
  arg_types = {"this": True, "unpack": False}
5573
5638
 
@@ -6193,12 +6258,16 @@ class Floor(Func):
6193
6258
  arg_types = {"this": True, "decimals": False, "to": False}
6194
6259
 
6195
6260
 
6261
+ class FromBase32(Func):
6262
+ pass
6263
+
6264
+
6196
6265
  class FromBase64(Func):
6197
6266
  pass
6198
6267
 
6199
6268
 
6200
- class FeaturesAtTime(Func):
6201
- arg_types = {"this": True, "time": False, "num_rows": False, "ignore_feature_nulls": False}
6269
+ class ToBase32(Func):
6270
+ pass
6202
6271
 
6203
6272
 
6204
6273
  class ToBase64(Func):
@@ -6553,9 +6622,18 @@ class JSONFormat(Func):
6553
6622
 
6554
6623
  # https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#operator_member-of
6555
6624
  class JSONArrayContains(Binary, Predicate, Func):
6625
+ arg_types = {"this": True, "expression": True, "json_type": False}
6556
6626
  _sql_names = ["JSON_ARRAY_CONTAINS"]
6557
6627
 
6558
6628
 
6629
+ class ParseBignumeric(Func):
6630
+ pass
6631
+
6632
+
6633
+ class ParseNumeric(Func):
6634
+ pass
6635
+
6636
+
6559
6637
  class ParseJSON(Func):
6560
6638
  # BigQuery, Snowflake have PARSE_JSON, Presto has JSON_PARSE
6561
6639
  # Snowflake also has TRY_PARSE_JSON, which is represented using `safe`
@@ -6726,6 +6804,29 @@ class Predict(Func):
6726
6804
  arg_types = {"this": True, "expression": True, "params_struct": False}
6727
6805
 
6728
6806
 
6807
+ # https://cloud.google.com/bigquery/docs/reference/standard-sql/bigqueryml-syntax-feature-time
6808
+ class FeaturesAtTime(Func):
6809
+ arg_types = {"this": True, "time": False, "num_rows": False, "ignore_feature_nulls": False}
6810
+
6811
+
6812
+ # https://cloud.google.com/bigquery/docs/reference/standard-sql/bigqueryml-syntax-generate-embedding
6813
+ class GenerateEmbedding(Func):
6814
+ arg_types = {"this": True, "expression": True, "params_struct": False}
6815
+
6816
+
6817
+ # https://cloud.google.com/bigquery/docs/reference/standard-sql/search_functions#vector_search
6818
+ class VectorSearch(Func):
6819
+ arg_types = {
6820
+ "this": True,
6821
+ "column_to_search": True,
6822
+ "query_table": True,
6823
+ "query_column_to_search": False,
6824
+ "top_k": False,
6825
+ "distance_type": False,
6826
+ "options": False,
6827
+ }
6828
+
6829
+
6729
6830
  class Pow(Binary, Func):
6730
6831
  _sql_names = ["POWER", "POW"]
6731
6832
 
@@ -6743,7 +6844,13 @@ class Quantile(AggFunc):
6743
6844
 
6744
6845
 
6745
6846
  class ApproxQuantile(Quantile):
6746
- arg_types = {"this": True, "quantile": True, "accuracy": False, "weight": False}
6847
+ arg_types = {
6848
+ "this": True,
6849
+ "quantile": True,
6850
+ "accuracy": False,
6851
+ "weight": False,
6852
+ "error_tolerance": False,
6853
+ }
6747
6854
 
6748
6855
 
6749
6856
  class Quarter(Func):
@@ -6845,6 +6952,10 @@ class SafeDivide(Func):
6845
6952
  arg_types = {"this": True, "expression": True}
6846
6953
 
6847
6954
 
6955
+ class SafeConvertBytesToString(Func):
6956
+ pass
6957
+
6958
+
6848
6959
  class SHA(Func):
6849
6960
  _sql_names = ["SHA", "SHA1"]
6850
6961