From beba715b97dd2349e01dde9b077d2535680ebdca Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 10 May 2023 08:44:58 +0200 Subject: Merging upstream version 12.2.0. Signed-off-by: Daniel Baumann --- docs/sqlglot/dialects/hive.html | 1497 ++++++++++++++++++++------------------- 1 file changed, 760 insertions(+), 737 deletions(-) (limited to 'docs/sqlglot/dialects/hive.html') diff --git a/docs/sqlglot/dialects/hive.html b/docs/sqlglot/dialects/hive.html index b477f0e..5266bd3 100644 --- a/docs/sqlglot/dialects/hive.html +++ b/docs/sqlglot/dialects/hive.html @@ -169,300 +169,316 @@ 81 return f"{diff_sql}{multiplier_sql}" 82 83 - 84def _array_sort(self: generator.Generator, expression: exp.ArraySort) -> str: - 85 if expression.expression: - 86 self.unsupported("Hive SORT_ARRAY does not support a comparator") - 87 return f"SORT_ARRAY({self.sql(expression, 'this')})" - 88 + 84def _json_format_sql(self: generator.Generator, expression: exp.JSONFormat) -> str: + 85 this = expression.this + 86 + 87 if not this.type: + 88 from sqlglot.optimizer.annotate_types import annotate_types 89 - 90def _property_sql(self: generator.Generator, expression: exp.Property) -> str: - 91 return f"'{expression.name}'={self.sql(expression, 'value')}" - 92 - 93 - 94def _str_to_unix(self: generator.Generator, expression: exp.StrToUnix) -> str: - 95 return self.func("UNIX_TIMESTAMP", expression.this, _time_format(self, expression)) + 90 annotate_types(this) + 91 + 92 if this.type.is_type(exp.DataType.Type.JSON): + 93 return self.sql(this) + 94 return self.func("TO_JSON", this, expression.args.get("options")) + 95 96 - 97 - 98def _str_to_date(self: generator.Generator, expression: exp.StrToDate) -> str: - 99 this = self.sql(expression, "this") -100 time_format = self.format_time(expression) -101 if time_format not in (Hive.time_format, Hive.date_format): -102 this = f"FROM_UNIXTIME(UNIX_TIMESTAMP({this}, {time_format}))" -103 return f"CAST({this} AS DATE)" -104 + 97def _array_sort_sql(self: generator.Generator, expression: exp.ArraySort) -> str: + 98 if expression.expression: + 99 self.unsupported("Hive SORT_ARRAY does not support a comparator") +100 return f"SORT_ARRAY({self.sql(expression, 'this')})" +101 +102 +103def _property_sql(self: generator.Generator, expression: exp.Property) -> str: +104 return f"'{expression.name}'={self.sql(expression, 'value')}" 105 -106def _str_to_time(self: generator.Generator, expression: exp.StrToTime) -> str: -107 this = self.sql(expression, "this") -108 time_format = self.format_time(expression) -109 if time_format not in (Hive.time_format, Hive.date_format): -110 this = f"FROM_UNIXTIME(UNIX_TIMESTAMP({this}, {time_format}))" -111 return f"CAST({this} AS TIMESTAMP)" -112 -113 -114def _time_format( -115 self: generator.Generator, expression: exp.UnixToStr | exp.StrToUnix -116) -> t.Optional[str]: -117 time_format = self.format_time(expression) -118 if time_format == Hive.time_format: -119 return None -120 return time_format -121 -122 -123def _time_to_str(self: generator.Generator, expression: exp.TimeToStr) -> str: -124 this = self.sql(expression, "this") -125 time_format = self.format_time(expression) -126 return f"DATE_FORMAT({this}, {time_format})" -127 -128 -129def _to_date_sql(self: generator.Generator, expression: exp.TsOrDsToDate) -> str: -130 this = self.sql(expression, "this") -131 time_format = self.format_time(expression) -132 if time_format and time_format not in (Hive.time_format, Hive.date_format): -133 return f"TO_DATE({this}, {time_format})" -134 return f"TO_DATE({this})" +106 +107def _str_to_unix_sql(self: generator.Generator, expression: exp.StrToUnix) -> str: +108 return self.func("UNIX_TIMESTAMP", expression.this, _time_format(self, expression)) +109 +110 +111def _str_to_date_sql(self: generator.Generator, expression: exp.StrToDate) -> str: +112 this = self.sql(expression, "this") +113 time_format = self.format_time(expression) +114 if time_format not in (Hive.time_format, Hive.date_format): +115 this = f"FROM_UNIXTIME(UNIX_TIMESTAMP({this}, {time_format}))" +116 return f"CAST({this} AS DATE)" +117 +118 +119def _str_to_time_sql(self: generator.Generator, expression: exp.StrToTime) -> str: +120 this = self.sql(expression, "this") +121 time_format = self.format_time(expression) +122 if time_format not in (Hive.time_format, Hive.date_format): +123 this = f"FROM_UNIXTIME(UNIX_TIMESTAMP({this}, {time_format}))" +124 return f"CAST({this} AS TIMESTAMP)" +125 +126 +127def _time_format( +128 self: generator.Generator, expression: exp.UnixToStr | exp.StrToUnix +129) -> t.Optional[str]: +130 time_format = self.format_time(expression) +131 if time_format == Hive.time_format: +132 return None +133 return time_format +134 135 -136 -137def _index_sql(self: generator.Generator, expression: exp.Index) -> str: -138 this = self.sql(expression, "this") -139 table = self.sql(expression, "table") -140 columns = self.sql(expression, "columns") -141 return f"{this} ON TABLE {table} {columns}" -142 -143 -144class Hive(Dialect): -145 alias_post_tablesample = True -146 -147 time_mapping = { -148 "y": "%Y", -149 "Y": "%Y", -150 "YYYY": "%Y", -151 "yyyy": "%Y", -152 "YY": "%y", -153 "yy": "%y", -154 "MMMM": "%B", -155 "MMM": "%b", -156 "MM": "%m", -157 "M": "%-m", -158 "dd": "%d", -159 "d": "%-d", -160 "HH": "%H", -161 "H": "%-H", -162 "hh": "%I", -163 "h": "%-I", -164 "mm": "%M", -165 "m": "%-M", -166 "ss": "%S", -167 "s": "%-S", -168 "SSSSSS": "%f", -169 "a": "%p", -170 "DD": "%j", -171 "D": "%-j", -172 "E": "%a", -173 "EE": "%a", -174 "EEE": "%a", -175 "EEEE": "%A", -176 } -177 -178 date_format = "'yyyy-MM-dd'" -179 dateint_format = "'yyyyMMdd'" -180 time_format = "'yyyy-MM-dd HH:mm:ss'" -181 -182 class Tokenizer(tokens.Tokenizer): -183 QUOTES = ["'", '"'] -184 IDENTIFIERS = ["`"] -185 STRING_ESCAPES = ["\\"] -186 ENCODE = "utf-8" -187 IDENTIFIER_CAN_START_WITH_DIGIT = True -188 -189 KEYWORDS = { -190 **tokens.Tokenizer.KEYWORDS, -191 "ADD ARCHIVE": TokenType.COMMAND, -192 "ADD ARCHIVES": TokenType.COMMAND, -193 "ADD FILE": TokenType.COMMAND, -194 "ADD FILES": TokenType.COMMAND, -195 "ADD JAR": TokenType.COMMAND, -196 "ADD JARS": TokenType.COMMAND, -197 "MSCK REPAIR": TokenType.COMMAND, -198 "WITH SERDEPROPERTIES": TokenType.SERDE_PROPERTIES, -199 } -200 -201 NUMERIC_LITERALS = { -202 "L": "BIGINT", -203 "S": "SMALLINT", -204 "Y": "TINYINT", -205 "D": "DOUBLE", -206 "F": "FLOAT", -207 "BD": "DECIMAL", -208 } -209 -210 class Parser(parser.Parser): -211 LOG_DEFAULTS_TO_LN = True -212 STRICT_CAST = False +136def _time_to_str(self: generator.Generator, expression: exp.TimeToStr) -> str: +137 this = self.sql(expression, "this") +138 time_format = self.format_time(expression) +139 return f"DATE_FORMAT({this}, {time_format})" +140 +141 +142def _to_date_sql(self: generator.Generator, expression: exp.TsOrDsToDate) -> str: +143 this = self.sql(expression, "this") +144 time_format = self.format_time(expression) +145 if time_format and time_format not in (Hive.time_format, Hive.date_format): +146 return f"TO_DATE({this}, {time_format})" +147 return f"TO_DATE({this})" +148 +149 +150def _index_sql(self: generator.Generator, expression: exp.Index) -> str: +151 this = self.sql(expression, "this") +152 table = self.sql(expression, "table") +153 columns = self.sql(expression, "columns") +154 return f"{this} ON TABLE {table} {columns}" +155 +156 +157class Hive(Dialect): +158 alias_post_tablesample = True +159 +160 time_mapping = { +161 "y": "%Y", +162 "Y": "%Y", +163 "YYYY": "%Y", +164 "yyyy": "%Y", +165 "YY": "%y", +166 "yy": "%y", +167 "MMMM": "%B", +168 "MMM": "%b", +169 "MM": "%m", +170 "M": "%-m", +171 "dd": "%d", +172 "d": "%-d", +173 "HH": "%H", +174 "H": "%-H", +175 "hh": "%I", +176 "h": "%-I", +177 "mm": "%M", +178 "m": "%-M", +179 "ss": "%S", +180 "s": "%-S", +181 "SSSSSS": "%f", +182 "a": "%p", +183 "DD": "%j", +184 "D": "%-j", +185 "E": "%a", +186 "EE": "%a", +187 "EEE": "%a", +188 "EEEE": "%A", +189 } +190 +191 date_format = "'yyyy-MM-dd'" +192 dateint_format = "'yyyyMMdd'" +193 time_format = "'yyyy-MM-dd HH:mm:ss'" +194 +195 class Tokenizer(tokens.Tokenizer): +196 QUOTES = ["'", '"'] +197 IDENTIFIERS = ["`"] +198 STRING_ESCAPES = ["\\"] +199 ENCODE = "utf-8" +200 IDENTIFIER_CAN_START_WITH_DIGIT = True +201 +202 KEYWORDS = { +203 **tokens.Tokenizer.KEYWORDS, +204 "ADD ARCHIVE": TokenType.COMMAND, +205 "ADD ARCHIVES": TokenType.COMMAND, +206 "ADD FILE": TokenType.COMMAND, +207 "ADD FILES": TokenType.COMMAND, +208 "ADD JAR": TokenType.COMMAND, +209 "ADD JARS": TokenType.COMMAND, +210 "MSCK REPAIR": TokenType.COMMAND, +211 "WITH SERDEPROPERTIES": TokenType.SERDE_PROPERTIES, +212 } 213 -214 FUNCTIONS = { -215 **parser.Parser.FUNCTIONS, # type: ignore -216 "APPROX_COUNT_DISTINCT": exp.ApproxDistinct.from_arg_list, -217 "COLLECT_LIST": exp.ArrayAgg.from_arg_list, -218 "DATE_ADD": lambda args: exp.TsOrDsAdd( -219 this=seq_get(args, 0), -220 expression=seq_get(args, 1), -221 unit=exp.Literal.string("DAY"), -222 ), -223 "DATEDIFF": lambda args: exp.DateDiff( -224 this=exp.TsOrDsToDate(this=seq_get(args, 0)), -225 expression=exp.TsOrDsToDate(this=seq_get(args, 1)), -226 ), -227 "DATE_SUB": lambda args: exp.TsOrDsAdd( -228 this=seq_get(args, 0), -229 expression=exp.Mul( -230 this=seq_get(args, 1), -231 expression=exp.Literal.number(-1), -232 ), -233 unit=exp.Literal.string("DAY"), -234 ), -235 "DATE_FORMAT": lambda args: format_time_lambda(exp.TimeToStr, "hive")( -236 [ -237 exp.TimeStrToTime(this=seq_get(args, 0)), -238 seq_get(args, 1), -239 ] -240 ), -241 "DAY": lambda args: exp.Day(this=exp.TsOrDsToDate(this=seq_get(args, 0))), -242 "FROM_UNIXTIME": format_time_lambda(exp.UnixToStr, "hive", True), -243 "GET_JSON_OBJECT": exp.JSONExtractScalar.from_arg_list, -244 "LOCATE": locate_to_strposition, -245 "MAP": parse_var_map, -246 "MONTH": lambda args: exp.Month(this=exp.TsOrDsToDate.from_arg_list(args)), -247 "PERCENTILE": exp.Quantile.from_arg_list, -248 "PERCENTILE_APPROX": exp.ApproxQuantile.from_arg_list, -249 "COLLECT_SET": exp.SetAgg.from_arg_list, -250 "SIZE": exp.ArraySize.from_arg_list, -251 "SPLIT": exp.RegexpSplit.from_arg_list, -252 "TO_DATE": format_time_lambda(exp.TsOrDsToDate, "hive"), -253 "TO_JSON": exp.JSONFormat.from_arg_list, -254 "UNIX_TIMESTAMP": format_time_lambda(exp.StrToUnix, "hive", True), -255 "YEAR": lambda args: exp.Year(this=exp.TsOrDsToDate.from_arg_list(args)), -256 } -257 -258 PROPERTY_PARSERS = { -259 **parser.Parser.PROPERTY_PARSERS, # type: ignore -260 "WITH SERDEPROPERTIES": lambda self: exp.SerdeProperties( -261 expressions=self._parse_wrapped_csv(self._parse_property) -262 ), -263 } -264 -265 class Generator(generator.Generator): -266 LIMIT_FETCH = "LIMIT" -267 TABLESAMPLE_WITH_METHOD = False -268 TABLESAMPLE_SIZE_IS_PERCENT = True -269 JOIN_HINTS = False -270 TABLE_HINTS = False -271 -272 TYPE_MAPPING = { -273 **generator.Generator.TYPE_MAPPING, # type: ignore -274 exp.DataType.Type.TEXT: "STRING", -275 exp.DataType.Type.DATETIME: "TIMESTAMP", -276 exp.DataType.Type.VARBINARY: "BINARY", -277 exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP", -278 exp.DataType.Type.BIT: "BOOLEAN", -279 } -280 -281 TRANSFORMS = { -282 **generator.Generator.TRANSFORMS, # type: ignore -283 **transforms.UNALIAS_GROUP, # type: ignore -284 **transforms.ELIMINATE_QUALIFY, # type: ignore -285 exp.Select: transforms.preprocess( -286 [transforms.eliminate_qualify, transforms.unnest_to_explode] -287 ), -288 exp.Property: _property_sql, -289 exp.ApproxDistinct: approx_count_distinct_sql, -290 exp.ArrayConcat: rename_func("CONCAT"), -291 exp.ArraySize: rename_func("SIZE"), -292 exp.ArraySort: _array_sort, -293 exp.With: no_recursive_cte_sql, -294 exp.DateAdd: _add_date_sql, -295 exp.DateDiff: _date_diff_sql, -296 exp.DateStrToDate: rename_func("TO_DATE"), -297 exp.DateSub: _add_date_sql, -298 exp.DateToDi: lambda self, e: f"CAST(DATE_FORMAT({self.sql(e, 'this')}, {Hive.dateint_format}) AS INT)", -299 exp.DiToDate: lambda self, e: f"TO_DATE(CAST({self.sql(e, 'this')} AS STRING), {Hive.dateint_format})", -300 exp.FileFormatProperty: lambda self, e: f"STORED AS {self.sql(e, 'this') if isinstance(e.this, exp.InputOutputFormat) else e.name.upper()}", -301 exp.If: if_sql, -302 exp.Index: _index_sql, -303 exp.ILike: no_ilike_sql, -304 exp.JSONExtract: rename_func("GET_JSON_OBJECT"), -305 exp.JSONExtractScalar: rename_func("GET_JSON_OBJECT"), -306 exp.JSONFormat: rename_func("TO_JSON"), -307 exp.Map: var_map_sql, -308 exp.Max: max_or_greatest, -309 exp.Min: min_or_least, -310 exp.VarMap: var_map_sql, -311 exp.Create: create_with_partitions_sql, -312 exp.Quantile: rename_func("PERCENTILE"), -313 exp.ApproxQuantile: rename_func("PERCENTILE_APPROX"), -314 exp.RegexpLike: lambda self, e: self.binary(e, "RLIKE"), -315 exp.RegexpSplit: rename_func("SPLIT"), -316 exp.SafeDivide: no_safe_divide_sql, -317 exp.SchemaCommentProperty: lambda self, e: self.naked_property(e), -318 exp.SetAgg: rename_func("COLLECT_SET"), -319 exp.Split: lambda self, e: f"SPLIT({self.sql(e, 'this')}, CONCAT('\\\\Q', {self.sql(e, 'expression')}))", -320 exp.StrPosition: strposition_to_locate_sql, -321 exp.StrToDate: _str_to_date, -322 exp.StrToTime: _str_to_time, -323 exp.StrToUnix: _str_to_unix, -324 exp.StructExtract: struct_extract_sql, -325 exp.TableFormatProperty: lambda self, e: f"USING {self.sql(e, 'this')}", -326 exp.TimeStrToDate: rename_func("TO_DATE"), -327 exp.TimeStrToTime: timestrtotime_sql, -328 exp.TimeStrToUnix: rename_func("UNIX_TIMESTAMP"), -329 exp.TimeToStr: _time_to_str, -330 exp.TimeToUnix: rename_func("UNIX_TIMESTAMP"), -331 exp.TsOrDiToDi: lambda self, e: f"CAST(SUBSTR(REPLACE(CAST({self.sql(e, 'this')} AS STRING), '-', ''), 1, 8) AS INT)", -332 exp.TsOrDsAdd: lambda self, e: f"DATE_ADD({self.sql(e, 'this')}, {self.sql(e, 'expression')})", -333 exp.TsOrDsToDate: _to_date_sql, -334 exp.TryCast: no_trycast_sql, -335 exp.UnixToStr: lambda self, e: self.func( -336 "FROM_UNIXTIME", e.this, _time_format(self, e) -337 ), -338 exp.UnixToTime: rename_func("FROM_UNIXTIME"), -339 exp.UnixToTimeStr: rename_func("FROM_UNIXTIME"), -340 exp.PartitionedByProperty: lambda self, e: f"PARTITIONED BY {self.sql(e, 'this')}", -341 exp.RowFormatSerdeProperty: lambda self, e: f"ROW FORMAT SERDE {self.sql(e, 'this')}", -342 exp.SerdeProperties: lambda self, e: self.properties(e, prefix="WITH SERDEPROPERTIES"), -343 exp.NumberToStr: rename_func("FORMAT_NUMBER"), -344 exp.LastDateOfMonth: rename_func("LAST_DAY"), -345 exp.National: lambda self, e: self.sql(e, "this"), -346 } -347 -348 PROPERTIES_LOCATION = { -349 **generator.Generator.PROPERTIES_LOCATION, # type: ignore -350 exp.FileFormatProperty: exp.Properties.Location.POST_SCHEMA, -351 exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA, -352 exp.TableFormatProperty: exp.Properties.Location.POST_SCHEMA, -353 exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, -354 } -355 -356 def arrayagg_sql(self, expression: exp.ArrayAgg) -> str: -357 return self.func( -358 "COLLECT_LIST", -359 expression.this.this if isinstance(expression.this, exp.Order) else expression.this, -360 ) -361 -362 def with_properties(self, properties: exp.Properties) -> str: -363 return self.properties( -364 properties, -365 prefix=self.seg("TBLPROPERTIES"), -366 ) -367 -368 def datatype_sql(self, expression: exp.DataType) -> str: -369 if ( -370 expression.this in (exp.DataType.Type.VARCHAR, exp.DataType.Type.NVARCHAR) -371 and not expression.expressions -372 ): -373 expression = exp.DataType.build("text") -374 elif expression.this in exp.DataType.TEMPORAL_TYPES: -375 expression = exp.DataType.build(expression.this) -376 -377 return super().datatype_sql(expression) +214 NUMERIC_LITERALS = { +215 "L": "BIGINT", +216 "S": "SMALLINT", +217 "Y": "TINYINT", +218 "D": "DOUBLE", +219 "F": "FLOAT", +220 "BD": "DECIMAL", +221 } +222 +223 class Parser(parser.Parser): +224 LOG_DEFAULTS_TO_LN = True +225 STRICT_CAST = False +226 +227 FUNCTIONS = { +228 **parser.Parser.FUNCTIONS, # type: ignore +229 "APPROX_COUNT_DISTINCT": exp.ApproxDistinct.from_arg_list, +230 "COLLECT_LIST": exp.ArrayAgg.from_arg_list, +231 "DATE_ADD": lambda args: exp.TsOrDsAdd( +232 this=seq_get(args, 0), +233 expression=seq_get(args, 1), +234 unit=exp.Literal.string("DAY"), +235 ), +236 "DATEDIFF": lambda args: exp.DateDiff( +237 this=exp.TsOrDsToDate(this=seq_get(args, 0)), +238 expression=exp.TsOrDsToDate(this=seq_get(args, 1)), +239 ), +240 "DATE_SUB": lambda args: exp.TsOrDsAdd( +241 this=seq_get(args, 0), +242 expression=exp.Mul( +243 this=seq_get(args, 1), +244 expression=exp.Literal.number(-1), +245 ), +246 unit=exp.Literal.string("DAY"), +247 ), +248 "DATE_FORMAT": lambda args: format_time_lambda(exp.TimeToStr, "hive")( +249 [ +250 exp.TimeStrToTime(this=seq_get(args, 0)), +251 seq_get(args, 1), +252 ] +253 ), +254 "DAY": lambda args: exp.Day(this=exp.TsOrDsToDate(this=seq_get(args, 0))), +255 "FROM_UNIXTIME": format_time_lambda(exp.UnixToStr, "hive", True), +256 "GET_JSON_OBJECT": exp.JSONExtractScalar.from_arg_list, +257 "LOCATE": locate_to_strposition, +258 "MAP": parse_var_map, +259 "MONTH": lambda args: exp.Month(this=exp.TsOrDsToDate.from_arg_list(args)), +260 "PERCENTILE": exp.Quantile.from_arg_list, +261 "PERCENTILE_APPROX": exp.ApproxQuantile.from_arg_list, +262 "COLLECT_SET": exp.SetAgg.from_arg_list, +263 "SIZE": exp.ArraySize.from_arg_list, +264 "SPLIT": exp.RegexpSplit.from_arg_list, +265 "TO_DATE": format_time_lambda(exp.TsOrDsToDate, "hive"), +266 "TO_JSON": exp.JSONFormat.from_arg_list, +267 "UNIX_TIMESTAMP": format_time_lambda(exp.StrToUnix, "hive", True), +268 "YEAR": lambda args: exp.Year(this=exp.TsOrDsToDate.from_arg_list(args)), +269 } +270 +271 PROPERTY_PARSERS = { +272 **parser.Parser.PROPERTY_PARSERS, # type: ignore +273 "WITH SERDEPROPERTIES": lambda self: exp.SerdeProperties( +274 expressions=self._parse_wrapped_csv(self._parse_property) +275 ), +276 } +277 +278 class Generator(generator.Generator): +279 LIMIT_FETCH = "LIMIT" +280 TABLESAMPLE_WITH_METHOD = False +281 TABLESAMPLE_SIZE_IS_PERCENT = True +282 JOIN_HINTS = False +283 TABLE_HINTS = False +284 +285 TYPE_MAPPING = { +286 **generator.Generator.TYPE_MAPPING, # type: ignore +287 exp.DataType.Type.TEXT: "STRING", +288 exp.DataType.Type.DATETIME: "TIMESTAMP", +289 exp.DataType.Type.VARBINARY: "BINARY", +290 exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP", +291 exp.DataType.Type.BIT: "BOOLEAN", +292 } +293 +294 TRANSFORMS = { +295 **generator.Generator.TRANSFORMS, # type: ignore +296 exp.Group: transforms.preprocess([transforms.unalias_group]), +297 exp.Select: transforms.preprocess( +298 [ +299 transforms.eliminate_qualify, +300 transforms.eliminate_distinct_on, +301 transforms.unnest_to_explode, +302 ] +303 ), +304 exp.Property: _property_sql, +305 exp.ApproxDistinct: approx_count_distinct_sql, +306 exp.ArrayConcat: rename_func("CONCAT"), +307 exp.ArraySize: rename_func("SIZE"), +308 exp.ArraySort: _array_sort_sql, +309 exp.With: no_recursive_cte_sql, +310 exp.DateAdd: _add_date_sql, +311 exp.DateDiff: _date_diff_sql, +312 exp.DateStrToDate: rename_func("TO_DATE"), +313 exp.DateSub: _add_date_sql, +314 exp.DateToDi: lambda self, e: f"CAST(DATE_FORMAT({self.sql(e, 'this')}, {Hive.dateint_format}) AS INT)", +315 exp.DiToDate: lambda self, e: f"TO_DATE(CAST({self.sql(e, 'this')} AS STRING), {Hive.dateint_format})", +316 exp.FileFormatProperty: lambda self, e: f"STORED AS {self.sql(e, 'this') if isinstance(e.this, exp.InputOutputFormat) else e.name.upper()}", +317 exp.If: if_sql, +318 exp.Index: _index_sql, +319 exp.ILike: no_ilike_sql, +320 exp.JSONExtract: rename_func("GET_JSON_OBJECT"), +321 exp.JSONExtractScalar: rename_func("GET_JSON_OBJECT"), +322 exp.JSONFormat: _json_format_sql, +323 exp.Map: var_map_sql, +324 exp.Max: max_or_greatest, +325 exp.Min: min_or_least, +326 exp.VarMap: var_map_sql, +327 exp.Create: create_with_partitions_sql, +328 exp.Quantile: rename_func("PERCENTILE"), +329 exp.ApproxQuantile: rename_func("PERCENTILE_APPROX"), +330 exp.RegexpLike: lambda self, e: self.binary(e, "RLIKE"), +331 exp.RegexpSplit: rename_func("SPLIT"), +332 exp.SafeDivide: no_safe_divide_sql, +333 exp.SchemaCommentProperty: lambda self, e: self.naked_property(e), +334 exp.SetAgg: rename_func("COLLECT_SET"), +335 exp.Split: lambda self, e: f"SPLIT({self.sql(e, 'this')}, CONCAT('\\\\Q', {self.sql(e, 'expression')}))", +336 exp.StrPosition: strposition_to_locate_sql, +337 exp.StrToDate: _str_to_date_sql, +338 exp.StrToTime: _str_to_time_sql, +339 exp.StrToUnix: _str_to_unix_sql, +340 exp.StructExtract: struct_extract_sql, +341 exp.TableFormatProperty: lambda self, e: f"USING {self.sql(e, 'this')}", +342 exp.TimeStrToDate: rename_func("TO_DATE"), +343 exp.TimeStrToTime: timestrtotime_sql, +344 exp.TimeStrToUnix: rename_func("UNIX_TIMESTAMP"), +345 exp.TimeToStr: _time_to_str, +346 exp.TimeToUnix: rename_func("UNIX_TIMESTAMP"), +347 exp.TsOrDiToDi: lambda self, e: f"CAST(SUBSTR(REPLACE(CAST({self.sql(e, 'this')} AS STRING), '-', ''), 1, 8) AS INT)", +348 exp.TsOrDsAdd: lambda self, e: f"DATE_ADD({self.sql(e, 'this')}, {self.sql(e, 'expression')})", +349 exp.TsOrDsToDate: _to_date_sql, +350 exp.TryCast: no_trycast_sql, +351 exp.UnixToStr: lambda self, e: self.func( +352 "FROM_UNIXTIME", e.this, _time_format(self, e) +353 ), +354 exp.UnixToTime: rename_func("FROM_UNIXTIME"), +355 exp.UnixToTimeStr: rename_func("FROM_UNIXTIME"), +356 exp.PartitionedByProperty: lambda self, e: f"PARTITIONED BY {self.sql(e, 'this')}", +357 exp.RowFormatSerdeProperty: lambda self, e: f"ROW FORMAT SERDE {self.sql(e, 'this')}", +358 exp.SerdeProperties: lambda self, e: self.properties(e, prefix="WITH SERDEPROPERTIES"), +359 exp.NumberToStr: rename_func("FORMAT_NUMBER"), +360 exp.LastDateOfMonth: rename_func("LAST_DAY"), +361 exp.National: lambda self, e: self.sql(e, "this"), +362 } +363 +364 PROPERTIES_LOCATION = { +365 **generator.Generator.PROPERTIES_LOCATION, # type: ignore +366 exp.FileFormatProperty: exp.Properties.Location.POST_SCHEMA, +367 exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA, +368 exp.TableFormatProperty: exp.Properties.Location.POST_SCHEMA, +369 exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, +370 } +371 +372 def arrayagg_sql(self, expression: exp.ArrayAgg) -> str: +373 return self.func( +374 "COLLECT_LIST", +375 expression.this.this if isinstance(expression.this, exp.Order) else expression.this, +376 ) +377 +378 def with_properties(self, properties: exp.Properties) -> str: +379 return self.properties( +380 properties, +381 prefix=self.seg("TBLPROPERTIES"), +382 ) +383 +384 def datatype_sql(self, expression: exp.DataType) -> str: +385 if ( +386 expression.this in (exp.DataType.Type.VARCHAR, exp.DataType.Type.NVARCHAR) +387 and not expression.expressions +388 ): +389 expression = exp.DataType.build("text") +390 elif expression.this in exp.DataType.TEMPORAL_TYPES: +391 expression = exp.DataType.build(expression.this) +392 +393 return super().datatype_sql(expression) @@ -478,240 +494,243 @@ -
145class Hive(Dialect):
-146    alias_post_tablesample = True
-147
-148    time_mapping = {
-149        "y": "%Y",
-150        "Y": "%Y",
-151        "YYYY": "%Y",
-152        "yyyy": "%Y",
-153        "YY": "%y",
-154        "yy": "%y",
-155        "MMMM": "%B",
-156        "MMM": "%b",
-157        "MM": "%m",
-158        "M": "%-m",
-159        "dd": "%d",
-160        "d": "%-d",
-161        "HH": "%H",
-162        "H": "%-H",
-163        "hh": "%I",
-164        "h": "%-I",
-165        "mm": "%M",
-166        "m": "%-M",
-167        "ss": "%S",
-168        "s": "%-S",
-169        "SSSSSS": "%f",
-170        "a": "%p",
-171        "DD": "%j",
-172        "D": "%-j",
-173        "E": "%a",
-174        "EE": "%a",
-175        "EEE": "%a",
-176        "EEEE": "%A",
-177    }
-178
-179    date_format = "'yyyy-MM-dd'"
-180    dateint_format = "'yyyyMMdd'"
-181    time_format = "'yyyy-MM-dd HH:mm:ss'"
-182
-183    class Tokenizer(tokens.Tokenizer):
-184        QUOTES = ["'", '"']
-185        IDENTIFIERS = ["`"]
-186        STRING_ESCAPES = ["\\"]
-187        ENCODE = "utf-8"
-188        IDENTIFIER_CAN_START_WITH_DIGIT = True
-189
-190        KEYWORDS = {
-191            **tokens.Tokenizer.KEYWORDS,
-192            "ADD ARCHIVE": TokenType.COMMAND,
-193            "ADD ARCHIVES": TokenType.COMMAND,
-194            "ADD FILE": TokenType.COMMAND,
-195            "ADD FILES": TokenType.COMMAND,
-196            "ADD JAR": TokenType.COMMAND,
-197            "ADD JARS": TokenType.COMMAND,
-198            "MSCK REPAIR": TokenType.COMMAND,
-199            "WITH SERDEPROPERTIES": TokenType.SERDE_PROPERTIES,
-200        }
-201
-202        NUMERIC_LITERALS = {
-203            "L": "BIGINT",
-204            "S": "SMALLINT",
-205            "Y": "TINYINT",
-206            "D": "DOUBLE",
-207            "F": "FLOAT",
-208            "BD": "DECIMAL",
-209        }
-210
-211    class Parser(parser.Parser):
-212        LOG_DEFAULTS_TO_LN = True
-213        STRICT_CAST = False
+            
158class Hive(Dialect):
+159    alias_post_tablesample = True
+160
+161    time_mapping = {
+162        "y": "%Y",
+163        "Y": "%Y",
+164        "YYYY": "%Y",
+165        "yyyy": "%Y",
+166        "YY": "%y",
+167        "yy": "%y",
+168        "MMMM": "%B",
+169        "MMM": "%b",
+170        "MM": "%m",
+171        "M": "%-m",
+172        "dd": "%d",
+173        "d": "%-d",
+174        "HH": "%H",
+175        "H": "%-H",
+176        "hh": "%I",
+177        "h": "%-I",
+178        "mm": "%M",
+179        "m": "%-M",
+180        "ss": "%S",
+181        "s": "%-S",
+182        "SSSSSS": "%f",
+183        "a": "%p",
+184        "DD": "%j",
+185        "D": "%-j",
+186        "E": "%a",
+187        "EE": "%a",
+188        "EEE": "%a",
+189        "EEEE": "%A",
+190    }
+191
+192    date_format = "'yyyy-MM-dd'"
+193    dateint_format = "'yyyyMMdd'"
+194    time_format = "'yyyy-MM-dd HH:mm:ss'"
+195
+196    class Tokenizer(tokens.Tokenizer):
+197        QUOTES = ["'", '"']
+198        IDENTIFIERS = ["`"]
+199        STRING_ESCAPES = ["\\"]
+200        ENCODE = "utf-8"
+201        IDENTIFIER_CAN_START_WITH_DIGIT = True
+202
+203        KEYWORDS = {
+204            **tokens.Tokenizer.KEYWORDS,
+205            "ADD ARCHIVE": TokenType.COMMAND,
+206            "ADD ARCHIVES": TokenType.COMMAND,
+207            "ADD FILE": TokenType.COMMAND,
+208            "ADD FILES": TokenType.COMMAND,
+209            "ADD JAR": TokenType.COMMAND,
+210            "ADD JARS": TokenType.COMMAND,
+211            "MSCK REPAIR": TokenType.COMMAND,
+212            "WITH SERDEPROPERTIES": TokenType.SERDE_PROPERTIES,
+213        }
 214
-215        FUNCTIONS = {
-216            **parser.Parser.FUNCTIONS,  # type: ignore
-217            "APPROX_COUNT_DISTINCT": exp.ApproxDistinct.from_arg_list,
-218            "COLLECT_LIST": exp.ArrayAgg.from_arg_list,
-219            "DATE_ADD": lambda args: exp.TsOrDsAdd(
-220                this=seq_get(args, 0),
-221                expression=seq_get(args, 1),
-222                unit=exp.Literal.string("DAY"),
-223            ),
-224            "DATEDIFF": lambda args: exp.DateDiff(
-225                this=exp.TsOrDsToDate(this=seq_get(args, 0)),
-226                expression=exp.TsOrDsToDate(this=seq_get(args, 1)),
-227            ),
-228            "DATE_SUB": lambda args: exp.TsOrDsAdd(
-229                this=seq_get(args, 0),
-230                expression=exp.Mul(
-231                    this=seq_get(args, 1),
-232                    expression=exp.Literal.number(-1),
-233                ),
-234                unit=exp.Literal.string("DAY"),
-235            ),
-236            "DATE_FORMAT": lambda args: format_time_lambda(exp.TimeToStr, "hive")(
-237                [
-238                    exp.TimeStrToTime(this=seq_get(args, 0)),
-239                    seq_get(args, 1),
-240                ]
-241            ),
-242            "DAY": lambda args: exp.Day(this=exp.TsOrDsToDate(this=seq_get(args, 0))),
-243            "FROM_UNIXTIME": format_time_lambda(exp.UnixToStr, "hive", True),
-244            "GET_JSON_OBJECT": exp.JSONExtractScalar.from_arg_list,
-245            "LOCATE": locate_to_strposition,
-246            "MAP": parse_var_map,
-247            "MONTH": lambda args: exp.Month(this=exp.TsOrDsToDate.from_arg_list(args)),
-248            "PERCENTILE": exp.Quantile.from_arg_list,
-249            "PERCENTILE_APPROX": exp.ApproxQuantile.from_arg_list,
-250            "COLLECT_SET": exp.SetAgg.from_arg_list,
-251            "SIZE": exp.ArraySize.from_arg_list,
-252            "SPLIT": exp.RegexpSplit.from_arg_list,
-253            "TO_DATE": format_time_lambda(exp.TsOrDsToDate, "hive"),
-254            "TO_JSON": exp.JSONFormat.from_arg_list,
-255            "UNIX_TIMESTAMP": format_time_lambda(exp.StrToUnix, "hive", True),
-256            "YEAR": lambda args: exp.Year(this=exp.TsOrDsToDate.from_arg_list(args)),
-257        }
-258
-259        PROPERTY_PARSERS = {
-260            **parser.Parser.PROPERTY_PARSERS,  # type: ignore
-261            "WITH SERDEPROPERTIES": lambda self: exp.SerdeProperties(
-262                expressions=self._parse_wrapped_csv(self._parse_property)
-263            ),
-264        }
-265
-266    class Generator(generator.Generator):
-267        LIMIT_FETCH = "LIMIT"
-268        TABLESAMPLE_WITH_METHOD = False
-269        TABLESAMPLE_SIZE_IS_PERCENT = True
-270        JOIN_HINTS = False
-271        TABLE_HINTS = False
-272
-273        TYPE_MAPPING = {
-274            **generator.Generator.TYPE_MAPPING,  # type: ignore
-275            exp.DataType.Type.TEXT: "STRING",
-276            exp.DataType.Type.DATETIME: "TIMESTAMP",
-277            exp.DataType.Type.VARBINARY: "BINARY",
-278            exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP",
-279            exp.DataType.Type.BIT: "BOOLEAN",
-280        }
-281
-282        TRANSFORMS = {
-283            **generator.Generator.TRANSFORMS,  # type: ignore
-284            **transforms.UNALIAS_GROUP,  # type: ignore
-285            **transforms.ELIMINATE_QUALIFY,  # type: ignore
-286            exp.Select: transforms.preprocess(
-287                [transforms.eliminate_qualify, transforms.unnest_to_explode]
-288            ),
-289            exp.Property: _property_sql,
-290            exp.ApproxDistinct: approx_count_distinct_sql,
-291            exp.ArrayConcat: rename_func("CONCAT"),
-292            exp.ArraySize: rename_func("SIZE"),
-293            exp.ArraySort: _array_sort,
-294            exp.With: no_recursive_cte_sql,
-295            exp.DateAdd: _add_date_sql,
-296            exp.DateDiff: _date_diff_sql,
-297            exp.DateStrToDate: rename_func("TO_DATE"),
-298            exp.DateSub: _add_date_sql,
-299            exp.DateToDi: lambda self, e: f"CAST(DATE_FORMAT({self.sql(e, 'this')}, {Hive.dateint_format}) AS INT)",
-300            exp.DiToDate: lambda self, e: f"TO_DATE(CAST({self.sql(e, 'this')} AS STRING), {Hive.dateint_format})",
-301            exp.FileFormatProperty: lambda self, e: f"STORED AS {self.sql(e, 'this') if isinstance(e.this, exp.InputOutputFormat) else e.name.upper()}",
-302            exp.If: if_sql,
-303            exp.Index: _index_sql,
-304            exp.ILike: no_ilike_sql,
-305            exp.JSONExtract: rename_func("GET_JSON_OBJECT"),
-306            exp.JSONExtractScalar: rename_func("GET_JSON_OBJECT"),
-307            exp.JSONFormat: rename_func("TO_JSON"),
-308            exp.Map: var_map_sql,
-309            exp.Max: max_or_greatest,
-310            exp.Min: min_or_least,
-311            exp.VarMap: var_map_sql,
-312            exp.Create: create_with_partitions_sql,
-313            exp.Quantile: rename_func("PERCENTILE"),
-314            exp.ApproxQuantile: rename_func("PERCENTILE_APPROX"),
-315            exp.RegexpLike: lambda self, e: self.binary(e, "RLIKE"),
-316            exp.RegexpSplit: rename_func("SPLIT"),
-317            exp.SafeDivide: no_safe_divide_sql,
-318            exp.SchemaCommentProperty: lambda self, e: self.naked_property(e),
-319            exp.SetAgg: rename_func("COLLECT_SET"),
-320            exp.Split: lambda self, e: f"SPLIT({self.sql(e, 'this')}, CONCAT('\\\\Q', {self.sql(e, 'expression')}))",
-321            exp.StrPosition: strposition_to_locate_sql,
-322            exp.StrToDate: _str_to_date,
-323            exp.StrToTime: _str_to_time,
-324            exp.StrToUnix: _str_to_unix,
-325            exp.StructExtract: struct_extract_sql,
-326            exp.TableFormatProperty: lambda self, e: f"USING {self.sql(e, 'this')}",
-327            exp.TimeStrToDate: rename_func("TO_DATE"),
-328            exp.TimeStrToTime: timestrtotime_sql,
-329            exp.TimeStrToUnix: rename_func("UNIX_TIMESTAMP"),
-330            exp.TimeToStr: _time_to_str,
-331            exp.TimeToUnix: rename_func("UNIX_TIMESTAMP"),
-332            exp.TsOrDiToDi: lambda self, e: f"CAST(SUBSTR(REPLACE(CAST({self.sql(e, 'this')} AS STRING), '-', ''), 1, 8) AS INT)",
-333            exp.TsOrDsAdd: lambda self, e: f"DATE_ADD({self.sql(e, 'this')}, {self.sql(e, 'expression')})",
-334            exp.TsOrDsToDate: _to_date_sql,
-335            exp.TryCast: no_trycast_sql,
-336            exp.UnixToStr: lambda self, e: self.func(
-337                "FROM_UNIXTIME", e.this, _time_format(self, e)
-338            ),
-339            exp.UnixToTime: rename_func("FROM_UNIXTIME"),
-340            exp.UnixToTimeStr: rename_func("FROM_UNIXTIME"),
-341            exp.PartitionedByProperty: lambda self, e: f"PARTITIONED BY {self.sql(e, 'this')}",
-342            exp.RowFormatSerdeProperty: lambda self, e: f"ROW FORMAT SERDE {self.sql(e, 'this')}",
-343            exp.SerdeProperties: lambda self, e: self.properties(e, prefix="WITH SERDEPROPERTIES"),
-344            exp.NumberToStr: rename_func("FORMAT_NUMBER"),
-345            exp.LastDateOfMonth: rename_func("LAST_DAY"),
-346            exp.National: lambda self, e: self.sql(e, "this"),
-347        }
-348
-349        PROPERTIES_LOCATION = {
-350            **generator.Generator.PROPERTIES_LOCATION,  # type: ignore
-351            exp.FileFormatProperty: exp.Properties.Location.POST_SCHEMA,
-352            exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA,
-353            exp.TableFormatProperty: exp.Properties.Location.POST_SCHEMA,
-354            exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED,
-355        }
-356
-357        def arrayagg_sql(self, expression: exp.ArrayAgg) -> str:
-358            return self.func(
-359                "COLLECT_LIST",
-360                expression.this.this if isinstance(expression.this, exp.Order) else expression.this,
-361            )
-362
-363        def with_properties(self, properties: exp.Properties) -> str:
-364            return self.properties(
-365                properties,
-366                prefix=self.seg("TBLPROPERTIES"),
-367            )
-368
-369        def datatype_sql(self, expression: exp.DataType) -> str:
-370            if (
-371                expression.this in (exp.DataType.Type.VARCHAR, exp.DataType.Type.NVARCHAR)
-372                and not expression.expressions
-373            ):
-374                expression = exp.DataType.build("text")
-375            elif expression.this in exp.DataType.TEMPORAL_TYPES:
-376                expression = exp.DataType.build(expression.this)
-377
-378            return super().datatype_sql(expression)
+215        NUMERIC_LITERALS = {
+216            "L": "BIGINT",
+217            "S": "SMALLINT",
+218            "Y": "TINYINT",
+219            "D": "DOUBLE",
+220            "F": "FLOAT",
+221            "BD": "DECIMAL",
+222        }
+223
+224    class Parser(parser.Parser):
+225        LOG_DEFAULTS_TO_LN = True
+226        STRICT_CAST = False
+227
+228        FUNCTIONS = {
+229            **parser.Parser.FUNCTIONS,  # type: ignore
+230            "APPROX_COUNT_DISTINCT": exp.ApproxDistinct.from_arg_list,
+231            "COLLECT_LIST": exp.ArrayAgg.from_arg_list,
+232            "DATE_ADD": lambda args: exp.TsOrDsAdd(
+233                this=seq_get(args, 0),
+234                expression=seq_get(args, 1),
+235                unit=exp.Literal.string("DAY"),
+236            ),
+237            "DATEDIFF": lambda args: exp.DateDiff(
+238                this=exp.TsOrDsToDate(this=seq_get(args, 0)),
+239                expression=exp.TsOrDsToDate(this=seq_get(args, 1)),
+240            ),
+241            "DATE_SUB": lambda args: exp.TsOrDsAdd(
+242                this=seq_get(args, 0),
+243                expression=exp.Mul(
+244                    this=seq_get(args, 1),
+245                    expression=exp.Literal.number(-1),
+246                ),
+247                unit=exp.Literal.string("DAY"),
+248            ),
+249            "DATE_FORMAT": lambda args: format_time_lambda(exp.TimeToStr, "hive")(
+250                [
+251                    exp.TimeStrToTime(this=seq_get(args, 0)),
+252                    seq_get(args, 1),
+253                ]
+254            ),
+255            "DAY": lambda args: exp.Day(this=exp.TsOrDsToDate(this=seq_get(args, 0))),
+256            "FROM_UNIXTIME": format_time_lambda(exp.UnixToStr, "hive", True),
+257            "GET_JSON_OBJECT": exp.JSONExtractScalar.from_arg_list,
+258            "LOCATE": locate_to_strposition,
+259            "MAP": parse_var_map,
+260            "MONTH": lambda args: exp.Month(this=exp.TsOrDsToDate.from_arg_list(args)),
+261            "PERCENTILE": exp.Quantile.from_arg_list,
+262            "PERCENTILE_APPROX": exp.ApproxQuantile.from_arg_list,
+263            "COLLECT_SET": exp.SetAgg.from_arg_list,
+264            "SIZE": exp.ArraySize.from_arg_list,
+265            "SPLIT": exp.RegexpSplit.from_arg_list,
+266            "TO_DATE": format_time_lambda(exp.TsOrDsToDate, "hive"),
+267            "TO_JSON": exp.JSONFormat.from_arg_list,
+268            "UNIX_TIMESTAMP": format_time_lambda(exp.StrToUnix, "hive", True),
+269            "YEAR": lambda args: exp.Year(this=exp.TsOrDsToDate.from_arg_list(args)),
+270        }
+271
+272        PROPERTY_PARSERS = {
+273            **parser.Parser.PROPERTY_PARSERS,  # type: ignore
+274            "WITH SERDEPROPERTIES": lambda self: exp.SerdeProperties(
+275                expressions=self._parse_wrapped_csv(self._parse_property)
+276            ),
+277        }
+278
+279    class Generator(generator.Generator):
+280        LIMIT_FETCH = "LIMIT"
+281        TABLESAMPLE_WITH_METHOD = False
+282        TABLESAMPLE_SIZE_IS_PERCENT = True
+283        JOIN_HINTS = False
+284        TABLE_HINTS = False
+285
+286        TYPE_MAPPING = {
+287            **generator.Generator.TYPE_MAPPING,  # type: ignore
+288            exp.DataType.Type.TEXT: "STRING",
+289            exp.DataType.Type.DATETIME: "TIMESTAMP",
+290            exp.DataType.Type.VARBINARY: "BINARY",
+291            exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP",
+292            exp.DataType.Type.BIT: "BOOLEAN",
+293        }
+294
+295        TRANSFORMS = {
+296            **generator.Generator.TRANSFORMS,  # type: ignore
+297            exp.Group: transforms.preprocess([transforms.unalias_group]),
+298            exp.Select: transforms.preprocess(
+299                [
+300                    transforms.eliminate_qualify,
+301                    transforms.eliminate_distinct_on,
+302                    transforms.unnest_to_explode,
+303                ]
+304            ),
+305            exp.Property: _property_sql,
+306            exp.ApproxDistinct: approx_count_distinct_sql,
+307            exp.ArrayConcat: rename_func("CONCAT"),
+308            exp.ArraySize: rename_func("SIZE"),
+309            exp.ArraySort: _array_sort_sql,
+310            exp.With: no_recursive_cte_sql,
+311            exp.DateAdd: _add_date_sql,
+312            exp.DateDiff: _date_diff_sql,
+313            exp.DateStrToDate: rename_func("TO_DATE"),
+314            exp.DateSub: _add_date_sql,
+315            exp.DateToDi: lambda self, e: f"CAST(DATE_FORMAT({self.sql(e, 'this')}, {Hive.dateint_format}) AS INT)",
+316            exp.DiToDate: lambda self, e: f"TO_DATE(CAST({self.sql(e, 'this')} AS STRING), {Hive.dateint_format})",
+317            exp.FileFormatProperty: lambda self, e: f"STORED AS {self.sql(e, 'this') if isinstance(e.this, exp.InputOutputFormat) else e.name.upper()}",
+318            exp.If: if_sql,
+319            exp.Index: _index_sql,
+320            exp.ILike: no_ilike_sql,
+321            exp.JSONExtract: rename_func("GET_JSON_OBJECT"),
+322            exp.JSONExtractScalar: rename_func("GET_JSON_OBJECT"),
+323            exp.JSONFormat: _json_format_sql,
+324            exp.Map: var_map_sql,
+325            exp.Max: max_or_greatest,
+326            exp.Min: min_or_least,
+327            exp.VarMap: var_map_sql,
+328            exp.Create: create_with_partitions_sql,
+329            exp.Quantile: rename_func("PERCENTILE"),
+330            exp.ApproxQuantile: rename_func("PERCENTILE_APPROX"),
+331            exp.RegexpLike: lambda self, e: self.binary(e, "RLIKE"),
+332            exp.RegexpSplit: rename_func("SPLIT"),
+333            exp.SafeDivide: no_safe_divide_sql,
+334            exp.SchemaCommentProperty: lambda self, e: self.naked_property(e),
+335            exp.SetAgg: rename_func("COLLECT_SET"),
+336            exp.Split: lambda self, e: f"SPLIT({self.sql(e, 'this')}, CONCAT('\\\\Q', {self.sql(e, 'expression')}))",
+337            exp.StrPosition: strposition_to_locate_sql,
+338            exp.StrToDate: _str_to_date_sql,
+339            exp.StrToTime: _str_to_time_sql,
+340            exp.StrToUnix: _str_to_unix_sql,
+341            exp.StructExtract: struct_extract_sql,
+342            exp.TableFormatProperty: lambda self, e: f"USING {self.sql(e, 'this')}",
+343            exp.TimeStrToDate: rename_func("TO_DATE"),
+344            exp.TimeStrToTime: timestrtotime_sql,
+345            exp.TimeStrToUnix: rename_func("UNIX_TIMESTAMP"),
+346            exp.TimeToStr: _time_to_str,
+347            exp.TimeToUnix: rename_func("UNIX_TIMESTAMP"),
+348            exp.TsOrDiToDi: lambda self, e: f"CAST(SUBSTR(REPLACE(CAST({self.sql(e, 'this')} AS STRING), '-', ''), 1, 8) AS INT)",
+349            exp.TsOrDsAdd: lambda self, e: f"DATE_ADD({self.sql(e, 'this')}, {self.sql(e, 'expression')})",
+350            exp.TsOrDsToDate: _to_date_sql,
+351            exp.TryCast: no_trycast_sql,
+352            exp.UnixToStr: lambda self, e: self.func(
+353                "FROM_UNIXTIME", e.this, _time_format(self, e)
+354            ),
+355            exp.UnixToTime: rename_func("FROM_UNIXTIME"),
+356            exp.UnixToTimeStr: rename_func("FROM_UNIXTIME"),
+357            exp.PartitionedByProperty: lambda self, e: f"PARTITIONED BY {self.sql(e, 'this')}",
+358            exp.RowFormatSerdeProperty: lambda self, e: f"ROW FORMAT SERDE {self.sql(e, 'this')}",
+359            exp.SerdeProperties: lambda self, e: self.properties(e, prefix="WITH SERDEPROPERTIES"),
+360            exp.NumberToStr: rename_func("FORMAT_NUMBER"),
+361            exp.LastDateOfMonth: rename_func("LAST_DAY"),
+362            exp.National: lambda self, e: self.sql(e, "this"),
+363        }
+364
+365        PROPERTIES_LOCATION = {
+366            **generator.Generator.PROPERTIES_LOCATION,  # type: ignore
+367            exp.FileFormatProperty: exp.Properties.Location.POST_SCHEMA,
+368            exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA,
+369            exp.TableFormatProperty: exp.Properties.Location.POST_SCHEMA,
+370            exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED,
+371        }
+372
+373        def arrayagg_sql(self, expression: exp.ArrayAgg) -> str:
+374            return self.func(
+375                "COLLECT_LIST",
+376                expression.this.this if isinstance(expression.this, exp.Order) else expression.this,
+377            )
+378
+379        def with_properties(self, properties: exp.Properties) -> str:
+380            return self.properties(
+381                properties,
+382                prefix=self.seg("TBLPROPERTIES"),
+383            )
+384
+385        def datatype_sql(self, expression: exp.DataType) -> str:
+386            if (
+387                expression.this in (exp.DataType.Type.VARCHAR, exp.DataType.Type.NVARCHAR)
+388                and not expression.expressions
+389            ):
+390                expression = exp.DataType.build("text")
+391            elif expression.this in exp.DataType.TEMPORAL_TYPES:
+392                expression = exp.DataType.build(expression.this)
+393
+394            return super().datatype_sql(expression)
 
@@ -746,33 +765,33 @@
-
183    class Tokenizer(tokens.Tokenizer):
-184        QUOTES = ["'", '"']
-185        IDENTIFIERS = ["`"]
-186        STRING_ESCAPES = ["\\"]
-187        ENCODE = "utf-8"
-188        IDENTIFIER_CAN_START_WITH_DIGIT = True
-189
-190        KEYWORDS = {
-191            **tokens.Tokenizer.KEYWORDS,
-192            "ADD ARCHIVE": TokenType.COMMAND,
-193            "ADD ARCHIVES": TokenType.COMMAND,
-194            "ADD FILE": TokenType.COMMAND,
-195            "ADD FILES": TokenType.COMMAND,
-196            "ADD JAR": TokenType.COMMAND,
-197            "ADD JARS": TokenType.COMMAND,
-198            "MSCK REPAIR": TokenType.COMMAND,
-199            "WITH SERDEPROPERTIES": TokenType.SERDE_PROPERTIES,
-200        }
-201
-202        NUMERIC_LITERALS = {
-203            "L": "BIGINT",
-204            "S": "SMALLINT",
-205            "Y": "TINYINT",
-206            "D": "DOUBLE",
-207            "F": "FLOAT",
-208            "BD": "DECIMAL",
-209        }
+            
196    class Tokenizer(tokens.Tokenizer):
+197        QUOTES = ["'", '"']
+198        IDENTIFIERS = ["`"]
+199        STRING_ESCAPES = ["\\"]
+200        ENCODE = "utf-8"
+201        IDENTIFIER_CAN_START_WITH_DIGIT = True
+202
+203        KEYWORDS = {
+204            **tokens.Tokenizer.KEYWORDS,
+205            "ADD ARCHIVE": TokenType.COMMAND,
+206            "ADD ARCHIVES": TokenType.COMMAND,
+207            "ADD FILE": TokenType.COMMAND,
+208            "ADD FILES": TokenType.COMMAND,
+209            "ADD JAR": TokenType.COMMAND,
+210            "ADD JARS": TokenType.COMMAND,
+211            "MSCK REPAIR": TokenType.COMMAND,
+212            "WITH SERDEPROPERTIES": TokenType.SERDE_PROPERTIES,
+213        }
+214
+215        NUMERIC_LITERALS = {
+216            "L": "BIGINT",
+217            "S": "SMALLINT",
+218            "Y": "TINYINT",
+219            "D": "DOUBLE",
+220            "F": "FLOAT",
+221            "BD": "DECIMAL",
+222        }
 
@@ -800,60 +819,60 @@
-
211    class Parser(parser.Parser):
-212        LOG_DEFAULTS_TO_LN = True
-213        STRICT_CAST = False
-214
-215        FUNCTIONS = {
-216            **parser.Parser.FUNCTIONS,  # type: ignore
-217            "APPROX_COUNT_DISTINCT": exp.ApproxDistinct.from_arg_list,
-218            "COLLECT_LIST": exp.ArrayAgg.from_arg_list,
-219            "DATE_ADD": lambda args: exp.TsOrDsAdd(
-220                this=seq_get(args, 0),
-221                expression=seq_get(args, 1),
-222                unit=exp.Literal.string("DAY"),
-223            ),
-224            "DATEDIFF": lambda args: exp.DateDiff(
-225                this=exp.TsOrDsToDate(this=seq_get(args, 0)),
-226                expression=exp.TsOrDsToDate(this=seq_get(args, 1)),
-227            ),
-228            "DATE_SUB": lambda args: exp.TsOrDsAdd(
-229                this=seq_get(args, 0),
-230                expression=exp.Mul(
-231                    this=seq_get(args, 1),
-232                    expression=exp.Literal.number(-1),
-233                ),
-234                unit=exp.Literal.string("DAY"),
-235            ),
-236            "DATE_FORMAT": lambda args: format_time_lambda(exp.TimeToStr, "hive")(
-237                [
-238                    exp.TimeStrToTime(this=seq_get(args, 0)),
-239                    seq_get(args, 1),
-240                ]
-241            ),
-242            "DAY": lambda args: exp.Day(this=exp.TsOrDsToDate(this=seq_get(args, 0))),
-243            "FROM_UNIXTIME": format_time_lambda(exp.UnixToStr, "hive", True),
-244            "GET_JSON_OBJECT": exp.JSONExtractScalar.from_arg_list,
-245            "LOCATE": locate_to_strposition,
-246            "MAP": parse_var_map,
-247            "MONTH": lambda args: exp.Month(this=exp.TsOrDsToDate.from_arg_list(args)),
-248            "PERCENTILE": exp.Quantile.from_arg_list,
-249            "PERCENTILE_APPROX": exp.ApproxQuantile.from_arg_list,
-250            "COLLECT_SET": exp.SetAgg.from_arg_list,
-251            "SIZE": exp.ArraySize.from_arg_list,
-252            "SPLIT": exp.RegexpSplit.from_arg_list,
-253            "TO_DATE": format_time_lambda(exp.TsOrDsToDate, "hive"),
-254            "TO_JSON": exp.JSONFormat.from_arg_list,
-255            "UNIX_TIMESTAMP": format_time_lambda(exp.StrToUnix, "hive", True),
-256            "YEAR": lambda args: exp.Year(this=exp.TsOrDsToDate.from_arg_list(args)),
-257        }
-258
-259        PROPERTY_PARSERS = {
-260            **parser.Parser.PROPERTY_PARSERS,  # type: ignore
-261            "WITH SERDEPROPERTIES": lambda self: exp.SerdeProperties(
-262                expressions=self._parse_wrapped_csv(self._parse_property)
-263            ),
-264        }
+            
224    class Parser(parser.Parser):
+225        LOG_DEFAULTS_TO_LN = True
+226        STRICT_CAST = False
+227
+228        FUNCTIONS = {
+229            **parser.Parser.FUNCTIONS,  # type: ignore
+230            "APPROX_COUNT_DISTINCT": exp.ApproxDistinct.from_arg_list,
+231            "COLLECT_LIST": exp.ArrayAgg.from_arg_list,
+232            "DATE_ADD": lambda args: exp.TsOrDsAdd(
+233                this=seq_get(args, 0),
+234                expression=seq_get(args, 1),
+235                unit=exp.Literal.string("DAY"),
+236            ),
+237            "DATEDIFF": lambda args: exp.DateDiff(
+238                this=exp.TsOrDsToDate(this=seq_get(args, 0)),
+239                expression=exp.TsOrDsToDate(this=seq_get(args, 1)),
+240            ),
+241            "DATE_SUB": lambda args: exp.TsOrDsAdd(
+242                this=seq_get(args, 0),
+243                expression=exp.Mul(
+244                    this=seq_get(args, 1),
+245                    expression=exp.Literal.number(-1),
+246                ),
+247                unit=exp.Literal.string("DAY"),
+248            ),
+249            "DATE_FORMAT": lambda args: format_time_lambda(exp.TimeToStr, "hive")(
+250                [
+251                    exp.TimeStrToTime(this=seq_get(args, 0)),
+252                    seq_get(args, 1),
+253                ]
+254            ),
+255            "DAY": lambda args: exp.Day(this=exp.TsOrDsToDate(this=seq_get(args, 0))),
+256            "FROM_UNIXTIME": format_time_lambda(exp.UnixToStr, "hive", True),
+257            "GET_JSON_OBJECT": exp.JSONExtractScalar.from_arg_list,
+258            "LOCATE": locate_to_strposition,
+259            "MAP": parse_var_map,
+260            "MONTH": lambda args: exp.Month(this=exp.TsOrDsToDate.from_arg_list(args)),
+261            "PERCENTILE": exp.Quantile.from_arg_list,
+262            "PERCENTILE_APPROX": exp.ApproxQuantile.from_arg_list,
+263            "COLLECT_SET": exp.SetAgg.from_arg_list,
+264            "SIZE": exp.ArraySize.from_arg_list,
+265            "SPLIT": exp.RegexpSplit.from_arg_list,
+266            "TO_DATE": format_time_lambda(exp.TsOrDsToDate, "hive"),
+267            "TO_JSON": exp.JSONFormat.from_arg_list,
+268            "UNIX_TIMESTAMP": format_time_lambda(exp.StrToUnix, "hive", True),
+269            "YEAR": lambda args: exp.Year(this=exp.TsOrDsToDate.from_arg_list(args)),
+270        }
+271
+272        PROPERTY_PARSERS = {
+273            **parser.Parser.PROPERTY_PARSERS,  # type: ignore
+274            "WITH SERDEPROPERTIES": lambda self: exp.SerdeProperties(
+275                expressions=self._parse_wrapped_csv(self._parse_property)
+276            ),
+277        }
 
@@ -910,119 +929,122 @@ Default: "nulls_are_small"
-
266    class Generator(generator.Generator):
-267        LIMIT_FETCH = "LIMIT"
-268        TABLESAMPLE_WITH_METHOD = False
-269        TABLESAMPLE_SIZE_IS_PERCENT = True
-270        JOIN_HINTS = False
-271        TABLE_HINTS = False
-272
-273        TYPE_MAPPING = {
-274            **generator.Generator.TYPE_MAPPING,  # type: ignore
-275            exp.DataType.Type.TEXT: "STRING",
-276            exp.DataType.Type.DATETIME: "TIMESTAMP",
-277            exp.DataType.Type.VARBINARY: "BINARY",
-278            exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP",
-279            exp.DataType.Type.BIT: "BOOLEAN",
-280        }
-281
-282        TRANSFORMS = {
-283            **generator.Generator.TRANSFORMS,  # type: ignore
-284            **transforms.UNALIAS_GROUP,  # type: ignore
-285            **transforms.ELIMINATE_QUALIFY,  # type: ignore
-286            exp.Select: transforms.preprocess(
-287                [transforms.eliminate_qualify, transforms.unnest_to_explode]
-288            ),
-289            exp.Property: _property_sql,
-290            exp.ApproxDistinct: approx_count_distinct_sql,
-291            exp.ArrayConcat: rename_func("CONCAT"),
-292            exp.ArraySize: rename_func("SIZE"),
-293            exp.ArraySort: _array_sort,
-294            exp.With: no_recursive_cte_sql,
-295            exp.DateAdd: _add_date_sql,
-296            exp.DateDiff: _date_diff_sql,
-297            exp.DateStrToDate: rename_func("TO_DATE"),
-298            exp.DateSub: _add_date_sql,
-299            exp.DateToDi: lambda self, e: f"CAST(DATE_FORMAT({self.sql(e, 'this')}, {Hive.dateint_format}) AS INT)",
-300            exp.DiToDate: lambda self, e: f"TO_DATE(CAST({self.sql(e, 'this')} AS STRING), {Hive.dateint_format})",
-301            exp.FileFormatProperty: lambda self, e: f"STORED AS {self.sql(e, 'this') if isinstance(e.this, exp.InputOutputFormat) else e.name.upper()}",
-302            exp.If: if_sql,
-303            exp.Index: _index_sql,
-304            exp.ILike: no_ilike_sql,
-305            exp.JSONExtract: rename_func("GET_JSON_OBJECT"),
-306            exp.JSONExtractScalar: rename_func("GET_JSON_OBJECT"),
-307            exp.JSONFormat: rename_func("TO_JSON"),
-308            exp.Map: var_map_sql,
-309            exp.Max: max_or_greatest,
-310            exp.Min: min_or_least,
-311            exp.VarMap: var_map_sql,
-312            exp.Create: create_with_partitions_sql,
-313            exp.Quantile: rename_func("PERCENTILE"),
-314            exp.ApproxQuantile: rename_func("PERCENTILE_APPROX"),
-315            exp.RegexpLike: lambda self, e: self.binary(e, "RLIKE"),
-316            exp.RegexpSplit: rename_func("SPLIT"),
-317            exp.SafeDivide: no_safe_divide_sql,
-318            exp.SchemaCommentProperty: lambda self, e: self.naked_property(e),
-319            exp.SetAgg: rename_func("COLLECT_SET"),
-320            exp.Split: lambda self, e: f"SPLIT({self.sql(e, 'this')}, CONCAT('\\\\Q', {self.sql(e, 'expression')}))",
-321            exp.StrPosition: strposition_to_locate_sql,
-322            exp.StrToDate: _str_to_date,
-323            exp.StrToTime: _str_to_time,
-324            exp.StrToUnix: _str_to_unix,
-325            exp.StructExtract: struct_extract_sql,
-326            exp.TableFormatProperty: lambda self, e: f"USING {self.sql(e, 'this')}",
-327            exp.TimeStrToDate: rename_func("TO_DATE"),
-328            exp.TimeStrToTime: timestrtotime_sql,
-329            exp.TimeStrToUnix: rename_func("UNIX_TIMESTAMP"),
-330            exp.TimeToStr: _time_to_str,
-331            exp.TimeToUnix: rename_func("UNIX_TIMESTAMP"),
-332            exp.TsOrDiToDi: lambda self, e: f"CAST(SUBSTR(REPLACE(CAST({self.sql(e, 'this')} AS STRING), '-', ''), 1, 8) AS INT)",
-333            exp.TsOrDsAdd: lambda self, e: f"DATE_ADD({self.sql(e, 'this')}, {self.sql(e, 'expression')})",
-334            exp.TsOrDsToDate: _to_date_sql,
-335            exp.TryCast: no_trycast_sql,
-336            exp.UnixToStr: lambda self, e: self.func(
-337                "FROM_UNIXTIME", e.this, _time_format(self, e)
-338            ),
-339            exp.UnixToTime: rename_func("FROM_UNIXTIME"),
-340            exp.UnixToTimeStr: rename_func("FROM_UNIXTIME"),
-341            exp.PartitionedByProperty: lambda self, e: f"PARTITIONED BY {self.sql(e, 'this')}",
-342            exp.RowFormatSerdeProperty: lambda self, e: f"ROW FORMAT SERDE {self.sql(e, 'this')}",
-343            exp.SerdeProperties: lambda self, e: self.properties(e, prefix="WITH SERDEPROPERTIES"),
-344            exp.NumberToStr: rename_func("FORMAT_NUMBER"),
-345            exp.LastDateOfMonth: rename_func("LAST_DAY"),
-346            exp.National: lambda self, e: self.sql(e, "this"),
-347        }
-348
-349        PROPERTIES_LOCATION = {
-350            **generator.Generator.PROPERTIES_LOCATION,  # type: ignore
-351            exp.FileFormatProperty: exp.Properties.Location.POST_SCHEMA,
-352            exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA,
-353            exp.TableFormatProperty: exp.Properties.Location.POST_SCHEMA,
-354            exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED,
-355        }
-356
-357        def arrayagg_sql(self, expression: exp.ArrayAgg) -> str:
-358            return self.func(
-359                "COLLECT_LIST",
-360                expression.this.this if isinstance(expression.this, exp.Order) else expression.this,
-361            )
-362
-363        def with_properties(self, properties: exp.Properties) -> str:
-364            return self.properties(
-365                properties,
-366                prefix=self.seg("TBLPROPERTIES"),
-367            )
-368
-369        def datatype_sql(self, expression: exp.DataType) -> str:
-370            if (
-371                expression.this in (exp.DataType.Type.VARCHAR, exp.DataType.Type.NVARCHAR)
-372                and not expression.expressions
-373            ):
-374                expression = exp.DataType.build("text")
-375            elif expression.this in exp.DataType.TEMPORAL_TYPES:
-376                expression = exp.DataType.build(expression.this)
-377
-378            return super().datatype_sql(expression)
+            
279    class Generator(generator.Generator):
+280        LIMIT_FETCH = "LIMIT"
+281        TABLESAMPLE_WITH_METHOD = False
+282        TABLESAMPLE_SIZE_IS_PERCENT = True
+283        JOIN_HINTS = False
+284        TABLE_HINTS = False
+285
+286        TYPE_MAPPING = {
+287            **generator.Generator.TYPE_MAPPING,  # type: ignore
+288            exp.DataType.Type.TEXT: "STRING",
+289            exp.DataType.Type.DATETIME: "TIMESTAMP",
+290            exp.DataType.Type.VARBINARY: "BINARY",
+291            exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP",
+292            exp.DataType.Type.BIT: "BOOLEAN",
+293        }
+294
+295        TRANSFORMS = {
+296            **generator.Generator.TRANSFORMS,  # type: ignore
+297            exp.Group: transforms.preprocess([transforms.unalias_group]),
+298            exp.Select: transforms.preprocess(
+299                [
+300                    transforms.eliminate_qualify,
+301                    transforms.eliminate_distinct_on,
+302                    transforms.unnest_to_explode,
+303                ]
+304            ),
+305            exp.Property: _property_sql,
+306            exp.ApproxDistinct: approx_count_distinct_sql,
+307            exp.ArrayConcat: rename_func("CONCAT"),
+308            exp.ArraySize: rename_func("SIZE"),
+309            exp.ArraySort: _array_sort_sql,
+310            exp.With: no_recursive_cte_sql,
+311            exp.DateAdd: _add_date_sql,
+312            exp.DateDiff: _date_diff_sql,
+313            exp.DateStrToDate: rename_func("TO_DATE"),
+314            exp.DateSub: _add_date_sql,
+315            exp.DateToDi: lambda self, e: f"CAST(DATE_FORMAT({self.sql(e, 'this')}, {Hive.dateint_format}) AS INT)",
+316            exp.DiToDate: lambda self, e: f"TO_DATE(CAST({self.sql(e, 'this')} AS STRING), {Hive.dateint_format})",
+317            exp.FileFormatProperty: lambda self, e: f"STORED AS {self.sql(e, 'this') if isinstance(e.this, exp.InputOutputFormat) else e.name.upper()}",
+318            exp.If: if_sql,
+319            exp.Index: _index_sql,
+320            exp.ILike: no_ilike_sql,
+321            exp.JSONExtract: rename_func("GET_JSON_OBJECT"),
+322            exp.JSONExtractScalar: rename_func("GET_JSON_OBJECT"),
+323            exp.JSONFormat: _json_format_sql,
+324            exp.Map: var_map_sql,
+325            exp.Max: max_or_greatest,
+326            exp.Min: min_or_least,
+327            exp.VarMap: var_map_sql,
+328            exp.Create: create_with_partitions_sql,
+329            exp.Quantile: rename_func("PERCENTILE"),
+330            exp.ApproxQuantile: rename_func("PERCENTILE_APPROX"),
+331            exp.RegexpLike: lambda self, e: self.binary(e, "RLIKE"),
+332            exp.RegexpSplit: rename_func("SPLIT"),
+333            exp.SafeDivide: no_safe_divide_sql,
+334            exp.SchemaCommentProperty: lambda self, e: self.naked_property(e),
+335            exp.SetAgg: rename_func("COLLECT_SET"),
+336            exp.Split: lambda self, e: f"SPLIT({self.sql(e, 'this')}, CONCAT('\\\\Q', {self.sql(e, 'expression')}))",
+337            exp.StrPosition: strposition_to_locate_sql,
+338            exp.StrToDate: _str_to_date_sql,
+339            exp.StrToTime: _str_to_time_sql,
+340            exp.StrToUnix: _str_to_unix_sql,
+341            exp.StructExtract: struct_extract_sql,
+342            exp.TableFormatProperty: lambda self, e: f"USING {self.sql(e, 'this')}",
+343            exp.TimeStrToDate: rename_func("TO_DATE"),
+344            exp.TimeStrToTime: timestrtotime_sql,
+345            exp.TimeStrToUnix: rename_func("UNIX_TIMESTAMP"),
+346            exp.TimeToStr: _time_to_str,
+347            exp.TimeToUnix: rename_func("UNIX_TIMESTAMP"),
+348            exp.TsOrDiToDi: lambda self, e: f"CAST(SUBSTR(REPLACE(CAST({self.sql(e, 'this')} AS STRING), '-', ''), 1, 8) AS INT)",
+349            exp.TsOrDsAdd: lambda self, e: f"DATE_ADD({self.sql(e, 'this')}, {self.sql(e, 'expression')})",
+350            exp.TsOrDsToDate: _to_date_sql,
+351            exp.TryCast: no_trycast_sql,
+352            exp.UnixToStr: lambda self, e: self.func(
+353                "FROM_UNIXTIME", e.this, _time_format(self, e)
+354            ),
+355            exp.UnixToTime: rename_func("FROM_UNIXTIME"),
+356            exp.UnixToTimeStr: rename_func("FROM_UNIXTIME"),
+357            exp.PartitionedByProperty: lambda self, e: f"PARTITIONED BY {self.sql(e, 'this')}",
+358            exp.RowFormatSerdeProperty: lambda self, e: f"ROW FORMAT SERDE {self.sql(e, 'this')}",
+359            exp.SerdeProperties: lambda self, e: self.properties(e, prefix="WITH SERDEPROPERTIES"),
+360            exp.NumberToStr: rename_func("FORMAT_NUMBER"),
+361            exp.LastDateOfMonth: rename_func("LAST_DAY"),
+362            exp.National: lambda self, e: self.sql(e, "this"),
+363        }
+364
+365        PROPERTIES_LOCATION = {
+366            **generator.Generator.PROPERTIES_LOCATION,  # type: ignore
+367            exp.FileFormatProperty: exp.Properties.Location.POST_SCHEMA,
+368            exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA,
+369            exp.TableFormatProperty: exp.Properties.Location.POST_SCHEMA,
+370            exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED,
+371        }
+372
+373        def arrayagg_sql(self, expression: exp.ArrayAgg) -> str:
+374            return self.func(
+375                "COLLECT_LIST",
+376                expression.this.this if isinstance(expression.this, exp.Order) else expression.this,
+377            )
+378
+379        def with_properties(self, properties: exp.Properties) -> str:
+380            return self.properties(
+381                properties,
+382                prefix=self.seg("TBLPROPERTIES"),
+383            )
+384
+385        def datatype_sql(self, expression: exp.DataType) -> str:
+386            if (
+387                expression.this in (exp.DataType.Type.VARCHAR, exp.DataType.Type.NVARCHAR)
+388                and not expression.expressions
+389            ):
+390                expression = exp.DataType.build("text")
+391            elif expression.this in exp.DataType.TEMPORAL_TYPES:
+392                expression = exp.DataType.build(expression.this)
+393
+394            return super().datatype_sql(expression)
 
@@ -1081,11 +1103,11 @@ Default: True
-
357        def arrayagg_sql(self, expression: exp.ArrayAgg) -> str:
-358            return self.func(
-359                "COLLECT_LIST",
-360                expression.this.this if isinstance(expression.this, exp.Order) else expression.this,
-361            )
+            
373        def arrayagg_sql(self, expression: exp.ArrayAgg) -> str:
+374            return self.func(
+375                "COLLECT_LIST",
+376                expression.this.this if isinstance(expression.this, exp.Order) else expression.this,
+377            )
 
@@ -1103,11 +1125,11 @@ Default: True
-
363        def with_properties(self, properties: exp.Properties) -> str:
-364            return self.properties(
-365                properties,
-366                prefix=self.seg("TBLPROPERTIES"),
-367            )
+            
379        def with_properties(self, properties: exp.Properties) -> str:
+380            return self.properties(
+381                properties,
+382                prefix=self.seg("TBLPROPERTIES"),
+383            )
 
@@ -1125,16 +1147,16 @@ Default: True
-
369        def datatype_sql(self, expression: exp.DataType) -> str:
-370            if (
-371                expression.this in (exp.DataType.Type.VARCHAR, exp.DataType.Type.NVARCHAR)
-372                and not expression.expressions
-373            ):
-374                expression = exp.DataType.build("text")
-375            elif expression.this in exp.DataType.TEMPORAL_TYPES:
-376                expression = exp.DataType.build(expression.this)
-377
-378            return super().datatype_sql(expression)
+            
385        def datatype_sql(self, expression: exp.DataType) -> str:
+386            if (
+387                expression.this in (exp.DataType.Type.VARCHAR, exp.DataType.Type.NVARCHAR)
+388                and not expression.expressions
+389            ):
+390                expression = exp.DataType.build("text")
+391            elif expression.this in exp.DataType.TEMPORAL_TYPES:
+392                expression = exp.DataType.build(expression.this)
+393
+394            return super().datatype_sql(expression)
 
@@ -1263,7 +1285,7 @@ Default: True
where_sql
window_sql
partition_by_sql
-
window_spec_sql
+
windowspec_sql
withingroup_sql
between_sql
bracket_sql
@@ -1272,6 +1294,7 @@ Default: True
exists_sql
case_sql
constraint_sql
+
nextvaluefor_sql
extract_sql
trim_sql
concat_sql
-- cgit v1.2.3