1use std::borrow::Cow;
14use std::sync::Arc;
15
16use crate::error::Result;
17use crate::expressions::*;
18use crate::guard::{enforce_generate_ast, ComplexityGuardOptions};
19use crate::DialectType;
20use serde::{Deserialize, Serialize};
21
22pub struct Generator {
47 config: Arc<GeneratorConfig>,
48 output: String,
49 unsupported_messages: Vec<String>,
50 indent_level: usize,
51 athena_hive_context: bool,
54 sqlite_inline_pk_columns: std::collections::HashSet<String>,
56 merge_strip_qualifiers: Vec<String>,
58 clickhouse_nullable_depth: i32,
63}
64
65#[derive(Debug, Clone, Copy, PartialEq, Default)]
71pub enum NormalizeFunctions {
72 #[default]
74 Upper,
75 Lower,
77 None,
79}
80
81#[derive(Debug, Clone, Copy, PartialEq, Default)]
83pub enum LimitFetchStyle {
84 #[default]
86 Limit,
87 Top,
89 FetchFirst,
91}
92
93#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
95pub enum NotInStyle {
96 #[default]
98 Prefix,
99 Infix,
101}
102
103#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
105#[serde(rename_all = "lowercase")]
106pub enum UnsupportedLevel {
107 Ignore,
109 #[default]
111 Warn,
112 Raise,
114 Immediate,
116}
117
118#[derive(Debug, Clone, Copy, PartialEq, Eq)]
119enum ConnectorOperator {
120 And,
121 Or,
122}
123
124impl ConnectorOperator {
125 fn keyword(self) -> &'static str {
126 match self {
127 Self::And => "AND",
128 Self::Or => "OR",
129 }
130 }
131}
132
133#[derive(Debug, Clone, PartialEq, Eq)]
134enum TsqlDatePart {
135 Native(String),
136 Epoch,
137 IsoDayOfWeek,
138 Unsupported(String),
139}
140
141#[derive(Debug, Clone, Copy, PartialEq)]
143pub struct IdentifierQuoteStyle {
144 pub start: char,
146 pub end: char,
148}
149
150impl Default for IdentifierQuoteStyle {
151 fn default() -> Self {
152 Self {
153 start: '"',
154 end: '"',
155 }
156 }
157}
158
159impl IdentifierQuoteStyle {
160 pub const DOUBLE_QUOTE: Self = Self {
162 start: '"',
163 end: '"',
164 };
165 pub const BACKTICK: Self = Self {
167 start: '`',
168 end: '`',
169 };
170 pub const BRACKET: Self = Self {
172 start: '[',
173 end: ']',
174 };
175}
176
177#[derive(Debug, Clone)]
199pub struct GeneratorConfig {
200 pub pretty: bool,
203 pub indent: &'static str,
205 pub max_text_width: usize,
207 pub identifier_quote: char,
209 pub identifier_quote_style: IdentifierQuoteStyle,
211 pub uppercase_keywords: bool,
213 pub normalize_identifiers: bool,
215 pub dialect: Option<crate::dialects::DialectType>,
217 pub source_dialect: Option<crate::dialects::DialectType>,
219 pub unsupported_level: UnsupportedLevel,
221 pub max_unsupported: usize,
223 pub complexity_guard: ComplexityGuardOptions,
225 pub normalize_functions: NormalizeFunctions,
227 pub string_escape: char,
229 pub case_sensitive_identifiers: bool,
231 pub identifiers_can_start_with_digit: bool,
233 pub always_quote_identifiers: bool,
236 pub not_in_style: NotInStyle,
238
239 pub null_ordering_supported: bool,
243 pub ignore_nulls_in_func: bool,
246 pub nvl2_supported: bool,
248
249 pub limit_fetch_style: LimitFetchStyle,
252 pub limit_is_top: bool,
254 pub limit_only_literals: bool,
256
257 pub single_string_interval: bool,
260 pub interval_allows_plural_form: bool,
262
263 pub cte_recursive_keyword_required: bool,
266
267 pub values_as_table: bool,
270 pub wrap_derived_values: bool,
272
273 pub tablesample_seed_keyword: &'static str,
276 pub tablesample_requires_parens: bool,
278 pub tablesample_size_is_rows: bool,
280 pub tablesample_keywords: &'static str,
282 pub tablesample_with_method: bool,
284 pub alias_post_tablesample: bool,
286
287 pub aggregate_filter_supported: bool,
290 pub multi_arg_distinct: bool,
292 pub quantified_no_paren_space: bool,
294 pub supports_median: bool,
296
297 pub supports_select_into: bool,
300 pub locking_reads_supported: bool,
302
303 pub rename_table_with_db: bool,
306 pub semi_anti_join_with_side: bool,
308 pub supports_table_alias_columns: bool,
310 pub join_hints: bool,
312 pub table_hints: bool,
314 pub query_hints: bool,
316 pub query_hint_sep: &'static str,
318 pub supports_column_join_marks: bool,
320
321 pub index_using_no_space: bool,
325 pub supports_unlogged_tables: bool,
327 pub supports_create_table_like: bool,
329 pub like_property_inside_schema: bool,
331 pub alter_table_include_column_keyword: bool,
333 pub supports_table_copy: bool,
335 pub alter_set_type: &'static str,
337 pub alter_set_wrapped: bool,
339
340 pub tz_to_with_time_zone: bool,
343 pub supports_convert_timezone: bool,
345
346 pub json_type_required_for_extraction: bool,
349 pub json_path_bracketed_key_supported: bool,
351 pub json_path_single_quote_escape: bool,
353 pub quote_json_path: bool,
355 pub json_key_value_pair_sep: &'static str,
357
358 pub copy_params_are_wrapped: bool,
361 pub copy_params_eq_required: bool,
363 pub copy_has_into_keyword: bool,
365
366 pub supports_window_exclude: bool,
369 pub unnest_with_ordinality: bool,
371 pub lowercase_window_frame_keywords: bool,
374 pub normalize_window_frame_between: bool,
377
378 pub array_concat_is_var_len: bool,
381 pub array_size_dim_required: Option<bool>,
384 pub can_implement_array_any: bool,
386 pub array_size_name: &'static str,
388
389 pub supports_between_flags: bool,
392
393 pub is_bool_allowed: bool,
396 pub ensure_bools: bool,
398
399 pub extract_allows_quotes: bool,
402 pub normalize_extract_date_parts: bool,
404
405 pub try_supported: bool,
408 pub supports_uescape: bool,
410 pub supports_to_number: bool,
412 pub supports_single_arg_concat: bool,
414 pub last_day_supports_date_part: bool,
416 pub supports_exploding_projections: bool,
418 pub supports_unix_seconds: bool,
420 pub supports_like_quantifiers: bool,
422 pub supports_decode_case: bool,
424 pub set_op_modifiers: bool,
426 pub update_statement_supports_from: bool,
428
429 pub collate_is_func: bool,
432
433 pub duplicate_key_update_with_set: bool,
436 pub insert_overwrite: &'static str,
438
439 pub returning_end: bool,
442
443 pub matched_by_source: bool,
446
447 pub create_function_return_as: bool,
450 pub parameter_default_equals: bool,
452
453 pub computed_column_with_type: bool,
456
457 pub unpivot_aliases_are_identifiers: bool,
460
461 pub star_except: &'static str,
464
465 pub hex_func: &'static str,
468
469 pub with_properties_prefix: &'static str,
472
473 pub pad_fill_pattern_is_required: bool,
476
477 pub index_on: &'static str,
480
481 pub groupings_sep: &'static str,
484
485 pub struct_delimiter: (&'static str, &'static str),
488 pub struct_curly_brace_notation: bool,
490 pub array_bracket_only: bool,
492 pub struct_field_sep: &'static str,
494
495 pub except_intersect_support_all_clause: bool,
498
499 pub parameter_token: &'static str,
502 pub named_placeholder_token: &'static str,
504
505 pub data_type_specifiers_allowed: bool,
508
509 pub schema_comment_with_eq: bool,
513}
514
515impl Default for GeneratorConfig {
516 fn default() -> Self {
517 Self {
518 pretty: false,
520 indent: " ",
521 max_text_width: 80,
522 identifier_quote: '"',
523 identifier_quote_style: IdentifierQuoteStyle::DOUBLE_QUOTE,
524 uppercase_keywords: true,
525 normalize_identifiers: false,
526 dialect: None,
527 source_dialect: None,
528 unsupported_level: UnsupportedLevel::Warn,
529 max_unsupported: 3,
530 complexity_guard: ComplexityGuardOptions::default(),
531 normalize_functions: NormalizeFunctions::Upper,
532 string_escape: '\'',
533 case_sensitive_identifiers: false,
534 identifiers_can_start_with_digit: false,
535 always_quote_identifiers: false,
536 not_in_style: NotInStyle::Prefix,
537
538 null_ordering_supported: true,
540 ignore_nulls_in_func: false,
541 nvl2_supported: true,
542
543 limit_fetch_style: LimitFetchStyle::Limit,
545 limit_is_top: false,
546 limit_only_literals: false,
547
548 single_string_interval: false,
550 interval_allows_plural_form: true,
551
552 cte_recursive_keyword_required: true,
554
555 values_as_table: true,
557 wrap_derived_values: true,
558
559 tablesample_seed_keyword: "SEED",
561 tablesample_requires_parens: true,
562 tablesample_size_is_rows: true,
563 tablesample_keywords: "TABLESAMPLE",
564 tablesample_with_method: true,
565 alias_post_tablesample: false,
566
567 aggregate_filter_supported: true,
569 multi_arg_distinct: true,
570 quantified_no_paren_space: false,
571 supports_median: true,
572
573 supports_select_into: false,
575 locking_reads_supported: true,
576
577 rename_table_with_db: true,
579 semi_anti_join_with_side: true,
580 supports_table_alias_columns: true,
581 join_hints: true,
582 table_hints: true,
583 query_hints: true,
584 query_hint_sep: ", ",
585 supports_column_join_marks: false,
586
587 index_using_no_space: false,
589 supports_unlogged_tables: false,
590 supports_create_table_like: true,
591 like_property_inside_schema: false,
592 alter_table_include_column_keyword: true,
593 supports_table_copy: true,
594 alter_set_type: "SET DATA TYPE",
595 alter_set_wrapped: false,
596
597 tz_to_with_time_zone: false,
599 supports_convert_timezone: false,
600
601 json_type_required_for_extraction: false,
603 json_path_bracketed_key_supported: true,
604 json_path_single_quote_escape: false,
605 quote_json_path: true,
606 json_key_value_pair_sep: ":",
607
608 copy_params_are_wrapped: true,
610 copy_params_eq_required: false,
611 copy_has_into_keyword: true,
612
613 supports_window_exclude: false,
615 unnest_with_ordinality: true,
616 lowercase_window_frame_keywords: false,
617 normalize_window_frame_between: false,
618
619 array_concat_is_var_len: true,
621 array_size_dim_required: None,
622 can_implement_array_any: false,
623 array_size_name: "ARRAY_LENGTH",
624
625 supports_between_flags: false,
627
628 is_bool_allowed: true,
630 ensure_bools: false,
631
632 extract_allows_quotes: true,
634 normalize_extract_date_parts: false,
635
636 try_supported: true,
638 supports_uescape: true,
639 supports_to_number: true,
640 supports_single_arg_concat: true,
641 last_day_supports_date_part: true,
642 supports_exploding_projections: true,
643 supports_unix_seconds: false,
644 supports_like_quantifiers: true,
645 supports_decode_case: true,
646 set_op_modifiers: true,
647 update_statement_supports_from: true,
648
649 collate_is_func: false,
651
652 duplicate_key_update_with_set: true,
654 insert_overwrite: " OVERWRITE TABLE",
655
656 returning_end: true,
658
659 matched_by_source: true,
661
662 create_function_return_as: true,
664 parameter_default_equals: false,
665
666 computed_column_with_type: true,
668
669 unpivot_aliases_are_identifiers: true,
671
672 star_except: "EXCEPT",
674
675 hex_func: "HEX",
677
678 with_properties_prefix: "WITH",
680
681 pad_fill_pattern_is_required: false,
683
684 index_on: "ON",
686
687 groupings_sep: ",",
689
690 struct_delimiter: ("<", ">"),
692 struct_curly_brace_notation: false,
693 array_bracket_only: false,
694 struct_field_sep: " ",
695
696 except_intersect_support_all_clause: true,
698
699 parameter_token: "@",
701 named_placeholder_token: ":",
702
703 data_type_specifiers_allowed: false,
705
706 schema_comment_with_eq: true,
708 }
709 }
710}
711
712mod reserved_keywords {
715 use std::collections::HashSet;
716 use std::sync::LazyLock;
717
718 pub static SQL_RESERVED: LazyLock<HashSet<&'static str>> = LazyLock::new(|| {
720 [
721 "all",
722 "alter",
723 "and",
724 "any",
725 "array",
726 "as",
727 "asc",
728 "at",
729 "authorization",
730 "begin",
731 "between",
732 "both",
733 "by",
734 "case",
735 "cast",
736 "check",
737 "collate",
738 "column",
739 "commit",
740 "constraint",
741 "create",
742 "cross",
743 "cube",
744 "current",
745 "current_date",
746 "current_time",
747 "current_timestamp",
748 "current_user",
749 "default",
750 "delete",
751 "desc",
752 "distinct",
753 "drop",
754 "else",
755 "end",
756 "escape",
757 "except",
758 "execute",
759 "exists",
760 "external",
761 "false",
762 "fetch",
763 "filter",
764 "for",
765 "foreign",
766 "from",
767 "full",
768 "function",
769 "grant",
770 "group",
771 "grouping",
772 "having",
773 "if",
774 "in",
775 "index",
776 "inner",
777 "insert",
778 "intersect",
779 "interval",
780 "into",
781 "is",
782 "join",
783 "key",
784 "leading",
785 "left",
786 "like",
787 "limit",
788 "local",
789 "localtime",
790 "localtimestamp",
791 "match",
792 "merge",
793 "natural",
794 "no",
795 "not",
796 "null",
797 "of",
798 "offset",
799 "on",
800 "only",
801 "or",
802 "order",
803 "outer",
804 "over",
805 "partition",
806 "primary",
807 "procedure",
808 "range",
809 "references",
810 "right",
811 "rollback",
812 "rollup",
813 "row",
814 "rows",
815 "select",
816 "session_user",
817 "set",
818 "some",
819 "table",
820 "tablesample",
821 "then",
822 "to",
823 "trailing",
824 "true",
825 "truncate",
826 "union",
827 "unique",
828 "unknown",
829 "update",
830 "user",
831 "using",
832 "values",
833 "view",
834 "when",
835 "where",
836 "window",
837 "with",
838 ]
839 .into_iter()
840 .collect()
841 });
842
843 pub static BIGQUERY_RESERVED: LazyLock<HashSet<&'static str>> = LazyLock::new(|| {
846 let mut set = SQL_RESERVED.clone();
847 set.extend([
848 "assert_rows_modified",
849 "at",
850 "contains",
851 "cube",
852 "current",
853 "define",
854 "enum",
855 "escape",
856 "exclude",
857 "following",
858 "for",
859 "groups",
860 "hash",
861 "ignore",
862 "lateral",
863 "lookup",
864 "new",
865 "no",
866 "nulls",
867 "of",
868 "over",
869 "preceding",
870 "proto",
871 "qualify",
872 "recursive",
873 "respect",
874 "struct",
875 "tablesample",
876 "treat",
877 "unbounded",
878 "unnest",
879 "window",
880 "within",
881 ]);
882 set.remove("grant");
884 set.remove("key");
885 set.remove("index");
886 set.remove("offset");
887 set.remove("values");
888 set.remove("table");
889 set
890 });
891
892 pub static MYSQL_RESERVED: LazyLock<HashSet<&'static str>> = LazyLock::new(|| {
894 let mut set = SQL_RESERVED.clone();
895 set.extend([
896 "accessible",
897 "add",
898 "analyze",
899 "asensitive",
900 "before",
901 "bigint",
902 "binary",
903 "blob",
904 "call",
905 "cascade",
906 "change",
907 "char",
908 "character",
909 "condition",
910 "continue",
911 "convert",
912 "current_date",
913 "current_time",
914 "current_timestamp",
915 "current_user",
916 "cursor",
917 "database",
918 "databases",
919 "day_hour",
920 "day_microsecond",
921 "day_minute",
922 "day_second",
923 "dec",
924 "decimal",
925 "declare",
926 "delayed",
927 "describe",
928 "deterministic",
929 "distinctrow",
930 "div",
931 "double",
932 "dual",
933 "each",
934 "elseif",
935 "enclosed",
936 "escaped",
937 "exit",
938 "explain",
939 "float",
940 "float4",
941 "float8",
942 "force",
943 "get",
944 "high_priority",
945 "hour_microsecond",
946 "hour_minute",
947 "hour_second",
948 "ignore",
949 "infile",
950 "inout",
951 "insensitive",
952 "int",
953 "int1",
954 "int2",
955 "int3",
956 "int4",
957 "int8",
958 "integer",
959 "iterate",
960 "keys",
961 "kill",
962 "leave",
963 "linear",
964 "lines",
965 "load",
966 "lock",
967 "long",
968 "longblob",
969 "longtext",
970 "loop",
971 "low_priority",
972 "master_ssl_verify_server_cert",
973 "maxvalue",
974 "mediumblob",
975 "mediumint",
976 "mediumtext",
977 "middleint",
978 "minute_microsecond",
979 "minute_second",
980 "mod",
981 "modifies",
982 "no_write_to_binlog",
983 "numeric",
984 "optimize",
985 "option",
986 "optionally",
987 "out",
988 "outfile",
989 "precision",
990 "purge",
991 "read",
992 "reads",
993 "real",
994 "regexp",
995 "release",
996 "rename",
997 "repeat",
998 "replace",
999 "require",
1000 "resignal",
1001 "restrict",
1002 "return",
1003 "revoke",
1004 "rlike",
1005 "schema",
1006 "schemas",
1007 "second_microsecond",
1008 "sensitive",
1009 "separator",
1010 "show",
1011 "signal",
1012 "smallint",
1013 "spatial",
1014 "specific",
1015 "sql",
1016 "sql_big_result",
1017 "sql_calc_found_rows",
1018 "sql_small_result",
1019 "sqlexception",
1020 "sqlstate",
1021 "sqlwarning",
1022 "ssl",
1023 "starting",
1024 "straight_join",
1025 "terminated",
1026 "text",
1027 "tinyblob",
1028 "tinyint",
1029 "tinytext",
1030 "trigger",
1031 "undo",
1032 "unlock",
1033 "unsigned",
1034 "usage",
1035 "utc_date",
1036 "utc_time",
1037 "utc_timestamp",
1038 "varbinary",
1039 "varchar",
1040 "varcharacter",
1041 "varying",
1042 "while",
1043 "write",
1044 "xor",
1045 "year_month",
1046 "zerofill",
1047 ]);
1048 set.remove("table");
1049 set
1050 });
1051
1052 pub static DORIS_RESERVED: LazyLock<HashSet<&'static str>> = LazyLock::new(|| {
1055 let mut set = MYSQL_RESERVED.clone();
1056 set.extend([
1057 "aggregate",
1058 "anti",
1059 "array",
1060 "backend",
1061 "backup",
1062 "begin",
1063 "bitmap",
1064 "boolean",
1065 "broker",
1066 "buckets",
1067 "cached",
1068 "cancel",
1069 "cast",
1070 "catalog",
1071 "charset",
1072 "cluster",
1073 "collation",
1074 "columns",
1075 "comment",
1076 "commit",
1077 "config",
1078 "connection",
1079 "count",
1080 "current",
1081 "data",
1082 "date",
1083 "datetime",
1084 "day",
1085 "deferred",
1086 "distributed",
1087 "dynamic",
1088 "enable",
1089 "end",
1090 "events",
1091 "export",
1092 "external",
1093 "fields",
1094 "first",
1095 "follower",
1096 "format",
1097 "free",
1098 "frontend",
1099 "full",
1100 "functions",
1101 "global",
1102 "grants",
1103 "hash",
1104 "help",
1105 "hour",
1106 "install",
1107 "intermediate",
1108 "json",
1109 "label",
1110 "last",
1111 "less",
1112 "level",
1113 "link",
1114 "local",
1115 "location",
1116 "max",
1117 "merge",
1118 "min",
1119 "minute",
1120 "modify",
1121 "month",
1122 "name",
1123 "names",
1124 "negative",
1125 "nulls",
1126 "observer",
1127 "offset",
1128 "only",
1129 "open",
1130 "overwrite",
1131 "password",
1132 "path",
1133 "plan",
1134 "plugin",
1135 "plugins",
1136 "policy",
1137 "process",
1138 "properties",
1139 "property",
1140 "query",
1141 "quota",
1142 "recover",
1143 "refresh",
1144 "repair",
1145 "replica",
1146 "repository",
1147 "resource",
1148 "restore",
1149 "resume",
1150 "role",
1151 "roles",
1152 "rollback",
1153 "rollup",
1154 "routine",
1155 "sample",
1156 "second",
1157 "semi",
1158 "session",
1159 "signed",
1160 "snapshot",
1161 "start",
1162 "stats",
1163 "status",
1164 "stop",
1165 "stream",
1166 "string",
1167 "sum",
1168 "tables",
1169 "tablet",
1170 "temporary",
1171 "text",
1172 "timestamp",
1173 "transaction",
1174 "trash",
1175 "trim",
1176 "truncate",
1177 "type",
1178 "user",
1179 "value",
1180 "variables",
1181 "verbose",
1182 "version",
1183 "view",
1184 "warnings",
1185 "week",
1186 "work",
1187 "year",
1188 ]);
1189 set
1190 });
1191
1192 pub static POSTGRES_RESERVED: LazyLock<HashSet<&'static str>> = LazyLock::new(|| {
1194 let mut set = SQL_RESERVED.clone();
1195 set.extend([
1196 "analyse",
1197 "analyze",
1198 "asymmetric",
1199 "binary",
1200 "collation",
1201 "concurrently",
1202 "current_catalog",
1203 "current_role",
1204 "current_schema",
1205 "deferrable",
1206 "do",
1207 "freeze",
1208 "ilike",
1209 "initially",
1210 "isnull",
1211 "lateral",
1212 "notnull",
1213 "placing",
1214 "returning",
1215 "similar",
1216 "symmetric",
1217 "variadic",
1218 "verbose",
1219 ]);
1220 set.remove("default");
1222 set.remove("interval");
1223 set.remove("match");
1224 set.remove("offset");
1225 set.remove("table");
1226 set
1227 });
1228
1229 pub static REDSHIFT_RESERVED: LazyLock<HashSet<&'static str>> = LazyLock::new(|| {
1233 [
1234 "aes128",
1235 "aes256",
1236 "all",
1237 "allowoverwrite",
1238 "analyse",
1239 "analyze",
1240 "and",
1241 "any",
1242 "array",
1243 "as",
1244 "asc",
1245 "authorization",
1246 "az64",
1247 "backup",
1248 "between",
1249 "binary",
1250 "blanksasnull",
1251 "both",
1252 "bytedict",
1253 "bzip2",
1254 "case",
1255 "cast",
1256 "check",
1257 "collate",
1258 "column",
1259 "constraint",
1260 "create",
1261 "credentials",
1262 "cross",
1263 "current_date",
1264 "current_time",
1265 "current_timestamp",
1266 "current_user",
1267 "current_user_id",
1268 "default",
1269 "deferrable",
1270 "deflate",
1271 "defrag",
1272 "delta",
1273 "delta32k",
1274 "desc",
1275 "disable",
1276 "distinct",
1277 "do",
1278 "else",
1279 "emptyasnull",
1280 "enable",
1281 "encode",
1282 "encrypt",
1283 "encryption",
1284 "end",
1285 "except",
1286 "explicit",
1287 "false",
1288 "for",
1289 "foreign",
1290 "freeze",
1291 "from",
1292 "full",
1293 "globaldict256",
1294 "globaldict64k",
1295 "grant",
1296 "group",
1297 "gzip",
1298 "having",
1299 "identity",
1300 "ignore",
1301 "ilike",
1302 "in",
1303 "initially",
1304 "inner",
1305 "intersect",
1306 "interval",
1307 "into",
1308 "is",
1309 "isnull",
1310 "join",
1311 "leading",
1312 "left",
1313 "like",
1314 "limit",
1315 "localtime",
1316 "localtimestamp",
1317 "lun",
1318 "luns",
1319 "lzo",
1320 "lzop",
1321 "minus",
1322 "mostly16",
1323 "mostly32",
1324 "mostly8",
1325 "natural",
1326 "new",
1327 "not",
1328 "notnull",
1329 "null",
1330 "nulls",
1331 "off",
1332 "offline",
1333 "offset",
1334 "oid",
1335 "old",
1336 "on",
1337 "only",
1338 "open",
1339 "or",
1340 "order",
1341 "outer",
1342 "overlaps",
1343 "parallel",
1344 "partition",
1345 "percent",
1346 "permissions",
1347 "pivot",
1348 "placing",
1349 "primary",
1350 "raw",
1351 "readratio",
1352 "recover",
1353 "references",
1354 "rejectlog",
1355 "resort",
1356 "respect",
1357 "restore",
1358 "right",
1359 "select",
1360 "session_user",
1361 "similar",
1362 "snapshot",
1363 "some",
1364 "sysdate",
1365 "system",
1366 "table",
1367 "tag",
1368 "tdes",
1369 "text255",
1370 "text32k",
1371 "then",
1372 "timestamp",
1373 "to",
1374 "top",
1375 "trailing",
1376 "true",
1377 "truncatecolumns",
1378 "type",
1379 "union",
1380 "unique",
1381 "unnest",
1382 "unpivot",
1383 "user",
1384 "using",
1385 "verbose",
1386 "wallet",
1387 "when",
1388 "where",
1389 "with",
1390 "without",
1391 ]
1392 .into_iter()
1393 .collect()
1394 });
1395
1396 pub static DUCKDB_RESERVED: LazyLock<HashSet<&'static str>> = LazyLock::new(|| {
1398 let mut set = POSTGRES_RESERVED.clone();
1399 set.extend([
1400 "anti",
1401 "asof",
1402 "columns",
1403 "describe",
1404 "groups",
1405 "macro",
1406 "pivot",
1407 "pivot_longer",
1408 "pivot_wider",
1409 "qualify",
1410 "replace",
1411 "respect",
1412 "semi",
1413 "show",
1414 "table",
1415 "unpivot",
1416 ]);
1417 set.remove("at");
1418 set.remove("key");
1419 set.remove("range");
1420 set.remove("row");
1421 set.remove("values");
1422 set
1423 });
1424
1425 pub static PRESTO_TRINO_RESERVED: LazyLock<HashSet<&'static str>> = LazyLock::new(|| {
1427 let mut set = SQL_RESERVED.clone();
1428 set.extend([
1429 "alter",
1430 "and",
1431 "as",
1432 "between",
1433 "by",
1434 "case",
1435 "cast",
1436 "constraint",
1437 "create",
1438 "cross",
1439 "cube",
1440 "current_catalog",
1441 "current_date",
1442 "current_path",
1443 "current_role",
1444 "current_schema",
1445 "current_time",
1446 "current_timestamp",
1447 "current_user",
1448 "deallocate",
1449 "delete",
1450 "describe",
1451 "distinct",
1452 "drop",
1453 "else",
1454 "end",
1455 "escape",
1456 "except",
1457 "execute",
1458 "exists",
1459 "extract",
1460 "false",
1461 "for",
1462 "from",
1463 "full",
1464 "group",
1465 "grouping",
1466 "having",
1467 "in",
1468 "inner",
1469 "insert",
1470 "intersect",
1471 "into",
1472 "is",
1473 "join",
1474 "json_array",
1475 "json_exists",
1476 "json_object",
1477 "json_query",
1478 "json_table",
1479 "json_value",
1480 "left",
1481 "like",
1482 "listagg",
1483 "localtime",
1484 "localtimestamp",
1485 "natural",
1486 "normalize",
1487 "not",
1488 "null",
1489 "on",
1490 "or",
1491 "order",
1492 "outer",
1493 "prepare",
1494 "recursive",
1495 "right",
1496 "rollup",
1497 "select",
1498 "skip",
1499 "table",
1500 "then",
1501 "trim",
1502 "true",
1503 "uescape",
1504 "union",
1505 "unnest",
1506 "using",
1507 "values",
1508 "when",
1509 "where",
1510 "with",
1511 ]);
1512 set.remove("key");
1514 set
1515 });
1516
1517 pub static STARROCKS_RESERVED: LazyLock<HashSet<&'static str>> = LazyLock::new(|| {
1520 [
1521 "add",
1522 "all",
1523 "alter",
1524 "analyze",
1525 "and",
1526 "array",
1527 "as",
1528 "asc",
1529 "between",
1530 "bigint",
1531 "bitmap",
1532 "both",
1533 "by",
1534 "case",
1535 "char",
1536 "character",
1537 "check",
1538 "collate",
1539 "column",
1540 "compaction",
1541 "convert",
1542 "create",
1543 "cross",
1544 "cube",
1545 "current_date",
1546 "current_role",
1547 "current_time",
1548 "current_timestamp",
1549 "current_user",
1550 "database",
1551 "databases",
1552 "decimal",
1553 "decimalv2",
1554 "decimal32",
1555 "decimal64",
1556 "decimal128",
1557 "default",
1558 "deferred",
1559 "delete",
1560 "dense_rank",
1561 "desc",
1562 "describe",
1563 "distinct",
1564 "double",
1565 "drop",
1566 "dual",
1567 "else",
1568 "except",
1569 "exists",
1570 "explain",
1571 "false",
1572 "first_value",
1573 "float",
1574 "for",
1575 "force",
1576 "from",
1577 "full",
1578 "function",
1579 "grant",
1580 "group",
1581 "grouping",
1582 "grouping_id",
1583 "groups",
1584 "having",
1585 "hll",
1586 "host",
1587 "if",
1588 "ignore",
1589 "immediate",
1590 "in",
1591 "index",
1592 "infile",
1593 "inner",
1594 "insert",
1595 "int",
1596 "integer",
1597 "intersect",
1598 "into",
1599 "is",
1600 "join",
1601 "json",
1602 "key",
1603 "keys",
1604 "kill",
1605 "lag",
1606 "largeint",
1607 "last_value",
1608 "lateral",
1609 "lead",
1610 "left",
1611 "like",
1612 "limit",
1613 "load",
1614 "localtime",
1615 "localtimestamp",
1616 "maxvalue",
1617 "minus",
1618 "mod",
1619 "not",
1620 "ntile",
1621 "null",
1622 "on",
1623 "or",
1624 "order",
1625 "outer",
1626 "outfile",
1627 "over",
1628 "partition",
1629 "percentile",
1630 "primary",
1631 "procedure",
1632 "qualify",
1633 "range",
1634 "rank",
1635 "read",
1636 "regexp",
1637 "release",
1638 "rename",
1639 "replace",
1640 "revoke",
1641 "right",
1642 "rlike",
1643 "row",
1644 "row_number",
1645 "rows",
1646 "schema",
1647 "schemas",
1648 "select",
1649 "set",
1650 "set_var",
1651 "show",
1652 "smallint",
1653 "system",
1654 "table",
1655 "terminated",
1656 "text",
1657 "then",
1658 "tinyint",
1659 "to",
1660 "true",
1661 "union",
1662 "unique",
1663 "unsigned",
1664 "update",
1665 "use",
1666 "using",
1667 "values",
1668 "varchar",
1669 "when",
1670 "where",
1671 "with",
1672 ]
1673 .into_iter()
1674 .collect()
1675 });
1676
1677 pub static SINGLESTORE_RESERVED: LazyLock<HashSet<&'static str>> = LazyLock::new(|| {
1680 let mut set = MYSQL_RESERVED.clone();
1681 set.extend([
1682 "abs",
1685 "account",
1686 "acos",
1687 "adddate",
1688 "addtime",
1689 "admin",
1690 "aes_decrypt",
1691 "aes_encrypt",
1692 "aggregate",
1693 "aggregates",
1694 "aggregator",
1695 "anti_join",
1696 "any_value",
1697 "approx_count_distinct",
1698 "approx_percentile",
1699 "arrange",
1700 "arrangement",
1701 "asin",
1702 "atan",
1703 "atan2",
1704 "attach",
1705 "autostats",
1706 "avro",
1707 "background",
1708 "backup",
1709 "batch",
1710 "batches",
1711 "boot_strapping",
1712 "ceil",
1713 "ceiling",
1714 "coercibility",
1715 "columnar",
1716 "columnstore",
1717 "compile",
1718 "concurrent",
1719 "connection_id",
1720 "cos",
1721 "cot",
1722 "current_security_groups",
1723 "current_security_roles",
1724 "dayname",
1725 "dayofmonth",
1726 "dayofweek",
1727 "dayofyear",
1728 "degrees",
1729 "dot_product",
1730 "dump",
1731 "durability",
1732 "earliest",
1733 "echo",
1734 "election",
1735 "euclidean_distance",
1736 "exp",
1737 "extractor",
1738 "extractors",
1739 "floor",
1740 "foreground",
1741 "found_rows",
1742 "from_base64",
1743 "from_days",
1744 "from_unixtime",
1745 "fs",
1746 "fulltext",
1747 "gc",
1748 "gcs",
1749 "geography",
1750 "geography_area",
1751 "geography_contains",
1752 "geography_distance",
1753 "geography_intersects",
1754 "geography_latitude",
1755 "geography_length",
1756 "geography_longitude",
1757 "geographypoint",
1758 "geography_point",
1759 "geography_within_distance",
1760 "geometry",
1761 "geometry_area",
1762 "geometry_contains",
1763 "geometry_distance",
1764 "geometry_filter",
1765 "geometry_intersects",
1766 "geometry_length",
1767 "geometrypoint",
1768 "geometry_point",
1769 "geometry_within_distance",
1770 "geometry_x",
1771 "geometry_y",
1772 "greatest",
1773 "groups",
1774 "group_concat",
1775 "gzip",
1776 "hdfs",
1777 "hex",
1778 "highlight",
1779 "ifnull",
1780 "ilike",
1781 "inet_aton",
1782 "inet_ntoa",
1783 "inet6_aton",
1784 "inet6_ntoa",
1785 "initcap",
1786 "instr",
1787 "interpreter_mode",
1788 "isnull",
1789 "json",
1790 "json_agg",
1791 "json_array_contains_double",
1792 "json_array_contains_json",
1793 "json_array_contains_string",
1794 "json_delete_key",
1795 "json_extract_double",
1796 "json_extract_json",
1797 "json_extract_string",
1798 "json_extract_bigint",
1799 "json_get_type",
1800 "json_length",
1801 "json_set_double",
1802 "json_set_json",
1803 "json_set_string",
1804 "kafka",
1805 "lag",
1806 "last_day",
1807 "last_insert_id",
1808 "latest",
1809 "lcase",
1810 "lead",
1811 "leaf",
1812 "least",
1813 "leaves",
1814 "length",
1815 "license",
1816 "links",
1817 "llvm",
1818 "ln",
1819 "load",
1820 "locate",
1821 "log",
1822 "log10",
1823 "log2",
1824 "lpad",
1825 "lz4",
1826 "management",
1827 "match",
1828 "mbc",
1829 "md5",
1830 "median",
1831 "memsql",
1832 "memsql_deserialize",
1833 "memsql_serialize",
1834 "metadata",
1835 "microsecond",
1836 "minute",
1837 "model",
1838 "monthname",
1839 "months_between",
1840 "mpl",
1841 "namespace",
1842 "node",
1843 "noparam",
1844 "now",
1845 "nth_value",
1846 "ntile",
1847 "nullcols",
1848 "nullif",
1849 "object",
1850 "octet_length",
1851 "offsets",
1852 "online",
1853 "optimizer",
1854 "orphan",
1855 "parquet",
1856 "partitions",
1857 "pause",
1858 "percentile_cont",
1859 "percentile_disc",
1860 "periodic",
1861 "persisted",
1862 "pi",
1863 "pipeline",
1864 "pipelines",
1865 "plancache",
1866 "plugins",
1867 "pool",
1868 "pools",
1869 "pow",
1870 "power",
1871 "process",
1872 "processlist",
1873 "profile",
1874 "profiles",
1875 "quarter",
1876 "queries",
1877 "query",
1878 "radians",
1879 "rand",
1880 "record",
1881 "reduce",
1882 "redundancy",
1883 "regexp_match",
1884 "regexp_substr",
1885 "remote",
1886 "replication",
1887 "resource",
1888 "resource_pool",
1889 "restore",
1890 "retry",
1891 "role",
1892 "roles",
1893 "round",
1894 "rpad",
1895 "rtrim",
1896 "running",
1897 "s3",
1898 "scalar",
1899 "sec_to_time",
1900 "second",
1901 "security_lists_intersect",
1902 "semi_join",
1903 "sha",
1904 "sha1",
1905 "sha2",
1906 "shard",
1907 "sharded",
1908 "sharded_id",
1909 "sigmoid",
1910 "sign",
1911 "sin",
1912 "skip",
1913 "sleep",
1914 "snapshot",
1915 "soname",
1916 "sparse",
1917 "spatial_check_index",
1918 "split",
1919 "sqrt",
1920 "standalone",
1921 "std",
1922 "stddev",
1923 "stddev_pop",
1924 "stddev_samp",
1925 "stop",
1926 "str_to_date",
1927 "subdate",
1928 "substr",
1929 "substring_index",
1930 "success",
1931 "synchronize",
1932 "table_checksum",
1933 "tan",
1934 "task",
1935 "timediff",
1936 "time_bucket",
1937 "time_format",
1938 "time_to_sec",
1939 "timestampadd",
1940 "timestampdiff",
1941 "to_base64",
1942 "to_char",
1943 "to_date",
1944 "to_days",
1945 "to_json",
1946 "to_number",
1947 "to_seconds",
1948 "to_timestamp",
1949 "tracelogs",
1950 "transform",
1951 "trim",
1952 "trunc",
1953 "truncate",
1954 "ucase",
1955 "unhex",
1956 "unix_timestamp",
1957 "utc_date",
1958 "utc_time",
1959 "utc_timestamp",
1960 "vacuum",
1961 "variance",
1962 "var_pop",
1963 "var_samp",
1964 "vector_sub",
1965 "voting",
1966 "week",
1967 "weekday",
1968 "weekofyear",
1969 "workload",
1970 "year",
1971 ]);
1972 set.remove("all");
1974 set
1975 });
1976
1977 pub static SQLITE_RESERVED: LazyLock<HashSet<&'static str>> = LazyLock::new(|| {
1981 [
1983 "abort",
1984 "action",
1985 "add",
1986 "after",
1987 "all",
1988 "alter",
1989 "always",
1990 "analyze",
1991 "and",
1992 "as",
1993 "asc",
1994 "attach",
1995 "autoincrement",
1996 "before",
1997 "begin",
1998 "between",
1999 "by",
2000 "cascade",
2001 "case",
2002 "cast",
2003 "check",
2004 "collate",
2005 "column",
2006 "commit",
2007 "conflict",
2008 "constraint",
2009 "create",
2010 "cross",
2011 "current",
2012 "current_date",
2013 "current_time",
2014 "current_timestamp",
2015 "database",
2016 "default",
2017 "deferrable",
2018 "deferred",
2019 "delete",
2020 "desc",
2021 "detach",
2022 "distinct",
2023 "do",
2024 "drop",
2025 "each",
2026 "else",
2027 "end",
2028 "escape",
2029 "except",
2030 "exclude",
2031 "exclusive",
2032 "exists",
2033 "explain",
2034 "fail",
2035 "filter",
2036 "first",
2037 "following",
2038 "for",
2039 "foreign",
2040 "from",
2041 "full",
2042 "generated",
2043 "glob",
2044 "group",
2045 "groups",
2046 "having",
2047 "if",
2048 "ignore",
2049 "immediate",
2050 "in",
2051 "index",
2052 "indexed",
2053 "initially",
2054 "inner",
2055 "insert",
2056 "instead",
2057 "intersect",
2058 "into",
2059 "is",
2060 "isnull",
2061 "join",
2062 "key",
2063 "last",
2064 "left",
2065 "like",
2066 "limit",
2067 "natural",
2068 "no",
2069 "not",
2070 "nothing",
2071 "notnull",
2072 "null",
2073 "nulls",
2074 "of",
2075 "offset",
2076 "on",
2077 "or",
2078 "order",
2079 "others",
2080 "outer",
2081 "partition",
2082 "plan",
2083 "pragma",
2084 "preceding",
2085 "primary",
2086 "query",
2087 "raise",
2088 "range",
2089 "recursive",
2090 "references",
2091 "regexp",
2092 "reindex",
2093 "release",
2094 "rename",
2095 "replace",
2096 "restrict",
2097 "returning",
2098 "right",
2099 "rollback",
2100 "row",
2101 "rows",
2102 "savepoint",
2103 "select",
2104 "set",
2105 "table",
2106 "temp",
2107 "temporary",
2108 "then",
2109 "ties",
2110 "to",
2111 "transaction",
2112 "trigger",
2113 "unbounded",
2114 "union",
2115 "unique",
2116 "update",
2117 "using",
2118 "vacuum",
2119 "values",
2120 "view",
2121 "virtual",
2122 "when",
2123 "where",
2124 "window",
2125 "with",
2126 "without",
2127 ]
2128 .into_iter()
2129 .collect()
2130 });
2131}
2132
2133impl Generator {
2134 pub fn new() -> Self {
2140 Self::with_config(GeneratorConfig::default())
2141 }
2142
2143 pub fn with_config(config: GeneratorConfig) -> Self {
2148 Self::with_arc_config(Arc::new(config))
2149 }
2150
2151 pub(crate) fn with_arc_config(config: Arc<GeneratorConfig>) -> Self {
2156 Self {
2157 config,
2158 output: String::new(),
2159 unsupported_messages: Vec::new(),
2160 indent_level: 0,
2161 athena_hive_context: false,
2162 sqlite_inline_pk_columns: std::collections::HashSet::new(),
2163 merge_strip_qualifiers: Vec::new(),
2164 clickhouse_nullable_depth: 0,
2165 }
2166 }
2167
2168 fn add_column_aliases_to_query(expr: Expression) -> Expression {
2172 match expr {
2173 Expression::Select(mut select) => {
2174 select.expressions = select
2176 .expressions
2177 .into_iter()
2178 .map(|e| Self::add_alias_to_expression(e))
2179 .collect();
2180
2181 if let Some(ref mut from) = select.from {
2183 from.expressions = from
2184 .expressions
2185 .iter()
2186 .cloned()
2187 .map(|e| Self::add_column_aliases_to_query(e))
2188 .collect();
2189 }
2190
2191 Expression::Select(select)
2192 }
2193 Expression::Subquery(mut sq) => {
2194 sq.this = Self::add_column_aliases_to_query(sq.this);
2195 Expression::Subquery(sq)
2196 }
2197 Expression::Paren(mut p) => {
2198 p.this = Self::add_column_aliases_to_query(p.this);
2199 Expression::Paren(p)
2200 }
2201 other => other,
2203 }
2204 }
2205
2206 fn add_alias_to_expression(expr: Expression) -> Expression {
2209 use crate::expressions::Alias;
2210
2211 match &expr {
2212 Expression::Alias(_) => expr,
2214
2215 Expression::Column(col) => Expression::Alias(Box::new(Alias {
2217 this: expr.clone(),
2218 alias: col.name.clone(),
2219 column_aliases: Vec::new(),
2220 alias_explicit_as: false,
2221 alias_keyword: None,
2222 pre_alias_comments: Vec::new(),
2223 trailing_comments: Vec::new(),
2224 inferred_type: None,
2225 })),
2226
2227 Expression::Identifier(ident) => Expression::Alias(Box::new(Alias {
2229 this: expr.clone(),
2230 alias: ident.clone(),
2231 column_aliases: Vec::new(),
2232 alias_explicit_as: false,
2233 alias_keyword: None,
2234 pre_alias_comments: Vec::new(),
2235 trailing_comments: Vec::new(),
2236 inferred_type: None,
2237 })),
2238
2239 Expression::Subquery(sq) => {
2241 let processed = Self::add_column_aliases_to_query(Expression::Subquery(sq.clone()));
2242 if sq.alias.is_some() {
2244 processed
2245 } else {
2246 processed
2248 }
2249 }
2250
2251 Expression::Star(_) => expr,
2253
2254 _ => expr,
2257 }
2258 }
2259
2260 fn try_evaluate_constant(expr: &Expression) -> Option<i64> {
2264 match expr {
2265 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
2266 let Literal::Number(n) = lit.as_ref() else {
2267 unreachable!()
2268 };
2269 n.parse::<i64>().ok()
2270 }
2271 Expression::Add(op) => {
2272 let left = Self::try_evaluate_constant(&op.left)?;
2273 let right = Self::try_evaluate_constant(&op.right)?;
2274 Some(left + right)
2275 }
2276 Expression::Sub(op) => {
2277 let left = Self::try_evaluate_constant(&op.left)?;
2278 let right = Self::try_evaluate_constant(&op.right)?;
2279 Some(left - right)
2280 }
2281 Expression::Mul(op) => {
2282 let left = Self::try_evaluate_constant(&op.left)?;
2283 let right = Self::try_evaluate_constant(&op.right)?;
2284 Some(left * right)
2285 }
2286 Expression::Div(op) => {
2287 let left = Self::try_evaluate_constant(&op.left)?;
2288 let right = Self::try_evaluate_constant(&op.right)?;
2289 if right != 0 {
2290 Some(left / right)
2291 } else {
2292 None
2293 }
2294 }
2295 Expression::Paren(p) => Self::try_evaluate_constant(&p.this),
2296 _ => None,
2297 }
2298 }
2299
2300 fn is_reserved_keyword(&self, name: &str) -> bool {
2302 use crate::dialects::DialectType;
2303 let mut buf = [0u8; 128];
2304 let lower_ref: &str = if name.len() <= 128 {
2305 for (i, b) in name.bytes().enumerate() {
2306 buf[i] = b.to_ascii_lowercase();
2307 }
2308 std::str::from_utf8(&buf[..name.len()]).unwrap_or(name)
2310 } else {
2311 return false;
2312 };
2313
2314 match self.config.dialect {
2315 Some(DialectType::BigQuery) => reserved_keywords::BIGQUERY_RESERVED.contains(lower_ref),
2316 Some(DialectType::MySQL) | Some(DialectType::TiDB) => {
2317 reserved_keywords::MYSQL_RESERVED.contains(lower_ref)
2318 }
2319 Some(DialectType::Doris) => reserved_keywords::DORIS_RESERVED.contains(lower_ref),
2320 Some(DialectType::SingleStore) => {
2321 reserved_keywords::SINGLESTORE_RESERVED.contains(lower_ref)
2322 }
2323 Some(DialectType::StarRocks) => {
2324 reserved_keywords::STARROCKS_RESERVED.contains(lower_ref)
2325 }
2326 Some(DialectType::PostgreSQL)
2327 | Some(DialectType::CockroachDB)
2328 | Some(DialectType::Materialize)
2329 | Some(DialectType::RisingWave) => {
2330 reserved_keywords::POSTGRES_RESERVED.contains(lower_ref)
2331 }
2332 Some(DialectType::Redshift) => reserved_keywords::REDSHIFT_RESERVED.contains(lower_ref),
2333 Some(DialectType::Snowflake) => false,
2336 Some(DialectType::ClickHouse) => false,
2338 Some(DialectType::DuckDB) => reserved_keywords::DUCKDB_RESERVED.contains(lower_ref),
2339 Some(DialectType::Teradata) => false,
2341 Some(DialectType::TSQL)
2343 | Some(DialectType::Fabric)
2344 | Some(DialectType::Oracle)
2345 | Some(DialectType::Spark)
2346 | Some(DialectType::Databricks)
2347 | Some(DialectType::Hive)
2348 | Some(DialectType::Solr) => false,
2349 Some(DialectType::Presto) | Some(DialectType::Trino) | Some(DialectType::Athena) => {
2350 reserved_keywords::PRESTO_TRINO_RESERVED.contains(lower_ref)
2351 }
2352 Some(DialectType::SQLite) => reserved_keywords::SQLITE_RESERVED.contains(lower_ref),
2353 Some(DialectType::Generic) | None => false,
2355 _ => reserved_keywords::SQL_RESERVED.contains(lower_ref),
2357 }
2358 }
2359
2360 fn normalize_func_name<'a>(&self, name: &'a str) -> Cow<'a, str> {
2362 match self.config.normalize_functions {
2363 NormalizeFunctions::Upper => Cow::Owned(name.to_ascii_uppercase()),
2364 NormalizeFunctions::Lower => Cow::Owned(name.to_ascii_lowercase()),
2365 NormalizeFunctions::None => Cow::Borrowed(name),
2366 }
2367 }
2368
2369 pub fn generate(&mut self, expr: &Expression) -> Result<String> {
2378 self.output.clear();
2379 self.unsupported_messages.clear();
2380 enforce_generate_ast(expr, &self.config.complexity_guard)?;
2381 self.generate_expression(expr)?;
2382 if self.config.unsupported_level == UnsupportedLevel::Raise
2383 && !self.unsupported_messages.is_empty()
2384 {
2385 return Err(crate::error::Error::generate(
2386 self.format_unsupported_messages(),
2387 ));
2388 }
2389 Ok(std::mem::take(&mut self.output))
2390 }
2391
2392 pub fn unsupported_messages(&self) -> &[String] {
2394 &self.unsupported_messages
2395 }
2396
2397 fn unsupported(&mut self, message: impl Into<String>) -> Result<()> {
2398 let message = message.into();
2399 if self.config.unsupported_level == UnsupportedLevel::Immediate {
2400 return Err(crate::error::Error::generate(message));
2401 }
2402 self.unsupported_messages.push(message);
2403 Ok(())
2404 }
2405
2406 fn write_unsupported_comment(&mut self, message: &str) -> Result<()> {
2407 self.unsupported(message.to_string())?;
2408 self.write("/* ");
2409 self.write(message);
2410 self.write(" */");
2411 Ok(())
2412 }
2413
2414 fn format_unsupported_messages(&self) -> String {
2415 let limit = self.config.max_unsupported.max(1);
2416 if self.unsupported_messages.len() <= limit {
2417 return self.unsupported_messages.join("; ");
2418 }
2419
2420 let mut messages = self
2421 .unsupported_messages
2422 .iter()
2423 .take(limit)
2424 .cloned()
2425 .collect::<Vec<_>>();
2426 messages.push(format!(
2427 "... and {} more",
2428 self.unsupported_messages.len() - limit
2429 ));
2430 messages.join("; ")
2431 }
2432
2433 pub fn sql(expr: &Expression) -> Result<String> {
2439 let mut gen = Generator::new();
2440 gen.generate(expr)
2441 }
2442
2443 pub fn pretty_sql(expr: &Expression) -> Result<String> {
2448 let config = GeneratorConfig {
2449 pretty: true,
2450 ..Default::default()
2451 };
2452 let mut gen = Generator::with_config(config);
2453 let mut sql = gen.generate(expr)?;
2454 if !sql.ends_with(';') {
2456 sql.push(';');
2457 }
2458 Ok(sql)
2459 }
2460
2461 fn generate_expression(&mut self, expr: &Expression) -> Result<()> {
2462 #[cfg(feature = "stacker")]
2463 {
2464 let red_zone = if cfg!(debug_assertions) {
2465 4 * 1024 * 1024
2466 } else {
2467 1024 * 1024
2468 };
2469 stacker::maybe_grow(red_zone, 8 * 1024 * 1024, || {
2470 self.generate_expression_inner(expr)
2471 })
2472 }
2473 #[cfg(not(feature = "stacker"))]
2474 {
2475 self.generate_expression_inner(expr)
2476 }
2477 }
2478
2479 fn generate_expression_inner(&mut self, expr: &Expression) -> Result<()> {
2480 match expr {
2481 Expression::Select(select) => self.generate_select(select),
2482 Expression::Union(union) => self.generate_union(union),
2483 Expression::Intersect(intersect) => self.generate_intersect(intersect),
2484 Expression::Except(except) => self.generate_except(except),
2485 Expression::Insert(insert) => self.generate_insert(insert),
2486 Expression::Update(update) => self.generate_update(update),
2487 Expression::Delete(delete) => self.generate_delete(delete),
2488 Expression::Literal(lit) => self.generate_literal(lit),
2489 Expression::Boolean(b) => self.generate_boolean(b),
2490 Expression::Null(_) => {
2491 self.write_keyword("NULL");
2492 Ok(())
2493 }
2494 Expression::Identifier(id) => self.generate_identifier(id),
2495 Expression::Column(col) => self.generate_column(col),
2496 Expression::Pseudocolumn(pc) => self.generate_pseudocolumn(pc),
2497 Expression::Connect(c) => self.generate_connect_expr(c),
2498 Expression::Prior(p) => self.generate_prior(p),
2499 Expression::ConnectByRoot(cbr) => self.generate_connect_by_root(cbr),
2500 Expression::MatchRecognize(mr) => self.generate_match_recognize(mr),
2501 Expression::Table(table) => self.generate_table(table),
2502 Expression::StageReference(sr) => self.generate_stage_reference(sr),
2503 Expression::HistoricalData(hd) => self.generate_historical_data(hd),
2504 Expression::JoinedTable(jt) => self.generate_joined_table(jt),
2505 Expression::Star(star) => self.generate_star(star),
2506 Expression::BracedWildcard(expr) => self.generate_braced_wildcard(expr),
2507 Expression::Alias(alias) => self.generate_alias(alias),
2508 Expression::Cast(cast) => self.generate_cast(cast),
2509 Expression::Collation(coll) => self.generate_collation(coll),
2510 Expression::Case(case) => self.generate_case(case),
2511 Expression::Function(func) => self.generate_function(func),
2512 Expression::FunctionEmits(fe) => self.generate_function_emits(fe),
2513 Expression::AggregateFunction(func) => self.generate_aggregate_function(func),
2514 Expression::WindowFunction(wf) => self.generate_window_function(wf),
2515 Expression::WithinGroup(wg) => self.generate_within_group(wg),
2516 Expression::Interval(interval) => self.generate_interval(interval),
2517
2518 Expression::ConcatWs(f) => self.generate_concat_ws(f),
2520 Expression::Substring(f) => self.generate_substring(f),
2521 Expression::Upper(f) => self.generate_unary_func("UPPER", f),
2522 Expression::Lower(f) => self.generate_unary_func("LOWER", f),
2523 Expression::Length(f) => {
2524 let name = match self.config.dialect {
2525 Some(DialectType::TSQL) | Some(DialectType::Fabric) => "LEN",
2526 _ => "LENGTH",
2527 };
2528 self.generate_unary_func(name, f)
2529 }
2530 Expression::Trim(f) => self.generate_trim(f),
2531 Expression::LTrim(f) => self.generate_simple_func("LTRIM", &f.this),
2532 Expression::RTrim(f) => self.generate_simple_func("RTRIM", &f.this),
2533 Expression::Replace(f) => self.generate_replace(f),
2534 Expression::Reverse(f) => self.generate_simple_func("REVERSE", &f.this),
2535 Expression::Left(f) => self.generate_left_right("LEFT", f),
2536 Expression::Right(f) => self.generate_left_right("RIGHT", f),
2537 Expression::Repeat(f) => self.generate_repeat(f),
2538 Expression::Lpad(f) => self.generate_pad("LPAD", f),
2539 Expression::Rpad(f) => self.generate_pad("RPAD", f),
2540 Expression::Split(f) => self.generate_split(f),
2541 Expression::RegexpLike(f) => self.generate_regexp_like(f),
2542 Expression::RegexpReplace(f) => self.generate_regexp_replace(f),
2543 Expression::RegexpExtract(f) => self.generate_regexp_extract(f),
2544 Expression::Overlay(f) => self.generate_overlay(f),
2545
2546 Expression::Abs(f) => self.generate_simple_func("ABS", &f.this),
2548 Expression::Round(f) => self.generate_round(f),
2549 Expression::Floor(f) => self.generate_floor(f),
2550 Expression::Ceil(f) => self.generate_ceil(f),
2551 Expression::Power(f) => self.generate_power(f),
2552 Expression::Sqrt(f) => self.generate_sqrt_cbrt(f, "SQRT", "|/"),
2553 Expression::Cbrt(f) => self.generate_sqrt_cbrt(f, "CBRT", "||/"),
2554 Expression::Ln(f) => self.generate_simple_func("LN", &f.this),
2555 Expression::Log(f) => self.generate_log(f),
2556 Expression::Exp(f) => self.generate_simple_func("EXP", &f.this),
2557 Expression::Sign(f) => self.generate_simple_func("SIGN", &f.this),
2558 Expression::Greatest(f) => self.generate_vararg_func("GREATEST", &f.expressions),
2559 Expression::Least(f) => self.generate_vararg_func("LEAST", &f.expressions),
2560
2561 Expression::CurrentDate(_) => {
2563 self.write_keyword("CURRENT_DATE");
2564 Ok(())
2565 }
2566 Expression::CurrentTime(f) => self.generate_current_time(f),
2567 Expression::CurrentTimestamp(f) => self.generate_current_timestamp(f),
2568 Expression::AtTimeZone(f) => self.generate_at_time_zone(f),
2569 Expression::DateAdd(f) => self.generate_date_add(f, "DATE_ADD"),
2570 Expression::DateSub(f) => self.generate_date_add(f, "DATE_SUB"),
2571 Expression::DateDiff(f) => self.generate_datediff(f),
2572 Expression::DateTrunc(f) => self.generate_date_trunc(f),
2573 Expression::Extract(f) => self.generate_extract(f),
2574 Expression::ToDate(f) => self.generate_to_date(f),
2575 Expression::ToTimestamp(f) => self.generate_to_timestamp(f),
2576
2577 Expression::Coalesce(f) => {
2579 let func_name = f.original_name.as_deref().unwrap_or("COALESCE");
2581 self.generate_vararg_func(func_name, &f.expressions)
2582 }
2583 Expression::NullIf(f) => self.generate_binary_func("NULLIF", &f.this, &f.expression),
2584 Expression::IfFunc(f) => self.generate_if_func(f),
2585 Expression::IfNull(f) => self.generate_ifnull(f),
2586 Expression::Nvl(f) => self.generate_nvl(f),
2587 Expression::Nvl2(f) => self.generate_nvl2(f),
2588
2589 Expression::TryCast(cast) => self.generate_try_cast(cast),
2591 Expression::SafeCast(cast) => self.generate_safe_cast(cast),
2592
2593 Expression::Count(f) => self.generate_count(f),
2595 Expression::Sum(f) => self.generate_agg_func("SUM", f),
2596 Expression::Avg(f) => self.generate_agg_func("AVG", f),
2597 Expression::Min(f) => self.generate_agg_func("MIN", f),
2598 Expression::Max(f) => self.generate_agg_func("MAX", f),
2599 Expression::GroupConcat(f) => self.generate_group_concat(f),
2600 Expression::StringAgg(f) => self.generate_string_agg(f),
2601 Expression::ListAgg(f) => self.generate_listagg(f),
2602 Expression::ArrayAgg(f) => {
2603 let override_name = f
2606 .name
2607 .as_ref()
2608 .filter(|n| !n.eq_ignore_ascii_case("ARRAY_AGG"))
2609 .map(|n| n.to_ascii_uppercase());
2610 match override_name {
2611 Some(name) => self.generate_agg_func(&name, f),
2612 None => self.generate_agg_func("ARRAY_AGG", f),
2613 }
2614 }
2615 Expression::ArrayConcatAgg(f) => self.generate_agg_func("ARRAY_CONCAT_AGG", f),
2616 Expression::CountIf(f) => self.generate_agg_func("COUNT_IF", f),
2617 Expression::SumIf(f) => self.generate_sum_if(f),
2618 Expression::Stddev(f) => self.generate_agg_func("STDDEV", f),
2619 Expression::StddevPop(f) => self.generate_agg_func("STDDEV_POP", f),
2620 Expression::StddevSamp(f) => self.generate_stddev_samp(f),
2621 Expression::Variance(f) => self.generate_agg_func("VARIANCE", f),
2622 Expression::VarPop(f) => {
2623 let name = if matches!(self.config.dialect, Some(DialectType::Snowflake)) {
2624 "VARIANCE_POP"
2625 } else {
2626 "VAR_POP"
2627 };
2628 self.generate_agg_func(name, f)
2629 }
2630 Expression::VarSamp(f) => self.generate_agg_func("VAR_SAMP", f),
2631 Expression::Skewness(f) => {
2632 let name = match self.config.dialect {
2633 Some(DialectType::Snowflake) => "SKEW",
2634 _ => "SKEWNESS",
2635 };
2636 self.generate_agg_func(name, f)
2637 }
2638 Expression::Median(f) => self.generate_agg_func("MEDIAN", f),
2639 Expression::Mode(f) => self.generate_agg_func("MODE", f),
2640 Expression::First(f) => self.generate_agg_func_with_ignore_nulls_bool("FIRST", f),
2641 Expression::Last(f) => self.generate_agg_func_with_ignore_nulls_bool("LAST", f),
2642 Expression::AnyValue(f) => self.generate_agg_func("ANY_VALUE", f),
2643 Expression::ApproxDistinct(f) => {
2644 match self.config.dialect {
2645 Some(DialectType::Hive)
2646 | Some(DialectType::Spark)
2647 | Some(DialectType::Databricks)
2648 | Some(DialectType::BigQuery) => {
2649 self.generate_agg_func("APPROX_COUNT_DISTINCT", f)
2651 }
2652 Some(DialectType::Redshift) => {
2653 self.write_keyword("APPROXIMATE COUNT");
2655 self.write("(");
2656 self.write_keyword("DISTINCT");
2657 self.write(" ");
2658 self.generate_expression(&f.this)?;
2659 self.write(")");
2660 Ok(())
2661 }
2662 _ => self.generate_agg_func("APPROX_DISTINCT", f),
2663 }
2664 }
2665 Expression::ApproxCountDistinct(f) => {
2666 self.generate_agg_func("APPROX_COUNT_DISTINCT", f)
2667 }
2668 Expression::ApproxPercentile(f) => self.generate_approx_percentile(f),
2669 Expression::Percentile(f) => self.generate_percentile("PERCENTILE", f),
2670 Expression::LogicalAnd(f) => {
2671 let name = match self.config.dialect {
2672 Some(DialectType::Snowflake) => "BOOLAND_AGG",
2673 Some(DialectType::Spark)
2674 | Some(DialectType::Databricks)
2675 | Some(DialectType::PostgreSQL)
2676 | Some(DialectType::DuckDB)
2677 | Some(DialectType::Redshift) => "BOOL_AND",
2678 Some(DialectType::Oracle)
2679 | Some(DialectType::SQLite)
2680 | Some(DialectType::MySQL) => "MIN",
2681 _ => "BOOL_AND",
2682 };
2683 self.generate_agg_func(name, f)
2684 }
2685 Expression::LogicalOr(f) => {
2686 let name = match self.config.dialect {
2687 Some(DialectType::Snowflake) => "BOOLOR_AGG",
2688 Some(DialectType::Spark)
2689 | Some(DialectType::Databricks)
2690 | Some(DialectType::PostgreSQL)
2691 | Some(DialectType::DuckDB)
2692 | Some(DialectType::Redshift) => "BOOL_OR",
2693 Some(DialectType::Oracle)
2694 | Some(DialectType::SQLite)
2695 | Some(DialectType::MySQL) => "MAX",
2696 _ => "BOOL_OR",
2697 };
2698 self.generate_agg_func(name, f)
2699 }
2700
2701 Expression::RowNumber(_) => {
2703 if self.config.dialect == Some(DialectType::ClickHouse) {
2704 self.write("row_number");
2705 } else {
2706 self.write_keyword("ROW_NUMBER");
2707 }
2708 self.write("()");
2709 Ok(())
2710 }
2711 Expression::Rank(r) => {
2712 self.write_keyword("RANK");
2713 self.write("(");
2714 if !r.args.is_empty() {
2716 for (i, arg) in r.args.iter().enumerate() {
2717 if i > 0 {
2718 self.write(", ");
2719 }
2720 self.generate_expression(arg)?;
2721 }
2722 } else if let Some(order_by) = &r.order_by {
2723 self.write_keyword(" ORDER BY ");
2725 for (i, ob) in order_by.iter().enumerate() {
2726 if i > 0 {
2727 self.write(", ");
2728 }
2729 self.generate_ordered(ob)?;
2730 }
2731 }
2732 self.write(")");
2733 Ok(())
2734 }
2735 Expression::DenseRank(dr) => {
2736 self.write_keyword("DENSE_RANK");
2737 self.write("(");
2738 for (i, arg) in dr.args.iter().enumerate() {
2740 if i > 0 {
2741 self.write(", ");
2742 }
2743 self.generate_expression(arg)?;
2744 }
2745 self.write(")");
2746 Ok(())
2747 }
2748 Expression::NTile(f) => self.generate_ntile(f),
2749 Expression::Lead(f) => self.generate_lead_lag("LEAD", f),
2750 Expression::Lag(f) => self.generate_lead_lag("LAG", f),
2751 Expression::FirstValue(f) => {
2752 self.generate_value_func_with_ignore_nulls_bool("FIRST_VALUE", f)
2753 }
2754 Expression::LastValue(f) => {
2755 self.generate_value_func_with_ignore_nulls_bool("LAST_VALUE", f)
2756 }
2757 Expression::NthValue(f) => self.generate_nth_value(f),
2758 Expression::PercentRank(pr) => {
2759 self.write_keyword("PERCENT_RANK");
2760 self.write("(");
2761 if !pr.args.is_empty() {
2763 for (i, arg) in pr.args.iter().enumerate() {
2764 if i > 0 {
2765 self.write(", ");
2766 }
2767 self.generate_expression(arg)?;
2768 }
2769 } else if let Some(order_by) = &pr.order_by {
2770 self.write_keyword(" ORDER BY ");
2772 for (i, ob) in order_by.iter().enumerate() {
2773 if i > 0 {
2774 self.write(", ");
2775 }
2776 self.generate_ordered(ob)?;
2777 }
2778 }
2779 self.write(")");
2780 Ok(())
2781 }
2782 Expression::CumeDist(cd) => {
2783 self.write_keyword("CUME_DIST");
2784 self.write("(");
2785 if !cd.args.is_empty() {
2787 for (i, arg) in cd.args.iter().enumerate() {
2788 if i > 0 {
2789 self.write(", ");
2790 }
2791 self.generate_expression(arg)?;
2792 }
2793 } else if let Some(order_by) = &cd.order_by {
2794 self.write_keyword(" ORDER BY ");
2796 for (i, ob) in order_by.iter().enumerate() {
2797 if i > 0 {
2798 self.write(", ");
2799 }
2800 self.generate_ordered(ob)?;
2801 }
2802 }
2803 self.write(")");
2804 Ok(())
2805 }
2806 Expression::PercentileCont(f) => self.generate_percentile("PERCENTILE_CONT", f),
2807 Expression::PercentileDisc(f) => self.generate_percentile("PERCENTILE_DISC", f),
2808
2809 Expression::Contains(f) => {
2811 self.generate_binary_func("CONTAINS", &f.this, &f.expression)
2812 }
2813 Expression::StartsWith(f) => {
2814 let name = match self.config.dialect {
2815 Some(DialectType::Spark) | Some(DialectType::Databricks) => "STARTSWITH",
2816 _ => "STARTS_WITH",
2817 };
2818 self.generate_binary_func(name, &f.this, &f.expression)
2819 }
2820 Expression::EndsWith(f) => {
2821 let name = match self.config.dialect {
2822 Some(DialectType::Snowflake) => "ENDSWITH",
2823 Some(DialectType::Spark) | Some(DialectType::Databricks) => "ENDSWITH",
2824 Some(DialectType::ClickHouse) => "endsWith",
2825 _ => "ENDS_WITH",
2826 };
2827 self.generate_binary_func(name, &f.this, &f.expression)
2828 }
2829 Expression::Position(f) => self.generate_position(f),
2830 Expression::Initcap(f) => match self.config.dialect {
2831 Some(DialectType::Presto)
2832 | Some(DialectType::Trino)
2833 | Some(DialectType::Athena) => {
2834 self.write_keyword("REGEXP_REPLACE");
2835 self.write("(");
2836 self.generate_expression(&f.this)?;
2837 self.write(", '(\\w)(\\w*)', x -> UPPER(x[1]) || LOWER(x[2]))");
2838 Ok(())
2839 }
2840 _ => self.generate_simple_func("INITCAP", &f.this),
2841 },
2842 Expression::Ascii(f) => self.generate_simple_func("ASCII", &f.this),
2843 Expression::Chr(f) => self.generate_simple_func("CHR", &f.this),
2844 Expression::CharFunc(f) => self.generate_char_func(f),
2845 Expression::Soundex(f) => self.generate_simple_func("SOUNDEX", &f.this),
2846 Expression::Levenshtein(f) => {
2847 self.generate_binary_func("LEVENSHTEIN", &f.this, &f.expression)
2848 }
2849
2850 Expression::ModFunc(f) => self.generate_mod_func(f),
2852 Expression::Random(_) => {
2853 self.write_keyword("RANDOM");
2854 self.write("()");
2855 Ok(())
2856 }
2857 Expression::Rand(f) => self.generate_rand(f),
2858 Expression::TruncFunc(f) => self.generate_truncate_func(f),
2859 Expression::Pi(_) => {
2860 self.write_keyword("PI");
2861 self.write("()");
2862 Ok(())
2863 }
2864 Expression::Radians(f) => self.generate_simple_func("RADIANS", &f.this),
2865 Expression::Degrees(f) => self.generate_simple_func("DEGREES", &f.this),
2866 Expression::Sin(f) => self.generate_simple_func("SIN", &f.this),
2867 Expression::Cos(f) => self.generate_simple_func("COS", &f.this),
2868 Expression::Tan(f) => self.generate_simple_func("TAN", &f.this),
2869 Expression::Asin(f) => self.generate_simple_func("ASIN", &f.this),
2870 Expression::Acos(f) => self.generate_simple_func("ACOS", &f.this),
2871 Expression::Atan(f) => self.generate_simple_func("ATAN", &f.this),
2872 Expression::Atan2(f) => {
2873 let name = f.original_name.as_deref().unwrap_or("ATAN2");
2874 self.generate_binary_func(name, &f.this, &f.expression)
2875 }
2876
2877 Expression::Decode(f) => self.generate_decode(f),
2879
2880 Expression::DateFormat(f) => self.generate_date_format("DATE_FORMAT", f),
2882 Expression::FormatDate(f) => self.generate_date_format("FORMAT_DATE", f),
2883 Expression::Year(f) => self.generate_simple_func("YEAR", &f.this),
2884 Expression::Month(f) => self.generate_simple_func("MONTH", &f.this),
2885 Expression::Day(f) => self.generate_simple_func("DAY", &f.this),
2886 Expression::Hour(f) => self.generate_simple_func("HOUR", &f.this),
2887 Expression::Minute(f) => self.generate_simple_func("MINUTE", &f.this),
2888 Expression::Second(f) => self.generate_simple_func("SECOND", &f.this),
2889 Expression::DayOfWeek(f) => {
2890 let name = match self.config.dialect {
2891 Some(DialectType::Presto)
2892 | Some(DialectType::Trino)
2893 | Some(DialectType::Athena) => "DAY_OF_WEEK",
2894 Some(DialectType::DuckDB) => "ISODOW",
2895 _ => "DAYOFWEEK",
2896 };
2897 self.generate_simple_func(name, &f.this)
2898 }
2899 Expression::DayOfMonth(f) => {
2900 let name = match self.config.dialect {
2901 Some(DialectType::Presto)
2902 | Some(DialectType::Trino)
2903 | Some(DialectType::Athena) => "DAY_OF_MONTH",
2904 _ => "DAYOFMONTH",
2905 };
2906 self.generate_simple_func(name, &f.this)
2907 }
2908 Expression::DayOfYear(f) => {
2909 let name = match self.config.dialect {
2910 Some(DialectType::Presto)
2911 | Some(DialectType::Trino)
2912 | Some(DialectType::Athena) => "DAY_OF_YEAR",
2913 _ => "DAYOFYEAR",
2914 };
2915 self.generate_simple_func(name, &f.this)
2916 }
2917 Expression::WeekOfYear(f) => {
2918 let name = match self.config.dialect {
2920 Some(DialectType::Hive)
2921 | Some(DialectType::DuckDB)
2922 | Some(DialectType::Spark)
2923 | Some(DialectType::Databricks)
2924 | Some(DialectType::MySQL) => "WEEKOFYEAR",
2925 _ => "WEEK_OF_YEAR",
2926 };
2927 self.generate_simple_func(name, &f.this)
2928 }
2929 Expression::Quarter(f) => self.generate_simple_func("QUARTER", &f.this),
2930 Expression::AddMonths(f) => {
2931 self.generate_binary_func("ADD_MONTHS", &f.this, &f.expression)
2932 }
2933 Expression::MonthsBetween(f) => {
2934 self.generate_binary_func("MONTHS_BETWEEN", &f.this, &f.expression)
2935 }
2936 Expression::LastDay(f) => self.generate_last_day(f),
2937 Expression::NextDay(f) => self.generate_binary_func("NEXT_DAY", &f.this, &f.expression),
2938 Expression::Epoch(f) => self.generate_simple_func("EPOCH", &f.this),
2939 Expression::EpochMs(f) => self.generate_simple_func("EPOCH_MS", &f.this),
2940 Expression::FromUnixtime(f) => self.generate_from_unixtime(f),
2941 Expression::UnixTimestamp(f) => self.generate_unix_timestamp(f),
2942 Expression::MakeDate(f) => self.generate_make_date(f),
2943 Expression::MakeTimestamp(f) => self.generate_make_timestamp(f),
2944 Expression::TimestampTrunc(f) => self.generate_date_trunc(f),
2945
2946 Expression::ArrayFunc(f) => self.generate_array_constructor(f),
2948 Expression::ArrayLength(f) => self.generate_simple_func("ARRAY_LENGTH", &f.this),
2949 Expression::ArraySize(f) => self.generate_simple_func("ARRAY_SIZE", &f.this),
2950 Expression::Cardinality(f) => self.generate_simple_func("CARDINALITY", &f.this),
2951 Expression::ArrayContains(f) => {
2952 self.generate_binary_func("ARRAY_CONTAINS", &f.this, &f.expression)
2953 }
2954 Expression::ArrayPosition(f) => {
2955 self.generate_binary_func("ARRAY_POSITION", &f.this, &f.expression)
2956 }
2957 Expression::ArrayAppend(f) => {
2958 self.generate_binary_func("ARRAY_APPEND", &f.this, &f.expression)
2959 }
2960 Expression::ArrayPrepend(f) => {
2961 self.generate_binary_func("ARRAY_PREPEND", &f.this, &f.expression)
2962 }
2963 Expression::ArrayConcat(f) => self.generate_vararg_func("ARRAY_CONCAT", &f.expressions),
2964 Expression::ArraySort(f) => self.generate_array_sort(f),
2965 Expression::ArrayReverse(f) => self.generate_simple_func("ARRAY_REVERSE", &f.this),
2966 Expression::ArrayDistinct(f) => self.generate_simple_func("ARRAY_DISTINCT", &f.this),
2967 Expression::ArrayJoin(f) => self.generate_array_join("ARRAY_JOIN", f),
2968 Expression::ArrayToString(f) => self.generate_array_join("ARRAY_TO_STRING", f),
2969 Expression::Unnest(f) => self.generate_unnest(f),
2970 Expression::Explode(f) => self.generate_simple_func("EXPLODE", &f.this),
2971 Expression::ExplodeOuter(f) => self.generate_simple_func("EXPLODE_OUTER", &f.this),
2972 Expression::ArrayFilter(f) => self.generate_array_filter(f),
2973 Expression::ArrayTransform(f) => self.generate_array_transform(f),
2974 Expression::ArrayFlatten(f) => self.generate_simple_func("FLATTEN", &f.this),
2975 Expression::ArrayCompact(f) => {
2976 if matches!(self.config.dialect, Some(DialectType::DuckDB)) {
2977 self.write("LIST_FILTER(");
2979 self.generate_expression(&f.this)?;
2980 self.write(", _u -> NOT _u IS NULL)");
2981 Ok(())
2982 } else {
2983 self.generate_simple_func("ARRAY_COMPACT", &f.this)
2984 }
2985 }
2986 Expression::ArrayIntersect(f) => {
2987 let func_name = f.original_name.as_deref().unwrap_or("ARRAY_INTERSECT");
2988 self.generate_vararg_func(func_name, &f.expressions)
2989 }
2990 Expression::ArrayUnion(f) => {
2991 self.generate_binary_func("ARRAY_UNION", &f.this, &f.expression)
2992 }
2993 Expression::ArrayExcept(f) => {
2994 self.generate_binary_func("ARRAY_EXCEPT", &f.this, &f.expression)
2995 }
2996 Expression::ArrayRemove(f) => {
2997 self.generate_binary_func("ARRAY_REMOVE", &f.this, &f.expression)
2998 }
2999 Expression::ArrayZip(f) => self.generate_vararg_func("ARRAYS_ZIP", &f.expressions),
3000 Expression::Sequence(f) => self.generate_sequence("SEQUENCE", f),
3001 Expression::Generate(f) => self.generate_sequence("GENERATE_SERIES", f),
3002
3003 Expression::StructFunc(f) => self.generate_struct_constructor(f),
3005 Expression::StructExtract(f) => self.generate_struct_extract(f),
3006 Expression::NamedStruct(f) => self.generate_named_struct(f),
3007
3008 Expression::MapFunc(f) => self.generate_map_constructor(f),
3010 Expression::MapFromEntries(f) => self.generate_simple_func("MAP_FROM_ENTRIES", &f.this),
3011 Expression::MapFromArrays(f) => {
3012 self.generate_binary_func("MAP_FROM_ARRAYS", &f.this, &f.expression)
3013 }
3014 Expression::MapKeys(f) => self.generate_simple_func("MAP_KEYS", &f.this),
3015 Expression::MapValues(f) => self.generate_simple_func("MAP_VALUES", &f.this),
3016 Expression::MapContainsKey(f) => {
3017 self.generate_binary_func("MAP_CONTAINS_KEY", &f.this, &f.expression)
3018 }
3019 Expression::MapConcat(f) => self.generate_vararg_func("MAP_CONCAT", &f.expressions),
3020 Expression::ElementAt(f) => {
3021 self.generate_binary_func("ELEMENT_AT", &f.this, &f.expression)
3022 }
3023 Expression::TransformKeys(f) => self.generate_transform_func("TRANSFORM_KEYS", f),
3024 Expression::TransformValues(f) => self.generate_transform_func("TRANSFORM_VALUES", f),
3025
3026 Expression::JsonExtract(f) => self.generate_json_extract("JSON_EXTRACT", f),
3028 Expression::JsonExtractScalar(f) => {
3029 self.generate_json_extract("JSON_EXTRACT_SCALAR", f)
3030 }
3031 Expression::JsonExtractPath(f) => self.generate_json_path("JSON_EXTRACT_PATH", f),
3032 Expression::JsonArray(f) => self.generate_vararg_func("JSON_ARRAY", &f.expressions),
3033 Expression::JsonObject(f) => self.generate_json_object(f),
3034 Expression::JsonQuery(f) => self.generate_json_extract("JSON_QUERY", f),
3035 Expression::JsonValue(f) => self.generate_json_extract("JSON_VALUE", f),
3036 Expression::JsonArrayLength(f) => {
3037 self.generate_simple_func("JSON_ARRAY_LENGTH", &f.this)
3038 }
3039 Expression::JsonKeys(f) => self.generate_simple_func("JSON_KEYS", &f.this),
3040 Expression::JsonType(f) => self.generate_simple_func("JSON_TYPE", &f.this),
3041 Expression::ParseJson(f) => {
3042 let name = match self.config.dialect {
3043 Some(DialectType::Presto)
3044 | Some(DialectType::Trino)
3045 | Some(DialectType::Athena) => "JSON_PARSE",
3046 Some(DialectType::PostgreSQL) | Some(DialectType::Redshift) => {
3047 self.write_keyword("CAST");
3049 self.write("(");
3050 self.generate_expression(&f.this)?;
3051 self.write_keyword(" AS ");
3052 self.write_keyword("JSON");
3053 self.write(")");
3054 return Ok(());
3055 }
3056 Some(DialectType::Spark)
3057 | Some(DialectType::MySQL)
3058 | Some(DialectType::SingleStore)
3059 | Some(DialectType::TiDB)
3060 | Some(DialectType::TSQL) => {
3061 self.generate_expression(&f.this)?;
3063 return Ok(());
3064 }
3065 Some(DialectType::DuckDB) => "JSON",
3066 _ => "PARSE_JSON",
3067 };
3068 self.generate_simple_func(name, &f.this)
3069 }
3070 Expression::ToJson(f) => self.generate_simple_func("TO_JSON", &f.this),
3071 Expression::JsonSet(f) => self.generate_json_modify("JSON_SET", f),
3072 Expression::JsonInsert(f) => self.generate_json_modify("JSON_INSERT", f),
3073 Expression::JsonRemove(f) => self.generate_json_path("JSON_REMOVE", f),
3074 Expression::JsonMergePatch(f) => {
3075 self.generate_binary_func("JSON_MERGE_PATCH", &f.this, &f.expression)
3076 }
3077 Expression::JsonArrayAgg(f) => self.generate_json_array_agg(f),
3078 Expression::JsonObjectAgg(f) => self.generate_json_object_agg(f),
3079
3080 Expression::Convert(f) => self.generate_convert(f),
3082 Expression::Typeof(f) => self.generate_simple_func("TYPEOF", &f.this),
3083
3084 Expression::Lambda(f) => self.generate_lambda(f),
3086 Expression::Parameter(f) => self.generate_parameter(f),
3087 Expression::Placeholder(f) => self.generate_placeholder(f),
3088 Expression::NamedArgument(f) => self.generate_named_argument(f),
3089 Expression::TableArgument(f) => self.generate_table_argument(f),
3090 Expression::SqlComment(f) => self.generate_sql_comment(f),
3091
3092 Expression::NullSafeEq(op) => self.generate_null_safe_eq(op),
3094 Expression::NullSafeNeq(op) => self.generate_null_safe_neq(op),
3095 Expression::Glob(op) => self.generate_binary_op(op, "GLOB"),
3096 Expression::SimilarTo(f) => self.generate_similar_to(f),
3097 Expression::Any(f) => self.generate_quantified("ANY", f),
3098 Expression::All(f) => self.generate_quantified("ALL", f),
3099 Expression::Overlaps(f) => self.generate_overlaps(f),
3100
3101 Expression::BitwiseLeftShift(op) => {
3103 if matches!(
3104 self.config.dialect,
3105 Some(DialectType::Presto) | Some(DialectType::Trino)
3106 ) {
3107 self.write_keyword("BITWISE_LEFT_SHIFT");
3108 self.write("(");
3109 self.generate_expression(&op.left)?;
3110 self.write(", ");
3111 self.generate_expression(&op.right)?;
3112 self.write(")");
3113 Ok(())
3114 } else if matches!(
3115 self.config.dialect,
3116 Some(DialectType::Spark) | Some(DialectType::Databricks)
3117 ) {
3118 self.write_keyword("SHIFTLEFT");
3119 self.write("(");
3120 self.generate_expression(&op.left)?;
3121 self.write(", ");
3122 self.generate_expression(&op.right)?;
3123 self.write(")");
3124 Ok(())
3125 } else {
3126 self.generate_binary_op(op, "<<")
3127 }
3128 }
3129 Expression::BitwiseRightShift(op) => {
3130 if matches!(
3131 self.config.dialect,
3132 Some(DialectType::Presto) | Some(DialectType::Trino)
3133 ) {
3134 self.write_keyword("BITWISE_RIGHT_SHIFT");
3135 self.write("(");
3136 self.generate_expression(&op.left)?;
3137 self.write(", ");
3138 self.generate_expression(&op.right)?;
3139 self.write(")");
3140 Ok(())
3141 } else if matches!(
3142 self.config.dialect,
3143 Some(DialectType::Spark) | Some(DialectType::Databricks)
3144 ) {
3145 self.write_keyword("SHIFTRIGHT");
3146 self.write("(");
3147 self.generate_expression(&op.left)?;
3148 self.write(", ");
3149 self.generate_expression(&op.right)?;
3150 self.write(")");
3151 Ok(())
3152 } else {
3153 self.generate_binary_op(op, ">>")
3154 }
3155 }
3156 Expression::BitwiseAndAgg(f) => self.generate_agg_func("BIT_AND", f),
3157 Expression::BitwiseOrAgg(f) => self.generate_agg_func("BIT_OR", f),
3158 Expression::BitwiseXorAgg(f) => self.generate_agg_func("BIT_XOR", f),
3159
3160 Expression::Subscript(s) => self.generate_subscript(s),
3162 Expression::Dot(d) => self.generate_dot_access(d),
3163 Expression::MethodCall(m) => self.generate_method_call(m),
3164 Expression::ArraySlice(s) => self.generate_array_slice(s),
3165
3166 Expression::And(op) => self.generate_connector_op(op, ConnectorOperator::And),
3167 Expression::Or(op) => self.generate_connector_op(op, ConnectorOperator::Or),
3168 Expression::Add(op) => self.generate_binary_op(op, "+"),
3169 Expression::Sub(op) => self.generate_binary_op(op, "-"),
3170 Expression::Mul(op) => self.generate_binary_op(op, "*"),
3171 Expression::Div(op) => self.generate_binary_op(op, "/"),
3172 Expression::IntDiv(f) => {
3173 use crate::dialects::DialectType;
3174 if matches!(self.config.dialect, Some(DialectType::DuckDB)) {
3175 self.generate_expression(&f.this)?;
3177 self.write(" // ");
3178 self.generate_expression(&f.expression)?;
3179 Ok(())
3180 } else if matches!(
3181 self.config.dialect,
3182 Some(DialectType::Hive | DialectType::Spark | DialectType::Databricks)
3183 ) {
3184 self.generate_expression(&f.this)?;
3186 self.write(" ");
3187 self.write_keyword("DIV");
3188 self.write(" ");
3189 self.generate_expression(&f.expression)?;
3190 Ok(())
3191 } else {
3192 self.write_keyword("DIV");
3194 self.write("(");
3195 self.generate_expression(&f.this)?;
3196 self.write(", ");
3197 self.generate_expression(&f.expression)?;
3198 self.write(")");
3199 Ok(())
3200 }
3201 }
3202 Expression::Mod(op) => {
3203 if matches!(self.config.dialect, Some(DialectType::Teradata)) {
3204 self.generate_binary_op(op, "MOD")
3205 } else {
3206 self.generate_binary_op(op, "%")
3207 }
3208 }
3209 Expression::Eq(op) => self.generate_binary_op(op, "="),
3210 Expression::Neq(op) => self.generate_binary_op(op, "<>"),
3211 Expression::Lt(op) => self.generate_binary_op(op, "<"),
3212 Expression::Lte(op) => self.generate_binary_op(op, "<="),
3213 Expression::Gt(op) => self.generate_binary_op(op, ">"),
3214 Expression::Gte(op) => self.generate_binary_op(op, ">="),
3215 Expression::Like(op) => self.generate_like_op(op, "LIKE"),
3216 Expression::ILike(op) => self.generate_like_op(op, "ILIKE"),
3217 Expression::Match(op) => self.generate_binary_op(op, "MATCH"),
3218 Expression::Concat(op) => {
3219 if self.config.dialect == Some(DialectType::Solr) {
3221 self.generate_binary_op(op, "OR")
3222 } else if self.config.dialect == Some(DialectType::MySQL) {
3223 self.generate_mysql_concat_from_concat(op)
3224 } else {
3225 self.generate_binary_op(op, "||")
3226 }
3227 }
3228 Expression::BitwiseAnd(op) => {
3229 if matches!(
3231 self.config.dialect,
3232 Some(DialectType::Presto) | Some(DialectType::Trino)
3233 ) {
3234 self.write_keyword("BITWISE_AND");
3235 self.write("(");
3236 self.generate_expression(&op.left)?;
3237 self.write(", ");
3238 self.generate_expression(&op.right)?;
3239 self.write(")");
3240 Ok(())
3241 } else {
3242 self.generate_binary_op(op, "&")
3243 }
3244 }
3245 Expression::BitwiseOr(op) => {
3246 if matches!(
3248 self.config.dialect,
3249 Some(DialectType::Presto) | Some(DialectType::Trino)
3250 ) {
3251 self.write_keyword("BITWISE_OR");
3252 self.write("(");
3253 self.generate_expression(&op.left)?;
3254 self.write(", ");
3255 self.generate_expression(&op.right)?;
3256 self.write(")");
3257 Ok(())
3258 } else {
3259 self.generate_binary_op(op, "|")
3260 }
3261 }
3262 Expression::BitwiseXor(op) => {
3263 if matches!(
3265 self.config.dialect,
3266 Some(DialectType::Presto) | Some(DialectType::Trino)
3267 ) {
3268 self.write_keyword("BITWISE_XOR");
3269 self.write("(");
3270 self.generate_expression(&op.left)?;
3271 self.write(", ");
3272 self.generate_expression(&op.right)?;
3273 self.write(")");
3274 Ok(())
3275 } else if matches!(self.config.dialect, Some(DialectType::PostgreSQL)) {
3276 self.generate_binary_op(op, "#")
3277 } else {
3278 self.generate_binary_op(op, "^")
3279 }
3280 }
3281 Expression::Adjacent(op) => self.generate_binary_op(op, "-|-"),
3282 Expression::TsMatch(op) => self.generate_binary_op(op, "@@"),
3283 Expression::PropertyEQ(op) => self.generate_binary_op(op, ":="),
3284 Expression::ArrayContainsAll(op) => self.generate_binary_op(op, "@>"),
3285 Expression::ArrayContainedBy(op) => self.generate_binary_op(op, "<@"),
3286 Expression::ArrayOverlaps(op) => self.generate_binary_op(op, "&&"),
3287 Expression::JSONBContainsAllTopKeys(op) => self.generate_binary_op(op, "?&"),
3288 Expression::JSONBContainsAnyTopKeys(op) => self.generate_binary_op(op, "?|"),
3289 Expression::JSONBContains(f) => {
3290 self.generate_expression(&f.this)?;
3292 self.write_space();
3293 self.write(f.original_name.as_deref().unwrap_or("?"));
3294 self.write_space();
3295 self.generate_expression(&f.expression)
3296 }
3297 Expression::JSONBDeleteAtPath(op) => self.generate_binary_op(op, "#-"),
3298 Expression::ExtendsLeft(op) => self.generate_binary_op(op, "&<"),
3299 Expression::ExtendsRight(op) => self.generate_binary_op(op, "&>"),
3300 Expression::Not(op) => match &op.this {
3301 Expression::Like(like) => self.generate_like_op_negated(like, "LIKE"),
3302 Expression::ILike(like) => self.generate_like_op_negated(like, "ILIKE"),
3303 _ => self.generate_unary_op(op, "NOT"),
3304 },
3305 Expression::Neg(op) => self.generate_unary_op(op, "-"),
3306 Expression::BitwiseNot(op) => {
3307 if matches!(
3309 self.config.dialect,
3310 Some(DialectType::Presto) | Some(DialectType::Trino)
3311 ) {
3312 self.write_keyword("BITWISE_NOT");
3313 self.write("(");
3314 self.generate_expression(&op.this)?;
3315 self.write(")");
3316 Ok(())
3317 } else {
3318 self.generate_unary_op(op, "~")
3319 }
3320 }
3321 Expression::In(in_expr) => self.generate_in(in_expr),
3322 Expression::Between(between) => self.generate_between(between),
3323 Expression::IsNull(is_null) => self.generate_is_null(is_null),
3324 Expression::IsTrue(is_true) => self.generate_is_true(is_true),
3325 Expression::IsFalse(is_false) => self.generate_is_false(is_false),
3326 Expression::IsJson(is_json) => self.generate_is_json(is_json),
3327 Expression::Is(is_expr) => self.generate_is(is_expr),
3328 Expression::Exists(exists) => self.generate_exists(exists),
3329 Expression::MemberOf(member_of) => self.generate_member_of(member_of),
3330 Expression::Subquery(subquery) => self.generate_subquery(subquery),
3331 Expression::Paren(paren) => {
3332 let skip_parens = matches!(&paren.this, Expression::JoinedTable(_));
3334
3335 if !skip_parens {
3336 self.write("(");
3337 if self.config.pretty {
3338 self.write_newline();
3339 self.indent_level += 1;
3340 self.write_indent();
3341 }
3342 }
3343 self.generate_expression(&paren.this)?;
3344 if !skip_parens {
3345 if self.config.pretty {
3346 self.write_newline();
3347 self.indent_level -= 1;
3348 self.write_indent();
3349 }
3350 self.write(")");
3351 }
3352 for comment in &paren.trailing_comments {
3354 self.write(" ");
3355 self.write_formatted_comment(comment);
3356 }
3357 Ok(())
3358 }
3359 Expression::Array(arr) => self.generate_array(arr),
3360 Expression::Tuple(tuple) => self.generate_tuple(tuple),
3361 Expression::PipeOperator(pipe) => self.generate_pipe_operator(pipe),
3362 Expression::Ordered(ordered) => self.generate_ordered(ordered),
3363 Expression::DataType(dt) => self.generate_data_type(dt),
3364 Expression::Raw(raw) => {
3365 self.write(&raw.sql);
3366 Ok(())
3367 }
3368 Expression::CreateTask(task) => self.generate_create_task(task),
3369 Expression::TryCatch(try_catch) => self.generate_try_catch(try_catch),
3370 Expression::Command(cmd) => {
3371 self.write(&cmd.this);
3372 if matches!(self.config.dialect, Some(DialectType::ClickHouse))
3373 && cmd
3374 .this
3375 .trim_start()
3376 .get(..7)
3377 .is_some_and(|prefix| prefix.eq_ignore_ascii_case("EXPLAIN"))
3378 {
3379 for _ in 0..Self::missing_closing_parens_outside_quotes(&cmd.this) {
3380 self.write(")");
3381 }
3382 }
3383 Ok(())
3384 }
3385 Expression::Kill(kill) => {
3386 self.write_keyword("KILL");
3387 if let Some(kind) = &kill.kind {
3388 self.write_space();
3389 self.write_keyword(kind);
3390 }
3391 self.write_space();
3392 self.generate_expression(&kill.this)?;
3393 Ok(())
3394 }
3395 Expression::Prepare(prepare) => self.generate_prepare(prepare),
3396 Expression::Execute(exec) => {
3397 self.write_keyword("EXECUTE");
3398 self.write_space();
3399 if let Some(return_status) = &exec.return_status {
3400 self.write(return_status);
3401 self.write(" = ");
3402 }
3403 self.generate_expression(&exec.this)?;
3404 if exec.prepared {
3405 if !exec.arguments.is_empty() {
3406 self.write("(");
3407 for (i, argument) in exec.arguments.iter().enumerate() {
3408 if i > 0 {
3409 self.write(", ");
3410 }
3411 self.generate_expression(argument)?;
3412 }
3413 self.write(")");
3414 }
3415 return Ok(());
3416 }
3417 for (i, param) in exec.parameters.iter().enumerate() {
3418 if i == 0 {
3419 self.write_space();
3420 } else {
3421 self.write(", ");
3422 }
3423 self.write(¶m.name);
3424 if !param.positional {
3426 self.write(" = ");
3427 self.generate_expression(¶m.value)?;
3428 }
3429 if param.output {
3430 self.write_space();
3431 self.write_keyword("OUTPUT");
3432 }
3433 }
3434 if let Some(ref suffix) = exec.suffix {
3435 self.write_space();
3436 self.write(suffix);
3437 }
3438 Ok(())
3439 }
3440 Expression::Annotated(annotated) => {
3441 self.generate_expression(&annotated.this)?;
3442 for comment in &annotated.trailing_comments {
3443 self.write(" ");
3444 self.write_formatted_comment(comment);
3445 }
3446 Ok(())
3447 }
3448
3449 Expression::CreateTable(ct) => self.generate_create_table(ct),
3451 Expression::DropTable(dt) => self.generate_drop_table(dt),
3452 Expression::Undrop(u) => self.generate_undrop(u),
3453 Expression::AlterTable(at) => self.generate_alter_table(at),
3454 Expression::SplitTable(st) => self.generate_split_table(st),
3455 Expression::FlashbackTable(ft) => self.generate_flashback_table(ft),
3456 Expression::CreateIndex(ci) => self.generate_create_index(ci),
3457 Expression::DropIndex(di) => self.generate_drop_index(di),
3458 Expression::CreateView(cv) => self.generate_create_view(cv),
3459 Expression::DropView(dv) => self.generate_drop_view(dv),
3460 Expression::AlterView(av) => self.generate_alter_view(av),
3461 Expression::AlterIndex(ai) => self.generate_alter_index(ai),
3462 Expression::Truncate(tr) => self.generate_truncate(tr),
3463 Expression::Use(u) => self.generate_use(u),
3464 Expression::CreateSchema(cs) => self.generate_create_schema(cs),
3466 Expression::DropSchema(ds) => self.generate_drop_schema(ds),
3467 Expression::DropNamespace(dn) => self.generate_drop_namespace(dn),
3468 Expression::CreateDatabase(cd) => self.generate_create_database(cd),
3469 Expression::DropDatabase(dd) => self.generate_drop_database(dd),
3470 Expression::CreateFunction(cf) => self.generate_create_function(cf),
3471 Expression::DropFunction(df) => self.generate_drop_function(df),
3472 Expression::CreateProcedure(cp) => self.generate_create_procedure(cp),
3473 Expression::DropProcedure(dp) => self.generate_drop_procedure(dp),
3474 Expression::CreateSequence(cs) => self.generate_create_sequence(cs),
3475 Expression::CreateSynonym(cs) => {
3476 self.write_keyword("CREATE SYNONYM");
3477 self.write_space();
3478 self.generate_table(&cs.name)?;
3479 self.write_space();
3480 self.write_keyword("FOR");
3481 self.write_space();
3482 self.generate_table(&cs.target)?;
3483 Ok(())
3484 }
3485 Expression::DropSequence(ds) => self.generate_drop_sequence(ds),
3486 Expression::AlterSequence(als) => self.generate_alter_sequence(als),
3487 Expression::CreateTrigger(ct) => self.generate_create_trigger(ct),
3488 Expression::DropTrigger(dt) => self.generate_drop_trigger(dt),
3489 Expression::CreateType(ct) => self.generate_create_type(ct),
3490 Expression::DropType(dt) => self.generate_drop_type(dt),
3491 Expression::Describe(d) => self.generate_describe(d),
3492 Expression::Show(s) => self.generate_show(s),
3493
3494 Expression::Cache(c) => self.generate_cache(c),
3496 Expression::Uncache(u) => self.generate_uncache(u),
3497 Expression::LoadData(l) => self.generate_load_data(l),
3498 Expression::Pragma(p) => self.generate_pragma(p),
3499 Expression::Grant(g) => self.generate_grant(g),
3500 Expression::Revoke(r) => self.generate_revoke(r),
3501 Expression::Comment(c) => self.generate_comment(c),
3502 Expression::SetStatement(s) => self.generate_set_statement(s),
3503
3504 Expression::Pivot(pivot) => self.generate_pivot(pivot),
3506 Expression::Unpivot(unpivot) => self.generate_unpivot(unpivot),
3507
3508 Expression::Values(values) => self.generate_values(values),
3510
3511 Expression::AIAgg(e) => self.generate_ai_agg(e),
3513 Expression::AIClassify(e) => self.generate_ai_classify(e),
3514 Expression::AddPartition(e) => self.generate_add_partition(e),
3515 Expression::AlgorithmProperty(e) => self.generate_algorithm_property(e),
3516 Expression::Aliases(e) => self.generate_aliases(e),
3517 Expression::AllowedValuesProperty(e) => self.generate_allowed_values_property(e),
3518 Expression::AlterColumn(e) => self.generate_alter_column(e),
3519 Expression::AlterSession(e) => self.generate_alter_session(e),
3520 Expression::AlterSet(e) => self.generate_alter_set(e),
3521 Expression::AlterSortKey(e) => self.generate_alter_sort_key(e),
3522 Expression::Analyze(e) => self.generate_analyze(e),
3523 Expression::AnalyzeDelete(e) => self.generate_analyze_delete(e),
3524 Expression::AnalyzeHistogram(e) => self.generate_analyze_histogram(e),
3525 Expression::AnalyzeListChainedRows(e) => self.generate_analyze_list_chained_rows(e),
3526 Expression::AnalyzeSample(e) => self.generate_analyze_sample(e),
3527 Expression::AnalyzeStatistics(e) => self.generate_analyze_statistics(e),
3528 Expression::AnalyzeValidate(e) => self.generate_analyze_validate(e),
3529 Expression::AnalyzeWith(e) => self.generate_analyze_with(e),
3530 Expression::Anonymous(e) => self.generate_anonymous(e),
3531 Expression::AnonymousAggFunc(e) => self.generate_anonymous_agg_func(e),
3532 Expression::Apply(e) => self.generate_apply(e),
3533 Expression::ApproxPercentileEstimate(e) => self.generate_approx_percentile_estimate(e),
3534 Expression::ApproxQuantile(e) => self.generate_approx_quantile(e),
3535 Expression::ApproxQuantiles(e) => self.generate_approx_quantiles(e),
3536 Expression::ApproxTopK(e) => self.generate_approx_top_k(e),
3537 Expression::ApproxTopKAccumulate(e) => self.generate_approx_top_k_accumulate(e),
3538 Expression::ApproxTopKCombine(e) => self.generate_approx_top_k_combine(e),
3539 Expression::ApproxTopKEstimate(e) => self.generate_approx_top_k_estimate(e),
3540 Expression::ApproxTopSum(e) => self.generate_approx_top_sum(e),
3541 Expression::ArgMax(e) => self.generate_arg_max(e),
3542 Expression::ArgMin(e) => self.generate_arg_min(e),
3543 Expression::ArrayAll(e) => self.generate_array_all(e),
3544 Expression::ArrayAny(e) => self.generate_array_any(e),
3545 Expression::ArrayConstructCompact(e) => self.generate_array_construct_compact(e),
3546 Expression::ArraySum(e) => self.generate_array_sum(e),
3547 Expression::AtIndex(e) => self.generate_at_index(e),
3548 Expression::Attach(e) => self.generate_attach(e),
3549 Expression::AttachOption(e) => self.generate_attach_option(e),
3550 Expression::AutoIncrementProperty(e) => self.generate_auto_increment_property(e),
3551 Expression::AutoRefreshProperty(e) => self.generate_auto_refresh_property(e),
3552 Expression::BackupProperty(e) => self.generate_backup_property(e),
3553 Expression::Base64DecodeBinary(e) => self.generate_base64_decode_binary(e),
3554 Expression::Base64DecodeString(e) => self.generate_base64_decode_string(e),
3555 Expression::Base64Encode(e) => self.generate_base64_encode(e),
3556 Expression::BlockCompressionProperty(e) => self.generate_block_compression_property(e),
3557 Expression::Booland(e) => self.generate_booland(e),
3558 Expression::Boolor(e) => self.generate_boolor(e),
3559 Expression::BuildProperty(e) => self.generate_build_property(e),
3560 Expression::ByteString(e) => self.generate_byte_string(e),
3561 Expression::CaseSpecificColumnConstraint(e) => {
3562 self.generate_case_specific_column_constraint(e)
3563 }
3564 Expression::CastToStrType(e) => self.generate_cast_to_str_type(e),
3565 Expression::Changes(e) => self.generate_changes(e),
3566 Expression::CharacterSetColumnConstraint(e) => {
3567 self.generate_character_set_column_constraint(e)
3568 }
3569 Expression::CharacterSetProperty(e) => self.generate_character_set_property(e),
3570 Expression::CheckColumnConstraint(e) => self.generate_check_column_constraint(e),
3571 Expression::AssumeColumnConstraint(e) => self.generate_assume_column_constraint(e),
3572 Expression::CheckJson(e) => self.generate_check_json(e),
3573 Expression::CheckXml(e) => self.generate_check_xml(e),
3574 Expression::ChecksumProperty(e) => self.generate_checksum_property(e),
3575 Expression::Clone(e) => self.generate_clone(e),
3576 Expression::ClusterBy(e) => self.generate_cluster_by(e),
3577 Expression::ClusterByColumnsProperty(e) => self.generate_cluster_by_columns_property(e),
3578 Expression::ClusteredByProperty(e) => self.generate_clustered_by_property(e),
3579 Expression::CollateProperty(e) => self.generate_collate_property(e),
3580 Expression::ColumnConstraint(e) => self.generate_column_constraint(e),
3581 Expression::ColumnDef(e) => self.generate_column_def_expr(e),
3582 Expression::ColumnPosition(e) => self.generate_column_position(e),
3583 Expression::ColumnPrefix(e) => self.generate_column_prefix(e),
3584 Expression::Columns(e) => self.generate_columns(e),
3585 Expression::CombinedAggFunc(e) => self.generate_combined_agg_func(e),
3586 Expression::CombinedParameterizedAgg(e) => self.generate_combined_parameterized_agg(e),
3587 Expression::Commit(e) => self.generate_commit(e),
3588 Expression::Comprehension(e) => self.generate_comprehension(e),
3589 Expression::Compress(e) => self.generate_compress(e),
3590 Expression::CompressColumnConstraint(e) => self.generate_compress_column_constraint(e),
3591 Expression::ComputedColumnConstraint(e) => self.generate_computed_column_constraint(e),
3592 Expression::ConditionalInsert(e) => self.generate_conditional_insert(e),
3593 Expression::Constraint(e) => self.generate_constraint(e),
3594 Expression::ConvertTimezone(e) => self.generate_convert_timezone(e),
3595 Expression::ConvertToCharset(e) => self.generate_convert_to_charset(e),
3596 Expression::Copy(e) => self.generate_copy(e),
3597 Expression::CopyParameter(e) => self.generate_copy_parameter(e),
3598 Expression::Corr(e) => self.generate_corr(e),
3599 Expression::CosineDistance(e) => self.generate_cosine_distance(e),
3600 Expression::CovarPop(e) => self.generate_covar_pop(e),
3601 Expression::CovarSamp(e) => self.generate_covar_samp(e),
3602 Expression::Credentials(e) => self.generate_credentials(e),
3603 Expression::CredentialsProperty(e) => self.generate_credentials_property(e),
3604 Expression::Cte(e) => self.generate_cte(e),
3605 Expression::Cube(e) => self.generate_cube(e),
3606 Expression::CurrentDatetime(e) => self.generate_current_datetime(e),
3607 Expression::CurrentSchema(e) => self.generate_current_schema(e),
3608 Expression::CurrentSchemas(e) => self.generate_current_schemas(e),
3609 Expression::CurrentUser(e) => self.generate_current_user(e),
3610 Expression::DPipe(e) => self.generate_d_pipe(e),
3611 Expression::DataBlocksizeProperty(e) => self.generate_data_blocksize_property(e),
3612 Expression::DataDeletionProperty(e) => self.generate_data_deletion_property(e),
3613 Expression::Date(e) => self.generate_date_func(e),
3614 Expression::DateBin(e) => self.generate_date_bin(e),
3615 Expression::DateFormatColumnConstraint(e) => {
3616 self.generate_date_format_column_constraint(e)
3617 }
3618 Expression::DateFromParts(e) => self.generate_date_from_parts(e),
3619 Expression::Datetime(e) => self.generate_datetime(e),
3620 Expression::DatetimeAdd(e) => self.generate_datetime_add(e),
3621 Expression::DatetimeDiff(e) => self.generate_datetime_diff(e),
3622 Expression::DatetimeSub(e) => self.generate_datetime_sub(e),
3623 Expression::DatetimeTrunc(e) => self.generate_datetime_trunc(e),
3624 Expression::Dayname(e) => self.generate_dayname(e),
3625 Expression::Declare(e) => self.generate_declare(e),
3626 Expression::DeclareItem(e) => self.generate_declare_item(e),
3627 Expression::DecodeCase(e) => self.generate_decode_case(e),
3628 Expression::DecompressBinary(e) => self.generate_decompress_binary(e),
3629 Expression::DecompressString(e) => self.generate_decompress_string(e),
3630 Expression::Decrypt(e) => self.generate_decrypt(e),
3631 Expression::DecryptRaw(e) => self.generate_decrypt_raw(e),
3632 Expression::DefaultColumnConstraint(e) => {
3633 self.write_keyword("DEFAULT");
3634 self.write_space();
3635 self.generate_expression(&e.this)?;
3636 if let Some(ref col) = e.for_column {
3637 self.write_space();
3638 self.write_keyword("FOR");
3639 self.write_space();
3640 self.generate_identifier(col)?;
3641 }
3642 Ok(())
3643 }
3644 Expression::DefinerProperty(e) => self.generate_definer_property(e),
3645 Expression::Detach(e) => self.generate_detach(e),
3646 Expression::DictProperty(e) => self.generate_dict_property(e),
3647 Expression::DictRange(e) => self.generate_dict_range(e),
3648 Expression::Directory(e) => self.generate_directory(e),
3649 Expression::DistKeyProperty(e) => self.generate_dist_key_property(e),
3650 Expression::DistStyleProperty(e) => self.generate_dist_style_property(e),
3651 Expression::DistributeBy(e) => self.generate_distribute_by(e),
3652 Expression::DistributedByProperty(e) => self.generate_distributed_by_property(e),
3653 Expression::DotProduct(e) => self.generate_dot_product(e),
3654 Expression::DropPartition(e) => self.generate_drop_partition(e),
3655 Expression::DuplicateKeyProperty(e) => self.generate_duplicate_key_property(e),
3656 Expression::Elt(e) => self.generate_elt(e),
3657 Expression::Encode(e) => self.generate_encode(e),
3658 Expression::EncodeProperty(e) => self.generate_encode_property(e),
3659 Expression::Encrypt(e) => self.generate_encrypt(e),
3660 Expression::EncryptRaw(e) => self.generate_encrypt_raw(e),
3661 Expression::EngineProperty(e) => self.generate_engine_property(e),
3662 Expression::EnviromentProperty(e) => self.generate_enviroment_property(e),
3663 Expression::EphemeralColumnConstraint(e) => {
3664 self.generate_ephemeral_column_constraint(e)
3665 }
3666 Expression::EqualNull(e) => self.generate_equal_null(e),
3667 Expression::EuclideanDistance(e) => self.generate_euclidean_distance(e),
3668 Expression::ExecuteAsProperty(e) => self.generate_execute_as_property(e),
3669 Expression::Export(e) => self.generate_export(e),
3670 Expression::ExternalProperty(e) => self.generate_external_property(e),
3671 Expression::FallbackProperty(e) => self.generate_fallback_property(e),
3672 Expression::FarmFingerprint(e) => self.generate_farm_fingerprint(e),
3673 Expression::FeaturesAtTime(e) => self.generate_features_at_time(e),
3674 Expression::Fetch(e) => self.generate_fetch(e),
3675 Expression::FileFormatProperty(e) => self.generate_file_format_property(e),
3676 Expression::Filter(e) => self.generate_filter(e),
3677 Expression::Float64(e) => self.generate_float64(e),
3678 Expression::ForIn(e) => self.generate_for_in(e),
3679 Expression::ForeignKey(e) => self.generate_foreign_key(e),
3680 Expression::Format(e) => self.generate_format(e),
3681 Expression::FormatPhrase(e) => self.generate_format_phrase(e),
3682 Expression::FreespaceProperty(e) => self.generate_freespace_property(e),
3683 Expression::From(e) => self.generate_from(e),
3684 Expression::FromBase(e) => self.generate_from_base(e),
3685 Expression::FromTimeZone(e) => self.generate_from_time_zone(e),
3686 Expression::GapFill(e) => self.generate_gap_fill(e),
3687 Expression::GenerateDateArray(e) => self.generate_generate_date_array(e),
3688 Expression::GenerateEmbedding(e) => self.generate_generate_embedding(e),
3689 Expression::GenerateSeries(e) => self.generate_generate_series(e),
3690 Expression::GenerateTimestampArray(e) => self.generate_generate_timestamp_array(e),
3691 Expression::GeneratedAsIdentityColumnConstraint(e) => {
3692 self.generate_generated_as_identity_column_constraint(e)
3693 }
3694 Expression::GeneratedAsRowColumnConstraint(e) => {
3695 self.generate_generated_as_row_column_constraint(e)
3696 }
3697 Expression::Get(e) => self.generate_get(e),
3698 Expression::GetExtract(e) => self.generate_get_extract(e),
3699 Expression::Getbit(e) => self.generate_getbit(e),
3700 Expression::GrantPrincipal(e) => self.generate_grant_principal(e),
3701 Expression::GrantPrivilege(e) => self.generate_grant_privilege(e),
3702 Expression::Group(e) => self.generate_group(e),
3703 Expression::GroupBy(e) => self.generate_group_by(e),
3704 Expression::Grouping(e) => self.generate_grouping(e),
3705 Expression::GroupingId(e) => self.generate_grouping_id(e),
3706 Expression::GroupingSets(e) => self.generate_grouping_sets(e),
3707 Expression::HashAgg(e) => self.generate_hash_agg(e),
3708 Expression::Having(e) => self.generate_having(e),
3709 Expression::HavingMax(e) => self.generate_having_max(e),
3710 Expression::Heredoc(e) => self.generate_heredoc(e),
3711 Expression::HexEncode(e) => self.generate_hex_encode(e),
3712 Expression::Hll(e) => self.generate_hll(e),
3713 Expression::InOutColumnConstraint(e) => self.generate_in_out_column_constraint(e),
3714 Expression::IncludeProperty(e) => self.generate_include_property(e),
3715 Expression::Index(e) => self.generate_index(e),
3716 Expression::IndexColumnConstraint(e) => self.generate_index_column_constraint(e),
3717 Expression::IndexConstraintOption(e) => self.generate_index_constraint_option(e),
3718 Expression::IndexParameters(e) => self.generate_index_parameters(e),
3719 Expression::IndexTableHint(e) => self.generate_index_table_hint(e),
3720 Expression::InheritsProperty(e) => self.generate_inherits_property(e),
3721 Expression::InputModelProperty(e) => self.generate_input_model_property(e),
3722 Expression::InputOutputFormat(e) => self.generate_input_output_format(e),
3723 Expression::Install(e) => self.generate_install(e),
3724 Expression::IntervalOp(e) => self.generate_interval_op(e),
3725 Expression::IntervalSpan(e) => self.generate_interval_span(e),
3726 Expression::IntoClause(e) => self.generate_into_clause(e),
3727 Expression::Introducer(e) => self.generate_introducer(e),
3728 Expression::IsolatedLoadingProperty(e) => self.generate_isolated_loading_property(e),
3729 Expression::JSON(e) => self.generate_json(e),
3730 Expression::JSONArray(e) => self.generate_json_array(e),
3731 Expression::JSONArrayAgg(e) => self.generate_json_array_agg_struct(e),
3732 Expression::JSONArrayAppend(e) => self.generate_json_array_append(e),
3733 Expression::JSONArrayContains(e) => self.generate_json_array_contains(e),
3734 Expression::JSONArrayInsert(e) => self.generate_json_array_insert(e),
3735 Expression::JSONBExists(e) => self.generate_jsonb_exists(e),
3736 Expression::JSONBExtractScalar(e) => self.generate_jsonb_extract_scalar(e),
3737 Expression::JSONBObjectAgg(e) => self.generate_jsonb_object_agg(e),
3738 Expression::JSONObjectAgg(e) => self.generate_json_object_agg_struct(e),
3739 Expression::JSONColumnDef(e) => self.generate_json_column_def(e),
3740 Expression::JSONExists(e) => self.generate_json_exists(e),
3741 Expression::JSONCast(e) => self.generate_json_cast(e),
3742 Expression::JSONExtract(e) => self.generate_json_extract_path(e),
3743 Expression::JSONExtractArray(e) => self.generate_json_extract_array(e),
3744 Expression::JSONExtractQuote(e) => self.generate_json_extract_quote(e),
3745 Expression::JSONExtractScalar(e) => self.generate_json_extract_scalar(e),
3746 Expression::JSONFormat(e) => self.generate_json_format(e),
3747 Expression::JSONKeyValue(e) => self.generate_json_key_value(e),
3748 Expression::JSONKeys(e) => self.generate_json_keys(e),
3749 Expression::JSONKeysAtDepth(e) => self.generate_json_keys_at_depth(e),
3750 Expression::JSONPath(e) => self.generate_json_path_expr(e),
3751 Expression::JSONPathFilter(e) => self.generate_json_path_filter(e),
3752 Expression::JSONPathKey(e) => self.generate_json_path_key(e),
3753 Expression::JSONPathRecursive(e) => self.generate_json_path_recursive(e),
3754 Expression::JSONPathRoot(_) => self.generate_json_path_root(),
3755 Expression::JSONPathScript(e) => self.generate_json_path_script(e),
3756 Expression::JSONPathSelector(e) => self.generate_json_path_selector(e),
3757 Expression::JSONPathSlice(e) => self.generate_json_path_slice(e),
3758 Expression::JSONPathSubscript(e) => self.generate_json_path_subscript(e),
3759 Expression::JSONPathUnion(e) => self.generate_json_path_union(e),
3760 Expression::JSONRemove(e) => self.generate_json_remove(e),
3761 Expression::JSONSchema(e) => self.generate_json_schema(e),
3762 Expression::JSONSet(e) => self.generate_json_set(e),
3763 Expression::JSONStripNulls(e) => self.generate_json_strip_nulls(e),
3764 Expression::JSONTable(e) => self.generate_json_table(e),
3765 Expression::JSONType(e) => self.generate_json_type(e),
3766 Expression::JSONValue(e) => self.generate_json_value(e),
3767 Expression::JSONValueArray(e) => self.generate_json_value_array(e),
3768 Expression::JarowinklerSimilarity(e) => self.generate_jarowinkler_similarity(e),
3769 Expression::JoinHint(e) => self.generate_join_hint(e),
3770 Expression::JournalProperty(e) => self.generate_journal_property(e),
3771 Expression::LanguageProperty(e) => self.generate_language_property(e),
3772 Expression::Lateral(e) => self.generate_lateral(e),
3773 Expression::LikeProperty(e) => self.generate_like_property(e),
3774 Expression::Limit(e) => self.generate_limit(e),
3775 Expression::LimitOptions(e) => self.generate_limit_options(e),
3776 Expression::List(e) => self.generate_list(e),
3777 Expression::ToMap(e) => self.generate_tomap(e),
3778 Expression::Localtime(e) => self.generate_localtime(e),
3779 Expression::Localtimestamp(e) => self.generate_localtimestamp(e),
3780 Expression::LocationProperty(e) => self.generate_location_property(e),
3781 Expression::Lock(e) => self.generate_lock(e),
3782 Expression::LockProperty(e) => self.generate_lock_property(e),
3783 Expression::LockingProperty(e) => self.generate_locking_property(e),
3784 Expression::LockingStatement(e) => self.generate_locking_statement(e),
3785 Expression::LogProperty(e) => self.generate_log_property(e),
3786 Expression::MD5Digest(e) => self.generate_md5_digest(e),
3787 Expression::MLForecast(e) => self.generate_ml_forecast(e),
3788 Expression::MLTranslate(e) => self.generate_ml_translate(e),
3789 Expression::MakeInterval(e) => self.generate_make_interval(e),
3790 Expression::ManhattanDistance(e) => self.generate_manhattan_distance(e),
3791 Expression::Map(e) => self.generate_map(e),
3792 Expression::MapCat(e) => self.generate_map_cat(e),
3793 Expression::MapDelete(e) => self.generate_map_delete(e),
3794 Expression::MapInsert(e) => self.generate_map_insert(e),
3795 Expression::MapPick(e) => self.generate_map_pick(e),
3796 Expression::MaskingPolicyColumnConstraint(e) => {
3797 self.generate_masking_policy_column_constraint(e)
3798 }
3799 Expression::MatchAgainst(e) => self.generate_match_against(e),
3800 Expression::MatchRecognizeMeasure(e) => self.generate_match_recognize_measure(e),
3801 Expression::MaterializedProperty(e) => self.generate_materialized_property(e),
3802 Expression::Merge(e) => self.generate_merge(e),
3803 Expression::MergeBlockRatioProperty(e) => self.generate_merge_block_ratio_property(e),
3804 Expression::MergeTreeTTL(e) => self.generate_merge_tree_ttl(e),
3805 Expression::MergeTreeTTLAction(e) => self.generate_merge_tree_ttl_action(e),
3806 Expression::Minhash(e) => self.generate_minhash(e),
3807 Expression::ModelAttribute(e) => self.generate_model_attribute(e),
3808 Expression::Monthname(e) => self.generate_monthname(e),
3809 Expression::MultitableInserts(e) => self.generate_multitable_inserts(e),
3810 Expression::NextValueFor(e) => self.generate_next_value_for(e),
3811 Expression::Normal(e) => self.generate_normal(e),
3812 Expression::Normalize(e) => self.generate_normalize(e),
3813 Expression::NotNullColumnConstraint(e) => self.generate_not_null_column_constraint(e),
3814 Expression::Nullif(e) => self.generate_nullif(e),
3815 Expression::NumberToStr(e) => self.generate_number_to_str(e),
3816 Expression::ObjectAgg(e) => self.generate_object_agg(e),
3817 Expression::ObjectIdentifier(e) => self.generate_object_identifier(e),
3818 Expression::ObjectInsert(e) => self.generate_object_insert(e),
3819 Expression::Offset(e) => self.generate_offset(e),
3820 Expression::Qualify(e) => self.generate_qualify(e),
3821 Expression::OnCluster(e) => self.generate_on_cluster(e),
3822 Expression::OnCommitProperty(e) => self.generate_on_commit_property(e),
3823 Expression::OnCondition(e) => self.generate_on_condition(e),
3824 Expression::OnConflict(e) => self.generate_on_conflict(e),
3825 Expression::OnProperty(e) => self.generate_on_property(e),
3826 Expression::Opclass(e) => self.generate_opclass(e),
3827 Expression::OpenJSON(e) => self.generate_open_json(e),
3828 Expression::OpenJSONColumnDef(e) => self.generate_open_json_column_def(e),
3829 Expression::Operator(e) => self.generate_operator(e),
3830 Expression::OrderBy(e) => self.generate_order_by(e),
3831 Expression::OutputModelProperty(e) => self.generate_output_model_property(e),
3832 Expression::OverflowTruncateBehavior(e) => self.generate_overflow_truncate_behavior(e),
3833 Expression::ParameterizedAgg(e) => self.generate_parameterized_agg(e),
3834 Expression::ParseDatetime(e) => self.generate_parse_datetime(e),
3835 Expression::ParseIp(e) => self.generate_parse_ip(e),
3836 Expression::ParseJSON(e) => self.generate_parse_json(e),
3837 Expression::ParseTime(e) => self.generate_parse_time(e),
3838 Expression::ParseUrl(e) => self.generate_parse_url(e),
3839 Expression::Partition(e) => self.generate_partition_expr(e),
3840 Expression::PartitionBoundSpec(e) => self.generate_partition_bound_spec(e),
3841 Expression::PartitionByListProperty(e) => self.generate_partition_by_list_property(e),
3842 Expression::PartitionByRangeProperty(e) => self.generate_partition_by_range_property(e),
3843 Expression::PartitionByRangePropertyDynamic(e) => {
3844 self.generate_partition_by_range_property_dynamic(e)
3845 }
3846 Expression::PartitionByTruncate(e) => self.generate_partition_by_truncate(e),
3847 Expression::PartitionList(e) => self.generate_partition_list(e),
3848 Expression::PartitionRange(e) => self.generate_partition_range(e),
3849 Expression::PartitionByProperty(e) => self.generate_partition_by_property(e),
3850 Expression::PartitionedByBucket(e) => self.generate_partitioned_by_bucket(e),
3851 Expression::PartitionedByProperty(e) => self.generate_partitioned_by_property(e),
3852 Expression::PartitionedOfProperty(e) => self.generate_partitioned_of_property(e),
3853 Expression::PeriodForSystemTimeConstraint(e) => {
3854 self.generate_period_for_system_time_constraint(e)
3855 }
3856 Expression::PivotAlias(e) => self.generate_pivot_alias(e),
3857 Expression::PivotAny(e) => self.generate_pivot_any(e),
3858 Expression::Predict(e) => self.generate_predict(e),
3859 Expression::PreviousDay(e) => self.generate_previous_day(e),
3860 Expression::PrimaryKey(e) => self.generate_primary_key(e),
3861 Expression::PrimaryKeyColumnConstraint(e) => {
3862 self.generate_primary_key_column_constraint(e)
3863 }
3864 Expression::PathColumnConstraint(e) => self.generate_path_column_constraint(e),
3865 Expression::ProjectionDef(e) => self.generate_projection_def(e),
3866 Expression::OptionsProperty(e) => self.generate_options_property(e),
3867 Expression::Properties(e) => self.generate_properties(e),
3868 Expression::Property(e) => self.generate_property(e),
3869 Expression::PseudoType(e) => self.generate_pseudo_type(e),
3870 Expression::Put(e) => self.generate_put(e),
3871 Expression::Quantile(e) => self.generate_quantile(e),
3872 Expression::QueryBand(e) => self.generate_query_band(e),
3873 Expression::QueryOption(e) => self.generate_query_option(e),
3874 Expression::QueryTransform(e) => self.generate_query_transform(e),
3875 Expression::Randn(e) => self.generate_randn(e),
3876 Expression::Randstr(e) => self.generate_randstr(e),
3877 Expression::RangeBucket(e) => self.generate_range_bucket(e),
3878 Expression::RangeN(e) => self.generate_range_n(e),
3879 Expression::ReadCSV(e) => self.generate_read_csv(e),
3880 Expression::ReadParquet(e) => self.generate_read_parquet(e),
3881 Expression::RecursiveWithSearch(e) => self.generate_recursive_with_search(e),
3882 Expression::Reduce(e) => self.generate_reduce(e),
3883 Expression::Reference(e) => self.generate_reference(e),
3884 Expression::Refresh(e) => self.generate_refresh(e),
3885 Expression::RefreshTriggerProperty(e) => self.generate_refresh_trigger_property(e),
3886 Expression::RegexpCount(e) => self.generate_regexp_count(e),
3887 Expression::RegexpExtractAll(e) => self.generate_regexp_extract_all(e),
3888 Expression::RegexpFullMatch(e) => self.generate_regexp_full_match(e),
3889 Expression::RegexpILike(e) => self.generate_regexp_i_like(e),
3890 Expression::RegexpInstr(e) => self.generate_regexp_instr(e),
3891 Expression::RegexpSplit(e) => self.generate_regexp_split(e),
3892 Expression::RegrAvgx(e) => self.generate_regr_avgx(e),
3893 Expression::RegrAvgy(e) => self.generate_regr_avgy(e),
3894 Expression::RegrCount(e) => self.generate_regr_count(e),
3895 Expression::RegrIntercept(e) => self.generate_regr_intercept(e),
3896 Expression::RegrR2(e) => self.generate_regr_r2(e),
3897 Expression::RegrSlope(e) => self.generate_regr_slope(e),
3898 Expression::RegrSxx(e) => self.generate_regr_sxx(e),
3899 Expression::RegrSxy(e) => self.generate_regr_sxy(e),
3900 Expression::RegrSyy(e) => self.generate_regr_syy(e),
3901 Expression::RegrValx(e) => self.generate_regr_valx(e),
3902 Expression::RegrValy(e) => self.generate_regr_valy(e),
3903 Expression::RemoteWithConnectionModelProperty(e) => {
3904 self.generate_remote_with_connection_model_property(e)
3905 }
3906 Expression::RenameColumn(e) => self.generate_rename_column(e),
3907 Expression::ReplacePartition(e) => self.generate_replace_partition(e),
3908 Expression::Returning(e) => self.generate_returning(e),
3909 Expression::ReturnsProperty(e) => self.generate_returns_property(e),
3910 Expression::Rollback(e) => self.generate_rollback(e),
3911 Expression::Rollup(e) => self.generate_rollup(e),
3912 Expression::RowFormatDelimitedProperty(e) => {
3913 self.generate_row_format_delimited_property(e)
3914 }
3915 Expression::RowFormatProperty(e) => self.generate_row_format_property(e),
3916 Expression::RowFormatSerdeProperty(e) => self.generate_row_format_serde_property(e),
3917 Expression::SHA2(e) => self.generate_sha2(e),
3918 Expression::SHA2Digest(e) => self.generate_sha2_digest(e),
3919 Expression::SafeAdd(e) => self.generate_safe_add(e),
3920 Expression::SafeDivide(e) => self.generate_safe_divide(e),
3921 Expression::SafeMultiply(e) => self.generate_safe_multiply(e),
3922 Expression::SafeSubtract(e) => self.generate_safe_subtract(e),
3923 Expression::SampleProperty(e) => self.generate_sample_property(e),
3924 Expression::Schema(e) => self.generate_schema(e),
3925 Expression::SchemaCommentProperty(e) => self.generate_schema_comment_property(e),
3926 Expression::ScopeResolution(e) => self.generate_scope_resolution(e),
3927 Expression::Search(e) => self.generate_search(e),
3928 Expression::SearchIp(e) => self.generate_search_ip(e),
3929 Expression::SecurityProperty(e) => self.generate_security_property(e),
3930 Expression::SemanticView(e) => self.generate_semantic_view(e),
3931 Expression::SequenceProperties(e) => self.generate_sequence_properties(e),
3932 Expression::SerdeProperties(e) => self.generate_serde_properties(e),
3933 Expression::SessionParameter(e) => self.generate_session_parameter(e),
3934 Expression::Set(e) => self.generate_set(e),
3935 Expression::SetConfigProperty(e) => self.generate_set_config_property(e),
3936 Expression::SetItem(e) => self.generate_set_item(e),
3937 Expression::SetOperation(e) => self.generate_set_operation(e),
3938 Expression::SetProperty(e) => self.generate_set_property(e),
3939 Expression::SettingsProperty(e) => self.generate_settings_property(e),
3940 Expression::SharingProperty(e) => self.generate_sharing_property(e),
3941 Expression::Slice(e) => self.generate_slice(e),
3942 Expression::SortArray(e) => self.generate_sort_array(e),
3943 Expression::SortBy(e) => self.generate_sort_by(e),
3944 Expression::SortKeyProperty(e) => self.generate_sort_key_property(e),
3945 Expression::SplitPart(e) => self.generate_split_part(e),
3946 Expression::SqlReadWriteProperty(e) => self.generate_sql_read_write_property(e),
3947 Expression::SqlSecurityProperty(e) => self.generate_sql_security_property(e),
3948 Expression::StDistance(e) => self.generate_st_distance(e),
3949 Expression::StPoint(e) => self.generate_st_point(e),
3950 Expression::StabilityProperty(e) => self.generate_stability_property(e),
3951 Expression::StandardHash(e) => self.generate_standard_hash(e),
3952 Expression::StorageHandlerProperty(e) => self.generate_storage_handler_property(e),
3953 Expression::StrPosition(e) => self.generate_str_position(e),
3954 Expression::StrToDate(e) => self.generate_str_to_date(e),
3955 Expression::DateStrToDate(f) => self.generate_simple_func("DATE_STR_TO_DATE", &f.this),
3956 Expression::DateToDateStr(f) => self.generate_simple_func("DATE_TO_DATE_STR", &f.this),
3957 Expression::StrToMap(e) => self.generate_str_to_map(e),
3958 Expression::StrToTime(e) => self.generate_str_to_time(e),
3959 Expression::StrToUnix(e) => self.generate_str_to_unix(e),
3960 Expression::StringToArray(e) => self.generate_string_to_array(e),
3961 Expression::Struct(e) => self.generate_struct(e),
3962 Expression::Stuff(e) => self.generate_stuff(e),
3963 Expression::SubstringIndex(e) => self.generate_substring_index(e),
3964 Expression::Summarize(e) => self.generate_summarize(e),
3965 Expression::Systimestamp(e) => self.generate_systimestamp(e),
3966 Expression::TableAlias(e) => self.generate_table_alias(e),
3967 Expression::TableFromRows(e) => self.generate_table_from_rows(e),
3968 Expression::RowsFrom(e) => self.generate_rows_from(e),
3969 Expression::TableSample(e) => self.generate_table_sample(e),
3970 Expression::Tag(e) => self.generate_tag(e),
3971 Expression::Tags(e) => self.generate_tags(e),
3972 Expression::TemporaryProperty(e) => self.generate_temporary_property(e),
3973 Expression::Time(e) => self.generate_time_func(e),
3974 Expression::TimeAdd(e) => self.generate_time_add(e),
3975 Expression::TimeDiff(e) => self.generate_time_diff(e),
3976 Expression::TimeFromParts(e) => self.generate_time_from_parts(e),
3977 Expression::TimeSlice(e) => self.generate_time_slice(e),
3978 Expression::TimeStrToDate(e) => self.generate_time_str_to_date(e),
3979 Expression::TimeStrToTime(e) => self.generate_time_str_to_time(e),
3980 Expression::TimeSub(e) => self.generate_time_sub(e),
3981 Expression::TimeToStr(e) => self.generate_time_to_str(e),
3982 Expression::TimeToUnix(e) => self.generate_time_to_unix(e),
3983 Expression::TimeTrunc(e) => self.generate_time_trunc(e),
3984 Expression::TimeUnit(e) => self.generate_time_unit(e),
3985 Expression::Timestamp(e) => self.generate_timestamp_func(e),
3986 Expression::TimestampAdd(e) => self.generate_timestamp_add(e),
3987 Expression::TimestampDiff(e) => self.generate_timestamp_diff(e),
3988 Expression::TimestampFromParts(e) => self.generate_timestamp_from_parts(e),
3989 Expression::TimestampSub(e) => self.generate_timestamp_sub(e),
3990 Expression::TimestampTzFromParts(e) => self.generate_timestamp_tz_from_parts(e),
3991 Expression::ToBinary(e) => self.generate_to_binary(e),
3992 Expression::ToBoolean(e) => self.generate_to_boolean(e),
3993 Expression::ToChar(e) => self.generate_to_char(e),
3994 Expression::ToDecfloat(e) => self.generate_to_decfloat(e),
3995 Expression::ToDouble(e) => self.generate_to_double(e),
3996 Expression::ToFile(e) => self.generate_to_file(e),
3997 Expression::ToNumber(e) => self.generate_to_number(e),
3998 Expression::ToTableProperty(e) => self.generate_to_table_property(e),
3999 Expression::Transaction(e) => self.generate_transaction(e),
4000 Expression::Transform(e) => self.generate_transform(e),
4001 Expression::TransformModelProperty(e) => self.generate_transform_model_property(e),
4002 Expression::TransientProperty(e) => self.generate_transient_property(e),
4003 Expression::Translate(e) => self.generate_translate(e),
4004 Expression::TranslateCharacters(e) => self.generate_translate_characters(e),
4005 Expression::TruncateTable(e) => self.generate_truncate_table(e),
4006 Expression::TryBase64DecodeBinary(e) => self.generate_try_base64_decode_binary(e),
4007 Expression::TryBase64DecodeString(e) => self.generate_try_base64_decode_string(e),
4008 Expression::TryToDecfloat(e) => self.generate_try_to_decfloat(e),
4009 Expression::TsOrDsAdd(e) => self.generate_ts_or_ds_add(e),
4010 Expression::TsOrDsDiff(e) => self.generate_ts_or_ds_diff(e),
4011 Expression::TsOrDsToDate(e) => self.generate_ts_or_ds_to_date(e),
4012 Expression::TsOrDsToTime(e) => self.generate_ts_or_ds_to_time(e),
4013 Expression::Unhex(e) => self.generate_unhex(e),
4014 Expression::UnicodeString(e) => self.generate_unicode_string(e),
4015 Expression::Uniform(e) => self.generate_uniform(e),
4016 Expression::UniqueColumnConstraint(e) => self.generate_unique_column_constraint(e),
4017 Expression::UniqueKeyProperty(e) => self.generate_unique_key_property(e),
4018 Expression::RollupProperty(e) => self.generate_rollup_property(e),
4019 Expression::UnixToStr(e) => self.generate_unix_to_str(e),
4020 Expression::UnixToTime(e) => self.generate_unix_to_time(e),
4021 Expression::UnpivotColumns(e) => self.generate_unpivot_columns(e),
4022 Expression::UserDefinedFunction(e) => self.generate_user_defined_function(e),
4023 Expression::UsingTemplateProperty(e) => self.generate_using_template_property(e),
4024 Expression::UtcTime(e) => self.generate_utc_time(e),
4025 Expression::UtcTimestamp(e) => self.generate_utc_timestamp(e),
4026 Expression::Uuid(e) => self.generate_uuid(e),
4027 Expression::Var(v) => {
4028 if matches!(self.config.dialect, Some(DialectType::MySQL))
4029 && v.this.len() > 2
4030 && (v.this.starts_with("0x") || v.this.starts_with("0X"))
4031 && !v.this[2..].chars().all(|c| c.is_ascii_hexdigit())
4032 {
4033 return self.generate_identifier(&Identifier {
4034 name: v.this.clone(),
4035 quoted: true,
4036 trailing_comments: Vec::new(),
4037 span: None,
4038 });
4039 }
4040 self.write(&v.this);
4041 Ok(())
4042 }
4043 Expression::Variadic(e) => {
4044 self.write_keyword("VARIADIC");
4045 self.write_space();
4046 self.generate_expression(&e.this)?;
4047 Ok(())
4048 }
4049 Expression::VarMap(e) => self.generate_var_map(e),
4050 Expression::VectorSearch(e) => self.generate_vector_search(e),
4051 Expression::Version(e) => self.generate_version(e),
4052 Expression::ViewAttributeProperty(e) => self.generate_view_attribute_property(e),
4053 Expression::VolatileProperty(e) => self.generate_volatile_property(e),
4054 Expression::WatermarkColumnConstraint(e) => {
4055 self.generate_watermark_column_constraint(e)
4056 }
4057 Expression::Week(e) => self.generate_week(e),
4058 Expression::When(e) => self.generate_when(e),
4059 Expression::Whens(e) => self.generate_whens(e),
4060 Expression::Where(e) => self.generate_where(e),
4061 Expression::WidthBucket(e) => self.generate_width_bucket(e),
4062 Expression::Window(e) => self.generate_window(e),
4063 Expression::WindowSpec(e) => self.generate_window_spec(e),
4064 Expression::WithDataProperty(e) => self.generate_with_data_property(e),
4065 Expression::WithFill(e) => self.generate_with_fill(e),
4066 Expression::WithJournalTableProperty(e) => self.generate_with_journal_table_property(e),
4067 Expression::WithOperator(e) => self.generate_with_operator(e),
4068 Expression::WithProcedureOptions(e) => self.generate_with_procedure_options(e),
4069 Expression::WithSchemaBindingProperty(e) => {
4070 self.generate_with_schema_binding_property(e)
4071 }
4072 Expression::WithSystemVersioningProperty(e) => {
4073 self.generate_with_system_versioning_property(e)
4074 }
4075 Expression::WithTableHint(e) => self.generate_with_table_hint(e),
4076 Expression::XMLElement(e) => self.generate_xml_element(e),
4077 Expression::XMLGet(e) => self.generate_xml_get(e),
4078 Expression::XMLKeyValueOption(e) => self.generate_xml_key_value_option(e),
4079 Expression::XMLTable(e) => self.generate_xml_table(e),
4080 Expression::Xor(e) => self.generate_xor(e),
4081 Expression::Zipf(e) => self.generate_zipf(e),
4082 _ => self.write_unsupported_comment("unsupported expression"),
4083 }
4084 }
4085
4086 fn should_handle_tsql_distinct_null_ordering(&self, select: &Select) -> bool {
4087 matches!(
4088 self.config.dialect,
4089 Some(DialectType::TSQL) | Some(DialectType::Fabric)
4090 ) && !self.config.null_ordering_supported
4091 && select.distinct
4092 && select.order_by.as_ref().is_some_and(|order_by| {
4093 order_by
4094 .expressions
4095 .iter()
4096 .any(Self::ordered_requires_tsql_null_ordering_emulation)
4097 })
4098 }
4099
4100 fn ordered_requires_tsql_null_ordering_emulation(ordered: &Ordered) -> bool {
4101 let Some(nulls_first) = ordered.nulls_first else {
4102 return false;
4103 };
4104
4105 let random_ordering = matches!(ordered.this, Expression::Rand(_) | Expression::Random(_));
4106 let target_default_nulls_first = !ordered.desc;
4107
4108 nulls_first != target_default_nulls_first && !random_ordering
4109 }
4110
4111 fn projection_output_identifier(expression: &Expression) -> Option<Identifier> {
4112 match expression {
4113 Expression::Alias(alias) if !alias.alias.name.is_empty() => Some(alias.alias.clone()),
4114 Expression::Column(column) => Some(column.name.clone()),
4115 Expression::Identifier(identifier) => Some(identifier.clone()),
4116 _ => None,
4117 }
4118 }
4119
4120 fn identifier_names_match(left: &Identifier, right: &Identifier) -> bool {
4121 if left.quoted || right.quoted {
4122 left.name == right.name
4123 } else {
4124 left.name.eq_ignore_ascii_case(&right.name)
4125 }
4126 }
4127
4128 fn expression_matches_identifier(expression: &Expression, identifier: &Identifier) -> bool {
4129 match expression {
4130 Expression::Column(column) if column.table.is_none() => {
4131 Self::identifier_names_match(&column.name, identifier)
4132 }
4133 Expression::Identifier(other) => Self::identifier_names_match(other, identifier),
4134 _ => false,
4135 }
4136 }
4137
4138 fn column_expression(identifier: Identifier) -> Expression {
4139 Expression::Column(Box::new(Column {
4140 name: identifier,
4141 table: None,
4142 join_mark: false,
4143 trailing_comments: Vec::new(),
4144 span: None,
4145 inferred_type: None,
4146 }))
4147 }
4148
4149 fn positional_ordering_index(expression: &Expression) -> Option<usize> {
4150 match expression {
4151 Expression::Literal(lit) => match lit.as_ref() {
4152 Literal::Number(n) => {
4153 let value = n.parse::<usize>().ok()?;
4154 value.checked_sub(1)
4155 }
4156 _ => None,
4157 },
4158 _ => None,
4159 }
4160 }
4161
4162 fn projection_sort_expression(expression: &Expression) -> Option<Expression> {
4163 let expression = match expression {
4164 Expression::Alias(alias) => &alias.this,
4165 other => other,
4166 };
4167
4168 match expression {
4169 Expression::Star(_)
4170 | Expression::Literal(_)
4171 | Expression::Null(_)
4172 | Expression::Boolean(_) => None,
4173 _ => Some(expression.clone()),
4174 }
4175 }
4176
4177 fn resolve_positional_order_projection(
4178 projections: &[Expression],
4179 index: usize,
4180 ) -> Option<Expression> {
4181 Self::projection_sort_expression(projections.get(index)?)
4182 }
4183
4184 fn is_direct_grouping_expression(expression: &Expression) -> bool {
4185 match expression {
4186 Expression::Paren(paren) => Self::is_direct_grouping_expression(&paren.this),
4187 Expression::Grouping(_) | Expression::GroupingId(_) => true,
4188 Expression::Function(function) => {
4189 function.name.eq_ignore_ascii_case("GROUPING")
4190 || function.name.eq_ignore_ascii_case("GROUPING_ID")
4191 }
4192 _ => false,
4193 }
4194 }
4195
4196 fn group_by_has_multiple_grouping_levels(group_by: &GroupBy) -> bool {
4197 group_by
4198 .expressions
4199 .iter()
4200 .any(|expression| match expression {
4201 Expression::Cube(_) | Expression::Rollup(_) => true,
4202 Expression::GroupingSets(grouping_sets) => grouping_sets.expressions.len() > 1,
4203 Expression::Function(function)
4204 if function.name.eq_ignore_ascii_case("CUBE")
4205 || function.name.eq_ignore_ascii_case("ROLLUP") =>
4206 {
4207 !function.args.is_empty()
4208 }
4209 Expression::Function(function)
4210 if function.name.eq_ignore_ascii_case("GROUPING SETS") =>
4211 {
4212 function.args.len() > 1
4213 || function.args.first().is_some_and(|expression| {
4214 matches!(expression, Expression::Cube(_) | Expression::Rollup(_))
4215 || matches!(expression,
4216 Expression::Function(nested)
4217 if nested.name.eq_ignore_ascii_case("CUBE")
4218 || nested.name.eq_ignore_ascii_case("ROLLUP")
4219 )
4220 })
4221 }
4222 _ => false,
4223 })
4224 }
4225
4226 fn set_output_identifier_at(expression: &Expression, index: usize) -> Option<Identifier> {
4227 match expression {
4228 Expression::Select(select) => {
4229 Self::projection_output_identifier(select.expressions.get(index)?)
4230 }
4231 Expression::Union(union) => Self::set_output_identifier_at(&union.left, index),
4232 Expression::Intersect(intersect) => {
4233 Self::set_output_identifier_at(&intersect.left, index)
4234 }
4235 Expression::Except(except) => Self::set_output_identifier_at(&except.left, index),
4236 Expression::Subquery(subquery) => subquery
4237 .column_aliases
4238 .get(index)
4239 .cloned()
4240 .or_else(|| Self::set_output_identifier_at(&subquery.this, index)),
4241 _ => None,
4242 }
4243 }
4244
4245 fn resolve_single_subquery_star_projection(
4246 select: &Select,
4247 index: usize,
4248 ) -> Option<Expression> {
4249 if select.expressions.len() != 1
4250 || !matches!(select.expressions.first(), Some(Expression::Star(_)))
4251 {
4252 return None;
4253 }
4254
4255 let from = select.from.as_ref()?;
4256 if from.expressions.len() != 1 {
4257 return None;
4258 }
4259
4260 let Expression::Subquery(subquery) = from.expressions.first()? else {
4261 return None;
4262 };
4263
4264 subquery
4265 .column_aliases
4266 .get(index)
4267 .cloned()
4268 .or_else(|| Self::set_output_identifier_at(&subquery.this, index))
4269 .map(Self::column_expression)
4270 }
4271
4272 fn sole_tsql_ordering_source_qualifier(select: &Select) -> Option<Identifier> {
4273 if !select.joins.is_empty() {
4274 return None;
4275 }
4276
4277 let from = select.from.as_ref()?;
4278 if from.expressions.len() != 1 {
4279 return None;
4280 }
4281
4282 match from.expressions.first()? {
4283 Expression::Table(table) => {
4284 Some(table.alias.clone().unwrap_or_else(|| table.name.clone()))
4285 }
4286 Expression::Subquery(subquery) => subquery.alias.clone(),
4287 _ => None,
4288 }
4289 }
4290
4291 fn resolve_duplicate_tsql_ordering_column(
4292 select: &Select,
4293 expression: &Expression,
4294 ) -> Option<Expression> {
4295 let Expression::Column(order_column) = expression else {
4296 return None;
4297 };
4298 if order_column.table.is_some() {
4299 return None;
4300 }
4301
4302 let matching_projections: Vec<_> = select
4303 .expressions
4304 .iter()
4305 .filter(|projection| {
4306 Self::projection_output_identifier(projection).is_some_and(|identifier| {
4307 Self::identifier_names_match(&identifier, &order_column.name)
4308 })
4309 })
4310 .filter_map(Self::projection_sort_expression)
4311 .collect();
4312
4313 if matching_projections.len() < 2
4314 || matching_projections[1..]
4315 .iter()
4316 .any(|projection| projection != &matching_projections[0])
4317 {
4318 return None;
4319 }
4320
4321 let Expression::Column(projected_column) = &matching_projections[0] else {
4322 return None;
4323 };
4324 if !Self::identifier_names_match(&projected_column.name, &order_column.name) {
4325 return None;
4326 }
4327
4328 let qualifier = projected_column
4329 .table
4330 .clone()
4331 .or_else(|| Self::sole_tsql_ordering_source_qualifier(select))?;
4332 let mut resolved = order_column.as_ref().clone();
4333 resolved.table = Some(qualifier);
4334 Some(Expression::Column(Box::new(resolved)))
4335 }
4336
4337 fn resolve_tsql_null_ordering_for_select(&self, select: &Select) -> Option<Select> {
4338 if !matches!(
4339 self.config.dialect,
4340 Some(DialectType::TSQL) | Some(DialectType::Fabric)
4341 ) || self.config.null_ordering_supported
4342 {
4343 return None;
4344 }
4345
4346 let order_by = select.order_by.as_ref()?;
4347 let grouping_order_is_constant = matches!(self.config.dialect, Some(DialectType::Fabric))
4348 && select
4349 .group_by
4350 .as_ref()
4351 .is_some_and(|group_by| !Self::group_by_has_multiple_grouping_levels(group_by));
4352 let mut resolved_expressions = Vec::with_capacity(order_by.expressions.len());
4353 let mut changed = false;
4354
4355 for mut ordered in order_by.expressions.iter().cloned() {
4356 if Self::ordered_requires_tsql_null_ordering_emulation(&ordered) {
4357 if let Some(index) = Self::positional_ordering_index(&ordered.this) {
4358 if let Some(resolved) =
4359 Self::resolve_positional_order_projection(&select.expressions, index)
4360 .or_else(|| {
4361 Self::resolve_single_subquery_star_projection(select, index)
4362 })
4363 {
4364 if resolved != ordered.this {
4365 ordered.this = resolved;
4366 changed = true;
4367 }
4368 }
4369 }
4370
4371 if let Some(resolved) =
4372 Self::resolve_duplicate_tsql_ordering_column(select, &ordered.this)
4373 {
4374 ordered.this = resolved;
4375 changed = true;
4376 }
4377 }
4378
4379 if grouping_order_is_constant && Self::is_direct_grouping_expression(&ordered.this) {
4383 changed = true;
4384 continue;
4385 }
4386
4387 resolved_expressions.push(ordered);
4388 }
4389
4390 if changed {
4391 let mut resolved_select = select.clone();
4392 resolved_select.order_by = if resolved_expressions.is_empty() {
4393 None
4394 } else {
4395 Some(OrderBy {
4396 expressions: resolved_expressions,
4397 siblings: order_by.siblings,
4398 comments: order_by.comments.clone(),
4399 })
4400 };
4401 Some(resolved_select)
4402 } else {
4403 None
4404 }
4405 }
4406
4407 fn resolve_distinct_order_projection(
4408 projections: &[Expression],
4409 order_expression: &Expression,
4410 ) -> Option<Expression> {
4411 for projection in projections {
4412 if let Expression::Alias(alias) = projection {
4413 if Self::expression_matches_identifier(order_expression, &alias.alias)
4414 || &alias.this == order_expression
4415 {
4416 return Some(alias.this.clone());
4417 }
4418 } else if projection == order_expression {
4419 return Some(projection.clone());
4420 } else if let Some(identifier) = Self::projection_output_identifier(projection) {
4421 if Self::expression_matches_identifier(order_expression, &identifier) {
4422 return Some(projection.clone());
4423 }
4424 }
4425 }
4426
4427 None
4428 }
4429
4430 fn fresh_polyglot_alias(base: &str, index: usize, used_names: &mut Vec<String>) -> String {
4431 let mut suffix = 0;
4432 loop {
4433 let candidate = if suffix == 0 {
4434 format!("{base}_{index}")
4435 } else {
4436 format!("{base}_{index}_{suffix}")
4437 };
4438
4439 if !used_names
4440 .iter()
4441 .any(|name| name.eq_ignore_ascii_case(&candidate))
4442 {
4443 used_names.push(candidate.clone());
4444 return candidate;
4445 }
4446
4447 suffix += 1;
4448 }
4449 }
4450
4451 fn tsql_null_ordering_case(expression: Expression) -> Expression {
4452 Expression::Case(Box::new(Case {
4453 operand: None,
4454 whens: vec![(
4455 Expression::IsNull(Box::new(IsNull {
4456 this: expression,
4457 not: false,
4458 postfix_form: false,
4459 })),
4460 Expression::number(1),
4461 )],
4462 else_: Some(Expression::number(0)),
4463 comments: Vec::new(),
4464 inferred_type: None,
4465 }))
4466 }
4467
4468 fn try_build_tsql_distinct_null_ordering_wrapper(&self, select: &Select) -> Option<Select> {
4469 let order_by = select.order_by.as_ref()?;
4470
4471 if order_by.siblings
4472 || select.distinct_on.is_some()
4473 || select.distribute_by.is_some()
4474 || select.cluster_by.is_some()
4475 || select.sort_by.is_some()
4476 || select.limit.is_some()
4477 || select.offset.is_some()
4478 || select.limit_by.is_some()
4479 || select.fetch.is_some()
4480 || select.top.is_some()
4481 || select.settings.is_some()
4482 || select.format.is_some()
4483 || select.kind.is_some()
4484 || select.hint.is_some()
4485 || select.into.is_some()
4486 || !select.locks.is_empty()
4487 || !select.for_xml.is_empty()
4488 || !select.for_json.is_empty()
4489 || !select.operation_modifiers.is_empty()
4490 || select.option.is_some()
4491 || select.exclude.is_some()
4492 {
4493 return None;
4494 }
4495
4496 let projection_identifiers: Vec<_> = select
4497 .expressions
4498 .iter()
4499 .map(Self::projection_output_identifier)
4500 .collect::<Option<_>>()?;
4501 let mut used_names: Vec<_> = projection_identifiers
4502 .iter()
4503 .map(|identifier| identifier.name.clone())
4504 .collect();
4505
4506 let mut inner = select.clone();
4507 inner.order_by = None;
4508
4509 let outer_with = inner.with.take();
4510 let outer_leading_comments = std::mem::take(&mut inner.leading_comments);
4511 let outer_post_select_comments = std::mem::take(&mut inner.post_select_comments);
4512
4513 let mut outer_order_expressions = Vec::with_capacity(order_by.expressions.len() * 2);
4514 for (index, ordered) in order_by.expressions.iter().enumerate() {
4515 if ordered.with_fill.is_some() {
4516 return None;
4517 }
4518
4519 let sort_expression =
4520 Self::resolve_distinct_order_projection(&select.expressions, &ordered.this)?;
4521
4522 if Self::ordered_requires_tsql_null_ordering_emulation(ordered) {
4523 let null_alias =
4524 Self::fresh_polyglot_alias("_polyglot_order_null", index, &mut used_names);
4525 inner.expressions.push(
4526 Self::tsql_null_ordering_case(sort_expression.clone())
4527 .alias(null_alias.clone()),
4528 );
4529 outer_order_expressions.push(Ordered {
4530 this: Expression::column(null_alias),
4531 desc: ordered.nulls_first == Some(true),
4532 nulls_first: None,
4533 explicit_asc: false,
4534 with_fill: None,
4535 });
4536 }
4537
4538 let key_alias =
4539 Self::fresh_polyglot_alias("_polyglot_order_key", index, &mut used_names);
4540 inner
4541 .expressions
4542 .push(sort_expression.alias(key_alias.clone()));
4543 outer_order_expressions.push(Ordered {
4544 this: Expression::column(key_alias),
4545 desc: ordered.desc,
4546 nulls_first: None,
4547 explicit_asc: ordered.explicit_asc,
4548 with_fill: None,
4549 });
4550 }
4551
4552 let subquery = Subquery {
4553 this: Expression::Select(Box::new(inner)),
4554 alias: Some(Identifier::new("_polyglot_distinct_order")),
4555 column_aliases: Vec::new(),
4556 alias_explicit_as: true,
4557 alias_keyword: None,
4558 order_by: None,
4559 limit: None,
4560 offset: None,
4561 distribute_by: None,
4562 sort_by: None,
4563 cluster_by: None,
4564 lateral: false,
4565 modifiers_inside: false,
4566 trailing_comments: Vec::new(),
4567 inferred_type: None,
4568 };
4569
4570 let mut outer = Select::new();
4571 outer.with = outer_with;
4572 outer.leading_comments = outer_leading_comments;
4573 outer.post_select_comments = outer_post_select_comments;
4574 outer.expressions = projection_identifiers
4575 .into_iter()
4576 .map(Self::column_expression)
4577 .collect();
4578 outer.from = Some(From {
4579 expressions: vec![Expression::Subquery(Box::new(subquery))],
4580 });
4581 outer.order_by = Some(OrderBy {
4582 expressions: outer_order_expressions,
4583 siblings: false,
4584 comments: order_by.comments.clone(),
4585 });
4586
4587 Some(outer)
4588 }
4589
4590 fn generate_select(&mut self, select: &Select) -> Result<()> {
4591 use crate::dialects::DialectType;
4592
4593 if let Some(resolved_select) = self.resolve_tsql_null_ordering_for_select(select) {
4594 return self.generate_select(&resolved_select);
4595 }
4596
4597 if self.should_handle_tsql_distinct_null_ordering(select) {
4598 if let Some(wrapped_select) = self.try_build_tsql_distinct_null_ordering_wrapper(select)
4599 {
4600 return self.generate_select(&wrapped_select);
4601 }
4602
4603 self.unsupported(
4604 "SELECT DISTINCT with emulated NULL ordering is not supported for TSQL/Fabric",
4605 )?;
4606 }
4607
4608 if let Some(exclude) = &select.exclude {
4612 if !exclude.is_empty() && !matches!(self.config.dialect, Some(DialectType::Redshift)) {
4613 let mut inner_select = select.clone();
4615 inner_select.exclude = None;
4616 let inner_expr = Expression::Select(Box::new(inner_select));
4617
4618 let subquery = crate::expressions::Subquery {
4620 this: inner_expr,
4621 alias: None,
4622 column_aliases: Vec::new(),
4623 alias_explicit_as: false,
4624 alias_keyword: None,
4625 order_by: None,
4626 limit: None,
4627 offset: None,
4628 distribute_by: None,
4629 sort_by: None,
4630 cluster_by: None,
4631 lateral: false,
4632 modifiers_inside: false,
4633 trailing_comments: Vec::new(),
4634 inferred_type: None,
4635 };
4636
4637 let star = Expression::Star(crate::expressions::Star {
4639 table: None,
4640 except: Some(
4641 exclude
4642 .iter()
4643 .map(|e| match e {
4644 Expression::Column(col) => col.name.clone(),
4645 Expression::Identifier(id) => id.clone(),
4646 _ => crate::expressions::Identifier::new("unknown".to_string()),
4647 })
4648 .collect(),
4649 ),
4650 replace: None,
4651 rename: None,
4652 trailing_comments: Vec::new(),
4653 span: None,
4654 });
4655
4656 let outer_select = Select {
4657 expressions: vec![star],
4658 from: Some(crate::expressions::From {
4659 expressions: vec![Expression::Subquery(Box::new(subquery))],
4660 }),
4661 ..Select::new()
4662 };
4663
4664 return self.generate_select(&outer_select);
4665 }
4666 }
4667
4668 for comment in &select.leading_comments {
4670 self.write_formatted_comment(comment);
4671 self.write(" ");
4672 }
4673
4674 if let Some(with) = &select.with {
4676 self.generate_with(with)?;
4677 if self.config.pretty {
4678 self.write_newline();
4679 self.write_indent();
4680 } else {
4681 self.write_space();
4682 }
4683 }
4684
4685 for comment in &select.post_select_comments {
4688 self.write_formatted_comment(comment);
4689 self.write(" ");
4690 }
4691
4692 self.write_keyword("SELECT");
4693
4694 if let Some(hint) = &select.hint {
4696 self.generate_hint(hint)?;
4697 }
4698
4699 let use_top_from_limit = matches!(
4703 self.config.dialect,
4704 Some(DialectType::TSQL) | Some(DialectType::Fabric)
4705 ) && select.top.is_none()
4706 && select
4707 .limit
4708 .as_ref()
4709 .is_some_and(|limit| !Self::is_noop_limit_expr(&limit.this))
4710 && select.offset.is_none(); let is_top_dialect = matches!(
4715 self.config.dialect,
4716 Some(DialectType::TSQL) | Some(DialectType::Teradata) | Some(DialectType::Fabric)
4717 );
4718 let keep_top_verbatim = !is_top_dialect
4719 && select.limit.is_none()
4720 && select
4721 .top
4722 .as_ref()
4723 .map_or(false, |top| top.percent || top.with_ties);
4724
4725 if select.distinct && (is_top_dialect || select.top.is_some()) {
4726 self.write_space();
4727 self.write_keyword("DISTINCT");
4728 }
4729
4730 if is_top_dialect || keep_top_verbatim {
4731 if let Some(top) = &select.top {
4732 self.write_space();
4733 self.write_keyword("TOP");
4734 if top.parenthesized {
4735 if matches!(&top.this, Expression::Subquery(_) | Expression::Paren(_)) {
4736 self.write_space();
4737 self.generate_expression(&top.this)?;
4738 } else {
4739 self.write(" (");
4740 self.generate_expression(&top.this)?;
4741 self.write(")");
4742 }
4743 } else {
4744 self.write_space();
4745 self.generate_expression(&top.this)?;
4746 }
4747 if top.percent {
4748 self.write_space();
4749 self.write_keyword("PERCENT");
4750 }
4751 if top.with_ties {
4752 self.write_space();
4753 self.write_keyword("WITH TIES");
4754 }
4755 } else if use_top_from_limit {
4756 if let Some(limit) = &select.limit {
4758 self.write_space();
4759 self.write_keyword("TOP");
4760 let is_simple_literal = matches!(&limit.this, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)));
4762 if is_simple_literal {
4763 self.write_space();
4764 self.generate_expression(&limit.this)?;
4765 } else {
4766 self.write(" (");
4767 self.generate_expression(&limit.this)?;
4768 self.write(")");
4769 }
4770 }
4771 }
4772 }
4773
4774 if select.distinct && !is_top_dialect && select.top.is_none() {
4775 self.write_space();
4776 self.write_keyword("DISTINCT");
4777 }
4778
4779 if let Some(distinct_on) = &select.distinct_on {
4781 self.write_space();
4782 self.write_keyword("ON");
4783 self.write(" (");
4784 for (i, expr) in distinct_on.iter().enumerate() {
4785 if i > 0 {
4786 self.write(", ");
4787 }
4788 self.generate_expression(expr)?;
4789 }
4790 self.write(")");
4791 }
4792
4793 for modifier in &select.operation_modifiers {
4795 self.write_space();
4796 self.write_keyword(modifier);
4797 }
4798
4799 if let Some(kind) = &select.kind {
4801 self.write_space();
4802 self.write_keyword("AS");
4803 self.write_space();
4804 self.write_keyword(kind);
4805 }
4806
4807 if !select.expressions.is_empty() {
4809 if self.config.pretty {
4810 self.write_newline();
4811 self.indent_level += 1;
4812 } else {
4813 self.write_space();
4814 }
4815 }
4816
4817 for (i, expr) in select.expressions.iter().enumerate() {
4818 if i > 0 {
4819 self.write(",");
4820 if self.config.pretty {
4821 self.write_newline();
4822 } else {
4823 self.write_space();
4824 }
4825 }
4826 if self.config.pretty {
4827 self.write_indent();
4828 }
4829 self.generate_expression(expr)?;
4830 }
4831
4832 if self.config.pretty && !select.expressions.is_empty() {
4833 self.indent_level -= 1;
4834 }
4835
4836 if let Some(exclude) = &select.exclude {
4841 if !exclude.is_empty() && matches!(self.config.dialect, Some(DialectType::Redshift)) {
4842 self.write_space();
4843 self.write_keyword("EXCLUDE");
4844 self.write(" (");
4845 for (i, col) in exclude.iter().enumerate() {
4846 if i > 0 {
4847 self.write(", ");
4848 }
4849 self.generate_expression(col)?;
4850 }
4851 self.write(")");
4852 }
4853 }
4854
4855 if let Some(into) = &select.into {
4858 if self.config.pretty {
4859 self.write_newline();
4860 self.write_indent();
4861 } else {
4862 self.write_space();
4863 }
4864 if into.bulk_collect {
4865 self.write_keyword("BULK COLLECT INTO");
4866 } else {
4867 self.write_keyword("INTO");
4868 }
4869 if into.temporary {
4870 self.write_space();
4871 self.write_keyword("TEMPORARY");
4872 }
4873 if into.unlogged {
4874 self.write_space();
4875 self.write_keyword("UNLOGGED");
4876 }
4877 self.write_space();
4878 if !into.expressions.is_empty() {
4880 for (i, expr) in into.expressions.iter().enumerate() {
4881 if i > 0 {
4882 self.write(", ");
4883 }
4884 self.generate_expression(expr)?;
4885 }
4886 } else {
4887 self.generate_expression(&into.this)?;
4888 }
4889 }
4890
4891 if let Some(from) = &select.from {
4893 if self.config.pretty {
4894 self.write_newline();
4895 self.write_indent();
4896 } else {
4897 self.write_space();
4898 }
4899 self.write_keyword("FROM");
4900 self.write_space();
4901
4902 let has_tablesample = from
4907 .expressions
4908 .iter()
4909 .any(|e| matches!(e, Expression::TableSample(_)));
4910 let is_cross_join_dialect = matches!(
4911 self.config.dialect,
4912 Some(DialectType::BigQuery)
4913 | Some(DialectType::Hive)
4914 | Some(DialectType::Spark)
4915 | Some(DialectType::Databricks)
4916 | Some(DialectType::SQLite)
4917 | Some(DialectType::ClickHouse)
4918 );
4919 let source_is_same_as_target = self.config.source_dialect.is_some()
4922 && self.config.source_dialect == self.config.dialect;
4923 let source_is_cross_join_dialect = matches!(
4924 self.config.source_dialect,
4925 Some(DialectType::BigQuery)
4926 | Some(DialectType::Hive)
4927 | Some(DialectType::Spark)
4928 | Some(DialectType::Databricks)
4929 | Some(DialectType::SQLite)
4930 | Some(DialectType::ClickHouse)
4931 );
4932 let use_cross_join = !has_tablesample
4933 && is_cross_join_dialect
4934 && (source_is_same_as_target
4935 || source_is_cross_join_dialect
4936 || self.config.source_dialect.is_none());
4937
4938 let wrap_values_in_parens = self.config.dialect.is_none()
4941 || matches!(
4942 self.config.dialect,
4943 Some(
4944 DialectType::Generic
4945 | DialectType::Snowflake
4946 | DialectType::Presto
4947 | DialectType::Trino
4948 | DialectType::Athena
4949 )
4950 );
4951
4952 for (i, expr) in from.expressions.iter().enumerate() {
4953 if i > 0 {
4954 if use_cross_join {
4955 self.write(" CROSS JOIN ");
4956 } else {
4957 self.write(", ");
4958 }
4959 }
4960 self.generate_from_source(expr, wrap_values_in_parens)?;
4961 let leading = Self::extract_table_leading_comments(expr);
4964 for comment in &leading {
4965 self.write_space();
4966 self.write_formatted_comment(comment);
4967 }
4968 }
4969 }
4970
4971 if self.config.pretty {
4975 self.generate_joins_with_nesting(&select.joins)?;
4976 } else {
4977 for join in &select.joins {
4978 self.generate_join(join)?;
4979 }
4980 for join in select.joins.iter().rev() {
4982 if join.deferred_condition {
4983 self.generate_join_condition(join)?;
4984 }
4985 }
4986 }
4987
4988 for (lv_idx, lateral_view) in select.lateral_views.iter().enumerate() {
4990 self.generate_lateral_view(lateral_view, lv_idx)?;
4991 }
4992
4993 if let Some(prewhere) = &select.prewhere {
4995 self.write_clause_condition("PREWHERE", prewhere)?;
4996 }
4997
4998 if let Some(where_clause) = &select.where_clause {
5000 self.write_clause_condition("WHERE", &where_clause.this)?;
5001 }
5002
5003 if let Some(connect) = &select.connect {
5005 self.generate_connect(connect)?;
5006 }
5007
5008 if let Some(group_by) = &select.group_by {
5010 if self.config.pretty {
5011 for comment in &group_by.comments {
5013 self.write_newline();
5014 self.write_indent();
5015 self.write_formatted_comment(comment);
5016 }
5017 self.write_newline();
5018 self.write_indent();
5019 } else {
5020 self.write_space();
5021 for comment in &group_by.comments {
5023 self.write_formatted_comment(comment);
5024 self.write_space();
5025 }
5026 }
5027 let clickhouse_bare_modifiers =
5028 matches!(self.config.dialect, Some(DialectType::ClickHouse))
5029 && group_by.all.is_none()
5030 && (group_by.totals || !group_by.expressions.is_empty())
5031 && group_by.expressions.iter().all(|expr| match expr {
5032 Expression::Cube(c) => c.expressions.is_empty(),
5033 Expression::Rollup(r) => r.expressions.is_empty(),
5034 _ => false,
5035 });
5036
5037 if clickhouse_bare_modifiers {
5038 let trailing_cube = group_by
5039 .expressions
5040 .iter()
5041 .any(|expr| matches!(expr, Expression::Cube(c) if c.expressions.is_empty()));
5042 let trailing_rollup = group_by
5043 .expressions
5044 .iter()
5045 .any(|expr| matches!(expr, Expression::Rollup(r) if r.expressions.is_empty()));
5046
5047 if trailing_cube {
5048 self.write_keyword("WITH CUBE");
5049 } else if trailing_rollup {
5050 self.write_keyword("WITH ROLLUP");
5051 }
5052
5053 if group_by.totals {
5054 if trailing_cube || trailing_rollup {
5055 self.write_space();
5056 }
5057 self.write_keyword("WITH TOTALS");
5058 }
5059 } else {
5060 self.write_keyword("GROUP BY");
5061 match group_by.all {
5063 Some(true) => {
5064 self.write_space();
5065 self.write_keyword("ALL");
5066 }
5067 Some(false) => {
5068 self.write_space();
5069 self.write_keyword("DISTINCT");
5070 }
5071 None => {}
5072 }
5073 if !group_by.expressions.is_empty() {
5074 let mut trailing_cube = false;
5077 let mut trailing_rollup = false;
5078 let mut plain_expressions: Vec<&Expression> = Vec::new();
5079 let mut grouping_sets_expressions: Vec<&Expression> = Vec::new();
5080 let mut cube_expressions: Vec<&Expression> = Vec::new();
5081 let mut rollup_expressions: Vec<&Expression> = Vec::new();
5082
5083 for expr in &group_by.expressions {
5084 match expr {
5085 Expression::Cube(c) if c.expressions.is_empty() => {
5086 trailing_cube = true;
5087 }
5088 Expression::Rollup(r) if r.expressions.is_empty() => {
5089 trailing_rollup = true;
5090 }
5091 Expression::Function(f) if f.name == "CUBE" => {
5092 cube_expressions.push(expr);
5093 }
5094 Expression::Function(f) if f.name == "ROLLUP" => {
5095 rollup_expressions.push(expr);
5096 }
5097 Expression::Function(f) if f.name == "GROUPING SETS" => {
5098 grouping_sets_expressions.push(expr);
5099 }
5100 _ => {
5101 plain_expressions.push(expr);
5102 }
5103 }
5104 }
5105
5106 let mut regular_expressions: Vec<&Expression> = Vec::new();
5108 regular_expressions.extend(plain_expressions);
5109 regular_expressions.extend(grouping_sets_expressions);
5110 regular_expressions.extend(cube_expressions);
5111 regular_expressions.extend(rollup_expressions);
5112
5113 if self.config.pretty {
5114 self.write_newline();
5115 self.indent_level += 1;
5116 self.write_indent();
5117 } else {
5118 self.write_space();
5119 }
5120
5121 for (i, expr) in regular_expressions.iter().enumerate() {
5122 if i > 0 {
5123 if self.config.pretty {
5124 self.write(",");
5125 self.write_newline();
5126 self.write_indent();
5127 } else {
5128 self.write(", ");
5129 }
5130 }
5131 self.generate_expression(expr)?;
5132 }
5133
5134 if self.config.pretty {
5135 self.indent_level -= 1;
5136 }
5137
5138 if trailing_cube {
5140 self.write_space();
5141 self.write_keyword("WITH CUBE");
5142 } else if trailing_rollup {
5143 self.write_space();
5144 self.write_keyword("WITH ROLLUP");
5145 }
5146 }
5147
5148 if group_by.totals {
5150 self.write_space();
5151 self.write_keyword("WITH TOTALS");
5152 }
5153 }
5154 }
5155
5156 if let Some(having) = &select.having {
5158 if self.config.pretty {
5159 for comment in &having.comments {
5161 self.write_newline();
5162 self.write_indent();
5163 self.write_formatted_comment(comment);
5164 }
5165 } else {
5166 for comment in &having.comments {
5167 self.write_space();
5168 self.write_formatted_comment(comment);
5169 }
5170 }
5171 self.write_clause_condition("HAVING", &having.this)?;
5172 }
5173
5174 if select.qualify_after_window {
5176 if let Some(windows) = &select.windows {
5178 self.write_window_clause(windows)?;
5179 }
5180 if let Some(qualify) = &select.qualify {
5181 self.write_clause_condition("QUALIFY", &qualify.this)?;
5182 }
5183 } else {
5184 if let Some(qualify) = &select.qualify {
5186 self.write_clause_condition("QUALIFY", &qualify.this)?;
5187 }
5188 if let Some(windows) = &select.windows {
5189 self.write_window_clause(windows)?;
5190 }
5191 }
5192
5193 if let Some(distribute_by) = &select.distribute_by {
5195 self.write_clause_expressions("DISTRIBUTE BY", &distribute_by.expressions)?;
5196 }
5197
5198 if let Some(cluster_by) = &select.cluster_by {
5200 self.write_order_clause("CLUSTER BY", &cluster_by.expressions)?;
5201 }
5202
5203 if let Some(sort_by) = &select.sort_by {
5205 self.write_order_clause("SORT BY", &sort_by.expressions)?;
5206 }
5207
5208 if let Some(order_by) = &select.order_by {
5210 if self.config.pretty {
5211 for comment in &order_by.comments {
5213 self.write_newline();
5214 self.write_indent();
5215 self.write_formatted_comment(comment);
5216 }
5217 } else {
5218 for comment in &order_by.comments {
5219 self.write_space();
5220 self.write_formatted_comment(comment);
5221 }
5222 }
5223 let keyword = if order_by.siblings {
5224 "ORDER SIBLINGS BY"
5225 } else {
5226 "ORDER BY"
5227 };
5228 self.write_order_clause(keyword, &order_by.expressions)?;
5229 }
5230
5231 if select.order_by.is_none()
5233 && select.fetch.is_some()
5234 && matches!(
5235 self.config.dialect,
5236 Some(DialectType::TSQL) | Some(DialectType::Fabric)
5237 )
5238 {
5239 if self.config.pretty {
5240 self.write_newline();
5241 self.write_indent();
5242 } else {
5243 self.write_space();
5244 }
5245 self.write_keyword("ORDER BY (SELECT NULL) OFFSET 0 ROWS");
5246 }
5247
5248 let is_presto_like = matches!(
5253 self.config.dialect,
5254 Some(DialectType::Presto) | Some(DialectType::Trino)
5255 );
5256
5257 if is_presto_like && select.offset.is_some() {
5258 if let Some(offset) = &select.offset {
5260 if self.config.pretty {
5261 self.write_newline();
5262 self.write_indent();
5263 } else {
5264 self.write_space();
5265 }
5266 self.write_keyword("OFFSET");
5267 self.write_space();
5268 self.write_limit_expr(&offset.this)?;
5269 if offset.rows == Some(true) {
5270 self.write_space();
5271 self.write_keyword("ROWS");
5272 }
5273 }
5274 if let Some(limit) = &select.limit {
5275 if self.config.pretty {
5276 self.write_newline();
5277 self.write_indent();
5278 } else {
5279 self.write_space();
5280 }
5281 self.write_keyword("LIMIT");
5282 self.write_space();
5283 self.write_limit_expr(&limit.this)?;
5284 if limit.percent {
5285 self.write_space();
5286 self.write_keyword("PERCENT");
5287 }
5288 for comment in &limit.comments {
5290 self.write(" ");
5291 self.write_formatted_comment(comment);
5292 }
5293 }
5294 } else {
5295 let fetch_as_limit = select.fetch.as_ref().map_or(false, |fetch| {
5297 !fetch.percent
5298 && !fetch.with_ties
5299 && fetch.count.is_some()
5300 && matches!(
5301 self.config.dialect,
5302 Some(DialectType::Spark)
5303 | Some(DialectType::Hive)
5304 | Some(DialectType::DuckDB)
5305 | Some(DialectType::SQLite)
5306 | Some(DialectType::MySQL)
5307 | Some(DialectType::BigQuery)
5308 | Some(DialectType::Databricks)
5309 | Some(DialectType::StarRocks)
5310 | Some(DialectType::Doris)
5311 | Some(DialectType::Athena)
5312 | Some(DialectType::ClickHouse)
5313 | Some(DialectType::Redshift)
5314 )
5315 });
5316
5317 if let Some(limit) = &select.limit {
5319 if !matches!(
5321 self.config.dialect,
5322 Some(DialectType::TSQL) | Some(DialectType::Fabric)
5323 ) {
5324 if self.config.pretty {
5325 self.write_newline();
5326 self.write_indent();
5327 } else {
5328 self.write_space();
5329 }
5330 self.write_keyword("LIMIT");
5331 self.write_space();
5332 self.write_limit_expr(&limit.this)?;
5333 if limit.percent {
5334 self.write_space();
5335 self.write_keyword("PERCENT");
5336 }
5337 for comment in &limit.comments {
5339 self.write(" ");
5340 self.write_formatted_comment(comment);
5341 }
5342 }
5343 }
5344
5345 if select.top.is_some() && !is_top_dialect && select.limit.is_none() {
5347 if let Some(top) = &select.top {
5348 if !top.percent && !top.with_ties {
5349 if self.config.pretty {
5350 self.write_newline();
5351 self.write_indent();
5352 } else {
5353 self.write_space();
5354 }
5355 self.write_keyword("LIMIT");
5356 self.write_space();
5357 self.generate_expression(&top.this)?;
5358 }
5359 }
5360 }
5361
5362 if fetch_as_limit && select.offset.is_some() {
5365 if let Some(fetch) = &select.fetch {
5366 if self.config.pretty {
5367 self.write_newline();
5368 self.write_indent();
5369 } else {
5370 self.write_space();
5371 }
5372 self.write_keyword("LIMIT");
5373 self.write_space();
5374 self.generate_expression(fetch.count.as_ref().unwrap())?;
5375 }
5376 }
5377
5378 if let Some(offset) = &select.offset {
5382 if self.config.pretty {
5383 self.write_newline();
5384 self.write_indent();
5385 } else {
5386 self.write_space();
5387 }
5388 if matches!(
5389 self.config.dialect,
5390 Some(DialectType::TSQL) | Some(DialectType::Fabric)
5391 ) {
5392 self.write_keyword("OFFSET");
5394 self.write_space();
5395 self.write_limit_expr(&offset.this)?;
5396 self.write_space();
5397 self.write_keyword("ROWS");
5398 if let Some(limit) = &select.limit {
5402 if !Self::is_noop_limit_expr(&limit.this) {
5403 self.write_space();
5404 self.write_keyword("FETCH NEXT");
5405 self.write_space();
5406 self.write_limit_expr(&limit.this)?;
5407 self.write_space();
5408 self.write_keyword("ROWS ONLY");
5409 }
5410 }
5411 } else {
5412 self.write_keyword("OFFSET");
5413 self.write_space();
5414 self.write_limit_expr(&offset.this)?;
5415 if offset.rows == Some(true) {
5417 self.write_space();
5418 self.write_keyword("ROWS");
5419 }
5420 }
5421 }
5422 }
5423
5424 if matches!(self.config.dialect, Some(DialectType::ClickHouse)) {
5426 if let Some(limit_by) = &select.limit_by {
5427 if !limit_by.is_empty() {
5428 self.write_space();
5429 self.write_keyword("BY");
5430 self.write_space();
5431 for (i, expr) in limit_by.iter().enumerate() {
5432 if i > 0 {
5433 self.write(", ");
5434 }
5435 self.generate_expression(expr)?;
5436 }
5437 }
5438 }
5439 }
5440
5441 if matches!(self.config.dialect, Some(DialectType::ClickHouse)) {
5443 if let Some(settings) = &select.settings {
5444 if self.config.pretty {
5445 self.write_newline();
5446 self.write_indent();
5447 } else {
5448 self.write_space();
5449 }
5450 self.write_keyword("SETTINGS");
5451 self.write_space();
5452 for (i, expr) in settings.iter().enumerate() {
5453 if i > 0 {
5454 self.write(", ");
5455 }
5456 self.generate_expression(expr)?;
5457 }
5458 }
5459
5460 if let Some(format_expr) = &select.format {
5461 if self.config.pretty {
5462 self.write_newline();
5463 self.write_indent();
5464 } else {
5465 self.write_space();
5466 }
5467 self.write_keyword("FORMAT");
5468 self.write_space();
5469 self.generate_expression(format_expr)?;
5470 }
5471 }
5472
5473 if let Some(fetch) = &select.fetch {
5475 let fetch_already_as_limit = select.offset.is_some()
5477 && !fetch.percent
5478 && !fetch.with_ties
5479 && fetch.count.is_some()
5480 && matches!(
5481 self.config.dialect,
5482 Some(DialectType::Spark)
5483 | Some(DialectType::Hive)
5484 | Some(DialectType::DuckDB)
5485 | Some(DialectType::SQLite)
5486 | Some(DialectType::MySQL)
5487 | Some(DialectType::BigQuery)
5488 | Some(DialectType::Databricks)
5489 | Some(DialectType::StarRocks)
5490 | Some(DialectType::Doris)
5491 | Some(DialectType::Athena)
5492 | Some(DialectType::ClickHouse)
5493 | Some(DialectType::Redshift)
5494 );
5495
5496 if fetch_already_as_limit {
5497 } else {
5499 if self.config.pretty {
5500 self.write_newline();
5501 self.write_indent();
5502 } else {
5503 self.write_space();
5504 }
5505
5506 let use_limit = !fetch.percent
5508 && !fetch.with_ties
5509 && matches!(
5510 self.config.dialect,
5511 Some(DialectType::Spark)
5512 | Some(DialectType::Hive)
5513 | Some(DialectType::DuckDB)
5514 | Some(DialectType::SQLite)
5515 | Some(DialectType::MySQL)
5516 | Some(DialectType::BigQuery)
5517 | Some(DialectType::Databricks)
5518 | Some(DialectType::StarRocks)
5519 | Some(DialectType::Doris)
5520 | Some(DialectType::Athena)
5521 | Some(DialectType::ClickHouse)
5522 | Some(DialectType::Redshift)
5523 );
5524
5525 if use_limit {
5526 self.write_keyword("LIMIT");
5527 self.write_space();
5528 if let Some(count) = &fetch.count {
5529 self.generate_expression(count)?;
5530 } else {
5531 self.write("1");
5532 }
5533 } else {
5534 self.write_keyword("FETCH");
5535 self.write_space();
5536 self.write_keyword(&fetch.direction);
5537 if let Some(ref count) = fetch.count {
5538 self.write_space();
5539 self.generate_expression(count)?;
5540 }
5541 if fetch.percent {
5542 self.write_space();
5543 self.write_keyword("PERCENT");
5544 }
5545 if fetch.rows {
5546 self.write_space();
5547 self.write_keyword("ROWS");
5548 }
5549 if fetch.with_ties {
5550 self.write_space();
5551 self.write_keyword("WITH TIES");
5552 } else {
5553 self.write_space();
5554 self.write_keyword("ONLY");
5555 }
5556 }
5557 } }
5559
5560 if let Some(sample) = &select.sample {
5562 use crate::dialects::DialectType;
5563 if self.config.pretty {
5564 self.write_newline();
5565 } else {
5566 self.write_space();
5567 }
5568
5569 if sample.is_using_sample {
5570 self.write_keyword("USING SAMPLE");
5572 self.generate_sample_body(sample)?;
5573 } else {
5574 self.write_keyword("TABLESAMPLE");
5575
5576 let snowflake_bernoulli =
5578 matches!(self.config.dialect, Some(DialectType::Snowflake))
5579 && !sample.explicit_method;
5580 if snowflake_bernoulli {
5581 self.write_space();
5582 self.write_keyword("BERNOULLI");
5583 }
5584
5585 if matches!(sample.method, SampleMethod::Bucket) {
5587 self.write_space();
5588 self.write("(");
5589 self.write_keyword("BUCKET");
5590 self.write_space();
5591 if let Some(ref num) = sample.bucket_numerator {
5592 self.generate_expression(num)?;
5593 }
5594 self.write_space();
5595 self.write_keyword("OUT OF");
5596 self.write_space();
5597 if let Some(ref denom) = sample.bucket_denominator {
5598 self.generate_expression(denom)?;
5599 }
5600 if let Some(ref field) = sample.bucket_field {
5601 self.write_space();
5602 self.write_keyword("ON");
5603 self.write_space();
5604 self.generate_expression(field)?;
5605 }
5606 self.write(")");
5607 } else if sample.unit_after_size {
5608 if sample.explicit_method && sample.method_before_size {
5610 self.write_space();
5611 match sample.method {
5612 SampleMethod::Bernoulli => self.write_keyword("BERNOULLI"),
5613 SampleMethod::System => self.write_keyword("SYSTEM"),
5614 SampleMethod::Block => self.write_keyword("BLOCK"),
5615 SampleMethod::Row => self.write_keyword("ROW"),
5616 SampleMethod::Reservoir => self.write_keyword("RESERVOIR"),
5617 _ => {}
5618 }
5619 }
5620 self.write(" (");
5621 self.generate_expression(&sample.size)?;
5622 self.write_space();
5623 match sample.method {
5624 SampleMethod::Percent => self.write_keyword("PERCENT"),
5625 SampleMethod::Row => self.write_keyword("ROWS"),
5626 SampleMethod::Reservoir => self.write_keyword("ROWS"),
5627 _ => {
5628 self.write_keyword("PERCENT");
5629 }
5630 }
5631 self.write(")");
5632 } else {
5633 self.write_space();
5635 match sample.method {
5636 SampleMethod::Bernoulli => self.write_keyword("BERNOULLI"),
5637 SampleMethod::System => self.write_keyword("SYSTEM"),
5638 SampleMethod::Block => self.write_keyword("BLOCK"),
5639 SampleMethod::Row => self.write_keyword("ROW"),
5640 SampleMethod::Percent => self.write_keyword("BERNOULLI"),
5641 SampleMethod::Bucket => {}
5642 SampleMethod::Reservoir => self.write_keyword("RESERVOIR"),
5643 }
5644 self.write(" (");
5645 self.generate_expression(&sample.size)?;
5646 if matches!(sample.method, SampleMethod::Percent) {
5647 self.write_space();
5648 self.write_keyword("PERCENT");
5649 }
5650 self.write(")");
5651 }
5652 }
5653
5654 if let Some(seed) = &sample.seed {
5655 self.write_space();
5656 let use_seed = sample.use_seed_keyword
5658 && !matches!(
5659 self.config.dialect,
5660 Some(crate::dialects::DialectType::Databricks)
5661 | Some(crate::dialects::DialectType::Spark)
5662 );
5663 if use_seed {
5664 self.write_keyword("SEED");
5665 } else {
5666 self.write_keyword("REPEATABLE");
5667 }
5668 self.write(" (");
5669 self.generate_expression(seed)?;
5670 self.write(")");
5671 }
5672 }
5673
5674 if self.config.locking_reads_supported {
5677 for lock in &select.locks {
5678 if self.config.pretty {
5679 self.write_newline();
5680 self.write_indent();
5681 } else {
5682 self.write_space();
5683 }
5684 self.generate_lock(lock)?;
5685 }
5686 }
5687
5688 if !select.for_xml.is_empty() {
5690 if self.config.pretty {
5691 self.write_newline();
5692 self.write_indent();
5693 } else {
5694 self.write_space();
5695 }
5696 self.write_keyword("FOR XML");
5697 for (i, opt) in select.for_xml.iter().enumerate() {
5698 if self.config.pretty {
5699 if i > 0 {
5700 self.write(",");
5701 }
5702 self.write_newline();
5703 self.write_indent();
5704 self.write(" "); } else {
5706 if i > 0 {
5707 self.write(",");
5708 }
5709 self.write_space();
5710 }
5711 self.generate_for_xml_option(opt)?;
5712 }
5713 }
5714
5715 if !select.for_json.is_empty()
5717 && matches!(
5718 self.config.dialect,
5719 None | Some(DialectType::TSQL) | Some(DialectType::Fabric)
5720 )
5721 {
5722 if self.config.pretty {
5723 self.write_newline();
5724 self.write_indent();
5725 } else {
5726 self.write_space();
5727 }
5728 self.write_keyword("FOR JSON");
5729 for (i, opt) in select.for_json.iter().enumerate() {
5730 if self.config.pretty {
5731 if i > 0 {
5732 self.write(",");
5733 }
5734 self.write_newline();
5735 self.write_indent();
5736 self.write(" "); } else {
5738 if i > 0 {
5739 self.write(",");
5740 }
5741 self.write_space();
5742 }
5743 self.generate_for_xml_option(opt)?;
5744 }
5745 }
5746
5747 if let Some(ref option) = select.option {
5749 if matches!(
5750 self.config.dialect,
5751 Some(crate::dialects::DialectType::TSQL)
5752 | Some(crate::dialects::DialectType::Fabric)
5753 ) {
5754 self.write_space();
5755 self.write(option);
5756 }
5757 }
5758
5759 Ok(())
5760 }
5761
5762 fn generate_for_xml_option(&mut self, opt: &Expression) -> Result<()> {
5764 match opt {
5765 Expression::QueryOption(qo) => {
5766 if let Expression::Var(var) = &*qo.this {
5768 self.write(&var.this);
5769 } else {
5770 self.generate_expression(&qo.this)?;
5771 }
5772 if let Some(expr) = &qo.expression {
5774 self.write("(");
5775 self.generate_expression(expr)?;
5776 self.write(")");
5777 }
5778 }
5779 _ => {
5780 self.generate_expression(opt)?;
5781 }
5782 }
5783 Ok(())
5784 }
5785
5786 fn generate_with(&mut self, with: &With) -> Result<()> {
5787 use crate::dialects::DialectType;
5788
5789 for comment in &with.leading_comments {
5791 self.write_formatted_comment(comment);
5792 self.write(" ");
5793 }
5794 self.write_keyword("WITH");
5795 if with.recursive && self.config.cte_recursive_keyword_required {
5796 self.write_space();
5797 self.write_keyword("RECURSIVE");
5798 }
5799 self.write_space();
5800
5801 let skip_cte_columns = matches!(self.config.dialect, Some(DialectType::BigQuery));
5803
5804 for (i, cte) in with.ctes.iter().enumerate() {
5805 if i > 0 {
5806 self.write(",");
5807 if self.config.pretty {
5808 self.write_space();
5809 } else {
5810 self.write(" ");
5811 }
5812 }
5813 if matches!(self.config.dialect, Some(DialectType::ClickHouse)) && !cte.alias_first {
5814 self.generate_expression(&cte.this)?;
5815 self.write_space();
5816 self.write_keyword("AS");
5817 self.write_space();
5818 self.generate_identifier(&cte.alias)?;
5819 continue;
5820 }
5821 self.generate_identifier(&cte.alias)?;
5822 for comment in &cte.comments {
5824 self.write_space();
5825 self.write_formatted_comment(comment);
5826 }
5827 if !cte.columns.is_empty() && !skip_cte_columns {
5828 self.write("(");
5829 for (j, col) in cte.columns.iter().enumerate() {
5830 if j > 0 {
5831 self.write(", ");
5832 }
5833 self.generate_identifier(col)?;
5834 }
5835 self.write(")");
5836 }
5837 if !cte.key_expressions.is_empty() {
5839 self.write_space();
5840 self.write_keyword("USING KEY");
5841 self.write(" (");
5842 for (i, key) in cte.key_expressions.iter().enumerate() {
5843 if i > 0 {
5844 self.write(", ");
5845 }
5846 self.generate_identifier(key)?;
5847 }
5848 self.write(")");
5849 }
5850 self.write_space();
5851 self.write_keyword("AS");
5852 if let Some(materialized) = cte.materialized {
5854 self.write_space();
5855 if materialized {
5856 self.write_keyword("MATERIALIZED");
5857 } else {
5858 self.write_keyword("NOT MATERIALIZED");
5859 }
5860 }
5861 self.write(" (");
5862 if self.config.pretty {
5863 self.write_newline();
5864 self.indent_level += 1;
5865 self.write_indent();
5866 }
5867 let wrap_values_in_select = matches!(
5870 self.config.dialect,
5871 Some(DialectType::Spark) | Some(DialectType::Databricks)
5872 ) && matches!(&cte.this, Expression::Values(_));
5873
5874 if wrap_values_in_select {
5875 self.write_keyword("SELECT");
5876 self.write(" * ");
5877 self.write_keyword("FROM");
5878 self.write_space();
5879 }
5880 self.generate_expression(&cte.this)?;
5881 if self.config.pretty {
5882 self.write_newline();
5883 self.indent_level -= 1;
5884 self.write_indent();
5885 }
5886 self.write(")");
5887 }
5888
5889 if let Some(search) = &with.search {
5891 self.write_space();
5892 self.generate_expression(search)?;
5893 }
5894
5895 Ok(())
5896 }
5897
5898 fn generate_joins_with_nesting(&mut self, joins: &[Join]) -> Result<()> {
5902 let mut i = 0;
5903 while i < joins.len() {
5904 if joins[i].deferred_condition {
5905 let parent_group = joins[i].nesting_group;
5906
5907 self.generate_join_without_condition(&joins[i])?;
5910
5911 let child_start = i + 1;
5913 let mut child_end = child_start;
5914 while child_end < joins.len()
5915 && !joins[child_end].deferred_condition
5916 && joins[child_end].nesting_group == parent_group
5917 {
5918 child_end += 1;
5919 }
5920
5921 if child_start < child_end {
5923 self.indent_level += 1;
5924 for j in child_start..child_end {
5925 self.generate_join(&joins[j])?;
5926 }
5927 self.indent_level -= 1;
5928 }
5929
5930 self.generate_join_condition(&joins[i])?;
5932
5933 i = child_end;
5934 } else {
5935 self.generate_join(&joins[i])?;
5937 i += 1;
5938 }
5939 }
5940 Ok(())
5941 }
5942
5943 fn generate_join_without_condition(&mut self, join: &Join) -> Result<()> {
5946 let mut join_copy = join.clone();
5949 join_copy.on = None;
5950 join_copy.using = Vec::new();
5951 join_copy.deferred_condition = false;
5952 self.generate_join(&join_copy)
5953 }
5954
5955 fn generate_join(&mut self, join: &Join) -> Result<()> {
5956 if join.kind == JoinKind::Implicit {
5958 self.write(",");
5959 if self.config.pretty {
5960 self.write_newline();
5961 self.write_indent();
5962 } else {
5963 self.write_space();
5964 }
5965 self.generate_expression(&join.this)?;
5966 return Ok(());
5967 }
5968
5969 if self.config.pretty {
5970 self.write_newline();
5971 self.write_indent();
5972 } else {
5973 self.write_space();
5974 }
5975
5976 let hint_str = if self.config.join_hints {
5979 join.join_hint
5980 .as_ref()
5981 .map(|h| format!(" {}", h))
5982 .unwrap_or_default()
5983 } else {
5984 String::new()
5985 };
5986
5987 let clickhouse_join_keyword =
5988 if matches!(self.config.dialect, Some(DialectType::ClickHouse)) {
5989 if let Some(hint) = &join.join_hint {
5990 let mut global = false;
5991 let mut strictness: Option<&'static str> = None;
5992 for part in hint.split_whitespace() {
5993 if part.eq_ignore_ascii_case("GLOBAL") {
5994 global = true;
5995 } else if part.eq_ignore_ascii_case("ALL") {
5996 strictness = Some("ALL");
5997 } else if part.eq_ignore_ascii_case("ANY") {
5998 strictness = Some("ANY");
5999 } else if part.eq_ignore_ascii_case("ASOF") {
6000 strictness = Some("ASOF");
6001 } else if part.eq_ignore_ascii_case("SEMI") {
6002 strictness = Some("SEMI");
6003 } else if part.eq_ignore_ascii_case("ANTI") {
6004 strictness = Some("ANTI");
6005 }
6006 }
6007
6008 if global || strictness.is_some() {
6009 let join_type = match join.kind {
6010 JoinKind::Left => {
6011 if join.use_outer_keyword {
6012 "LEFT OUTER"
6013 } else if join.use_inner_keyword {
6014 "LEFT INNER"
6015 } else {
6016 "LEFT"
6017 }
6018 }
6019 JoinKind::Right => {
6020 if join.use_outer_keyword {
6021 "RIGHT OUTER"
6022 } else if join.use_inner_keyword {
6023 "RIGHT INNER"
6024 } else {
6025 "RIGHT"
6026 }
6027 }
6028 JoinKind::Full => {
6029 if join.use_outer_keyword {
6030 "FULL OUTER"
6031 } else {
6032 "FULL"
6033 }
6034 }
6035 JoinKind::Inner => {
6036 if join.use_inner_keyword {
6037 "INNER"
6038 } else {
6039 ""
6040 }
6041 }
6042 _ => "",
6043 };
6044
6045 let mut parts = Vec::new();
6046 if global {
6047 parts.push("GLOBAL");
6048 }
6049 if !join_type.is_empty() {
6050 parts.push(join_type);
6051 }
6052 if let Some(strict) = strictness {
6053 parts.push(strict);
6054 }
6055 parts.push("JOIN");
6056 Some(parts.join(" "))
6057 } else {
6058 None
6059 }
6060 } else {
6061 None
6062 }
6063 } else {
6064 None
6065 };
6066
6067 if !join.comments.is_empty() {
6071 if self.config.pretty {
6072 let trimmed = self.output.trim_end().len();
6077 self.output.truncate(trimmed);
6078 for comment in &join.comments {
6079 self.write_newline();
6080 self.write_indent();
6081 self.write_formatted_comment(comment);
6082 }
6083 self.write_newline();
6084 self.write_indent();
6085 } else {
6086 for comment in &join.comments {
6087 self.write_formatted_comment(comment);
6088 self.write_space();
6089 }
6090 }
6091 }
6092
6093 let directed_str = if join.directed { " DIRECTED" } else { "" };
6094
6095 if let Some(keyword) = clickhouse_join_keyword {
6096 self.write_keyword(&keyword);
6097 } else {
6098 match join.kind {
6099 JoinKind::Inner => {
6100 if join.use_inner_keyword {
6101 if hint_str.is_empty() && directed_str.is_empty() {
6102 self.write_keyword("INNER JOIN");
6103 } else {
6104 self.write_keyword("INNER");
6105 if !hint_str.is_empty() {
6106 self.write_keyword(&hint_str);
6107 }
6108 if !directed_str.is_empty() {
6109 self.write_keyword(directed_str);
6110 }
6111 self.write_keyword(" JOIN");
6112 }
6113 } else {
6114 if !hint_str.is_empty() {
6115 self.write_keyword(hint_str.trim());
6116 self.write_keyword(" ");
6117 }
6118 if !directed_str.is_empty() {
6119 self.write_keyword("DIRECTED ");
6120 }
6121 self.write_keyword("JOIN");
6122 }
6123 }
6124 JoinKind::Left => {
6125 if join.use_outer_keyword {
6126 if hint_str.is_empty() && directed_str.is_empty() {
6127 self.write_keyword("LEFT OUTER JOIN");
6128 } else {
6129 self.write_keyword("LEFT OUTER");
6130 if !hint_str.is_empty() {
6131 self.write_keyword(&hint_str);
6132 }
6133 if !directed_str.is_empty() {
6134 self.write_keyword(directed_str);
6135 }
6136 self.write_keyword(" JOIN");
6137 }
6138 } else if join.use_inner_keyword {
6139 if hint_str.is_empty() && directed_str.is_empty() {
6140 self.write_keyword("LEFT INNER JOIN");
6141 } else {
6142 self.write_keyword("LEFT INNER");
6143 if !hint_str.is_empty() {
6144 self.write_keyword(&hint_str);
6145 }
6146 if !directed_str.is_empty() {
6147 self.write_keyword(directed_str);
6148 }
6149 self.write_keyword(" JOIN");
6150 }
6151 } else {
6152 if hint_str.is_empty() && directed_str.is_empty() {
6153 self.write_keyword("LEFT JOIN");
6154 } else {
6155 self.write_keyword("LEFT");
6156 if !hint_str.is_empty() {
6157 self.write_keyword(&hint_str);
6158 }
6159 if !directed_str.is_empty() {
6160 self.write_keyword(directed_str);
6161 }
6162 self.write_keyword(" JOIN");
6163 }
6164 }
6165 }
6166 JoinKind::Right => {
6167 if join.use_outer_keyword {
6168 if hint_str.is_empty() && directed_str.is_empty() {
6169 self.write_keyword("RIGHT OUTER JOIN");
6170 } else {
6171 self.write_keyword("RIGHT OUTER");
6172 if !hint_str.is_empty() {
6173 self.write_keyword(&hint_str);
6174 }
6175 if !directed_str.is_empty() {
6176 self.write_keyword(directed_str);
6177 }
6178 self.write_keyword(" JOIN");
6179 }
6180 } else if join.use_inner_keyword {
6181 if hint_str.is_empty() && directed_str.is_empty() {
6182 self.write_keyword("RIGHT INNER JOIN");
6183 } else {
6184 self.write_keyword("RIGHT INNER");
6185 if !hint_str.is_empty() {
6186 self.write_keyword(&hint_str);
6187 }
6188 if !directed_str.is_empty() {
6189 self.write_keyword(directed_str);
6190 }
6191 self.write_keyword(" JOIN");
6192 }
6193 } else {
6194 if hint_str.is_empty() && directed_str.is_empty() {
6195 self.write_keyword("RIGHT JOIN");
6196 } else {
6197 self.write_keyword("RIGHT");
6198 if !hint_str.is_empty() {
6199 self.write_keyword(&hint_str);
6200 }
6201 if !directed_str.is_empty() {
6202 self.write_keyword(directed_str);
6203 }
6204 self.write_keyword(" JOIN");
6205 }
6206 }
6207 }
6208 JoinKind::Full => {
6209 if join.use_outer_keyword {
6210 if hint_str.is_empty() && directed_str.is_empty() {
6211 self.write_keyword("FULL OUTER JOIN");
6212 } else {
6213 self.write_keyword("FULL OUTER");
6214 if !hint_str.is_empty() {
6215 self.write_keyword(&hint_str);
6216 }
6217 if !directed_str.is_empty() {
6218 self.write_keyword(directed_str);
6219 }
6220 self.write_keyword(" JOIN");
6221 }
6222 } else {
6223 if hint_str.is_empty() && directed_str.is_empty() {
6224 self.write_keyword("FULL JOIN");
6225 } else {
6226 self.write_keyword("FULL");
6227 if !hint_str.is_empty() {
6228 self.write_keyword(&hint_str);
6229 }
6230 if !directed_str.is_empty() {
6231 self.write_keyword(directed_str);
6232 }
6233 self.write_keyword(" JOIN");
6234 }
6235 }
6236 }
6237 JoinKind::Outer => {
6238 if directed_str.is_empty() {
6239 self.write_keyword("OUTER JOIN");
6240 } else {
6241 self.write_keyword("OUTER");
6242 self.write_keyword(directed_str);
6243 self.write_keyword(" JOIN");
6244 }
6245 }
6246 JoinKind::Cross => {
6247 if directed_str.is_empty() {
6248 self.write_keyword("CROSS JOIN");
6249 } else {
6250 self.write_keyword("CROSS");
6251 self.write_keyword(directed_str);
6252 self.write_keyword(" JOIN");
6253 }
6254 }
6255 JoinKind::Natural => {
6256 if join.use_inner_keyword {
6257 if directed_str.is_empty() {
6258 self.write_keyword("NATURAL INNER JOIN");
6259 } else {
6260 self.write_keyword("NATURAL INNER");
6261 self.write_keyword(directed_str);
6262 self.write_keyword(" JOIN");
6263 }
6264 } else {
6265 if directed_str.is_empty() {
6266 self.write_keyword("NATURAL JOIN");
6267 } else {
6268 self.write_keyword("NATURAL");
6269 self.write_keyword(directed_str);
6270 self.write_keyword(" JOIN");
6271 }
6272 }
6273 }
6274 JoinKind::NaturalLeft => {
6275 if join.use_outer_keyword {
6276 if directed_str.is_empty() {
6277 self.write_keyword("NATURAL LEFT OUTER JOIN");
6278 } else {
6279 self.write_keyword("NATURAL LEFT OUTER");
6280 self.write_keyword(directed_str);
6281 self.write_keyword(" JOIN");
6282 }
6283 } else {
6284 if directed_str.is_empty() {
6285 self.write_keyword("NATURAL LEFT JOIN");
6286 } else {
6287 self.write_keyword("NATURAL LEFT");
6288 self.write_keyword(directed_str);
6289 self.write_keyword(" JOIN");
6290 }
6291 }
6292 }
6293 JoinKind::NaturalRight => {
6294 if join.use_outer_keyword {
6295 if directed_str.is_empty() {
6296 self.write_keyword("NATURAL RIGHT OUTER JOIN");
6297 } else {
6298 self.write_keyword("NATURAL RIGHT OUTER");
6299 self.write_keyword(directed_str);
6300 self.write_keyword(" JOIN");
6301 }
6302 } else {
6303 if directed_str.is_empty() {
6304 self.write_keyword("NATURAL RIGHT JOIN");
6305 } else {
6306 self.write_keyword("NATURAL RIGHT");
6307 self.write_keyword(directed_str);
6308 self.write_keyword(" JOIN");
6309 }
6310 }
6311 }
6312 JoinKind::NaturalFull => {
6313 if join.use_outer_keyword {
6314 if directed_str.is_empty() {
6315 self.write_keyword("NATURAL FULL OUTER JOIN");
6316 } else {
6317 self.write_keyword("NATURAL FULL OUTER");
6318 self.write_keyword(directed_str);
6319 self.write_keyword(" JOIN");
6320 }
6321 } else {
6322 if directed_str.is_empty() {
6323 self.write_keyword("NATURAL FULL JOIN");
6324 } else {
6325 self.write_keyword("NATURAL FULL");
6326 self.write_keyword(directed_str);
6327 self.write_keyword(" JOIN");
6328 }
6329 }
6330 }
6331 JoinKind::Semi => self.write_keyword("SEMI JOIN"),
6332 JoinKind::Anti => self.write_keyword("ANTI JOIN"),
6333 JoinKind::LeftSemi => self.write_keyword("LEFT SEMI JOIN"),
6334 JoinKind::LeftAnti => self.write_keyword("LEFT ANTI JOIN"),
6335 JoinKind::RightSemi => self.write_keyword("RIGHT SEMI JOIN"),
6336 JoinKind::RightAnti => self.write_keyword("RIGHT ANTI JOIN"),
6337 JoinKind::CrossApply => {
6338 if matches!(
6340 self.config.dialect,
6341 Some(DialectType::TSQL) | Some(DialectType::Fabric) | None
6342 ) {
6343 self.write_keyword("CROSS APPLY");
6344 } else {
6345 self.write_keyword("INNER JOIN LATERAL");
6346 }
6347 }
6348 JoinKind::OuterApply => {
6349 if matches!(
6351 self.config.dialect,
6352 Some(DialectType::TSQL) | Some(DialectType::Fabric) | None
6353 ) {
6354 self.write_keyword("OUTER APPLY");
6355 } else {
6356 self.write_keyword("LEFT JOIN LATERAL");
6357 }
6358 }
6359 JoinKind::AsOf => self.write_keyword("ASOF JOIN"),
6360 JoinKind::AsOfLeft => {
6361 if join.use_outer_keyword {
6362 self.write_keyword("ASOF LEFT OUTER JOIN");
6363 } else {
6364 self.write_keyword("ASOF LEFT JOIN");
6365 }
6366 }
6367 JoinKind::AsOfRight => {
6368 if join.use_outer_keyword {
6369 self.write_keyword("ASOF RIGHT OUTER JOIN");
6370 } else {
6371 self.write_keyword("ASOF RIGHT JOIN");
6372 }
6373 }
6374 JoinKind::Lateral => self.write_keyword("LATERAL JOIN"),
6375 JoinKind::LeftLateral => {
6376 if join.use_outer_keyword {
6377 self.write_keyword("LEFT OUTER LATERAL JOIN");
6378 } else {
6379 self.write_keyword("LEFT LATERAL JOIN");
6380 }
6381 }
6382 JoinKind::Straight => self.write_keyword("STRAIGHT_JOIN"),
6383 JoinKind::Implicit => {
6384 use crate::dialects::DialectType;
6388 let is_cj_dialect = matches!(
6389 self.config.dialect,
6390 Some(DialectType::BigQuery)
6391 | Some(DialectType::Hive)
6392 | Some(DialectType::Spark)
6393 | Some(DialectType::Databricks)
6394 );
6395 let source_is_same = self.config.source_dialect.is_some()
6396 && self.config.source_dialect == self.config.dialect;
6397 let source_is_cj = matches!(
6398 self.config.source_dialect,
6399 Some(DialectType::BigQuery)
6400 | Some(DialectType::Hive)
6401 | Some(DialectType::Spark)
6402 | Some(DialectType::Databricks)
6403 );
6404 if is_cj_dialect
6405 && (source_is_same || source_is_cj || self.config.source_dialect.is_none())
6406 {
6407 self.write_keyword("CROSS JOIN");
6408 } else {
6409 self.output.truncate(self.output.trim_end().len());
6413 self.write(",");
6414 }
6415 }
6416 JoinKind::Array => self.write_keyword("ARRAY JOIN"),
6417 JoinKind::LeftArray => self.write_keyword("LEFT ARRAY JOIN"),
6418 JoinKind::Paste => self.write_keyword("PASTE JOIN"),
6419 JoinKind::Positional => self.write_keyword("POSITIONAL JOIN"),
6420 }
6421 }
6422
6423 if matches!(join.kind, JoinKind::Array | JoinKind::LeftArray) {
6425 match &join.this {
6426 Expression::Tuple(t) if t.expressions.is_empty() => {}
6427 Expression::Tuple(t) => {
6428 self.write_space();
6429 for (i, item) in t.expressions.iter().enumerate() {
6430 if i > 0 {
6431 self.write(", ");
6432 }
6433 self.generate_expression(item)?;
6434 }
6435 }
6436 other => {
6437 self.write_space();
6438 self.generate_expression(other)?;
6439 }
6440 }
6441 } else {
6442 self.write_space();
6443 self.generate_expression(&join.this)?;
6444 }
6445
6446 if !join.deferred_condition {
6448 if let Some(match_cond) = &join.match_condition {
6450 self.write_space();
6451 self.write_keyword("MATCH_CONDITION");
6452 self.write(" (");
6453 self.generate_expression(match_cond)?;
6454 self.write(")");
6455 }
6456
6457 if let Some(on) = &join.on {
6458 if self.config.pretty {
6459 self.write_newline();
6460 self.indent_level += 1;
6461 self.write_indent();
6462 self.write_keyword("ON");
6463 self.write_space();
6464 self.generate_join_on_condition(on)?;
6465 self.indent_level -= 1;
6466 } else {
6467 self.write_space();
6468 self.write_keyword("ON");
6469 self.write_space();
6470 self.generate_expression(on)?;
6471 }
6472 }
6473
6474 if !join.using.is_empty() {
6475 if self.config.pretty {
6476 self.write_newline();
6477 self.indent_level += 1;
6478 self.write_indent();
6479 self.write_keyword("USING");
6480 self.write(" (");
6481 for (i, col) in join.using.iter().enumerate() {
6482 if i > 0 {
6483 self.write(", ");
6484 }
6485 self.generate_identifier(col)?;
6486 }
6487 self.write(")");
6488 self.indent_level -= 1;
6489 } else {
6490 self.write_space();
6491 self.write_keyword("USING");
6492 self.write(" (");
6493 for (i, col) in join.using.iter().enumerate() {
6494 if i > 0 {
6495 self.write(", ");
6496 }
6497 self.generate_identifier(col)?;
6498 }
6499 self.write(")");
6500 }
6501 }
6502 }
6503
6504 for pivot in &join.pivots {
6506 self.write_space();
6507 self.generate_expression(pivot)?;
6508 }
6509
6510 Ok(())
6511 }
6512
6513 fn generate_join_condition(&mut self, join: &Join) -> Result<()> {
6515 if let Some(match_cond) = &join.match_condition {
6517 self.write_space();
6518 self.write_keyword("MATCH_CONDITION");
6519 self.write(" (");
6520 self.generate_expression(match_cond)?;
6521 self.write(")");
6522 }
6523
6524 if let Some(on) = &join.on {
6525 if self.config.pretty {
6526 self.write_newline();
6527 self.indent_level += 1;
6528 self.write_indent();
6529 self.write_keyword("ON");
6530 self.write_space();
6531 self.generate_join_on_condition(on)?;
6533 self.indent_level -= 1;
6534 } else {
6535 self.write_space();
6536 self.write_keyword("ON");
6537 self.write_space();
6538 self.generate_expression(on)?;
6539 }
6540 }
6541
6542 if !join.using.is_empty() {
6543 if self.config.pretty {
6544 self.write_newline();
6545 self.indent_level += 1;
6546 self.write_indent();
6547 self.write_keyword("USING");
6548 self.write(" (");
6549 for (i, col) in join.using.iter().enumerate() {
6550 if i > 0 {
6551 self.write(", ");
6552 }
6553 self.generate_identifier(col)?;
6554 }
6555 self.write(")");
6556 self.indent_level -= 1;
6557 } else {
6558 self.write_space();
6559 self.write_keyword("USING");
6560 self.write(" (");
6561 for (i, col) in join.using.iter().enumerate() {
6562 if i > 0 {
6563 self.write(", ");
6564 }
6565 self.generate_identifier(col)?;
6566 }
6567 self.write(")");
6568 }
6569 }
6570
6571 for pivot in &join.pivots {
6573 self.write_space();
6574 self.generate_expression(pivot)?;
6575 }
6576
6577 Ok(())
6578 }
6579
6580 fn generate_join_on_condition(&mut self, expr: &Expression) -> Result<()> {
6582 if let Expression::And(and_op) = expr {
6583 if let Some(conditions) = self.flatten_connector_terms(and_op, ConnectorOperator::And) {
6584 self.generate_expression(conditions[0])?;
6585 for condition in conditions.iter().skip(1) {
6586 self.write_newline();
6587 self.write_indent();
6588 self.write_keyword("AND");
6589 self.write_space();
6590 self.generate_expression(condition)?;
6591 }
6592 return Ok(());
6593 }
6594 }
6595
6596 self.generate_expression(expr)
6597 }
6598
6599 fn generate_joined_table(&mut self, jt: &JoinedTable) -> Result<()> {
6600 self.write("(");
6602 self.generate_expression(&jt.left)?;
6603
6604 for join in &jt.joins {
6606 self.generate_join(join)?;
6607 }
6608
6609 for (lv_idx, lv) in jt.lateral_views.iter().enumerate() {
6611 self.generate_lateral_view(lv, lv_idx)?;
6612 }
6613
6614 self.write(")");
6615
6616 if let Some(alias) = &jt.alias {
6618 self.write_space();
6619 self.write_keyword("AS");
6620 self.write_space();
6621 self.generate_identifier(alias)?;
6622 }
6623
6624 Ok(())
6625 }
6626
6627 fn generate_lateral_view(&mut self, lv: &LateralView, lv_index: usize) -> Result<()> {
6628 use crate::dialects::DialectType;
6629
6630 if self.config.pretty {
6631 self.write_newline();
6632 self.write_indent();
6633 } else {
6634 self.write_space();
6635 }
6636
6637 let use_lateral_join = matches!(
6640 self.config.dialect,
6641 Some(DialectType::PostgreSQL)
6642 | Some(DialectType::DuckDB)
6643 | Some(DialectType::Snowflake)
6644 | Some(DialectType::TSQL)
6645 | Some(DialectType::Presto)
6646 | Some(DialectType::Trino)
6647 | Some(DialectType::Athena)
6648 );
6649
6650 let use_unnest = matches!(
6652 self.config.dialect,
6653 Some(DialectType::DuckDB)
6654 | Some(DialectType::Presto)
6655 | Some(DialectType::Trino)
6656 | Some(DialectType::Athena)
6657 );
6658
6659 let (is_posexplode, is_inline, func_args) = match &lv.this {
6661 Expression::Explode(uf) => {
6662 (false, false, vec![uf.this.clone()])
6664 }
6665 Expression::Unnest(uf) => {
6666 let mut args = vec![uf.this.clone()];
6667 args.extend(uf.expressions.clone());
6668 (false, false, args)
6669 }
6670 Expression::Function(func) => {
6671 if func.name.eq_ignore_ascii_case("POSEXPLODE")
6672 || func.name.eq_ignore_ascii_case("POSEXPLODE_OUTER")
6673 {
6674 (true, false, func.args.clone())
6675 } else if func.name.eq_ignore_ascii_case("INLINE") {
6676 (false, true, func.args.clone())
6677 } else if func.name.eq_ignore_ascii_case("EXPLODE")
6678 || func.name.eq_ignore_ascii_case("EXPLODE_OUTER")
6679 {
6680 (false, false, func.args.clone())
6681 } else {
6682 (false, false, vec![])
6683 }
6684 }
6685 _ => (false, false, vec![]),
6686 };
6687
6688 if use_lateral_join {
6689 if lv.outer {
6691 self.write_keyword("LEFT JOIN LATERAL");
6692 } else {
6693 self.write_keyword("CROSS JOIN");
6694 }
6695 self.write_space();
6696
6697 if use_unnest && !func_args.is_empty() {
6698 let unnest_args = if matches!(self.config.dialect, Some(DialectType::DuckDB)) {
6701 func_args
6703 .iter()
6704 .map(|a| {
6705 if let Expression::Function(ref f) = a {
6706 if f.name.eq_ignore_ascii_case("ARRAY") && f.args.len() == 1 {
6707 return Expression::ArrayFunc(Box::new(
6708 crate::expressions::ArrayConstructor {
6709 expressions: f.args.clone(),
6710 bracket_notation: true,
6711 use_list_keyword: false,
6712 },
6713 ));
6714 }
6715 }
6716 a.clone()
6717 })
6718 .collect::<Vec<_>>()
6719 } else if matches!(
6720 self.config.dialect,
6721 Some(DialectType::Presto)
6722 | Some(DialectType::Trino)
6723 | Some(DialectType::Athena)
6724 ) {
6725 func_args
6727 .iter()
6728 .map(|a| {
6729 if let Expression::Function(ref f) = a {
6730 if f.name.eq_ignore_ascii_case("ARRAY") && f.args.len() >= 1 {
6731 return Expression::ArrayFunc(Box::new(
6732 crate::expressions::ArrayConstructor {
6733 expressions: f.args.clone(),
6734 bracket_notation: true,
6735 use_list_keyword: false,
6736 },
6737 ));
6738 }
6739 }
6740 a.clone()
6741 })
6742 .collect::<Vec<_>>()
6743 } else {
6744 func_args
6745 };
6746
6747 if is_posexplode {
6749 self.write_keyword("LATERAL");
6750 self.write(" (");
6751 self.write_keyword("SELECT");
6752 self.write_space();
6753
6754 let pos_alias = if !lv.column_aliases.is_empty() {
6757 lv.column_aliases[0].clone()
6758 } else {
6759 Identifier::new("pos")
6760 };
6761 let data_aliases: Vec<Identifier> = if lv.column_aliases.len() > 1 {
6762 lv.column_aliases[1..].to_vec()
6763 } else {
6764 vec![Identifier::new("col")]
6765 };
6766
6767 self.generate_identifier(&pos_alias)?;
6769 self.write(" - 1");
6770 self.write_space();
6771 self.write_keyword("AS");
6772 self.write_space();
6773 self.generate_identifier(&pos_alias)?;
6774
6775 for data_col in &data_aliases {
6777 self.write(", ");
6778 self.generate_identifier(data_col)?;
6779 }
6780
6781 self.write_space();
6782 self.write_keyword("FROM");
6783 self.write_space();
6784 self.write_keyword("UNNEST");
6785 self.write("(");
6786 for (i, arg) in unnest_args.iter().enumerate() {
6787 if i > 0 {
6788 self.write(", ");
6789 }
6790 self.generate_expression(arg)?;
6791 }
6792 self.write(")");
6793 self.write_space();
6794 self.write_keyword("WITH ORDINALITY");
6795 self.write_space();
6796 self.write_keyword("AS");
6797 self.write_space();
6798
6799 let table_alias_ident = lv
6801 .table_alias
6802 .clone()
6803 .unwrap_or_else(|| Identifier::new("t"));
6804 self.generate_identifier(&table_alias_ident)?;
6805 self.write("(");
6806 for (i, data_col) in data_aliases.iter().enumerate() {
6807 if i > 0 {
6808 self.write(", ");
6809 }
6810 self.generate_identifier(data_col)?;
6811 }
6812 self.write(", ");
6813 self.generate_identifier(&pos_alias)?;
6814 self.write("))");
6815 } else if is_inline && matches!(self.config.dialect, Some(DialectType::DuckDB)) {
6816 self.write_keyword("LATERAL");
6818 self.write(" (");
6819 self.write_keyword("SELECT");
6820 self.write_space();
6821 self.write_keyword("UNNEST");
6822 self.write("(");
6823 for (i, arg) in unnest_args.iter().enumerate() {
6824 if i > 0 {
6825 self.write(", ");
6826 }
6827 self.generate_expression(arg)?;
6828 }
6829 self.write(", ");
6830 self.write_keyword("max_depth");
6831 self.write(" => 2))");
6832
6833 if let Some(alias) = &lv.table_alias {
6835 self.write_space();
6836 self.write_keyword("AS");
6837 self.write_space();
6838 self.generate_identifier(alias)?;
6839 if !lv.column_aliases.is_empty() {
6840 self.write("(");
6841 for (i, col) in lv.column_aliases.iter().enumerate() {
6842 if i > 0 {
6843 self.write(", ");
6844 }
6845 self.generate_identifier(col)?;
6846 }
6847 self.write(")");
6848 }
6849 } else if !lv.column_aliases.is_empty() {
6850 self.write_space();
6852 self.write_keyword("AS");
6853 self.write_space();
6854 self.write(&format!("_u_{}", lv_index));
6855 self.write("(");
6856 for (i, col) in lv.column_aliases.iter().enumerate() {
6857 if i > 0 {
6858 self.write(", ");
6859 }
6860 self.generate_identifier(col)?;
6861 }
6862 self.write(")");
6863 }
6864 } else {
6865 self.write_keyword("UNNEST");
6866 self.write("(");
6867 for (i, arg) in unnest_args.iter().enumerate() {
6868 if i > 0 {
6869 self.write(", ");
6870 }
6871 self.generate_expression(arg)?;
6872 }
6873 self.write(")");
6874
6875 if let Some(alias) = &lv.table_alias {
6877 self.write_space();
6878 self.write_keyword("AS");
6879 self.write_space();
6880 self.generate_identifier(alias)?;
6881 if !lv.column_aliases.is_empty() {
6882 self.write("(");
6883 for (i, col) in lv.column_aliases.iter().enumerate() {
6884 if i > 0 {
6885 self.write(", ");
6886 }
6887 self.generate_identifier(col)?;
6888 }
6889 self.write(")");
6890 }
6891 } else if !lv.column_aliases.is_empty() {
6892 self.write_space();
6893 self.write_keyword("AS");
6894 self.write(" t(");
6895 for (i, col) in lv.column_aliases.iter().enumerate() {
6896 if i > 0 {
6897 self.write(", ");
6898 }
6899 self.generate_identifier(col)?;
6900 }
6901 self.write(")");
6902 }
6903 }
6904 } else {
6905 if !lv.outer {
6907 self.write_keyword("LATERAL");
6908 self.write_space();
6909 }
6910 self.generate_expression(&lv.this)?;
6911
6912 if let Some(alias) = &lv.table_alias {
6914 self.write_space();
6915 self.write_keyword("AS");
6916 self.write_space();
6917 self.generate_identifier(alias)?;
6918 if !lv.column_aliases.is_empty() {
6919 self.write("(");
6920 for (i, col) in lv.column_aliases.iter().enumerate() {
6921 if i > 0 {
6922 self.write(", ");
6923 }
6924 self.generate_identifier(col)?;
6925 }
6926 self.write(")");
6927 }
6928 } else if !lv.column_aliases.is_empty() {
6929 self.write_space();
6930 self.write_keyword("AS");
6931 self.write(" t(");
6932 for (i, col) in lv.column_aliases.iter().enumerate() {
6933 if i > 0 {
6934 self.write(", ");
6935 }
6936 self.generate_identifier(col)?;
6937 }
6938 self.write(")");
6939 }
6940 }
6941
6942 if lv.outer {
6944 self.write_space();
6945 self.write_keyword("ON TRUE");
6946 }
6947 } else {
6948 self.write_keyword("LATERAL VIEW");
6950 if lv.outer {
6951 self.write_space();
6952 self.write_keyword("OUTER");
6953 }
6954 if self.config.pretty {
6955 self.write_newline();
6956 self.write_indent();
6957 } else {
6958 self.write_space();
6959 }
6960 self.generate_expression(&lv.this)?;
6961
6962 if let Some(alias) = &lv.table_alias {
6964 self.write_space();
6965 self.generate_identifier(alias)?;
6966 }
6967
6968 if !lv.column_aliases.is_empty() {
6970 self.write_space();
6971 self.write_keyword("AS");
6972 self.write_space();
6973 for (i, col) in lv.column_aliases.iter().enumerate() {
6974 if i > 0 {
6975 self.write(", ");
6976 }
6977 self.generate_identifier(col)?;
6978 }
6979 }
6980 }
6981
6982 Ok(())
6983 }
6984
6985 fn should_wrap_set_operation_modifiers(
6986 &self,
6987 order_by: &Option<OrderBy>,
6988 limit: &Option<Box<Expression>>,
6989 offset: &Option<Box<Expression>>,
6990 ) -> bool {
6991 let has_row_limit = limit.is_some() || offset.is_some();
6992 let has_emulated_null_ordering = order_by.as_ref().map_or(false, |order_by| {
6993 order_by
6994 .expressions
6995 .iter()
6996 .any(|ordered| ordered.nulls_first.is_some())
6997 });
6998
6999 (has_row_limit || has_emulated_null_ordering)
7000 && matches!(
7001 self.config.dialect,
7002 Some(DialectType::TSQL) | Some(DialectType::Fabric)
7003 )
7004 }
7005
7006 fn generate_tsql_wrapped_set_operation(
7007 &mut self,
7008 inner: Expression,
7009 with: Option<With>,
7010 order_by: Option<OrderBy>,
7011 limit: Option<Box<Expression>>,
7012 offset: Option<Box<Expression>>,
7013 ) -> Result<()> {
7014 let subquery = Subquery {
7015 this: inner,
7016 alias: Some(Identifier::new("_l_0".to_string())),
7017 column_aliases: Vec::new(),
7018 alias_explicit_as: true,
7019 alias_keyword: None,
7020 order_by: None,
7021 limit: None,
7022 offset: None,
7023 lateral: false,
7024 modifiers_inside: false,
7025 trailing_comments: Vec::new(),
7026 distribute_by: None,
7027 sort_by: None,
7028 cluster_by: None,
7029 inferred_type: None,
7030 };
7031
7032 let mut outer_select = Select {
7033 expressions: vec![Expression::Star(Star {
7034 table: None,
7035 except: None,
7036 replace: None,
7037 rename: None,
7038 trailing_comments: Vec::new(),
7039 span: None,
7040 })],
7041 from: Some(From {
7042 expressions: vec![Expression::Subquery(Box::new(subquery))],
7043 }),
7044 with,
7045 order_by,
7046 limit: limit.map(|limit| Limit {
7047 this: *limit,
7048 percent: false,
7049 comments: Vec::new(),
7050 }),
7051 offset: offset.map(|offset| Offset {
7052 this: *offset,
7053 rows: Some(true),
7054 }),
7055 ..Select::new()
7056 };
7057
7058 if outer_select.offset.is_some() && outer_select.order_by.is_none() {
7059 outer_select.order_by = Some(Self::dummy_tsql_order_by());
7060 }
7061
7062 self.generate_select(&outer_select)
7063 }
7064
7065 pub(crate) fn dummy_tsql_order_by() -> OrderBy {
7066 let null_select = Expression::Select(Box::new(Select {
7067 expressions: vec![Expression::Null(Null)],
7068 ..Select::new()
7069 }));
7070
7071 OrderBy {
7072 expressions: vec![Ordered {
7073 this: Expression::Subquery(Box::new(Subquery {
7074 this: null_select,
7075 alias: None,
7076 column_aliases: Vec::new(),
7077 alias_explicit_as: false,
7078 alias_keyword: None,
7079 order_by: None,
7080 limit: None,
7081 offset: None,
7082 lateral: false,
7083 modifiers_inside: false,
7084 trailing_comments: Vec::new(),
7085 distribute_by: None,
7086 sort_by: None,
7087 cluster_by: None,
7088 inferred_type: None,
7089 })),
7090 desc: false,
7091 nulls_first: None,
7092 explicit_asc: false,
7093 with_fill: None,
7094 }],
7095 siblings: false,
7096 comments: Vec::new(),
7097 }
7098 }
7099
7100 fn generate_union(&mut self, outermost: &Union) -> Result<()> {
7101 if self.should_wrap_set_operation_modifiers(
7102 &outermost.order_by,
7103 &outermost.limit,
7104 &outermost.offset,
7105 ) {
7106 let mut inner = outermost.clone();
7107 let with = inner.with.take();
7108 let order_by = inner.order_by.take();
7109 let limit = inner.limit.take();
7110 let offset = inner.offset.take();
7111
7112 return self.generate_tsql_wrapped_set_operation(
7113 Expression::Union(Box::new(inner)),
7114 with,
7115 order_by,
7116 limit,
7117 offset,
7118 );
7119 }
7120
7121 let mut chain: Vec<&Union> = vec![outermost];
7126 let mut leftmost: &Expression = &outermost.left;
7127 while let Expression::Union(inner) = leftmost {
7128 chain.push(inner);
7129 leftmost = &inner.left;
7130 }
7131 if let Some(with) = &outermost.with {
7136 self.generate_with(with)?;
7137 self.write_space();
7138 }
7139
7140 self.generate_expression(leftmost)?;
7142
7143 for union in chain.iter().rev() {
7145 self.generate_union_step(union)?;
7146 }
7147 Ok(())
7148 }
7149
7150 fn generate_union_step(&mut self, union: &Union) -> Result<()> {
7152 if self.config.pretty {
7153 self.write_newline();
7154 self.write_indent();
7155 } else {
7156 self.write_space();
7157 }
7158
7159 if let Some(side) = &union.side {
7161 self.write_keyword(side);
7162 self.write_space();
7163 }
7164 if let Some(kind) = &union.kind {
7165 self.write_keyword(kind);
7166 self.write_space();
7167 }
7168
7169 self.write_keyword("UNION");
7170 if union.all {
7171 self.write_space();
7172 self.write_keyword("ALL");
7173 } else if union.distinct {
7174 self.write_space();
7175 self.write_keyword("DISTINCT");
7176 }
7177
7178 if union.corresponding || union.by_name {
7181 self.write_space();
7182 self.write_keyword("BY NAME");
7183 }
7184 if !union.on_columns.is_empty() {
7185 self.write_space();
7186 self.write_keyword("ON");
7187 self.write(" (");
7188 for (i, col) in union.on_columns.iter().enumerate() {
7189 if i > 0 {
7190 self.write(", ");
7191 }
7192 self.generate_expression(col)?;
7193 }
7194 self.write(")");
7195 }
7196
7197 if self.config.pretty {
7198 self.write_newline();
7199 self.write_indent();
7200 } else {
7201 self.write_space();
7202 }
7203 self.generate_expression(&union.right)?;
7204 if let Some(order_by) = &union.order_by {
7206 if self.config.pretty {
7207 self.write_newline();
7208 } else {
7209 self.write_space();
7210 }
7211 self.write_keyword("ORDER BY");
7212 self.write_space();
7213 for (i, ordered) in order_by.expressions.iter().enumerate() {
7214 if i > 0 {
7215 self.write(", ");
7216 }
7217 self.generate_ordered(ordered)?;
7218 }
7219 }
7220 if let Some(limit) = &union.limit {
7221 if self.config.pretty {
7222 self.write_newline();
7223 } else {
7224 self.write_space();
7225 }
7226 self.write_keyword("LIMIT");
7227 self.write_space();
7228 self.generate_expression(limit)?;
7229 }
7230 if let Some(offset) = &union.offset {
7231 if self.config.pretty {
7232 self.write_newline();
7233 } else {
7234 self.write_space();
7235 }
7236 self.write_keyword("OFFSET");
7237 self.write_space();
7238 self.generate_expression(offset)?;
7239 }
7240 if let Some(distribute_by) = &union.distribute_by {
7242 self.write_space();
7243 self.write_keyword("DISTRIBUTE BY");
7244 self.write_space();
7245 for (i, expr) in distribute_by.expressions.iter().enumerate() {
7246 if i > 0 {
7247 self.write(", ");
7248 }
7249 self.generate_expression(expr)?;
7250 }
7251 }
7252 if let Some(sort_by) = &union.sort_by {
7254 self.write_space();
7255 self.write_keyword("SORT BY");
7256 self.write_space();
7257 for (i, ord) in sort_by.expressions.iter().enumerate() {
7258 if i > 0 {
7259 self.write(", ");
7260 }
7261 self.generate_ordered(ord)?;
7262 }
7263 }
7264 if let Some(cluster_by) = &union.cluster_by {
7266 self.write_space();
7267 self.write_keyword("CLUSTER BY");
7268 self.write_space();
7269 for (i, ord) in cluster_by.expressions.iter().enumerate() {
7270 if i > 0 {
7271 self.write(", ");
7272 }
7273 self.generate_ordered(ord)?;
7274 }
7275 }
7276 Ok(())
7277 }
7278
7279 fn generate_intersect(&mut self, outermost: &Intersect) -> Result<()> {
7280 if self.should_wrap_set_operation_modifiers(
7281 &outermost.order_by,
7282 &outermost.limit,
7283 &outermost.offset,
7284 ) {
7285 let mut inner = outermost.clone();
7286 let with = inner.with.take();
7287 let order_by = inner.order_by.take();
7288 let limit = inner.limit.take();
7289 let offset = inner.offset.take();
7290
7291 return self.generate_tsql_wrapped_set_operation(
7292 Expression::Intersect(Box::new(inner)),
7293 with,
7294 order_by,
7295 limit,
7296 offset,
7297 );
7298 }
7299
7300 let mut chain: Vec<&Intersect> = vec![outermost];
7302 let mut leftmost: &Expression = &outermost.left;
7303 while let Expression::Intersect(inner) = leftmost {
7304 chain.push(inner);
7305 leftmost = &inner.left;
7306 }
7307
7308 if let Some(with) = &outermost.with {
7309 self.generate_with(with)?;
7310 self.write_space();
7311 }
7312
7313 self.generate_expression(leftmost)?;
7314
7315 for intersect in chain.iter().rev() {
7316 self.generate_intersect_step(intersect)?;
7317 }
7318 Ok(())
7319 }
7320
7321 fn generate_intersect_step(&mut self, intersect: &Intersect) -> Result<()> {
7323 if self.config.pretty {
7324 self.write_newline();
7325 self.write_indent();
7326 } else {
7327 self.write_space();
7328 }
7329
7330 if let Some(side) = &intersect.side {
7332 self.write_keyword(side);
7333 self.write_space();
7334 }
7335 if let Some(kind) = &intersect.kind {
7336 self.write_keyword(kind);
7337 self.write_space();
7338 }
7339
7340 self.write_keyword("INTERSECT");
7341 if intersect.all {
7342 if !self.config.except_intersect_support_all_clause {
7343 self.unsupported("INTERSECT ALL is not supported")?;
7344 }
7345 self.write_space();
7346 self.write_keyword("ALL");
7347 } else if intersect.distinct {
7348 self.write_space();
7349 self.write_keyword("DISTINCT");
7350 }
7351
7352 if intersect.corresponding || intersect.by_name {
7355 self.write_space();
7356 self.write_keyword("BY NAME");
7357 }
7358 if !intersect.on_columns.is_empty() {
7359 self.write_space();
7360 self.write_keyword("ON");
7361 self.write(" (");
7362 for (i, col) in intersect.on_columns.iter().enumerate() {
7363 if i > 0 {
7364 self.write(", ");
7365 }
7366 self.generate_expression(col)?;
7367 }
7368 self.write(")");
7369 }
7370
7371 if self.config.pretty {
7372 self.write_newline();
7373 self.write_indent();
7374 } else {
7375 self.write_space();
7376 }
7377 self.generate_expression(&intersect.right)?;
7378 if let Some(order_by) = &intersect.order_by {
7380 if self.config.pretty {
7381 self.write_newline();
7382 } else {
7383 self.write_space();
7384 }
7385 self.write_keyword("ORDER BY");
7386 self.write_space();
7387 for (i, ordered) in order_by.expressions.iter().enumerate() {
7388 if i > 0 {
7389 self.write(", ");
7390 }
7391 self.generate_ordered(ordered)?;
7392 }
7393 }
7394 if let Some(limit) = &intersect.limit {
7395 if self.config.pretty {
7396 self.write_newline();
7397 } else {
7398 self.write_space();
7399 }
7400 self.write_keyword("LIMIT");
7401 self.write_space();
7402 self.generate_expression(limit)?;
7403 }
7404 if let Some(offset) = &intersect.offset {
7405 if self.config.pretty {
7406 self.write_newline();
7407 } else {
7408 self.write_space();
7409 }
7410 self.write_keyword("OFFSET");
7411 self.write_space();
7412 self.generate_expression(offset)?;
7413 }
7414 if let Some(distribute_by) = &intersect.distribute_by {
7416 self.write_space();
7417 self.write_keyword("DISTRIBUTE BY");
7418 self.write_space();
7419 for (i, expr) in distribute_by.expressions.iter().enumerate() {
7420 if i > 0 {
7421 self.write(", ");
7422 }
7423 self.generate_expression(expr)?;
7424 }
7425 }
7426 if let Some(sort_by) = &intersect.sort_by {
7428 self.write_space();
7429 self.write_keyword("SORT BY");
7430 self.write_space();
7431 for (i, ord) in sort_by.expressions.iter().enumerate() {
7432 if i > 0 {
7433 self.write(", ");
7434 }
7435 self.generate_ordered(ord)?;
7436 }
7437 }
7438 if let Some(cluster_by) = &intersect.cluster_by {
7440 self.write_space();
7441 self.write_keyword("CLUSTER BY");
7442 self.write_space();
7443 for (i, ord) in cluster_by.expressions.iter().enumerate() {
7444 if i > 0 {
7445 self.write(", ");
7446 }
7447 self.generate_ordered(ord)?;
7448 }
7449 }
7450 Ok(())
7451 }
7452
7453 fn generate_except(&mut self, outermost: &Except) -> Result<()> {
7454 if self.should_wrap_set_operation_modifiers(
7455 &outermost.order_by,
7456 &outermost.limit,
7457 &outermost.offset,
7458 ) {
7459 let mut inner = outermost.clone();
7460 let with = inner.with.take();
7461 let order_by = inner.order_by.take();
7462 let limit = inner.limit.take();
7463 let offset = inner.offset.take();
7464
7465 return self.generate_tsql_wrapped_set_operation(
7466 Expression::Except(Box::new(inner)),
7467 with,
7468 order_by,
7469 limit,
7470 offset,
7471 );
7472 }
7473
7474 let mut chain: Vec<&Except> = vec![outermost];
7476 let mut leftmost: &Expression = &outermost.left;
7477 while let Expression::Except(inner) = leftmost {
7478 chain.push(inner);
7479 leftmost = &inner.left;
7480 }
7481
7482 if let Some(with) = &outermost.with {
7483 self.generate_with(with)?;
7484 self.write_space();
7485 }
7486
7487 self.generate_expression(leftmost)?;
7488
7489 for except in chain.iter().rev() {
7490 self.generate_except_step(except)?;
7491 }
7492 Ok(())
7493 }
7494
7495 fn generate_except_step(&mut self, except: &Except) -> Result<()> {
7497 use crate::dialects::DialectType;
7498
7499 if self.config.pretty {
7500 self.write_newline();
7501 self.write_indent();
7502 } else {
7503 self.write_space();
7504 }
7505
7506 if let Some(side) = &except.side {
7508 self.write_keyword(side);
7509 self.write_space();
7510 }
7511 if let Some(kind) = &except.kind {
7512 self.write_keyword(kind);
7513 self.write_space();
7514 }
7515
7516 match self.config.dialect {
7518 Some(DialectType::Oracle) if !except.all => {
7519 self.write_keyword("MINUS");
7520 }
7521 Some(DialectType::ClickHouse) => {
7522 self.write_keyword("EXCEPT");
7523 let preserve_all = self.config.source_dialect.is_none()
7524 || matches!(self.config.source_dialect, Some(DialectType::ClickHouse));
7525 if except.all && preserve_all {
7526 self.write_space();
7527 self.write_keyword("ALL");
7528 }
7529 if except.distinct {
7530 self.write_space();
7531 self.write_keyword("DISTINCT");
7532 }
7533 }
7534 Some(DialectType::BigQuery) => {
7535 self.write_keyword("EXCEPT");
7537 if except.all {
7538 self.write_space();
7539 self.write_keyword("ALL");
7540 } else {
7541 self.write_space();
7542 self.write_keyword("DISTINCT");
7543 }
7544 }
7545 _ => {
7546 self.write_keyword("EXCEPT");
7547 if except.all {
7548 if !self.config.except_intersect_support_all_clause {
7549 self.unsupported("EXCEPT ALL is not supported")?;
7550 }
7551 self.write_space();
7552 self.write_keyword("ALL");
7553 } else if except.distinct {
7554 self.write_space();
7555 self.write_keyword("DISTINCT");
7556 }
7557 }
7558 }
7559
7560 if except.corresponding || except.by_name {
7563 self.write_space();
7564 self.write_keyword("BY NAME");
7565 }
7566 if !except.on_columns.is_empty() {
7567 self.write_space();
7568 self.write_keyword("ON");
7569 self.write(" (");
7570 for (i, col) in except.on_columns.iter().enumerate() {
7571 if i > 0 {
7572 self.write(", ");
7573 }
7574 self.generate_expression(col)?;
7575 }
7576 self.write(")");
7577 }
7578
7579 if self.config.pretty {
7580 self.write_newline();
7581 self.write_indent();
7582 } else {
7583 self.write_space();
7584 }
7585 self.generate_expression(&except.right)?;
7586 if let Some(order_by) = &except.order_by {
7588 if self.config.pretty {
7589 self.write_newline();
7590 } else {
7591 self.write_space();
7592 }
7593 self.write_keyword("ORDER BY");
7594 self.write_space();
7595 for (i, ordered) in order_by.expressions.iter().enumerate() {
7596 if i > 0 {
7597 self.write(", ");
7598 }
7599 self.generate_ordered(ordered)?;
7600 }
7601 }
7602 if let Some(limit) = &except.limit {
7603 if self.config.pretty {
7604 self.write_newline();
7605 } else {
7606 self.write_space();
7607 }
7608 self.write_keyword("LIMIT");
7609 self.write_space();
7610 self.generate_expression(limit)?;
7611 }
7612 if let Some(offset) = &except.offset {
7613 if self.config.pretty {
7614 self.write_newline();
7615 } else {
7616 self.write_space();
7617 }
7618 self.write_keyword("OFFSET");
7619 self.write_space();
7620 self.generate_expression(offset)?;
7621 }
7622 if let Some(distribute_by) = &except.distribute_by {
7624 self.write_space();
7625 self.write_keyword("DISTRIBUTE BY");
7626 self.write_space();
7627 for (i, expr) in distribute_by.expressions.iter().enumerate() {
7628 if i > 0 {
7629 self.write(", ");
7630 }
7631 self.generate_expression(expr)?;
7632 }
7633 }
7634 if let Some(sort_by) = &except.sort_by {
7636 self.write_space();
7637 self.write_keyword("SORT BY");
7638 self.write_space();
7639 for (i, ord) in sort_by.expressions.iter().enumerate() {
7640 if i > 0 {
7641 self.write(", ");
7642 }
7643 self.generate_ordered(ord)?;
7644 }
7645 }
7646 if let Some(cluster_by) = &except.cluster_by {
7648 self.write_space();
7649 self.write_keyword("CLUSTER BY");
7650 self.write_space();
7651 for (i, ord) in cluster_by.expressions.iter().enumerate() {
7652 if i > 0 {
7653 self.write(", ");
7654 }
7655 self.generate_ordered(ord)?;
7656 }
7657 }
7658 Ok(())
7659 }
7660
7661 fn generate_insert(&mut self, insert: &Insert) -> Result<()> {
7662 let prepend_query_cte = if insert.with.is_none() {
7664 use crate::dialects::DialectType;
7665 let should_prepend = matches!(
7666 self.config.dialect,
7667 Some(DialectType::TSQL)
7668 | Some(DialectType::Fabric)
7669 | Some(DialectType::Spark)
7670 | Some(DialectType::Databricks)
7671 | Some(DialectType::Hive)
7672 );
7673 if should_prepend {
7674 if let Some(Expression::Select(select)) = &insert.query {
7675 select.with.clone()
7676 } else {
7677 None
7678 }
7679 } else {
7680 None
7681 }
7682 } else {
7683 None
7684 };
7685
7686 if let Some(with) = &insert.with {
7688 self.generate_with(with)?;
7689 self.write_space();
7690 } else if let Some(with) = &prepend_query_cte {
7691 self.generate_with(with)?;
7692 self.write_space();
7693 }
7694
7695 for comment in &insert.leading_comments {
7697 self.write_formatted_comment(comment);
7698 self.write(" ");
7699 }
7700
7701 if let Some(dir) = &insert.directory {
7703 self.write_keyword("INSERT OVERWRITE");
7704 if dir.local {
7705 self.write_space();
7706 self.write_keyword("LOCAL");
7707 }
7708 self.write_space();
7709 self.write_keyword("DIRECTORY");
7710 self.write_space();
7711 self.write("'");
7712 self.write(&dir.path);
7713 self.write("'");
7714
7715 if let Some(row_format) = &dir.row_format {
7717 self.write_space();
7718 self.write_keyword("ROW FORMAT");
7719 if row_format.delimited {
7720 self.write_space();
7721 self.write_keyword("DELIMITED");
7722 }
7723 if let Some(val) = &row_format.fields_terminated_by {
7724 self.write_space();
7725 self.write_keyword("FIELDS TERMINATED BY");
7726 self.write_space();
7727 self.generate_string_literal(val)?;
7728 }
7729 if let Some(val) = &row_format.collection_items_terminated_by {
7730 self.write_space();
7731 self.write_keyword("COLLECTION ITEMS TERMINATED BY");
7732 self.write_space();
7733 self.write("'");
7734 self.write(val);
7735 self.write("'");
7736 }
7737 if let Some(val) = &row_format.map_keys_terminated_by {
7738 self.write_space();
7739 self.write_keyword("MAP KEYS TERMINATED BY");
7740 self.write_space();
7741 self.write("'");
7742 self.write(val);
7743 self.write("'");
7744 }
7745 if let Some(val) = &row_format.lines_terminated_by {
7746 self.write_space();
7747 self.write_keyword("LINES TERMINATED BY");
7748 self.write_space();
7749 self.write("'");
7750 self.write(val);
7751 self.write("'");
7752 }
7753 if let Some(val) = &row_format.null_defined_as {
7754 self.write_space();
7755 self.write_keyword("NULL DEFINED AS");
7756 self.write_space();
7757 self.write("'");
7758 self.write(val);
7759 self.write("'");
7760 }
7761 }
7762
7763 if let Some(format) = &dir.stored_as {
7765 self.write_space();
7766 self.write_keyword("STORED AS");
7767 self.write_space();
7768 self.write_keyword(format);
7769 }
7770
7771 if let Some(query) = &insert.query {
7773 self.write_space();
7774 self.generate_expression(query)?;
7775 }
7776
7777 return Ok(());
7778 }
7779
7780 if insert.is_replace {
7781 self.write_keyword("REPLACE INTO");
7783 } else if insert.overwrite {
7784 self.write_keyword("INSERT");
7786 if let Some(ref hint) = insert.hint {
7788 self.generate_hint(hint)?;
7789 }
7790 self.write(&self.config.insert_overwrite.to_ascii_uppercase());
7791 } else if let Some(ref action) = insert.conflict_action {
7792 self.write_keyword("INSERT OR");
7794 self.write_space();
7795 self.write_keyword(action);
7796 self.write_space();
7797 self.write_keyword("INTO");
7798 } else if insert.ignore {
7799 self.write_keyword("INSERT IGNORE INTO");
7801 } else {
7802 self.write_keyword("INSERT");
7803 if let Some(ref hint) = insert.hint {
7805 self.generate_hint(hint)?;
7806 }
7807 self.write_space();
7808 self.write_keyword("INTO");
7809 }
7810 if let Some(ref func) = insert.function_target {
7812 self.write_space();
7813 self.write_keyword("FUNCTION");
7814 self.write_space();
7815 self.generate_expression(func)?;
7816 } else {
7817 self.write_space();
7818 self.generate_table(&insert.table)?;
7819 }
7820
7821 if let Some(ref alias) = insert.alias {
7823 self.write_space();
7824 if insert.alias_explicit_as {
7825 self.write_keyword("AS");
7826 self.write_space();
7827 }
7828 self.generate_identifier(alias)?;
7829 }
7830
7831 if insert.if_exists {
7833 self.write_space();
7834 self.write_keyword("IF EXISTS");
7835 }
7836
7837 if let Some(ref replace_where) = insert.replace_where {
7839 if self.config.pretty {
7840 self.write_newline();
7841 self.write_indent();
7842 } else {
7843 self.write_space();
7844 }
7845 self.write_keyword("REPLACE WHERE");
7846 self.write_space();
7847 self.generate_expression(replace_where)?;
7848 }
7849
7850 if !insert.partition.is_empty() {
7852 self.write_space();
7853 self.write_keyword("PARTITION");
7854 self.write("(");
7855 for (i, (col, val)) in insert.partition.iter().enumerate() {
7856 if i > 0 {
7857 self.write(", ");
7858 }
7859 self.generate_identifier(col)?;
7860 if let Some(v) = val {
7861 self.write(" = ");
7862 self.generate_expression(v)?;
7863 }
7864 }
7865 self.write(")");
7866 }
7867
7868 if let Some(ref partition_by) = insert.partition_by {
7870 self.write_space();
7871 self.write_keyword("PARTITION BY");
7872 self.write_space();
7873 self.generate_expression(partition_by)?;
7874 }
7875
7876 if !insert.settings.is_empty() {
7878 self.write_space();
7879 self.write_keyword("SETTINGS");
7880 self.write_space();
7881 for (i, setting) in insert.settings.iter().enumerate() {
7882 if i > 0 {
7883 self.write(", ");
7884 }
7885 self.generate_expression(setting)?;
7886 }
7887 }
7888
7889 if !insert.columns.is_empty() {
7890 if insert.alias.is_some() && insert.alias_explicit_as {
7891 self.write("(");
7893 } else {
7894 self.write(" (");
7896 }
7897 for (i, col) in insert.columns.iter().enumerate() {
7898 if i > 0 {
7899 self.write(", ");
7900 }
7901 self.generate_identifier(col)?;
7902 }
7903 self.write(")");
7904 }
7905
7906 if let Some(ref output) = insert.output {
7908 self.generate_output_clause(output)?;
7909 }
7910
7911 if insert.by_name {
7913 self.write_space();
7914 self.write_keyword("BY NAME");
7915 }
7916
7917 if insert.default_values {
7918 self.write_space();
7919 self.write_keyword("DEFAULT VALUES");
7920 } else if let Some(query) = &insert.query {
7921 if self.config.pretty {
7922 self.write_newline();
7923 } else {
7924 self.write_space();
7925 }
7926 if prepend_query_cte.is_some() {
7928 if let Expression::Select(select) = query {
7929 let mut select_no_with = select.clone();
7930 select_no_with.with = None;
7931 self.generate_select(&select_no_with)?;
7932 } else {
7933 self.generate_expression(query)?;
7934 }
7935 } else {
7936 self.generate_expression(query)?;
7937 }
7938 } else if !insert.values.is_empty() {
7939 if self.config.pretty {
7940 self.write_newline();
7942 self.write_keyword("VALUES");
7943 self.write_newline();
7944 self.indent_level += 1;
7945 for (i, row) in insert.values.iter().enumerate() {
7946 if i > 0 {
7947 self.write(",");
7948 self.write_newline();
7949 }
7950 self.write_indent();
7951 self.write("(");
7952 for (j, val) in row.iter().enumerate() {
7953 if j > 0 {
7954 self.write(", ");
7955 }
7956 self.generate_expression(val)?;
7957 }
7958 self.write(")");
7959 }
7960 self.indent_level -= 1;
7961 } else {
7962 self.write_space();
7964 self.write_keyword("VALUES");
7965 for (i, row) in insert.values.iter().enumerate() {
7966 if i > 0 {
7967 self.write(",");
7968 }
7969 self.write(" (");
7970 for (j, val) in row.iter().enumerate() {
7971 if j > 0 {
7972 self.write(", ");
7973 }
7974 self.generate_expression(val)?;
7975 }
7976 self.write(")");
7977 }
7978 }
7979 }
7980
7981 if let Some(ref source) = insert.source {
7983 self.write_space();
7984 self.write_keyword("TABLE");
7985 self.write_space();
7986 self.generate_expression(source)?;
7987 }
7988
7989 if let Some(alias) = &insert.source_alias {
7991 self.write_space();
7992 self.write_keyword("AS");
7993 self.write_space();
7994 self.generate_identifier(alias)?;
7995 }
7996
7997 if let Some(on_conflict) = &insert.on_conflict {
7999 if !matches!(self.config.dialect, Some(DialectType::Materialize)) {
8000 self.write_space();
8001 self.generate_expression(on_conflict)?;
8002 }
8003 }
8004
8005 if !insert.returning.is_empty() {
8007 self.write_space();
8008 self.write_keyword("RETURNING");
8009 self.write_space();
8010 for (i, expr) in insert.returning.iter().enumerate() {
8011 if i > 0 {
8012 self.write(", ");
8013 }
8014 self.generate_expression(expr)?;
8015 }
8016 }
8017
8018 Ok(())
8019 }
8020
8021 fn generate_update(&mut self, update: &Update) -> Result<()> {
8022 for comment in &update.leading_comments {
8024 self.write_formatted_comment(comment);
8025 self.write(" ");
8026 }
8027
8028 if let Some(ref with) = update.with {
8030 self.generate_with(with)?;
8031 self.write_space();
8032 }
8033
8034 self.write_keyword("UPDATE");
8035 if let Some(hint) = &update.hint {
8036 self.generate_hint(hint)?;
8037 }
8038 self.write_space();
8039 self.generate_table(&update.table)?;
8040
8041 let mysql_like_update_from = matches!(
8042 self.config.dialect,
8043 Some(DialectType::MySQL) | Some(DialectType::SingleStore)
8044 ) && update.from_clause.is_some();
8045
8046 let mut set_pairs = update.set.clone();
8047
8048 let mut pre_set_joins = update.table_joins.clone();
8050 if mysql_like_update_from {
8051 let target_name = update
8052 .table
8053 .alias
8054 .as_ref()
8055 .map(|a| a.name.clone())
8056 .unwrap_or_else(|| update.table.name.name.clone());
8057
8058 for (col, _) in &mut set_pairs {
8059 if !col.name.contains('.') {
8060 col.name = format!("{}.{}", target_name, col.name);
8061 }
8062 }
8063
8064 if let Some(from_clause) = &update.from_clause {
8065 for table_expr in &from_clause.expressions {
8066 pre_set_joins.push(crate::expressions::Join {
8067 this: table_expr.clone(),
8068 on: Some(Expression::Boolean(crate::expressions::BooleanLiteral {
8069 value: true,
8070 })),
8071 using: Vec::new(),
8072 kind: crate::expressions::JoinKind::Inner,
8073 use_inner_keyword: false,
8074 use_outer_keyword: false,
8075 deferred_condition: false,
8076 join_hint: None,
8077 match_condition: None,
8078 pivots: Vec::new(),
8079 comments: Vec::new(),
8080 nesting_group: 0,
8081 directed: false,
8082 });
8083 }
8084 }
8085 for join in &update.from_joins {
8086 let mut join = join.clone();
8087 if join.on.is_none() && join.using.is_empty() {
8088 join.on = Some(Expression::Boolean(crate::expressions::BooleanLiteral {
8089 value: true,
8090 }));
8091 }
8092 pre_set_joins.push(join);
8093 }
8094 }
8095
8096 for extra_table in &update.extra_tables {
8098 self.write(", ");
8099 self.generate_table(extra_table)?;
8100 }
8101
8102 for join in &pre_set_joins {
8104 self.generate_join(join)?;
8106 }
8107
8108 let teradata_from_before_set = matches!(self.config.dialect, Some(DialectType::Teradata));
8110 if teradata_from_before_set && !mysql_like_update_from {
8111 if let Some(ref from_clause) = update.from_clause {
8112 self.write_space();
8113 self.write_keyword("FROM");
8114 self.write_space();
8115 for (i, table_expr) in from_clause.expressions.iter().enumerate() {
8116 if i > 0 {
8117 self.write(", ");
8118 }
8119 self.generate_expression(table_expr)?;
8120 }
8121 }
8122 for join in &update.from_joins {
8123 self.generate_join(join)?;
8124 }
8125 }
8126
8127 self.write_space();
8128 self.write_keyword("SET");
8129 self.write_space();
8130
8131 for (i, (col, val)) in set_pairs.iter().enumerate() {
8132 if i > 0 {
8133 self.write(", ");
8134 }
8135 self.generate_identifier(col)?;
8136 self.write(" = ");
8137 self.generate_expression(val)?;
8138 }
8139
8140 if let Some(ref output) = update.output {
8142 self.generate_output_clause(output)?;
8143 }
8144
8145 if !mysql_like_update_from && !teradata_from_before_set {
8147 if let Some(ref from_clause) = update.from_clause {
8148 self.write_space();
8149 self.write_keyword("FROM");
8150 self.write_space();
8151 for (i, table_expr) in from_clause.expressions.iter().enumerate() {
8153 if i > 0 {
8154 self.write(", ");
8155 }
8156 self.generate_expression(table_expr)?;
8157 }
8158 }
8159 }
8160
8161 if !mysql_like_update_from && !teradata_from_before_set {
8162 for join in &update.from_joins {
8164 self.generate_join(join)?;
8165 }
8166 }
8167
8168 if let Some(where_clause) = &update.where_clause {
8169 self.write_space();
8170 self.write_keyword("WHERE");
8171 self.write_space();
8172 self.generate_expression(&where_clause.this)?;
8173 }
8174
8175 if !update.returning.is_empty() {
8177 self.write_space();
8178 self.write_keyword("RETURNING");
8179 self.write_space();
8180 for (i, expr) in update.returning.iter().enumerate() {
8181 if i > 0 {
8182 self.write(", ");
8183 }
8184 self.generate_expression(expr)?;
8185 }
8186 }
8187
8188 if let Some(ref order_by) = update.order_by {
8190 self.write_space();
8191 self.generate_order_by(order_by)?;
8192 }
8193
8194 if let Some(ref limit) = update.limit {
8196 self.write_space();
8197 self.write_keyword("LIMIT");
8198 self.write_space();
8199 self.generate_expression(limit)?;
8200 }
8201
8202 Ok(())
8203 }
8204
8205 fn generate_delete(&mut self, delete: &Delete) -> Result<()> {
8206 if let Some(with) = &delete.with {
8208 self.generate_with(with)?;
8209 self.write_space();
8210 }
8211
8212 for comment in &delete.leading_comments {
8214 self.write_formatted_comment(comment);
8215 self.write(" ");
8216 }
8217
8218 if !delete.tables.is_empty() && !delete.tables_from_using {
8220 self.write_keyword("DELETE");
8222 if let Some(hint) = &delete.hint {
8223 self.generate_hint(hint)?;
8224 }
8225 self.write_space();
8226 for (i, tbl) in delete.tables.iter().enumerate() {
8227 if i > 0 {
8228 self.write(", ");
8229 }
8230 self.generate_table(tbl)?;
8231 }
8232 if let Some(ref output) = delete.output {
8234 self.generate_output_clause(output)?;
8235 }
8236 self.write_space();
8237 self.write_keyword("FROM");
8238 self.write_space();
8239 self.generate_table(&delete.table)?;
8240 } else if !delete.tables.is_empty() && delete.tables_from_using {
8241 self.write_keyword("DELETE");
8243 if let Some(hint) = &delete.hint {
8244 self.generate_hint(hint)?;
8245 }
8246 self.write_space();
8247 self.write_keyword("FROM");
8248 self.write_space();
8249 for (i, tbl) in delete.tables.iter().enumerate() {
8250 if i > 0 {
8251 self.write(", ");
8252 }
8253 self.generate_table(tbl)?;
8254 }
8255 } else if delete.no_from && matches!(self.config.dialect, Some(DialectType::BigQuery)) {
8256 self.write_keyword("DELETE");
8258 if let Some(hint) = &delete.hint {
8259 self.generate_hint(hint)?;
8260 }
8261 self.write_space();
8262 self.generate_table(&delete.table)?;
8263 } else {
8264 self.write_keyword("DELETE");
8265 if let Some(hint) = &delete.hint {
8266 self.generate_hint(hint)?;
8267 }
8268 self.write_space();
8269 self.write_keyword("FROM");
8270 self.write_space();
8271 self.generate_table(&delete.table)?;
8272 }
8273
8274 if let Some(ref on_cluster) = delete.on_cluster {
8276 self.write_space();
8277 self.generate_on_cluster(on_cluster)?;
8278 }
8279
8280 if let Some(ref idx) = delete.force_index {
8282 self.write_space();
8283 self.write_keyword("FORCE INDEX");
8284 self.write(" (");
8285 self.write(idx);
8286 self.write(")");
8287 }
8288
8289 if let Some(ref alias) = delete.alias {
8291 self.write_space();
8292 if delete.alias_explicit_as
8293 || matches!(self.config.dialect, Some(DialectType::BigQuery))
8294 {
8295 self.write_keyword("AS");
8296 self.write_space();
8297 }
8298 self.generate_identifier(alias)?;
8299 }
8300
8301 if !delete.tables_from_using {
8303 for join in &delete.joins {
8304 self.generate_join(join)?;
8305 }
8306 }
8307
8308 if !delete.using.is_empty() {
8310 self.write_space();
8311 self.write_keyword("USING");
8312 for (i, table) in delete.using.iter().enumerate() {
8313 if i > 0 {
8314 self.write(",");
8315 }
8316 self.write_space();
8317 if !table.hints.is_empty() && table.name.is_empty() {
8319 self.generate_expression(&table.hints[0])?;
8321 if let Some(ref alias) = table.alias {
8322 self.write_space();
8323 if table.alias_explicit_as {
8324 self.write_keyword("AS");
8325 self.write_space();
8326 }
8327 self.generate_identifier(alias)?;
8328 if !table.column_aliases.is_empty() {
8329 self.write("(");
8330 for (j, col_alias) in table.column_aliases.iter().enumerate() {
8331 if j > 0 {
8332 self.write(", ");
8333 }
8334 self.generate_identifier(col_alias)?;
8335 }
8336 self.write(")");
8337 }
8338 }
8339 } else {
8340 self.generate_table(table)?;
8341 }
8342 }
8343 }
8344
8345 if delete.tables_from_using {
8347 for join in &delete.joins {
8348 self.generate_join(join)?;
8349 }
8350 }
8351
8352 let output_already_emitted =
8354 !delete.tables.is_empty() && !delete.tables_from_using && delete.output.is_some();
8355 if !output_already_emitted {
8356 if let Some(ref output) = delete.output {
8357 self.generate_output_clause(output)?;
8358 }
8359 }
8360
8361 if let Some(where_clause) = &delete.where_clause {
8362 self.write_space();
8363 self.write_keyword("WHERE");
8364 self.write_space();
8365 self.generate_expression(&where_clause.this)?;
8366 }
8367
8368 if let Some(ref order_by) = delete.order_by {
8370 self.write_space();
8371 self.generate_order_by(order_by)?;
8372 }
8373
8374 if let Some(ref limit) = delete.limit {
8376 self.write_space();
8377 self.write_keyword("LIMIT");
8378 self.write_space();
8379 self.generate_expression(limit)?;
8380 }
8381
8382 if !delete.returning.is_empty() {
8384 self.write_space();
8385 self.write_keyword("RETURNING");
8386 self.write_space();
8387 for (i, expr) in delete.returning.iter().enumerate() {
8388 if i > 0 {
8389 self.write(", ");
8390 }
8391 self.generate_expression(expr)?;
8392 }
8393 }
8394
8395 Ok(())
8396 }
8397
8398 fn generate_create_table(&mut self, ct: &CreateTable) -> Result<()> {
8401 let saved_athena_hive_context = self.athena_hive_context;
8405 let is_clickhouse = matches!(self.config.dialect, Some(DialectType::ClickHouse));
8406 if matches!(
8407 self.config.dialect,
8408 Some(crate::dialects::DialectType::Athena)
8409 ) {
8410 let is_external = ct
8414 .table_modifier
8415 .as_ref()
8416 .map(|m| m.eq_ignore_ascii_case("EXTERNAL"))
8417 .unwrap_or(false);
8418 let has_as_select = ct.as_select.is_some();
8419 self.athena_hive_context = is_external || !has_as_select;
8420 }
8421
8422 if matches!(
8424 self.config.dialect,
8425 Some(crate::dialects::DialectType::TSQL)
8426 ) {
8427 if let Some(ref query) = ct.as_select {
8428 if let Some(with_cte) = &ct.with_cte {
8430 self.generate_with(with_cte)?;
8431 self.write_space();
8432 }
8433
8434 self.write_keyword("SELECT");
8436 self.write(" * ");
8437 self.write_keyword("INTO");
8438 self.write_space();
8439
8440 if ct.temporary {
8442 self.write("#");
8443 }
8444 self.generate_table(&ct.name)?;
8445
8446 self.write_space();
8447 self.write_keyword("FROM");
8448 self.write(" (");
8449 let aliased_query = Self::add_column_aliases_to_query(query.clone());
8451 self.generate_expression(&aliased_query)?;
8452 self.write(") ");
8453 self.write_keyword("AS");
8454 self.write(" temp");
8455 return Ok(());
8456 }
8457 }
8458
8459 if let Some(with_cte) = &ct.with_cte {
8461 self.generate_with(with_cte)?;
8462 self.write_space();
8463 }
8464
8465 for comment in &ct.leading_comments {
8467 self.write_formatted_comment(comment);
8468 self.write(" ");
8469 }
8470 self.write_keyword("CREATE");
8471
8472 if ct.or_replace {
8473 self.write_space();
8474 self.write_keyword("OR REPLACE");
8475 }
8476
8477 if ct.temporary {
8478 self.write_space();
8479 if matches!(self.config.dialect, Some(DialectType::Oracle)) {
8481 self.write_keyword("GLOBAL TEMPORARY");
8482 } else {
8483 self.write_keyword("TEMPORARY");
8484 }
8485 }
8486
8487 let is_dictionary = ct
8489 .table_modifier
8490 .as_ref()
8491 .map(|m| m.eq_ignore_ascii_case("DICTIONARY"))
8492 .unwrap_or(false);
8493 if let Some(ref modifier) = ct.table_modifier {
8494 let skip_transient = modifier.eq_ignore_ascii_case("TRANSIENT")
8496 && !matches!(self.config.dialect, Some(DialectType::Snowflake) | None);
8497 let is_teradata_modifier = modifier.eq_ignore_ascii_case("VOLATILE")
8499 || modifier.eq_ignore_ascii_case("SET")
8500 || modifier.eq_ignore_ascii_case("MULTISET")
8501 || modifier.to_ascii_uppercase().contains("VOLATILE")
8502 || modifier.to_ascii_uppercase().starts_with("SET ")
8503 || modifier.to_ascii_uppercase().starts_with("MULTISET ");
8504 let skip_teradata =
8505 is_teradata_modifier && !matches!(self.config.dialect, Some(DialectType::Teradata));
8506 if !skip_transient && !skip_teradata {
8507 self.write_space();
8508 self.write_keyword(modifier);
8509 }
8510 }
8511
8512 if !is_dictionary {
8513 self.write_space();
8514 self.write_keyword("TABLE");
8515 }
8516
8517 if ct.if_not_exists {
8518 self.write_space();
8519 self.write_keyword("IF NOT EXISTS");
8520 }
8521
8522 self.write_space();
8523 self.generate_table(&ct.name)?;
8524
8525 if let Some(ref uuid) = ct.uuid {
8527 self.write_space();
8528 self.write_keyword("UUID");
8529 self.write(" '");
8530 self.write(uuid);
8531 self.write("'");
8532 }
8533
8534 if let Some(ref on_cluster) = ct.on_cluster {
8536 self.write_space();
8537 self.generate_on_cluster(on_cluster)?;
8538 }
8539
8540 if matches!(
8542 self.config.dialect,
8543 Some(crate::dialects::DialectType::Teradata)
8544 ) && !ct.teradata_post_name_options.is_empty()
8545 {
8546 for opt in &ct.teradata_post_name_options {
8547 self.write(", ");
8548 self.write(opt);
8549 }
8550 }
8551
8552 if ct.copy_grants {
8554 self.write_space();
8555 self.write_keyword("COPY GRANTS");
8556 }
8557
8558 if let Some(ref using_template) = ct.using_template {
8560 self.write_space();
8561 self.write_keyword("USING TEMPLATE");
8562 self.write_space();
8563 self.generate_expression(using_template)?;
8564 return Ok(());
8565 }
8566
8567 if is_clickhouse {
8571 if let Some(ref clone_source) = ct.clone_source {
8572 if ct.columns.is_empty() && ct.constraints.is_empty() {
8573 self.write_space();
8574 self.write_keyword("AS");
8575 self.write_space();
8576 self.generate_table(clone_source)?;
8577 }
8578 }
8579 }
8580
8581 if !is_clickhouse {
8583 if let Some(ref clone_source) = ct.clone_source {
8584 self.write_space();
8585 if ct.is_copy && self.config.supports_table_copy {
8586 self.write_keyword("COPY");
8588 } else if ct.shallow_clone {
8589 self.write_keyword("SHALLOW CLONE");
8590 } else if ct.deep_clone {
8591 self.write_keyword("DEEP CLONE");
8592 } else {
8593 self.write_keyword("CLONE");
8594 }
8595 self.write_space();
8596 self.generate_table(clone_source)?;
8597 if let Some(ref at_clause) = ct.clone_at_clause {
8599 self.write_space();
8600 self.generate_expression(at_clause)?;
8601 }
8602 return Ok(());
8603 }
8604 }
8605
8606 if let Some(ref partition_of) = ct.partition_of {
8610 self.write_space();
8611
8612 if let Expression::PartitionedOfProperty(ref pop) = partition_of {
8614 self.write_keyword("PARTITION OF");
8616 self.write_space();
8617 self.generate_expression(&pop.this)?;
8618
8619 if !ct.columns.is_empty() || !ct.constraints.is_empty() {
8621 self.write(" (");
8622 let mut first = true;
8623 for col in &ct.columns {
8624 if !first {
8625 self.write(", ");
8626 }
8627 first = false;
8628 self.generate_column_def(col)?;
8629 }
8630 for constraint in &ct.constraints {
8631 if !first {
8632 self.write(", ");
8633 }
8634 first = false;
8635 self.generate_table_constraint(constraint)?;
8636 }
8637 self.write(")");
8638 }
8639
8640 if let Expression::PartitionBoundSpec(_) = pop.expression.as_ref() {
8642 self.write_space();
8643 self.write_keyword("FOR VALUES");
8644 self.write_space();
8645 self.generate_expression(&pop.expression)?;
8646 } else {
8647 self.write_space();
8648 self.write_keyword("DEFAULT");
8649 }
8650 } else {
8651 self.generate_expression(partition_of)?;
8653
8654 if !ct.columns.is_empty() || !ct.constraints.is_empty() {
8656 self.write(" (");
8657 let mut first = true;
8658 for col in &ct.columns {
8659 if !first {
8660 self.write(", ");
8661 }
8662 first = false;
8663 self.generate_column_def(col)?;
8664 }
8665 for constraint in &ct.constraints {
8666 if !first {
8667 self.write(", ");
8668 }
8669 first = false;
8670 self.generate_table_constraint(constraint)?;
8671 }
8672 self.write(")");
8673 }
8674 }
8675
8676 for prop in &ct.properties {
8678 self.write_space();
8679 self.generate_expression(prop)?;
8680 }
8681
8682 return Ok(());
8683 }
8684
8685 self.sqlite_inline_pk_columns.clear();
8688 if matches!(
8689 self.config.dialect,
8690 Some(crate::dialects::DialectType::SQLite)
8691 ) {
8692 for constraint in &ct.constraints {
8693 if let TableConstraint::PrimaryKey { columns, name, .. } = constraint {
8694 if columns.len() == 1 && name.is_none() {
8696 let pk_col_name = columns[0].name.to_ascii_lowercase();
8697 if ct
8699 .columns
8700 .iter()
8701 .any(|c| c.name.name.to_ascii_lowercase() == pk_col_name)
8702 {
8703 self.sqlite_inline_pk_columns.insert(pk_col_name);
8704 }
8705 }
8706 }
8707 }
8708 }
8709
8710 if !ct.columns.is_empty() {
8712 if self.config.pretty {
8713 self.write(" (");
8715 self.write_newline();
8716 self.indent_level += 1;
8717 for (i, col) in ct.columns.iter().enumerate() {
8718 if i > 0 {
8719 self.write(",");
8720 self.write_newline();
8721 }
8722 self.write_indent();
8723 self.generate_column_def(col)?;
8724 }
8725 for constraint in &ct.constraints {
8727 if let TableConstraint::PrimaryKey { columns, name, .. } = constraint {
8729 if columns.len() == 1
8730 && name.is_none()
8731 && self
8732 .sqlite_inline_pk_columns
8733 .contains(&columns[0].name.to_ascii_lowercase())
8734 {
8735 continue;
8736 }
8737 }
8738 self.write(",");
8739 self.write_newline();
8740 self.write_indent();
8741 self.generate_table_constraint(constraint)?;
8742 }
8743 self.indent_level -= 1;
8744 self.write_newline();
8745 self.write(")");
8746 } else {
8747 self.write(" (");
8748 for (i, col) in ct.columns.iter().enumerate() {
8749 if i > 0 {
8750 self.write(", ");
8751 }
8752 self.generate_column_def(col)?;
8753 }
8754 let mut first_constraint = true;
8756 for constraint in &ct.constraints {
8757 if let TableConstraint::PrimaryKey { columns, name, .. } = constraint {
8759 if columns.len() == 1
8760 && name.is_none()
8761 && self
8762 .sqlite_inline_pk_columns
8763 .contains(&columns[0].name.to_ascii_lowercase())
8764 {
8765 continue;
8766 }
8767 }
8768 if first_constraint {
8769 self.write(", ");
8770 first_constraint = false;
8771 } else {
8772 self.write(", ");
8773 }
8774 self.generate_table_constraint(constraint)?;
8775 }
8776 self.write(")");
8777 }
8778 } else if !ct.constraints.is_empty() {
8779 let has_like_only = ct
8781 .constraints
8782 .iter()
8783 .all(|c| matches!(c, TableConstraint::Like { .. }));
8784 let has_tags_only = ct
8785 .constraints
8786 .iter()
8787 .all(|c| matches!(c, TableConstraint::Tags(_)));
8788 let is_pg_like = matches!(
8792 self.config.dialect,
8793 Some(crate::dialects::DialectType::PostgreSQL)
8794 | Some(crate::dialects::DialectType::CockroachDB)
8795 | Some(crate::dialects::DialectType::Materialize)
8796 | Some(crate::dialects::DialectType::RisingWave)
8797 | Some(crate::dialects::DialectType::Redshift)
8798 | Some(crate::dialects::DialectType::Presto)
8799 | Some(crate::dialects::DialectType::Trino)
8800 | Some(crate::dialects::DialectType::Athena)
8801 );
8802 let use_parens = if has_like_only {
8803 is_pg_like
8804 } else {
8805 !has_tags_only
8806 };
8807 if self.config.pretty && use_parens {
8808 self.write(" (");
8809 self.write_newline();
8810 self.indent_level += 1;
8811 for (i, constraint) in ct.constraints.iter().enumerate() {
8812 if i > 0 {
8813 self.write(",");
8814 self.write_newline();
8815 }
8816 self.write_indent();
8817 self.generate_table_constraint(constraint)?;
8818 }
8819 self.indent_level -= 1;
8820 self.write_newline();
8821 self.write(")");
8822 } else {
8823 if use_parens {
8824 self.write(" (");
8825 } else {
8826 self.write_space();
8827 }
8828 for (i, constraint) in ct.constraints.iter().enumerate() {
8829 if i > 0 {
8830 self.write(", ");
8831 }
8832 self.generate_table_constraint(constraint)?;
8833 }
8834 if use_parens {
8835 self.write(")");
8836 }
8837 }
8838 }
8839
8840 if is_clickhouse && (!ct.columns.is_empty() || !ct.constraints.is_empty()) {
8841 if let Some(ref clone_source) = ct.clone_source {
8842 self.write_space();
8843 self.write_keyword("AS");
8844 self.write_space();
8845 self.generate_table(clone_source)?;
8846 }
8847 }
8848
8849 if let Some(ref on_prop) = ct.on_property {
8851 self.write(" ");
8852 self.write_keyword("ON");
8853 self.write(" ");
8854 self.generate_expression(&on_prop.this)?;
8855 }
8856
8857 if !ct.with_partition_columns.is_empty() {
8859 if self.config.pretty {
8860 self.write_newline();
8861 } else {
8862 self.write_space();
8863 }
8864 self.write_keyword("WITH PARTITION COLUMNS");
8865 self.write(" (");
8866 if self.config.pretty {
8867 self.write_newline();
8868 self.indent_level += 1;
8869 for (i, col) in ct.with_partition_columns.iter().enumerate() {
8870 if i > 0 {
8871 self.write(",");
8872 self.write_newline();
8873 }
8874 self.write_indent();
8875 self.generate_column_def(col)?;
8876 }
8877 self.indent_level -= 1;
8878 self.write_newline();
8879 } else {
8880 for (i, col) in ct.with_partition_columns.iter().enumerate() {
8881 if i > 0 {
8882 self.write(", ");
8883 }
8884 self.generate_column_def(col)?;
8885 }
8886 }
8887 self.write(")");
8888 }
8889
8890 if let Some(ref conn) = ct.with_connection {
8892 if self.config.pretty {
8893 self.write_newline();
8894 } else {
8895 self.write_space();
8896 }
8897 self.write_keyword("WITH CONNECTION");
8898 self.write_space();
8899 self.generate_table(conn)?;
8900 }
8901
8902 if !is_clickhouse {
8905 for prop in &ct.properties {
8906 if let Expression::SchemaCommentProperty(_) = prop {
8907 if self.config.pretty {
8908 self.write_newline();
8909 } else {
8910 self.write_space();
8911 }
8912 self.generate_expression(prop)?;
8913 }
8914 }
8915 }
8916
8917 if !ct.with_properties.is_empty() {
8919 let is_snowflake_special_table = matches!(
8921 self.config.dialect,
8922 Some(crate::dialects::DialectType::Snowflake)
8923 ) && (ct.table_modifier.as_deref() == Some("ICEBERG")
8924 || ct.table_modifier.as_deref() == Some("DYNAMIC"));
8925 if is_snowflake_special_table {
8926 for (key, value) in &ct.with_properties {
8927 self.write_space();
8928 self.write(key);
8929 self.write("=");
8930 self.write(value);
8931 }
8932 } else if self.config.pretty {
8933 self.write_newline();
8934 self.write_keyword("WITH");
8935 self.write(" (");
8936 self.write_newline();
8937 self.indent_level += 1;
8938 for (i, (key, value)) in ct.with_properties.iter().enumerate() {
8939 if i > 0 {
8940 self.write(",");
8941 self.write_newline();
8942 }
8943 self.write_indent();
8944 self.write(key);
8945 self.write("=");
8946 self.write(value);
8947 }
8948 self.indent_level -= 1;
8949 self.write_newline();
8950 self.write(")");
8951 } else {
8952 self.write_space();
8953 self.write_keyword("WITH");
8954 self.write(" (");
8955 for (i, (key, value)) in ct.with_properties.iter().enumerate() {
8956 if i > 0 {
8957 self.write(", ");
8958 }
8959 self.write(key);
8960 self.write("=");
8961 self.write(value);
8962 }
8963 self.write(")");
8964 }
8965 }
8966
8967 let (pre_as_properties, post_as_properties): (Vec<&Expression>, Vec<&Expression>) =
8968 if is_clickhouse && ct.as_select.is_some() {
8969 let mut pre = Vec::new();
8970 let mut post = Vec::new();
8971 for prop in &ct.properties {
8972 if matches!(prop, Expression::SchemaCommentProperty(_)) {
8973 post.push(prop);
8974 } else {
8975 pre.push(prop);
8976 }
8977 }
8978 (pre, post)
8979 } else {
8980 (ct.properties.iter().collect(), Vec::new())
8981 };
8982
8983 for prop in pre_as_properties {
8985 if !is_clickhouse && matches!(prop, Expression::SchemaCommentProperty(_)) {
8987 continue;
8988 }
8989 if self.config.pretty {
8990 self.write_newline();
8991 } else {
8992 self.write_space();
8993 }
8994 if let Expression::Properties(props) = prop {
8998 let is_hive_dialect = matches!(
8999 self.config.dialect,
9000 Some(crate::dialects::DialectType::Hive)
9001 | Some(crate::dialects::DialectType::Spark)
9002 | Some(crate::dialects::DialectType::Databricks)
9003 | Some(crate::dialects::DialectType::Athena)
9004 );
9005 let is_doris_starrocks = matches!(
9006 self.config.dialect,
9007 Some(crate::dialects::DialectType::Doris)
9008 | Some(crate::dialects::DialectType::StarRocks)
9009 );
9010 if is_hive_dialect {
9011 self.generate_tblproperties_clause(&props.expressions)?;
9012 } else if is_doris_starrocks {
9013 self.generate_properties_clause(&props.expressions)?;
9014 } else {
9015 self.generate_options_clause(&props.expressions)?;
9016 }
9017 } else {
9018 self.generate_expression(prop)?;
9019 }
9020 }
9021
9022 for prop in &ct.post_table_properties {
9024 if let Expression::WithSystemVersioningProperty(ref svp) = prop {
9025 self.write(" WITH(");
9026 self.generate_system_versioning_content(svp)?;
9027 self.write(")");
9028 } else if let Expression::Properties(props) = prop {
9029 let is_doris_starrocks = matches!(
9031 self.config.dialect,
9032 Some(crate::dialects::DialectType::Doris)
9033 | Some(crate::dialects::DialectType::StarRocks)
9034 );
9035 self.write_space();
9036 if is_doris_starrocks {
9037 self.generate_properties_clause(&props.expressions)?;
9038 } else {
9039 self.generate_options_clause(&props.expressions)?;
9040 }
9041 } else {
9042 self.write_space();
9043 self.generate_expression(prop)?;
9044 }
9045 }
9046
9047 if let Some(ref rollup) = ct.rollup {
9050 if matches!(self.config.dialect, Some(DialectType::StarRocks)) {
9051 self.write_space();
9052 self.generate_rollup_property(rollup)?;
9053 }
9054 }
9055
9056 let is_mysql_compatible = matches!(
9060 self.config.dialect,
9061 Some(DialectType::MySQL)
9062 | Some(DialectType::TiDB)
9063 | Some(DialectType::SingleStore)
9064 | Some(DialectType::Doris)
9065 | Some(DialectType::StarRocks)
9066 | None
9067 );
9068 let is_hive_compatible = matches!(
9069 self.config.dialect,
9070 Some(DialectType::Hive)
9071 | Some(DialectType::Spark)
9072 | Some(DialectType::Databricks)
9073 | Some(DialectType::Athena)
9074 );
9075 let mysql_pretty_options =
9076 self.config.pretty && matches!(self.config.dialect, Some(DialectType::MySQL));
9077 for (key, value) in &ct.mysql_table_options {
9078 let should_output = if is_mysql_compatible {
9080 true
9081 } else if is_hive_compatible && key == "COMMENT" {
9082 true } else {
9084 false
9085 };
9086 if should_output {
9087 if mysql_pretty_options {
9088 self.write_newline();
9089 self.write_indent();
9090 } else {
9091 self.write_space();
9092 }
9093 self.write_keyword(key);
9094 if key == "COMMENT" && !self.config.schema_comment_with_eq {
9096 self.write_space();
9097 } else {
9098 self.write("=");
9099 }
9100 self.write(value);
9101 }
9102 }
9103
9104 for option in &ct.tidb_table_options {
9105 if self.config.pretty {
9106 self.write_newline();
9107 self.write_indent();
9108 } else {
9109 self.write_space();
9110 }
9111 self.generate_tidb_table_option(option, false)?;
9112 }
9113
9114 if ct.temporary
9116 && matches!(
9117 self.config.dialect,
9118 Some(DialectType::Spark) | Some(DialectType::Databricks)
9119 )
9120 && ct.as_select.is_none()
9121 {
9122 self.write_space();
9123 self.write_keyword("USING PARQUET");
9124 }
9125
9126 if !ct.inherits.is_empty() {
9128 self.write_space();
9129 self.write_keyword("INHERITS");
9130 self.write(" (");
9131 for (i, parent) in ct.inherits.iter().enumerate() {
9132 if i > 0 {
9133 self.write(", ");
9134 }
9135 self.generate_table(parent)?;
9136 }
9137 self.write(")");
9138 }
9139
9140 if let Some(ref query) = ct.as_select {
9142 self.write_space();
9143 self.write_keyword("AS");
9144 self.write_space();
9145 let source_is_clickhouse =
9146 matches!(self.config.source_dialect, Some(DialectType::ClickHouse));
9147 let wrap_as_select =
9148 ct.as_select_parenthesized && !(is_clickhouse && source_is_clickhouse);
9149 if wrap_as_select {
9150 self.write("(");
9151 }
9152 self.generate_expression(query)?;
9153 if wrap_as_select {
9154 self.write(")");
9155 }
9156
9157 if let Some(with_data) = ct.with_data {
9159 self.write_space();
9160 self.write_keyword("WITH");
9161 if !with_data {
9162 self.write_space();
9163 self.write_keyword("NO");
9164 }
9165 self.write_space();
9166 self.write_keyword("DATA");
9167 }
9168
9169 if let Some(with_statistics) = ct.with_statistics {
9171 self.write_space();
9172 self.write_keyword("AND");
9173 if !with_statistics {
9174 self.write_space();
9175 self.write_keyword("NO");
9176 }
9177 self.write_space();
9178 self.write_keyword("STATISTICS");
9179 }
9180
9181 for index in &ct.teradata_indexes {
9183 self.write_space();
9184 match index.kind {
9185 TeradataIndexKind::NoPrimary => {
9186 self.write_keyword("NO PRIMARY INDEX");
9187 }
9188 TeradataIndexKind::Primary => {
9189 self.write_keyword("PRIMARY INDEX");
9190 }
9191 TeradataIndexKind::PrimaryAmp => {
9192 self.write_keyword("PRIMARY AMP INDEX");
9193 }
9194 TeradataIndexKind::Unique => {
9195 self.write_keyword("UNIQUE INDEX");
9196 }
9197 TeradataIndexKind::UniquePrimary => {
9198 self.write_keyword("UNIQUE PRIMARY INDEX");
9199 }
9200 TeradataIndexKind::Secondary => {
9201 self.write_keyword("INDEX");
9202 }
9203 }
9204 if let Some(ref name) = index.name {
9206 self.write_space();
9207 self.write(name);
9208 }
9209 if !index.columns.is_empty() {
9211 self.write(" (");
9212 for (i, col) in index.columns.iter().enumerate() {
9213 if i > 0 {
9214 self.write(", ");
9215 }
9216 self.write(col);
9217 }
9218 self.write(")");
9219 }
9220 }
9221
9222 if let Some(ref on_commit) = ct.on_commit {
9224 self.write_space();
9225 self.write_keyword("ON COMMIT");
9226 self.write_space();
9227 match on_commit {
9228 OnCommit::PreserveRows => self.write_keyword("PRESERVE ROWS"),
9229 OnCommit::DeleteRows => self.write_keyword("DELETE ROWS"),
9230 }
9231 }
9232
9233 if !post_as_properties.is_empty() {
9234 for prop in post_as_properties {
9235 self.write_space();
9236 self.generate_expression(prop)?;
9237 }
9238 }
9239
9240 self.athena_hive_context = saved_athena_hive_context;
9242 return Ok(());
9243 }
9244
9245 if let Some(ref on_commit) = ct.on_commit {
9247 self.write_space();
9248 self.write_keyword("ON COMMIT");
9249 self.write_space();
9250 match on_commit {
9251 OnCommit::PreserveRows => self.write_keyword("PRESERVE ROWS"),
9252 OnCommit::DeleteRows => self.write_keyword("DELETE ROWS"),
9253 }
9254 }
9255
9256 self.athena_hive_context = saved_athena_hive_context;
9258
9259 Ok(())
9260 }
9261
9262 fn generate_column_def_expr(&mut self, col: &ColumnDef) -> Result<()> {
9265 self.generate_identifier(&col.name)?;
9267 if !matches!(col.data_type, DataType::Unknown) {
9269 self.write_space();
9270 self.generate_data_type(&col.data_type)?;
9271 }
9272 for constraint in &col.constraints {
9274 if let ColumnConstraint::Path(path_expr) = constraint {
9275 self.write_space();
9276 self.write_keyword("PATH");
9277 self.write_space();
9278 self.generate_expression(path_expr)?;
9279 }
9280 }
9281 Ok(())
9282 }
9283
9284 fn generate_column_def(&mut self, col: &ColumnDef) -> Result<()> {
9285 let has_computed_no_type = matches!(&col.data_type, DataType::Custom { name } if name.is_empty())
9287 && col
9288 .constraints
9289 .iter()
9290 .any(|c| matches!(c, ColumnConstraint::ComputedColumn(_)));
9291 let omit_computed_type = !self.config.computed_column_with_type
9293 && col
9294 .constraints
9295 .iter()
9296 .any(|c| matches!(c, ColumnConstraint::ComputedColumn(_)));
9297
9298 let is_partition_column_spec = matches!(col.data_type, DataType::Unknown);
9301
9302 let has_no_type = col.no_type
9305 || (matches!(&col.data_type, DataType::Custom { name } if name.is_empty())
9306 && col.constraints.is_empty());
9307
9308 self.generate_identifier(&col.name)?;
9309
9310 let serial_expansion = if matches!(
9312 self.config.dialect,
9313 Some(DialectType::Materialize) | Some(DialectType::PostgreSQL)
9314 ) {
9315 if let DataType::Custom { ref name } = col.data_type {
9316 if name.eq_ignore_ascii_case("SERIAL") {
9317 Some("INT")
9318 } else if name.eq_ignore_ascii_case("BIGSERIAL") {
9319 Some("BIGINT")
9320 } else if name.eq_ignore_ascii_case("SMALLSERIAL") {
9321 Some("SMALLINT")
9322 } else {
9323 None
9324 }
9325 } else {
9326 None
9327 }
9328 } else {
9329 None
9330 };
9331
9332 if !has_computed_no_type && !omit_computed_type && !is_partition_column_spec && !has_no_type
9333 {
9334 self.write_space();
9335 let saved_nullable_depth = self.clickhouse_nullable_depth;
9338 if matches!(self.config.dialect, Some(DialectType::ClickHouse)) {
9339 self.clickhouse_nullable_depth = -1;
9340 }
9341 if let Some(int_type) = serial_expansion {
9342 self.write_keyword(int_type);
9344 } else if col.unsigned && matches!(self.config.dialect, Some(DialectType::DuckDB)) {
9345 let unsigned_type = match &col.data_type {
9347 DataType::Int { .. } => Some("UINTEGER"),
9348 DataType::BigInt { .. } => Some("UBIGINT"),
9349 DataType::SmallInt { .. } => Some("USMALLINT"),
9350 DataType::TinyInt { .. } => Some("UTINYINT"),
9351 _ => None,
9352 };
9353 if let Some(utype) = unsigned_type {
9354 self.write_keyword(utype);
9355 } else {
9356 self.generate_data_type(&col.data_type)?;
9357 }
9358 } else {
9359 self.generate_data_type(&col.data_type)?;
9360 }
9361 self.clickhouse_nullable_depth = saved_nullable_depth;
9362 }
9363
9364 if col.unsigned && !matches!(self.config.dialect, Some(DialectType::DuckDB)) {
9367 self.write_space();
9368 self.write_keyword("UNSIGNED");
9369 }
9370 if col.zerofill {
9371 self.write_space();
9372 self.write_keyword("ZEROFILL");
9373 }
9374
9375 if let Some(ref charset) = col.character_set {
9379 self.write_space();
9380 self.write_keyword("CHARACTER SET");
9381 self.write_space();
9382 self.write(charset);
9383 }
9384
9385 if col.uppercase {
9386 self.write_space();
9387 self.write_keyword("UPPERCASE");
9388 }
9389
9390 if let Some(casespecific) = col.casespecific {
9391 self.write_space();
9392 if casespecific {
9393 self.write_keyword("CASESPECIFIC");
9394 } else {
9395 self.write_keyword("NOT CASESPECIFIC");
9396 }
9397 }
9398
9399 if let Some(ref format) = col.format {
9400 self.write_space();
9401 self.write_keyword("FORMAT");
9402 self.write(" '");
9403 self.write(format);
9404 self.write("'");
9405 }
9406
9407 if let Some(ref title) = col.title {
9408 self.write_space();
9409 self.write_keyword("TITLE");
9410 self.write(" '");
9411 self.write(title);
9412 self.write("'");
9413 }
9414
9415 if let Some(length) = col.inline_length {
9416 self.write_space();
9417 self.write_keyword("INLINE LENGTH");
9418 self.write(" ");
9419 self.write(&length.to_string());
9420 }
9421
9422 if let Some(ref compress) = col.compress {
9423 self.write_space();
9424 self.write_keyword("COMPRESS");
9425 if !compress.is_empty() {
9426 if compress.len() == 1 {
9428 if let Expression::Literal(lit) = &compress[0] {
9429 if let Literal::String(_) = lit.as_ref() {
9430 self.write_space();
9431 self.generate_expression(&compress[0])?;
9432 }
9433 } else {
9434 self.write(" (");
9435 self.generate_expression(&compress[0])?;
9436 self.write(")");
9437 }
9438 } else {
9439 self.write(" (");
9440 for (i, val) in compress.iter().enumerate() {
9441 if i > 0 {
9442 self.write(", ");
9443 }
9444 self.generate_expression(val)?;
9445 }
9446 self.write(")");
9447 }
9448 }
9449 }
9450
9451 if !col.constraint_order.is_empty() {
9454 let mut references_idx = 0;
9457 let mut check_idx = 0;
9458 let mut generated_idx = 0;
9459 let mut collate_idx = 0;
9460 let mut comment_idx = 0;
9461 let defer_not_null_after_identity = false;
9464 let mut pending_not_null_after_identity = false;
9465
9466 for constraint_type in &col.constraint_order {
9467 match constraint_type {
9468 ConstraintType::PrimaryKey => {
9469 if col.primary_key
9471 && !matches!(self.config.dialect, Some(DialectType::Materialize))
9472 {
9473 if let Some(ref cname) = col.primary_key_constraint_name {
9474 self.write_space();
9475 self.write_keyword("CONSTRAINT");
9476 self.write_space();
9477 self.write(cname);
9478 }
9479 self.write_space();
9480 self.write_keyword("PRIMARY KEY");
9481 if let Some(ref order) = col.primary_key_order {
9482 self.write_space();
9483 match order {
9484 SortOrder::Asc => self.write_keyword("ASC"),
9485 SortOrder::Desc => self.write_keyword("DESC"),
9486 }
9487 }
9488 }
9489 }
9490 ConstraintType::Unique => {
9491 if col.unique {
9492 if let Some(ref cname) = col.unique_constraint_name {
9493 self.write_space();
9494 self.write_keyword("CONSTRAINT");
9495 self.write_space();
9496 self.write(cname);
9497 }
9498 self.write_space();
9499 self.write_keyword("UNIQUE");
9500 if col.unique_nulls_not_distinct {
9502 self.write(" NULLS NOT DISTINCT");
9503 }
9504 }
9505 }
9506 ConstraintType::NotNull => {
9507 if col.nullable == Some(false) {
9508 if defer_not_null_after_identity {
9509 pending_not_null_after_identity = true;
9510 continue;
9511 }
9512 if let Some(ref cname) = col.not_null_constraint_name {
9513 self.write_space();
9514 self.write_keyword("CONSTRAINT");
9515 self.write_space();
9516 self.write(cname);
9517 }
9518 self.write_space();
9519 self.write_keyword("NOT NULL");
9520 }
9521 }
9522 ConstraintType::Null => {
9523 if col.nullable == Some(true) {
9524 self.write_space();
9525 self.write_keyword("NULL");
9526 }
9527 }
9528 ConstraintType::Default => {
9529 if let Some(ref default) = col.default {
9530 self.write_space();
9531 self.write_keyword("DEFAULT");
9532 self.write_space();
9533 self.generate_expression(default)?;
9534 }
9535 }
9536 ConstraintType::AutoIncrement => {
9537 if col.auto_increment {
9538 if matches!(
9540 self.config.dialect,
9541 Some(crate::dialects::DialectType::DuckDB)
9542 ) {
9543 } else if matches!(
9545 self.config.dialect,
9546 Some(crate::dialects::DialectType::Materialize)
9547 ) {
9548 if !matches!(col.nullable, Some(false)) {
9550 self.write_space();
9551 self.write_keyword("NOT NULL");
9552 }
9553 } else if matches!(
9554 self.config.dialect,
9555 Some(crate::dialects::DialectType::PostgreSQL)
9556 ) {
9557 self.write_space();
9559 self.generate_auto_increment_keyword(col)?;
9560 } else if matches!(
9561 self.config.dialect,
9562 Some(crate::dialects::DialectType::SQLite)
9563 ) && !col.primary_key
9564 && self
9565 .sqlite_inline_pk_columns
9566 .contains(&col.name.name.to_ascii_lowercase())
9567 {
9568 } else {
9571 self.write_space();
9572 self.generate_auto_increment_keyword(col)?;
9573 if pending_not_null_after_identity {
9574 self.write_space();
9575 self.write_keyword("NOT NULL");
9576 pending_not_null_after_identity = false;
9577 }
9578 }
9579 } }
9581 ConstraintType::AutoRandom => {
9582 if let Some(ref auto_random) = col.auto_random {
9583 self.write_space();
9584 self.generate_tidb_auto_random(auto_random)?;
9585 }
9586 }
9587 ConstraintType::References => {
9588 while references_idx < col.constraints.len() {
9590 if let ColumnConstraint::References(fk_ref) =
9591 &col.constraints[references_idx]
9592 {
9593 if let Some(ref name) = fk_ref.constraint_name {
9595 self.write_space();
9596 self.write_keyword("CONSTRAINT");
9597 self.write_space();
9598 self.write(name);
9599 }
9600 self.write_space();
9601 if fk_ref.has_foreign_key_keywords {
9602 self.write_keyword("FOREIGN KEY");
9603 self.write_space();
9604 }
9605 self.write_keyword("REFERENCES");
9606 self.write_space();
9607 self.generate_table(&fk_ref.table)?;
9608 if !fk_ref.columns.is_empty() {
9609 self.write(" (");
9610 for (i, c) in fk_ref.columns.iter().enumerate() {
9611 if i > 0 {
9612 self.write(", ");
9613 }
9614 self.generate_identifier(c)?;
9615 }
9616 self.write(")");
9617 }
9618 self.generate_referential_actions(fk_ref)?;
9619 references_idx += 1;
9620 break;
9621 }
9622 references_idx += 1;
9623 }
9624 }
9625 ConstraintType::Check => {
9626 while check_idx < col.constraints.len() {
9628 if let ColumnConstraint::Check(expr) = &col.constraints[check_idx] {
9629 if check_idx == 0 {
9631 if let Some(ref cname) = col.check_constraint_name {
9632 self.write_space();
9633 self.write_keyword("CONSTRAINT");
9634 self.write_space();
9635 self.write(cname);
9636 }
9637 }
9638 self.write_space();
9639 self.write_keyword("CHECK");
9640 self.write(" (");
9641 self.generate_expression(expr)?;
9642 self.write(")");
9643 check_idx += 1;
9644 break;
9645 }
9646 check_idx += 1;
9647 }
9648 }
9649 ConstraintType::GeneratedAsIdentity => {
9650 while generated_idx < col.constraints.len() {
9652 if let ColumnConstraint::GeneratedAsIdentity(gen) =
9653 &col.constraints[generated_idx]
9654 {
9655 self.write_space();
9656 if matches!(
9658 self.config.dialect,
9659 Some(crate::dialects::DialectType::Redshift)
9660 ) {
9661 self.write_keyword("IDENTITY");
9662 self.write("(");
9663 if let Some(ref start) = gen.start {
9664 self.generate_expression(start)?;
9665 } else {
9666 self.write("0");
9667 }
9668 self.write(", ");
9669 if let Some(ref incr) = gen.increment {
9670 self.generate_expression(incr)?;
9671 } else {
9672 self.write("1");
9673 }
9674 self.write(")");
9675 } else {
9676 self.write_keyword("GENERATED");
9677 if gen.always {
9678 self.write_space();
9679 self.write_keyword("ALWAYS");
9680 } else {
9681 self.write_space();
9682 self.write_keyword("BY DEFAULT");
9683 if gen.on_null {
9684 self.write_space();
9685 self.write_keyword("ON NULL");
9686 }
9687 }
9688 self.write_space();
9689 self.write_keyword("AS IDENTITY");
9690
9691 let has_options = gen.start.is_some()
9692 || gen.increment.is_some()
9693 || gen.minvalue.is_some()
9694 || gen.maxvalue.is_some()
9695 || gen.cycle.is_some();
9696 if has_options {
9697 self.write(" (");
9698 let mut first = true;
9699 if let Some(ref start) = gen.start {
9700 if !first {
9701 self.write(" ");
9702 }
9703 first = false;
9704 self.write_keyword("START WITH");
9705 self.write_space();
9706 self.generate_expression(start)?;
9707 }
9708 if let Some(ref incr) = gen.increment {
9709 if !first {
9710 self.write(" ");
9711 }
9712 first = false;
9713 self.write_keyword("INCREMENT BY");
9714 self.write_space();
9715 self.generate_expression(incr)?;
9716 }
9717 if let Some(ref minv) = gen.minvalue {
9718 if !first {
9719 self.write(" ");
9720 }
9721 first = false;
9722 self.write_keyword("MINVALUE");
9723 self.write_space();
9724 self.generate_expression(minv)?;
9725 }
9726 if let Some(ref maxv) = gen.maxvalue {
9727 if !first {
9728 self.write(" ");
9729 }
9730 first = false;
9731 self.write_keyword("MAXVALUE");
9732 self.write_space();
9733 self.generate_expression(maxv)?;
9734 }
9735 if let Some(cycle) = gen.cycle {
9736 if !first {
9737 self.write(" ");
9738 }
9739 if cycle {
9740 self.write_keyword("CYCLE");
9741 } else {
9742 self.write_keyword("NO CYCLE");
9743 }
9744 }
9745 self.write(")");
9746 }
9747 }
9748 generated_idx += 1;
9749 break;
9750 }
9751 generated_idx += 1;
9752 }
9753 }
9754 ConstraintType::Collate => {
9755 while collate_idx < col.constraints.len() {
9757 if let ColumnConstraint::Collate(collation) =
9758 &col.constraints[collate_idx]
9759 {
9760 self.write_space();
9761 self.write_keyword("COLLATE");
9762 self.write_space();
9763 self.generate_identifier(collation)?;
9764 collate_idx += 1;
9765 break;
9766 }
9767 collate_idx += 1;
9768 }
9769 }
9770 ConstraintType::Comment => {
9771 while comment_idx < col.constraints.len() {
9773 if let ColumnConstraint::Comment(comment) =
9774 &col.constraints[comment_idx]
9775 {
9776 self.write_space();
9777 self.write_keyword("COMMENT");
9778 self.write_space();
9779 self.generate_string_literal(comment)?;
9780 comment_idx += 1;
9781 break;
9782 }
9783 comment_idx += 1;
9784 }
9785 }
9786 ConstraintType::Tags => {
9787 for constraint in &col.constraints {
9789 if let ColumnConstraint::Tags(tags) = constraint {
9790 self.write_space();
9791 self.write_keyword("TAG");
9792 self.write(" (");
9793 for (i, expr) in tags.expressions.iter().enumerate() {
9794 if i > 0 {
9795 self.write(", ");
9796 }
9797 self.generate_expression(expr)?;
9798 }
9799 self.write(")");
9800 break;
9801 }
9802 }
9803 }
9804 ConstraintType::ComputedColumn => {
9805 for constraint in &col.constraints {
9807 if let ColumnConstraint::ComputedColumn(cc) = constraint {
9808 self.write_space();
9809 self.generate_computed_column_inline(cc)?;
9810 break;
9811 }
9812 }
9813 }
9814 ConstraintType::GeneratedAsRow => {
9815 for constraint in &col.constraints {
9817 if let ColumnConstraint::GeneratedAsRow(gar) = constraint {
9818 self.write_space();
9819 self.generate_generated_as_row_inline(gar)?;
9820 break;
9821 }
9822 }
9823 }
9824 ConstraintType::OnUpdate => {
9825 if let Some(ref expr) = col.on_update {
9826 self.write_space();
9827 self.write_keyword("ON UPDATE");
9828 self.write_space();
9829 self.generate_expression(expr)?;
9830 }
9831 }
9832 ConstraintType::Encode => {
9833 if let Some(ref encoding) = col.encoding {
9834 self.write_space();
9835 self.write_keyword("ENCODE");
9836 self.write_space();
9837 self.write(encoding);
9838 }
9839 }
9840 ConstraintType::Path => {
9841 for constraint in &col.constraints {
9843 if let ColumnConstraint::Path(path_expr) = constraint {
9844 self.write_space();
9845 self.write_keyword("PATH");
9846 self.write_space();
9847 self.generate_expression(path_expr)?;
9848 break;
9849 }
9850 }
9851 }
9852 }
9853 }
9854 if pending_not_null_after_identity {
9855 self.write_space();
9856 self.write_keyword("NOT NULL");
9857 }
9858 } else {
9859 if col.primary_key {
9861 self.write_space();
9862 self.write_keyword("PRIMARY KEY");
9863 if let Some(ref order) = col.primary_key_order {
9864 self.write_space();
9865 match order {
9866 SortOrder::Asc => self.write_keyword("ASC"),
9867 SortOrder::Desc => self.write_keyword("DESC"),
9868 }
9869 }
9870 }
9871
9872 if col.unique {
9873 self.write_space();
9874 self.write_keyword("UNIQUE");
9875 if col.unique_nulls_not_distinct {
9877 self.write(" NULLS NOT DISTINCT");
9878 }
9879 }
9880
9881 match col.nullable {
9882 Some(false) => {
9883 self.write_space();
9884 self.write_keyword("NOT NULL");
9885 }
9886 Some(true) => {
9887 self.write_space();
9888 self.write_keyword("NULL");
9889 }
9890 None => {}
9891 }
9892
9893 if let Some(ref default) = col.default {
9894 self.write_space();
9895 self.write_keyword("DEFAULT");
9896 self.write_space();
9897 self.generate_expression(default)?;
9898 }
9899
9900 if col.auto_increment {
9901 self.write_space();
9902 self.generate_auto_increment_keyword(col)?;
9903 }
9904
9905 if let Some(ref auto_random) = col.auto_random {
9906 self.write_space();
9907 self.generate_tidb_auto_random(auto_random)?;
9908 }
9909
9910 for constraint in &col.constraints {
9912 match constraint {
9913 ColumnConstraint::References(fk_ref) => {
9914 self.write_space();
9915 if fk_ref.has_foreign_key_keywords {
9916 self.write_keyword("FOREIGN KEY");
9917 self.write_space();
9918 }
9919 self.write_keyword("REFERENCES");
9920 self.write_space();
9921 self.generate_table(&fk_ref.table)?;
9922 if !fk_ref.columns.is_empty() {
9923 self.write(" (");
9924 for (i, c) in fk_ref.columns.iter().enumerate() {
9925 if i > 0 {
9926 self.write(", ");
9927 }
9928 self.generate_identifier(c)?;
9929 }
9930 self.write(")");
9931 }
9932 self.generate_referential_actions(fk_ref)?;
9933 }
9934 ColumnConstraint::Check(expr) => {
9935 self.write_space();
9936 self.write_keyword("CHECK");
9937 self.write(" (");
9938 self.generate_expression(expr)?;
9939 self.write(")");
9940 }
9941 ColumnConstraint::GeneratedAsIdentity(gen) => {
9942 self.write_space();
9943 if matches!(
9945 self.config.dialect,
9946 Some(crate::dialects::DialectType::Redshift)
9947 ) {
9948 self.write_keyword("IDENTITY");
9949 self.write("(");
9950 if let Some(ref start) = gen.start {
9951 self.generate_expression(start)?;
9952 } else {
9953 self.write("0");
9954 }
9955 self.write(", ");
9956 if let Some(ref incr) = gen.increment {
9957 self.generate_expression(incr)?;
9958 } else {
9959 self.write("1");
9960 }
9961 self.write(")");
9962 } else {
9963 self.write_keyword("GENERATED");
9964 if gen.always {
9965 self.write_space();
9966 self.write_keyword("ALWAYS");
9967 } else {
9968 self.write_space();
9969 self.write_keyword("BY DEFAULT");
9970 if gen.on_null {
9971 self.write_space();
9972 self.write_keyword("ON NULL");
9973 }
9974 }
9975 self.write_space();
9976 self.write_keyword("AS IDENTITY");
9977
9978 let has_options = gen.start.is_some()
9979 || gen.increment.is_some()
9980 || gen.minvalue.is_some()
9981 || gen.maxvalue.is_some()
9982 || gen.cycle.is_some();
9983 if has_options {
9984 self.write(" (");
9985 let mut first = true;
9986 if let Some(ref start) = gen.start {
9987 if !first {
9988 self.write(" ");
9989 }
9990 first = false;
9991 self.write_keyword("START WITH");
9992 self.write_space();
9993 self.generate_expression(start)?;
9994 }
9995 if let Some(ref incr) = gen.increment {
9996 if !first {
9997 self.write(" ");
9998 }
9999 first = false;
10000 self.write_keyword("INCREMENT BY");
10001 self.write_space();
10002 self.generate_expression(incr)?;
10003 }
10004 if let Some(ref minv) = gen.minvalue {
10005 if !first {
10006 self.write(" ");
10007 }
10008 first = false;
10009 self.write_keyword("MINVALUE");
10010 self.write_space();
10011 self.generate_expression(minv)?;
10012 }
10013 if let Some(ref maxv) = gen.maxvalue {
10014 if !first {
10015 self.write(" ");
10016 }
10017 first = false;
10018 self.write_keyword("MAXVALUE");
10019 self.write_space();
10020 self.generate_expression(maxv)?;
10021 }
10022 if let Some(cycle) = gen.cycle {
10023 if !first {
10024 self.write(" ");
10025 }
10026 if cycle {
10027 self.write_keyword("CYCLE");
10028 } else {
10029 self.write_keyword("NO CYCLE");
10030 }
10031 }
10032 self.write(")");
10033 }
10034 }
10035 }
10036 ColumnConstraint::Collate(collation) => {
10037 self.write_space();
10038 self.write_keyword("COLLATE");
10039 self.write_space();
10040 self.generate_identifier(collation)?;
10041 }
10042 ColumnConstraint::Comment(comment) => {
10043 self.write_space();
10044 self.write_keyword("COMMENT");
10045 self.write_space();
10046 self.generate_string_literal(comment)?;
10047 }
10048 ColumnConstraint::Path(path_expr) => {
10049 self.write_space();
10050 self.write_keyword("PATH");
10051 self.write_space();
10052 self.generate_expression(path_expr)?;
10053 }
10054 _ => {} }
10056 }
10057
10058 if let Some(ref encoding) = col.encoding {
10060 self.write_space();
10061 self.write_keyword("ENCODE");
10062 self.write_space();
10063 self.write(encoding);
10064 }
10065 }
10066
10067 if let Some(ref codec) = col.codec {
10069 self.write_space();
10070 self.write_keyword("CODEC");
10071 self.write("(");
10072 self.write(codec);
10073 self.write(")");
10074 }
10075
10076 if let Some(visible) = col.visible {
10077 self.write_space();
10078 if visible {
10079 self.write_keyword("VISIBLE");
10080 } else {
10081 self.write_keyword("INVISIBLE");
10082 }
10083 }
10084
10085 if let Some(ref ephemeral) = col.ephemeral {
10087 self.write_space();
10088 self.write_keyword("EPHEMERAL");
10089 if let Some(ref expr) = ephemeral {
10090 self.write_space();
10091 self.generate_expression(expr)?;
10092 }
10093 }
10094
10095 if let Some(ref mat_expr) = col.materialized_expr {
10097 self.write_space();
10098 self.write_keyword("MATERIALIZED");
10099 self.write_space();
10100 self.generate_expression(mat_expr)?;
10101 }
10102
10103 if let Some(ref alias_expr) = col.alias_expr {
10105 self.write_space();
10106 self.write_keyword("ALIAS");
10107 self.write_space();
10108 self.generate_expression(alias_expr)?;
10109 }
10110
10111 if let Some(ref ttl_expr) = col.ttl_expr {
10113 self.write_space();
10114 self.write_keyword("TTL");
10115 self.write_space();
10116 self.generate_expression(ttl_expr)?;
10117 }
10118
10119 if col.not_for_replication
10121 && matches!(
10122 self.config.dialect,
10123 Some(crate::dialects::DialectType::TSQL)
10124 | Some(crate::dialects::DialectType::Fabric)
10125 )
10126 {
10127 self.write_space();
10128 self.write_keyword("NOT FOR REPLICATION");
10129 }
10130
10131 if !col.options.is_empty() {
10133 self.write_space();
10134 self.generate_options_clause(&col.options)?;
10135 }
10136
10137 if !col.primary_key
10140 && self
10141 .sqlite_inline_pk_columns
10142 .contains(&col.name.name.to_ascii_lowercase())
10143 {
10144 self.write_space();
10145 self.write_keyword("PRIMARY KEY");
10146 if matches!(self.config.dialect, Some(DialectType::SQLite)) && col.auto_increment {
10147 self.write_space();
10148 self.generate_auto_increment_keyword(col)?;
10149 }
10150 }
10151
10152 if serial_expansion.is_some() {
10155 if matches!(self.config.dialect, Some(DialectType::PostgreSQL)) {
10156 self.write_space();
10157 self.write_keyword("GENERATED BY DEFAULT AS IDENTITY NOT NULL");
10158 } else if matches!(self.config.dialect, Some(DialectType::Materialize)) {
10159 self.write_space();
10160 self.write_keyword("NOT NULL");
10161 }
10162 }
10163
10164 Ok(())
10165 }
10166
10167 fn generate_table_constraint(&mut self, constraint: &TableConstraint) -> Result<()> {
10168 match constraint {
10169 TableConstraint::PrimaryKey {
10170 name,
10171 columns,
10172 timeseries_columns,
10173 include_columns,
10174 modifiers,
10175 has_constraint_keyword,
10176 } => {
10177 if let Some(ref n) = name {
10178 if *has_constraint_keyword {
10179 self.write_keyword("CONSTRAINT");
10180 self.write_space();
10181 self.generate_identifier(n)?;
10182 self.write_space();
10183 }
10184 }
10185 self.write_keyword("PRIMARY KEY");
10186 if let Some(ref clustered) = modifiers.clustered {
10188 self.write_space();
10189 self.write_keyword(clustered);
10190 }
10191 if let Some(ref n) = name {
10193 if !*has_constraint_keyword {
10194 self.write_space();
10195 self.generate_identifier(n)?;
10196 }
10197 }
10198 self.write(" (");
10199 for (i, col) in columns.iter().enumerate() {
10200 if i > 0 {
10201 self.write(", ");
10202 }
10203 self.generate_identifier(col)?;
10204 if matches!(self.config.dialect, Some(DialectType::Databricks))
10205 && timeseries_columns.iter().any(|candidate| candidate == col)
10206 {
10207 self.write_space();
10208 self.write_keyword("TIMESERIES");
10209 }
10210 }
10211 self.write(")");
10212 if !include_columns.is_empty() {
10213 self.write_space();
10214 self.write_keyword("INCLUDE");
10215 self.write(" (");
10216 for (i, col) in include_columns.iter().enumerate() {
10217 if i > 0 {
10218 self.write(", ");
10219 }
10220 self.generate_identifier(col)?;
10221 }
10222 self.write(")");
10223 }
10224 self.generate_constraint_modifiers(modifiers);
10225 }
10226 TableConstraint::Unique {
10227 name,
10228 columns,
10229 columns_parenthesized,
10230 modifiers,
10231 has_constraint_keyword,
10232 nulls_not_distinct,
10233 } => {
10234 if let Some(ref n) = name {
10235 if *has_constraint_keyword {
10236 self.write_keyword("CONSTRAINT");
10237 self.write_space();
10238 self.generate_identifier(n)?;
10239 self.write_space();
10240 }
10241 }
10242 self.write_keyword("UNIQUE");
10243 if let Some(ref clustered) = modifiers.clustered {
10245 self.write_space();
10246 self.write_keyword(clustered);
10247 }
10248 if *nulls_not_distinct {
10250 self.write(" NULLS NOT DISTINCT");
10251 }
10252 if let Some(ref n) = name {
10254 if !*has_constraint_keyword {
10255 self.write_space();
10256 self.generate_identifier(n)?;
10257 }
10258 }
10259 if *columns_parenthesized {
10260 self.write(" (");
10261 for (i, col) in columns.iter().enumerate() {
10262 if i > 0 {
10263 self.write(", ");
10264 }
10265 self.generate_identifier(col)?;
10266 }
10267 self.write(")");
10268 } else {
10269 for col in columns.iter() {
10271 self.write_space();
10272 self.generate_identifier(col)?;
10273 }
10274 }
10275 self.generate_constraint_modifiers(modifiers);
10276 }
10277 TableConstraint::ForeignKey {
10278 name,
10279 columns,
10280 references,
10281 on_delete,
10282 on_update,
10283 modifiers,
10284 } => {
10285 if let Some(ref n) = name {
10286 self.write_keyword("CONSTRAINT");
10287 self.write_space();
10288 self.generate_identifier(n)?;
10289 self.write_space();
10290 }
10291 self.write_keyword("FOREIGN KEY");
10292 self.write(" (");
10293 for (i, col) in columns.iter().enumerate() {
10294 if i > 0 {
10295 self.write(", ");
10296 }
10297 self.generate_identifier(col)?;
10298 }
10299 self.write(")");
10300 if let Some(ref refs) = references {
10301 self.write(" ");
10302 self.write_keyword("REFERENCES");
10303 self.write_space();
10304 self.generate_table(&refs.table)?;
10305 if !refs.columns.is_empty() {
10306 if self.config.pretty {
10307 self.write(" (");
10308 self.write_newline();
10309 self.indent_level += 1;
10310 for (i, col) in refs.columns.iter().enumerate() {
10311 if i > 0 {
10312 self.write(",");
10313 self.write_newline();
10314 }
10315 self.write_indent();
10316 self.generate_identifier(col)?;
10317 }
10318 self.indent_level -= 1;
10319 self.write_newline();
10320 self.write_indent();
10321 self.write(")");
10322 } else {
10323 self.write(" (");
10324 for (i, col) in refs.columns.iter().enumerate() {
10325 if i > 0 {
10326 self.write(", ");
10327 }
10328 self.generate_identifier(col)?;
10329 }
10330 self.write(")");
10331 }
10332 }
10333 self.generate_referential_actions(refs)?;
10334 } else {
10335 if let Some(ref action) = on_delete {
10337 self.write_space();
10338 self.write_keyword("ON DELETE");
10339 self.write_space();
10340 self.generate_referential_action(action);
10341 }
10342 if let Some(ref action) = on_update {
10343 self.write_space();
10344 self.write_keyword("ON UPDATE");
10345 self.write_space();
10346 self.generate_referential_action(action);
10347 }
10348 }
10349 self.generate_constraint_modifiers(modifiers);
10350 }
10351 TableConstraint::Check {
10352 name,
10353 expression,
10354 modifiers,
10355 } => {
10356 if let Some(ref n) = name {
10357 self.write_keyword("CONSTRAINT");
10358 self.write_space();
10359 self.generate_identifier(n)?;
10360 self.write_space();
10361 }
10362 self.write_keyword("CHECK");
10363 self.write(" (");
10364 self.generate_expression(expression)?;
10365 self.write(")");
10366 self.generate_constraint_modifiers(modifiers);
10367 }
10368 TableConstraint::Assume { name, expression } => {
10369 if let Some(ref n) = name {
10370 self.write_keyword("CONSTRAINT");
10371 self.write_space();
10372 self.generate_identifier(n)?;
10373 self.write_space();
10374 }
10375 self.write_keyword("ASSUME");
10376 self.write(" (");
10377 self.generate_expression(expression)?;
10378 self.write(")");
10379 }
10380 TableConstraint::Default {
10381 name,
10382 expression,
10383 column,
10384 } => {
10385 if let Some(ref n) = name {
10386 self.write_keyword("CONSTRAINT");
10387 self.write_space();
10388 self.generate_identifier(n)?;
10389 self.write_space();
10390 }
10391 self.write_keyword("DEFAULT");
10392 self.write_space();
10393 self.generate_expression(expression)?;
10394 self.write_space();
10395 self.write_keyword("FOR");
10396 self.write_space();
10397 self.generate_identifier(column)?;
10398 }
10399 TableConstraint::Index {
10400 name,
10401 columns,
10402 key_parts,
10403 kind,
10404 modifiers,
10405 use_key_keyword,
10406 expression,
10407 index_type,
10408 granularity,
10409 } => {
10410 if expression.is_some() {
10412 self.write_keyword("INDEX");
10413 if let Some(ref n) = name {
10414 self.write_space();
10415 self.generate_identifier(n)?;
10416 }
10417 if let Some(ref expr) = expression {
10418 self.write_space();
10419 self.generate_expression(expr)?;
10420 }
10421 if let Some(ref idx_type) = index_type {
10422 self.write_space();
10423 self.write_keyword("TYPE");
10424 self.write_space();
10425 self.generate_expression(idx_type)?;
10426 }
10427 if let Some(ref gran) = granularity {
10428 self.write_space();
10429 self.write_keyword("GRANULARITY");
10430 self.write_space();
10431 self.generate_expression(gran)?;
10432 }
10433 } else {
10434 use crate::dialects::DialectType;
10438 let index_keyword = if *use_key_keyword
10439 && !matches!(self.config.dialect, Some(DialectType::MySQL))
10440 {
10441 "KEY"
10442 } else {
10443 "INDEX"
10444 };
10445
10446 if let Some(ref k) = kind {
10448 self.write_keyword(k);
10449 if k != "UNIQUE" {
10451 self.write_space();
10452 self.write_keyword(index_keyword);
10453 }
10454 } else {
10455 self.write_keyword(index_keyword);
10456 }
10457
10458 if modifiers.using_before_columns && name.is_none() {
10460 if let Some(ref using) = modifiers.using {
10461 self.write_space();
10462 self.write_keyword("USING");
10463 self.write_space();
10464 self.write_keyword(using);
10465 }
10466 }
10467
10468 if let Some(ref n) = name {
10470 self.write_space();
10471 self.generate_identifier(n)?;
10472 }
10473
10474 if modifiers.using_before_columns && name.is_some() {
10476 if let Some(ref using) = modifiers.using {
10477 self.write_space();
10478 self.write_keyword("USING");
10479 self.write_space();
10480 self.write_keyword(using);
10481 }
10482 }
10483
10484 self.write(" (");
10486 if key_parts.is_empty() {
10487 for (i, col) in columns.iter().enumerate() {
10488 if i > 0 {
10489 self.write(", ");
10490 }
10491 self.generate_identifier(col)?;
10492 }
10493 } else {
10494 self.generate_index_key_parts(key_parts)?;
10495 }
10496 self.write(")");
10497
10498 if !modifiers.using_before_columns {
10500 if let Some(ref using) = modifiers.using {
10501 self.write_space();
10502 self.write_keyword("USING");
10503 self.write_space();
10504 self.write_keyword(using);
10505 }
10506 }
10507
10508 self.generate_constraint_modifiers_without_using(modifiers);
10510 }
10511 }
10512 TableConstraint::Projection { name, expression } => {
10513 self.write_keyword("PROJECTION");
10515 self.write_space();
10516 self.generate_identifier(name)?;
10517 if matches!(self.config.dialect, Some(DialectType::ClickHouse)) {
10518 if let Expression::Raw(raw) = expression {
10519 if raw
10520 .sql
10521 .trim_start()
10522 .to_ascii_uppercase()
10523 .starts_with("INDEX ")
10524 {
10525 self.write_space();
10526 self.write(raw.sql.trim());
10527 return Ok(());
10528 }
10529 }
10530 }
10531 self.write(" (");
10532 self.generate_expression(expression)?;
10533 self.write(")");
10534 }
10535 TableConstraint::Like { source, options } => {
10536 self.write_keyword("LIKE");
10537 self.write_space();
10538 self.generate_table(source)?;
10539 for (action, prop) in options {
10540 self.write_space();
10541 match action {
10542 LikeOptionAction::Including => self.write_keyword("INCLUDING"),
10543 LikeOptionAction::Excluding => self.write_keyword("EXCLUDING"),
10544 }
10545 self.write_space();
10546 self.write_keyword(prop);
10547 }
10548 }
10549 TableConstraint::PeriodForSystemTime { start_col, end_col } => {
10550 self.write_keyword("PERIOD FOR SYSTEM_TIME");
10551 self.write(" (");
10552 self.generate_identifier(start_col)?;
10553 self.write(", ");
10554 self.generate_identifier(end_col)?;
10555 self.write(")");
10556 }
10557 TableConstraint::Exclude {
10558 name,
10559 using,
10560 elements,
10561 include_columns,
10562 where_clause,
10563 with_params,
10564 using_index_tablespace,
10565 modifiers: _,
10566 } => {
10567 if let Some(ref n) = name {
10568 self.write_keyword("CONSTRAINT");
10569 self.write_space();
10570 self.generate_identifier(n)?;
10571 self.write_space();
10572 }
10573 self.write_keyword("EXCLUDE");
10574 if let Some(ref method) = using {
10575 self.write_space();
10576 self.write_keyword("USING");
10577 self.write_space();
10578 self.write(method);
10579 self.write("(");
10580 } else {
10581 self.write(" (");
10582 }
10583 for (i, elem) in elements.iter().enumerate() {
10584 if i > 0 {
10585 self.write(", ");
10586 }
10587 self.write(&elem.expression);
10588 self.write_space();
10589 self.write_keyword("WITH");
10590 self.write_space();
10591 self.write(&elem.operator);
10592 }
10593 self.write(")");
10594 if !include_columns.is_empty() {
10595 self.write_space();
10596 self.write_keyword("INCLUDE");
10597 self.write(" (");
10598 for (i, col) in include_columns.iter().enumerate() {
10599 if i > 0 {
10600 self.write(", ");
10601 }
10602 self.generate_identifier(col)?;
10603 }
10604 self.write(")");
10605 }
10606 if !with_params.is_empty() {
10607 self.write_space();
10608 self.write_keyword("WITH");
10609 self.write(" (");
10610 for (i, (key, val)) in with_params.iter().enumerate() {
10611 if i > 0 {
10612 self.write(", ");
10613 }
10614 self.write(key);
10615 self.write("=");
10616 self.write(val);
10617 }
10618 self.write(")");
10619 }
10620 if let Some(ref tablespace) = using_index_tablespace {
10621 self.write_space();
10622 self.write_keyword("USING INDEX TABLESPACE");
10623 self.write_space();
10624 self.write(tablespace);
10625 }
10626 if let Some(ref where_expr) = where_clause {
10627 self.write_space();
10628 self.write_keyword("WHERE");
10629 self.write(" (");
10630 self.generate_expression(where_expr)?;
10631 self.write(")");
10632 }
10633 }
10634 TableConstraint::Tags(tags) => {
10635 self.write_keyword("TAG");
10636 self.write(" (");
10637 for (i, expr) in tags.expressions.iter().enumerate() {
10638 if i > 0 {
10639 self.write(", ");
10640 }
10641 self.generate_expression(expr)?;
10642 }
10643 self.write(")");
10644 }
10645 TableConstraint::InitiallyDeferred { deferred } => {
10646 self.write_keyword("INITIALLY");
10647 self.write_space();
10648 if *deferred {
10649 self.write_keyword("DEFERRED");
10650 } else {
10651 self.write_keyword("IMMEDIATE");
10652 }
10653 }
10654 }
10655 Ok(())
10656 }
10657
10658 fn generate_constraint_modifiers(&mut self, modifiers: &ConstraintModifiers) {
10659 if let Some(using) = &modifiers.using {
10661 self.write_space();
10662 self.write_keyword("USING");
10663 self.write_space();
10664 self.write_keyword(using);
10665 }
10666 if let Some(enforced) = modifiers.enforced {
10668 self.write_space();
10669 if enforced {
10670 self.write_keyword("ENFORCED");
10671 } else {
10672 self.write_keyword("NOT ENFORCED");
10673 }
10674 }
10675 if let Some(deferrable) = modifiers.deferrable {
10677 self.write_space();
10678 if deferrable {
10679 self.write_keyword("DEFERRABLE");
10680 } else {
10681 self.write_keyword("NOT DEFERRABLE");
10682 }
10683 }
10684 if let Some(initially_deferred) = modifiers.initially_deferred {
10686 self.write_space();
10687 if initially_deferred {
10688 self.write_keyword("INITIALLY DEFERRED");
10689 } else {
10690 self.write_keyword("INITIALLY IMMEDIATE");
10691 }
10692 }
10693 if modifiers.norely {
10695 self.write_space();
10696 self.write_keyword("NORELY");
10697 }
10698 if modifiers.rely {
10700 self.write_space();
10701 self.write_keyword("RELY");
10702 }
10703 if modifiers.not_valid {
10705 self.write_space();
10706 self.write_keyword("NOT VALID");
10707 }
10708 if let Some(on_conflict) = &modifiers.on_conflict {
10710 self.write_space();
10711 self.write_keyword("ON CONFLICT");
10712 self.write_space();
10713 self.write_keyword(on_conflict);
10714 }
10715 if !modifiers.with_options.is_empty() {
10717 self.write_space();
10718 self.write_keyword("WITH");
10719 self.write(" (");
10720 for (i, (key, value)) in modifiers.with_options.iter().enumerate() {
10721 if i > 0 {
10722 self.write(", ");
10723 }
10724 self.write(key);
10725 self.write("=");
10726 self.write(value);
10727 }
10728 self.write(")");
10729 }
10730 if let Some(ref fg) = modifiers.on_filegroup {
10732 self.write_space();
10733 self.write_keyword("ON");
10734 self.write_space();
10735 let _ = self.generate_identifier(fg);
10736 }
10737 }
10738
10739 fn generate_constraint_modifiers_without_using(&mut self, modifiers: &ConstraintModifiers) {
10741 if let Some(enforced) = modifiers.enforced {
10743 self.write_space();
10744 if enforced {
10745 self.write_keyword("ENFORCED");
10746 } else {
10747 self.write_keyword("NOT ENFORCED");
10748 }
10749 }
10750 if let Some(deferrable) = modifiers.deferrable {
10752 self.write_space();
10753 if deferrable {
10754 self.write_keyword("DEFERRABLE");
10755 } else {
10756 self.write_keyword("NOT DEFERRABLE");
10757 }
10758 }
10759 if let Some(initially_deferred) = modifiers.initially_deferred {
10761 self.write_space();
10762 if initially_deferred {
10763 self.write_keyword("INITIALLY DEFERRED");
10764 } else {
10765 self.write_keyword("INITIALLY IMMEDIATE");
10766 }
10767 }
10768 if modifiers.norely {
10770 self.write_space();
10771 self.write_keyword("NORELY");
10772 }
10773 if modifiers.rely {
10775 self.write_space();
10776 self.write_keyword("RELY");
10777 }
10778 if modifiers.not_valid {
10780 self.write_space();
10781 self.write_keyword("NOT VALID");
10782 }
10783 if let Some(on_conflict) = &modifiers.on_conflict {
10785 self.write_space();
10786 self.write_keyword("ON CONFLICT");
10787 self.write_space();
10788 self.write_keyword(on_conflict);
10789 }
10790 self.generate_index_specific_modifiers(modifiers);
10792 }
10793
10794 fn generate_index_specific_modifiers(&mut self, modifiers: &ConstraintModifiers) {
10796 if let Some(ref comment) = modifiers.comment {
10797 self.write_space();
10798 self.write_keyword("COMMENT");
10799 self.write(" '");
10800 self.write(comment);
10801 self.write("'");
10802 }
10803 if let Some(visible) = modifiers.visible {
10804 self.write_space();
10805 if visible {
10806 self.write_keyword("VISIBLE");
10807 } else {
10808 self.write_keyword("INVISIBLE");
10809 }
10810 }
10811 if let Some(ref attr) = modifiers.engine_attribute {
10812 self.write_space();
10813 self.write_keyword("ENGINE_ATTRIBUTE");
10814 self.write(" = '");
10815 self.write(attr);
10816 self.write("'");
10817 }
10818 if let Some(ref parser) = modifiers.with_parser {
10819 self.write_space();
10820 self.write_keyword("WITH PARSER");
10821 self.write_space();
10822 self.write(parser);
10823 }
10824 }
10825
10826 fn generate_referential_actions(&mut self, fk_ref: &ForeignKeyRef) -> Result<()> {
10827 if !fk_ref.match_after_actions {
10829 if let Some(ref match_type) = fk_ref.match_type {
10830 self.write_space();
10831 self.write_keyword("MATCH");
10832 self.write_space();
10833 match match_type {
10834 MatchType::Full => self.write_keyword("FULL"),
10835 MatchType::Partial => self.write_keyword("PARTIAL"),
10836 MatchType::Simple => self.write_keyword("SIMPLE"),
10837 }
10838 }
10839 }
10840
10841 if fk_ref.on_update_first {
10843 if let Some(ref action) = fk_ref.on_update {
10844 self.write_space();
10845 self.write_keyword("ON UPDATE");
10846 self.write_space();
10847 self.generate_referential_action(action);
10848 }
10849 if let Some(ref action) = fk_ref.on_delete {
10850 self.write_space();
10851 self.write_keyword("ON DELETE");
10852 self.write_space();
10853 self.generate_referential_action(action);
10854 }
10855 } else {
10856 if let Some(ref action) = fk_ref.on_delete {
10857 self.write_space();
10858 self.write_keyword("ON DELETE");
10859 self.write_space();
10860 self.generate_referential_action(action);
10861 }
10862 if let Some(ref action) = fk_ref.on_update {
10863 self.write_space();
10864 self.write_keyword("ON UPDATE");
10865 self.write_space();
10866 self.generate_referential_action(action);
10867 }
10868 }
10869
10870 if fk_ref.match_after_actions {
10872 if let Some(ref match_type) = fk_ref.match_type {
10873 self.write_space();
10874 self.write_keyword("MATCH");
10875 self.write_space();
10876 match match_type {
10877 MatchType::Full => self.write_keyword("FULL"),
10878 MatchType::Partial => self.write_keyword("PARTIAL"),
10879 MatchType::Simple => self.write_keyword("SIMPLE"),
10880 }
10881 }
10882 }
10883
10884 if let Some(deferrable) = fk_ref.deferrable {
10886 self.write_space();
10887 if deferrable {
10888 self.write_keyword("DEFERRABLE");
10889 } else {
10890 self.write_keyword("NOT DEFERRABLE");
10891 }
10892 }
10893
10894 Ok(())
10895 }
10896
10897 fn generate_referential_action(&mut self, action: &ReferentialAction) {
10898 match action {
10899 ReferentialAction::Cascade => self.write_keyword("CASCADE"),
10900 ReferentialAction::SetNull => self.write_keyword("SET NULL"),
10901 ReferentialAction::SetDefault => self.write_keyword("SET DEFAULT"),
10902 ReferentialAction::Restrict => self.write_keyword("RESTRICT"),
10903 ReferentialAction::NoAction => self.write_keyword("NO ACTION"),
10904 }
10905 }
10906
10907 fn generate_drop_table(&mut self, dt: &DropTable) -> Result<()> {
10908 if let Some(ref object_id_args) = dt.object_id_args {
10910 if matches!(
10911 self.config.dialect,
10912 Some(crate::dialects::DialectType::TSQL)
10913 | Some(crate::dialects::DialectType::Fabric)
10914 ) {
10915 self.write_keyword("IF NOT OBJECT_ID");
10916 self.write("(");
10917 self.write(object_id_args);
10918 self.write(")");
10919 self.write_space();
10920 self.write_keyword("IS NULL BEGIN DROP TABLE");
10921 self.write_space();
10922 for (i, table) in dt.names.iter().enumerate() {
10923 if i > 0 {
10924 self.write(", ");
10925 }
10926 self.generate_table(table)?;
10927 }
10928 self.write("; ");
10929 self.write_keyword("END");
10930 return Ok(());
10931 }
10932 }
10933
10934 let saved_athena_hive_context = self.athena_hive_context;
10936 if matches!(
10937 self.config.dialect,
10938 Some(crate::dialects::DialectType::Athena)
10939 ) {
10940 self.athena_hive_context = true;
10941 }
10942
10943 for comment in &dt.leading_comments {
10945 self.write_formatted_comment(comment);
10946 self.write_space();
10947 }
10948 if dt.iceberg {
10949 self.write_keyword("DROP ICEBERG TABLE");
10950 } else {
10951 self.write_keyword("DROP TABLE");
10952 }
10953
10954 if dt.if_exists {
10955 self.write_space();
10956 self.write_keyword("IF EXISTS");
10957 }
10958
10959 self.write_space();
10960 for (i, table) in dt.names.iter().enumerate() {
10961 if i > 0 {
10962 self.write(", ");
10963 }
10964 self.generate_table(table)?;
10965 }
10966
10967 if dt.cascade_constraints {
10968 self.write_space();
10969 self.write_keyword("CASCADE CONSTRAINTS");
10970 } else if dt.cascade {
10971 self.write_space();
10972 self.write_keyword("CASCADE");
10973 }
10974
10975 if dt.restrict {
10976 self.write_space();
10977 self.write_keyword("RESTRICT");
10978 }
10979
10980 if dt.purge {
10981 self.write_space();
10982 self.write_keyword("PURGE");
10983 }
10984
10985 if dt.sync {
10986 self.write_space();
10987 self.write_keyword("SYNC");
10988 }
10989
10990 self.athena_hive_context = saved_athena_hive_context;
10992
10993 Ok(())
10994 }
10995
10996 fn generate_undrop(&mut self, u: &Undrop) -> Result<()> {
10997 self.write_keyword("UNDROP");
10998 self.write_space();
10999 self.write_keyword(&u.kind);
11000 if u.if_exists {
11001 self.write_space();
11002 self.write_keyword("IF EXISTS");
11003 }
11004 self.write_space();
11005 self.generate_table(&u.name)?;
11006 if let Some(rename_to) = &u.rename_to {
11007 self.write_space();
11008 self.write_keyword("RENAME TO");
11009 self.write_space();
11010 self.generate_table(rename_to)?;
11011 }
11012 Ok(())
11013 }
11014
11015 fn generate_split_table(&mut self, split: &SplitTable) -> Result<()> {
11016 if !matches!(self.config.dialect, Some(DialectType::TiDB)) {
11017 return self
11018 .write_unsupported_comment("SPLIT TABLE is only supported by the TiDB dialect");
11019 }
11020
11021 match &split.partition_scope {
11022 SplitTablePartitionScope::Table => self.write_keyword("SPLIT TABLE"),
11023 SplitTablePartitionScope::AllPartitions
11024 | SplitTablePartitionScope::Partitions { .. } => {
11025 self.write_keyword("SPLIT PARTITION TABLE")
11026 }
11027 }
11028 self.write_space();
11029 self.generate_table(&split.table)?;
11030 if let SplitTablePartitionScope::Partitions { names } = &split.partition_scope {
11031 self.write_space();
11032 self.write_keyword("PARTITION");
11033 self.write(" (");
11034 for (index, name) in names.iter().enumerate() {
11035 if index > 0 {
11036 self.write(", ");
11037 }
11038 self.generate_identifier(name)?;
11039 }
11040 self.write(")");
11041 }
11042 if let Some(index) = &split.index {
11043 self.write_space();
11044 self.write_keyword("INDEX");
11045 self.write_space();
11046 self.generate_identifier(index)?;
11047 }
11048 match &split.mode {
11049 SplitTableMode::Between {
11050 lower,
11051 upper,
11052 regions,
11053 } => {
11054 self.write_space();
11055 self.write_keyword("BETWEEN");
11056 self.write_space();
11057 self.generate_tidb_split_values(lower)?;
11058 self.write_space();
11059 self.write_keyword("AND");
11060 self.write_space();
11061 self.generate_tidb_split_values(upper)?;
11062 self.write_space();
11063 self.write_keyword("REGIONS");
11064 self.write_space();
11065 self.write(®ions.to_string());
11066 }
11067 SplitTableMode::By { points } => {
11068 self.write_space();
11069 self.write_keyword("BY");
11070 self.write_space();
11071 for (index, point) in points.iter().enumerate() {
11072 if index > 0 {
11073 self.write(", ");
11074 }
11075 self.generate_tidb_split_values(point)?;
11076 }
11077 }
11078 }
11079 Ok(())
11080 }
11081
11082 fn generate_tidb_split_values(&mut self, values: &[Expression]) -> Result<()> {
11083 self.write("(");
11084 for (index, value) in values.iter().enumerate() {
11085 if index > 0 {
11086 self.write(", ");
11087 }
11088 self.generate_expression(value)?;
11089 }
11090 self.write(")");
11091 Ok(())
11092 }
11093
11094 fn generate_flashback_table(&mut self, flashback: &FlashbackTable) -> Result<()> {
11095 if !matches!(self.config.dialect, Some(DialectType::TiDB)) {
11096 return self.write_unsupported_comment(
11097 "FLASHBACK TABLE is only supported by the TiDB dialect",
11098 );
11099 }
11100 self.write_keyword("FLASHBACK TABLE");
11101 self.write_space();
11102 self.generate_table(&flashback.table)?;
11103 if let Some(rename_to) = &flashback.rename_to {
11104 self.write_space();
11105 self.write_keyword("TO");
11106 self.write_space();
11107 self.generate_identifier(rename_to)?;
11108 }
11109 Ok(())
11110 }
11111
11112 fn generate_alter_table(&mut self, at: &AlterTable) -> Result<()> {
11113 let saved_athena_hive_context = self.athena_hive_context;
11115 if matches!(
11116 self.config.dialect,
11117 Some(crate::dialects::DialectType::Athena)
11118 ) {
11119 self.athena_hive_context = true;
11120 }
11121
11122 self.write_keyword("ALTER");
11123 if let Some(ref modifier) = at.table_modifier {
11125 if !matches!(
11126 self.config.dialect,
11127 Some(crate::dialects::DialectType::DuckDB)
11128 ) {
11129 self.write_space();
11130 self.write_keyword(modifier);
11131 }
11132 }
11133 self.write(" ");
11134 self.write_keyword("TABLE");
11135 if at.if_exists {
11136 self.write_space();
11137 self.write_keyword("IF EXISTS");
11138 }
11139 self.write_space();
11140 self.generate_table(&at.name)?;
11141
11142 if let Some(ref on_cluster) = at.on_cluster {
11144 self.write_space();
11145 self.generate_on_cluster(on_cluster)?;
11146 }
11147
11148 if let Some(ref partition) = at.partition {
11150 self.write_space();
11151 self.write_keyword("PARTITION");
11152 self.write("(");
11153 for (i, (key, value)) in partition.iter().enumerate() {
11154 if i > 0 {
11155 self.write(", ");
11156 }
11157 self.generate_identifier(key)?;
11158 self.write(" = ");
11159 self.generate_expression(value)?;
11160 }
11161 self.write(")");
11162 }
11163
11164 if let Some(ref with_check) = at.with_check {
11166 self.write_space();
11167 self.write_keyword(with_check);
11168 }
11169
11170 if self.config.pretty {
11171 self.write_newline();
11173 self.indent_level += 1;
11174 for (i, action) in at.actions.iter().enumerate() {
11175 let is_continuation = i > 0
11177 && matches!(
11178 (&at.actions[i - 1], action),
11179 (
11180 AlterTableAction::AddColumn { .. },
11181 AlterTableAction::AddColumn { .. }
11182 ) | (
11183 AlterTableAction::AddConstraint(_),
11184 AlterTableAction::AddConstraint(_)
11185 )
11186 );
11187 if i > 0 {
11188 self.write(",");
11189 self.write_newline();
11190 }
11191 self.write_indent();
11192 self.generate_alter_action_with_continuation(action, is_continuation)?;
11193 }
11194 self.indent_level -= 1;
11195 } else {
11196 for (i, action) in at.actions.iter().enumerate() {
11197 let is_continuation = i > 0
11199 && matches!(
11200 (&at.actions[i - 1], action),
11201 (
11202 AlterTableAction::AddColumn { .. },
11203 AlterTableAction::AddColumn { .. }
11204 ) | (
11205 AlterTableAction::AddConstraint(_),
11206 AlterTableAction::AddConstraint(_)
11207 )
11208 );
11209 if i > 0 {
11210 self.write(",");
11211 }
11212 self.write_space();
11213 self.generate_alter_action_with_continuation(action, is_continuation)?;
11214 }
11215 }
11216
11217 if let Some(ref algorithm) = at.algorithm {
11219 self.write(", ");
11220 self.write_keyword("ALGORITHM");
11221 self.write("=");
11222 self.write_keyword(algorithm);
11223 }
11224 if let Some(ref lock) = at.lock {
11225 self.write(", ");
11226 self.write_keyword("LOCK");
11227 self.write("=");
11228 self.write_keyword(lock);
11229 }
11230
11231 self.athena_hive_context = saved_athena_hive_context;
11233
11234 Ok(())
11235 }
11236
11237 fn generate_alter_action_with_continuation(
11238 &mut self,
11239 action: &AlterTableAction,
11240 is_continuation: bool,
11241 ) -> Result<()> {
11242 match action {
11243 AlterTableAction::AddColumn {
11244 column,
11245 if_not_exists,
11246 position,
11247 } => {
11248 use crate::dialects::DialectType;
11249 let is_snowflake = matches!(self.config.dialect, Some(DialectType::Snowflake));
11253 let is_tsql_like = matches!(
11254 self.config.dialect,
11255 Some(DialectType::TSQL) | Some(DialectType::Fabric)
11256 );
11257 let is_athena = matches!(self.config.dialect, Some(DialectType::Athena));
11259
11260 if is_continuation && (is_snowflake || is_tsql_like) {
11261 } else if is_snowflake {
11263 self.write_keyword("ADD");
11264 self.write_space();
11265 } else if is_athena {
11266 self.write_keyword("ADD COLUMNS");
11268 self.write(" (");
11269 } else if self.config.alter_table_include_column_keyword {
11270 self.write_keyword("ADD COLUMN");
11271 self.write_space();
11272 } else {
11273 self.write_keyword("ADD");
11275 self.write_space();
11276 }
11277
11278 if *if_not_exists {
11279 self.write_keyword("IF NOT EXISTS");
11280 self.write_space();
11281 }
11282 self.generate_column_def(column)?;
11283
11284 if is_athena {
11286 self.write(")");
11287 }
11288
11289 if let Some(pos) = position {
11291 self.write_space();
11292 match pos {
11293 ColumnPosition::First => self.write_keyword("FIRST"),
11294 ColumnPosition::After(col_name) => {
11295 self.write_keyword("AFTER");
11296 self.write_space();
11297 self.generate_identifier(col_name)?;
11298 }
11299 }
11300 }
11301 }
11302 AlterTableAction::DropColumn {
11303 name,
11304 if_exists,
11305 cascade,
11306 } => {
11307 self.write_keyword("DROP COLUMN");
11308 if *if_exists {
11309 self.write_space();
11310 self.write_keyword("IF EXISTS");
11311 }
11312 self.write_space();
11313 self.generate_identifier(name)?;
11314 if *cascade {
11315 self.write_space();
11316 self.write_keyword("CASCADE");
11317 }
11318 }
11319 AlterTableAction::DropColumns { names } => {
11320 self.write_keyword("DROP COLUMNS");
11321 self.write(" (");
11322 for (i, name) in names.iter().enumerate() {
11323 if i > 0 {
11324 self.write(", ");
11325 }
11326 self.generate_identifier(name)?;
11327 }
11328 self.write(")");
11329 }
11330 AlterTableAction::RenameColumn {
11331 old_name,
11332 new_name,
11333 if_exists,
11334 } => {
11335 self.write_keyword("RENAME COLUMN");
11336 if *if_exists {
11337 self.write_space();
11338 self.write_keyword("IF EXISTS");
11339 }
11340 self.write_space();
11341 self.generate_identifier(old_name)?;
11342 self.write_space();
11343 self.write_keyword("TO");
11344 self.write_space();
11345 self.generate_identifier(new_name)?;
11346 }
11347 AlterTableAction::AlterColumn {
11348 name,
11349 action,
11350 use_modify_keyword,
11351 } => {
11352 use crate::dialects::DialectType;
11353 let use_modify = *use_modify_keyword
11356 || (matches!(self.config.dialect, Some(DialectType::MySQL))
11357 && matches!(action, AlterColumnAction::SetDataType { .. }));
11358 if use_modify {
11359 self.write_keyword("MODIFY COLUMN");
11360 self.write_space();
11361 self.generate_identifier(name)?;
11362 if let AlterColumnAction::SetDataType {
11364 data_type,
11365 using: _,
11366 collate,
11367 } = action
11368 {
11369 self.write_space();
11370 self.generate_data_type(data_type)?;
11371 if let Some(collate_name) = collate {
11373 self.write_space();
11374 self.write_keyword("COLLATE");
11375 self.write_space();
11376 self.write(&format!("'{}'", collate_name));
11378 }
11379 } else {
11380 self.write_space();
11381 self.generate_alter_column_action(action)?;
11382 }
11383 } else if matches!(self.config.dialect, Some(DialectType::Hive))
11384 && matches!(action, AlterColumnAction::SetDataType { .. })
11385 {
11386 self.write_keyword("CHANGE COLUMN");
11388 self.write_space();
11389 self.generate_identifier(name)?;
11390 self.write_space();
11391 self.generate_identifier(name)?;
11392 if let AlterColumnAction::SetDataType { data_type, .. } = action {
11393 self.write_space();
11394 self.generate_data_type(data_type)?;
11395 }
11396 } else {
11397 self.write_keyword("ALTER COLUMN");
11398 self.write_space();
11399 self.generate_identifier(name)?;
11400 self.write_space();
11401 self.generate_alter_column_action(action)?;
11402 }
11403 }
11404 AlterTableAction::ModifyColumn {
11405 column,
11406 if_exists,
11407 position,
11408 } => {
11409 if !matches!(
11410 self.config.dialect,
11411 Some(DialectType::TiDB) | Some(DialectType::MySQL)
11412 ) {
11413 return self.write_unsupported_comment(
11414 "MODIFY COLUMN is only supported by MySQL-compatible dialects",
11415 );
11416 }
11417 self.write_keyword("MODIFY COLUMN");
11418 self.write_space();
11419 if *if_exists {
11420 self.write_keyword("IF EXISTS");
11421 self.write_space();
11422 }
11423 self.generate_column_def(column)?;
11424 if let Some(position) = position {
11425 self.write_space();
11426 match position {
11427 ColumnPosition::First => self.write_keyword("FIRST"),
11428 ColumnPosition::After(name) => {
11429 self.write_keyword("AFTER");
11430 self.write_space();
11431 self.generate_identifier(name)?;
11432 }
11433 }
11434 }
11435 }
11436 AlterTableAction::RenameTable(new_name) => {
11437 let mysql_like = matches!(
11439 self.config.dialect,
11440 Some(DialectType::MySQL)
11441 | Some(DialectType::Doris)
11442 | Some(DialectType::StarRocks)
11443 | Some(DialectType::SingleStore)
11444 );
11445 if mysql_like {
11446 self.write_keyword("RENAME");
11447 } else {
11448 self.write_keyword("RENAME TO");
11449 }
11450 self.write_space();
11451 let rename_table_with_db = !matches!(
11453 self.config.dialect,
11454 Some(DialectType::Doris)
11455 | Some(DialectType::DuckDB)
11456 | Some(DialectType::BigQuery)
11457 | Some(DialectType::PostgreSQL)
11458 );
11459 if !rename_table_with_db {
11460 let mut stripped = new_name.clone();
11461 stripped.schema = None;
11462 stripped.catalog = None;
11463 self.generate_table(&stripped)?;
11464 } else {
11465 self.generate_table(new_name)?;
11466 }
11467 }
11468 AlterTableAction::AddConstraint(constraint) => {
11469 if !is_continuation {
11472 self.write_keyword("ADD");
11473 self.write_space();
11474 }
11475 self.generate_table_constraint(constraint)?;
11476 }
11477 AlterTableAction::DropConstraint { name, if_exists } => {
11478 self.write_keyword("DROP CONSTRAINT");
11479 if *if_exists {
11480 self.write_space();
11481 self.write_keyword("IF EXISTS");
11482 }
11483 self.write_space();
11484 self.generate_identifier(name)?;
11485 }
11486 AlterTableAction::DropForeignKey { name } => {
11487 self.write_keyword("DROP FOREIGN KEY");
11488 self.write_space();
11489 self.generate_identifier(name)?;
11490 }
11491 AlterTableAction::DropPartition {
11492 partitions,
11493 if_exists,
11494 } => {
11495 self.write_keyword("DROP");
11496 if *if_exists {
11497 self.write_space();
11498 self.write_keyword("IF EXISTS");
11499 }
11500 for (i, partition) in partitions.iter().enumerate() {
11501 if i > 0 {
11502 self.write(",");
11503 }
11504 self.write_space();
11505 self.write_keyword("PARTITION");
11506 if partition.len() == 1 && partition[0].0.name == "__expr__" {
11508 self.write_space();
11510 self.generate_expression(&partition[0].1)?;
11511 } else if partition.len() == 1 && partition[0].0.name == "ALL" {
11512 self.write_space();
11514 self.write_keyword("ALL");
11515 } else if partition.len() == 1 && partition[0].0.name == "ID" {
11516 self.write_space();
11518 self.write_keyword("ID");
11519 self.write_space();
11520 self.generate_expression(&partition[0].1)?;
11521 } else {
11522 self.write("(");
11524 for (j, (key, value)) in partition.iter().enumerate() {
11525 if j > 0 {
11526 self.write(", ");
11527 }
11528 self.generate_identifier(key)?;
11529 self.write(" = ");
11530 self.generate_expression(value)?;
11531 }
11532 self.write(")");
11533 }
11534 }
11535 }
11536 AlterTableAction::Delete { where_clause } => {
11537 self.write_keyword("DELETE");
11538 self.write_space();
11539 self.write_keyword("WHERE");
11540 self.write_space();
11541 self.generate_expression(where_clause)?;
11542 }
11543 AlterTableAction::SwapWith(target) => {
11544 self.write_keyword("SWAP WITH");
11545 self.write_space();
11546 self.generate_table(target)?;
11547 }
11548 AlterTableAction::SetProperty { properties } => {
11549 use crate::dialects::DialectType;
11550 self.write_keyword("SET");
11551 let is_trino_presto = matches!(
11553 self.config.dialect,
11554 Some(DialectType::Trino) | Some(DialectType::Presto)
11555 );
11556 if is_trino_presto {
11557 self.write_space();
11558 self.write_keyword("PROPERTIES");
11559 }
11560 let eq = if is_trino_presto { " = " } else { "=" };
11561 for (i, (key, value)) in properties.iter().enumerate() {
11562 if i > 0 {
11563 self.write(",");
11564 }
11565 self.write_space();
11566 if key.contains(' ') {
11568 self.generate_string_literal(key)?;
11569 } else {
11570 self.write(key);
11571 }
11572 self.write(eq);
11573 self.generate_expression(value)?;
11574 }
11575 }
11576 AlterTableAction::UnsetProperty { properties } => {
11577 self.write_keyword("UNSET");
11578 for (i, name) in properties.iter().enumerate() {
11579 if i > 0 {
11580 self.write(",");
11581 }
11582 self.write_space();
11583 self.write(name);
11584 }
11585 }
11586 AlterTableAction::ClusterBy { expressions } => {
11587 self.write_keyword("CLUSTER BY");
11588 self.write(" (");
11589 for (i, expr) in expressions.iter().enumerate() {
11590 if i > 0 {
11591 self.write(", ");
11592 }
11593 self.generate_expression(expr)?;
11594 }
11595 self.write(")");
11596 }
11597 AlterTableAction::SetTag { expressions } => {
11598 self.write_keyword("SET TAG");
11599 for (i, (key, value)) in expressions.iter().enumerate() {
11600 if i > 0 {
11601 self.write(",");
11602 }
11603 self.write_space();
11604 self.write(key);
11605 self.write(" = ");
11606 self.generate_expression(value)?;
11607 }
11608 }
11609 AlterTableAction::UnsetTag { names } => {
11610 self.write_keyword("UNSET TAG");
11611 for (i, name) in names.iter().enumerate() {
11612 if i > 0 {
11613 self.write(",");
11614 }
11615 self.write_space();
11616 self.write(name);
11617 }
11618 }
11619 AlterTableAction::SetOptions { expressions } => {
11620 self.write_keyword("SET");
11621 self.write(" (");
11622 for (i, expr) in expressions.iter().enumerate() {
11623 if i > 0 {
11624 self.write(", ");
11625 }
11626 self.generate_expression(expr)?;
11627 }
11628 self.write(")");
11629 }
11630 AlterTableAction::AlterIndex { name, visible } => {
11631 self.write_keyword("ALTER INDEX");
11632 self.write_space();
11633 self.generate_identifier(name)?;
11634 self.write_space();
11635 if *visible {
11636 self.write_keyword("VISIBLE");
11637 } else {
11638 self.write_keyword("INVISIBLE");
11639 }
11640 }
11641 AlterTableAction::SetAttribute { attribute } => {
11642 self.write_keyword("SET");
11643 self.write_space();
11644 self.write_keyword(attribute);
11645 }
11646 AlterTableAction::SetStageFileFormat { options } => {
11647 self.write_keyword("SET");
11648 self.write_space();
11649 self.write_keyword("STAGE_FILE_FORMAT");
11650 self.write(" = (");
11651 if let Some(opts) = options {
11652 self.generate_space_separated_properties(opts)?;
11653 }
11654 self.write(")");
11655 }
11656 AlterTableAction::SetStageCopyOptions { options } => {
11657 self.write_keyword("SET");
11658 self.write_space();
11659 self.write_keyword("STAGE_COPY_OPTIONS");
11660 self.write(" = (");
11661 if let Some(opts) = options {
11662 self.generate_space_separated_properties(opts)?;
11663 }
11664 self.write(")");
11665 }
11666 AlterTableAction::AddColumns { columns, cascade } => {
11667 let is_oracle = matches!(self.config.dialect, Some(DialectType::Oracle));
11670 if is_oracle {
11671 self.write_keyword("ADD");
11672 } else {
11673 self.write_keyword("ADD COLUMNS");
11674 }
11675 self.write(" (");
11676 for (i, col) in columns.iter().enumerate() {
11677 if i > 0 {
11678 self.write(", ");
11679 }
11680 self.generate_column_def(col)?;
11681 }
11682 self.write(")");
11683 if *cascade {
11684 self.write_space();
11685 self.write_keyword("CASCADE");
11686 }
11687 }
11688 AlterTableAction::ChangeColumn {
11689 old_name,
11690 new_name,
11691 data_type,
11692 comment,
11693 cascade,
11694 } => {
11695 use crate::dialects::DialectType;
11696 let is_spark = matches!(
11697 self.config.dialect,
11698 Some(DialectType::Spark) | Some(DialectType::Databricks)
11699 );
11700 let is_rename = old_name.name != new_name.name;
11701
11702 if is_spark {
11703 if is_rename {
11704 self.write_keyword("RENAME COLUMN");
11706 self.write_space();
11707 self.generate_identifier(old_name)?;
11708 self.write_space();
11709 self.write_keyword("TO");
11710 self.write_space();
11711 self.generate_identifier(new_name)?;
11712 } else if comment.is_some() {
11713 self.write_keyword("ALTER COLUMN");
11715 self.write_space();
11716 self.generate_identifier(old_name)?;
11717 self.write_space();
11718 self.write_keyword("COMMENT");
11719 self.write_space();
11720 self.write("'");
11721 self.write(comment.as_ref().unwrap());
11722 self.write("'");
11723 } else if data_type.is_some() {
11724 self.write_keyword("ALTER COLUMN");
11726 self.write_space();
11727 self.generate_identifier(old_name)?;
11728 self.write_space();
11729 self.write_keyword("TYPE");
11730 self.write_space();
11731 self.generate_data_type(data_type.as_ref().unwrap())?;
11732 } else {
11733 self.write_keyword("CHANGE COLUMN");
11735 self.write_space();
11736 self.generate_identifier(old_name)?;
11737 self.write_space();
11738 self.generate_identifier(new_name)?;
11739 }
11740 } else {
11741 if data_type.is_some() {
11743 self.write_keyword("CHANGE COLUMN");
11744 } else {
11745 self.write_keyword("CHANGE");
11746 }
11747 self.write_space();
11748 self.generate_identifier(old_name)?;
11749 self.write_space();
11750 self.generate_identifier(new_name)?;
11751 if let Some(ref dt) = data_type {
11752 self.write_space();
11753 self.generate_data_type(dt)?;
11754 }
11755 if let Some(ref c) = comment {
11756 self.write_space();
11757 self.write_keyword("COMMENT");
11758 self.write_space();
11759 self.write("'");
11760 self.write(c);
11761 self.write("'");
11762 }
11763 if *cascade {
11764 self.write_space();
11765 self.write_keyword("CASCADE");
11766 }
11767 }
11768 }
11769 AlterTableAction::AddPartition {
11770 partition,
11771 if_not_exists,
11772 location,
11773 } => {
11774 self.write_keyword("ADD");
11775 self.write_space();
11776 if *if_not_exists {
11777 self.write_keyword("IF NOT EXISTS");
11778 self.write_space();
11779 }
11780 self.generate_expression(partition)?;
11781 if let Some(ref loc) = location {
11782 self.write_space();
11783 self.write_keyword("LOCATION");
11784 self.write_space();
11785 self.generate_expression(loc)?;
11786 }
11787 }
11788 AlterTableAction::AlterSortKey {
11789 this,
11790 expressions,
11791 compound,
11792 } => {
11793 self.write_keyword("ALTER");
11795 if *compound {
11796 self.write_space();
11797 self.write_keyword("COMPOUND");
11798 }
11799 self.write_space();
11800 self.write_keyword("SORTKEY");
11801 self.write_space();
11802 if let Some(style) = this {
11803 self.write_keyword(style);
11804 } else if !expressions.is_empty() {
11805 self.write("(");
11806 for (i, expr) in expressions.iter().enumerate() {
11807 if i > 0 {
11808 self.write(", ");
11809 }
11810 self.generate_expression(expr)?;
11811 }
11812 self.write(")");
11813 }
11814 }
11815 AlterTableAction::AlterDistStyle { style, distkey } => {
11816 self.write_keyword("ALTER");
11818 self.write_space();
11819 self.write_keyword("DISTSTYLE");
11820 self.write_space();
11821 self.write_keyword(style);
11822 if let Some(col) = distkey {
11823 self.write_space();
11824 self.write_keyword("DISTKEY");
11825 self.write_space();
11826 self.generate_identifier(col)?;
11827 }
11828 }
11829 AlterTableAction::SetTableProperties { properties } => {
11830 self.write_keyword("SET TABLE PROPERTIES");
11832 self.write(" (");
11833 for (i, (key, value)) in properties.iter().enumerate() {
11834 if i > 0 {
11835 self.write(", ");
11836 }
11837 self.generate_expression(key)?;
11838 self.write(" = ");
11839 self.generate_expression(value)?;
11840 }
11841 self.write(")");
11842 }
11843 AlterTableAction::SetLocation { location } => {
11844 self.write_keyword("SET LOCATION");
11846 self.write_space();
11847 self.write("'");
11848 self.write(location);
11849 self.write("'");
11850 }
11851 AlterTableAction::SetFileFormat { format } => {
11852 self.write_keyword("SET FILE FORMAT");
11854 self.write_space();
11855 self.write_keyword(format);
11856 }
11857 AlterTableAction::ReplacePartition { partition, source } => {
11858 self.write_keyword("REPLACE PARTITION");
11860 self.write_space();
11861 self.generate_expression(partition)?;
11862 if let Some(src) = source {
11863 self.write_space();
11864 self.write_keyword("FROM");
11865 self.write_space();
11866 self.generate_expression(src)?;
11867 }
11868 }
11869 AlterTableAction::SetTiDBTableOption { option, force } => {
11870 self.generate_tidb_table_option(option, *force)?;
11871 }
11872 AlterTableAction::RemoveTiDBTtl { executable_comment } => {
11873 if !matches!(self.config.dialect, Some(DialectType::TiDB)) {
11874 return self.write_unsupported_comment(
11875 "REMOVE TTL is only supported by the TiDB dialect",
11876 );
11877 }
11878 if *executable_comment {
11879 self.write("/*T![ttl] REMOVE TTL */");
11880 } else {
11881 self.write_keyword("REMOVE TTL");
11882 }
11883 }
11884 AlterTableAction::Raw { sql } => {
11885 self.write(sql);
11886 }
11887 }
11888 Ok(())
11889 }
11890
11891 fn generate_alter_column_action(&mut self, action: &AlterColumnAction) -> Result<()> {
11892 match action {
11893 AlterColumnAction::SetDataType {
11894 data_type,
11895 using,
11896 collate,
11897 } => {
11898 use crate::dialects::DialectType;
11899 let is_no_prefix = matches!(
11904 self.config.dialect,
11905 Some(DialectType::TSQL) | Some(DialectType::Fabric) | Some(DialectType::Hive)
11906 );
11907 let is_type_only = matches!(
11908 self.config.dialect,
11909 Some(DialectType::Redshift)
11910 | Some(DialectType::Spark)
11911 | Some(DialectType::Databricks)
11912 );
11913 if is_type_only {
11914 self.write_keyword("TYPE");
11915 self.write_space();
11916 } else if !is_no_prefix {
11917 self.write_keyword("SET DATA TYPE");
11918 self.write_space();
11919 }
11920 self.generate_data_type(data_type)?;
11921 if let Some(ref collation) = collate {
11922 self.write_space();
11923 self.write_keyword("COLLATE");
11924 self.write_space();
11925 self.write(collation);
11926 }
11927 if let Some(ref using_expr) = using {
11928 self.write_space();
11929 self.write_keyword("USING");
11930 self.write_space();
11931 self.generate_expression(using_expr)?;
11932 }
11933 }
11934 AlterColumnAction::SetDefault(expr) => {
11935 self.write_keyword("SET DEFAULT");
11936 self.write_space();
11937 self.generate_expression(expr)?;
11938 }
11939 AlterColumnAction::DropDefault => {
11940 self.write_keyword("DROP DEFAULT");
11941 }
11942 AlterColumnAction::SetNotNull => {
11943 self.write_keyword("SET NOT NULL");
11944 }
11945 AlterColumnAction::DropNotNull => {
11946 self.write_keyword("DROP NOT NULL");
11947 }
11948 AlterColumnAction::Comment(comment) => {
11949 self.write_keyword("COMMENT");
11950 self.write_space();
11951 self.generate_string_literal(comment)?;
11952 }
11953 AlterColumnAction::SetVisible => {
11954 self.write_keyword("SET VISIBLE");
11955 }
11956 AlterColumnAction::SetInvisible => {
11957 self.write_keyword("SET INVISIBLE");
11958 }
11959 }
11960 Ok(())
11961 }
11962
11963 fn generate_create_index(&mut self, ci: &CreateIndex) -> Result<()> {
11964 self.write_keyword("CREATE");
11965
11966 if ci.unique {
11967 self.write_space();
11968 self.write_keyword("UNIQUE");
11969 }
11970
11971 if let Some(ref clustered) = ci.clustered {
11973 self.write_space();
11974 self.write_keyword(clustered);
11975 }
11976
11977 self.write_space();
11978 self.write_keyword("INDEX");
11979
11980 if ci.concurrently {
11982 self.write_space();
11983 self.write_keyword("CONCURRENTLY");
11984 }
11985
11986 if ci.if_not_exists {
11987 self.write_space();
11988 self.write_keyword("IF NOT EXISTS");
11989 }
11990
11991 if !ci.name.name.is_empty() {
11993 self.write_space();
11994 self.generate_identifier(&ci.name)?;
11995 }
11996 self.write_space();
11997 self.write_keyword("ON");
11998 if matches!(self.config.dialect, Some(DialectType::Hive)) {
12000 self.write_space();
12001 self.write_keyword("TABLE");
12002 }
12003 self.write_space();
12004 self.generate_table(&ci.table)?;
12005
12006 if !ci.columns.is_empty() || !ci.key_parts.is_empty() || ci.using.is_some() {
12009 let space_before_paren = false;
12010
12011 if let Some(ref using) = ci.using {
12012 self.write_space();
12013 self.write_keyword("USING");
12014 self.write_space();
12015 self.write(using);
12016 if space_before_paren {
12017 self.write(" (");
12018 } else {
12019 self.write("(");
12020 }
12021 } else {
12022 if space_before_paren {
12023 self.write(" (");
12024 } else {
12025 self.write("(");
12026 }
12027 }
12028 if ci.key_parts.is_empty() {
12029 for (i, col) in ci.columns.iter().enumerate() {
12030 if i > 0 {
12031 self.write(", ");
12032 }
12033 self.generate_identifier(&col.column)?;
12034 if let Some(ref opclass) = col.opclass {
12035 self.write_space();
12036 self.write(opclass);
12037 }
12038 if col.desc {
12039 self.write_space();
12040 self.write_keyword("DESC");
12041 } else if col.asc {
12042 self.write_space();
12043 self.write_keyword("ASC");
12044 }
12045 if let Some(nulls_first) = col.nulls_first {
12046 self.write_space();
12047 self.write_keyword("NULLS");
12048 self.write_space();
12049 self.write_keyword(if nulls_first { "FIRST" } else { "LAST" });
12050 }
12051 }
12052 } else {
12053 self.generate_index_key_parts(&ci.key_parts)?;
12054 }
12055 self.write(")");
12056 }
12057
12058 if !ci.include_columns.is_empty() {
12060 self.write_space();
12061 self.write_keyword("INCLUDE");
12062 self.write(" (");
12063 for (i, col) in ci.include_columns.iter().enumerate() {
12064 if i > 0 {
12065 self.write(", ");
12066 }
12067 self.generate_identifier(col)?;
12068 }
12069 self.write(")");
12070 }
12071
12072 if !ci.with_options.is_empty() {
12074 self.write_space();
12075 self.write_keyword("WITH");
12076 self.write(" (");
12077 for (i, (key, value)) in ci.with_options.iter().enumerate() {
12078 if i > 0 {
12079 self.write(", ");
12080 }
12081 self.write(key);
12082 self.write("=");
12083 self.write(value);
12084 }
12085 self.write(")");
12086 }
12087
12088 if let Some(ref where_clause) = ci.where_clause {
12090 self.write_space();
12091 self.write_keyword("WHERE");
12092 self.write_space();
12093 self.generate_expression(where_clause)?;
12094 }
12095
12096 if let Some(ref on_fg) = ci.on_filegroup {
12098 self.write_space();
12099 self.write_keyword("ON");
12100 self.write_space();
12101 self.write(on_fg);
12102 }
12103
12104 Ok(())
12105 }
12106
12107 fn generate_index_key_parts(&mut self, key_parts: &[IndexKeyPart]) -> Result<()> {
12108 for (i, part) in key_parts.iter().enumerate() {
12109 if i > 0 {
12110 self.write(", ");
12111 }
12112 self.generate_expression(&part.expression)?;
12113 if let Some(ref prefix_length) = part.prefix_length {
12114 self.write("(");
12115 self.write(prefix_length);
12116 self.write(")");
12117 }
12118 if let Some(ref opclass) = part.opclass {
12119 self.write_space();
12120 self.write(opclass);
12121 }
12122 if part.desc {
12123 self.write_space();
12124 self.write_keyword("DESC");
12125 } else if part.asc {
12126 self.write_space();
12127 self.write_keyword("ASC");
12128 }
12129 if let Some(nulls_first) = part.nulls_first {
12130 self.write_space();
12131 self.write_keyword("NULLS");
12132 self.write_space();
12133 self.write_keyword(if nulls_first { "FIRST" } else { "LAST" });
12134 }
12135 }
12136 Ok(())
12137 }
12138
12139 fn generate_drop_index(&mut self, di: &DropIndex) -> Result<()> {
12140 self.write_keyword("DROP INDEX");
12141
12142 if di.concurrently {
12143 self.write_space();
12144 self.write_keyword("CONCURRENTLY");
12145 }
12146
12147 if di.if_exists {
12148 self.write_space();
12149 self.write_keyword("IF EXISTS");
12150 }
12151
12152 self.write_space();
12153 self.generate_table(&di.name)?;
12154
12155 if let Some(ref table) = di.table {
12156 self.write_space();
12157 self.write_keyword("ON");
12158 self.write_space();
12159 self.generate_table(table)?;
12160 }
12161
12162 Ok(())
12163 }
12164
12165 fn generate_create_view(&mut self, cv: &CreateView) -> Result<()> {
12166 self.write_keyword("CREATE");
12167
12168 if let Some(ref algorithm) = cv.algorithm {
12170 self.write_space();
12171 self.write_keyword("ALGORITHM");
12172 self.write("=");
12173 self.write_keyword(algorithm);
12174 }
12175
12176 if let Some(ref definer) = cv.definer {
12178 self.write_space();
12179 self.write_keyword("DEFINER");
12180 self.write("=");
12181 self.write(definer);
12182 }
12183
12184 if cv.security_sql_style && !cv.security_after_name {
12186 if let Some(ref security) = cv.security {
12187 self.write_space();
12188 self.write_keyword("SQL SECURITY");
12189 self.write_space();
12190 match security {
12191 FunctionSecurity::Definer => self.write_keyword("DEFINER"),
12192 FunctionSecurity::Invoker => self.write_keyword("INVOKER"),
12193 FunctionSecurity::None => self.write_keyword("NONE"),
12194 }
12195 }
12196 }
12197
12198 if cv.or_alter {
12199 self.write_space();
12200 self.write_keyword("OR ALTER");
12201 } else if cv.or_replace {
12202 self.write_space();
12203 self.write_keyword("OR REPLACE");
12204 }
12205
12206 if cv.temporary {
12207 self.write_space();
12208 self.write_keyword("TEMPORARY");
12209 }
12210
12211 if cv.materialized {
12212 self.write_space();
12213 self.write_keyword("MATERIALIZED");
12214 }
12215
12216 if cv.secure {
12218 self.write_space();
12219 self.write_keyword("SECURE");
12220 }
12221
12222 self.write_space();
12223 self.write_keyword("VIEW");
12224
12225 if cv.if_not_exists {
12226 self.write_space();
12227 self.write_keyword("IF NOT EXISTS");
12228 }
12229
12230 self.write_space();
12231 self.generate_table(&cv.name)?;
12232
12233 if let Some(ref on_cluster) = cv.on_cluster {
12235 self.write_space();
12236 self.generate_on_cluster(on_cluster)?;
12237 }
12238
12239 if let Some(ref to_table) = cv.to_table {
12241 self.write_space();
12242 self.write_keyword("TO");
12243 self.write_space();
12244 self.generate_table(to_table)?;
12245 }
12246
12247 if !cv.materialized {
12250 if let Some(ref schema) = cv.schema {
12252 self.write(" (");
12253 for (i, expr) in schema.expressions.iter().enumerate() {
12254 if i > 0 {
12255 self.write(", ");
12256 }
12257 self.generate_expression(expr)?;
12258 }
12259 self.write(")");
12260 } else if !cv.columns.is_empty() {
12261 self.write(" (");
12262 for (i, col) in cv.columns.iter().enumerate() {
12263 if i > 0 {
12264 self.write(", ");
12265 }
12266 self.generate_identifier(&col.name)?;
12267 if !col.options.is_empty() {
12269 self.write_space();
12270 self.generate_options_clause(&col.options)?;
12271 }
12272 if let Some(ref comment) = col.comment {
12273 self.write_space();
12274 self.write_keyword("COMMENT");
12275 self.write_space();
12276 self.generate_string_literal(comment)?;
12277 }
12278 }
12279 self.write(")");
12280 }
12281
12282 if !cv.security_sql_style || cv.security_after_name {
12285 if let Some(ref security) = cv.security {
12286 self.write_space();
12287 if cv.security_sql_style {
12288 self.write_keyword("SQL SECURITY");
12289 } else {
12290 self.write_keyword("SECURITY");
12291 }
12292 self.write_space();
12293 match security {
12294 FunctionSecurity::Definer => self.write_keyword("DEFINER"),
12295 FunctionSecurity::Invoker => self.write_keyword("INVOKER"),
12296 FunctionSecurity::None => self.write_keyword("NONE"),
12297 }
12298 }
12299 }
12300
12301 if cv.copy_grants {
12303 self.write_space();
12304 self.write_keyword("COPY GRANTS");
12305 }
12306 } else {
12307 if cv.copy_grants {
12309 self.write_space();
12310 self.write_keyword("COPY GRANTS");
12311 }
12312
12313 if let Some(ref schema) = cv.schema {
12315 self.write(" (");
12316 for (i, expr) in schema.expressions.iter().enumerate() {
12317 if i > 0 {
12318 self.write(", ");
12319 }
12320 self.generate_expression(expr)?;
12321 }
12322 self.write(")");
12323 } else if !cv.columns.is_empty() {
12324 self.write(" (");
12326 for (i, col) in cv.columns.iter().enumerate() {
12327 if i > 0 {
12328 self.write(", ");
12329 }
12330 self.generate_identifier(&col.name)?;
12331 if !col.options.is_empty() {
12333 self.write_space();
12334 self.generate_options_clause(&col.options)?;
12335 }
12336 if let Some(ref comment) = col.comment {
12337 self.write_space();
12338 self.write_keyword("COMMENT");
12339 self.write_space();
12340 self.generate_string_literal(comment)?;
12341 }
12342 }
12343 self.write(")");
12344 }
12345
12346 if let Some(ref unique_key) = cv.unique_key {
12348 self.write_space();
12349 self.write_keyword("KEY");
12350 self.write(" (");
12351 for (i, expr) in unique_key.expressions.iter().enumerate() {
12352 if i > 0 {
12353 self.write(", ");
12354 }
12355 self.generate_expression(expr)?;
12356 }
12357 self.write(")");
12358 }
12359 }
12360
12361 if let Some(ref row_access_policy) = cv.row_access_policy {
12362 self.write_space();
12363 self.write_keyword("WITH");
12364 self.write_space();
12365 self.write(row_access_policy);
12366 }
12367
12368 if let Some(ref comment) = cv.comment {
12370 self.write_space();
12371 self.write_keyword("COMMENT");
12372 self.write("=");
12373 self.generate_string_literal(comment)?;
12374 }
12375
12376 if !cv.tags.is_empty() {
12378 self.write_space();
12379 self.write_keyword("TAG");
12380 self.write(" (");
12381 for (i, (name, value)) in cv.tags.iter().enumerate() {
12382 if i > 0 {
12383 self.write(", ");
12384 }
12385 self.write(name);
12386 self.write("='");
12387 self.write(value);
12388 self.write("'");
12389 }
12390 self.write(")");
12391 }
12392
12393 if !cv.options.is_empty() {
12395 self.write_space();
12396 self.generate_options_clause(&cv.options)?;
12397 }
12398
12399 if let Some(ref build) = cv.build {
12401 self.write_space();
12402 self.write_keyword("BUILD");
12403 self.write_space();
12404 self.write_keyword(build);
12405 }
12406
12407 if let Some(ref refresh) = cv.refresh {
12409 self.write_space();
12410 self.generate_refresh_trigger_property(refresh)?;
12411 }
12412
12413 if let Some(auto_refresh) = cv.auto_refresh {
12415 self.write_space();
12416 self.write_keyword("AUTO REFRESH");
12417 self.write_space();
12418 if auto_refresh {
12419 self.write_keyword("YES");
12420 } else {
12421 self.write_keyword("NO");
12422 }
12423 }
12424
12425 for prop in &cv.table_properties {
12427 self.write_space();
12428 self.generate_expression(prop)?;
12429 }
12430
12431 if let Some(ref population) = cv.clickhouse_population {
12433 self.write_space();
12434 self.write_keyword(population);
12435 }
12436
12437 if !matches!(&cv.query, Expression::Null(_)) {
12439 self.write_space();
12440 self.write_keyword("AS");
12441 self.write_space();
12442
12443 if let Some(ref mode) = cv.locking_mode {
12445 self.write_keyword("LOCKING");
12446 self.write_space();
12447 self.write_keyword(mode);
12448 if let Some(ref access) = cv.locking_access {
12449 self.write_space();
12450 self.write_keyword("FOR");
12451 self.write_space();
12452 self.write_keyword(access);
12453 }
12454 self.write_space();
12455 }
12456
12457 if cv.query_parenthesized {
12458 self.write("(");
12459 }
12460 self.generate_expression(&cv.query)?;
12461 if cv.query_parenthesized {
12462 self.write(")");
12463 }
12464 }
12465
12466 if cv.no_schema_binding {
12468 self.write_space();
12469 self.write_keyword("WITH NO SCHEMA BINDING");
12470 }
12471
12472 Ok(())
12473 }
12474
12475 fn generate_drop_view(&mut self, dv: &DropView) -> Result<()> {
12476 self.write_keyword("DROP");
12477
12478 if dv.materialized {
12479 self.write_space();
12480 self.write_keyword("MATERIALIZED");
12481 }
12482
12483 self.write_space();
12484 self.write_keyword("VIEW");
12485
12486 if dv.if_exists {
12487 self.write_space();
12488 self.write_keyword("IF EXISTS");
12489 }
12490
12491 self.write_space();
12492 self.generate_table(&dv.name)?;
12493
12494 Ok(())
12495 }
12496
12497 fn generate_truncate(&mut self, tr: &Truncate) -> Result<()> {
12498 match tr.target {
12499 TruncateTarget::Database => self.write_keyword("TRUNCATE DATABASE"),
12500 TruncateTarget::Table => self.write_keyword("TRUNCATE TABLE"),
12501 }
12502 if tr.if_exists {
12503 self.write_space();
12504 self.write_keyword("IF EXISTS");
12505 }
12506 self.write_space();
12507 self.generate_table(&tr.table)?;
12508
12509 if let Some(ref on_cluster) = tr.on_cluster {
12511 self.write_space();
12512 self.generate_on_cluster(on_cluster)?;
12513 }
12514
12515 if !tr.extra_tables.is_empty() {
12517 let skip_first = if let Some(first) = tr.extra_tables.first() {
12519 first.table.name == tr.table.name && first.star
12520 } else {
12521 false
12522 };
12523
12524 let strip_star = matches!(
12526 self.config.dialect,
12527 Some(crate::dialects::DialectType::PostgreSQL)
12528 | Some(crate::dialects::DialectType::Redshift)
12529 );
12530 if skip_first && !strip_star {
12531 self.write("*");
12532 }
12533
12534 for (i, entry) in tr.extra_tables.iter().enumerate() {
12536 if i == 0 && skip_first {
12537 continue; }
12539 self.write(", ");
12540 self.generate_table(&entry.table)?;
12541 if entry.star && !strip_star {
12542 self.write("*");
12543 }
12544 }
12545 }
12546
12547 if let Some(identity) = &tr.identity {
12549 self.write_space();
12550 match identity {
12551 TruncateIdentity::Restart => self.write_keyword("RESTART IDENTITY"),
12552 TruncateIdentity::Continue => self.write_keyword("CONTINUE IDENTITY"),
12553 }
12554 }
12555
12556 if tr.cascade {
12557 self.write_space();
12558 self.write_keyword("CASCADE");
12559 }
12560
12561 if tr.restrict {
12562 self.write_space();
12563 self.write_keyword("RESTRICT");
12564 }
12565
12566 if let Some(ref partition) = tr.partition {
12568 self.write_space();
12569 self.generate_expression(partition)?;
12570 }
12571
12572 Ok(())
12573 }
12574
12575 fn generate_use(&mut self, u: &Use) -> Result<()> {
12576 if matches!(self.config.dialect, Some(DialectType::Teradata)) {
12578 self.write_keyword("DATABASE");
12579 self.write_space();
12580 self.generate_identifier(&u.this)?;
12581 return Ok(());
12582 }
12583
12584 self.write_keyword("USE");
12585
12586 if let Some(kind) = &u.kind {
12587 self.write_space();
12588 match kind {
12589 UseKind::Database => self.write_keyword("DATABASE"),
12590 UseKind::Schema => self.write_keyword("SCHEMA"),
12591 UseKind::Role => self.write_keyword("ROLE"),
12592 UseKind::Warehouse => self.write_keyword("WAREHOUSE"),
12593 UseKind::Catalog => self.write_keyword("CATALOG"),
12594 UseKind::SecondaryRoles => self.write_keyword("SECONDARY ROLES"),
12595 }
12596 }
12597
12598 self.write_space();
12599 if matches!(&u.kind, Some(UseKind::SecondaryRoles)) {
12602 self.write(&u.this.name);
12603 } else {
12604 self.generate_identifier(&u.this)?;
12605 }
12606 Ok(())
12607 }
12608
12609 fn generate_cache(&mut self, c: &Cache) -> Result<()> {
12610 self.write_keyword("CACHE");
12611 if c.lazy {
12612 self.write_space();
12613 self.write_keyword("LAZY");
12614 }
12615 self.write_space();
12616 self.write_keyword("TABLE");
12617 self.write_space();
12618 self.generate_identifier(&c.table)?;
12619
12620 if !c.options.is_empty() {
12622 self.write_space();
12623 self.write_keyword("OPTIONS");
12624 self.write("(");
12625 for (i, (key, value)) in c.options.iter().enumerate() {
12626 if i > 0 {
12627 self.write(", ");
12628 }
12629 self.generate_expression(key)?;
12630 self.write(" = ");
12631 self.generate_expression(value)?;
12632 }
12633 self.write(")");
12634 }
12635
12636 if let Some(query) = &c.query {
12638 self.write_space();
12639 self.write_keyword("AS");
12640 self.write_space();
12641 self.generate_expression(query)?;
12642 }
12643
12644 Ok(())
12645 }
12646
12647 fn generate_uncache(&mut self, u: &Uncache) -> Result<()> {
12648 self.write_keyword("UNCACHE TABLE");
12649 if u.if_exists {
12650 self.write_space();
12651 self.write_keyword("IF EXISTS");
12652 }
12653 self.write_space();
12654 self.generate_identifier(&u.table)?;
12655 Ok(())
12656 }
12657
12658 fn generate_load_data(&mut self, l: &LoadData) -> Result<()> {
12659 self.write_keyword("LOAD DATA");
12660 if l.local {
12661 self.write_space();
12662 self.write_keyword("LOCAL");
12663 }
12664 self.write_space();
12665 self.write_keyword("INPATH");
12666 self.write_space();
12667 self.write("'");
12668 self.write(&l.inpath);
12669 self.write("'");
12670
12671 if l.overwrite {
12672 self.write_space();
12673 self.write_keyword("OVERWRITE");
12674 }
12675
12676 self.write_space();
12677 self.write_keyword("INTO TABLE");
12678 self.write_space();
12679 self.generate_expression(&l.table)?;
12680
12681 if !l.partition.is_empty() {
12683 self.write_space();
12684 self.write_keyword("PARTITION");
12685 self.write("(");
12686 for (i, (col, val)) in l.partition.iter().enumerate() {
12687 if i > 0 {
12688 self.write(", ");
12689 }
12690 self.generate_identifier(col)?;
12691 self.write(" = ");
12692 self.generate_expression(val)?;
12693 }
12694 self.write(")");
12695 }
12696
12697 if let Some(fmt) = &l.input_format {
12699 self.write_space();
12700 self.write_keyword("INPUTFORMAT");
12701 self.write_space();
12702 self.write("'");
12703 self.write(fmt);
12704 self.write("'");
12705 }
12706
12707 if let Some(serde) = &l.serde {
12709 self.write_space();
12710 self.write_keyword("SERDE");
12711 self.write_space();
12712 self.write("'");
12713 self.write(serde);
12714 self.write("'");
12715 }
12716
12717 Ok(())
12718 }
12719
12720 fn generate_pragma(&mut self, p: &Pragma) -> Result<()> {
12721 self.write_keyword("PRAGMA");
12722 self.write_space();
12723
12724 if let Some(schema) = &p.schema {
12726 self.generate_identifier(schema)?;
12727 self.write(".");
12728 }
12729
12730 self.generate_identifier(&p.name)?;
12732
12733 if p.use_assignment_syntax {
12735 self.write(" = ");
12736 if let Some(value) = &p.value {
12737 self.generate_expression(value)?;
12738 } else if let Some(arg) = p.args.first() {
12739 self.generate_expression(arg)?;
12740 }
12741 } else if !p.args.is_empty() {
12742 self.write("(");
12743 for (i, arg) in p.args.iter().enumerate() {
12744 if i > 0 {
12745 self.write(", ");
12746 }
12747 self.generate_expression(arg)?;
12748 }
12749 self.write(")");
12750 }
12751
12752 Ok(())
12753 }
12754
12755 fn generate_grant(&mut self, g: &Grant) -> Result<()> {
12756 self.write_keyword("GRANT");
12757 self.write_space();
12758
12759 for (i, privilege) in g.privileges.iter().enumerate() {
12761 if i > 0 {
12762 self.write(", ");
12763 }
12764 self.write_keyword(&privilege.name);
12765 if !privilege.columns.is_empty() {
12767 self.write("(");
12768 for (j, col) in privilege.columns.iter().enumerate() {
12769 if j > 0 {
12770 self.write(", ");
12771 }
12772 self.write(col);
12773 }
12774 self.write(")");
12775 }
12776 }
12777
12778 self.write_space();
12779 self.write_keyword("ON");
12780 self.write_space();
12781
12782 if let Some(kind) = &g.kind {
12784 self.write_keyword(kind);
12785 self.write_space();
12786 }
12787
12788 {
12790 use crate::dialects::DialectType;
12791 let should_upper = matches!(
12792 self.config.dialect,
12793 Some(DialectType::PostgreSQL)
12794 | Some(DialectType::CockroachDB)
12795 | Some(DialectType::Materialize)
12796 | Some(DialectType::RisingWave)
12797 ) && (g.kind.as_deref() == Some("FUNCTION")
12798 || g.kind.as_deref() == Some("PROCEDURE"));
12799 if should_upper {
12800 use crate::expressions::Identifier;
12801 let upper_id = Identifier {
12802 name: g.securable.name.to_ascii_uppercase(),
12803 quoted: g.securable.quoted,
12804 ..g.securable.clone()
12805 };
12806 self.generate_identifier(&upper_id)?;
12807 } else {
12808 self.generate_identifier(&g.securable)?;
12809 }
12810 }
12811
12812 if !g.function_params.is_empty() {
12814 self.write("(");
12815 for (i, param) in g.function_params.iter().enumerate() {
12816 if i > 0 {
12817 self.write(", ");
12818 }
12819 self.write(param);
12820 }
12821 self.write(")");
12822 }
12823
12824 self.write_space();
12825 self.write_keyword("TO");
12826 self.write_space();
12827
12828 for (i, principal) in g.principals.iter().enumerate() {
12830 if i > 0 {
12831 self.write(", ");
12832 }
12833 if principal.is_role {
12834 self.write_keyword("ROLE");
12835 self.write_space();
12836 } else if principal.is_group {
12837 self.write_keyword("GROUP");
12838 self.write_space();
12839 } else if principal.is_share {
12840 self.write_keyword("SHARE");
12841 self.write_space();
12842 }
12843 self.generate_identifier(&principal.name)?;
12844 }
12845
12846 if g.grant_option {
12848 self.write_space();
12849 self.write_keyword("WITH GRANT OPTION");
12850 }
12851
12852 if let Some(ref principal) = g.as_principal {
12854 self.write_space();
12855 self.write_keyword("AS");
12856 self.write_space();
12857 self.generate_identifier(principal)?;
12858 }
12859
12860 Ok(())
12861 }
12862
12863 fn generate_revoke(&mut self, r: &Revoke) -> Result<()> {
12864 self.write_keyword("REVOKE");
12865 self.write_space();
12866
12867 if r.grant_option {
12869 self.write_keyword("GRANT OPTION FOR");
12870 self.write_space();
12871 }
12872
12873 for (i, privilege) in r.privileges.iter().enumerate() {
12875 if i > 0 {
12876 self.write(", ");
12877 }
12878 self.write_keyword(&privilege.name);
12879 if !privilege.columns.is_empty() {
12881 self.write("(");
12882 for (j, col) in privilege.columns.iter().enumerate() {
12883 if j > 0 {
12884 self.write(", ");
12885 }
12886 self.write(col);
12887 }
12888 self.write(")");
12889 }
12890 }
12891
12892 self.write_space();
12893 self.write_keyword("ON");
12894 self.write_space();
12895
12896 if let Some(kind) = &r.kind {
12898 self.write_keyword(kind);
12899 self.write_space();
12900 }
12901
12902 {
12904 use crate::dialects::DialectType;
12905 let should_upper = matches!(
12906 self.config.dialect,
12907 Some(DialectType::PostgreSQL)
12908 | Some(DialectType::CockroachDB)
12909 | Some(DialectType::Materialize)
12910 | Some(DialectType::RisingWave)
12911 ) && (r.kind.as_deref() == Some("FUNCTION")
12912 || r.kind.as_deref() == Some("PROCEDURE"));
12913 if should_upper {
12914 use crate::expressions::Identifier;
12915 let upper_id = Identifier {
12916 name: r.securable.name.to_ascii_uppercase(),
12917 quoted: r.securable.quoted,
12918 ..r.securable.clone()
12919 };
12920 self.generate_identifier(&upper_id)?;
12921 } else {
12922 self.generate_identifier(&r.securable)?;
12923 }
12924 }
12925
12926 if !r.function_params.is_empty() {
12928 self.write("(");
12929 for (i, param) in r.function_params.iter().enumerate() {
12930 if i > 0 {
12931 self.write(", ");
12932 }
12933 self.write(param);
12934 }
12935 self.write(")");
12936 }
12937
12938 self.write_space();
12939 self.write_keyword("FROM");
12940 self.write_space();
12941
12942 for (i, principal) in r.principals.iter().enumerate() {
12944 if i > 0 {
12945 self.write(", ");
12946 }
12947 if principal.is_role {
12948 self.write_keyword("ROLE");
12949 self.write_space();
12950 } else if principal.is_group {
12951 self.write_keyword("GROUP");
12952 self.write_space();
12953 } else if principal.is_share {
12954 self.write_keyword("SHARE");
12955 self.write_space();
12956 }
12957 self.generate_identifier(&principal.name)?;
12958 }
12959
12960 if r.cascade {
12962 self.write_space();
12963 self.write_keyword("CASCADE");
12964 } else if r.restrict {
12965 self.write_space();
12966 self.write_keyword("RESTRICT");
12967 }
12968
12969 Ok(())
12970 }
12971
12972 fn generate_comment(&mut self, c: &Comment) -> Result<()> {
12973 self.write_keyword("COMMENT");
12974
12975 if c.exists {
12977 self.write_space();
12978 self.write_keyword("IF EXISTS");
12979 }
12980
12981 self.write_space();
12982 self.write_keyword("ON");
12983
12984 if c.materialized {
12986 self.write_space();
12987 self.write_keyword("MATERIALIZED");
12988 }
12989
12990 self.write_space();
12991 self.write_keyword(&c.kind);
12992 self.write_space();
12993
12994 self.generate_expression(&c.this)?;
12996
12997 self.write_space();
12998 self.write_keyword("IS");
12999 self.write_space();
13000
13001 self.generate_expression(&c.expression)?;
13003
13004 Ok(())
13005 }
13006
13007 fn generate_set_statement(&mut self, s: &SetStatement) -> Result<()> {
13008 self.write_keyword("SET");
13009
13010 for (i, item) in s.items.iter().enumerate() {
13011 if i > 0 {
13012 self.write(",");
13013 }
13014 self.write_space();
13015
13016 let has_variable_kind = item.kind.as_deref() == Some("VARIABLE");
13018 if let Some(ref kind) = item.kind {
13019 if has_variable_kind {
13023 if matches!(
13024 self.config.dialect,
13025 Some(DialectType::Spark | DialectType::Databricks | DialectType::DuckDB)
13026 ) {
13027 self.write_keyword("VARIABLE");
13028 self.write_space();
13029 }
13030 } else {
13031 self.write_keyword(kind);
13032 self.write_space();
13033 }
13034 }
13035
13036 let name_str = match &item.name {
13038 Expression::Identifier(id) => Some(id.name.as_str()),
13039 _ => None,
13040 };
13041
13042 let is_transaction = name_str == Some("TRANSACTION");
13043 let is_session_authorization = name_str == Some("SESSION AUTHORIZATION");
13044 let is_character_set = name_str == Some("CHARACTER SET");
13045 let is_names = name_str == Some("NAMES");
13046 let is_collate = name_str == Some("COLLATE");
13047 let is_identity_insert = name_str == Some("IDENTITY_INSERT");
13048 let is_value_only =
13049 matches!(&item.value, Expression::Identifier(id) if id.name.is_empty());
13050
13051 if is_session_authorization {
13052 self.write_keyword("SESSION AUTHORIZATION");
13055 self.write_space();
13056 self.generate_set_value(&item.value)?;
13057 } else if is_transaction {
13058 self.write_keyword("TRANSACTION");
13060 if let Expression::Identifier(id) = &item.value {
13061 if !id.name.is_empty() {
13062 self.write_space();
13063 self.write(&id.name);
13064 }
13065 }
13066 } else if is_character_set {
13067 self.write_keyword("CHARACTER SET");
13069 self.write_space();
13070 self.generate_set_value(&item.value)?;
13071 } else if is_names {
13072 self.write_keyword("NAMES");
13074 self.write_space();
13075 self.generate_set_value(&item.value)?;
13076 } else if is_collate {
13077 self.write_keyword("COLLATE");
13079 self.write_space();
13080 self.generate_set_value(&item.value)?;
13081 } else if is_identity_insert {
13082 self.write_keyword("IDENTITY_INSERT");
13084 self.write_space();
13085 self.generate_identity_insert_value(&item.value)?;
13086 } else if has_variable_kind {
13087 if let Some(ns) = name_str {
13090 self.write(ns);
13091 } else {
13092 self.generate_expression(&item.name)?;
13093 }
13094 self.write(" = ");
13095 self.generate_set_value(&item.value)?;
13096 } else if is_value_only {
13097 self.generate_expression(&item.name)?;
13099 } else if item.no_equals && matches!(self.config.dialect, Some(DialectType::TSQL)) {
13100 self.generate_expression(&item.name)?;
13102 self.write_space();
13103 self.generate_set_value(&item.value)?;
13104 } else {
13105 match &item.name {
13108 Expression::Identifier(id) => {
13109 self.write(&id.name);
13110 }
13111 _ => {
13112 self.generate_expression(&item.name)?;
13113 }
13114 }
13115 self.write(" = ");
13116 self.generate_set_value(&item.value)?;
13117 }
13118 }
13119
13120 Ok(())
13121 }
13122
13123 fn generate_identity_insert_value(&mut self, value: &Expression) -> Result<()> {
13124 if let Expression::Tuple(tuple) = value {
13125 if tuple.expressions.len() == 2 {
13126 self.generate_expression(&tuple.expressions[0])?;
13127 self.write_space();
13128 self.generate_set_value(&tuple.expressions[1])?;
13129 return Ok(());
13130 }
13131 }
13132
13133 self.generate_set_value(value)
13134 }
13135
13136 fn generate_set_value(&mut self, value: &Expression) -> Result<()> {
13139 if let Expression::Identifier(id) = value {
13140 match id.name.as_str() {
13141 "DEFAULT" | "ON" | "OFF" => {
13142 self.write_keyword(&id.name);
13143 return Ok(());
13144 }
13145 _ => {}
13146 }
13147 }
13148 self.generate_expression(value)
13149 }
13150
13151 fn generate_alter_view(&mut self, av: &AlterView) -> Result<()> {
13154 self.write_keyword("ALTER");
13155 if let Some(ref algorithm) = av.algorithm {
13157 self.write_space();
13158 self.write_keyword("ALGORITHM");
13159 self.write(" = ");
13160 self.write_keyword(algorithm);
13161 }
13162 if let Some(ref definer) = av.definer {
13163 self.write_space();
13164 self.write_keyword("DEFINER");
13165 self.write(" = ");
13166 self.write(definer);
13167 }
13168 if let Some(ref sql_security) = av.sql_security {
13169 self.write_space();
13170 self.write_keyword("SQL SECURITY");
13171 self.write(" = ");
13172 self.write_keyword(sql_security);
13173 }
13174 self.write_space();
13175 self.write_keyword("VIEW");
13176 self.write_space();
13177 self.generate_table(&av.name)?;
13178
13179 if !av.columns.is_empty() {
13181 self.write(" (");
13182 for (i, col) in av.columns.iter().enumerate() {
13183 if i > 0 {
13184 self.write(", ");
13185 }
13186 self.generate_identifier(&col.name)?;
13187 if let Some(ref comment) = col.comment {
13188 self.write_space();
13189 self.write_keyword("COMMENT");
13190 self.write(" ");
13191 self.generate_string_literal(comment)?;
13192 }
13193 }
13194 self.write(")");
13195 }
13196
13197 if let Some(ref opt) = av.with_option {
13199 self.write_space();
13200 self.write_keyword("WITH");
13201 self.write_space();
13202 self.write_keyword(opt);
13203 }
13204
13205 for action in &av.actions {
13206 self.write_space();
13207 match action {
13208 AlterViewAction::Rename(new_name) => {
13209 self.write_keyword("RENAME TO");
13210 self.write_space();
13211 self.generate_table(new_name)?;
13212 }
13213 AlterViewAction::OwnerTo(owner) => {
13214 self.write_keyword("OWNER TO");
13215 self.write_space();
13216 self.generate_identifier(owner)?;
13217 }
13218 AlterViewAction::SetSchema(schema) => {
13219 self.write_keyword("SET SCHEMA");
13220 self.write_space();
13221 self.generate_identifier(schema)?;
13222 }
13223 AlterViewAction::SetAuthorization(auth) => {
13224 self.write_keyword("SET AUTHORIZATION");
13225 self.write_space();
13226 self.write(auth);
13227 }
13228 AlterViewAction::AlterColumn { name, action } => {
13229 self.write_keyword("ALTER COLUMN");
13230 self.write_space();
13231 self.generate_identifier(name)?;
13232 self.write_space();
13233 self.generate_alter_column_action(action)?;
13234 }
13235 AlterViewAction::AsSelect(query) => {
13236 self.write_keyword("AS");
13237 self.write_space();
13238 self.generate_expression(query)?;
13239 }
13240 AlterViewAction::SetTblproperties(props) => {
13241 self.write_keyword("SET TBLPROPERTIES");
13242 self.write(" (");
13243 for (i, (key, value)) in props.iter().enumerate() {
13244 if i > 0 {
13245 self.write(", ");
13246 }
13247 self.generate_string_literal(key)?;
13248 self.write("=");
13249 self.generate_string_literal(value)?;
13250 }
13251 self.write(")");
13252 }
13253 AlterViewAction::UnsetTblproperties(keys) => {
13254 self.write_keyword("UNSET TBLPROPERTIES");
13255 self.write(" (");
13256 for (i, key) in keys.iter().enumerate() {
13257 if i > 0 {
13258 self.write(", ");
13259 }
13260 self.generate_string_literal(key)?;
13261 }
13262 self.write(")");
13263 }
13264 }
13265 }
13266
13267 Ok(())
13268 }
13269
13270 fn generate_alter_index(&mut self, ai: &AlterIndex) -> Result<()> {
13271 self.write_keyword("ALTER INDEX");
13272 self.write_space();
13273 self.generate_identifier(&ai.name)?;
13274
13275 if let Some(table) = &ai.table {
13276 self.write_space();
13277 self.write_keyword("ON");
13278 self.write_space();
13279 self.generate_table(table)?;
13280 }
13281
13282 for action in &ai.actions {
13283 self.write_space();
13284 match action {
13285 AlterIndexAction::Rename(new_name) => {
13286 self.write_keyword("RENAME TO");
13287 self.write_space();
13288 self.generate_identifier(new_name)?;
13289 }
13290 AlterIndexAction::SetTablespace(tablespace) => {
13291 self.write_keyword("SET TABLESPACE");
13292 self.write_space();
13293 self.generate_identifier(tablespace)?;
13294 }
13295 AlterIndexAction::Visible(visible) => {
13296 if *visible {
13297 self.write_keyword("VISIBLE");
13298 } else {
13299 self.write_keyword("INVISIBLE");
13300 }
13301 }
13302 }
13303 }
13304
13305 Ok(())
13306 }
13307
13308 fn generate_create_schema(&mut self, cs: &CreateSchema) -> Result<()> {
13309 for comment in &cs.leading_comments {
13311 self.write_formatted_comment(comment);
13312 self.write_space();
13313 }
13314
13315 let saved_athena_hive_context = self.athena_hive_context;
13317 if matches!(
13318 self.config.dialect,
13319 Some(crate::dialects::DialectType::Athena)
13320 ) {
13321 self.athena_hive_context = true;
13322 }
13323
13324 self.write_keyword("CREATE SCHEMA");
13325
13326 if cs.if_not_exists {
13327 self.write_space();
13328 self.write_keyword("IF NOT EXISTS");
13329 }
13330
13331 self.write_space();
13332 for (i, part) in cs.name.iter().enumerate() {
13333 if i > 0 {
13334 self.write(".");
13335 }
13336 self.generate_identifier(part)?;
13337 }
13338
13339 if let Some(ref clone_parts) = cs.clone_from {
13340 self.write_keyword(" CLONE ");
13341 for (i, part) in clone_parts.iter().enumerate() {
13342 if i > 0 {
13343 self.write(".");
13344 }
13345 self.generate_identifier(part)?;
13346 }
13347 }
13348
13349 if let Some(ref at_clause) = cs.at_clause {
13350 self.write_space();
13351 self.generate_expression(at_clause)?;
13352 }
13353
13354 if let Some(auth) = &cs.authorization {
13355 self.write_space();
13356 self.write_keyword("AUTHORIZATION");
13357 self.write_space();
13358 self.generate_identifier(auth)?;
13359 }
13360
13361 let with_properties: Vec<_> = cs
13364 .properties
13365 .iter()
13366 .filter(|p| matches!(p, Expression::Property(_)))
13367 .collect();
13368 let other_properties: Vec<_> = cs
13369 .properties
13370 .iter()
13371 .filter(|p| !matches!(p, Expression::Property(_)))
13372 .collect();
13373
13374 if !with_properties.is_empty() {
13376 self.write_space();
13377 self.write_keyword("WITH");
13378 self.write(" (");
13379 for (i, prop) in with_properties.iter().enumerate() {
13380 if i > 0 {
13381 self.write(", ");
13382 }
13383 self.generate_expression(prop)?;
13384 }
13385 self.write(")");
13386 }
13387
13388 for prop in other_properties {
13390 self.write_space();
13391 self.generate_expression(prop)?;
13392 }
13393
13394 self.athena_hive_context = saved_athena_hive_context;
13396
13397 Ok(())
13398 }
13399
13400 fn generate_drop_schema(&mut self, ds: &DropSchema) -> Result<()> {
13401 self.write_keyword("DROP SCHEMA");
13402
13403 if ds.if_exists {
13404 self.write_space();
13405 self.write_keyword("IF EXISTS");
13406 }
13407
13408 self.write_space();
13409 self.generate_identifier(&ds.name)?;
13410
13411 if ds.cascade {
13412 self.write_space();
13413 self.write_keyword("CASCADE");
13414 }
13415
13416 Ok(())
13417 }
13418
13419 fn generate_drop_namespace(&mut self, dn: &DropNamespace) -> Result<()> {
13420 self.write_keyword("DROP NAMESPACE");
13421
13422 if dn.if_exists {
13423 self.write_space();
13424 self.write_keyword("IF EXISTS");
13425 }
13426
13427 self.write_space();
13428 self.generate_identifier(&dn.name)?;
13429
13430 if dn.cascade {
13431 self.write_space();
13432 self.write_keyword("CASCADE");
13433 }
13434
13435 Ok(())
13436 }
13437
13438 fn generate_create_database(&mut self, cd: &CreateDatabase) -> Result<()> {
13439 self.write_keyword("CREATE DATABASE");
13440
13441 if cd.if_not_exists {
13442 self.write_space();
13443 self.write_keyword("IF NOT EXISTS");
13444 }
13445
13446 self.write_space();
13447 self.generate_identifier(&cd.name)?;
13448
13449 if let Some(ref clone_src) = cd.clone_from {
13450 self.write_keyword(" CLONE ");
13451 self.generate_identifier(clone_src)?;
13452 }
13453
13454 if let Some(ref at_clause) = cd.at_clause {
13456 self.write_space();
13457 self.generate_expression(at_clause)?;
13458 }
13459
13460 for option in &cd.options {
13461 self.write_space();
13462 match option {
13463 DatabaseOption::CharacterSet(charset) => {
13464 self.write_keyword("CHARACTER SET");
13465 self.write(" = ");
13466 self.write(&format!("'{}'", charset));
13467 }
13468 DatabaseOption::Collate(collate) => {
13469 self.write_keyword("COLLATE");
13470 self.write(" = ");
13471 self.write(&format!("'{}'", collate));
13472 }
13473 DatabaseOption::Owner(owner) => {
13474 self.write_keyword("OWNER");
13475 self.write(" = ");
13476 self.generate_identifier(owner)?;
13477 }
13478 DatabaseOption::Template(template) => {
13479 self.write_keyword("TEMPLATE");
13480 self.write(" = ");
13481 self.generate_identifier(template)?;
13482 }
13483 DatabaseOption::Encoding(encoding) => {
13484 self.write_keyword("ENCODING");
13485 self.write(" = ");
13486 self.write(&format!("'{}'", encoding));
13487 }
13488 DatabaseOption::Location(location) => {
13489 self.write_keyword("LOCATION");
13490 self.write(" = ");
13491 self.write(&format!("'{}'", location));
13492 }
13493 }
13494 }
13495
13496 Ok(())
13497 }
13498
13499 fn generate_drop_database(&mut self, dd: &DropDatabase) -> Result<()> {
13500 self.write_keyword("DROP DATABASE");
13501
13502 if dd.if_exists {
13503 self.write_space();
13504 self.write_keyword("IF EXISTS");
13505 }
13506
13507 self.write_space();
13508 self.generate_identifier(&dd.name)?;
13509
13510 if dd.sync {
13511 self.write_space();
13512 self.write_keyword("SYNC");
13513 }
13514
13515 Ok(())
13516 }
13517
13518 fn generate_create_function(&mut self, cf: &CreateFunction) -> Result<()> {
13519 self.write_keyword("CREATE");
13520
13521 if cf.or_alter {
13522 self.write_space();
13523 self.write_keyword("OR ALTER");
13524 } else if cf.or_replace {
13525 self.write_space();
13526 self.write_keyword("OR REPLACE");
13527 }
13528
13529 if cf.temporary {
13530 self.write_space();
13531 self.write_keyword("TEMPORARY");
13532 }
13533
13534 self.write_space();
13535 if cf.is_table_function {
13536 self.write_keyword("TABLE FUNCTION");
13537 } else {
13538 self.write_keyword("FUNCTION");
13539 }
13540
13541 if cf.if_not_exists {
13542 self.write_space();
13543 self.write_keyword("IF NOT EXISTS");
13544 }
13545
13546 self.write_space();
13547 self.generate_table(&cf.name)?;
13548 if cf.has_parens {
13549 let func_multiline = self.config.pretty
13550 && matches!(
13551 self.config.dialect,
13552 Some(crate::dialects::DialectType::TSQL)
13553 | Some(crate::dialects::DialectType::Fabric)
13554 )
13555 && !cf.parameters.is_empty();
13556 if func_multiline {
13557 self.write("(\n");
13558 self.indent_level += 2;
13559 self.write_indent();
13560 self.generate_function_parameters(&cf.parameters)?;
13561 self.write("\n");
13562 self.indent_level -= 2;
13563 self.write(")");
13564 } else {
13565 self.write("(");
13566 self.generate_function_parameters(&cf.parameters)?;
13567 self.write(")");
13568 }
13569 }
13570
13571 let use_multiline = self.config.pretty
13574 && matches!(
13575 self.config.dialect,
13576 Some(crate::dialects::DialectType::BigQuery)
13577 | Some(crate::dialects::DialectType::TSQL)
13578 | Some(crate::dialects::DialectType::Fabric)
13579 );
13580
13581 if cf.language_first {
13582 if let Some(lang) = &cf.language {
13584 if use_multiline {
13585 self.write_newline();
13586 } else {
13587 self.write_space();
13588 }
13589 self.write_keyword("LANGUAGE");
13590 self.write_space();
13591 self.write(lang);
13592 }
13593
13594 if let Some(sql_data) = &cf.sql_data_access {
13596 self.write_space();
13597 match sql_data {
13598 SqlDataAccess::NoSql => self.write_keyword("NO SQL"),
13599 SqlDataAccess::ContainsSql => self.write_keyword("CONTAINS SQL"),
13600 SqlDataAccess::ReadsSqlData => self.write_keyword("READS SQL DATA"),
13601 SqlDataAccess::ModifiesSqlData => self.write_keyword("MODIFIES SQL DATA"),
13602 }
13603 }
13604
13605 if let Some(ref rtb) = cf.returns_table_body {
13606 if use_multiline {
13607 self.write_newline();
13608 } else {
13609 self.write_space();
13610 }
13611 self.write_keyword("RETURNS");
13612 self.write_space();
13613 self.write(rtb);
13614 } else if let Some(return_type) = &cf.return_type {
13615 if use_multiline {
13616 self.write_newline();
13617 } else {
13618 self.write_space();
13619 }
13620 self.write_keyword("RETURNS");
13621 self.write_space();
13622 self.generate_function_return_type(return_type)?;
13623 }
13624 } else {
13625 let is_duckdb = matches!(
13628 self.config.dialect,
13629 Some(crate::dialects::DialectType::DuckDB)
13630 );
13631 if let Some(ref rtb) = cf.returns_table_body {
13632 if !(is_duckdb && rtb.is_empty()) {
13633 if use_multiline {
13634 self.write_newline();
13635 } else {
13636 self.write_space();
13637 }
13638 self.write_keyword("RETURNS");
13639 self.write_space();
13640 self.write(rtb);
13641 }
13642 } else if let Some(return_type) = &cf.return_type {
13643 if !is_duckdb {
13645 let is_table_return = matches!(return_type, crate::expressions::DataType::Custom { ref name } if name.eq_ignore_ascii_case("TABLE"));
13646 if use_multiline {
13647 self.write_newline();
13648 } else {
13649 self.write_space();
13650 }
13651 self.write_keyword("RETURNS");
13652 self.write_space();
13653 if is_table_return {
13654 self.write_keyword("TABLE");
13655 } else {
13656 self.generate_function_return_type(return_type)?;
13657 }
13658 }
13659 }
13660 }
13661
13662 if !cf.property_order.is_empty() {
13664 let is_bigquery = matches!(
13666 self.config.dialect,
13667 Some(crate::dialects::DialectType::BigQuery)
13668 );
13669 let is_postgres = matches!(
13670 self.config.dialect,
13671 Some(crate::dialects::DialectType::PostgreSQL)
13672 );
13673 let property_order = if is_bigquery {
13674 let mut reordered = Vec::new();
13676 let mut has_as = false;
13677 let mut has_options = false;
13678 for prop in &cf.property_order {
13679 match prop {
13680 FunctionPropertyKind::As => has_as = true,
13681 FunctionPropertyKind::Options => has_options = true,
13682 _ => {}
13683 }
13684 }
13685 if has_as && has_options {
13686 for prop in &cf.property_order {
13688 if *prop != FunctionPropertyKind::As
13689 && *prop != FunctionPropertyKind::Options
13690 {
13691 reordered.push(*prop);
13692 }
13693 }
13694 reordered.push(FunctionPropertyKind::Options);
13695 reordered.push(FunctionPropertyKind::As);
13696 reordered
13697 } else {
13698 cf.property_order.clone()
13699 }
13700 } else if is_postgres
13701 && cf.property_order.contains(&FunctionPropertyKind::As)
13702 && cf.property_order.contains(&FunctionPropertyKind::NullInput)
13703 {
13704 let mut reordered: Vec<_> = cf
13705 .property_order
13706 .iter()
13707 .copied()
13708 .filter(|prop| *prop != FunctionPropertyKind::As)
13709 .collect();
13710 reordered.push(FunctionPropertyKind::As);
13711 reordered
13712 } else {
13713 cf.property_order.clone()
13714 };
13715
13716 for prop in &property_order {
13717 match prop {
13718 FunctionPropertyKind::Set => {
13719 self.generate_function_set_options(cf)?;
13720 }
13721 FunctionPropertyKind::As => {
13722 self.generate_function_body(cf)?;
13723 }
13724 FunctionPropertyKind::Using => {
13725 self.generate_function_using_resources(cf)?;
13726 }
13727 FunctionPropertyKind::Language => {
13728 if !cf.language_first {
13729 if let Some(lang) = &cf.language {
13731 let use_multiline = self.config.pretty
13733 && matches!(
13734 self.config.dialect,
13735 Some(crate::dialects::DialectType::BigQuery)
13736 );
13737 if use_multiline {
13738 self.write_newline();
13739 } else {
13740 self.write_space();
13741 }
13742 self.write_keyword("LANGUAGE");
13743 self.write_space();
13744 self.write(lang);
13745 }
13746 }
13747 }
13748 FunctionPropertyKind::Determinism => {
13749 self.generate_function_determinism(cf)?;
13750 }
13751 FunctionPropertyKind::NullInput => {
13752 self.generate_function_null_input(cf)?;
13753 }
13754 FunctionPropertyKind::Security => {
13755 self.generate_function_security(cf)?;
13756 }
13757 FunctionPropertyKind::SqlDataAccess => {
13758 if !cf.language_first {
13759 self.generate_function_sql_data_access(cf)?;
13761 }
13762 }
13763 FunctionPropertyKind::Options => {
13764 if !cf.options.is_empty() {
13765 self.write_space();
13766 self.generate_options_clause(&cf.options)?;
13767 }
13768 }
13769 FunctionPropertyKind::Environment => {
13770 if !cf.environment.is_empty() {
13771 self.write_space();
13772 self.generate_environment_clause(&cf.environment)?;
13773 }
13774 }
13775 FunctionPropertyKind::Handler => {
13776 if let Some(ref h) = cf.handler {
13777 self.write_space();
13778 self.write_keyword("HANDLER");
13779 if cf.handler_uses_eq {
13780 self.write(" = ");
13781 } else {
13782 self.write_space();
13783 }
13784 self.write("'");
13785 self.write(h);
13786 self.write("'");
13787 }
13788 }
13789 FunctionPropertyKind::RuntimeVersion => {
13790 if let Some(ref runtime_version) = cf.runtime_version {
13791 self.write_space();
13792 self.write_keyword("RUNTIME_VERSION");
13793 self.write("='");
13794 self.write(runtime_version);
13795 self.write("'");
13796 }
13797 }
13798 FunctionPropertyKind::Packages => {
13799 if let Some(ref packages) = cf.packages {
13800 self.write_space();
13801 self.write_keyword("PACKAGES");
13802 self.write("=(");
13803 for (i, package) in packages.iter().enumerate() {
13804 if i > 0 {
13805 self.write(", ");
13806 }
13807 self.write("'");
13808 self.write(package);
13809 self.write("'");
13810 }
13811 self.write(")");
13812 }
13813 }
13814 FunctionPropertyKind::ParameterStyle => {
13815 if let Some(ref ps) = cf.parameter_style {
13816 self.write_space();
13817 self.write_keyword("PARAMETER STYLE");
13818 self.write_space();
13819 self.write_keyword(ps);
13820 }
13821 }
13822 }
13823 }
13824
13825 if !cf.options.is_empty() && !cf.property_order.contains(&FunctionPropertyKind::Options)
13827 {
13828 self.write_space();
13829 self.generate_options_clause(&cf.options)?;
13830 }
13831
13832 if !cf.environment.is_empty()
13834 && !cf
13835 .property_order
13836 .contains(&FunctionPropertyKind::Environment)
13837 {
13838 self.write_space();
13839 self.generate_environment_clause(&cf.environment)?;
13840 }
13841 } else {
13842 if matches!(
13845 self.config.dialect,
13846 Some(crate::dialects::DialectType::BigQuery)
13847 ) {
13848 self.generate_function_determinism(cf)?;
13849 }
13850
13851 let use_multiline = self.config.pretty
13853 && matches!(
13854 self.config.dialect,
13855 Some(crate::dialects::DialectType::BigQuery)
13856 );
13857
13858 if !cf.language_first {
13859 if let Some(lang) = &cf.language {
13860 if use_multiline {
13861 self.write_newline();
13862 } else {
13863 self.write_space();
13864 }
13865 self.write_keyword("LANGUAGE");
13866 self.write_space();
13867 self.write(lang);
13868 }
13869
13870 self.generate_function_sql_data_access(cf)?;
13872 }
13873
13874 if !matches!(
13876 self.config.dialect,
13877 Some(crate::dialects::DialectType::BigQuery)
13878 ) {
13879 self.generate_function_determinism(cf)?;
13880 }
13881
13882 self.generate_function_null_input(cf)?;
13883 self.generate_function_security(cf)?;
13884 self.generate_function_set_options(cf)?;
13885
13886 if !cf.options.is_empty() {
13888 self.write_space();
13889 self.generate_options_clause(&cf.options)?;
13890 }
13891
13892 if !cf.environment.is_empty() {
13894 self.write_space();
13895 self.generate_environment_clause(&cf.environment)?;
13896 }
13897
13898 if let Some(ref h) = cf.handler {
13899 self.write_space();
13900 self.write_keyword("HANDLER");
13901 if cf.handler_uses_eq {
13902 self.write(" = ");
13903 } else {
13904 self.write_space();
13905 }
13906 self.write("'");
13907 self.write(h);
13908 self.write("'");
13909 }
13910
13911 if let Some(ref runtime_version) = cf.runtime_version {
13912 self.write_space();
13913 self.write_keyword("RUNTIME_VERSION");
13914 self.write("='");
13915 self.write(runtime_version);
13916 self.write("'");
13917 }
13918
13919 if let Some(ref packages) = cf.packages {
13920 self.write_space();
13921 self.write_keyword("PACKAGES");
13922 self.write("=(");
13923 for (i, package) in packages.iter().enumerate() {
13924 if i > 0 {
13925 self.write(", ");
13926 }
13927 self.write("'");
13928 self.write(package);
13929 self.write("'");
13930 }
13931 self.write(")");
13932 }
13933
13934 self.generate_function_body(cf)?;
13935 self.generate_function_using_resources(cf)?;
13936 }
13937
13938 Ok(())
13939 }
13940
13941 fn generate_function_return_type(&mut self, return_type: &DataType) -> Result<()> {
13942 if matches!(
13943 self.config.dialect,
13944 Some(crate::dialects::DialectType::PostgreSQL)
13945 ) {
13946 if let DataType::Custom { name } = return_type {
13947 if name.eq_ignore_ascii_case("integer") {
13948 self.write_keyword("INT");
13949 return Ok(());
13950 }
13951 }
13952 }
13953
13954 self.generate_data_type(return_type)
13955 }
13956
13957 fn generate_function_set_options(&mut self, cf: &CreateFunction) -> Result<()> {
13959 for opt in &cf.set_options {
13960 self.write_space();
13961 self.write_keyword("SET");
13962 self.write_space();
13963 self.write(&opt.name);
13964 match &opt.value {
13965 FunctionSetValue::Value { value, use_to } => {
13966 if *use_to {
13967 self.write(" TO ");
13968 } else {
13969 self.write(" = ");
13970 }
13971 self.write(value);
13972 }
13973 FunctionSetValue::FromCurrent => {
13974 self.write_space();
13975 self.write_keyword("FROM CURRENT");
13976 }
13977 }
13978 }
13979 Ok(())
13980 }
13981
13982 fn generate_function_using_resources(&mut self, cf: &CreateFunction) -> Result<()> {
13983 if cf.using_resources.is_empty() {
13984 return Ok(());
13985 }
13986
13987 self.write_space();
13988 self.write_keyword("USING");
13989 for resource in &cf.using_resources {
13990 self.write_space();
13991 self.write_keyword(&resource.kind);
13992 self.write_space();
13993 self.generate_string_literal(&resource.uri)?;
13994 }
13995 Ok(())
13996 }
13997
13998 fn generate_function_body(&mut self, cf: &CreateFunction) -> Result<()> {
14000 if let Some(body) = &cf.body {
14001 self.write_space();
14003 let use_multiline = self.config.pretty
14005 && matches!(
14006 self.config.dialect,
14007 Some(crate::dialects::DialectType::BigQuery)
14008 );
14009 match body {
14010 FunctionBody::Block(block) => {
14011 self.write_keyword("AS");
14012 if matches!(
14013 self.config.dialect,
14014 Some(crate::dialects::DialectType::TSQL)
14015 ) {
14016 self.write(" BEGIN ");
14017 self.write(block);
14018 self.write(" END");
14019 } else if matches!(
14020 self.config.dialect,
14021 Some(crate::dialects::DialectType::PostgreSQL)
14022 ) {
14023 self.write(" $$");
14024 self.write(block);
14025 self.write("$$");
14026 } else {
14027 let escaped = self.escape_block_for_single_quote(block);
14029 if use_multiline {
14031 self.write_newline();
14032 } else {
14033 self.write(" ");
14034 }
14035 self.write("'");
14036 self.write(&escaped);
14037 self.write("'");
14038 }
14039 }
14040 FunctionBody::StringLiteral(s) => {
14041 self.write_keyword("AS");
14042 if use_multiline {
14044 self.write_newline();
14045 } else {
14046 self.write(" ");
14047 }
14048 self.generate_string_literal(s)?;
14049 }
14050 FunctionBody::Expression(expr) => {
14051 self.write_keyword("AS");
14052 self.write_space();
14053 self.generate_expression(expr)?;
14054 }
14055 FunctionBody::External(name) => {
14056 self.write_keyword("EXTERNAL NAME");
14057 self.write(" '");
14058 self.write(name);
14059 self.write("'");
14060 }
14061 FunctionBody::Return(expr) => {
14062 if matches!(
14063 self.config.dialect,
14064 Some(crate::dialects::DialectType::DuckDB)
14065 ) {
14066 self.write_keyword("AS");
14068 self.write_space();
14069 let is_table_return = cf.returns_table_body.is_some()
14071 || matches!(&cf.return_type, Some(crate::expressions::DataType::Custom { ref name }) if name.eq_ignore_ascii_case("TABLE"));
14072 if is_table_return {
14073 self.write_keyword("TABLE");
14074 self.write_space();
14075 }
14076 self.generate_expression(expr)?;
14077 } else {
14078 if self.config.create_function_return_as {
14079 self.write_keyword("AS");
14080 if self.config.pretty
14082 && matches!(
14083 self.config.dialect,
14084 Some(crate::dialects::DialectType::TSQL)
14085 | Some(crate::dialects::DialectType::Fabric)
14086 )
14087 {
14088 self.write_newline();
14089 } else {
14090 self.write_space();
14091 }
14092 }
14093 self.write_keyword("RETURN");
14094 self.write_space();
14095 self.generate_expression(expr)?;
14096 }
14097 }
14098 FunctionBody::Statements(stmts) => {
14099 self.write_keyword("AS");
14100 self.write(" BEGIN ");
14101 for (i, stmt) in stmts.iter().enumerate() {
14102 if i > 0 {
14103 self.write(" ");
14104 }
14105 self.generate_expression(stmt)?;
14106 self.write(";");
14107 }
14108 self.write(" END");
14109 }
14110 FunctionBody::RawBlock(text) => {
14111 self.write_newline();
14112 self.write(text);
14113 }
14114 FunctionBody::DollarQuoted { content, tag } => {
14115 self.write_keyword("AS");
14116 self.write(" ");
14117 let supports_dollar_quoting = matches!(
14119 self.config.dialect,
14120 Some(crate::dialects::DialectType::PostgreSQL)
14121 | Some(crate::dialects::DialectType::Databricks)
14122 | Some(crate::dialects::DialectType::Redshift)
14123 | Some(crate::dialects::DialectType::DuckDB)
14124 );
14125 if supports_dollar_quoting {
14126 self.write("$");
14128 if let Some(t) = tag {
14129 self.write(t);
14130 }
14131 self.write("$");
14132 self.write(content);
14133 self.write("$");
14134 if let Some(t) = tag {
14135 self.write(t);
14136 }
14137 self.write("$");
14138 } else {
14139 let escaped = self.escape_block_for_single_quote(content);
14141 self.write("'");
14142 self.write(&escaped);
14143 self.write("'");
14144 }
14145 }
14146 }
14147 }
14148 Ok(())
14149 }
14150
14151 fn generate_function_determinism(&mut self, cf: &CreateFunction) -> Result<()> {
14153 if let Some(det) = cf.deterministic {
14154 self.write_space();
14155 if matches!(
14156 self.config.dialect,
14157 Some(crate::dialects::DialectType::BigQuery)
14158 ) {
14159 if det {
14161 self.write_keyword("DETERMINISTIC");
14162 } else {
14163 self.write_keyword("NOT DETERMINISTIC");
14164 }
14165 } else {
14166 if det {
14168 self.write_keyword("IMMUTABLE");
14169 } else {
14170 self.write_keyword("VOLATILE");
14171 }
14172 }
14173 }
14174 Ok(())
14175 }
14176
14177 fn generate_function_null_input(&mut self, cf: &CreateFunction) -> Result<()> {
14179 if let Some(returns_null) = cf.returns_null_on_null_input {
14180 self.write_space();
14181 if returns_null {
14182 if cf.strict {
14183 self.write_keyword("STRICT");
14184 } else {
14185 self.write_keyword("RETURNS NULL ON NULL INPUT");
14186 }
14187 } else {
14188 self.write_keyword("CALLED ON NULL INPUT");
14189 }
14190 }
14191 Ok(())
14192 }
14193
14194 fn generate_function_security(&mut self, cf: &CreateFunction) -> Result<()> {
14196 if let Some(security) = &cf.security {
14197 self.write_space();
14198 if matches!(
14200 self.config.dialect,
14201 Some(crate::dialects::DialectType::MySQL)
14202 ) {
14203 self.write_keyword("SQL SECURITY");
14204 } else {
14205 self.write_keyword("SECURITY");
14206 }
14207 self.write_space();
14208 match security {
14209 FunctionSecurity::Definer => self.write_keyword("DEFINER"),
14210 FunctionSecurity::Invoker => self.write_keyword("INVOKER"),
14211 FunctionSecurity::None => self.write_keyword("NONE"),
14212 }
14213 }
14214 Ok(())
14215 }
14216
14217 fn generate_function_sql_data_access(&mut self, cf: &CreateFunction) -> Result<()> {
14219 if let Some(sql_data) = &cf.sql_data_access {
14220 self.write_space();
14221 match sql_data {
14222 SqlDataAccess::NoSql => self.write_keyword("NO SQL"),
14223 SqlDataAccess::ContainsSql => self.write_keyword("CONTAINS SQL"),
14224 SqlDataAccess::ReadsSqlData => self.write_keyword("READS SQL DATA"),
14225 SqlDataAccess::ModifiesSqlData => self.write_keyword("MODIFIES SQL DATA"),
14226 }
14227 }
14228 Ok(())
14229 }
14230
14231 fn generate_function_parameters(&mut self, params: &[FunctionParameter]) -> Result<()> {
14232 for (i, param) in params.iter().enumerate() {
14233 if i > 0 {
14234 self.write(", ");
14235 }
14236
14237 if let Some(mode) = ¶m.mode {
14238 if let Some(text) = ¶m.mode_text {
14239 self.write(text);
14240 } else {
14241 match mode {
14242 ParameterMode::In => self.write_keyword("IN"),
14243 ParameterMode::Out => self.write_keyword("OUT"),
14244 ParameterMode::InOut => self.write_keyword("INOUT"),
14245 ParameterMode::Variadic => self.write_keyword("VARIADIC"),
14246 }
14247 }
14248 self.write_space();
14249 }
14250
14251 if let Some(name) = ¶m.name {
14252 self.generate_identifier(name)?;
14253 let skip_type =
14255 matches!(¶m.data_type, DataType::Custom { name } if name.is_empty());
14256 if !skip_type {
14257 self.write_space();
14258 self.generate_data_type(¶m.data_type)?;
14259 }
14260 } else {
14261 self.generate_data_type(¶m.data_type)?;
14262 }
14263
14264 if let Some(default) = ¶m.default {
14265 if self.config.parameter_default_equals {
14266 self.write(" = ");
14267 } else {
14268 self.write(" DEFAULT ");
14269 }
14270 self.generate_expression(default)?;
14271 }
14272 }
14273
14274 Ok(())
14275 }
14276
14277 fn generate_drop_function(&mut self, df: &DropFunction) -> Result<()> {
14278 self.write_keyword("DROP FUNCTION");
14279
14280 if df.if_exists {
14281 self.write_space();
14282 self.write_keyword("IF EXISTS");
14283 }
14284
14285 self.write_space();
14286 self.generate_table(&df.name)?;
14287
14288 if let Some(params) = &df.parameters {
14289 self.write(" (");
14290 for (i, dt) in params.iter().enumerate() {
14291 if i > 0 {
14292 self.write(", ");
14293 }
14294 self.generate_data_type(dt)?;
14295 }
14296 self.write(")");
14297 }
14298
14299 if df.cascade {
14300 self.write_space();
14301 self.write_keyword("CASCADE");
14302 }
14303
14304 Ok(())
14305 }
14306
14307 fn generate_create_procedure(&mut self, cp: &CreateProcedure) -> Result<()> {
14308 self.write_keyword("CREATE");
14309
14310 if cp.or_alter {
14311 self.write_space();
14312 self.write_keyword("OR ALTER");
14313 } else if cp.or_replace {
14314 self.write_space();
14315 self.write_keyword("OR REPLACE");
14316 }
14317
14318 self.write_space();
14319 if cp.use_proc_keyword {
14320 self.write_keyword("PROC");
14321 } else {
14322 self.write_keyword("PROCEDURE");
14323 }
14324
14325 if cp.if_not_exists {
14326 self.write_space();
14327 self.write_keyword("IF NOT EXISTS");
14328 }
14329
14330 self.write_space();
14331 self.generate_table(&cp.name)?;
14332 if cp.has_parens {
14333 self.write("(");
14334 self.generate_function_parameters(&cp.parameters)?;
14335 self.write(")");
14336 } else if !cp.parameters.is_empty() {
14337 self.write_space();
14339 self.generate_function_parameters(&cp.parameters)?;
14340 }
14341
14342 if let Some(return_type) = &cp.return_type {
14344 self.write_space();
14345 self.write_keyword("RETURNS");
14346 self.write_space();
14347 self.generate_data_type(return_type)?;
14348 }
14349
14350 if let Some(execute_as) = &cp.execute_as {
14352 self.write_space();
14353 self.write_keyword("EXECUTE AS");
14354 self.write_space();
14355 self.write_keyword(execute_as);
14356 }
14357
14358 if let Some(lang) = &cp.language {
14359 self.write_space();
14360 self.write_keyword("LANGUAGE");
14361 self.write_space();
14362 self.write(lang);
14363 }
14364
14365 if let Some(security) = &cp.security {
14366 self.write_space();
14367 self.write_keyword("SECURITY");
14368 self.write_space();
14369 match security {
14370 FunctionSecurity::Definer => self.write_keyword("DEFINER"),
14371 FunctionSecurity::Invoker => self.write_keyword("INVOKER"),
14372 FunctionSecurity::None => self.write_keyword("NONE"),
14373 }
14374 }
14375
14376 if !cp.with_options.is_empty() {
14378 self.write_space();
14379 self.write_keyword("WITH");
14380 self.write_space();
14381 for (i, opt) in cp.with_options.iter().enumerate() {
14382 if i > 0 {
14383 self.write(", ");
14384 }
14385 self.write(opt);
14386 }
14387 }
14388
14389 if let Some(body) = &cp.body {
14390 self.write_space();
14391 match body {
14392 FunctionBody::Block(block) => {
14393 self.write_keyword("AS");
14394 if matches!(
14395 self.config.dialect,
14396 Some(crate::dialects::DialectType::TSQL)
14397 ) {
14398 self.write(" BEGIN ");
14399 self.write(block);
14400 self.write(" END");
14401 } else if matches!(
14402 self.config.dialect,
14403 Some(crate::dialects::DialectType::PostgreSQL)
14404 ) {
14405 self.write(" $$");
14406 self.write(block);
14407 self.write("$$");
14408 } else {
14409 let escaped = self.escape_block_for_single_quote(block);
14411 self.write(" '");
14412 self.write(&escaped);
14413 self.write("'");
14414 }
14415 }
14416 FunctionBody::StringLiteral(s) => {
14417 self.write_keyword("AS");
14418 self.write_space();
14419 self.generate_string_literal(s)?;
14420 }
14421 FunctionBody::Expression(expr) => {
14422 self.write_keyword("AS");
14423 self.write_space();
14424 self.generate_expression(expr)?;
14425 }
14426 FunctionBody::External(name) => {
14427 self.write_keyword("EXTERNAL NAME");
14428 self.write(" '");
14429 self.write(name);
14430 self.write("'");
14431 }
14432 FunctionBody::Return(expr) => {
14433 self.write_keyword("RETURN");
14434 self.write_space();
14435 self.generate_expression(expr)?;
14436 }
14437 FunctionBody::Statements(stmts) => {
14438 self.write_keyword("AS");
14439 self.write(" BEGIN ");
14440 for (i, stmt) in stmts.iter().enumerate() {
14441 if i > 0 {
14442 self.write(" ");
14443 }
14444 self.generate_expression(stmt)?;
14445 self.write(";");
14446 }
14447 self.write(" END");
14448 }
14449 FunctionBody::RawBlock(text) => {
14450 self.write_newline();
14451 self.write(text);
14452 }
14453 FunctionBody::DollarQuoted { content, tag } => {
14454 self.write_keyword("AS");
14455 self.write(" ");
14456 let supports_dollar_quoting = matches!(
14458 self.config.dialect,
14459 Some(crate::dialects::DialectType::PostgreSQL)
14460 | Some(crate::dialects::DialectType::Databricks)
14461 | Some(crate::dialects::DialectType::Redshift)
14462 | Some(crate::dialects::DialectType::DuckDB)
14463 );
14464 if supports_dollar_quoting {
14465 self.write("$");
14467 if let Some(t) = tag {
14468 self.write(t);
14469 }
14470 self.write("$");
14471 self.write(content);
14472 self.write("$");
14473 if let Some(t) = tag {
14474 self.write(t);
14475 }
14476 self.write("$");
14477 } else {
14478 let escaped = self.escape_block_for_single_quote(content);
14480 self.write("'");
14481 self.write(&escaped);
14482 self.write("'");
14483 }
14484 }
14485 }
14486 }
14487
14488 Ok(())
14489 }
14490
14491 fn generate_drop_procedure(&mut self, dp: &DropProcedure) -> Result<()> {
14492 self.write_keyword("DROP PROCEDURE");
14493
14494 if dp.if_exists {
14495 self.write_space();
14496 self.write_keyword("IF EXISTS");
14497 }
14498
14499 self.write_space();
14500 self.generate_table(&dp.name)?;
14501
14502 if let Some(params) = &dp.parameters {
14503 self.write(" (");
14504 for (i, dt) in params.iter().enumerate() {
14505 if i > 0 {
14506 self.write(", ");
14507 }
14508 self.generate_data_type(dt)?;
14509 }
14510 self.write(")");
14511 }
14512
14513 if dp.cascade {
14514 self.write_space();
14515 self.write_keyword("CASCADE");
14516 }
14517
14518 Ok(())
14519 }
14520
14521 fn generate_create_sequence(&mut self, cs: &CreateSequence) -> Result<()> {
14522 self.write_keyword("CREATE");
14523
14524 if cs.or_replace {
14525 self.write_space();
14526 self.write_keyword("OR REPLACE");
14527 }
14528
14529 if cs.temporary {
14530 self.write_space();
14531 self.write_keyword("TEMPORARY");
14532 }
14533
14534 self.write_space();
14535 self.write_keyword("SEQUENCE");
14536
14537 if cs.if_not_exists {
14538 self.write_space();
14539 self.write_keyword("IF NOT EXISTS");
14540 }
14541
14542 self.write_space();
14543 self.generate_table(&cs.name)?;
14544
14545 if let Some(as_type) = &cs.as_type {
14547 self.write_space();
14548 self.write_keyword("AS");
14549 self.write_space();
14550 self.generate_data_type(as_type)?;
14551 }
14552
14553 if let Some(comment) = &cs.comment {
14555 self.write_space();
14556 self.write_keyword("COMMENT");
14557 self.write("=");
14558 self.generate_string_literal(comment)?;
14559 }
14560
14561 if !cs.property_order.is_empty() {
14563 for prop in &cs.property_order {
14564 match prop {
14565 SeqPropKind::Start => {
14566 if let Some(start) = cs.start {
14567 self.write_space();
14568 self.write_keyword("START WITH");
14569 self.write(&format!(" {}", start));
14570 }
14571 }
14572 SeqPropKind::Increment => {
14573 if let Some(inc) = cs.increment {
14574 self.write_space();
14575 self.write_keyword("INCREMENT BY");
14576 self.write(&format!(" {}", inc));
14577 }
14578 }
14579 SeqPropKind::Minvalue => {
14580 if let Some(min) = &cs.minvalue {
14581 self.write_space();
14582 match min {
14583 SequenceBound::Value(v) => {
14584 self.write_keyword("MINVALUE");
14585 self.write(&format!(" {}", v));
14586 }
14587 SequenceBound::None => {
14588 self.write_keyword("NO MINVALUE");
14589 }
14590 }
14591 }
14592 }
14593 SeqPropKind::Maxvalue => {
14594 if let Some(max) = &cs.maxvalue {
14595 self.write_space();
14596 match max {
14597 SequenceBound::Value(v) => {
14598 self.write_keyword("MAXVALUE");
14599 self.write(&format!(" {}", v));
14600 }
14601 SequenceBound::None => {
14602 self.write_keyword("NO MAXVALUE");
14603 }
14604 }
14605 }
14606 }
14607 SeqPropKind::Cache => {
14608 if let Some(cache) = cs.cache {
14609 self.write_space();
14610 self.write_keyword("CACHE");
14611 self.write(&format!(" {}", cache));
14612 }
14613 }
14614 SeqPropKind::NoCache => {
14615 self.write_space();
14616 self.write_keyword("NO CACHE");
14617 }
14618 SeqPropKind::NoCacheWord => {
14619 self.write_space();
14620 self.write_keyword("NOCACHE");
14621 }
14622 SeqPropKind::Cycle => {
14623 self.write_space();
14624 self.write_keyword("CYCLE");
14625 }
14626 SeqPropKind::NoCycle => {
14627 self.write_space();
14628 self.write_keyword("NO CYCLE");
14629 }
14630 SeqPropKind::NoCycleWord => {
14631 self.write_space();
14632 self.write_keyword("NOCYCLE");
14633 }
14634 SeqPropKind::OwnedBy => {
14635 if !cs.owned_by_none {
14637 if let Some(owned) = &cs.owned_by {
14638 self.write_space();
14639 self.write_keyword("OWNED BY");
14640 self.write_space();
14641 self.generate_table(owned)?;
14642 }
14643 }
14644 }
14645 SeqPropKind::Order => {
14646 self.write_space();
14647 self.write_keyword("ORDER");
14648 }
14649 SeqPropKind::NoOrder => {
14650 self.write_space();
14651 self.write_keyword("NOORDER");
14652 }
14653 SeqPropKind::Comment => {
14654 }
14656 SeqPropKind::Sharing => {
14657 if let Some(val) = &cs.sharing {
14658 self.write_space();
14659 self.write(&format!("SHARING={}", val));
14660 }
14661 }
14662 SeqPropKind::Keep => {
14663 self.write_space();
14664 self.write_keyword("KEEP");
14665 }
14666 SeqPropKind::NoKeep => {
14667 self.write_space();
14668 self.write_keyword("NOKEEP");
14669 }
14670 SeqPropKind::Scale => {
14671 self.write_space();
14672 self.write_keyword("SCALE");
14673 if let Some(modifier) = &cs.scale_modifier {
14674 if !modifier.is_empty() {
14675 self.write_space();
14676 self.write_keyword(modifier);
14677 }
14678 }
14679 }
14680 SeqPropKind::NoScale => {
14681 self.write_space();
14682 self.write_keyword("NOSCALE");
14683 }
14684 SeqPropKind::Shard => {
14685 self.write_space();
14686 self.write_keyword("SHARD");
14687 if let Some(modifier) = &cs.shard_modifier {
14688 if !modifier.is_empty() {
14689 self.write_space();
14690 self.write_keyword(modifier);
14691 }
14692 }
14693 }
14694 SeqPropKind::NoShard => {
14695 self.write_space();
14696 self.write_keyword("NOSHARD");
14697 }
14698 SeqPropKind::Session => {
14699 self.write_space();
14700 self.write_keyword("SESSION");
14701 }
14702 SeqPropKind::Global => {
14703 self.write_space();
14704 self.write_keyword("GLOBAL");
14705 }
14706 SeqPropKind::NoMinvalueWord => {
14707 self.write_space();
14708 self.write_keyword("NOMINVALUE");
14709 }
14710 SeqPropKind::NoMaxvalueWord => {
14711 self.write_space();
14712 self.write_keyword("NOMAXVALUE");
14713 }
14714 }
14715 }
14716 } else {
14717 if let Some(inc) = cs.increment {
14719 self.write_space();
14720 self.write_keyword("INCREMENT BY");
14721 self.write(&format!(" {}", inc));
14722 }
14723
14724 if let Some(min) = &cs.minvalue {
14725 self.write_space();
14726 match min {
14727 SequenceBound::Value(v) => {
14728 self.write_keyword("MINVALUE");
14729 self.write(&format!(" {}", v));
14730 }
14731 SequenceBound::None => {
14732 self.write_keyword("NO MINVALUE");
14733 }
14734 }
14735 }
14736
14737 if let Some(max) = &cs.maxvalue {
14738 self.write_space();
14739 match max {
14740 SequenceBound::Value(v) => {
14741 self.write_keyword("MAXVALUE");
14742 self.write(&format!(" {}", v));
14743 }
14744 SequenceBound::None => {
14745 self.write_keyword("NO MAXVALUE");
14746 }
14747 }
14748 }
14749
14750 if let Some(start) = cs.start {
14751 self.write_space();
14752 self.write_keyword("START WITH");
14753 self.write(&format!(" {}", start));
14754 }
14755
14756 if let Some(cache) = cs.cache {
14757 self.write_space();
14758 self.write_keyword("CACHE");
14759 self.write(&format!(" {}", cache));
14760 }
14761
14762 if cs.cycle {
14763 self.write_space();
14764 self.write_keyword("CYCLE");
14765 }
14766
14767 if let Some(owned) = &cs.owned_by {
14768 self.write_space();
14769 self.write_keyword("OWNED BY");
14770 self.write_space();
14771 self.generate_table(owned)?;
14772 }
14773 }
14774
14775 Ok(())
14776 }
14777
14778 fn generate_drop_sequence(&mut self, ds: &DropSequence) -> Result<()> {
14779 self.write_keyword("DROP SEQUENCE");
14780
14781 if ds.if_exists {
14782 self.write_space();
14783 self.write_keyword("IF EXISTS");
14784 }
14785
14786 self.write_space();
14787 self.generate_table(&ds.name)?;
14788
14789 if ds.cascade {
14790 self.write_space();
14791 self.write_keyword("CASCADE");
14792 }
14793
14794 Ok(())
14795 }
14796
14797 fn generate_alter_sequence(&mut self, als: &AlterSequence) -> Result<()> {
14798 self.write_keyword("ALTER SEQUENCE");
14799
14800 if als.if_exists {
14801 self.write_space();
14802 self.write_keyword("IF EXISTS");
14803 }
14804
14805 self.write_space();
14806 self.generate_table(&als.name)?;
14807
14808 if let Some(inc) = als.increment {
14809 self.write_space();
14810 self.write_keyword("INCREMENT BY");
14811 self.write(&format!(" {}", inc));
14812 }
14813
14814 if let Some(min) = &als.minvalue {
14815 self.write_space();
14816 match min {
14817 SequenceBound::Value(v) => {
14818 self.write_keyword("MINVALUE");
14819 self.write(&format!(" {}", v));
14820 }
14821 SequenceBound::None => {
14822 self.write_keyword("NO MINVALUE");
14823 }
14824 }
14825 }
14826
14827 if let Some(max) = &als.maxvalue {
14828 self.write_space();
14829 match max {
14830 SequenceBound::Value(v) => {
14831 self.write_keyword("MAXVALUE");
14832 self.write(&format!(" {}", v));
14833 }
14834 SequenceBound::None => {
14835 self.write_keyword("NO MAXVALUE");
14836 }
14837 }
14838 }
14839
14840 if let Some(start) = als.start {
14841 self.write_space();
14842 self.write_keyword("START WITH");
14843 self.write(&format!(" {}", start));
14844 }
14845
14846 if let Some(restart) = &als.restart {
14847 self.write_space();
14848 self.write_keyword("RESTART");
14849 if let Some(val) = restart {
14850 self.write_keyword(" WITH");
14851 self.write(&format!(" {}", val));
14852 }
14853 }
14854
14855 if let Some(cache) = als.cache {
14856 self.write_space();
14857 self.write_keyword("CACHE");
14858 self.write(&format!(" {}", cache));
14859 }
14860
14861 if let Some(cycle) = als.cycle {
14862 self.write_space();
14863 if cycle {
14864 self.write_keyword("CYCLE");
14865 } else {
14866 self.write_keyword("NO CYCLE");
14867 }
14868 }
14869
14870 if let Some(owned) = &als.owned_by {
14871 self.write_space();
14872 self.write_keyword("OWNED BY");
14873 self.write_space();
14874 if let Some(table) = owned {
14875 self.generate_table(table)?;
14876 } else {
14877 self.write_keyword("NONE");
14878 }
14879 }
14880
14881 Ok(())
14882 }
14883
14884 fn generate_create_trigger(&mut self, ct: &CreateTrigger) -> Result<()> {
14885 self.write_keyword("CREATE");
14886
14887 if ct.or_alter {
14888 self.write_space();
14889 self.write_keyword("OR ALTER");
14890 } else if ct.or_replace {
14891 self.write_space();
14892 self.write_keyword("OR REPLACE");
14893 }
14894
14895 if ct.constraint {
14896 self.write_space();
14897 self.write_keyword("CONSTRAINT");
14898 }
14899
14900 self.write_space();
14901 self.write_keyword("TRIGGER");
14902 self.write_space();
14903 self.generate_identifier(&ct.name)?;
14904
14905 self.write_space();
14906 match ct.timing {
14907 TriggerTiming::Before => self.write_keyword("BEFORE"),
14908 TriggerTiming::After => self.write_keyword("AFTER"),
14909 TriggerTiming::InsteadOf => self.write_keyword("INSTEAD OF"),
14910 }
14911
14912 for (i, event) in ct.events.iter().enumerate() {
14914 if i > 0 {
14915 self.write_keyword(" OR");
14916 }
14917 self.write_space();
14918 match event {
14919 TriggerEvent::Insert => self.write_keyword("INSERT"),
14920 TriggerEvent::Update(cols) => {
14921 self.write_keyword("UPDATE");
14922 if let Some(cols) = cols {
14923 self.write_space();
14924 self.write_keyword("OF");
14925 for (j, col) in cols.iter().enumerate() {
14926 if j > 0 {
14927 self.write(",");
14928 }
14929 self.write_space();
14930 self.generate_identifier(col)?;
14931 }
14932 }
14933 }
14934 TriggerEvent::Delete => self.write_keyword("DELETE"),
14935 TriggerEvent::Truncate => self.write_keyword("TRUNCATE"),
14936 }
14937 }
14938
14939 self.write_space();
14940 self.write_keyword("ON");
14941 self.write_space();
14942 self.generate_table(&ct.table)?;
14943
14944 if let Some(ref_clause) = &ct.referencing {
14946 self.write_space();
14947 self.write_keyword("REFERENCING");
14948 if let Some(old_table) = &ref_clause.old_table {
14949 self.write_space();
14950 self.write_keyword("OLD TABLE AS");
14951 self.write_space();
14952 self.generate_identifier(old_table)?;
14953 }
14954 if let Some(new_table) = &ref_clause.new_table {
14955 self.write_space();
14956 self.write_keyword("NEW TABLE AS");
14957 self.write_space();
14958 self.generate_identifier(new_table)?;
14959 }
14960 if let Some(old_row) = &ref_clause.old_row {
14961 self.write_space();
14962 self.write_keyword("OLD ROW AS");
14963 self.write_space();
14964 self.generate_identifier(old_row)?;
14965 }
14966 if let Some(new_row) = &ref_clause.new_row {
14967 self.write_space();
14968 self.write_keyword("NEW ROW AS");
14969 self.write_space();
14970 self.generate_identifier(new_row)?;
14971 }
14972 }
14973
14974 if let Some(deferrable) = ct.deferrable {
14976 self.write_space();
14977 if deferrable {
14978 self.write_keyword("DEFERRABLE");
14979 } else {
14980 self.write_keyword("NOT DEFERRABLE");
14981 }
14982 }
14983
14984 if let Some(initially) = ct.initially_deferred {
14985 self.write_space();
14986 self.write_keyword("INITIALLY");
14987 self.write_space();
14988 if initially {
14989 self.write_keyword("DEFERRED");
14990 } else {
14991 self.write_keyword("IMMEDIATE");
14992 }
14993 }
14994
14995 if let Some(for_each) = ct.for_each {
14996 self.write_space();
14997 self.write_keyword("FOR EACH");
14998 self.write_space();
14999 match for_each {
15000 TriggerForEach::Row => self.write_keyword("ROW"),
15001 TriggerForEach::Statement => self.write_keyword("STATEMENT"),
15002 }
15003 }
15004
15005 if let Some(when) = &ct.when {
15007 self.write_space();
15008 self.write_keyword("WHEN");
15009 if ct.when_paren {
15010 self.write(" (");
15011 self.generate_expression(when)?;
15012 self.write(")");
15013 } else {
15014 self.write_space();
15015 self.generate_expression(when)?;
15016 }
15017 }
15018
15019 self.write_space();
15021 match &ct.body {
15022 TriggerBody::Execute { function, args } => {
15023 self.write_keyword("EXECUTE FUNCTION");
15024 self.write_space();
15025 self.generate_table(function)?;
15026 self.write("(");
15027 for (i, arg) in args.iter().enumerate() {
15028 if i > 0 {
15029 self.write(", ");
15030 }
15031 self.generate_expression(arg)?;
15032 }
15033 self.write(")");
15034 }
15035 TriggerBody::Block(block) => {
15036 self.write_keyword("BEGIN");
15037 self.write_space();
15038 self.write(block);
15039 self.write_space();
15040 self.write_keyword("END");
15041 }
15042 }
15043
15044 Ok(())
15045 }
15046
15047 fn generate_drop_trigger(&mut self, dt: &DropTrigger) -> Result<()> {
15048 self.write_keyword("DROP TRIGGER");
15049
15050 if dt.if_exists {
15051 self.write_space();
15052 self.write_keyword("IF EXISTS");
15053 }
15054
15055 self.write_space();
15056 self.generate_identifier(&dt.name)?;
15057
15058 if let Some(table) = &dt.table {
15059 self.write_space();
15060 self.write_keyword("ON");
15061 self.write_space();
15062 self.generate_table(table)?;
15063 }
15064
15065 if dt.cascade {
15066 self.write_space();
15067 self.write_keyword("CASCADE");
15068 }
15069
15070 Ok(())
15071 }
15072
15073 fn generate_create_type(&mut self, ct: &CreateType) -> Result<()> {
15074 self.write_keyword("CREATE TYPE");
15075
15076 if ct.if_not_exists {
15077 self.write_space();
15078 self.write_keyword("IF NOT EXISTS");
15079 }
15080
15081 self.write_space();
15082 self.generate_table(&ct.name)?;
15083
15084 if let TypeDefinition::Base {
15085 input,
15086 output,
15087 internallength,
15088 } = &ct.definition
15089 {
15090 if input.is_empty() && output.is_empty() && internallength.is_none() {
15091 return Ok(());
15092 }
15093 }
15094
15095 self.write_space();
15096 self.write_keyword("AS");
15097 self.write_space();
15098
15099 match &ct.definition {
15100 TypeDefinition::Enum(values) => {
15101 self.write_keyword("ENUM");
15102 self.write(" (");
15103 for (i, val) in values.iter().enumerate() {
15104 if i > 0 {
15105 self.write(", ");
15106 }
15107 self.write(&format!("'{}'", val));
15108 }
15109 self.write(")");
15110 }
15111 TypeDefinition::Composite(attrs) => {
15112 self.write("(");
15113 for (i, attr) in attrs.iter().enumerate() {
15114 if i > 0 {
15115 self.write(", ");
15116 }
15117 self.generate_identifier(&attr.name)?;
15118 self.write_space();
15119 self.generate_data_type(&attr.data_type)?;
15120 if let Some(collate) = &attr.collate {
15121 self.write_space();
15122 self.write_keyword("COLLATE");
15123 self.write_space();
15124 self.generate_identifier(collate)?;
15125 }
15126 }
15127 self.write(")");
15128 }
15129 TypeDefinition::Range {
15130 subtype,
15131 subtype_diff,
15132 canonical,
15133 } => {
15134 self.write_keyword("RANGE");
15135 self.write(" (");
15136 if matches!(self.config.dialect, Some(DialectType::PostgreSQL)) {
15137 self.write("subtype");
15138 } else {
15139 self.write_keyword("SUBTYPE");
15140 }
15141 self.write(" = ");
15142 self.generate_data_type(subtype)?;
15143 if let Some(diff) = subtype_diff {
15144 self.write(", ");
15145 if matches!(self.config.dialect, Some(DialectType::PostgreSQL)) {
15146 self.write("subtype_diff");
15147 } else {
15148 self.write_keyword("SUBTYPE_DIFF");
15149 }
15150 self.write(" = ");
15151 self.write(diff);
15152 }
15153 if let Some(canon) = canonical {
15154 self.write(", ");
15155 if matches!(self.config.dialect, Some(DialectType::PostgreSQL)) {
15156 self.write("canonical");
15157 } else {
15158 self.write_keyword("CANONICAL");
15159 }
15160 self.write(" = ");
15161 self.write(canon);
15162 }
15163 self.write(")");
15164 }
15165 TypeDefinition::Base {
15166 input,
15167 output,
15168 internallength,
15169 } => {
15170 self.write("(");
15171 self.write_keyword("INPUT");
15172 self.write(" = ");
15173 self.write(input);
15174 self.write(", ");
15175 self.write_keyword("OUTPUT");
15176 self.write(" = ");
15177 self.write(output);
15178 if let Some(len) = internallength {
15179 self.write(", ");
15180 self.write_keyword("INTERNALLENGTH");
15181 self.write(" = ");
15182 self.write(&len.to_string());
15183 }
15184 self.write(")");
15185 }
15186 TypeDefinition::Domain {
15187 base_type,
15188 default,
15189 constraints,
15190 } => {
15191 self.generate_data_type(base_type)?;
15192 if let Some(def) = default {
15193 self.write_space();
15194 self.write_keyword("DEFAULT");
15195 self.write_space();
15196 self.generate_expression(def)?;
15197 }
15198 for constr in constraints {
15199 self.write_space();
15200 if let Some(name) = &constr.name {
15201 self.write_keyword("CONSTRAINT");
15202 self.write_space();
15203 self.generate_identifier(name)?;
15204 self.write_space();
15205 }
15206 self.write_keyword("CHECK");
15207 self.write(" (");
15208 self.generate_expression(&constr.check)?;
15209 self.write(")");
15210 }
15211 }
15212 }
15213
15214 Ok(())
15215 }
15216
15217 fn generate_create_task(&mut self, task: &crate::expressions::CreateTask) -> Result<()> {
15218 self.write_keyword("CREATE");
15219 if task.or_replace {
15220 self.write_space();
15221 self.write_keyword("OR REPLACE");
15222 }
15223 self.write_space();
15224 self.write_keyword("TASK");
15225 if task.if_not_exists {
15226 self.write_space();
15227 self.write_keyword("IF NOT EXISTS");
15228 }
15229 self.write_space();
15230 self.write(&task.name);
15231 if !task.properties.is_empty() {
15232 if !task.properties.starts_with('\n') && !task.properties.starts_with(' ') {
15234 self.write_space();
15235 }
15236 self.write(&task.properties);
15237 }
15238 self.write_space();
15239 self.write_keyword("AS");
15240 self.write_space();
15241 self.generate_expression(&task.body)?;
15242 Ok(())
15243 }
15244
15245 fn generate_try_catch(&mut self, try_catch: &TryCatch) -> Result<()> {
15246 self.write_keyword("BEGIN TRY");
15247 self.generate_tsql_block_statements(&try_catch.try_body)?;
15248 self.write_keyword("END TRY");
15249
15250 if let Some(catch_body) = &try_catch.catch_body {
15251 if self.config.pretty {
15252 self.write_newline();
15253 self.write_indent();
15254 } else {
15255 self.write_space();
15256 }
15257 self.write_keyword("BEGIN CATCH");
15258 self.generate_tsql_block_statements(catch_body)?;
15259 self.write_keyword("END CATCH");
15260 }
15261
15262 Ok(())
15263 }
15264
15265 fn generate_tsql_block_statements(&mut self, statements: &[Expression]) -> Result<()> {
15266 if statements.is_empty() {
15267 self.write_space();
15268 return Ok(());
15269 }
15270
15271 if self.config.pretty {
15272 self.indent_level += 1;
15273 for stmt in statements {
15274 self.write_newline();
15275 self.write_indent();
15276 self.generate_expression(stmt)?;
15277 self.write(";");
15278 }
15279 self.indent_level -= 1;
15280 self.write_newline();
15281 self.write_indent();
15282 } else {
15283 self.write_space();
15284 for (i, stmt) in statements.iter().enumerate() {
15285 if i > 0 {
15286 self.write_space();
15287 }
15288 self.generate_expression(stmt)?;
15289 self.write(";");
15290 }
15291 self.write_space();
15292 }
15293
15294 Ok(())
15295 }
15296
15297 fn generate_drop_type(&mut self, dt: &DropType) -> Result<()> {
15298 self.write_keyword("DROP TYPE");
15299
15300 if dt.if_exists {
15301 self.write_space();
15302 self.write_keyword("IF EXISTS");
15303 }
15304
15305 self.write_space();
15306 self.generate_table(&dt.name)?;
15307
15308 if dt.cascade {
15309 self.write_space();
15310 self.write_keyword("CASCADE");
15311 }
15312
15313 Ok(())
15314 }
15315
15316 fn generate_describe(&mut self, d: &Describe) -> Result<()> {
15317 let saved_athena_hive_context = self.athena_hive_context;
15319 if matches!(
15320 self.config.dialect,
15321 Some(crate::dialects::DialectType::Athena)
15322 ) {
15323 self.athena_hive_context = true;
15324 }
15325
15326 for comment in &d.leading_comments {
15328 self.write_formatted_comment(comment);
15329 self.write(" ");
15330 }
15331
15332 self.write_keyword("DESCRIBE");
15333
15334 if d.extended {
15335 self.write_space();
15336 self.write_keyword("EXTENDED");
15337 } else if d.formatted {
15338 self.write_space();
15339 self.write_keyword("FORMATTED");
15340 }
15341
15342 if let Some(ref style) = d.style {
15344 self.write_space();
15345 self.write_keyword(style);
15346 }
15347
15348 let should_output_kind = match self.config.dialect {
15350 Some(DialectType::Spark) | Some(DialectType::Databricks) | Some(DialectType::Hive) => {
15352 false
15353 }
15354 Some(DialectType::Snowflake) => true,
15356 _ => d.kind.is_some(),
15357 };
15358 if should_output_kind {
15359 if let Some(ref kind) = d.kind {
15360 self.write_space();
15361 self.write_keyword(kind);
15362 } else if matches!(self.config.dialect, Some(DialectType::Snowflake)) {
15363 self.write_space();
15364 self.write_keyword("TABLE");
15365 }
15366 }
15367
15368 self.write_space();
15369 self.generate_expression(&d.target)?;
15370
15371 if !d.params.is_empty() {
15373 self.write("(");
15374 for (i, param) in d.params.iter().enumerate() {
15375 if i > 0 {
15376 self.write(", ");
15377 }
15378 self.write(param);
15379 }
15380 self.write(")");
15381 }
15382
15383 if let Some(ref partition) = d.partition {
15385 self.write_space();
15386 self.generate_expression(partition)?;
15387 }
15388
15389 if d.as_json {
15391 self.write_space();
15392 self.write_keyword("AS JSON");
15393 }
15394
15395 for (name, value) in &d.properties {
15397 self.write_space();
15398 self.write(name);
15399 self.write("=");
15400 self.write(value);
15401 }
15402
15403 self.athena_hive_context = saved_athena_hive_context;
15405
15406 Ok(())
15407 }
15408
15409 fn generate_show(&mut self, s: &Show) -> Result<()> {
15412 self.write_keyword("SHOW");
15413 self.write_space();
15414
15415 let show_terse = s.terse
15418 && !matches!(
15419 s.this.as_str(),
15420 "PRIMARY KEYS" | "UNIQUE KEYS" | "IMPORTED KEYS"
15421 );
15422 if show_terse {
15423 self.write_keyword("TERSE");
15424 self.write_space();
15425 }
15426
15427 self.write_keyword(&s.this);
15429
15430 if let Some(ref target_expr) = s.target {
15432 self.write_space();
15433 self.generate_expression(target_expr)?;
15434 }
15435
15436 if s.history {
15438 self.write_space();
15439 self.write_keyword("HISTORY");
15440 }
15441
15442 if let Some(ref for_target) = s.for_target {
15444 self.write_space();
15445 self.write_keyword("FOR");
15446 self.write_space();
15447 self.generate_expression(for_target)?;
15448 }
15449
15450 use crate::dialects::DialectType;
15454 let is_snowflake = matches!(self.config.dialect, Some(DialectType::Snowflake));
15455 let is_mysql = matches!(self.config.dialect, Some(DialectType::MySQL));
15456 let mysql_tables_scope_as_from = is_mysql
15457 && matches!(s.this.as_str(), "TABLES" | "FULL TABLES")
15458 && s.scope_kind.as_deref() == Some("SCHEMA")
15459 && s.scope.is_some()
15460 && s.from.is_none();
15461
15462 if !is_snowflake && s.from.is_some() {
15463 if let Some(ref scope_kind) = s.scope_kind {
15467 self.write_space();
15468 self.write_keyword("IN");
15469 self.write_space();
15470 self.write_keyword(scope_kind);
15471 if let Some(ref scope) = s.scope {
15472 self.write_space();
15473 self.generate_expression(scope)?;
15474 }
15475 } else if let Some(ref scope) = s.scope {
15476 self.write_space();
15477 self.write_keyword("IN");
15478 self.write_space();
15479 self.generate_expression(scope)?;
15480 }
15481
15482 if let Some(ref from) = s.from {
15484 self.write_space();
15485 self.write_keyword("FROM");
15486 self.write_space();
15487 self.generate_expression(from)?;
15488 }
15489
15490 if let Some(ref db) = s.db {
15492 self.write_space();
15493 self.write_keyword("FROM");
15494 self.write_space();
15495 self.generate_expression(db)?;
15496 }
15497
15498 if let Some(ref like) = s.like {
15500 self.write_space();
15501 self.write_keyword("LIKE");
15502 self.write_space();
15503 self.generate_expression(like)?;
15504 }
15505 } else {
15506 if let Some(ref like) = s.like {
15510 self.write_space();
15511 self.write_keyword("LIKE");
15512 self.write_space();
15513 self.generate_expression(like)?;
15514 }
15515
15516 if mysql_tables_scope_as_from {
15518 self.write_space();
15519 self.write_keyword("FROM");
15520 self.write_space();
15521 self.generate_expression(s.scope.as_ref().unwrap())?;
15522 } else if let Some(ref scope_kind) = s.scope_kind {
15523 self.write_space();
15524 self.write_keyword("IN");
15525 self.write_space();
15526 self.write_keyword(scope_kind);
15527 if let Some(ref scope) = s.scope {
15528 self.write_space();
15529 self.generate_expression(scope)?;
15530 }
15531 } else if let Some(ref scope) = s.scope {
15532 self.write_space();
15533 self.write_keyword("IN");
15534 self.write_space();
15535 self.generate_expression(scope)?;
15536 }
15537 }
15538
15539 if let Some(ref starts_with) = s.starts_with {
15541 self.write_space();
15542 self.write_keyword("STARTS WITH");
15543 self.write_space();
15544 self.generate_expression(starts_with)?;
15545 }
15546
15547 if let Some(ref limit) = s.limit {
15549 self.write_space();
15550 self.generate_limit(limit)?;
15551 }
15552
15553 if is_snowflake {
15555 if let Some(ref from) = s.from {
15556 self.write_space();
15557 self.write_keyword("FROM");
15558 self.write_space();
15559 self.generate_expression(from)?;
15560 }
15561 }
15562
15563 if let Some(ref where_clause) = s.where_clause {
15565 self.write_space();
15566 self.write_keyword("WHERE");
15567 self.write_space();
15568 self.generate_expression(where_clause)?;
15569 }
15570
15571 if let Some(is_mutex) = s.mutex {
15573 self.write_space();
15574 if is_mutex {
15575 self.write_keyword("MUTEX");
15576 } else {
15577 self.write_keyword("STATUS");
15578 }
15579 }
15580
15581 if !s.privileges.is_empty() {
15583 self.write_space();
15584 self.write_keyword("WITH PRIVILEGES");
15585 self.write_space();
15586 for (i, priv_name) in s.privileges.iter().enumerate() {
15587 if i > 0 {
15588 self.write(", ");
15589 }
15590 self.write_keyword(priv_name);
15591 }
15592 }
15593
15594 Ok(())
15595 }
15596
15597 fn generate_literal(&mut self, lit: &Literal) -> Result<()> {
15600 use crate::dialects::DialectType;
15601 match lit {
15602 Literal::String(s) => {
15603 self.generate_string_literal(s)?;
15604 }
15605 Literal::Number(n) => {
15606 if matches!(self.config.dialect, Some(DialectType::MySQL))
15607 && n.len() > 2
15608 && (n.starts_with("0x") || n.starts_with("0X"))
15609 && !n[2..].chars().all(|c| c.is_ascii_hexdigit())
15610 {
15611 return self.generate_identifier(&Identifier {
15612 name: n.clone(),
15613 quoted: true,
15614 trailing_comments: Vec::new(),
15615 span: None,
15616 });
15617 }
15618 let n = if n.contains('_')
15622 && !matches!(
15623 self.config.dialect,
15624 Some(DialectType::ClickHouse)
15625 | Some(DialectType::DuckDB)
15626 | Some(DialectType::PostgreSQL)
15627 | Some(DialectType::Hive)
15628 | Some(DialectType::Spark)
15629 | Some(DialectType::Databricks)
15630 ) {
15631 std::borrow::Cow::Owned(n.replace('_', ""))
15632 } else {
15633 std::borrow::Cow::Borrowed(n.as_str())
15634 };
15635 if n.starts_with('.') {
15638 self.write("0");
15639 self.write(&n);
15640 } else if n.starts_with("-.") {
15641 self.write("-0");
15643 self.write(&n[1..]);
15644 } else {
15645 self.write(&n);
15646 }
15647 }
15648 Literal::HexString(h) => {
15649 match self.config.dialect {
15651 Some(DialectType::TSQL) | Some(DialectType::Fabric) => {
15652 self.write("0x");
15653 self.write(h);
15654 return Ok(());
15655 }
15656 Some(DialectType::Spark)
15657 | Some(DialectType::Databricks)
15658 | Some(DialectType::Teradata) => self.write("X'"),
15659 _ => self.write("x'"),
15660 }
15661 self.write(h);
15662 self.write("'");
15663 }
15664 Literal::HexNumber(h) => {
15665 match self.config.dialect {
15669 Some(DialectType::BigQuery)
15670 | Some(DialectType::ClickHouse)
15671 | Some(DialectType::TSQL)
15672 | Some(DialectType::Fabric) => {
15673 self.write("0x");
15674 self.write(h);
15675 }
15676 _ => {
15677 if let Ok(val) = u64::from_str_radix(h, 16) {
15679 self.write(&val.to_string());
15680 } else {
15681 self.write("0x");
15683 self.write(h);
15684 }
15685 }
15686 }
15687 }
15688 Literal::BitString(b) => {
15689 self.write("B'");
15691 self.write(b);
15692 self.write("'");
15693 }
15694 Literal::ByteString(b) => {
15695 self.write("b'");
15697 self.write_escaped_byte_string(b);
15699 self.write("'");
15700 }
15701 Literal::NationalString(s) => {
15702 let keep_n_prefix = matches!(
15705 self.config.dialect,
15706 Some(DialectType::TSQL)
15707 | Some(DialectType::Oracle)
15708 | Some(DialectType::MySQL)
15709 | None
15710 );
15711 if keep_n_prefix {
15712 self.write("N'");
15713 } else {
15714 self.write("'");
15715 }
15716 self.write(s);
15717 self.write("'");
15718 }
15719 Literal::Date(d) => {
15720 self.generate_date_literal(d)?;
15721 }
15722 Literal::Time(t) => {
15723 self.generate_time_literal(t)?;
15724 }
15725 Literal::Timestamp(ts) => {
15726 self.generate_timestamp_literal(ts)?;
15727 }
15728 Literal::Datetime(dt) => {
15729 self.generate_datetime_literal(dt)?;
15730 }
15731 Literal::TripleQuotedString(s, _quote_char) => {
15732 if matches!(
15734 self.config.dialect,
15735 Some(crate::dialects::DialectType::BigQuery)
15736 | Some(crate::dialects::DialectType::DuckDB)
15737 | Some(crate::dialects::DialectType::Snowflake)
15738 | Some(crate::dialects::DialectType::Spark)
15739 | Some(crate::dialects::DialectType::Hive)
15740 | Some(crate::dialects::DialectType::Presto)
15741 | Some(crate::dialects::DialectType::Trino)
15742 | Some(crate::dialects::DialectType::PostgreSQL)
15743 | Some(crate::dialects::DialectType::MySQL)
15744 | Some(crate::dialects::DialectType::Redshift)
15745 | Some(crate::dialects::DialectType::TSQL)
15746 | Some(crate::dialects::DialectType::Oracle)
15747 | Some(crate::dialects::DialectType::ClickHouse)
15748 | Some(crate::dialects::DialectType::Databricks)
15749 | Some(crate::dialects::DialectType::SQLite)
15750 ) {
15751 self.generate_string_literal(s)?;
15752 } else {
15753 let quotes = format!("{0}{0}{0}", _quote_char);
15755 self.write("es);
15756 self.write(s);
15757 self.write("es);
15758 }
15759 }
15760 Literal::EscapeString(s) => {
15761 use crate::dialects::DialectType;
15765 let content = if let Some(c) = s.strip_prefix("e:") {
15766 c
15767 } else if let Some(c) = s.strip_prefix("E:") {
15768 c
15769 } else {
15770 s.as_str()
15771 };
15772
15773 if matches!(
15775 self.config.dialect,
15776 Some(DialectType::MySQL) | Some(DialectType::TiDB)
15777 ) {
15778 self.write("'");
15779 self.write(&content.replace('\'', "''"));
15780 self.write("'");
15781 } else {
15782 let prefix = if matches!(
15784 self.config.dialect,
15785 Some(DialectType::SingleStore)
15786 | Some(DialectType::DuckDB)
15787 | Some(DialectType::PostgreSQL)
15788 | Some(DialectType::CockroachDB)
15789 | Some(DialectType::Materialize)
15790 | Some(DialectType::RisingWave)
15791 ) {
15792 "e'"
15793 } else {
15794 "E'"
15795 };
15796
15797 let normalized = content.replace("\\'", "''");
15799 self.write(prefix);
15800 self.write(&normalized);
15801 self.write("'");
15802 }
15803 }
15804 Literal::DollarString(s) => {
15805 use crate::dialects::DialectType;
15808 let (_tag, content) = crate::tokens::parse_dollar_string_token(s);
15810 let escape_backslash = matches!(
15812 self.config.dialect,
15813 Some(DialectType::ClickHouse) | Some(DialectType::Snowflake)
15814 );
15815 let use_backslash_quote =
15819 matches!(self.config.dialect, Some(DialectType::Snowflake));
15820
15821 let mut escaped = String::with_capacity(content.len() + 4);
15822 for ch in content.chars() {
15823 if escape_backslash && ch == '\\' {
15824 escaped.push('\\');
15826 escaped.push('\\');
15827 } else if ch == '\'' {
15828 if use_backslash_quote {
15829 escaped.push('\\');
15830 escaped.push('\'');
15831 } else {
15832 escaped.push('\'');
15833 escaped.push('\'');
15834 }
15835 } else {
15836 escaped.push(ch);
15837 }
15838 }
15839 self.write("'");
15840 self.write(&escaped);
15841 self.write("'");
15842 }
15843 Literal::RawString(s) => {
15844 use crate::dialects::DialectType;
15850
15851 let escape_backslash = matches!(
15853 self.config.dialect,
15854 Some(DialectType::BigQuery)
15855 | Some(DialectType::MySQL)
15856 | Some(DialectType::SingleStore)
15857 | Some(DialectType::TiDB)
15858 | Some(DialectType::Hive)
15859 | Some(DialectType::Spark)
15860 | Some(DialectType::Databricks)
15861 | Some(DialectType::Drill)
15862 | Some(DialectType::Snowflake)
15863 | Some(DialectType::Redshift)
15864 | Some(DialectType::ClickHouse)
15865 );
15866
15867 let backslash_escapes_quote = matches!(
15870 self.config.dialect,
15871 Some(DialectType::BigQuery)
15872 | Some(DialectType::Hive)
15873 | Some(DialectType::Spark)
15874 | Some(DialectType::Databricks)
15875 | Some(DialectType::Drill)
15876 | Some(DialectType::Snowflake)
15877 | Some(DialectType::Redshift)
15878 );
15879
15880 let supports_escape_sequences = escape_backslash;
15883
15884 let mut escaped = String::with_capacity(s.len() + 4);
15885 for ch in s.chars() {
15886 if escape_backslash && ch == '\\' {
15887 escaped.push('\\');
15889 escaped.push('\\');
15890 } else if ch == '\'' {
15891 if backslash_escapes_quote {
15892 escaped.push('\\');
15894 escaped.push('\'');
15895 } else {
15896 escaped.push('\'');
15898 escaped.push('\'');
15899 }
15900 } else if supports_escape_sequences {
15901 match ch {
15904 '\n' => {
15905 escaped.push('\\');
15906 escaped.push('n');
15907 }
15908 '\r' => {
15909 escaped.push('\\');
15910 escaped.push('r');
15911 }
15912 '\t' => {
15913 escaped.push('\\');
15914 escaped.push('t');
15915 }
15916 '\x07' => {
15917 escaped.push('\\');
15918 escaped.push('a');
15919 }
15920 '\x08' => {
15921 escaped.push('\\');
15922 escaped.push('b');
15923 }
15924 '\x0C' => {
15925 escaped.push('\\');
15926 escaped.push('f');
15927 }
15928 '\x0B' => {
15929 escaped.push('\\');
15930 escaped.push('v');
15931 }
15932 _ => escaped.push(ch),
15933 }
15934 } else {
15935 escaped.push(ch);
15936 }
15937 }
15938 self.write("'");
15939 self.write(&escaped);
15940 self.write("'");
15941 }
15942 }
15943 Ok(())
15944 }
15945
15946 fn generate_date_literal(&mut self, d: &str) -> Result<()> {
15948 use crate::dialects::DialectType;
15949
15950 match self.config.dialect {
15951 Some(DialectType::TSQL) | Some(DialectType::Fabric) => {
15953 self.write("CAST('");
15954 self.write(d);
15955 self.write("' AS DATE)");
15956 }
15957 Some(DialectType::BigQuery) => {
15960 self.write("CAST('");
15961 self.write(d);
15962 self.write("' AS DATE)");
15963 }
15964 Some(DialectType::Exasol) => {
15967 self.write("CAST('");
15968 self.write(d);
15969 self.write("' AS DATE)");
15970 }
15971 Some(DialectType::Snowflake) => {
15974 self.write("CAST('");
15975 self.write(d);
15976 self.write("' AS DATE)");
15977 }
15978 Some(DialectType::PostgreSQL)
15980 | Some(DialectType::MySQL)
15981 | Some(DialectType::SingleStore)
15982 | Some(DialectType::TiDB)
15983 | Some(DialectType::Redshift) => {
15984 self.write("CAST('");
15985 self.write(d);
15986 self.write("' AS DATE)");
15987 }
15988 Some(DialectType::DuckDB)
15990 | Some(DialectType::Presto)
15991 | Some(DialectType::Trino)
15992 | Some(DialectType::Athena)
15993 | Some(DialectType::Spark)
15994 | Some(DialectType::Databricks)
15995 | Some(DialectType::Hive) => {
15996 self.write("CAST('");
15997 self.write(d);
15998 self.write("' AS DATE)");
15999 }
16000 Some(DialectType::Oracle) => {
16002 self.write("TO_DATE('");
16003 self.write(d);
16004 self.write("', 'YYYY-MM-DD')");
16005 }
16006 _ => {
16008 self.write_keyword("DATE");
16009 self.write(" '");
16010 self.write(d);
16011 self.write("'");
16012 }
16013 }
16014 Ok(())
16015 }
16016
16017 fn generate_time_literal(&mut self, t: &str) -> Result<()> {
16019 use crate::dialects::DialectType;
16020
16021 match self.config.dialect {
16022 Some(DialectType::TSQL) => {
16024 self.write("CAST('");
16025 self.write(t);
16026 self.write("' AS TIME)");
16027 }
16028 Some(DialectType::Fabric) => {
16029 self.write("CAST('");
16030 self.write(t);
16031 self.write("' AS TIME(6))");
16032 }
16033 _ => {
16035 self.write_keyword("TIME");
16036 self.write(" '");
16037 self.write(t);
16038 self.write("'");
16039 }
16040 }
16041 Ok(())
16042 }
16043
16044 fn generate_dremio_date_expression(&mut self, expr: &Expression) -> Result<()> {
16046 use crate::expressions::Literal;
16047
16048 match expr {
16049 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Date(_)) => {
16050 let Literal::Date(d) = lit.as_ref() else {
16051 unreachable!()
16052 };
16053 self.write("CAST('");
16055 self.write(d);
16056 self.write("' AS DATE)");
16057 }
16058 _ => {
16059 self.generate_expression(expr)?;
16061 }
16062 }
16063 Ok(())
16064 }
16065
16066 fn generate_timestamp_literal(&mut self, ts: &str) -> Result<()> {
16068 use crate::dialects::DialectType;
16069
16070 match self.config.dialect {
16071 Some(DialectType::TSQL) => {
16073 self.write("CAST('");
16074 self.write(ts);
16075 self.write("' AS DATETIME2)");
16076 }
16077 Some(DialectType::BigQuery) => {
16080 self.write("CAST('");
16081 self.write(ts);
16082 self.write("' AS TIMESTAMP)");
16083 }
16084 Some(DialectType::Snowflake) => {
16087 self.write("CAST('");
16088 self.write(ts);
16089 self.write("' AS TIMESTAMP)");
16090 }
16091 Some(DialectType::Dremio) => {
16094 self.write("CAST('");
16095 self.write(ts);
16096 self.write("' AS TIMESTAMP)");
16097 }
16098 Some(DialectType::Exasol) => {
16101 self.write("CAST('");
16102 self.write(ts);
16103 self.write("' AS TIMESTAMP)");
16104 }
16105 Some(DialectType::Oracle) => {
16108 self.write("TO_TIMESTAMP('");
16109 self.write(ts);
16110 self.write("', 'YYYY-MM-DD HH24:MI:SS.FF6')");
16111 }
16112 Some(DialectType::Presto) | Some(DialectType::Trino) => {
16114 if Self::timestamp_has_timezone(ts) {
16115 self.write("CAST('");
16116 self.write(ts);
16117 self.write("' AS TIMESTAMP WITH TIME ZONE)");
16118 } else {
16119 self.write("CAST('");
16120 self.write(ts);
16121 self.write("' AS TIMESTAMP)");
16122 }
16123 }
16124 Some(DialectType::ClickHouse) => {
16126 self.write("CAST('");
16127 self.write(ts);
16128 self.write("' AS Nullable(DateTime))");
16129 }
16130 Some(DialectType::Spark) => {
16132 self.write("CAST('");
16133 self.write(ts);
16134 self.write("' AS TIMESTAMP)");
16135 }
16136 Some(DialectType::Redshift) => {
16139 if ts == "epoch" {
16140 self.write_keyword("TIMESTAMP");
16141 self.write(" '");
16142 self.write(ts);
16143 self.write("'");
16144 } else {
16145 self.write("CAST('");
16146 self.write(ts);
16147 self.write("' AS TIMESTAMP)");
16148 }
16149 }
16150 Some(DialectType::PostgreSQL)
16152 | Some(DialectType::Hive)
16153 | Some(DialectType::SQLite)
16154 | Some(DialectType::DuckDB)
16155 | Some(DialectType::Athena)
16156 | Some(DialectType::Drill)
16157 | Some(DialectType::Teradata) => {
16158 self.write("CAST('");
16159 self.write(ts);
16160 self.write("' AS TIMESTAMP)");
16161 }
16162 Some(DialectType::MySQL) | Some(DialectType::StarRocks) | Some(DialectType::Doris) => {
16164 self.write("CAST('");
16165 self.write(ts);
16166 self.write("' AS DATETIME)");
16167 }
16168 Some(DialectType::Databricks) => {
16170 self.write("CAST('");
16171 self.write(ts);
16172 self.write("' AS TIMESTAMP_NTZ)");
16173 }
16174 _ => {
16176 self.write_keyword("TIMESTAMP");
16177 self.write(" '");
16178 self.write(ts);
16179 self.write("'");
16180 }
16181 }
16182 Ok(())
16183 }
16184
16185 fn timestamp_has_timezone(ts: &str) -> bool {
16188 let ts_lower = ts.to_ascii_lowercase();
16192
16193 let continent_prefixes = [
16195 "africa/",
16196 "america/",
16197 "antarctica/",
16198 "arctic/",
16199 "asia/",
16200 "atlantic/",
16201 "australia/",
16202 "europe/",
16203 "indian/",
16204 "pacific/",
16205 "etc/",
16206 "brazil/",
16207 "canada/",
16208 "chile/",
16209 "mexico/",
16210 "us/",
16211 ];
16212
16213 for prefix in &continent_prefixes {
16214 if ts_lower.contains(prefix) {
16215 return true;
16216 }
16217 }
16218
16219 let tz_abbrevs = [
16222 " utc", " gmt", " cet", " cest", " eet", " eest", " wet", " west", " est", " edt",
16223 " cst", " cdt", " mst", " mdt", " pst", " pdt", " ist", " bst", " jst", " kst", " hkt",
16224 " sgt", " aest", " aedt", " acst", " acdt", " awst",
16225 ];
16226
16227 for abbrev in &tz_abbrevs {
16228 if ts_lower.ends_with(abbrev) {
16229 return true;
16230 }
16231 }
16232
16233 let trimmed = ts.trim();
16237 if let Some(last_space) = trimmed.rfind(' ') {
16238 let suffix = &trimmed[last_space + 1..];
16239 if (suffix.starts_with('+') || suffix.starts_with('-')) && suffix.len() > 1 {
16240 let rest = &suffix[1..];
16242 if rest.chars().all(|c| c.is_ascii_digit() || c == ':') {
16243 return true;
16244 }
16245 }
16246 }
16247
16248 false
16249 }
16250
16251 fn generate_datetime_literal(&mut self, dt: &str) -> Result<()> {
16253 use crate::dialects::DialectType;
16254
16255 match self.config.dialect {
16256 Some(DialectType::BigQuery) => {
16259 self.write("CAST('");
16260 self.write(dt);
16261 self.write("' AS DATETIME)");
16262 }
16263 Some(DialectType::DuckDB) => {
16265 self.write("CAST('");
16266 self.write(dt);
16267 self.write("' AS TIMESTAMP)");
16268 }
16269 _ => {
16272 self.write_keyword("DATETIME");
16273 self.write(" '");
16274 self.write(dt);
16275 self.write("'");
16276 }
16277 }
16278 Ok(())
16279 }
16280
16281 fn generate_string_literal(&mut self, s: &str) -> Result<()> {
16283 use crate::dialects::DialectType;
16284
16285 match self.config.dialect {
16286 Some(DialectType::Hive) | Some(DialectType::Spark) | Some(DialectType::Databricks) => {
16290 self.write("'");
16292 for c in s.chars() {
16293 match c {
16294 '\'' => self.write("\\'"),
16295 '\\' => self.write("\\\\"),
16296 '\n' => self.write("\\n"),
16297 '\r' => self.write("\\r"),
16298 '\t' => self.write("\\t"),
16299 '\0' => self.write("\\0"),
16300 _ => self.output.push(c),
16301 }
16302 }
16303 self.write("'");
16304 }
16305 Some(DialectType::Drill) => {
16306 self.write("'");
16309 for c in s.chars() {
16310 match c {
16311 '\'' => self.write("''"),
16312 '\\' => self.write("\\\\"),
16313 '\n' => self.write("\\n"),
16314 '\r' => self.write("\\r"),
16315 '\t' => self.write("\\t"),
16316 '\0' => self.write("\\0"),
16317 _ => self.output.push(c),
16318 }
16319 }
16320 self.write("'");
16321 }
16322 Some(DialectType::MySQL) | Some(DialectType::SingleStore) | Some(DialectType::TiDB) => {
16323 self.write("'");
16324 for c in s.chars() {
16325 match c {
16326 '\'' => self.write("''"),
16328 '\\' => self.write("\\\\"),
16329 '\n' => self.write("\\n"),
16330 '\r' => self.write("\\r"),
16331 '\t' => self.write("\\t"),
16332 '\0' => self.output.push('\0'),
16334 _ => self.output.push(c),
16335 }
16336 }
16337 self.write("'");
16338 }
16339 Some(DialectType::BigQuery) => {
16341 self.write("'");
16342 for c in s.chars() {
16343 match c {
16344 '\'' => self.write("\\'"),
16345 '\\' => self.write("\\\\"),
16346 '\n' => self.write("\\n"),
16347 '\r' => self.write("\\r"),
16348 '\t' => self.write("\\t"),
16349 '\0' => self.write("\\0"),
16350 '\x07' => self.write("\\a"),
16351 '\x08' => self.write("\\b"),
16352 '\x0C' => self.write("\\f"),
16353 '\x0B' => self.write("\\v"),
16354 _ => self.output.push(c),
16355 }
16356 }
16357 self.write("'");
16358 }
16359 Some(DialectType::Athena) => {
16363 if self.athena_hive_context {
16364 self.write("'");
16366 for c in s.chars() {
16367 match c {
16368 '\'' => self.write("\\'"),
16369 '\\' => self.write("\\\\"),
16370 '\n' => self.write("\\n"),
16371 '\r' => self.write("\\r"),
16372 '\t' => self.write("\\t"),
16373 '\0' => self.write("\\0"),
16374 _ => self.output.push(c),
16375 }
16376 }
16377 self.write("'");
16378 } else {
16379 self.write("'");
16381 for c in s.chars() {
16382 match c {
16383 '\'' => self.write("''"),
16384 _ => self.output.push(c),
16386 }
16387 }
16388 self.write("'");
16389 }
16390 }
16391 Some(DialectType::Snowflake) => {
16393 self.write("'");
16394 for c in s.chars() {
16395 match c {
16396 '\'' => self.write("\\'"),
16397 '\\' => self.write("\\\\"),
16398 '\0' => self.write("\\x00"),
16399 '\x08' => self.write("\\b"),
16400 '\x0C' => self.write("\\f"),
16401 '\n' => self.write("\\n"),
16402 '\r' => self.write("\\r"),
16403 '\t' => self.write("\\t"),
16404 _ => self.output.push(c),
16405 }
16406 }
16407 self.write("'");
16408 }
16409 Some(DialectType::PostgreSQL) => {
16411 self.write("'");
16412 for c in s.chars() {
16413 match c {
16414 '\'' => self.write("''"),
16415 _ => self.output.push(c),
16416 }
16417 }
16418 self.write("'");
16419 }
16420 Some(DialectType::Redshift) => {
16422 self.write("'");
16423 for c in s.chars() {
16424 match c {
16425 '\'' => self.write("\\'"),
16426 _ => self.output.push(c),
16427 }
16428 }
16429 self.write("'");
16430 }
16431 Some(DialectType::Oracle) => {
16433 self.write("'");
16434 for ch in s.chars() {
16435 if ch == '\'' {
16436 self.output.push_str("''");
16437 } else {
16438 self.output.push(ch);
16439 }
16440 }
16441 self.write("'");
16442 }
16443 Some(DialectType::ClickHouse) => {
16446 self.write("'");
16447 for c in s.chars() {
16448 match c {
16449 '\'' => self.write("''"),
16450 '\\' => self.write("\\\\"),
16451 '\n' => self.write("\\n"),
16452 '\r' => self.write("\\r"),
16453 '\t' => self.write("\\t"),
16454 '\0' => self.write("\\0"),
16455 '\x07' => self.write("\\a"),
16456 '\x08' => self.write("\\b"),
16457 '\x0C' => self.write("\\f"),
16458 '\x0B' => self.write("\\v"),
16459 c if c.is_control() || (c as u32) < 0x20 => {
16461 let byte = c as u32;
16462 if byte < 256 {
16463 self.write(&format!("\\x{:02X}", byte));
16464 } else {
16465 self.output.push(c);
16466 }
16467 }
16468 _ => self.output.push(c),
16469 }
16470 }
16471 self.write("'");
16472 }
16473 _ => {
16476 self.write("'");
16477 for ch in s.chars() {
16478 if ch == '\'' {
16479 self.output.push_str("''");
16480 } else {
16481 self.output.push(ch);
16482 }
16483 }
16484 self.write("'");
16485 }
16486 }
16487 Ok(())
16488 }
16489
16490 fn write_escaped_byte_string(&mut self, s: &str) {
16493 for c in s.chars() {
16494 match c {
16495 '\'' => self.write("\\'"),
16497 '\\' => self.write("\\\\"),
16499 _ if !c.is_control() => self.output.push(c),
16501 _ => {
16503 let byte = c as u32;
16504 if byte < 256 {
16505 self.write(&format!("\\x{:02x}", byte));
16506 } else {
16507 for b in c.to_string().as_bytes() {
16509 self.write(&format!("\\x{:02x}", b));
16510 }
16511 }
16512 }
16513 }
16514 }
16515 }
16516
16517 fn generate_boolean(&mut self, b: &BooleanLiteral) -> Result<()> {
16518 use crate::dialects::DialectType;
16519
16520 match self.config.dialect {
16522 Some(DialectType::TSQL) => {
16525 self.write(if b.value { "1" } else { "0" });
16526 }
16527 Some(DialectType::Oracle) => {
16529 self.write(if b.value { "1" } else { "0" });
16530 }
16531 Some(DialectType::MySQL) => {
16533 self.write_keyword(if b.value { "TRUE" } else { "FALSE" });
16534 }
16535 _ => {
16537 self.write_keyword(if b.value { "TRUE" } else { "FALSE" });
16538 }
16539 }
16540 Ok(())
16541 }
16542
16543 fn generate_alias_identifier(&mut self, id: &Identifier) -> Result<()> {
16546 let name = &id.name;
16547 let quote_style = &self.config.identifier_quote_style;
16548
16549 let needs_quoting = id.quoted || self.is_reserved_keyword(name);
16553
16554 let output_name = if self.config.normalize_identifiers && !id.quoted {
16556 name.to_ascii_lowercase()
16557 } else {
16558 name.to_string()
16559 };
16560
16561 if needs_quoting {
16562 let quote_style = if matches!(self.config.dialect, Some(DialectType::ClickHouse))
16563 && matches!(self.config.source_dialect, Some(DialectType::ClickHouse))
16564 && quote_style.start == '"'
16565 && output_name.contains('"')
16566 {
16567 &IdentifierQuoteStyle::BACKTICK
16568 } else {
16569 quote_style
16570 };
16571 let escaped_name = if quote_style.start == quote_style.end {
16573 output_name.replace(
16574 quote_style.end,
16575 &format!("{}{}", quote_style.end, quote_style.end),
16576 )
16577 } else {
16578 output_name.replace(
16579 quote_style.end,
16580 &format!("{}{}", quote_style.end, quote_style.end),
16581 )
16582 };
16583 self.write(&format!(
16584 "{}{}{}",
16585 quote_style.start, escaped_name, quote_style.end
16586 ));
16587 } else {
16588 self.write(&output_name);
16589 }
16590
16591 for comment in &id.trailing_comments {
16593 self.write(" ");
16594 self.write_formatted_comment(comment);
16595 }
16596 Ok(())
16597 }
16598
16599 fn generate_identifier(&mut self, id: &Identifier) -> Result<()> {
16600 use crate::dialects::DialectType;
16601
16602 let name = &id.name;
16603
16604 let quote_style = if matches!(self.config.dialect, Some(DialectType::Athena))
16606 && self.athena_hive_context
16607 {
16608 &IdentifierQuoteStyle::BACKTICK
16609 } else {
16610 &self.config.identifier_quote_style
16611 };
16612
16613 let starts_with_digit = name.chars().next().map_or(false, |c| c.is_ascii_digit());
16620 let needs_digit_quoting = starts_with_digit
16621 && !self.config.identifiers_can_start_with_digit
16622 && self.config.dialect.is_some();
16623 let mysql_invalid_hex_identifier = matches!(self.config.dialect, Some(DialectType::MySQL))
16624 && name.len() > 2
16625 && (name.starts_with("0x") || name.starts_with("0X"))
16626 && !name[2..].chars().all(|c| c.is_ascii_hexdigit());
16627 let clickhouse_unsafe_identifier =
16628 matches!(self.config.dialect, Some(DialectType::ClickHouse))
16629 && matches!(self.config.source_dialect, Some(DialectType::ClickHouse))
16630 && !name.starts_with('{')
16631 && !name.contains('(')
16632 && !name.contains(')')
16633 && name != "?"
16634 && name
16635 .chars()
16636 .any(|c| !(c.is_ascii_alphanumeric() || c == '_'));
16637 let needs_quoting = id.quoted
16638 || self.is_reserved_keyword(name)
16639 || self.config.always_quote_identifiers
16640 || needs_digit_quoting
16641 || mysql_invalid_hex_identifier
16642 || clickhouse_unsafe_identifier;
16643
16644 let (base_name, suffix) = if needs_quoting {
16647 if let Some(paren_pos) = name.find('(') {
16649 let base = &name[..paren_pos];
16650 let rest = &name[paren_pos..];
16651 if rest.starts_with('(')
16653 && (rest.ends_with(')') || rest.ends_with(") ASC") || rest.ends_with(") DESC"))
16654 {
16655 let close_paren = rest.find(')').unwrap_or(rest.len());
16657 let inside = &rest[1..close_paren];
16658 if inside.chars().all(|c| c.is_ascii_digit()) {
16659 (base.to_string(), rest.to_string())
16660 } else {
16661 (name.to_string(), String::new())
16662 }
16663 } else {
16664 (name.to_string(), String::new())
16665 }
16666 } else if name.ends_with(" ASC") {
16667 let base = &name[..name.len() - 4];
16668 (base.to_string(), " ASC".to_string())
16669 } else if name.ends_with(" DESC") {
16670 let base = &name[..name.len() - 5];
16671 (base.to_string(), " DESC".to_string())
16672 } else {
16673 (name.to_string(), String::new())
16674 }
16675 } else {
16676 (name.to_string(), String::new())
16677 };
16678
16679 let output_name = if self.config.normalize_identifiers && !id.quoted {
16683 base_name.to_ascii_lowercase()
16684 } else if matches!(self.config.dialect, Some(DialectType::Exasol))
16685 && !id.quoted
16686 && self.is_reserved_keyword(name)
16687 {
16688 base_name.to_ascii_uppercase()
16691 } else {
16692 base_name
16693 };
16694
16695 if needs_quoting {
16696 let escaped_name = if quote_style.start == quote_style.end {
16698 output_name.replace(
16700 quote_style.end,
16701 &format!("{}{}", quote_style.end, quote_style.end),
16702 )
16703 } else {
16704 output_name.replace(
16706 quote_style.end,
16707 &format!("{}{}", quote_style.end, quote_style.end),
16708 )
16709 };
16710 self.write(&format!(
16711 "{}{}{}{}",
16712 quote_style.start, escaped_name, quote_style.end, suffix
16713 ));
16714 } else {
16715 self.write(&output_name);
16716 }
16717
16718 for comment in &id.trailing_comments {
16720 self.write(" ");
16721 self.write_formatted_comment(comment);
16722 }
16723 Ok(())
16724 }
16725
16726 fn generate_column(&mut self, col: &Column) -> Result<()> {
16727 use crate::dialects::DialectType;
16728
16729 if let Some(table) = &col.table {
16730 let is_exasol_local_prefix = matches!(self.config.dialect, Some(DialectType::Exasol))
16734 && !table.quoted
16735 && table.name.eq_ignore_ascii_case("LOCAL");
16736
16737 if is_exasol_local_prefix {
16738 self.write("LOCAL");
16740 } else {
16741 self.generate_identifier(table)?;
16742 }
16743 self.write(".");
16744 }
16745 let postgres_qualified_keyword = col.table.is_some()
16746 && matches!(self.config.dialect, Some(DialectType::PostgreSQL))
16747 && !col.name.quoted
16748 && matches!(
16749 col.name.name.to_ascii_uppercase().as_str(),
16750 "NULL" | "TRUE" | "FALSE"
16751 );
16752 if postgres_qualified_keyword {
16753 self.write(&col.name.name);
16754 } else {
16755 self.generate_identifier(&col.name)?;
16756 }
16757 if col.join_mark && self.config.supports_column_join_marks {
16760 self.write(" (+)");
16761 }
16762 for comment in &col.trailing_comments {
16764 self.write_space();
16765 self.write_formatted_comment(comment);
16766 }
16767 Ok(())
16768 }
16769
16770 fn generate_prepare(&mut self, prepare: &PrepareStatement) -> Result<()> {
16771 self.write_keyword("PREPARE");
16772 self.write_space();
16773 self.generate_identifier(&prepare.name)?;
16774
16775 if !prepare.parameter_types.is_empty() {
16776 self.write(" (");
16777 for (i, data_type) in prepare.parameter_types.iter().enumerate() {
16778 if i > 0 {
16779 self.write(", ");
16780 }
16781 self.generate_data_type(data_type)?;
16782 }
16783 self.write(")");
16784 }
16785
16786 self.write_space();
16787 self.write_keyword("AS");
16788 self.write_space();
16789 self.generate_expression(&prepare.statement)
16790 }
16791
16792 fn generate_pseudocolumn(&mut self, pc: &Pseudocolumn) -> Result<()> {
16795 use crate::dialects::DialectType;
16796 use crate::expressions::PseudocolumnType;
16797
16798 if pc.kind == PseudocolumnType::Sysdate
16800 && !matches!(
16801 self.config.dialect,
16802 Some(DialectType::Oracle) | Some(DialectType::Redshift) | None
16803 )
16804 {
16805 self.write_keyword("CURRENT_TIMESTAMP");
16806 if matches!(
16808 self.config.dialect,
16809 Some(DialectType::MySQL)
16810 | Some(DialectType::ClickHouse)
16811 | Some(DialectType::Spark)
16812 | Some(DialectType::Databricks)
16813 | Some(DialectType::Hive)
16814 ) {
16815 self.write("()");
16816 }
16817 } else {
16818 self.write(pc.kind.as_str());
16819 }
16820 Ok(())
16821 }
16822
16823 fn generate_connect(&mut self, connect: &Connect) -> Result<()> {
16825 use crate::dialects::DialectType;
16826
16827 let supports_connect_by = matches!(
16830 self.config.dialect,
16831 Some(DialectType::Oracle) | Some(DialectType::Snowflake)
16832 );
16833
16834 if !supports_connect_by && self.config.dialect.is_some() {
16835 if self.config.pretty {
16837 self.write_newline();
16838 } else {
16839 self.write_space();
16840 }
16841 self.write_unsupported_comment(
16842 "CONNECT BY requires manual conversion to recursive CTE",
16843 )?;
16844 }
16845
16846 if let Some(start) = &connect.start {
16848 if self.config.pretty {
16849 self.write_newline();
16850 } else {
16851 self.write_space();
16852 }
16853 self.write_keyword("START WITH");
16854 self.write_space();
16855 self.generate_expression(start)?;
16856 }
16857
16858 if self.config.pretty {
16860 self.write_newline();
16861 } else {
16862 self.write_space();
16863 }
16864 self.write_keyword("CONNECT BY");
16865 if connect.nocycle {
16866 self.write_space();
16867 self.write_keyword("NOCYCLE");
16868 }
16869 self.write_space();
16870 self.generate_expression(&connect.connect)?;
16871
16872 Ok(())
16873 }
16874
16875 fn generate_connect_expr(&mut self, connect: &Connect) -> Result<()> {
16877 self.generate_connect(connect)
16878 }
16879
16880 fn generate_prior(&mut self, prior: &Prior) -> Result<()> {
16882 self.write_keyword("PRIOR");
16883 self.write_space();
16884 self.generate_expression(&prior.this)?;
16885 Ok(())
16886 }
16887
16888 fn generate_connect_by_root(&mut self, cbr: &ConnectByRoot) -> Result<()> {
16891 self.write_keyword("CONNECT_BY_ROOT");
16892 self.write_space();
16893 self.generate_expression(&cbr.this)?;
16894 Ok(())
16895 }
16896
16897 fn generate_match_recognize(&mut self, mr: &MatchRecognize) -> Result<()> {
16899 use crate::dialects::DialectType;
16900
16901 let supports_match_recognize = matches!(
16903 self.config.dialect,
16904 Some(DialectType::Oracle)
16905 | Some(DialectType::Snowflake)
16906 | Some(DialectType::Presto)
16907 | Some(DialectType::Trino)
16908 );
16909
16910 if let Some(source) = &mr.this {
16912 self.generate_expression(source)?;
16913 }
16914
16915 if !supports_match_recognize {
16916 self.write_unsupported_comment("MATCH_RECOGNIZE not supported in this dialect")?;
16917 return Ok(());
16918 }
16919
16920 if self.config.pretty {
16922 self.write_newline();
16923 } else {
16924 self.write_space();
16925 }
16926
16927 self.write_keyword("MATCH_RECOGNIZE");
16928 self.write(" (");
16929
16930 if self.config.pretty {
16931 self.indent_level += 1;
16932 }
16933
16934 let mut needs_separator = false;
16935
16936 if let Some(partition_by) = &mr.partition_by {
16938 if !partition_by.is_empty() {
16939 if self.config.pretty {
16940 self.write_newline();
16941 self.write_indent();
16942 }
16943 self.write_keyword("PARTITION BY");
16944 self.write_space();
16945 for (i, expr) in partition_by.iter().enumerate() {
16946 if i > 0 {
16947 self.write(", ");
16948 }
16949 self.generate_expression(expr)?;
16950 }
16951 needs_separator = true;
16952 }
16953 }
16954
16955 if let Some(order_by) = &mr.order_by {
16957 if !order_by.is_empty() {
16958 if needs_separator {
16959 if self.config.pretty {
16960 self.write_newline();
16961 self.write_indent();
16962 } else {
16963 self.write_space();
16964 }
16965 } else if self.config.pretty {
16966 self.write_newline();
16967 self.write_indent();
16968 }
16969 self.write_keyword("ORDER BY");
16970 if self.config.pretty {
16972 self.indent_level += 1;
16973 for (i, ordered) in order_by.iter().enumerate() {
16974 if i > 0 {
16975 self.write(",");
16976 }
16977 self.write_newline();
16978 self.write_indent();
16979 self.generate_ordered(ordered)?;
16980 }
16981 self.indent_level -= 1;
16982 } else {
16983 self.write_space();
16984 for (i, ordered) in order_by.iter().enumerate() {
16985 if i > 0 {
16986 self.write(", ");
16987 }
16988 self.generate_ordered(ordered)?;
16989 }
16990 }
16991 needs_separator = true;
16992 }
16993 }
16994
16995 if let Some(measures) = &mr.measures {
16997 if !measures.is_empty() {
16998 if needs_separator {
16999 if self.config.pretty {
17000 self.write_newline();
17001 self.write_indent();
17002 } else {
17003 self.write_space();
17004 }
17005 } else if self.config.pretty {
17006 self.write_newline();
17007 self.write_indent();
17008 }
17009 self.write_keyword("MEASURES");
17010 if self.config.pretty {
17012 self.indent_level += 1;
17013 for (i, measure) in measures.iter().enumerate() {
17014 if i > 0 {
17015 self.write(",");
17016 }
17017 self.write_newline();
17018 self.write_indent();
17019 if let Some(semantics) = &measure.window_frame {
17021 match semantics {
17022 MatchRecognizeSemantics::Running => {
17023 self.write_keyword("RUNNING");
17024 self.write_space();
17025 }
17026 MatchRecognizeSemantics::Final => {
17027 self.write_keyword("FINAL");
17028 self.write_space();
17029 }
17030 }
17031 }
17032 self.generate_expression(&measure.this)?;
17033 }
17034 self.indent_level -= 1;
17035 } else {
17036 self.write_space();
17037 for (i, measure) in measures.iter().enumerate() {
17038 if i > 0 {
17039 self.write(", ");
17040 }
17041 if let Some(semantics) = &measure.window_frame {
17043 match semantics {
17044 MatchRecognizeSemantics::Running => {
17045 self.write_keyword("RUNNING");
17046 self.write_space();
17047 }
17048 MatchRecognizeSemantics::Final => {
17049 self.write_keyword("FINAL");
17050 self.write_space();
17051 }
17052 }
17053 }
17054 self.generate_expression(&measure.this)?;
17055 }
17056 }
17057 needs_separator = true;
17058 }
17059 }
17060
17061 if let Some(rows) = &mr.rows {
17063 if needs_separator {
17064 if self.config.pretty {
17065 self.write_newline();
17066 self.write_indent();
17067 } else {
17068 self.write_space();
17069 }
17070 } else if self.config.pretty {
17071 self.write_newline();
17072 self.write_indent();
17073 }
17074 match rows {
17075 MatchRecognizeRows::OneRowPerMatch => {
17076 self.write_keyword("ONE ROW PER MATCH");
17077 }
17078 MatchRecognizeRows::AllRowsPerMatch => {
17079 self.write_keyword("ALL ROWS PER MATCH");
17080 }
17081 MatchRecognizeRows::AllRowsPerMatchShowEmptyMatches => {
17082 self.write_keyword("ALL ROWS PER MATCH SHOW EMPTY MATCHES");
17083 }
17084 MatchRecognizeRows::AllRowsPerMatchOmitEmptyMatches => {
17085 self.write_keyword("ALL ROWS PER MATCH OMIT EMPTY MATCHES");
17086 }
17087 MatchRecognizeRows::AllRowsPerMatchWithUnmatchedRows => {
17088 self.write_keyword("ALL ROWS PER MATCH WITH UNMATCHED ROWS");
17089 }
17090 }
17091 needs_separator = true;
17092 }
17093
17094 if let Some(after) = &mr.after {
17096 if needs_separator {
17097 if self.config.pretty {
17098 self.write_newline();
17099 self.write_indent();
17100 } else {
17101 self.write_space();
17102 }
17103 } else if self.config.pretty {
17104 self.write_newline();
17105 self.write_indent();
17106 }
17107 match after {
17108 MatchRecognizeAfter::PastLastRow => {
17109 self.write_keyword("AFTER MATCH SKIP PAST LAST ROW");
17110 }
17111 MatchRecognizeAfter::ToNextRow => {
17112 self.write_keyword("AFTER MATCH SKIP TO NEXT ROW");
17113 }
17114 MatchRecognizeAfter::ToFirst(ident) => {
17115 self.write_keyword("AFTER MATCH SKIP TO FIRST");
17116 self.write_space();
17117 self.generate_identifier(ident)?;
17118 }
17119 MatchRecognizeAfter::ToLast(ident) => {
17120 self.write_keyword("AFTER MATCH SKIP TO LAST");
17121 self.write_space();
17122 self.generate_identifier(ident)?;
17123 }
17124 }
17125 needs_separator = true;
17126 }
17127
17128 if let Some(pattern) = &mr.pattern {
17130 if needs_separator {
17131 if self.config.pretty {
17132 self.write_newline();
17133 self.write_indent();
17134 } else {
17135 self.write_space();
17136 }
17137 } else if self.config.pretty {
17138 self.write_newline();
17139 self.write_indent();
17140 }
17141 self.write_keyword("PATTERN");
17142 self.write_space();
17143 self.write("(");
17144 self.write(pattern);
17145 self.write(")");
17146 needs_separator = true;
17147 }
17148
17149 if let Some(define) = &mr.define {
17151 if !define.is_empty() {
17152 if needs_separator {
17153 if self.config.pretty {
17154 self.write_newline();
17155 self.write_indent();
17156 } else {
17157 self.write_space();
17158 }
17159 } else if self.config.pretty {
17160 self.write_newline();
17161 self.write_indent();
17162 }
17163 self.write_keyword("DEFINE");
17164 if self.config.pretty {
17166 self.indent_level += 1;
17167 for (i, (name, expr)) in define.iter().enumerate() {
17168 if i > 0 {
17169 self.write(",");
17170 }
17171 self.write_newline();
17172 self.write_indent();
17173 self.generate_identifier(name)?;
17174 self.write(" AS ");
17175 self.generate_expression(expr)?;
17176 }
17177 self.indent_level -= 1;
17178 } else {
17179 self.write_space();
17180 for (i, (name, expr)) in define.iter().enumerate() {
17181 if i > 0 {
17182 self.write(", ");
17183 }
17184 self.generate_identifier(name)?;
17185 self.write(" AS ");
17186 self.generate_expression(expr)?;
17187 }
17188 }
17189 }
17190 }
17191
17192 if self.config.pretty {
17193 self.indent_level -= 1;
17194 self.write_newline();
17195 }
17196 self.write(")");
17197
17198 if let Some(alias) = &mr.alias {
17200 self.write(" ");
17201 if mr.alias_explicit_as {
17202 self.write_keyword("AS");
17203 self.write(" ");
17204 }
17205 self.generate_identifier(alias)?;
17206 }
17207
17208 Ok(())
17209 }
17210
17211 fn generate_hint(&mut self, hint: &Hint) -> Result<()> {
17213 use crate::dialects::DialectType;
17214
17215 let supports_hints = matches!(
17217 self.config.dialect,
17218 None | Some(DialectType::Oracle) | Some(DialectType::MySQL) |
17220 Some(DialectType::Spark) | Some(DialectType::Hive) |
17221 Some(DialectType::Databricks) | Some(DialectType::PostgreSQL)
17222 );
17223
17224 if !supports_hints || hint.expressions.is_empty() {
17225 return Ok(());
17226 }
17227
17228 let mut hint_strings: Vec<String> = Vec::new();
17231 for expr in &hint.expressions {
17232 match expr {
17233 HintExpression::Raw(text) => {
17234 let parsed = self.parse_raw_hint_text(text);
17236 hint_strings.extend(parsed);
17237 }
17238 _ => {
17239 hint_strings.push(self.hint_expression_to_string(expr)?);
17240 }
17241 }
17242 }
17243
17244 let use_multiline = self.config.pretty && hint_strings.len() > 1;
17248
17249 if use_multiline {
17250 self.write(" /*+ ");
17252 for (i, hint_str) in hint_strings.iter().enumerate() {
17253 if i > 0 {
17254 self.write_newline();
17255 self.write(" "); }
17257 self.write(hint_str);
17258 }
17259 self.write(" */");
17260 } else {
17261 self.write(" /*+ ");
17263 let sep = match self.config.dialect {
17264 Some(DialectType::Spark) | Some(DialectType::Databricks) => ", ",
17265 _ => " ",
17266 };
17267 for (i, hint_str) in hint_strings.iter().enumerate() {
17268 if i > 0 {
17269 self.write(sep);
17270 }
17271 self.write(hint_str);
17272 }
17273 self.write(" */");
17274 }
17275
17276 Ok(())
17277 }
17278
17279 fn parse_raw_hint_text(&self, text: &str) -> Vec<String> {
17283 let mut results = Vec::new();
17284 let mut chars = text.chars().peekable();
17285 let mut current = String::new();
17286 let mut paren_depth = 0;
17287 let mut has_unparseable_content = false;
17288 let mut position_after_last_function = 0;
17289 let mut char_position = 0;
17290
17291 while let Some(c) = chars.next() {
17292 char_position += c.len_utf8();
17293 match c {
17294 '(' => {
17295 paren_depth += 1;
17296 current.push(c);
17297 }
17298 ')' => {
17299 paren_depth -= 1;
17300 current.push(c);
17301 if paren_depth == 0 {
17303 let trimmed = current.trim().to_string();
17304 if !trimmed.is_empty() {
17305 let formatted = self.format_hint_function(&trimmed);
17307 results.push(formatted);
17308 }
17309 current.clear();
17310 position_after_last_function = char_position;
17311 }
17312 }
17313 ' ' | '\t' | '\n' | ',' if paren_depth == 0 => {
17314 }
17316 _ if paren_depth == 0 => {
17317 current.push(c);
17319 }
17320 _ => {
17321 current.push(c);
17322 }
17323 }
17324 }
17325
17326 let remaining_text = text[position_after_last_function..].trim();
17328 if !remaining_text.is_empty() {
17329 let words: Vec<&str> = remaining_text.split_whitespace().collect();
17333 let looks_like_hint_functions = words.iter().all(|word| {
17334 word.contains('(') || (word.chars().all(|c| c.is_ascii_uppercase() || c == '_'))
17336 });
17337
17338 if !looks_like_hint_functions && words.len() > 1 {
17339 has_unparseable_content = true;
17340 }
17341 }
17342
17343 if has_unparseable_content {
17345 return vec![text.trim().to_string()];
17346 }
17347
17348 if results.is_empty() {
17350 results.push(text.trim().to_string());
17351 }
17352
17353 results
17354 }
17355
17356 fn format_hint_function(&self, hint: &str) -> String {
17359 if !self.config.pretty {
17360 return hint.to_string();
17361 }
17362
17363 if let Some(paren_pos) = hint.find('(') {
17365 if hint.ends_with(')') {
17366 let name = &hint[..paren_pos];
17367 let args_str = &hint[paren_pos + 1..hint.len() - 1];
17368
17369 let args: Vec<&str> = args_str.split_whitespace().collect();
17371
17372 let total_args_width: usize =
17374 args.iter().map(|s| s.len()).sum::<usize>() + args.len().saturating_sub(1); if total_args_width > self.config.max_text_width && !args.is_empty() {
17378 let mut result = format!("{}(\n", name);
17379 for arg in &args {
17380 result.push_str(" "); result.push_str(arg);
17382 result.push('\n');
17383 }
17384 result.push_str(" )"); return result;
17386 }
17387 }
17388 }
17389
17390 hint.to_string()
17391 }
17392
17393 fn hint_expression_to_string(&mut self, expr: &HintExpression) -> Result<String> {
17395 match expr {
17396 HintExpression::Function { name, args } => {
17397 let arg_strings: Vec<String> = args
17399 .iter()
17400 .map(|arg| {
17401 let mut gen = Generator::with_arc_config(self.config.clone());
17402 gen.generate_expression(arg)?;
17403 Ok(gen.output)
17404 })
17405 .collect::<Result<Vec<_>>>()?;
17406
17407 let total_args_width: usize = arg_strings.iter().map(|s| s.len()).sum::<usize>()
17409 + arg_strings.len().saturating_sub(1); let args_multiline =
17414 self.config.pretty && total_args_width > self.config.max_text_width;
17415
17416 if args_multiline && !arg_strings.is_empty() {
17417 let mut result = format!("{}(\n", name);
17419 for arg_str in &arg_strings {
17420 result.push_str(" "); result.push_str(arg_str);
17422 result.push('\n');
17423 }
17424 result.push_str(" )"); Ok(result)
17426 } else {
17427 let args_str = arg_strings.join(" ");
17429 Ok(format!("{}({})", name, args_str))
17430 }
17431 }
17432 HintExpression::Identifier(name) => Ok(name.clone()),
17433 HintExpression::Raw(text) => {
17434 if self.config.pretty {
17436 Ok(self.format_hint_function(text))
17437 } else {
17438 Ok(text.clone())
17439 }
17440 }
17441 }
17442 }
17443
17444 fn generate_table(&mut self, table: &TableRef) -> Result<()> {
17445 if table.only {
17447 self.write_keyword("ONLY");
17448 self.write_space();
17449 }
17450
17451 if let Some(ref identifier_func) = table.identifier_func {
17453 self.generate_expression(identifier_func)?;
17454 if !table.name.name.is_empty() {
17456 if let Some(catalog) = &table.catalog {
17457 self.write(".");
17458 self.generate_identifier(catalog)?;
17459 }
17460 if let Some(schema) = &table.schema {
17461 self.write(".");
17462 self.generate_identifier(schema)?;
17463 }
17464 self.write(".");
17465 self.generate_identifier(&table.name)?;
17466 }
17467 } else {
17468 if let Some(catalog) = &table.catalog {
17469 self.generate_identifier(catalog)?;
17470 self.write(".");
17471 }
17472 if let Some(schema) = &table.schema {
17473 self.generate_identifier(schema)?;
17474 self.write(".");
17475 }
17476 self.generate_identifier(&table.name)?;
17477 }
17478
17479 if let Some(changes) = &table.changes {
17481 self.write(" ");
17482 self.generate_changes(changes)?;
17483 }
17484
17485 if !table.partitions.is_empty() {
17487 self.write_space();
17488 self.write_keyword("PARTITION");
17489 self.write("(");
17490 for (i, partition) in table.partitions.iter().enumerate() {
17491 if i > 0 {
17492 self.write(", ");
17493 }
17494 self.generate_identifier(partition)?;
17495 }
17496 self.write(")");
17497 }
17498
17499 let historical_data_post_alias = matches!(self.config.dialect, Some(DialectType::DuckDB));
17502 if table.changes.is_none() && !historical_data_post_alias {
17503 if let Some(when) = &table.when {
17504 self.write_space();
17505 self.generate_historical_data(when)?;
17506 }
17507 }
17508
17509 let system_time_post_alias = matches!(self.config.dialect, Some(DialectType::BigQuery));
17511 if !system_time_post_alias {
17512 if let Some(ref system_time) = table.system_time {
17513 self.write_space();
17514 self.write(system_time);
17515 }
17516 }
17517
17518 if let Some(ref version) = table.version {
17520 self.write_space();
17521 self.generate_version(version)?;
17522 }
17523
17524 let alias_post_tablesample = self.config.alias_post_tablesample;
17528
17529 if alias_post_tablesample {
17530 self.generate_table_sample_clause(table)?;
17532 }
17533
17534 let is_sqlite_hint = matches!(self.config.dialect, Some(DialectType::SQLite))
17537 && table.hints.iter().any(|h| {
17538 if let Expression::Identifier(id) = h {
17539 id.name.starts_with("INDEXED BY") || id.name == "NOT INDEXED"
17540 } else {
17541 false
17542 }
17543 });
17544 if !table.hints.is_empty() && !is_sqlite_hint {
17545 for hint in &table.hints {
17546 self.write_space();
17547 self.generate_expression(hint)?;
17548 }
17549 }
17550
17551 if let Some(alias) = &table.alias {
17552 self.write_space();
17553 let always_use_as = self.config.dialect.is_none()
17556 || matches!(
17557 self.config.dialect,
17558 Some(DialectType::Generic)
17559 | Some(DialectType::PostgreSQL)
17560 | Some(DialectType::Redshift)
17561 | Some(DialectType::Snowflake)
17562 | Some(DialectType::BigQuery)
17563 | Some(DialectType::DuckDB)
17564 | Some(DialectType::Presto)
17565 | Some(DialectType::Trino)
17566 | Some(DialectType::TSQL)
17567 | Some(DialectType::Fabric)
17568 | Some(DialectType::MySQL)
17569 | Some(DialectType::Spark)
17570 | Some(DialectType::Hive)
17571 | Some(DialectType::SQLite)
17572 | Some(DialectType::Drill)
17573 );
17574 let is_stage_ref = table.name.name.starts_with('@');
17575 let suppress_as = matches!(self.config.dialect, Some(DialectType::Oracle));
17577 if !suppress_as && (table.alias_explicit_as || always_use_as || is_stage_ref) {
17578 self.write_keyword("AS");
17579 self.write_space();
17580 }
17581 self.generate_identifier(alias)?;
17582
17583 if !table.column_aliases.is_empty() && self.config.supports_table_alias_columns {
17586 self.write("(");
17587 for (i, col_alias) in table.column_aliases.iter().enumerate() {
17588 if i > 0 {
17589 self.write(", ");
17590 }
17591 self.generate_identifier(col_alias)?;
17592 }
17593 self.write(")");
17594 }
17595 }
17596
17597 if system_time_post_alias {
17599 if let Some(ref system_time) = table.system_time {
17600 self.write_space();
17601 self.write(system_time);
17602 }
17603 }
17604
17605 if historical_data_post_alias && table.changes.is_none() {
17606 if let Some(when) = &table.when {
17607 self.write_space();
17608 self.generate_historical_data(when)?;
17609 }
17610 }
17611
17612 if !alias_post_tablesample {
17614 self.generate_table_sample_clause(table)?;
17615 }
17616
17617 if is_sqlite_hint {
17619 for hint in &table.hints {
17620 self.write_space();
17621 self.generate_expression(hint)?;
17622 }
17623 }
17624
17625 if table.final_ && matches!(self.config.dialect, Some(DialectType::ClickHouse)) {
17627 self.write_space();
17628 self.write_keyword("FINAL");
17629 }
17630
17631 for comment in &table.trailing_comments {
17633 self.write_space();
17634 self.write_formatted_comment(comment);
17635 }
17636 Ok(())
17640 }
17641
17642 fn generate_table_sample_clause(&mut self, table: &TableRef) -> Result<()> {
17644 if let Some(ref ts) = table.table_sample {
17645 self.write_space();
17646 if ts.is_using_sample {
17647 self.write_keyword("USING SAMPLE");
17648 } else {
17649 self.write_keyword(self.config.tablesample_keywords);
17651 }
17652 self.generate_sample_body(ts)?;
17653 if let Some(ref seed) = ts.seed {
17655 self.write_space();
17656 self.write_keyword(self.config.tablesample_seed_keyword);
17657 self.write(" (");
17658 self.generate_expression(seed)?;
17659 self.write(")");
17660 }
17661 }
17662 Ok(())
17663 }
17664
17665 fn generate_stage_reference(&mut self, sr: &StageReference) -> Result<()> {
17666 if sr.quoted {
17670 self.write("'");
17671 }
17672
17673 self.write(&sr.name);
17674 if let Some(path) = &sr.path {
17675 self.write(path);
17676 }
17677
17678 if sr.quoted {
17679 self.write("'");
17680 }
17681
17682 let has_options = sr.file_format.is_some() || sr.pattern.is_some();
17684 if has_options {
17685 self.write(" (");
17686 let mut first = true;
17687
17688 if let Some(file_format) = &sr.file_format {
17689 if !first {
17690 self.write(", ");
17691 }
17692 self.write_keyword("FILE_FORMAT");
17693 self.write(" => ");
17694 self.generate_expression(file_format)?;
17695 first = false;
17696 }
17697
17698 if let Some(pattern) = &sr.pattern {
17699 if !first {
17700 self.write(", ");
17701 }
17702 self.write_keyword("PATTERN");
17703 self.write(" => '");
17704 self.write(pattern);
17705 self.write("'");
17706 }
17707
17708 self.write(")");
17709 }
17710 Ok(())
17711 }
17712
17713 fn generate_star(&mut self, star: &Star) -> Result<()> {
17714 use crate::dialects::DialectType;
17715
17716 if let Some(table) = &star.table {
17717 self.generate_identifier(table)?;
17718 self.write(".");
17719 }
17720 self.write("*");
17721
17722 if let Some(except) = &star.except {
17724 if !except.is_empty() {
17725 self.write_space();
17726 match self.config.dialect {
17728 Some(DialectType::BigQuery) => self.write_keyword("EXCEPT"),
17729 Some(DialectType::DuckDB) | Some(DialectType::Snowflake) => {
17730 self.write_keyword("EXCLUDE")
17731 }
17732 _ => self.write_keyword("EXCEPT"), }
17734 self.write(" (");
17735 for (i, col) in except.iter().enumerate() {
17736 if i > 0 {
17737 self.write(", ");
17738 }
17739 self.generate_identifier(col)?;
17740 }
17741 self.write(")");
17742 }
17743 }
17744
17745 if let Some(replace) = &star.replace {
17747 if !replace.is_empty() {
17748 self.write_space();
17749 self.write_keyword("REPLACE");
17750 self.write(" (");
17751 for (i, alias) in replace.iter().enumerate() {
17752 if i > 0 {
17753 self.write(", ");
17754 }
17755 self.generate_expression(&alias.this)?;
17756 self.write_space();
17757 self.write_keyword("AS");
17758 self.write_space();
17759 self.generate_identifier(&alias.alias)?;
17760 }
17761 self.write(")");
17762 }
17763 }
17764
17765 if let Some(rename) = &star.rename {
17767 if !rename.is_empty() {
17768 self.write_space();
17769 self.write_keyword("RENAME");
17770 self.write(" (");
17771 for (i, (old_name, new_name)) in rename.iter().enumerate() {
17772 if i > 0 {
17773 self.write(", ");
17774 }
17775 self.generate_identifier(old_name)?;
17776 self.write_space();
17777 self.write_keyword("AS");
17778 self.write_space();
17779 self.generate_identifier(new_name)?;
17780 }
17781 self.write(")");
17782 }
17783 }
17784
17785 for comment in &star.trailing_comments {
17787 self.write_space();
17788 self.write_formatted_comment(comment);
17789 }
17790
17791 Ok(())
17792 }
17793
17794 fn generate_braced_wildcard(&mut self, expr: &Expression) -> Result<()> {
17796 self.write("{");
17797 match expr {
17798 Expression::Star(star) => {
17799 self.generate_star(star)?;
17801 }
17802 Expression::ILike(ilike) => {
17803 self.generate_expression(&ilike.left)?;
17805 self.write_space();
17806 self.write_keyword("ILIKE");
17807 self.write_space();
17808 self.generate_expression(&ilike.right)?;
17809 }
17810 _ => {
17811 self.generate_expression(expr)?;
17812 }
17813 }
17814 self.write("}");
17815 Ok(())
17816 }
17817
17818 fn generate_alias(&mut self, alias: &Alias) -> Result<()> {
17819 match &alias.this {
17823 Expression::Column(col) => {
17824 if let Some(table) = &col.table {
17826 self.generate_identifier(table)?;
17827 self.write(".");
17828 }
17829 self.generate_identifier(&col.name)?;
17830 }
17831 _ => {
17832 self.generate_expression(&alias.this)?;
17833 }
17834 }
17835
17836 if !alias.pre_alias_comments.is_empty() && !alias.trailing_comments.is_empty() {
17840 for comment in &alias.pre_alias_comments {
17841 self.write_space();
17842 self.write_formatted_comment(comment);
17843 }
17844 }
17845
17846 use crate::dialects::DialectType;
17847
17848 let is_table_source = matches!(
17854 &alias.this,
17855 Expression::JSONTable(_)
17856 | Expression::XMLTable(_)
17857 | Expression::TableFromRows(_)
17858 | Expression::Unnest(_)
17859 | Expression::MatchRecognize(_)
17860 | Expression::Select(_)
17861 | Expression::Subquery(_)
17862 | Expression::Paren(_)
17863 | Expression::JoinedTable(_)
17864 );
17865 let dialect_skips_table_alias_as = matches!(self.config.dialect, Some(DialectType::Oracle));
17866 let skip_as = is_table_source && dialect_skips_table_alias_as;
17867
17868 self.write_space();
17869 if !skip_as {
17870 if matches!(self.config.dialect, Some(DialectType::ClickHouse)) {
17871 if let Some(ref alias_keyword) = alias.alias_keyword {
17872 self.write(alias_keyword);
17873 } else {
17874 self.write_keyword("AS");
17875 }
17876 } else {
17877 self.write_keyword("AS");
17878 }
17879 self.write_space();
17880 }
17881
17882 let skip_column_aliases = matches!(self.config.dialect, Some(DialectType::BigQuery));
17884
17885 if alias.alias.is_empty() && !alias.column_aliases.is_empty() && !skip_column_aliases {
17887 self.write("(");
17889 for (i, col_alias) in alias.column_aliases.iter().enumerate() {
17890 if i > 0 {
17891 self.write(", ");
17892 }
17893 self.generate_alias_identifier(col_alias)?;
17894 }
17895 self.write(")");
17896 } else if !alias.column_aliases.is_empty() && !skip_column_aliases {
17897 self.generate_alias_identifier(&alias.alias)?;
17899 self.write("(");
17900 for (i, col_alias) in alias.column_aliases.iter().enumerate() {
17901 if i > 0 {
17902 self.write(", ");
17903 }
17904 self.generate_alias_identifier(col_alias)?;
17905 }
17906 self.write(")");
17907 } else {
17908 self.generate_alias_identifier(&alias.alias)?;
17910 }
17911
17912 for comment in &alias.trailing_comments {
17914 self.write_space();
17915 self.write_formatted_comment(comment);
17916 }
17917
17918 if alias.trailing_comments.is_empty() {
17923 for comment in &alias.pre_alias_comments {
17924 self.write_space();
17925 self.write_formatted_comment(comment);
17926 }
17927 }
17928
17929 Ok(())
17930 }
17931
17932 fn generate_cast(&mut self, cast: &Cast) -> Result<()> {
17933 use crate::dialects::DialectType;
17934
17935 if matches!(self.config.dialect, Some(DialectType::SingleStore)) {
17937 self.generate_expression(&cast.this)?;
17938 self.write(" :> ");
17939 self.generate_data_type(&cast.to)?;
17940 return Ok(());
17941 }
17942
17943 if matches!(self.config.dialect, Some(DialectType::Teradata)) {
17945 let is_unknown_type = matches!(cast.to, DataType::Unknown)
17946 || matches!(cast.to, DataType::Custom { ref name } if name.is_empty());
17947 if is_unknown_type {
17948 if let Some(format) = &cast.format {
17949 self.write_keyword("CAST");
17950 self.write("(");
17951 self.generate_expression(&cast.this)?;
17952 self.write_space();
17953 self.write_keyword("AS");
17954 self.write_space();
17955 self.write_keyword("FORMAT");
17956 self.write_space();
17957 self.generate_expression(format)?;
17958 self.write(")");
17959 return Ok(());
17960 }
17961 }
17962 }
17963
17964 if matches!(self.config.dialect, Some(DialectType::Oracle)) {
17967 if let Some(format) = &cast.format {
17968 let is_date = matches!(
17970 cast.to,
17971 DataType::Date
17972 | DataType::Oracle {
17973 oracle_type: OracleDataType::Date
17974 }
17975 );
17976 let is_timestamp = matches!(
17977 cast.to,
17978 DataType::Timestamp { .. }
17979 | DataType::Oracle {
17980 oracle_type: OracleDataType::Timestamp { .. }
17981 }
17982 );
17983
17984 if is_date || is_timestamp {
17985 let func_name = if is_date { "TO_DATE" } else { "TO_TIMESTAMP" };
17986 self.write_keyword(func_name);
17987 self.write("(");
17988 self.generate_expression(&cast.this)?;
17989 self.write(", ");
17990
17991 if let Expression::Literal(lit) = format.as_ref() {
17994 if let Literal::String(fmt_str) = lit.as_ref() {
17995 let normalized = self.normalize_oracle_format(fmt_str);
17996 self.write("'");
17997 self.write(&normalized);
17998 self.write("'");
17999 }
18000 } else {
18001 self.generate_expression(format)?;
18002 }
18003
18004 self.write(")");
18005 return Ok(());
18006 }
18007 }
18008 }
18009
18010 if matches!(self.config.dialect, Some(DialectType::BigQuery)) {
18013 if let Expression::Array(arr) = &cast.this {
18014 self.generate_data_type(&cast.to)?;
18015 self.write("[");
18017 for (i, expr) in arr.expressions.iter().enumerate() {
18018 if i > 0 {
18019 self.write(", ");
18020 }
18021 self.generate_expression(expr)?;
18022 }
18023 self.write("]");
18024 return Ok(());
18025 }
18026 if matches!(&cast.this, Expression::ArrayFunc(_)) {
18027 self.generate_data_type(&cast.to)?;
18028 self.generate_expression(&cast.this)?;
18029 return Ok(());
18030 }
18031 }
18032
18033 if matches!(
18036 self.config.dialect,
18037 Some(DialectType::DuckDB) | Some(DialectType::Presto) | Some(DialectType::Trino)
18038 ) {
18039 if let Expression::Struct(ref s) = cast.this {
18040 let all_unnamed = s.fields.iter().all(|(name, _)| name.is_none());
18041 if all_unnamed && matches!(cast.to, DataType::Struct { .. }) {
18042 self.write_keyword("CAST");
18043 self.write("(");
18044 self.generate_struct_as_row(s)?;
18045 self.write_space();
18046 self.write_keyword("AS");
18047 self.write_space();
18048 self.generate_data_type(&cast.to)?;
18049 self.write(")");
18050 return Ok(());
18051 }
18052 }
18053 }
18054
18055 let use_double_colon = cast.double_colon_syntax && self.dialect_prefers_double_colon();
18058
18059 if use_double_colon {
18060 self.generate_expression(&cast.this)?;
18062 self.write("::");
18063 self.generate_data_type(&cast.to)?;
18064 } else {
18065 self.write_keyword("CAST");
18067 self.write("(");
18068 self.generate_expression(&cast.this)?;
18069 self.write_space();
18070 self.write_keyword("AS");
18071 self.write_space();
18072 if matches!(
18075 self.config.dialect,
18076 Some(DialectType::MySQL) | Some(DialectType::SingleStore) | Some(DialectType::TiDB)
18077 ) {
18078 match &cast.to {
18079 DataType::Custom { ref name } => {
18080 if name.eq_ignore_ascii_case("LONGTEXT")
18081 || name.eq_ignore_ascii_case("MEDIUMTEXT")
18082 || name.eq_ignore_ascii_case("TINYTEXT")
18083 || name.eq_ignore_ascii_case("LONGBLOB")
18084 || name.eq_ignore_ascii_case("MEDIUMBLOB")
18085 || name.eq_ignore_ascii_case("TINYBLOB")
18086 {
18087 self.write_keyword("CHAR");
18088 } else {
18089 self.generate_data_type(&cast.to)?;
18090 }
18091 }
18092 DataType::VarChar { length, .. } => {
18093 self.write_keyword("CHAR");
18095 if let Some(n) = length {
18096 self.write(&format!("({})", n));
18097 }
18098 }
18099 DataType::Text => {
18100 self.write_keyword("CHAR");
18102 }
18103 DataType::Timestamp {
18104 precision,
18105 timezone: false,
18106 } => {
18107 self.write_keyword("DATETIME");
18109 if let Some(p) = precision {
18110 self.write(&format!("({})", p));
18111 }
18112 }
18113 _ => {
18114 self.generate_data_type(&cast.to)?;
18115 }
18116 }
18117 } else if matches!(self.config.dialect, Some(DialectType::Snowflake)) {
18118 match &cast.to {
18120 DataType::String { length } => {
18121 self.write_keyword("VARCHAR");
18122 if let Some(n) = length {
18123 self.write(&format!("({})", n));
18124 }
18125 }
18126 _ => {
18127 self.generate_data_type(&cast.to)?;
18128 }
18129 }
18130 } else if matches!(self.config.dialect, Some(DialectType::Oracle)) {
18131 match &cast.to {
18134 DataType::Oracle {
18135 oracle_type: OracleDataType::BinaryFloat,
18136 } => self.write_keyword("FLOAT"),
18137 DataType::Oracle {
18138 oracle_type: OracleDataType::BinaryDouble,
18139 } => self.write_keyword("DOUBLE PRECISION"),
18140 _ => self.generate_data_type(&cast.to)?,
18141 }
18142 } else {
18143 self.generate_data_type(&cast.to)?;
18144 }
18145
18146 if let Some(default) = &cast.default {
18148 self.write_space();
18149 self.write_keyword("DEFAULT");
18150 self.write_space();
18151 self.generate_expression(default)?;
18152 self.write_space();
18153 self.write_keyword("ON");
18154 self.write_space();
18155 self.write_keyword("CONVERSION");
18156 self.write_space();
18157 self.write_keyword("ERROR");
18158 }
18159
18160 if let Some(format) = &cast.format {
18163 if matches!(
18165 self.config.dialect,
18166 Some(crate::dialects::DialectType::Oracle)
18167 ) {
18168 self.write(", ");
18169 } else {
18170 self.write_space();
18171 self.write_keyword("FORMAT");
18172 self.write_space();
18173 }
18174 self.generate_expression(format)?;
18175 }
18176
18177 self.write(")");
18178 for comment in &cast.trailing_comments {
18180 self.write_space();
18181 self.write_formatted_comment(comment);
18182 }
18183 }
18184 Ok(())
18185 }
18186
18187 fn generate_struct_as_row(&mut self, s: &crate::expressions::Struct) -> Result<()> {
18190 self.write_keyword("ROW");
18191 self.write("(");
18192 for (i, (_, expr)) in s.fields.iter().enumerate() {
18193 if i > 0 {
18194 self.write(", ");
18195 }
18196 if let Expression::Struct(ref inner_s) = expr {
18198 self.generate_struct_as_row(inner_s)?;
18199 } else {
18200 self.generate_expression(expr)?;
18201 }
18202 }
18203 self.write(")");
18204 Ok(())
18205 }
18206
18207 fn normalize_oracle_format(&self, format: &str) -> String {
18210 let mut result = String::new();
18213 let chars: Vec<char> = format.chars().collect();
18214 let mut i = 0;
18215
18216 while i < chars.len() {
18217 if i + 1 < chars.len() && chars[i] == 'H' && chars[i + 1] == 'H' {
18218 if i + 2 < chars.len() {
18220 let next = chars[i + 2];
18221 if next == '1' || next == '2' {
18222 result.push('H');
18224 result.push('H');
18225 i += 2;
18226 continue;
18227 }
18228 }
18229 result.push_str("HH12");
18231 i += 2;
18232 } else {
18233 result.push(chars[i]);
18234 i += 1;
18235 }
18236 }
18237
18238 result
18239 }
18240
18241 fn dialect_prefers_double_colon(&self) -> bool {
18244 matches!(self.config.dialect, Some(DialectType::ClickHouse))
18245 }
18246
18247 fn generate_mod_func(&mut self, f: &crate::expressions::BinaryFunc) -> Result<()> {
18249 use crate::dialects::DialectType;
18250
18251 let use_percent_operator = matches!(
18253 self.config.dialect,
18254 Some(DialectType::Snowflake)
18255 | Some(DialectType::MySQL)
18256 | Some(DialectType::Presto)
18257 | Some(DialectType::Trino)
18258 | Some(DialectType::PostgreSQL)
18259 | Some(DialectType::DuckDB)
18260 | Some(DialectType::Hive)
18261 | Some(DialectType::Spark)
18262 | Some(DialectType::Databricks)
18263 | Some(DialectType::Athena)
18264 | Some(DialectType::TSQL)
18265 | Some(DialectType::Fabric)
18266 );
18267
18268 if use_percent_operator {
18269 let needs_paren = |e: &Expression| {
18272 matches!(
18273 e,
18274 Expression::Add(_)
18275 | Expression::Sub(_)
18276 | Expression::Mul(_)
18277 | Expression::Div(_)
18278 | Expression::Mod(_)
18279 | Expression::ModFunc(_)
18280 )
18281 };
18282 if needs_paren(&f.this) {
18283 self.write("(");
18284 self.generate_expression(&f.this)?;
18285 self.write(")");
18286 } else {
18287 self.generate_expression(&f.this)?;
18288 }
18289 self.write(" % ");
18290 if needs_paren(&f.expression) {
18291 self.write("(");
18292 self.generate_expression(&f.expression)?;
18293 self.write(")");
18294 } else {
18295 self.generate_expression(&f.expression)?;
18296 }
18297 Ok(())
18298 } else {
18299 self.generate_binary_func("MOD", &f.this, &f.expression)
18300 }
18301 }
18302
18303 fn generate_ifnull(&mut self, f: &crate::expressions::BinaryFunc) -> Result<()> {
18305 use crate::dialects::DialectType;
18306
18307 let func_name = match self.config.dialect {
18309 Some(DialectType::Snowflake) => "COALESCE",
18310 _ => "IFNULL",
18311 };
18312
18313 self.generate_binary_func(func_name, &f.this, &f.expression)
18314 }
18315
18316 fn generate_nvl(&mut self, f: &crate::expressions::BinaryFunc) -> Result<()> {
18318 if let Some(ref original_name) = f.original_name {
18320 return self.generate_binary_func(original_name, &f.this, &f.expression);
18321 }
18322
18323 use crate::dialects::DialectType;
18325 let func_name = match self.config.dialect {
18326 Some(DialectType::Snowflake)
18327 | Some(DialectType::ClickHouse)
18328 | Some(DialectType::PostgreSQL)
18329 | Some(DialectType::Presto)
18330 | Some(DialectType::Trino)
18331 | Some(DialectType::Athena)
18332 | Some(DialectType::DuckDB)
18333 | Some(DialectType::BigQuery)
18334 | Some(DialectType::Spark)
18335 | Some(DialectType::Databricks)
18336 | Some(DialectType::Hive) => "COALESCE",
18337 Some(DialectType::MySQL)
18338 | Some(DialectType::Doris)
18339 | Some(DialectType::StarRocks)
18340 | Some(DialectType::SingleStore)
18341 | Some(DialectType::TiDB) => "IFNULL",
18342 _ => "NVL",
18343 };
18344
18345 self.generate_binary_func(func_name, &f.this, &f.expression)
18346 }
18347
18348 fn generate_stddev_samp(&mut self, f: &crate::expressions::AggFunc) -> Result<()> {
18350 use crate::dialects::DialectType;
18351
18352 let func_name = match self.config.dialect {
18354 Some(DialectType::Snowflake) => "STDDEV",
18355 _ => "STDDEV_SAMP",
18356 };
18357
18358 self.generate_agg_func(func_name, f)
18359 }
18360
18361 fn generate_collation(&mut self, coll: &CollationExpr) -> Result<()> {
18362 self.generate_expression(&coll.this)?;
18363 self.write_space();
18364 self.write_keyword("COLLATE");
18365 self.write_space();
18366 if coll.quoted {
18367 self.write("'");
18369 self.write(&coll.collation);
18370 self.write("'");
18371 } else if coll.double_quoted {
18372 self.write("\"");
18374 self.write(&coll.collation);
18375 self.write("\"");
18376 } else {
18377 self.write(&coll.collation);
18379 }
18380 Ok(())
18381 }
18382
18383 fn generate_case(&mut self, case: &Case) -> Result<()> {
18384 let multiline_case = if self.config.pretty {
18386 let mut statements: Vec<String> = Vec::new();
18388 let operand_str = if let Some(operand) = &case.operand {
18389 let s = self.generate_to_string(operand)?;
18390 statements.push(format!("CASE {}", s));
18391 s
18392 } else {
18393 statements.push("CASE".to_string());
18394 String::new()
18395 };
18396 let _ = operand_str;
18397 for (condition, result) in &case.whens {
18398 statements.push(format!("WHEN {}", self.generate_to_string(condition)?));
18399 statements.push(format!("THEN {}", self.generate_to_string(result)?));
18400 }
18401 if let Some(else_) = &case.else_ {
18402 statements.push(format!("ELSE {}", self.generate_to_string(else_)?));
18403 }
18404 statements.push("END".to_string());
18405 self.too_wide(&statements)
18406 } else {
18407 false
18408 };
18409
18410 self.write_keyword("CASE");
18411 if let Some(operand) = &case.operand {
18412 self.write_space();
18413 self.generate_expression(operand)?;
18414 }
18415 if multiline_case {
18416 self.indent_level += 1;
18417 }
18418 for (condition, result) in &case.whens {
18419 if multiline_case {
18420 self.write_newline();
18421 self.write_indent();
18422 } else {
18423 self.write_space();
18424 }
18425 self.write_keyword("WHEN");
18426 self.write_space();
18427 self.generate_expression(condition)?;
18428 if multiline_case {
18429 self.write_newline();
18430 self.write_indent();
18431 } else {
18432 self.write_space();
18433 }
18434 self.write_keyword("THEN");
18435 self.write_space();
18436 self.generate_expression(result)?;
18437 }
18438 if let Some(else_) = &case.else_ {
18439 if multiline_case {
18440 self.write_newline();
18441 self.write_indent();
18442 } else {
18443 self.write_space();
18444 }
18445 self.write_keyword("ELSE");
18446 self.write_space();
18447 self.generate_expression(else_)?;
18448 }
18449 if multiline_case {
18450 self.indent_level -= 1;
18451 self.write_newline();
18452 self.write_indent();
18453 } else {
18454 self.write_space();
18455 }
18456 self.write_keyword("END");
18457 for comment in &case.comments {
18459 self.write(" ");
18460 self.write_formatted_comment(comment);
18461 }
18462 Ok(())
18463 }
18464
18465 fn generate_function(&mut self, func: &Function) -> Result<()> {
18466 let normalized_name = if func.name.eq_ignore_ascii_case("GROUPING")
18468 && func.args.len() > 1
18469 && matches!(
18470 self.config.dialect,
18471 Some(DialectType::TSQL | DialectType::Fabric)
18472 ) {
18473 Cow::Borrowed("GROUPING_ID")
18474 } else if matches!(self.config.dialect, Some(DialectType::Snowflake))
18475 && func.name.to_ascii_uppercase().starts_with("IDENTIFIER(")
18476 {
18477 Cow::Borrowed(func.name.as_str())
18478 } else {
18479 self.normalize_func_name(&func.name)
18480 };
18481
18482 if matches!(self.config.dialect, Some(DialectType::DuckDB))
18484 && func.name.eq_ignore_ascii_case("ARRAY_CONSTRUCT_COMPACT")
18485 {
18486 self.write("LIST_FILTER(");
18487 self.write("[");
18488 for (i, arg) in func.args.iter().enumerate() {
18489 if i > 0 {
18490 self.write(", ");
18491 }
18492 self.generate_expression(arg)?;
18493 }
18494 self.write("], _u -> NOT _u IS NULL)");
18495 return Ok(());
18496 }
18497
18498 if matches!(self.config.dialect, Some(DialectType::Snowflake))
18501 && func.name.eq_ignore_ascii_case("TO_VARIANT")
18502 && func.args.len() == 1
18503 {
18504 let array_expressions = match &func.args[0] {
18505 Expression::ArrayFunc(arr) => Some(&arr.expressions),
18506 Expression::Array(arr) => Some(&arr.expressions),
18507 _ => None,
18508 };
18509 if let Some(expressions) = array_expressions {
18510 self.write_keyword("TO_VARIANT");
18511 self.write("(");
18512 self.write_keyword("ARRAY_CONSTRUCT");
18513 self.write("(");
18514 for (i, arg) in expressions.iter().enumerate() {
18515 if i > 0 {
18516 self.write(", ");
18517 }
18518 self.generate_expression(arg)?;
18519 }
18520 self.write(")");
18521 self.write(")");
18522 return Ok(());
18523 }
18524 }
18525
18526 if func.name.eq_ignore_ascii_case("STRUCT")
18528 && !matches!(
18529 self.config.dialect,
18530 Some(DialectType::BigQuery)
18531 | Some(DialectType::Spark)
18532 | Some(DialectType::Databricks)
18533 | Some(DialectType::Hive)
18534 | None
18535 )
18536 {
18537 return self.generate_struct_function_cross_dialect(func);
18538 }
18539
18540 if func.name.eq_ignore_ascii_case("__SS_JSON_PATH_QMARK__") && func.args.len() == 2 {
18543 self.generate_expression(&func.args[0])?;
18544 self.write("::?");
18545 if let Expression::Literal(lit) = &func.args[1] {
18547 if let crate::expressions::Literal::String(key) = lit.as_ref() {
18548 self.write(key);
18549 }
18550 } else {
18551 self.generate_expression(&func.args[1])?;
18552 }
18553 return Ok(());
18554 }
18555
18556 if func.name.eq_ignore_ascii_case("__PG_BITWISE_XOR__") && func.args.len() == 2 {
18558 self.generate_expression(&func.args[0])?;
18559 self.write(" # ");
18560 self.generate_expression(&func.args[1])?;
18561 return Ok(());
18562 }
18563
18564 if matches!(
18566 self.config.dialect,
18567 Some(DialectType::Spark | DialectType::Databricks | DialectType::Hive)
18568 ) && func.name.eq_ignore_ascii_case("TRY")
18569 && func.args.len() == 1
18570 {
18571 self.generate_expression(&func.args[0])?;
18572 return Ok(());
18573 }
18574
18575 if self.config.dialect == Some(DialectType::ClickHouse)
18577 && func.name.eq_ignore_ascii_case("TOSTARTOFDAY")
18578 && func.args.len() == 1
18579 {
18580 self.write("dateTrunc('DAY', ");
18581 self.generate_expression(&func.args[0])?;
18582 self.write(")");
18583 return Ok(());
18584 }
18585
18586 if self.config.dialect == Some(DialectType::ClickHouse)
18588 && func.name.eq_ignore_ascii_case("DATE_TRUNC")
18589 && func.args.len() == 2
18590 {
18591 self.write("dateTrunc(");
18592 self.generate_expression(&func.args[0])?;
18593 self.write(", ");
18594 self.generate_expression(&func.args[1])?;
18595 self.write(")");
18596 return Ok(());
18597 }
18598
18599 if matches!(
18601 self.config.dialect,
18602 Some(DialectType::Presto | DialectType::Trino | DialectType::Athena)
18603 ) && func.name.eq_ignore_ascii_case("SUBSTRING")
18604 {
18605 self.write_keyword("SUBSTR");
18606 self.write("(");
18607 for (i, arg) in func.args.iter().enumerate() {
18608 if i > 0 {
18609 self.write(", ");
18610 }
18611 self.generate_expression(arg)?;
18612 }
18613 self.write(")");
18614 return Ok(());
18615 }
18616
18617 if self.config.dialect == Some(DialectType::Snowflake)
18618 && func.name.eq_ignore_ascii_case("LIST_DISTINCT")
18619 && func.args.len() == 1
18620 {
18621 self.write_keyword("ARRAY_DISTINCT");
18622 self.write("(");
18623 self.write_keyword("ARRAY_COMPACT");
18624 self.write("(");
18625 self.generate_expression(&func.args[0])?;
18626 self.write("))");
18627 return Ok(());
18628 }
18629
18630 if self.config.dialect == Some(DialectType::Snowflake)
18631 && func.name.eq_ignore_ascii_case("LIST")
18632 && func.args.len() == 1
18633 && !matches!(func.args.first(), Some(Expression::Select(_)))
18634 {
18635 self.write_keyword("ARRAY_AGG");
18636 self.write("(");
18637 self.generate_expression(&func.args[0])?;
18638 self.write(")");
18639 return Ok(());
18640 }
18641
18642 if self.config.dialect == Some(DialectType::Redshift)
18644 && func.name.eq_ignore_ascii_case("CONCAT")
18645 && func.args.len() >= 2
18646 {
18647 for (i, arg) in func.args.iter().enumerate() {
18648 if i > 0 {
18649 self.write(" || ");
18650 }
18651 self.generate_expression(arg)?;
18652 }
18653 return Ok(());
18654 }
18655
18656 if self.config.dialect == Some(DialectType::Redshift)
18658 && func.name.eq_ignore_ascii_case("CONCAT_WS")
18659 && func.args.len() >= 2
18660 {
18661 let sep = &func.args[0];
18662 for (i, arg) in func.args.iter().skip(1).enumerate() {
18663 if i > 0 {
18664 self.write(" || ");
18665 self.generate_expression(sep)?;
18666 self.write(" || ");
18667 }
18668 self.generate_expression(arg)?;
18669 }
18670 return Ok(());
18671 }
18672
18673 if self.config.dialect == Some(DialectType::Redshift)
18676 && (func.name.eq_ignore_ascii_case("DATEDIFF")
18677 || func.name.eq_ignore_ascii_case("DATE_DIFF"))
18678 && func.args.len() == 3
18679 {
18680 self.write_keyword("DATEDIFF");
18681 self.write("(");
18682 self.write_redshift_date_part(&func.args[0]);
18684 self.write(", ");
18685 self.generate_expression(&func.args[1])?;
18686 self.write(", ");
18687 self.generate_expression(&func.args[2])?;
18688 self.write(")");
18689 return Ok(());
18690 }
18691
18692 if self.config.dialect == Some(DialectType::Redshift)
18695 && (func.name.eq_ignore_ascii_case("DATEADD")
18696 || func.name.eq_ignore_ascii_case("DATE_ADD"))
18697 && func.args.len() == 3
18698 {
18699 self.write_keyword("DATEADD");
18700 self.write("(");
18701 self.write_redshift_date_part(&func.args[0]);
18703 self.write(", ");
18704 self.generate_expression(&func.args[1])?;
18705 self.write(", ");
18706 self.generate_expression(&func.args[2])?;
18707 self.write(")");
18708 return Ok(());
18709 }
18710
18711 if func.name.eq_ignore_ascii_case("UUID_STRING")
18713 && !matches!(self.config.dialect, Some(DialectType::Snowflake) | None)
18714 {
18715 if matches!(
18716 self.config.dialect,
18717 Some(DialectType::Hive | DialectType::Spark | DialectType::Databricks)
18718 ) {
18719 self.write_keyword("CAST");
18720 self.write("(");
18721 self.write_keyword("UUID");
18722 self.write("() ");
18723 self.write_keyword("AS");
18724 self.write(" ");
18725 self.write_keyword("STRING");
18726 self.write(")");
18727 return Ok(());
18728 }
18729
18730 if matches!(
18731 self.config.dialect,
18732 Some(DialectType::Presto | DialectType::Trino)
18733 ) {
18734 self.write_keyword("CAST");
18735 self.write("(");
18736 self.write_keyword("UUID");
18737 self.write("() ");
18738 self.write_keyword("AS");
18739 self.write(" ");
18740 self.write_keyword("VARCHAR");
18741 self.write(")");
18742 return Ok(());
18743 }
18744
18745 if self.config.dialect == Some(DialectType::DuckDB) && func.args.len() == 2 {
18746 self.write("(SELECT LOWER(SUBSTRING(h, 1, 8) || '-' || SUBSTRING(h, 9, 4) || '-' || '5' || SUBSTRING(h, 14, 3) || '-' || FORMAT('{:02x}', CAST('0x' || SUBSTRING(h, 17, 2) AS INT) & 63 | 128) || SUBSTRING(h, 19, 2) || '-' || SUBSTRING(h, 21, 12)) FROM (SELECT SUBSTRING(SHA1(UNHEX(REPLACE(");
18747 self.generate_expression(&func.args[0])?;
18748 self.write(", '-', '')) || ENCODE(");
18749 self.generate_expression(&func.args[1])?;
18750 self.write(")), 1, 32) AS h))");
18751 return Ok(());
18752 }
18753
18754 let func_name = match self.config.dialect {
18755 Some(DialectType::PostgreSQL) | Some(DialectType::Redshift) => "GEN_RANDOM_UUID",
18756 Some(DialectType::BigQuery) => "GENERATE_UUID",
18757 _ => "UUID",
18758 };
18759 self.write_keyword(func_name);
18760 self.write("()");
18761 return Ok(());
18762 }
18763
18764 if matches!(self.config.dialect, Some(DialectType::Snowflake))
18768 && func.name.eq_ignore_ascii_case("GENERATOR")
18769 {
18770 let has_positional_args =
18771 !func.args.is_empty() && !matches!(&func.args[0], Expression::NamedArgument(_));
18772 if has_positional_args {
18773 let param_names = ["ROWCOUNT", "TIMELIMIT"];
18774 self.write_keyword("GENERATOR");
18775 self.write("(");
18776 for (i, arg) in func.args.iter().enumerate() {
18777 if i > 0 {
18778 self.write(", ");
18779 }
18780 if i < param_names.len() {
18781 self.write_keyword(param_names[i]);
18782 self.write(" => ");
18783 self.generate_expression(arg)?;
18784 } else {
18785 self.generate_expression(arg)?;
18786 }
18787 }
18788 self.write(")");
18789 return Ok(());
18790 }
18791 }
18792
18793 if self.config.dialect == Some(DialectType::Redshift)
18796 && func.name.eq_ignore_ascii_case("DATE_TRUNC")
18797 && func.args.len() == 2
18798 {
18799 self.write_keyword("DATE_TRUNC");
18800 self.write("(");
18801 self.write_redshift_date_part_quoted(&func.args[0]);
18803 self.write(", ");
18804 self.generate_expression(&func.args[1])?;
18805 self.write(")");
18806 return Ok(());
18807 }
18808
18809 if matches!(
18811 self.config.dialect,
18812 Some(DialectType::TSQL) | Some(DialectType::Fabric)
18813 ) && (func.name.eq_ignore_ascii_case("DATE_PART")
18814 || func.name.eq_ignore_ascii_case("DATEPART"))
18815 && func.args.len() == 2
18816 {
18817 if let Some(part) = self.extract_date_part_string(&func.args[0]) {
18818 let date_part = self.classify_tsql_date_part_name(&part);
18819 self.generate_tsql_date_part(date_part, &func.args[1])?;
18820 } else {
18821 self.write_keyword("DATEPART");
18822 self.write("(");
18823 self.generate_expression(&func.args[0])?;
18824 self.write(", ");
18825 self.generate_expression(&func.args[1])?;
18826 self.write(")");
18827 }
18828 return Ok(());
18829 }
18830
18831 if matches!(
18833 self.config.dialect,
18834 Some(DialectType::TSQL) | Some(DialectType::Fabric)
18835 ) && (func.name.eq_ignore_ascii_case("DATETRUNC")
18836 || func.name.eq_ignore_ascii_case("DATE_TRUNC"))
18837 && func.args.len() == 2
18838 {
18839 if let Some(part) = self.extract_date_part_string(&func.args[0]) {
18840 let date_part = self.classify_tsql_date_trunc_name(&part);
18841 self.generate_tsql_date_trunc(date_part, &func.args[1])?;
18842 } else {
18843 self.write_keyword("DATETRUNC");
18844 self.write("(");
18845 self.generate_expression(&func.args[0])?;
18846 self.write(", ");
18847 self.generate_expression(&func.args[1])?;
18848 self.write(")");
18849 }
18850 return Ok(());
18851 }
18852
18853 if matches!(
18855 self.config.dialect,
18856 Some(DialectType::PostgreSQL) | Some(DialectType::Redshift)
18857 ) && (func.name.eq_ignore_ascii_case("DATE_PART")
18858 || func.name.eq_ignore_ascii_case("DATEPART"))
18859 && func.args.len() == 2
18860 {
18861 self.write_keyword("EXTRACT");
18862 self.write("(");
18863 match &func.args[0] {
18865 Expression::Literal(lit)
18866 if matches!(lit.as_ref(), crate::expressions::Literal::String(_)) =>
18867 {
18868 let crate::expressions::Literal::String(s) = lit.as_ref() else {
18869 unreachable!()
18870 };
18871 self.write(&s.to_ascii_lowercase());
18872 }
18873 _ => self.generate_expression(&func.args[0])?,
18874 }
18875 self.write_space();
18876 self.write_keyword("FROM");
18877 self.write_space();
18878 self.generate_expression(&func.args[1])?;
18879 self.write(")");
18880 return Ok(());
18881 }
18882
18883 if self.config.dialect == Some(DialectType::PostgreSQL)
18885 && matches!(
18886 func.name.to_ascii_uppercase().as_str(),
18887 "DATE_ADD" | "DATE_SUB"
18888 )
18889 && func.args.len() == 2
18890 && matches!(func.args[1], Expression::Interval(_))
18891 {
18892 self.generate_expression(&func.args[0])?;
18893 self.write_space();
18894 if func.name.eq_ignore_ascii_case("DATE_SUB") {
18895 self.write("-");
18896 } else {
18897 self.write("+");
18898 }
18899 self.write_space();
18900 self.generate_expression(&func.args[1])?;
18901 return Ok(());
18902 }
18903
18904 if self.config.dialect == Some(DialectType::Dremio)
18907 && (func.name.eq_ignore_ascii_case("DATE_PART")
18908 || func.name.eq_ignore_ascii_case("DATEPART"))
18909 && func.args.len() == 2
18910 {
18911 self.write_keyword("EXTRACT");
18912 self.write("(");
18913 self.generate_expression(&func.args[0])?;
18914 self.write_space();
18915 self.write_keyword("FROM");
18916 self.write_space();
18917 self.generate_dremio_date_expression(&func.args[1])?;
18919 self.write(")");
18920 return Ok(());
18921 }
18922
18923 if self.config.dialect == Some(DialectType::Dremio)
18925 && func.name.eq_ignore_ascii_case("CURRENT_DATE_UTC")
18926 && func.args.is_empty()
18927 {
18928 self.write_keyword("CURRENT_DATE_UTC");
18929 return Ok(());
18930 }
18931
18932 if self.config.dialect == Some(DialectType::Dremio)
18936 && func.name.eq_ignore_ascii_case("DATETYPE")
18937 && func.args.len() == 3
18938 {
18939 fn get_int_literal(expr: &Expression) -> Option<i64> {
18941 if let Expression::Literal(lit) = expr {
18942 if let crate::expressions::Literal::Number(s) = lit.as_ref() {
18943 s.parse::<i64>().ok()
18944 } else {
18945 None
18946 }
18947 } else {
18948 None
18949 }
18950 }
18951
18952 if let (Some(year), Some(month), Some(day)) = (
18954 get_int_literal(&func.args[0]),
18955 get_int_literal(&func.args[1]),
18956 get_int_literal(&func.args[2]),
18957 ) {
18958 self.write_keyword("DATE");
18960 self.write(&format!("('{:04}-{:02}-{:02}')", year, month, day));
18961 return Ok(());
18962 }
18963
18964 self.write_keyword("CAST");
18966 self.write("(");
18967 self.write_keyword("CONCAT");
18968 self.write("(");
18969 self.generate_expression(&func.args[0])?;
18970 self.write(", '-', ");
18971 self.generate_expression(&func.args[1])?;
18972 self.write(", '-', ");
18973 self.generate_expression(&func.args[2])?;
18974 self.write(")");
18975 self.write_space();
18976 self.write_keyword("AS");
18977 self.write_space();
18978 self.write_keyword("DATE");
18979 self.write(")");
18980 return Ok(());
18981 }
18982
18983 let is_presto_like = matches!(
18986 self.config.dialect,
18987 Some(DialectType::Presto) | Some(DialectType::Trino)
18988 );
18989 if is_presto_like && func.name.eq_ignore_ascii_case("DATE_ADD") && func.args.len() == 3 {
18990 self.write_keyword("DATE_ADD");
18991 self.write("(");
18992 self.generate_expression(&func.args[0])?;
18994 self.write(", ");
18995 let interval = &func.args[1];
18997 let needs_cast = !self.returns_integer_type(interval);
18998 if needs_cast {
18999 self.write_keyword("CAST");
19000 self.write("(");
19001 }
19002 self.generate_expression(interval)?;
19003 if needs_cast {
19004 self.write_space();
19005 self.write_keyword("AS");
19006 self.write_space();
19007 self.write_keyword("BIGINT");
19008 self.write(")");
19009 }
19010 self.write(", ");
19011 self.generate_expression(&func.args[2])?;
19013 self.write(")");
19014 return Ok(());
19015 }
19016
19017 let use_brackets = func.use_bracket_syntax;
19019
19020 let has_ordinality = func.name.len() >= 16
19025 && func.name[func.name.len() - 16..].eq_ignore_ascii_case(" WITH ORDINALITY");
19026 let output_name = if has_ordinality {
19027 let base_name = &func.name[..func.name.len() - " WITH ORDINALITY".len()];
19028 self.normalize_func_name(base_name)
19029 } else {
19030 normalized_name.clone()
19031 };
19032
19033 let quote_source_clickhouse_function =
19036 matches!(self.config.dialect, Some(DialectType::ClickHouse))
19037 && matches!(self.config.source_dialect, Some(DialectType::ClickHouse))
19038 && func.quoted;
19039
19040 if quote_source_clickhouse_function {
19041 self.generate_identifier(&Identifier {
19042 name: func.name.clone(),
19043 quoted: true,
19044 trailing_comments: Vec::new(),
19045 span: None,
19046 })?;
19047 } else if func.name.contains('.') && !has_ordinality {
19048 if func.quoted {
19051 self.write("`");
19052 self.write(&func.name);
19053 self.write("`");
19054 } else {
19055 self.write(&func.name);
19056 }
19057 } else {
19058 self.write(&output_name);
19059 }
19060
19061 let force_parens = func.no_parens && func.args.is_empty() && !func.distinct && {
19064 let needs_parens = if func.name.eq_ignore_ascii_case("CURRENT_USER")
19065 || func.name.eq_ignore_ascii_case("SESSION_USER")
19066 || func.name.eq_ignore_ascii_case("SYSTEM_USER")
19067 {
19068 matches!(
19069 self.config.dialect,
19070 Some(DialectType::Snowflake)
19071 | Some(DialectType::Spark)
19072 | Some(DialectType::Databricks)
19073 | Some(DialectType::Hive)
19074 )
19075 } else {
19076 false
19077 };
19078 !needs_parens
19079 };
19080 if force_parens {
19081 for comment in &func.trailing_comments {
19083 self.write_space();
19084 self.write_formatted_comment(comment);
19085 }
19086 return Ok(());
19087 }
19088
19089 if func.name.eq_ignore_ascii_case("CUBE")
19091 || func.name.eq_ignore_ascii_case("ROLLUP")
19092 || func.name.eq_ignore_ascii_case("GROUPING SETS")
19093 {
19094 self.write(" (");
19095 } else if use_brackets {
19096 self.write("[");
19097 } else {
19098 self.write("(");
19099 }
19100 if func.distinct {
19101 self.write_keyword("DISTINCT");
19102 self.write_space();
19103 }
19104
19105 let compact_pretty_func = matches!(self.config.dialect, Some(DialectType::Snowflake))
19107 && (func.name.eq_ignore_ascii_case("TABLE")
19108 || func.name.eq_ignore_ascii_case("FLATTEN"));
19109 let is_grouping_func = func.name.eq_ignore_ascii_case("GROUPING SETS")
19111 || func.name.eq_ignore_ascii_case("CUBE")
19112 || func.name.eq_ignore_ascii_case("ROLLUP");
19113 let should_split = if self.config.pretty && !func.args.is_empty() && !compact_pretty_func {
19114 if is_grouping_func {
19115 true
19116 } else {
19117 let mut expr_strings: Vec<String> = Vec::with_capacity(func.args.len());
19119 for arg in &func.args {
19120 let mut temp_gen = Generator::with_arc_config(self.config.clone());
19121 Arc::make_mut(&mut temp_gen.config).pretty = false; temp_gen.generate_expression(arg)?;
19123 expr_strings.push(temp_gen.output);
19124 }
19125 self.too_wide(&expr_strings)
19126 }
19127 } else {
19128 false
19129 };
19130
19131 if should_split {
19132 self.write_newline();
19134 self.indent_level += 1;
19135 for (i, arg) in func.args.iter().enumerate() {
19136 self.write_indent();
19137 self.generate_expression(arg)?;
19138 if i + 1 < func.args.len() {
19139 self.write(",");
19140 }
19141 self.write_newline();
19142 }
19143 self.indent_level -= 1;
19144 self.write_indent();
19145 } else {
19146 for (i, arg) in func.args.iter().enumerate() {
19148 if i > 0 {
19149 self.write(", ");
19150 }
19151 self.generate_expression(arg)?;
19152 }
19153 }
19154
19155 if use_brackets {
19156 self.write("]");
19157 } else {
19158 self.write(")");
19159 }
19160 if has_ordinality {
19162 self.write_space();
19163 self.write_keyword("WITH ORDINALITY");
19164 }
19165 for comment in &func.trailing_comments {
19167 self.write_space();
19168 self.write_formatted_comment(comment);
19169 }
19170 Ok(())
19171 }
19172
19173 fn generate_function_emits(&mut self, fe: &FunctionEmits) -> Result<()> {
19174 self.generate_expression(&fe.this)?;
19175 self.write_keyword(" EMITS ");
19176 self.generate_expression(&fe.emits)?;
19177 Ok(())
19178 }
19179
19180 fn generate_aggregate_function(&mut self, func: &AggregateFunction) -> Result<()> {
19181 let mut normalized_name = self.normalize_func_name(&func.name);
19183
19184 if func.name.eq_ignore_ascii_case("MAX_BY") || func.name.eq_ignore_ascii_case("MIN_BY") {
19186 let is_max = func.name.eq_ignore_ascii_case("MAX_BY");
19187 match self.config.dialect {
19188 Some(DialectType::ClickHouse) => {
19189 normalized_name = if is_max {
19190 Cow::Borrowed("argMax")
19191 } else {
19192 Cow::Borrowed("argMin")
19193 };
19194 }
19195 Some(DialectType::DuckDB) => {
19196 normalized_name = if is_max {
19197 Cow::Borrowed("ARG_MAX")
19198 } else {
19199 Cow::Borrowed("ARG_MIN")
19200 };
19201 }
19202 _ => {}
19203 }
19204 }
19205 self.write(normalized_name.as_ref());
19206 self.write("(");
19207 if func.distinct {
19208 self.write_keyword("DISTINCT");
19209 self.write_space();
19210 }
19211
19212 let is_count = normalized_name.eq_ignore_ascii_case("COUNT");
19216 let needs_multi_arg_transform =
19217 func.distinct && is_count && func.args.len() > 1 && !self.config.multi_arg_distinct;
19218
19219 if needs_multi_arg_transform {
19220 self.write_keyword("CASE");
19222 for arg in &func.args {
19223 self.write_space();
19224 self.write_keyword("WHEN");
19225 self.write_space();
19226 self.generate_expression(arg)?;
19227 self.write_space();
19228 self.write_keyword("IS NULL THEN NULL");
19229 }
19230 self.write_space();
19231 self.write_keyword("ELSE");
19232 self.write(" (");
19233 for (i, arg) in func.args.iter().enumerate() {
19234 if i > 0 {
19235 self.write(", ");
19236 }
19237 self.generate_expression(arg)?;
19238 }
19239 self.write(")");
19240 self.write_space();
19241 self.write_keyword("END");
19242 } else {
19243 for (i, arg) in func.args.iter().enumerate() {
19244 if i > 0 {
19245 self.write(", ");
19246 }
19247 self.generate_expression(arg)?;
19248 }
19249 }
19250
19251 let clickhouse_ignore_nulls_outside =
19253 matches!(self.config.dialect, Some(DialectType::ClickHouse));
19254 if self.config.ignore_nulls_in_func
19255 && !matches!(
19256 self.config.dialect,
19257 Some(DialectType::DuckDB) | Some(DialectType::ClickHouse)
19258 )
19259 {
19260 if let Some(ignore) = func.ignore_nulls {
19261 self.write_space();
19262 if ignore {
19263 self.write_keyword("IGNORE NULLS");
19264 } else {
19265 self.write_keyword("RESPECT NULLS");
19266 }
19267 }
19268 }
19269
19270 if !func.order_by.is_empty() {
19272 self.write_space();
19273 self.write_keyword("ORDER BY");
19274 self.write_space();
19275 for (i, ord) in func.order_by.iter().enumerate() {
19276 if i > 0 {
19277 self.write(", ");
19278 }
19279 self.generate_ordered(ord)?;
19280 }
19281 }
19282
19283 if let Some(limit) = &func.limit {
19285 self.write_space();
19286 self.write_keyword("LIMIT");
19287 self.write_space();
19288 if let Expression::Tuple(t) = limit.as_ref() {
19290 if t.expressions.len() == 2 {
19291 self.generate_expression(&t.expressions[0])?;
19292 self.write(", ");
19293 self.generate_expression(&t.expressions[1])?;
19294 } else {
19295 self.generate_expression(limit)?;
19296 }
19297 } else {
19298 self.generate_expression(limit)?;
19299 }
19300 }
19301
19302 self.write(")");
19303
19304 if (!self.config.ignore_nulls_in_func || clickhouse_ignore_nulls_outside)
19306 && !matches!(self.config.dialect, Some(DialectType::DuckDB))
19307 {
19308 if let Some(ignore) = func.ignore_nulls {
19309 self.write_space();
19310 if ignore {
19311 self.write_keyword("IGNORE NULLS");
19312 } else {
19313 self.write_keyword("RESPECT NULLS");
19314 }
19315 }
19316 }
19317
19318 if let Some(filter) = &func.filter {
19319 self.write_space();
19320 self.write_keyword("FILTER");
19321 self.write("(");
19322 self.write_keyword("WHERE");
19323 self.write_space();
19324 self.generate_expression(filter)?;
19325 self.write(")");
19326 }
19327
19328 Ok(())
19329 }
19330
19331 fn generate_window_function(&mut self, wf: &WindowFunction) -> Result<()> {
19332 self.generate_expression(&wf.this)?;
19333
19334 if let Some(keep) = &wf.keep {
19336 self.write_space();
19337 self.write_keyword("KEEP");
19338 self.write(" (");
19339 self.write_keyword("DENSE_RANK");
19340 self.write_space();
19341 if keep.first {
19342 self.write_keyword("FIRST");
19343 } else {
19344 self.write_keyword("LAST");
19345 }
19346 self.write_space();
19347 self.write_keyword("ORDER BY");
19348 self.write_space();
19349 for (i, ord) in keep.order_by.iter().enumerate() {
19350 if i > 0 {
19351 self.write(", ");
19352 }
19353 self.generate_ordered(ord)?;
19354 }
19355 self.write(")");
19356 }
19357
19358 let has_over = !wf.over.partition_by.is_empty()
19360 || !wf.over.order_by.is_empty()
19361 || wf.over.frame.is_some()
19362 || wf.over.window_name.is_some();
19363
19364 if has_over {
19366 self.write_space();
19367 self.write_keyword("OVER");
19368
19369 let has_specs = !wf.over.partition_by.is_empty()
19371 || !wf.over.order_by.is_empty()
19372 || wf.over.frame.is_some();
19373
19374 if wf.over.window_name.is_some() && !has_specs {
19375 self.write_space();
19377 self.write(&wf.over.window_name.as_ref().unwrap().name);
19378 } else {
19379 self.write(" (");
19381 self.generate_over(&wf.over)?;
19382 self.write(")");
19383 }
19384 } else if wf.keep.is_none() {
19385 self.write_space();
19387 self.write_keyword("OVER");
19388 self.write(" ()");
19389 }
19390
19391 Ok(())
19392 }
19393
19394 fn generate_within_group(&mut self, wg: &WithinGroup) -> Result<()> {
19396 self.generate_expression(&wg.this)?;
19397 self.write_space();
19398 self.write_keyword("WITHIN GROUP");
19399 self.write(" (");
19400 self.write_keyword("ORDER BY");
19401 self.write_space();
19402 for (i, ord) in wg.order_by.iter().enumerate() {
19403 if i > 0 {
19404 self.write(", ");
19405 }
19406 self.generate_ordered(ord)?;
19407 }
19408 self.write(")");
19409 Ok(())
19410 }
19411
19412 fn generate_over(&mut self, over: &Over) -> Result<()> {
19414 let mut has_content = false;
19415
19416 if let Some(name) = &over.window_name {
19418 self.write(&name.name);
19419 has_content = true;
19420 }
19421
19422 if !over.partition_by.is_empty() {
19424 if has_content {
19425 self.write_space();
19426 }
19427 self.write_keyword("PARTITION BY");
19428 self.write_space();
19429 for (i, expr) in over.partition_by.iter().enumerate() {
19430 if i > 0 {
19431 self.write(", ");
19432 }
19433 self.generate_expression(expr)?;
19434 }
19435 has_content = true;
19436 }
19437
19438 if !over.order_by.is_empty() {
19440 if has_content {
19441 self.write_space();
19442 }
19443 self.write_keyword("ORDER BY");
19444 self.write_space();
19445 for (i, ordered) in over.order_by.iter().enumerate() {
19446 if i > 0 {
19447 self.write(", ");
19448 }
19449 self.generate_ordered(ordered)?;
19450 }
19451 has_content = true;
19452 }
19453
19454 if let Some(frame) = &over.frame {
19456 if has_content {
19457 self.write_space();
19458 }
19459 self.generate_window_frame(frame)?;
19460 }
19461
19462 Ok(())
19463 }
19464
19465 fn generate_window_frame(&mut self, frame: &WindowFrame) -> Result<()> {
19466 let lowercase_frame = self.config.lowercase_window_frame_keywords;
19468
19469 if !lowercase_frame {
19471 if let Some(kind_text) = &frame.kind_text {
19472 self.write(kind_text);
19473 } else {
19474 match frame.kind {
19475 WindowFrameKind::Rows => self.write_keyword("ROWS"),
19476 WindowFrameKind::Range => self.write_keyword("RANGE"),
19477 WindowFrameKind::Groups => self.write_keyword("GROUPS"),
19478 }
19479 }
19480 } else {
19481 match frame.kind {
19482 WindowFrameKind::Rows => self.write("rows"),
19483 WindowFrameKind::Range => self.write("range"),
19484 WindowFrameKind::Groups => self.write("groups"),
19485 }
19486 }
19487
19488 self.write_space();
19491 let should_normalize = self.config.normalize_window_frame_between
19492 && frame.end.is_none()
19493 && matches!(
19494 frame.start,
19495 WindowFrameBound::Preceding(_)
19496 | WindowFrameBound::Following(_)
19497 | WindowFrameBound::UnboundedPreceding
19498 | WindowFrameBound::UnboundedFollowing
19499 );
19500
19501 if let Some(end) = &frame.end {
19502 self.write_keyword("BETWEEN");
19504 self.write_space();
19505 self.generate_window_frame_bound(&frame.start, frame.start_side_text.as_deref())?;
19506 self.write_space();
19507 self.write_keyword("AND");
19508 self.write_space();
19509 self.generate_window_frame_bound(end, frame.end_side_text.as_deref())?;
19510 } else if should_normalize {
19511 self.write_keyword("BETWEEN");
19513 self.write_space();
19514 self.generate_window_frame_bound(&frame.start, frame.start_side_text.as_deref())?;
19515 self.write_space();
19516 self.write_keyword("AND");
19517 self.write_space();
19518 self.write_keyword("CURRENT ROW");
19519 } else {
19520 self.generate_window_frame_bound(&frame.start, frame.start_side_text.as_deref())?;
19522 }
19523
19524 if let Some(exclude) = &frame.exclude {
19526 self.write_space();
19527 self.write_keyword("EXCLUDE");
19528 self.write_space();
19529 match exclude {
19530 WindowFrameExclude::CurrentRow => self.write_keyword("CURRENT ROW"),
19531 WindowFrameExclude::Group => self.write_keyword("GROUP"),
19532 WindowFrameExclude::Ties => self.write_keyword("TIES"),
19533 WindowFrameExclude::NoOthers => self.write_keyword("NO OTHERS"),
19534 }
19535 }
19536
19537 Ok(())
19538 }
19539
19540 fn generate_window_frame_bound(
19541 &mut self,
19542 bound: &WindowFrameBound,
19543 side_text: Option<&str>,
19544 ) -> Result<()> {
19545 let lowercase_frame = self.config.lowercase_window_frame_keywords;
19547
19548 match bound {
19549 WindowFrameBound::CurrentRow => {
19550 self.write_keyword("CURRENT ROW");
19551 }
19552 WindowFrameBound::UnboundedPreceding => {
19553 self.write_keyword("UNBOUNDED");
19554 self.write_space();
19555 if lowercase_frame {
19556 self.write("preceding");
19557 } else if let Some(text) = side_text {
19558 self.write(text);
19559 } else {
19560 self.write_keyword("PRECEDING");
19561 }
19562 }
19563 WindowFrameBound::UnboundedFollowing => {
19564 self.write_keyword("UNBOUNDED");
19565 self.write_space();
19566 if lowercase_frame {
19567 self.write("following");
19568 } else if let Some(text) = side_text {
19569 self.write(text);
19570 } else {
19571 self.write_keyword("FOLLOWING");
19572 }
19573 }
19574 WindowFrameBound::Preceding(expr) => {
19575 self.generate_expression(expr)?;
19576 self.write_space();
19577 if lowercase_frame {
19578 self.write("preceding");
19579 } else if let Some(text) = side_text {
19580 self.write(text);
19581 } else {
19582 self.write_keyword("PRECEDING");
19583 }
19584 }
19585 WindowFrameBound::Following(expr) => {
19586 self.generate_expression(expr)?;
19587 self.write_space();
19588 if lowercase_frame {
19589 self.write("following");
19590 } else if let Some(text) = side_text {
19591 self.write(text);
19592 } else {
19593 self.write_keyword("FOLLOWING");
19594 }
19595 }
19596 WindowFrameBound::BarePreceding => {
19597 if lowercase_frame {
19598 self.write("preceding");
19599 } else if let Some(text) = side_text {
19600 self.write(text);
19601 } else {
19602 self.write_keyword("PRECEDING");
19603 }
19604 }
19605 WindowFrameBound::BareFollowing => {
19606 if lowercase_frame {
19607 self.write("following");
19608 } else if let Some(text) = side_text {
19609 self.write(text);
19610 } else {
19611 self.write_keyword("FOLLOWING");
19612 }
19613 }
19614 WindowFrameBound::Value(expr) => {
19615 self.generate_expression(expr)?;
19617 }
19618 }
19619 Ok(())
19620 }
19621
19622 fn generate_interval(&mut self, interval: &Interval) -> Result<()> {
19623 let skip_interval_keyword = matches!(self.config.dialect, Some(DialectType::Oracle))
19626 && matches!(&interval.unit, Some(IntervalUnitSpec::ExprSpan(_)))
19627 && !matches!(&interval.this, Some(Expression::Literal(_)));
19628
19629 if self.config.single_string_interval {
19632 if let (
19633 Some(Expression::Literal(lit)),
19634 Some(IntervalUnitSpec::Simple {
19635 ref unit,
19636 ref use_plural,
19637 }),
19638 ) = (&interval.this, &interval.unit)
19639 {
19640 if let Literal::String(ref val) = lit.as_ref() {
19641 self.write_keyword("INTERVAL");
19642 self.write_space();
19643 let effective_plural = *use_plural && self.config.interval_allows_plural_form;
19644 let unit_str = self.interval_unit_str(unit, effective_plural);
19645 self.write("'");
19646 self.write(val);
19647 self.write(" ");
19648 self.write(&unit_str);
19649 self.write("'");
19650 return Ok(());
19651 }
19652 }
19653 }
19654
19655 if !skip_interval_keyword {
19656 self.write_keyword("INTERVAL");
19657 }
19658
19659 if let Some(ref value) = interval.this {
19661 if !skip_interval_keyword {
19662 self.write_space();
19663 }
19664 let needs_parens = interval.unit.is_some()
19668 && matches!(
19669 value,
19670 Expression::Add(_)
19671 | Expression::Sub(_)
19672 | Expression::Mul(_)
19673 | Expression::Div(_)
19674 | Expression::Mod(_)
19675 | Expression::BitwiseAnd(_)
19676 | Expression::BitwiseOr(_)
19677 | Expression::BitwiseXor(_)
19678 );
19679 if needs_parens {
19680 self.write("(");
19681 }
19682 self.generate_expression(value)?;
19683 if needs_parens {
19684 self.write(")");
19685 }
19686 }
19687
19688 if let Some(ref unit_spec) = interval.unit {
19690 self.write_space();
19691 self.write_interval_unit_spec(unit_spec)?;
19692 }
19693
19694 Ok(())
19695 }
19696
19697 fn interval_unit_str(&self, unit: &IntervalUnit, use_plural: bool) -> &'static str {
19699 match (unit, use_plural) {
19700 (IntervalUnit::Year, false) => "YEAR",
19701 (IntervalUnit::Year, true) => "YEARS",
19702 (IntervalUnit::Quarter, false) => "QUARTER",
19703 (IntervalUnit::Quarter, true) => "QUARTERS",
19704 (IntervalUnit::Month, false) => "MONTH",
19705 (IntervalUnit::Month, true) => "MONTHS",
19706 (IntervalUnit::Week, false) => "WEEK",
19707 (IntervalUnit::Week, true) => "WEEKS",
19708 (IntervalUnit::Day, false) => "DAY",
19709 (IntervalUnit::Day, true) => "DAYS",
19710 (IntervalUnit::Hour, false) => "HOUR",
19711 (IntervalUnit::Hour, true) => "HOURS",
19712 (IntervalUnit::Minute, false) => "MINUTE",
19713 (IntervalUnit::Minute, true) => "MINUTES",
19714 (IntervalUnit::Second, false) => "SECOND",
19715 (IntervalUnit::Second, true) => "SECONDS",
19716 (IntervalUnit::Millisecond, false) => "MILLISECOND",
19717 (IntervalUnit::Millisecond, true) => "MILLISECONDS",
19718 (IntervalUnit::Microsecond, false) => "MICROSECOND",
19719 (IntervalUnit::Microsecond, true) => "MICROSECONDS",
19720 (IntervalUnit::Nanosecond, false) => "NANOSECOND",
19721 (IntervalUnit::Nanosecond, true) => "NANOSECONDS",
19722 }
19723 }
19724
19725 fn write_interval_unit_spec(&mut self, unit_spec: &IntervalUnitSpec) -> Result<()> {
19726 match unit_spec {
19727 IntervalUnitSpec::Simple { unit, use_plural } => {
19728 let effective_plural = *use_plural && self.config.interval_allows_plural_form;
19730 self.write_simple_interval_unit(unit, effective_plural);
19731 }
19732 IntervalUnitSpec::Span(span) => {
19733 self.write_simple_interval_unit(&span.this, false);
19734 self.write_space();
19735 self.write_keyword("TO");
19736 self.write_space();
19737 self.write_simple_interval_unit(&span.expression, false);
19738 }
19739 IntervalUnitSpec::ExprSpan(span) => {
19740 self.generate_expression(&span.this)?;
19742 self.write_space();
19743 self.write_keyword("TO");
19744 self.write_space();
19745 self.generate_expression(&span.expression)?;
19746 }
19747 IntervalUnitSpec::Expr(expr) => {
19748 self.generate_expression(expr)?;
19749 }
19750 }
19751 Ok(())
19752 }
19753
19754 fn write_simple_interval_unit(&mut self, unit: &IntervalUnit, use_plural: bool) {
19755 match (unit, use_plural) {
19757 (IntervalUnit::Year, false) => self.write_keyword("YEAR"),
19758 (IntervalUnit::Year, true) => self.write_keyword("YEARS"),
19759 (IntervalUnit::Quarter, false) => self.write_keyword("QUARTER"),
19760 (IntervalUnit::Quarter, true) => self.write_keyword("QUARTERS"),
19761 (IntervalUnit::Month, false) => self.write_keyword("MONTH"),
19762 (IntervalUnit::Month, true) => self.write_keyword("MONTHS"),
19763 (IntervalUnit::Week, false) => self.write_keyword("WEEK"),
19764 (IntervalUnit::Week, true) => self.write_keyword("WEEKS"),
19765 (IntervalUnit::Day, false) => self.write_keyword("DAY"),
19766 (IntervalUnit::Day, true) => self.write_keyword("DAYS"),
19767 (IntervalUnit::Hour, false) => self.write_keyword("HOUR"),
19768 (IntervalUnit::Hour, true) => self.write_keyword("HOURS"),
19769 (IntervalUnit::Minute, false) => self.write_keyword("MINUTE"),
19770 (IntervalUnit::Minute, true) => self.write_keyword("MINUTES"),
19771 (IntervalUnit::Second, false) => self.write_keyword("SECOND"),
19772 (IntervalUnit::Second, true) => self.write_keyword("SECONDS"),
19773 (IntervalUnit::Millisecond, false) => self.write_keyword("MILLISECOND"),
19774 (IntervalUnit::Millisecond, true) => self.write_keyword("MILLISECONDS"),
19775 (IntervalUnit::Microsecond, false) => self.write_keyword("MICROSECOND"),
19776 (IntervalUnit::Microsecond, true) => self.write_keyword("MICROSECONDS"),
19777 (IntervalUnit::Nanosecond, false) => self.write_keyword("NANOSECOND"),
19778 (IntervalUnit::Nanosecond, true) => self.write_keyword("NANOSECONDS"),
19779 }
19780 }
19781
19782 fn write_redshift_date_part(&mut self, expr: &Expression) {
19785 let part_str = self.extract_date_part_string(expr);
19786 if let Some(part) = part_str {
19787 let normalized = self.normalize_date_part(&part);
19788 self.write_keyword(&normalized);
19789 } else {
19790 let _ = self.generate_expression(expr);
19792 }
19793 }
19794
19795 fn write_redshift_date_part_quoted(&mut self, expr: &Expression) {
19798 let part_str = self.extract_date_part_string(expr);
19799 if let Some(part) = part_str {
19800 let normalized = self.normalize_date_part(&part);
19801 self.write("'");
19802 self.write(&normalized);
19803 self.write("'");
19804 } else {
19805 let _ = self.generate_expression(expr);
19807 }
19808 }
19809
19810 fn extract_date_part_string(&self, expr: &Expression) -> Option<String> {
19812 match expr {
19813 Expression::Literal(lit)
19814 if matches!(lit.as_ref(), crate::expressions::Literal::String(_)) =>
19815 {
19816 let crate::expressions::Literal::String(s) = lit.as_ref() else {
19817 unreachable!()
19818 };
19819 Some(s.clone())
19820 }
19821 Expression::Identifier(id) => Some(id.name.clone()),
19822 Expression::Var(v) => Some(v.this.clone()),
19823 Expression::Column(col) if col.table.is_none() => {
19824 Some(col.name.name.clone())
19826 }
19827 Expression::Cast(cast)
19828 if cast.format.is_none()
19829 && cast.default.is_none()
19830 && Self::is_string_data_type(&cast.to)
19831 && matches!(
19832 &cast.this,
19833 Expression::Literal(lit)
19834 if matches!(lit.as_ref(), crate::expressions::Literal::String(_))
19835 ) =>
19836 {
19837 self.extract_date_part_string(&cast.this)
19838 }
19839 _ => None,
19840 }
19841 }
19842
19843 fn classify_tsql_datetime_field(&self, field: &DateTimeField) -> TsqlDatePart {
19844 match field {
19845 DateTimeField::Year => TsqlDatePart::Native("YEAR".to_string()),
19846 DateTimeField::Month => TsqlDatePart::Native("MONTH".to_string()),
19847 DateTimeField::Day => TsqlDatePart::Native("DAY".to_string()),
19848 DateTimeField::Hour => TsqlDatePart::Native("HOUR".to_string()),
19849 DateTimeField::Minute => TsqlDatePart::Native("MINUTE".to_string()),
19850 DateTimeField::Second => TsqlDatePart::Native("SECOND".to_string()),
19851 DateTimeField::Millisecond => TsqlDatePart::Native("MILLISECOND".to_string()),
19852 DateTimeField::Microsecond => TsqlDatePart::Native("MICROSECOND".to_string()),
19853 DateTimeField::DayOfWeek => TsqlDatePart::Native("WEEKDAY".to_string()),
19854 DateTimeField::DayOfYear => TsqlDatePart::Native("DAYOFYEAR".to_string()),
19855 DateTimeField::Week => TsqlDatePart::Native("WEEK".to_string()),
19856 DateTimeField::WeekWithModifier(modifier) => {
19857 TsqlDatePart::Unsupported(format!("WEEK({modifier})"))
19858 }
19859 DateTimeField::Quarter => TsqlDatePart::Native("QUARTER".to_string()),
19860 DateTimeField::Epoch => TsqlDatePart::Epoch,
19861 DateTimeField::TimezoneMinute => TsqlDatePart::Native("TZOFFSET".to_string()),
19862 DateTimeField::Timezone => TsqlDatePart::Unsupported("TIMEZONE".to_string()),
19863 DateTimeField::TimezoneHour => TsqlDatePart::Unsupported("TIMEZONE_HOUR".to_string()),
19864 DateTimeField::Date => TsqlDatePart::Unsupported("DATE".to_string()),
19865 DateTimeField::Time => TsqlDatePart::Unsupported("TIME".to_string()),
19866 DateTimeField::Custom(name) => self.classify_tsql_date_part_name(name),
19867 }
19868 }
19869
19870 fn classify_tsql_date_part_name(&self, part: &str) -> TsqlDatePart {
19871 let trimmed = part.trim();
19872 let upper = trimmed.to_ascii_uppercase();
19873 match upper.as_str() {
19874 "YEAR" => TsqlDatePart::Native(trimmed.to_string()),
19875 "YY" | "YYY" | "YYYY" | "YR" | "YEARS" | "YRS" => {
19876 TsqlDatePart::Native("YEAR".to_string())
19877 }
19878 "QUARTER" => TsqlDatePart::Native(trimmed.to_string()),
19879 "Q" | "QQ" | "QTR" | "QTRS" | "QUARTERS" => TsqlDatePart::Native("QUARTER".to_string()),
19880 "MONTH" => TsqlDatePart::Native(trimmed.to_string()),
19881 "MM" | "M" | "MON" | "MONS" | "MONTHS" => TsqlDatePart::Native("MONTH".to_string()),
19882 "DAYOFYEAR" => TsqlDatePart::Native(trimmed.to_string()),
19883 "DOY" | "DY" | "Y" => TsqlDatePart::Native("DAYOFYEAR".to_string()),
19884 "DAY" => TsqlDatePart::Native(trimmed.to_string()),
19885 "D" | "DD" | "DAYS" | "DAYOFMONTH" => TsqlDatePart::Native("DAY".to_string()),
19886 "WEEK" | "W" | "WK" | "WW" | "WEEKOFYEAR" | "WOY" | "WY" | "WEEKS" => {
19887 if upper == "WEEK" {
19888 TsqlDatePart::Native(trimmed.to_string())
19889 } else {
19890 TsqlDatePart::Native("WEEK".to_string())
19891 }
19892 }
19893 "WEEKDAY" => TsqlDatePart::Native(trimmed.to_string()),
19894 "DAYOFWEEK" | "DOW" | "DW" => TsqlDatePart::Native("WEEKDAY".to_string()),
19895 "ISODOW" | "ISO_DOW" | "DOW_ISO" | "DW_ISO" | "ISO_DAYOFWEEK" | "ISO_WEEKDAY"
19896 | "DAYOFWEEKISO" | "DAYOFWEEK_ISO" | "WEEKDAY_ISO" => TsqlDatePart::IsoDayOfWeek,
19897 "HOUR" => TsqlDatePart::Native(trimmed.to_string()),
19898 "H" | "HH" | "HR" | "HOURS" | "HRS" => TsqlDatePart::Native("HOUR".to_string()),
19899 "MINUTE" => TsqlDatePart::Native(trimmed.to_string()),
19900 "MI" | "MIN" | "MINUTES" | "MINS" | "N" => TsqlDatePart::Native("MINUTE".to_string()),
19901 "SECOND" => TsqlDatePart::Native(trimmed.to_string()),
19902 "S" | "SEC" | "SECONDS" | "SECS" | "SS" => TsqlDatePart::Native("SECOND".to_string()),
19903 "MILLISECOND" | "MS" | "MSEC" | "MSECS" | "MSECOND" | "MSECONDS" | "MILLISEC"
19904 | "MILLISECS" | "MILLISECON" | "MILLISECONDS" => {
19905 if upper == "MILLISECOND" {
19906 TsqlDatePart::Native(trimmed.to_string())
19907 } else {
19908 TsqlDatePart::Native("MILLISECOND".to_string())
19909 }
19910 }
19911 "MICROSECOND" | "US" | "USEC" | "USECS" | "MICROSEC" | "MICROSECS" | "USECOND"
19912 | "USECONDS" | "MICROSECONDS" | "MCS" => {
19913 if upper == "MICROSECOND" {
19914 TsqlDatePart::Native(trimmed.to_string())
19915 } else {
19916 TsqlDatePart::Native("MICROSECOND".to_string())
19917 }
19918 }
19919 "NANOSECOND" | "NS" | "NSEC" | "NANOSEC" | "NSECOND" | "NSECONDS" | "NANOSECS" => {
19920 if upper == "NANOSECOND" {
19921 TsqlDatePart::Native(trimmed.to_string())
19922 } else {
19923 TsqlDatePart::Native("NANOSECOND".to_string())
19924 }
19925 }
19926 "TZOFFSET" => TsqlDatePart::Native(trimmed.to_string()),
19927 "TZ" | "TZM" | "TIMEZONE_MINUTE" => TsqlDatePart::Native("TZOFFSET".to_string()),
19928 "ISO_WEEK" | "ISOWEEK" | "ISOWK" | "ISOWW" | "WEEKISO" | "WEEKOFYEARISO"
19929 | "WEEKOFYEAR_ISO" | "WEEK_ISO" => {
19930 if upper == "ISO_WEEK" {
19931 TsqlDatePart::Native(trimmed.to_string())
19932 } else {
19933 TsqlDatePart::Native("ISO_WEEK".to_string())
19934 }
19935 }
19936 "EPOCH" | "EPOCH_SECOND" | "EPOCH_SECONDS" => TsqlDatePart::Epoch,
19937 "DECADE" | "DECADES" | "DEC" | "DECS" | "CENTURY" | "CENTURIES" | "CENT" | "CENTS"
19938 | "MILLENNIUM" | "MILLENIA" | "MIL" | "MILS" | "TIMEZONE" | "TIMEZONE_HOUR" | "TZH"
19939 | "DATE" | "TIME" => TsqlDatePart::Unsupported(upper),
19940 _ => TsqlDatePart::Unsupported(upper),
19941 }
19942 }
19943
19944 fn classify_tsql_date_trunc_field(&self, field: &DateTimeField) -> TsqlDatePart {
19945 match field {
19946 DateTimeField::Year => TsqlDatePart::Native("YEAR".to_string()),
19947 DateTimeField::Month => TsqlDatePart::Native("MONTH".to_string()),
19948 DateTimeField::Day => TsqlDatePart::Native("DAY".to_string()),
19949 DateTimeField::Hour => TsqlDatePart::Native("HOUR".to_string()),
19950 DateTimeField::Minute => TsqlDatePart::Native("MINUTE".to_string()),
19951 DateTimeField::Second => TsqlDatePart::Native("SECOND".to_string()),
19952 DateTimeField::Millisecond => TsqlDatePart::Native("MILLISECOND".to_string()),
19953 DateTimeField::Microsecond => TsqlDatePart::Native("MICROSECOND".to_string()),
19954 DateTimeField::DayOfYear => TsqlDatePart::Native("DAYOFYEAR".to_string()),
19955 DateTimeField::Week => TsqlDatePart::Native("WEEK".to_string()),
19956 DateTimeField::WeekWithModifier(modifier) => {
19957 match modifier.to_ascii_uppercase().as_str() {
19958 "MONDAY" | "ISO" | "ISO_WEEK" => TsqlDatePart::Native("ISO_WEEK".to_string()),
19959 "SUNDAY" => TsqlDatePart::Native("WEEK".to_string()),
19960 _ => TsqlDatePart::Unsupported(format!("WEEK({modifier})")),
19961 }
19962 }
19963 DateTimeField::Quarter => TsqlDatePart::Native("QUARTER".to_string()),
19964 DateTimeField::DayOfWeek => TsqlDatePart::Unsupported("WEEKDAY".to_string()),
19965 DateTimeField::Epoch => TsqlDatePart::Unsupported("EPOCH".to_string()),
19966 DateTimeField::Timezone => TsqlDatePart::Unsupported("TIMEZONE".to_string()),
19967 DateTimeField::TimezoneHour => TsqlDatePart::Unsupported("TIMEZONE_HOUR".to_string()),
19968 DateTimeField::TimezoneMinute => {
19969 TsqlDatePart::Unsupported("TIMEZONE_MINUTE".to_string())
19970 }
19971 DateTimeField::Date => TsqlDatePart::Unsupported("DATE".to_string()),
19972 DateTimeField::Time => TsqlDatePart::Unsupported("TIME".to_string()),
19973 DateTimeField::Custom(name) => self.classify_tsql_date_trunc_name(name),
19974 }
19975 }
19976
19977 fn classify_tsql_date_trunc_name(&self, part: &str) -> TsqlDatePart {
19978 let upper = part.trim().to_ascii_uppercase();
19979 match upper.as_str() {
19980 "YEAR" | "YY" | "YYY" | "YYYY" | "YR" | "YEARS" | "YRS" => {
19981 TsqlDatePart::Native("YEAR".to_string())
19982 }
19983 "QUARTER" | "Q" | "QQ" | "QTR" | "QTRS" | "QUARTERS" => {
19984 TsqlDatePart::Native("QUARTER".to_string())
19985 }
19986 "MONTH" | "MM" | "M" | "MON" | "MONS" | "MONTHS" => {
19987 TsqlDatePart::Native("MONTH".to_string())
19988 }
19989 "DAYOFYEAR" | "DOY" | "DY" | "Y" => TsqlDatePart::Native("DAYOFYEAR".to_string()),
19990 "DAY" | "D" | "DD" | "DAYS" | "DAYOFMONTH" => TsqlDatePart::Native("DAY".to_string()),
19991 "WEEK" | "W" | "WK" | "WW" | "WEEKS" | "WEEKOFYEAR" | "WOY" | "WY" => {
19992 TsqlDatePart::Native("WEEK".to_string())
19993 }
19994 "ISO_WEEK" | "ISOWEEK" | "ISOWK" | "ISOWW" | "WEEKISO" | "WEEKOFYEARISO"
19995 | "WEEKOFYEAR_ISO" | "WEEK_ISO" => TsqlDatePart::Native("ISO_WEEK".to_string()),
19996 "HOUR" | "H" | "HH" | "HR" | "HOURS" | "HRS" => {
19997 TsqlDatePart::Native("HOUR".to_string())
19998 }
19999 "MINUTE" | "MI" | "MIN" | "MINUTES" | "MINS" | "N" => {
20000 TsqlDatePart::Native("MINUTE".to_string())
20001 }
20002 "SECOND" | "S" | "SEC" | "SECONDS" | "SECS" | "SS" => {
20003 TsqlDatePart::Native("SECOND".to_string())
20004 }
20005 "MILLISECOND" | "MS" | "MSEC" | "MSECS" | "MSECOND" | "MSECONDS" | "MILLISEC"
20006 | "MILLISECS" | "MILLISECON" | "MILLISECONDS" => {
20007 TsqlDatePart::Native("MILLISECOND".to_string())
20008 }
20009 "MICROSECOND" | "US" | "USEC" | "USECS" | "MICROSEC" | "MICROSECS" | "USECOND"
20010 | "USECONDS" | "MICROSECONDS" | "MCS" => {
20011 TsqlDatePart::Native("MICROSECOND".to_string())
20012 }
20013 "WEEKDAY" | "DAYOFWEEK" | "DOW" | "DW" | "ISODOW" | "ISO_DOW" | "DOW_ISO"
20014 | "DW_ISO" | "ISO_DAYOFWEEK" | "ISO_WEEKDAY" | "DAYOFWEEKISO" | "DAYOFWEEK_ISO"
20015 | "WEEKDAY_ISO" | "NANOSECOND" | "NS" | "NSEC" | "NANOSEC" | "NSECOND" | "NSECONDS"
20016 | "NANOSECS" | "TZOFFSET" | "TZ" | "TZM" | "TIMEZONE" | "TIMEZONE_HOUR"
20017 | "TIMEZONE_MINUTE" | "TZH" | "EPOCH" | "EPOCH_SECOND" | "EPOCH_SECONDS" | "DECADE"
20018 | "DECADES" | "DEC" | "DECS" | "CENTURY" | "CENTURIES" | "CENT" | "CENTS"
20019 | "MILLENNIUM" | "MILLENIA" | "MIL" | "MILS" | "DATE" | "TIME" => {
20020 TsqlDatePart::Unsupported(upper)
20021 }
20022 _ => TsqlDatePart::Unsupported(upper),
20023 }
20024 }
20025
20026 fn generate_tsql_date_part(&mut self, part: TsqlDatePart, expr: &Expression) -> Result<()> {
20027 match part {
20028 TsqlDatePart::Native(name) => self.generate_tsql_native_datepart(&name, expr),
20029 TsqlDatePart::Epoch => self.generate_tsql_epoch_seconds(expr),
20030 TsqlDatePart::IsoDayOfWeek => self.generate_tsql_iso_day_of_week(expr),
20031 TsqlDatePart::Unsupported(name) => {
20032 self.unsupported(format!("DATEPART {name} is not supported by T-SQL/Fabric"))?;
20033 self.write_keyword("DATEPART");
20034 self.write("(");
20035 self.write_keyword(&name);
20036 self.write(", ");
20037 self.generate_expression(expr)?;
20038 self.write(")");
20039 Ok(())
20040 }
20041 }
20042 }
20043
20044 fn generate_tsql_native_datepart(&mut self, name: &str, expr: &Expression) -> Result<()> {
20045 self.write_keyword("DATEPART");
20046 self.write("(");
20047 self.write_keyword(name);
20048 self.write(", ");
20049 self.generate_expression(expr)?;
20050 self.write(")");
20051 Ok(())
20052 }
20053
20054 fn generate_tsql_epoch_seconds(&mut self, expr: &Expression) -> Result<()> {
20055 self.write_keyword("DATEDIFF");
20056 self.write("(SECOND, ");
20057 self.write_keyword("CAST");
20058 self.write("('1970-01-01' AS ");
20059 self.write_keyword("DATETIME2");
20060 self.write("), ");
20061 self.generate_expression(expr)?;
20062 self.write(")");
20063 Ok(())
20064 }
20065
20066 fn generate_tsql_iso_day_of_week(&mut self, expr: &Expression) -> Result<()> {
20067 self.write("(((DATEPART(WEEKDAY, ");
20068 self.generate_expression(expr)?;
20069 self.write(") + @@DATEFIRST - 2) % 7) + 1)");
20070 Ok(())
20071 }
20072
20073 fn generate_tsql_date_trunc(&mut self, part: TsqlDatePart, expr: &Expression) -> Result<()> {
20074 match part {
20075 TsqlDatePart::Native(name) => {
20076 self.write_keyword("DATETRUNC");
20077 self.write("(");
20078 self.write_keyword(&name);
20079 self.write(", ");
20080 self.generate_expression(expr)?;
20081 self.write(")");
20082 Ok(())
20083 }
20084 TsqlDatePart::Epoch => {
20085 self.generate_tsql_unsupported_date_trunc("EPOCH".to_string(), expr)
20086 }
20087 TsqlDatePart::IsoDayOfWeek => {
20088 self.generate_tsql_unsupported_date_trunc("ISODOW".to_string(), expr)
20089 }
20090 TsqlDatePart::Unsupported(name) => {
20091 self.generate_tsql_unsupported_date_trunc(name, expr)
20092 }
20093 }
20094 }
20095
20096 fn generate_tsql_unsupported_date_trunc(
20097 &mut self,
20098 name: String,
20099 expr: &Expression,
20100 ) -> Result<()> {
20101 self.unsupported(format!("DATETRUNC {name} is not supported by T-SQL/Fabric"))?;
20102 self.write_keyword("DATETRUNC");
20103 self.write("(");
20104 self.write_keyword(&name);
20105 self.write(", ");
20106 self.generate_expression(expr)?;
20107 self.write(")");
20108 Ok(())
20109 }
20110
20111 fn normalize_date_part(&self, part: &str) -> String {
20114 let mut buf = [0u8; 64];
20115 let lower: &str = if part.len() <= 64 {
20116 for (i, b) in part.bytes().enumerate() {
20117 buf[i] = b.to_ascii_lowercase();
20118 }
20119 std::str::from_utf8(&buf[..part.len()]).unwrap_or(part)
20120 } else {
20121 return part.to_ascii_uppercase();
20122 };
20123 match lower {
20124 "day" | "days" | "d" => "DAY".to_string(),
20125 "month" | "months" | "mon" | "mons" | "mm" => "MONTH".to_string(),
20126 "year" | "years" | "y" | "yy" | "yyyy" => "YEAR".to_string(),
20127 "week" | "weeks" | "w" | "wk" => "WEEK".to_string(),
20128 "hour" | "hours" | "h" | "hh" => "HOUR".to_string(),
20129 "minute" | "minutes" | "m" | "mi" | "n" => "MINUTE".to_string(),
20130 "second" | "seconds" | "s" | "ss" => "SECOND".to_string(),
20131 "millisecond" | "milliseconds" | "ms" => "MILLISECOND".to_string(),
20132 "microsecond" | "microseconds" | "us" => "MICROSECOND".to_string(),
20133 "quarter" | "quarters" | "q" | "qq" => "QUARTER".to_string(),
20134 _ => part.to_ascii_uppercase(),
20135 }
20136 }
20137
20138 fn write_datetime_field(&mut self, field: &DateTimeField) {
20139 match field {
20140 DateTimeField::Year => self.write_keyword("YEAR"),
20141 DateTimeField::Month => self.write_keyword("MONTH"),
20142 DateTimeField::Day => self.write_keyword("DAY"),
20143 DateTimeField::Hour => self.write_keyword("HOUR"),
20144 DateTimeField::Minute => self.write_keyword("MINUTE"),
20145 DateTimeField::Second => self.write_keyword("SECOND"),
20146 DateTimeField::Millisecond => self.write_keyword("MILLISECOND"),
20147 DateTimeField::Microsecond => self.write_keyword("MICROSECOND"),
20148 DateTimeField::DayOfWeek => {
20149 let name = match self.config.dialect {
20150 Some(DialectType::DuckDB) | Some(DialectType::Snowflake) => "DAYOFWEEK",
20151 Some(DialectType::TSQL) | Some(DialectType::Fabric) => "WEEKDAY",
20152 _ => "DOW",
20153 };
20154 self.write_keyword(name);
20155 }
20156 DateTimeField::DayOfYear => {
20157 let name = match self.config.dialect {
20158 Some(DialectType::DuckDB) | Some(DialectType::Snowflake) => "DAYOFYEAR",
20159 _ => "DOY",
20160 };
20161 self.write_keyword(name);
20162 }
20163 DateTimeField::Week => self.write_keyword("WEEK"),
20164 DateTimeField::WeekWithModifier(modifier) => {
20165 self.write_keyword("WEEK");
20166 self.write("(");
20167 self.write(modifier);
20168 self.write(")");
20169 }
20170 DateTimeField::Quarter => self.write_keyword("QUARTER"),
20171 DateTimeField::Epoch => self.write_keyword("EPOCH"),
20172 DateTimeField::Timezone => self.write_keyword("TIMEZONE"),
20173 DateTimeField::TimezoneHour => self.write_keyword("TIMEZONE_HOUR"),
20174 DateTimeField::TimezoneMinute => self.write_keyword("TIMEZONE_MINUTE"),
20175 DateTimeField::Date => self.write_keyword("DATE"),
20176 DateTimeField::Time => self.write_keyword("TIME"),
20177 DateTimeField::Custom(name) => self.write(name),
20178 }
20179 }
20180
20181 fn write_datetime_field_lower(&mut self, field: &DateTimeField) {
20183 match field {
20184 DateTimeField::Year => self.write("year"),
20185 DateTimeField::Month => self.write("month"),
20186 DateTimeField::Day => self.write("day"),
20187 DateTimeField::Hour => self.write("hour"),
20188 DateTimeField::Minute => self.write("minute"),
20189 DateTimeField::Second => self.write("second"),
20190 DateTimeField::Millisecond => self.write("millisecond"),
20191 DateTimeField::Microsecond => self.write("microsecond"),
20192 DateTimeField::DayOfWeek => self.write("dow"),
20193 DateTimeField::DayOfYear => self.write("doy"),
20194 DateTimeField::Week => self.write("week"),
20195 DateTimeField::WeekWithModifier(modifier) => {
20196 self.write("week(");
20197 self.write(modifier);
20198 self.write(")");
20199 }
20200 DateTimeField::Quarter => self.write("quarter"),
20201 DateTimeField::Epoch => self.write("epoch"),
20202 DateTimeField::Timezone => self.write("timezone"),
20203 DateTimeField::TimezoneHour => self.write("timezone_hour"),
20204 DateTimeField::TimezoneMinute => self.write("timezone_minute"),
20205 DateTimeField::Date => self.write("date"),
20206 DateTimeField::Time => self.write("time"),
20207 DateTimeField::Custom(name) => self.write(name),
20208 }
20209 }
20210
20211 fn generate_simple_func(&mut self, name: &str, arg: &Expression) -> Result<()> {
20214 self.write_keyword(name);
20215 self.write("(");
20216 self.generate_expression(arg)?;
20217 self.write(")");
20218 Ok(())
20219 }
20220
20221 fn generate_unary_func(
20223 &mut self,
20224 default_name: &str,
20225 f: &crate::expressions::UnaryFunc,
20226 ) -> Result<()> {
20227 let name = f.original_name.as_deref().unwrap_or(default_name);
20228 self.write_keyword(name);
20229 self.write("(");
20230 self.generate_expression(&f.this)?;
20231 self.write(")");
20232 Ok(())
20233 }
20234
20235 fn generate_sqrt_cbrt(
20237 &mut self,
20238 f: &crate::expressions::UnaryFunc,
20239 func_name: &str,
20240 _op: &str,
20241 ) -> Result<()> {
20242 self.write_keyword(func_name);
20245 self.write("(");
20246 self.generate_expression(&f.this)?;
20247 self.write(")");
20248 Ok(())
20249 }
20250
20251 fn generate_binary_func(
20252 &mut self,
20253 name: &str,
20254 arg1: &Expression,
20255 arg2: &Expression,
20256 ) -> Result<()> {
20257 self.write_keyword(name);
20258 self.write("(");
20259 self.generate_expression(arg1)?;
20260 self.write(", ");
20261 self.generate_expression(arg2)?;
20262 self.write(")");
20263 Ok(())
20264 }
20265
20266 fn generate_char_func(&mut self, f: &crate::expressions::CharFunc) -> Result<()> {
20270 let func_name = f.name.as_deref().unwrap_or("CHAR");
20272 self.write_keyword(func_name);
20273 self.write("(");
20274 for (i, arg) in f.args.iter().enumerate() {
20275 if i > 0 {
20276 self.write(", ");
20277 }
20278 self.generate_expression(arg)?;
20279 }
20280 if let Some(ref charset) = f.charset {
20281 self.write(" ");
20282 self.write_keyword("USING");
20283 self.write(" ");
20284 self.write(charset);
20285 }
20286 self.write(")");
20287 Ok(())
20288 }
20289
20290 fn generate_power(&mut self, f: &BinaryFunc) -> Result<()> {
20291 use crate::dialects::DialectType;
20292
20293 match self.config.dialect {
20294 Some(DialectType::Teradata) => {
20295 self.generate_expression(&f.this)?;
20297 self.write(" ** ");
20298 self.generate_expression(&f.expression)?;
20299 Ok(())
20300 }
20301 _ => {
20302 self.generate_binary_func("POWER", &f.this, &f.expression)
20304 }
20305 }
20306 }
20307
20308 fn generate_vararg_func(&mut self, name: &str, args: &[Expression]) -> Result<()> {
20309 self.write_func_name(name);
20310 self.write("(");
20311 for (i, arg) in args.iter().enumerate() {
20312 if i > 0 {
20313 self.write(", ");
20314 }
20315 self.generate_expression(arg)?;
20316 }
20317 self.write(")");
20318 Ok(())
20319 }
20320
20321 fn generate_concat_ws(&mut self, f: &ConcatWs) -> Result<()> {
20324 self.write_keyword("CONCAT_WS");
20325 self.write("(");
20326 self.generate_expression(&f.separator)?;
20327 for expr in &f.expressions {
20328 self.write(", ");
20329 self.generate_expression(expr)?;
20330 }
20331 self.write(")");
20332 Ok(())
20333 }
20334
20335 fn collect_concat_operands<'a>(expr: &'a Expression, out: &mut Vec<&'a Expression>) {
20336 if let Expression::Concat(op) = expr {
20337 Self::collect_concat_operands(&op.left, out);
20338 Self::collect_concat_operands(&op.right, out);
20339 } else {
20340 out.push(expr);
20341 }
20342 }
20343
20344 fn generate_mysql_concat_from_concat(&mut self, op: &BinaryOp) -> Result<()> {
20345 let mut operands = Vec::new();
20346 Self::collect_concat_operands(&op.left, &mut operands);
20347 Self::collect_concat_operands(&op.right, &mut operands);
20348
20349 self.write_keyword("CONCAT");
20350 self.write("(");
20351 for (i, operand) in operands.iter().enumerate() {
20352 if i > 0 {
20353 self.write(", ");
20354 }
20355 self.generate_expression(operand)?;
20356 }
20357 self.write(")");
20358 Ok(())
20359 }
20360
20361 fn collect_dpipe_operands<'a>(expr: &'a Expression, out: &mut Vec<&'a Expression>) {
20362 if let Expression::DPipe(dpipe) = expr {
20363 Self::collect_dpipe_operands(&dpipe.this, out);
20364 Self::collect_dpipe_operands(&dpipe.expression, out);
20365 } else {
20366 out.push(expr);
20367 }
20368 }
20369
20370 fn generate_mysql_concat_from_dpipe(&mut self, e: &DPipe) -> Result<()> {
20371 let mut operands = Vec::new();
20372 Self::collect_dpipe_operands(&e.this, &mut operands);
20373 Self::collect_dpipe_operands(&e.expression, &mut operands);
20374
20375 self.write_keyword("CONCAT");
20376 self.write("(");
20377 for (i, operand) in operands.iter().enumerate() {
20378 if i > 0 {
20379 self.write(", ");
20380 }
20381 self.generate_expression(operand)?;
20382 }
20383 self.write(")");
20384 Ok(())
20385 }
20386
20387 fn generate_substring(&mut self, f: &SubstringFunc) -> Result<()> {
20388 let use_substr = matches!(
20390 self.config.dialect,
20391 Some(
20392 DialectType::Oracle
20393 | DialectType::Presto
20394 | DialectType::Trino
20395 | DialectType::Athena
20396 )
20397 );
20398 if use_substr {
20399 self.write_keyword("SUBSTR");
20400 } else {
20401 self.write_keyword("SUBSTRING");
20402 }
20403 self.write("(");
20404 self.generate_expression(&f.this)?;
20405 let force_from_for = matches!(self.config.dialect, Some(DialectType::PostgreSQL));
20407 let use_comma_syntax = matches!(
20409 self.config.dialect,
20410 Some(DialectType::Spark)
20411 | Some(DialectType::Hive)
20412 | Some(DialectType::Databricks)
20413 | Some(DialectType::TSQL)
20414 | Some(DialectType::Fabric)
20415 );
20416 if (f.from_for_syntax || force_from_for) && !use_comma_syntax {
20417 self.write_space();
20419 self.write_keyword("FROM");
20420 self.write_space();
20421 self.generate_expression(&f.start)?;
20422 if let Some(length) = &f.length {
20423 self.write_space();
20424 self.write_keyword("FOR");
20425 self.write_space();
20426 self.generate_expression(length)?;
20427 }
20428 } else {
20429 self.write(", ");
20431 self.generate_expression(&f.start)?;
20432 if let Some(length) = &f.length {
20433 self.write(", ");
20434 self.generate_expression(length)?;
20435 }
20436 }
20437 self.write(")");
20438 Ok(())
20439 }
20440
20441 fn generate_overlay(&mut self, f: &OverlayFunc) -> Result<()> {
20442 self.write_keyword("OVERLAY");
20443 self.write("(");
20444 self.generate_expression(&f.this)?;
20445 self.write_space();
20446 self.write_keyword("PLACING");
20447 self.write_space();
20448 self.generate_expression(&f.replacement)?;
20449 self.write_space();
20450 self.write_keyword("FROM");
20451 self.write_space();
20452 self.generate_expression(&f.from)?;
20453 if let Some(length) = &f.length {
20454 self.write_space();
20455 self.write_keyword("FOR");
20456 self.write_space();
20457 self.generate_expression(length)?;
20458 }
20459 self.write(")");
20460 Ok(())
20461 }
20462
20463 fn generate_trim(&mut self, f: &TrimFunc) -> Result<()> {
20464 if f.position_explicit && f.characters.is_none() {
20467 match f.position {
20468 TrimPosition::Leading => {
20469 self.write_keyword("LTRIM");
20470 self.write("(");
20471 self.generate_expression(&f.this)?;
20472 self.write(")");
20473 return Ok(());
20474 }
20475 TrimPosition::Trailing => {
20476 self.write_keyword("RTRIM");
20477 self.write("(");
20478 self.generate_expression(&f.this)?;
20479 self.write(")");
20480 return Ok(());
20481 }
20482 TrimPosition::Both => {
20483 }
20486 }
20487 }
20488
20489 self.write_keyword("TRIM");
20490 self.write("(");
20491 let force_standard = f.characters.is_some()
20494 && !f.sql_standard_syntax
20495 && matches!(
20496 self.config.dialect,
20497 Some(DialectType::Hive)
20498 | Some(DialectType::Spark)
20499 | Some(DialectType::Databricks)
20500 | Some(DialectType::ClickHouse)
20501 );
20502 let use_standard = (f.sql_standard_syntax || force_standard)
20503 && !(f.position_explicit
20504 && f.characters.is_none()
20505 && matches!(f.position, TrimPosition::Both));
20506 if use_standard {
20507 if f.position_explicit {
20510 match f.position {
20511 TrimPosition::Both => self.write_keyword("BOTH"),
20512 TrimPosition::Leading => self.write_keyword("LEADING"),
20513 TrimPosition::Trailing => self.write_keyword("TRAILING"),
20514 }
20515 self.write_space();
20516 }
20517 if let Some(chars) = &f.characters {
20518 self.generate_expression(chars)?;
20519 self.write_space();
20520 }
20521 self.write_keyword("FROM");
20522 self.write_space();
20523 self.generate_expression(&f.this)?;
20524 } else {
20525 self.generate_expression(&f.this)?;
20527 if let Some(chars) = &f.characters {
20528 self.write(", ");
20529 self.generate_expression(chars)?;
20530 }
20531 }
20532 self.write(")");
20533 Ok(())
20534 }
20535
20536 fn generate_replace(&mut self, f: &ReplaceFunc) -> Result<()> {
20537 self.write_keyword("REPLACE");
20538 self.write("(");
20539 self.generate_expression(&f.this)?;
20540 self.write(", ");
20541 self.generate_expression(&f.old)?;
20542 self.write(", ");
20543 self.generate_expression(&f.new)?;
20544 self.write(")");
20545 Ok(())
20546 }
20547
20548 fn generate_left_right(&mut self, name: &str, f: &LeftRightFunc) -> Result<()> {
20549 self.write_keyword(name);
20550 self.write("(");
20551 self.generate_expression(&f.this)?;
20552 self.write(", ");
20553 self.generate_expression(&f.length)?;
20554 self.write(")");
20555 Ok(())
20556 }
20557
20558 fn generate_repeat(&mut self, f: &RepeatFunc) -> Result<()> {
20559 self.write_keyword("REPEAT");
20560 self.write("(");
20561 self.generate_expression(&f.this)?;
20562 self.write(", ");
20563 self.generate_expression(&f.times)?;
20564 self.write(")");
20565 Ok(())
20566 }
20567
20568 fn generate_pad(&mut self, name: &str, f: &PadFunc) -> Result<()> {
20569 self.write_keyword(name);
20570 self.write("(");
20571 self.generate_expression(&f.this)?;
20572 self.write(", ");
20573 self.generate_expression(&f.length)?;
20574 if let Some(fill) = &f.fill {
20575 self.write(", ");
20576 self.generate_expression(fill)?;
20577 }
20578 self.write(")");
20579 Ok(())
20580 }
20581
20582 fn generate_split(&mut self, f: &SplitFunc) -> Result<()> {
20583 self.write_keyword("SPLIT");
20584 self.write("(");
20585 self.generate_expression(&f.this)?;
20586 self.write(", ");
20587 self.generate_expression(&f.delimiter)?;
20588 self.write(")");
20589 Ok(())
20590 }
20591
20592 fn generate_regexp_like(&mut self, f: &RegexpFunc) -> Result<()> {
20593 use crate::dialects::DialectType;
20594 if matches!(self.config.dialect, Some(DialectType::PostgreSQL)) && f.flags.is_none() {
20596 self.generate_expression(&f.this)?;
20597 self.write(" ~ ");
20598 self.generate_expression(&f.pattern)?;
20599 } else if matches!(self.config.dialect, Some(DialectType::ClickHouse)) && f.flags.is_none()
20600 {
20601 self.write("match(");
20603 self.generate_expression(&f.this)?;
20604 self.write(", ");
20605 self.generate_expression(&f.pattern)?;
20606 self.write(")");
20607 } else if matches!(self.config.dialect, Some(DialectType::Exasol)) && f.flags.is_none() {
20608 self.generate_expression(&f.this)?;
20610 self.write_keyword(" REGEXP_LIKE ");
20611 self.generate_expression(&f.pattern)?;
20612 } else if matches!(
20613 self.config.dialect,
20614 Some(DialectType::SingleStore)
20615 | Some(DialectType::Spark)
20616 | Some(DialectType::Hive)
20617 | Some(DialectType::Databricks)
20618 ) && f.flags.is_none()
20619 {
20620 self.generate_expression(&f.this)?;
20622 self.write_keyword(" RLIKE ");
20623 self.generate_expression(&f.pattern)?;
20624 } else if matches!(self.config.dialect, Some(DialectType::StarRocks)) {
20625 self.write_keyword("REGEXP");
20627 self.write("(");
20628 self.generate_expression(&f.this)?;
20629 self.write(", ");
20630 self.generate_expression(&f.pattern)?;
20631 if let Some(flags) = &f.flags {
20632 self.write(", ");
20633 self.generate_expression(flags)?;
20634 }
20635 self.write(")");
20636 } else {
20637 self.write_keyword("REGEXP_LIKE");
20638 self.write("(");
20639 self.generate_expression(&f.this)?;
20640 self.write(", ");
20641 self.generate_expression(&f.pattern)?;
20642 if let Some(flags) = &f.flags {
20643 self.write(", ");
20644 self.generate_expression(flags)?;
20645 }
20646 self.write(")");
20647 }
20648 Ok(())
20649 }
20650
20651 fn generate_regexp_replace(&mut self, f: &RegexpReplaceFunc) -> Result<()> {
20652 self.write_keyword("REGEXP_REPLACE");
20653 self.write("(");
20654 self.generate_expression(&f.this)?;
20655 self.write(", ");
20656 self.generate_expression(&f.pattern)?;
20657 self.write(", ");
20658 self.generate_expression(&f.replacement)?;
20659 if let Some(flags) = &f.flags {
20660 self.write(", ");
20661 self.generate_expression(flags)?;
20662 }
20663 self.write(")");
20664 Ok(())
20665 }
20666
20667 fn generate_regexp_extract(&mut self, f: &RegexpExtractFunc) -> Result<()> {
20668 self.write_keyword("REGEXP_EXTRACT");
20669 self.write("(");
20670 self.generate_expression(&f.this)?;
20671 self.write(", ");
20672 self.generate_expression(&f.pattern)?;
20673 if let Some(group) = &f.group {
20674 self.write(", ");
20675 self.generate_expression(group)?;
20676 }
20677 self.write(")");
20678 Ok(())
20679 }
20680
20681 fn generate_round(&mut self, f: &RoundFunc) -> Result<()> {
20684 self.write_keyword("ROUND");
20685 self.write("(");
20686 self.generate_expression(&f.this)?;
20687 if let Some(decimals) = &f.decimals {
20688 self.write(", ");
20689 self.generate_expression(decimals)?;
20690 }
20691 self.write(")");
20692 Ok(())
20693 }
20694
20695 fn generate_floor(&mut self, f: &FloorFunc) -> Result<()> {
20696 self.write_keyword("FLOOR");
20697 self.write("(");
20698 self.generate_expression(&f.this)?;
20699 if let Some(to) = &f.to {
20701 self.write(" ");
20702 self.write_keyword("TO");
20703 self.write(" ");
20704 self.generate_expression(to)?;
20705 } else if let Some(scale) = &f.scale {
20706 self.write(", ");
20707 self.generate_expression(scale)?;
20708 }
20709 self.write(")");
20710 Ok(())
20711 }
20712
20713 fn generate_ceil(&mut self, f: &CeilFunc) -> Result<()> {
20714 self.write_keyword("CEIL");
20715 self.write("(");
20716 self.generate_expression(&f.this)?;
20717 if let Some(to) = &f.to {
20719 self.write(" ");
20720 self.write_keyword("TO");
20721 self.write(" ");
20722 self.generate_expression(to)?;
20723 } else if let Some(decimals) = &f.decimals {
20724 self.write(", ");
20725 self.generate_expression(decimals)?;
20726 }
20727 self.write(")");
20728 Ok(())
20729 }
20730
20731 fn generate_log(&mut self, f: &LogFunc) -> Result<()> {
20732 use crate::expressions::Literal;
20733
20734 if let Some(base) = &f.base {
20735 if self.is_log_base_none() {
20738 if matches!(base, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(s) if s == "2"))
20739 {
20740 self.write_func_name("LOG2");
20741 self.write("(");
20742 self.generate_expression(&f.this)?;
20743 self.write(")");
20744 return Ok(());
20745 } else if matches!(base, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(s) if s == "10"))
20746 {
20747 self.write_func_name("LOG10");
20748 self.write("(");
20749 self.generate_expression(&f.this)?;
20750 self.write(")");
20751 return Ok(());
20752 }
20753 }
20755
20756 self.write_func_name("LOG");
20757 self.write("(");
20758 if self.is_log_value_first() {
20759 self.generate_expression(&f.this)?;
20761 self.write(", ");
20762 self.generate_expression(base)?;
20763 } else {
20764 self.generate_expression(base)?;
20766 self.write(", ");
20767 self.generate_expression(&f.this)?;
20768 }
20769 self.write(")");
20770 } else {
20771 self.write_func_name("LOG");
20773 self.write("(");
20774 self.generate_expression(&f.this)?;
20775 self.write(")");
20776 }
20777 Ok(())
20778 }
20779
20780 fn is_log_value_first(&self) -> bool {
20783 use crate::dialects::DialectType;
20784 matches!(
20785 self.config.dialect,
20786 Some(DialectType::BigQuery)
20787 | Some(DialectType::TSQL)
20788 | Some(DialectType::Tableau)
20789 | Some(DialectType::Fabric)
20790 )
20791 }
20792
20793 fn is_log_base_none(&self) -> bool {
20796 use crate::dialects::DialectType;
20797 matches!(
20798 self.config.dialect,
20799 Some(DialectType::Presto)
20800 | Some(DialectType::Trino)
20801 | Some(DialectType::ClickHouse)
20802 | Some(DialectType::Athena)
20803 )
20804 }
20805
20806 fn generate_current_time(&mut self, f: &CurrentTime) -> Result<()> {
20809 self.write_keyword("CURRENT_TIME");
20810 if let Some(precision) = f.precision {
20811 self.write(&format!("({})", precision));
20812 } else if matches!(
20813 self.config.dialect,
20814 Some(crate::dialects::DialectType::MySQL)
20815 | Some(crate::dialects::DialectType::SingleStore)
20816 | Some(crate::dialects::DialectType::TiDB)
20817 ) {
20818 self.write("()");
20819 }
20820 Ok(())
20821 }
20822
20823 fn generate_current_timestamp(&mut self, f: &CurrentTimestamp) -> Result<()> {
20824 use crate::dialects::DialectType;
20825
20826 if f.sysdate {
20828 match self.config.dialect {
20829 Some(DialectType::Oracle) | Some(DialectType::Redshift) => {
20830 self.write_keyword("SYSDATE");
20831 return Ok(());
20832 }
20833 Some(DialectType::Snowflake) => {
20834 self.write_keyword("SYSDATE");
20836 self.write("()");
20837 return Ok(());
20838 }
20839 _ => {
20840 }
20842 }
20843 }
20844
20845 self.write_keyword("CURRENT_TIMESTAMP");
20846 if let Some(precision) = f.precision {
20848 self.write(&format!("({})", precision));
20849 } else if matches!(
20850 self.config.dialect,
20851 Some(crate::dialects::DialectType::MySQL)
20852 | Some(crate::dialects::DialectType::SingleStore)
20853 | Some(crate::dialects::DialectType::TiDB)
20854 | Some(crate::dialects::DialectType::Spark)
20855 | Some(crate::dialects::DialectType::Hive)
20856 | Some(crate::dialects::DialectType::Databricks)
20857 | Some(crate::dialects::DialectType::ClickHouse)
20858 | Some(crate::dialects::DialectType::BigQuery)
20859 | Some(crate::dialects::DialectType::Snowflake)
20860 | Some(crate::dialects::DialectType::Exasol)
20861 ) {
20862 self.write("()");
20863 }
20864 Ok(())
20865 }
20866
20867 fn generate_at_time_zone(&mut self, f: &AtTimeZone) -> Result<()> {
20868 if matches!(&f.zone, Expression::Identifier(identifier) if identifier.name.eq_ignore_ascii_case("LOCAL"))
20869 {
20870 self.generate_expression(&f.this)?;
20871 self.write_space();
20872 self.write_keyword("AT LOCAL");
20873 return Ok(());
20874 }
20875
20876 if self.config.dialect == Some(DialectType::Exasol) {
20878 self.write_keyword("CONVERT_TZ");
20879 self.write("(");
20880 self.generate_expression(&f.this)?;
20881 self.write(", 'UTC', ");
20882 self.generate_expression(&f.zone)?;
20883 self.write(")");
20884 return Ok(());
20885 }
20886
20887 self.generate_expression(&f.this)?;
20888 self.write_space();
20889 self.write_keyword("AT TIME ZONE");
20890 self.write_space();
20891 self.generate_expression(&f.zone)?;
20892 Ok(())
20893 }
20894
20895 fn generate_date_add(&mut self, f: &DateAddFunc, name: &str) -> Result<()> {
20896 use crate::dialects::DialectType;
20897
20898 let is_presto_like = matches!(
20901 self.config.dialect,
20902 Some(DialectType::Presto) | Some(DialectType::Trino)
20903 );
20904
20905 if is_presto_like {
20906 self.write_keyword(name);
20907 self.write("(");
20908 self.write("'");
20910 self.write_simple_interval_unit(&f.unit, false);
20911 self.write("'");
20912 self.write(", ");
20913 let needs_cast = !self.returns_integer_type(&f.interval);
20915 if needs_cast {
20916 self.write_keyword("CAST");
20917 self.write("(");
20918 }
20919 self.generate_expression(&f.interval)?;
20920 if needs_cast {
20921 self.write_space();
20922 self.write_keyword("AS");
20923 self.write_space();
20924 self.write_keyword("BIGINT");
20925 self.write(")");
20926 }
20927 self.write(", ");
20928 self.generate_expression(&f.this)?;
20929 self.write(")");
20930 } else if matches!(self.config.dialect, Some(DialectType::PostgreSQL)) {
20931 self.generate_expression(&f.this)?;
20932 self.write_space();
20933 if name.eq_ignore_ascii_case("DATE_SUB") {
20934 self.write("-");
20935 } else {
20936 self.write("+");
20937 }
20938 self.write_space();
20939 self.write_keyword("INTERVAL");
20940 self.write_space();
20941 self.write("'");
20942 let mut interval_gen = Generator::with_arc_config(self.config.clone());
20943 let interval_sql = interval_gen.generate(&f.interval)?;
20944 self.write(&interval_sql);
20945 self.write(" ");
20946 self.write_simple_interval_unit(&f.unit, false);
20947 self.write("'");
20948 } else {
20949 self.write_keyword(name);
20950 self.write("(");
20951 self.generate_expression(&f.this)?;
20952 self.write(", ");
20953 self.write_keyword("INTERVAL");
20954 self.write_space();
20955 self.generate_expression(&f.interval)?;
20956 self.write_space();
20957 self.write_simple_interval_unit(&f.unit, false); self.write(")");
20959 }
20960 Ok(())
20961 }
20962
20963 fn returns_integer_type(&self, expr: &Expression) -> bool {
20966 use crate::expressions::{DataType, Literal};
20967 match expr {
20968 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
20970 let Literal::Number(n) = lit.as_ref() else {
20971 unreachable!()
20972 };
20973 !n.contains('.')
20974 }
20975
20976 Expression::Floor(f) => self.returns_integer_type(&f.this),
20978
20979 Expression::Round(f) => {
20981 f.decimals.is_none() && self.returns_integer_type(&f.this)
20983 }
20984
20985 Expression::Sign(f) => self.returns_integer_type(&f.this),
20987
20988 Expression::Abs(f) => self.returns_integer_type(&f.this),
20990
20991 Expression::Mul(op) => {
20993 self.returns_integer_type(&op.left) && self.returns_integer_type(&op.right)
20994 }
20995 Expression::Add(op) => {
20996 self.returns_integer_type(&op.left) && self.returns_integer_type(&op.right)
20997 }
20998 Expression::Sub(op) => {
20999 self.returns_integer_type(&op.left) && self.returns_integer_type(&op.right)
21000 }
21001 Expression::Mod(op) => self.returns_integer_type(&op.left),
21002
21003 Expression::Cast(c) => matches!(
21005 &c.to,
21006 DataType::BigInt { .. }
21007 | DataType::Int { .. }
21008 | DataType::SmallInt { .. }
21009 | DataType::TinyInt { .. }
21010 ),
21011
21012 Expression::Neg(op) => self.returns_integer_type(&op.this),
21014
21015 Expression::Paren(p) => self.returns_integer_type(&p.this),
21017
21018 _ => false,
21021 }
21022 }
21023
21024 fn generate_datediff(&mut self, f: &DateDiffFunc) -> Result<()> {
21025 self.write_keyword("DATEDIFF");
21026 self.write("(");
21027 if let Some(unit) = &f.unit {
21028 self.write_simple_interval_unit(unit, false); self.write(", ");
21030 }
21031 if self.config.dialect == Some(DialectType::Snowflake) {
21032 self.generate_expression(&f.expression)?;
21033 self.write(", ");
21034 self.generate_expression(&f.this)?;
21035 } else {
21036 self.generate_expression(&f.this)?;
21037 self.write(", ");
21038 self.generate_expression(&f.expression)?;
21039 }
21040 self.write(")");
21041 Ok(())
21042 }
21043
21044 fn generate_date_trunc(&mut self, f: &DateTruncFunc) -> Result<()> {
21045 if matches!(
21046 self.config.dialect,
21047 Some(DialectType::TSQL) | Some(DialectType::Fabric)
21048 ) {
21049 let date_part = self.classify_tsql_date_trunc_field(&f.unit);
21050 self.generate_tsql_date_trunc(date_part, &f.this)?;
21051 return Ok(());
21052 }
21053 if self.config.dialect == Some(DialectType::ClickHouse) {
21054 self.write("dateTrunc");
21055 } else {
21056 self.write_keyword("DATE_TRUNC");
21057 }
21058 self.write("('");
21059 self.write_datetime_field(&f.unit);
21060 self.write("', ");
21061 self.generate_expression(&f.this)?;
21062 self.write(")");
21063 Ok(())
21064 }
21065
21066 fn generate_last_day(&mut self, f: &LastDayFunc) -> Result<()> {
21067 use crate::dialects::DialectType;
21068 use crate::expressions::DateTimeField;
21069
21070 self.write_keyword("LAST_DAY");
21071 self.write("(");
21072 self.generate_expression(&f.this)?;
21073 if let Some(unit) = &f.unit {
21074 self.write(", ");
21075 if matches!(self.config.dialect, Some(DialectType::BigQuery)) {
21078 if let DateTimeField::WeekWithModifier(_) = unit {
21079 self.write_keyword("WEEK");
21080 } else {
21081 self.write_datetime_field(unit);
21082 }
21083 } else {
21084 self.write_datetime_field(unit);
21085 }
21086 }
21087 self.write(")");
21088 Ok(())
21089 }
21090
21091 fn generate_extract(&mut self, f: &ExtractFunc) -> Result<()> {
21092 if matches!(
21094 self.config.dialect,
21095 Some(DialectType::TSQL) | Some(DialectType::Fabric)
21096 ) {
21097 let date_part = self.classify_tsql_datetime_field(&f.field);
21098 self.generate_tsql_date_part(date_part, &f.this)?;
21099 return Ok(());
21100 }
21101 self.write_keyword("EXTRACT");
21102 self.write("(");
21103 if matches!(
21105 self.config.dialect,
21106 Some(DialectType::Hive) | Some(DialectType::Spark) | Some(DialectType::Databricks)
21107 ) {
21108 self.write_datetime_field_lower(&f.field);
21109 } else {
21110 self.write_datetime_field(&f.field);
21111 }
21112 self.write_space();
21113 self.write_keyword("FROM");
21114 self.write_space();
21115 self.generate_expression(&f.this)?;
21116 self.write(")");
21117 Ok(())
21118 }
21119
21120 fn generate_to_date(&mut self, f: &ToDateFunc) -> Result<()> {
21121 self.write_keyword("TO_DATE");
21122 self.write("(");
21123 self.generate_expression(&f.this)?;
21124 if let Some(format) = &f.format {
21125 self.write(", ");
21126 self.generate_expression(format)?;
21127 }
21128 self.write(")");
21129 Ok(())
21130 }
21131
21132 fn generate_to_timestamp(&mut self, f: &ToTimestampFunc) -> Result<()> {
21133 self.write_keyword("TO_TIMESTAMP");
21134 self.write("(");
21135 self.generate_expression(&f.this)?;
21136 if let Some(format) = &f.format {
21137 self.write(", ");
21138 self.generate_expression(format)?;
21139 }
21140 self.write(")");
21141 Ok(())
21142 }
21143
21144 fn generate_if_func(&mut self, f: &IfFunc) -> Result<()> {
21147 use crate::dialects::DialectType;
21148
21149 if self.config.dialect.is_none() || self.config.dialect == Some(DialectType::Generic) {
21151 self.write_keyword("CASE WHEN");
21152 self.write_space();
21153 self.generate_expression(&f.condition)?;
21154 self.write_space();
21155 self.write_keyword("THEN");
21156 self.write_space();
21157 self.generate_expression(&f.true_value)?;
21158 if let Some(false_val) = &f.false_value {
21159 self.write_space();
21160 self.write_keyword("ELSE");
21161 self.write_space();
21162 self.generate_expression(false_val)?;
21163 }
21164 self.write_space();
21165 self.write_keyword("END");
21166 return Ok(());
21167 }
21168
21169 if self.config.dialect == Some(DialectType::Exasol) {
21171 self.write_keyword("IF");
21172 self.write_space();
21173 self.generate_expression(&f.condition)?;
21174 self.write_space();
21175 self.write_keyword("THEN");
21176 self.write_space();
21177 self.generate_expression(&f.true_value)?;
21178 if let Some(false_val) = &f.false_value {
21179 self.write_space();
21180 self.write_keyword("ELSE");
21181 self.write_space();
21182 self.generate_expression(false_val)?;
21183 }
21184 self.write_space();
21185 self.write_keyword("ENDIF");
21186 return Ok(());
21187 }
21188
21189 let func_name = match self.config.dialect {
21191 Some(DialectType::ClickHouse) => f.original_name.as_deref().unwrap_or("IF"),
21192 Some(DialectType::Snowflake) => "IFF",
21193 Some(DialectType::SQLite) | Some(DialectType::TSQL) => "IIF",
21194 Some(DialectType::Drill) => "`IF`",
21195 _ => "IF",
21196 };
21197 self.write(func_name);
21198 self.write("(");
21199 self.generate_expression(&f.condition)?;
21200 self.write(", ");
21201 self.generate_expression(&f.true_value)?;
21202 if let Some(false_val) = &f.false_value {
21203 self.write(", ");
21204 self.generate_expression(false_val)?;
21205 }
21206 self.write(")");
21207 Ok(())
21208 }
21209
21210 fn generate_nvl2(&mut self, f: &Nvl2Func) -> Result<()> {
21211 self.write_keyword("NVL2");
21212 self.write("(");
21213 self.generate_expression(&f.this)?;
21214 self.write(", ");
21215 self.generate_expression(&f.true_value)?;
21216 self.write(", ");
21217 self.generate_expression(&f.false_value)?;
21218 self.write(")");
21219 Ok(())
21220 }
21221
21222 fn generate_count(&mut self, f: &CountFunc) -> Result<()> {
21225 let count_name = match self.config.normalize_functions {
21227 NormalizeFunctions::Upper => "COUNT".to_string(),
21228 NormalizeFunctions::Lower => "count".to_string(),
21229 NormalizeFunctions::None => f
21230 .original_name
21231 .clone()
21232 .unwrap_or_else(|| "COUNT".to_string()),
21233 };
21234 self.write(&count_name);
21235 self.write("(");
21236 if f.distinct {
21237 self.write_keyword("DISTINCT");
21238 self.write_space();
21239 }
21240 if f.star {
21241 self.write("*");
21242 } else if let Some(ref expr) = f.this {
21243 if let Expression::Tuple(tuple) = expr {
21245 let needs_transform =
21249 f.distinct && tuple.expressions.len() > 1 && !self.config.multi_arg_distinct;
21250
21251 if needs_transform {
21252 self.write_keyword("CASE");
21254 for e in &tuple.expressions {
21255 self.write_space();
21256 self.write_keyword("WHEN");
21257 self.write_space();
21258 self.generate_expression(e)?;
21259 self.write_space();
21260 self.write_keyword("IS NULL THEN NULL");
21261 }
21262 self.write_space();
21263 self.write_keyword("ELSE");
21264 self.write(" (");
21265 for (i, e) in tuple.expressions.iter().enumerate() {
21266 if i > 0 {
21267 self.write(", ");
21268 }
21269 self.generate_expression(e)?;
21270 }
21271 self.write(")");
21272 self.write_space();
21273 self.write_keyword("END");
21274 } else {
21275 for (i, e) in tuple.expressions.iter().enumerate() {
21276 if i > 0 {
21277 self.write(", ");
21278 }
21279 self.generate_expression(e)?;
21280 }
21281 }
21282 } else {
21283 self.generate_expression(expr)?;
21284 }
21285 }
21286 let clickhouse_ignore_nulls_outside =
21287 matches!(self.config.dialect, Some(DialectType::ClickHouse));
21288 if let Some(ignore) = f.ignore_nulls.filter(|_| !clickhouse_ignore_nulls_outside) {
21289 self.write_space();
21290 if ignore {
21291 self.write_keyword("IGNORE NULLS");
21292 } else {
21293 self.write_keyword("RESPECT NULLS");
21294 }
21295 }
21296 self.write(")");
21297 if let Some(ignore) = f.ignore_nulls.filter(|_| clickhouse_ignore_nulls_outside) {
21298 self.write_space();
21299 if ignore {
21300 self.write_keyword("IGNORE NULLS");
21301 } else {
21302 self.write_keyword("RESPECT NULLS");
21303 }
21304 }
21305 if let Some(ref filter) = f.filter {
21306 self.write_space();
21307 self.write_keyword("FILTER");
21308 self.write("(");
21309 self.write_keyword("WHERE");
21310 self.write_space();
21311 self.generate_expression(filter)?;
21312 self.write(")");
21313 }
21314 Ok(())
21315 }
21316
21317 fn generate_agg_func(&mut self, name: &str, f: &AggFunc) -> Result<()> {
21318 let func_name: Cow<'_, str> = match self.config.normalize_functions {
21320 NormalizeFunctions::Upper => Cow::Owned(name.to_ascii_uppercase()),
21321 NormalizeFunctions::Lower => Cow::Owned(name.to_ascii_lowercase()),
21322 NormalizeFunctions::None => {
21323 if let Some(ref original) = f.name {
21326 Cow::Owned(original.clone())
21327 } else {
21328 Cow::Owned(name.to_ascii_lowercase())
21329 }
21330 }
21331 };
21332 self.write(func_name.as_ref());
21333 self.write("(");
21334 if f.distinct {
21335 self.write_keyword("DISTINCT");
21336 self.write_space();
21337 }
21338 let is_zero_arg_mode =
21341 name.eq_ignore_ascii_case("MODE") && matches!(f.this, Expression::Null(_));
21342 if !is_zero_arg_mode {
21343 self.generate_expression(&f.this)?;
21344 }
21345 if self.config.ignore_nulls_in_func
21348 && !matches!(self.config.dialect, Some(DialectType::DuckDB))
21349 {
21350 match f.ignore_nulls {
21351 Some(true) => {
21352 self.write_space();
21353 self.write_keyword("IGNORE NULLS");
21354 }
21355 Some(false) => {
21356 self.write_space();
21357 self.write_keyword("RESPECT NULLS");
21358 }
21359 None => {}
21360 }
21361 }
21362 if let Some((ref expr, is_max)) = f.having_max {
21365 self.write_space();
21366 self.write_keyword("HAVING");
21367 self.write_space();
21368 if is_max {
21369 self.write_keyword("MAX");
21370 } else {
21371 self.write_keyword("MIN");
21372 }
21373 self.write_space();
21374 self.generate_expression(expr)?;
21375 }
21376 if !f.order_by.is_empty() {
21378 self.write_space();
21379 self.write_keyword("ORDER BY");
21380 self.write_space();
21381 for (i, ord) in f.order_by.iter().enumerate() {
21382 if i > 0 {
21383 self.write(", ");
21384 }
21385 self.generate_ordered(ord)?;
21386 }
21387 }
21388 if let Some(ref limit) = f.limit {
21390 self.write_space();
21391 self.write_keyword("LIMIT");
21392 self.write_space();
21393 if let Expression::Tuple(t) = limit.as_ref() {
21395 if t.expressions.len() == 2 {
21396 self.generate_expression(&t.expressions[0])?;
21397 self.write(", ");
21398 self.generate_expression(&t.expressions[1])?;
21399 } else {
21400 self.generate_expression(limit)?;
21401 }
21402 } else {
21403 self.generate_expression(limit)?;
21404 }
21405 }
21406 self.write(")");
21407 if !self.config.ignore_nulls_in_func
21410 && !matches!(self.config.dialect, Some(DialectType::DuckDB))
21411 {
21412 match f.ignore_nulls {
21413 Some(true) => {
21414 self.write_space();
21415 self.write_keyword("IGNORE NULLS");
21416 }
21417 Some(false) => {
21418 self.write_space();
21419 self.write_keyword("RESPECT NULLS");
21420 }
21421 None => {}
21422 }
21423 }
21424 if let Some(ref filter) = f.filter {
21425 self.write_space();
21426 self.write_keyword("FILTER");
21427 self.write("(");
21428 self.write_keyword("WHERE");
21429 self.write_space();
21430 self.generate_expression(filter)?;
21431 self.write(")");
21432 }
21433 Ok(())
21434 }
21435
21436 fn generate_agg_func_with_ignore_nulls_bool(&mut self, name: &str, f: &AggFunc) -> Result<()> {
21439 if matches!(self.config.dialect, Some(DialectType::Hive)) && f.ignore_nulls == Some(true) {
21441 let func_name: Cow<'_, str> = match self.config.normalize_functions {
21443 NormalizeFunctions::Upper => Cow::Owned(name.to_ascii_uppercase()),
21444 NormalizeFunctions::Lower => Cow::Owned(name.to_ascii_lowercase()),
21445 NormalizeFunctions::None => {
21446 if let Some(ref original) = f.name {
21447 Cow::Owned(original.clone())
21448 } else {
21449 Cow::Owned(name.to_ascii_lowercase())
21450 }
21451 }
21452 };
21453 self.write(func_name.as_ref());
21454 self.write("(");
21455 if f.distinct {
21456 self.write_keyword("DISTINCT");
21457 self.write_space();
21458 }
21459 if !matches!(f.this, Expression::Null(_)) {
21460 self.generate_expression(&f.this)?;
21461 }
21462 self.write(", ");
21463 self.write_keyword("TRUE");
21464 self.write(")");
21465 return Ok(());
21466 }
21467 self.generate_agg_func(name, f)
21468 }
21469
21470 fn generate_group_concat(&mut self, f: &GroupConcatFunc) -> Result<()> {
21471 self.write_keyword("GROUP_CONCAT");
21472 self.write("(");
21473 if f.distinct {
21474 self.write_keyword("DISTINCT");
21475 self.write_space();
21476 }
21477 self.generate_expression(&f.this)?;
21478 if let Some(ref order_by) = f.order_by {
21479 self.write_space();
21480 self.write_keyword("ORDER BY");
21481 self.write_space();
21482 for (i, ord) in order_by.iter().enumerate() {
21483 if i > 0 {
21484 self.write(", ");
21485 }
21486 self.generate_ordered(ord)?;
21487 }
21488 }
21489 if let Some(ref sep) = f.separator {
21490 if matches!(
21493 self.config.dialect,
21494 Some(crate::dialects::DialectType::SQLite)
21495 ) {
21496 self.write(", ");
21497 self.generate_expression(sep)?;
21498 } else {
21499 self.write_space();
21500 self.write_keyword("SEPARATOR");
21501 self.write_space();
21502 self.generate_expression(sep)?;
21503 }
21504 }
21505 if let Some(ref limit) = f.limit {
21506 self.write_space();
21507 self.write_keyword("LIMIT");
21508 self.write_space();
21509 self.generate_expression(limit)?;
21510 }
21511 self.write(")");
21512 if let Some(ref filter) = f.filter {
21513 self.write_space();
21514 self.write_keyword("FILTER");
21515 self.write("(");
21516 self.write_keyword("WHERE");
21517 self.write_space();
21518 self.generate_expression(filter)?;
21519 self.write(")");
21520 }
21521 Ok(())
21522 }
21523
21524 fn generate_string_agg(&mut self, f: &StringAggFunc) -> Result<()> {
21525 let uses_within_group_order = matches!(
21526 self.config.dialect,
21527 Some(crate::dialects::DialectType::TSQL | crate::dialects::DialectType::Fabric)
21528 );
21529 self.write_keyword("STRING_AGG");
21530 self.write("(");
21531 if f.distinct {
21532 self.write_keyword("DISTINCT");
21533 self.write_space();
21534 }
21535 self.generate_expression(&f.this)?;
21536 if let Some(ref separator) = f.separator {
21537 self.write(", ");
21538 self.generate_string_agg_separator(separator)?;
21539 }
21540 if !uses_within_group_order {
21542 if let Some(ref order_by) = f.order_by {
21543 self.write_space();
21544 self.write_keyword("ORDER BY");
21545 self.write_space();
21546 for (i, ord) in order_by.iter().enumerate() {
21547 if i > 0 {
21548 self.write(", ");
21549 }
21550 self.generate_ordered(ord)?;
21551 }
21552 }
21553 }
21554 if let Some(ref limit) = f.limit {
21555 self.write_space();
21556 self.write_keyword("LIMIT");
21557 self.write_space();
21558 self.generate_expression(limit)?;
21559 }
21560 self.write(")");
21561 if uses_within_group_order {
21562 if let Some(ref order_by) = f.order_by {
21563 self.write_space();
21564 self.write_keyword("WITHIN GROUP");
21565 self.write(" (");
21566 self.write_keyword("ORDER BY");
21567 self.write_space();
21568 for (i, ord) in order_by.iter().enumerate() {
21569 if i > 0 {
21570 self.write(", ");
21571 }
21572 self.generate_ordered(ord)?;
21573 }
21574 self.write(")");
21575 }
21576 }
21577 if let Some(ref filter) = f.filter {
21578 self.write_space();
21579 self.write_keyword("FILTER");
21580 self.write("(");
21581 self.write_keyword("WHERE");
21582 self.write_space();
21583 self.generate_expression(filter)?;
21584 self.write(")");
21585 }
21586 Ok(())
21587 }
21588
21589 fn generate_string_agg_separator(&mut self, separator: &Expression) -> Result<()> {
21590 if matches!(
21591 self.config.dialect,
21592 Some(crate::dialects::DialectType::TSQL | crate::dialects::DialectType::Fabric)
21593 ) {
21594 if let Some(inner) = Self::tsql_string_agg_literal_separator_cast_inner(separator) {
21595 return self.generate_expression(inner);
21596 }
21597 }
21598
21599 self.generate_expression(separator)
21600 }
21601
21602 fn tsql_string_agg_literal_separator_cast_inner(separator: &Expression) -> Option<&Expression> {
21603 let Expression::Cast(cast) = separator else {
21604 return None;
21605 };
21606
21607 if cast.format.is_some() || cast.default.is_some() {
21608 return None;
21609 }
21610
21611 if !Self::is_string_data_type(&cast.to) {
21612 return None;
21613 }
21614
21615 match &cast.this {
21616 Expression::Literal(literal) if literal.is_string() => Some(&cast.this),
21617 _ => None,
21618 }
21619 }
21620
21621 fn is_string_data_type(data_type: &DataType) -> bool {
21622 matches!(
21623 data_type,
21624 DataType::Char { .. }
21625 | DataType::VarChar { .. }
21626 | DataType::String { .. }
21627 | DataType::Text
21628 | DataType::TextWithLength { .. }
21629 ) || matches!(
21630 data_type,
21631 DataType::Custom { name, .. }
21632 if name.eq_ignore_ascii_case("VARCHAR")
21633 || name.eq_ignore_ascii_case("NVARCHAR")
21634 || name.eq_ignore_ascii_case("VARCHAR(MAX)")
21635 || name.eq_ignore_ascii_case("NVARCHAR(MAX)")
21636 )
21637 }
21638
21639 fn generate_listagg(&mut self, f: &ListAggFunc) -> Result<()> {
21640 use crate::dialects::DialectType;
21641 let order_inside_args = matches!(self.config.dialect, Some(DialectType::DuckDB));
21642 self.write_keyword("LISTAGG");
21643 self.write("(");
21644 if f.distinct {
21645 self.write_keyword("DISTINCT");
21646 self.write_space();
21647 }
21648 self.generate_expression(&f.this)?;
21649 if let Some(ref sep) = f.separator {
21650 self.write(", ");
21651 self.generate_expression(sep)?;
21652 } else if matches!(
21653 self.config.dialect,
21654 Some(DialectType::Trino) | Some(DialectType::Presto)
21655 ) {
21656 self.write(", ','");
21658 }
21659 if let Some(ref overflow) = f.on_overflow {
21660 self.write_space();
21661 self.write_keyword("ON OVERFLOW");
21662 self.write_space();
21663 match overflow {
21664 ListAggOverflow::Error => self.write_keyword("ERROR"),
21665 ListAggOverflow::Truncate { filler, with_count } => {
21666 self.write_keyword("TRUNCATE");
21667 if let Some(ref fill) = filler {
21668 self.write_space();
21669 self.generate_expression(fill)?;
21670 }
21671 if *with_count {
21672 self.write_space();
21673 self.write_keyword("WITH COUNT");
21674 } else {
21675 self.write_space();
21676 self.write_keyword("WITHOUT COUNT");
21677 }
21678 }
21679 }
21680 }
21681 if order_inside_args {
21682 if let Some(ref order_by) = f.order_by {
21683 self.write_space();
21684 self.write_keyword("ORDER BY");
21685 self.write_space();
21686 for (i, ord) in order_by.iter().enumerate() {
21687 if i > 0 {
21688 self.write(", ");
21689 }
21690 self.generate_ordered(ord)?;
21691 }
21692 }
21693 }
21694 self.write(")");
21695 if !order_inside_args {
21696 if let Some(ref order_by) = f.order_by {
21697 self.write_space();
21698 self.write_keyword("WITHIN GROUP");
21699 self.write(" (");
21700 self.write_keyword("ORDER BY");
21701 self.write_space();
21702 for (i, ord) in order_by.iter().enumerate() {
21703 if i > 0 {
21704 self.write(", ");
21705 }
21706 self.generate_ordered(ord)?;
21707 }
21708 self.write(")");
21709 }
21710 }
21711 if let Some(ref filter) = f.filter {
21712 self.write_space();
21713 self.write_keyword("FILTER");
21714 self.write("(");
21715 self.write_keyword("WHERE");
21716 self.write_space();
21717 self.generate_expression(filter)?;
21718 self.write(")");
21719 }
21720 Ok(())
21721 }
21722
21723 fn generate_sum_if(&mut self, f: &SumIfFunc) -> Result<()> {
21724 self.write_keyword("SUM_IF");
21725 self.write("(");
21726 self.generate_expression(&f.this)?;
21727 self.write(", ");
21728 self.generate_expression(&f.condition)?;
21729 self.write(")");
21730 if let Some(ref filter) = f.filter {
21731 self.write_space();
21732 self.write_keyword("FILTER");
21733 self.write("(");
21734 self.write_keyword("WHERE");
21735 self.write_space();
21736 self.generate_expression(filter)?;
21737 self.write(")");
21738 }
21739 Ok(())
21740 }
21741
21742 fn generate_approx_percentile(&mut self, f: &ApproxPercentileFunc) -> Result<()> {
21743 self.write_keyword("APPROX_PERCENTILE");
21744 self.write("(");
21745 self.generate_expression(&f.this)?;
21746 self.write(", ");
21747 self.generate_expression(&f.percentile)?;
21748 if let Some(ref acc) = f.accuracy {
21749 self.write(", ");
21750 self.generate_expression(acc)?;
21751 }
21752 self.write(")");
21753 if let Some(ref filter) = f.filter {
21754 self.write_space();
21755 self.write_keyword("FILTER");
21756 self.write("(");
21757 self.write_keyword("WHERE");
21758 self.write_space();
21759 self.generate_expression(filter)?;
21760 self.write(")");
21761 }
21762 Ok(())
21763 }
21764
21765 fn generate_percentile(&mut self, name: &str, f: &PercentileFunc) -> Result<()> {
21766 self.write_keyword(name);
21767 self.write("(");
21768 self.generate_expression(&f.percentile)?;
21769 self.write(")");
21770 if let Some(ref order_by) = f.order_by {
21771 self.write_space();
21772 self.write_keyword("WITHIN GROUP");
21773 self.write(" (");
21774 self.write_keyword("ORDER BY");
21775 self.write_space();
21776 self.generate_expression(&f.this)?;
21777 for ord in order_by.iter() {
21778 if ord.desc {
21779 self.write_space();
21780 self.write_keyword("DESC");
21781 }
21782 }
21783 self.write(")");
21784 }
21785 if let Some(ref filter) = f.filter {
21786 self.write_space();
21787 self.write_keyword("FILTER");
21788 self.write("(");
21789 self.write_keyword("WHERE");
21790 self.write_space();
21791 self.generate_expression(filter)?;
21792 self.write(")");
21793 }
21794 Ok(())
21795 }
21796
21797 fn generate_ntile(&mut self, f: &NTileFunc) -> Result<()> {
21800 self.write_keyword("NTILE");
21801 self.write("(");
21802 if let Some(num_buckets) = &f.num_buckets {
21803 self.generate_expression(num_buckets)?;
21804 }
21805 if let Some(order_by) = &f.order_by {
21806 self.write_keyword(" ORDER BY ");
21807 for (i, ob) in order_by.iter().enumerate() {
21808 if i > 0 {
21809 self.write(", ");
21810 }
21811 self.generate_ordered(ob)?;
21812 }
21813 }
21814 self.write(")");
21815 Ok(())
21816 }
21817
21818 fn generate_lead_lag(&mut self, name: &str, f: &LeadLagFunc) -> Result<()> {
21819 self.write_keyword(name);
21820 self.write("(");
21821 self.generate_expression(&f.this)?;
21822 if let Some(ref offset) = f.offset {
21823 self.write(", ");
21824 self.generate_expression(offset)?;
21825 if let Some(ref default) = f.default {
21826 self.write(", ");
21827 self.generate_expression(default)?;
21828 }
21829 }
21830 if self.config.ignore_nulls_in_func {
21832 match f.ignore_nulls {
21833 Some(true) => {
21834 self.write_space();
21835 self.write_keyword("IGNORE NULLS");
21836 }
21837 Some(false) => {
21838 self.write_space();
21839 self.write_keyword("RESPECT NULLS");
21840 }
21841 None => {}
21842 }
21843 }
21844 self.write(")");
21845 if !self.config.ignore_nulls_in_func {
21847 match f.ignore_nulls {
21848 Some(true) => {
21849 self.write_space();
21850 self.write_keyword("IGNORE NULLS");
21851 }
21852 Some(false) => {
21853 self.write_space();
21854 self.write_keyword("RESPECT NULLS");
21855 }
21856 None => {}
21857 }
21858 }
21859 Ok(())
21860 }
21861
21862 fn generate_value_func(&mut self, name: &str, f: &ValueFunc) -> Result<()> {
21863 self.write_keyword(name);
21864 self.write("(");
21865 self.generate_expression(&f.this)?;
21866 if !f.order_by.is_empty() {
21868 self.write_space();
21869 self.write_keyword("ORDER BY");
21870 self.write_space();
21871 for (i, ordered) in f.order_by.iter().enumerate() {
21872 if i > 0 {
21873 self.write(", ");
21874 }
21875 self.generate_ordered(ordered)?;
21876 }
21877 }
21878 if self.config.ignore_nulls_in_func {
21880 match f.ignore_nulls {
21881 Some(true) => {
21882 self.write_space();
21883 self.write_keyword("IGNORE NULLS");
21884 }
21885 Some(false) => {
21886 self.write_space();
21887 self.write_keyword("RESPECT NULLS");
21888 }
21889 None => {}
21890 }
21891 }
21892 self.write(")");
21893 if !self.config.ignore_nulls_in_func {
21895 match f.ignore_nulls {
21896 Some(true) => {
21897 self.write_space();
21898 self.write_keyword("IGNORE NULLS");
21899 }
21900 Some(false) => {
21901 self.write_space();
21902 self.write_keyword("RESPECT NULLS");
21903 }
21904 None => {}
21905 }
21906 }
21907 Ok(())
21908 }
21909
21910 fn generate_value_func_with_ignore_nulls_bool(
21913 &mut self,
21914 name: &str,
21915 f: &ValueFunc,
21916 ) -> Result<()> {
21917 if matches!(self.config.dialect, Some(DialectType::Hive)) && f.ignore_nulls == Some(true) {
21918 self.write_keyword(name);
21919 self.write("(");
21920 self.generate_expression(&f.this)?;
21921 self.write(", ");
21922 self.write_keyword("TRUE");
21923 self.write(")");
21924 return Ok(());
21925 }
21926 self.generate_value_func(name, f)
21927 }
21928
21929 fn generate_nth_value(&mut self, f: &NthValueFunc) -> Result<()> {
21930 self.write_keyword("NTH_VALUE");
21931 self.write("(");
21932 self.generate_expression(&f.this)?;
21933 self.write(", ");
21934 self.generate_expression(&f.offset)?;
21935 if self.config.ignore_nulls_in_func {
21937 match f.ignore_nulls {
21938 Some(true) => {
21939 self.write_space();
21940 self.write_keyword("IGNORE NULLS");
21941 }
21942 Some(false) => {
21943 self.write_space();
21944 self.write_keyword("RESPECT NULLS");
21945 }
21946 None => {}
21947 }
21948 }
21949 self.write(")");
21950 if matches!(
21952 self.config.dialect,
21953 Some(crate::dialects::DialectType::Snowflake)
21954 ) {
21955 match f.from_first {
21956 Some(true) => {
21957 self.write_space();
21958 self.write_keyword("FROM FIRST");
21959 }
21960 Some(false) => {
21961 self.write_space();
21962 self.write_keyword("FROM LAST");
21963 }
21964 None => {}
21965 }
21966 }
21967 if !self.config.ignore_nulls_in_func {
21969 match f.ignore_nulls {
21970 Some(true) => {
21971 self.write_space();
21972 self.write_keyword("IGNORE NULLS");
21973 }
21974 Some(false) => {
21975 self.write_space();
21976 self.write_keyword("RESPECT NULLS");
21977 }
21978 None => {}
21979 }
21980 }
21981 Ok(())
21982 }
21983
21984 fn generate_position(&mut self, f: &PositionFunc) -> Result<()> {
21987 if matches!(
21990 self.config.dialect,
21991 Some(crate::dialects::DialectType::ClickHouse)
21992 ) {
21993 self.write_keyword("POSITION");
21994 self.write("(");
21995 self.generate_expression(&f.string)?;
21996 self.write(", ");
21997 self.generate_expression(&f.substring)?;
21998 if let Some(ref start) = f.start {
21999 self.write(", ");
22000 self.generate_expression(start)?;
22001 }
22002 self.write(")");
22003 return Ok(());
22004 }
22005
22006 self.write_keyword("POSITION");
22007 self.write("(");
22008 self.generate_expression(&f.substring)?;
22009 self.write_space();
22010 self.write_keyword("IN");
22011 self.write_space();
22012 self.generate_expression(&f.string)?;
22013 if let Some(ref start) = f.start {
22014 self.write(", ");
22015 self.generate_expression(start)?;
22016 }
22017 self.write(")");
22018 Ok(())
22019 }
22020
22021 fn generate_rand(&mut self, f: &Rand) -> Result<()> {
22024 if f.lower.is_some() || f.upper.is_some() {
22026 self.write_keyword("RANDOM");
22027 self.write("(");
22028 if let Some(ref lower) = f.lower {
22029 self.generate_expression(lower)?;
22030 }
22031 if let Some(ref upper) = f.upper {
22032 self.write(", ");
22033 self.generate_expression(upper)?;
22034 }
22035 self.write(")");
22036 return Ok(());
22037 }
22038 let func_name = match self.config.dialect {
22040 Some(crate::dialects::DialectType::Snowflake)
22041 | Some(crate::dialects::DialectType::DuckDB) => "RANDOM",
22042 _ => "RAND",
22043 };
22044 self.write_keyword(func_name);
22045 self.write("(");
22046 if !matches!(
22048 self.config.dialect,
22049 Some(crate::dialects::DialectType::DuckDB)
22050 ) {
22051 if let Some(ref seed) = f.seed {
22052 self.generate_expression(seed)?;
22053 }
22054 }
22055 self.write(")");
22056 Ok(())
22057 }
22058
22059 fn generate_truncate_func(&mut self, f: &TruncateFunc) -> Result<()> {
22060 self.write_keyword("TRUNCATE");
22061 self.write("(");
22062 self.generate_expression(&f.this)?;
22063 if let Some(ref decimals) = f.decimals {
22064 self.write(", ");
22065 self.generate_expression(decimals)?;
22066 }
22067 self.write(")");
22068 Ok(())
22069 }
22070
22071 fn generate_decode(&mut self, f: &DecodeFunc) -> Result<()> {
22074 self.write_keyword("DECODE");
22075 self.write("(");
22076 self.generate_expression(&f.this)?;
22077 for (search, result) in &f.search_results {
22078 self.write(", ");
22079 self.generate_expression(search)?;
22080 self.write(", ");
22081 self.generate_expression(result)?;
22082 }
22083 if let Some(ref default) = f.default {
22084 self.write(", ");
22085 self.generate_expression(default)?;
22086 }
22087 self.write(")");
22088 Ok(())
22089 }
22090
22091 fn generate_date_format(&mut self, name: &str, f: &DateFormatFunc) -> Result<()> {
22094 self.write_keyword(name);
22095 self.write("(");
22096 self.generate_expression(&f.this)?;
22097 self.write(", ");
22098 self.generate_expression(&f.format)?;
22099 self.write(")");
22100 Ok(())
22101 }
22102
22103 fn generate_from_unixtime(&mut self, f: &FromUnixtimeFunc) -> Result<()> {
22104 self.write_keyword("FROM_UNIXTIME");
22105 self.write("(");
22106 self.generate_expression(&f.this)?;
22107 if let Some(ref format) = f.format {
22108 self.write(", ");
22109 self.generate_expression(format)?;
22110 }
22111 self.write(")");
22112 Ok(())
22113 }
22114
22115 fn generate_unix_timestamp(&mut self, f: &UnixTimestampFunc) -> Result<()> {
22116 self.write_keyword("UNIX_TIMESTAMP");
22117 self.write("(");
22118 if let Some(ref expr) = f.this {
22119 self.generate_expression(expr)?;
22120 if let Some(ref format) = f.format {
22121 self.write(", ");
22122 self.generate_expression(format)?;
22123 }
22124 } else if matches!(
22125 self.config.dialect,
22126 Some(DialectType::Spark) | Some(DialectType::Hive) | Some(DialectType::Databricks)
22127 ) {
22128 self.write_keyword("CURRENT_TIMESTAMP");
22130 self.write("()");
22131 }
22132 self.write(")");
22133 Ok(())
22134 }
22135
22136 fn generate_make_date(&mut self, f: &MakeDateFunc) -> Result<()> {
22137 self.write_keyword("MAKE_DATE");
22138 self.write("(");
22139 self.generate_expression(&f.year)?;
22140 self.write(", ");
22141 self.generate_expression(&f.month)?;
22142 self.write(", ");
22143 self.generate_expression(&f.day)?;
22144 self.write(")");
22145 Ok(())
22146 }
22147
22148 fn generate_make_timestamp(&mut self, f: &MakeTimestampFunc) -> Result<()> {
22149 self.write_keyword("MAKE_TIMESTAMP");
22150 self.write("(");
22151 self.generate_expression(&f.year)?;
22152 self.write(", ");
22153 self.generate_expression(&f.month)?;
22154 self.write(", ");
22155 self.generate_expression(&f.day)?;
22156 self.write(", ");
22157 self.generate_expression(&f.hour)?;
22158 self.write(", ");
22159 self.generate_expression(&f.minute)?;
22160 self.write(", ");
22161 self.generate_expression(&f.second)?;
22162 if let Some(ref tz) = f.timezone {
22163 self.write(", ");
22164 self.generate_expression(tz)?;
22165 }
22166 self.write(")");
22167 Ok(())
22168 }
22169
22170 fn extract_struct_field_names(expr: &Expression) -> Option<Vec<String>> {
22172 match expr {
22173 Expression::Struct(s) => {
22174 if s.fields.iter().all(|(name, _)| name.is_some()) {
22175 Some(
22176 s.fields
22177 .iter()
22178 .map(|(name, _)| name.as_deref().unwrap_or("").to_string())
22179 .collect(),
22180 )
22181 } else {
22182 None
22183 }
22184 }
22185 Expression::Function(f) if f.name.eq_ignore_ascii_case("STRUCT") => {
22186 if f.args.iter().all(|a| matches!(a, Expression::Alias(_))) {
22188 Some(
22189 f.args
22190 .iter()
22191 .filter_map(|a| {
22192 if let Expression::Alias(alias) = a {
22193 Some(alias.alias.name.clone())
22194 } else {
22195 None
22196 }
22197 })
22198 .collect(),
22199 )
22200 } else {
22201 None
22202 }
22203 }
22204 _ => None,
22205 }
22206 }
22207
22208 fn struct_has_unnamed_fields(expr: &Expression) -> bool {
22210 match expr {
22211 Expression::Struct(s) => s.fields.iter().any(|(name, _)| name.is_none()),
22212 Expression::Function(f) if f.name.eq_ignore_ascii_case("STRUCT") => {
22213 f.args.iter().any(|a| !matches!(a, Expression::Alias(_)))
22214 }
22215 _ => false,
22216 }
22217 }
22218
22219 fn struct_field_count(expr: &Expression) -> usize {
22221 match expr {
22222 Expression::Struct(s) => s.fields.len(),
22223 Expression::Function(f) if f.name.eq_ignore_ascii_case("STRUCT") => f.args.len(),
22224 _ => 0,
22225 }
22226 }
22227
22228 fn apply_struct_field_names(expr: &Expression, field_names: &[String]) -> Expression {
22230 match expr {
22231 Expression::Struct(s) => {
22232 let mut new_fields = Vec::with_capacity(s.fields.len());
22233 for (i, (name, value)) in s.fields.iter().enumerate() {
22234 if name.is_none() && i < field_names.len() {
22235 new_fields.push((Some(field_names[i].clone()), value.clone()));
22236 } else {
22237 new_fields.push((name.clone(), value.clone()));
22238 }
22239 }
22240 Expression::Struct(Box::new(crate::expressions::Struct { fields: new_fields }))
22241 }
22242 Expression::Function(f) if f.name.eq_ignore_ascii_case("STRUCT") => {
22243 let mut new_args = Vec::with_capacity(f.args.len());
22244 for (i, arg) in f.args.iter().enumerate() {
22245 if !matches!(arg, Expression::Alias(_)) && i < field_names.len() {
22246 new_args.push(Expression::Alias(Box::new(crate::expressions::Alias {
22248 this: arg.clone(),
22249 alias: crate::expressions::Identifier::new(field_names[i].clone()),
22250 column_aliases: Vec::new(),
22251 alias_explicit_as: false,
22252 alias_keyword: None,
22253 pre_alias_comments: Vec::new(),
22254 trailing_comments: Vec::new(),
22255 inferred_type: None,
22256 })));
22257 } else {
22258 new_args.push(arg.clone());
22259 }
22260 }
22261 Expression::Function(Box::new(crate::expressions::Function {
22262 name: f.name.clone(),
22263 args: new_args,
22264 distinct: f.distinct,
22265 trailing_comments: f.trailing_comments.clone(),
22266 use_bracket_syntax: f.use_bracket_syntax,
22267 no_parens: f.no_parens,
22268 quoted: f.quoted,
22269 span: None,
22270 inferred_type: None,
22271 }))
22272 }
22273 _ => expr.clone(),
22274 }
22275 }
22276
22277 fn inherit_struct_field_names(expressions: &[Expression]) -> Vec<Expression> {
22281 let first = match expressions.first() {
22282 Some(e) => e,
22283 None => return expressions.to_vec(),
22284 };
22285
22286 let field_names = match Self::extract_struct_field_names(first) {
22287 Some(names) if !names.is_empty() => names,
22288 _ => return expressions.to_vec(),
22289 };
22290
22291 let mut result = Vec::with_capacity(expressions.len());
22292 for (idx, expr) in expressions.iter().enumerate() {
22293 if idx == 0 {
22294 result.push(expr.clone());
22295 continue;
22296 }
22297 if Self::struct_field_count(expr) == field_names.len()
22299 && Self::struct_has_unnamed_fields(expr)
22300 {
22301 result.push(Self::apply_struct_field_names(expr, &field_names));
22302 } else {
22303 result.push(expr.clone());
22304 }
22305 }
22306 result
22307 }
22308
22309 fn generate_array_constructor(&mut self, f: &ArrayConstructor) -> Result<()> {
22312 let needs_inheritance = matches!(
22315 self.config.dialect,
22316 Some(DialectType::DuckDB)
22317 | Some(DialectType::Spark)
22318 | Some(DialectType::Databricks)
22319 | Some(DialectType::Hive)
22320 | Some(DialectType::Snowflake)
22321 | Some(DialectType::Presto)
22322 | Some(DialectType::Trino)
22323 );
22324 let propagated: Vec<Expression>;
22325 let expressions = if needs_inheritance && f.expressions.len() > 1 {
22326 propagated = Self::inherit_struct_field_names(&f.expressions);
22327 &propagated
22328 } else {
22329 &f.expressions
22330 };
22331
22332 let should_split = if self.config.pretty && !expressions.is_empty() {
22334 let mut expr_strings: Vec<String> = Vec::with_capacity(expressions.len());
22335 for expr in expressions {
22336 let mut temp_gen = Generator::with_arc_config(self.config.clone());
22337 Arc::make_mut(&mut temp_gen.config).pretty = false;
22338 temp_gen.generate_expression(expr)?;
22339 expr_strings.push(temp_gen.output);
22340 }
22341 self.too_wide(&expr_strings)
22342 } else {
22343 false
22344 };
22345
22346 if f.bracket_notation {
22347 let (open, close) = match self.config.dialect {
22351 None
22352 | Some(DialectType::Generic)
22353 | Some(DialectType::Spark)
22354 | Some(DialectType::Databricks)
22355 | Some(DialectType::Hive) => {
22356 self.write_keyword("ARRAY");
22357 ("(", ")")
22358 }
22359 Some(DialectType::Presto)
22360 | Some(DialectType::Trino)
22361 | Some(DialectType::PostgreSQL)
22362 | Some(DialectType::Redshift)
22363 | Some(DialectType::Materialize)
22364 | Some(DialectType::RisingWave)
22365 | Some(DialectType::CockroachDB) => {
22366 self.write_keyword("ARRAY");
22367 ("[", "]")
22368 }
22369 _ => ("[", "]"),
22370 };
22371 self.write(open);
22372 if should_split {
22373 self.write_newline();
22374 self.indent_level += 1;
22375 for (i, expr) in expressions.iter().enumerate() {
22376 self.write_indent();
22377 self.generate_expression(expr)?;
22378 if i + 1 < expressions.len() {
22379 self.write(",");
22380 }
22381 self.write_newline();
22382 }
22383 self.indent_level -= 1;
22384 self.write_indent();
22385 } else {
22386 for (i, expr) in expressions.iter().enumerate() {
22387 if i > 0 {
22388 self.write(", ");
22389 }
22390 self.generate_expression(expr)?;
22391 }
22392 }
22393 self.write(close);
22394 } else {
22395 if f.use_list_keyword {
22397 self.write_keyword("LIST");
22398 } else {
22399 self.write_keyword("ARRAY");
22400 }
22401 let has_subquery = expressions
22404 .iter()
22405 .any(|e| matches!(e, Expression::Select(_)));
22406 let (open, close) = if matches!(
22407 self.config.dialect,
22408 Some(DialectType::Spark) | Some(DialectType::Databricks) | Some(DialectType::Hive)
22409 ) || (matches!(self.config.dialect, Some(DialectType::BigQuery))
22410 && has_subquery)
22411 {
22412 ("(", ")")
22413 } else {
22414 ("[", "]")
22415 };
22416 self.write(open);
22417 if should_split {
22418 self.write_newline();
22419 self.indent_level += 1;
22420 for (i, expr) in expressions.iter().enumerate() {
22421 self.write_indent();
22422 self.generate_expression(expr)?;
22423 if i + 1 < expressions.len() {
22424 self.write(",");
22425 }
22426 self.write_newline();
22427 }
22428 self.indent_level -= 1;
22429 self.write_indent();
22430 } else {
22431 for (i, expr) in expressions.iter().enumerate() {
22432 if i > 0 {
22433 self.write(", ");
22434 }
22435 self.generate_expression(expr)?;
22436 }
22437 }
22438 self.write(close);
22439 }
22440 Ok(())
22441 }
22442
22443 fn generate_array_sort(&mut self, f: &ArraySortFunc) -> Result<()> {
22444 self.write_keyword("ARRAY_SORT");
22445 self.write("(");
22446 self.generate_expression(&f.this)?;
22447 if let Some(ref comp) = f.comparator {
22448 self.write(", ");
22449 self.generate_expression(comp)?;
22450 }
22451 self.write(")");
22452 Ok(())
22453 }
22454
22455 fn generate_array_join(&mut self, name: &str, f: &ArrayJoinFunc) -> Result<()> {
22456 self.write_keyword(name);
22457 self.write("(");
22458 self.generate_expression(&f.this)?;
22459 self.write(", ");
22460 self.generate_expression(&f.separator)?;
22461 if let Some(ref null_rep) = f.null_replacement {
22462 self.write(", ");
22463 self.generate_expression(null_rep)?;
22464 }
22465 self.write(")");
22466 Ok(())
22467 }
22468
22469 fn generate_unnest(&mut self, f: &UnnestFunc) -> Result<()> {
22470 self.write_keyword("UNNEST");
22471 self.write("(");
22472 self.generate_expression(&f.this)?;
22473 for extra in &f.expressions {
22474 self.write(", ");
22475 self.generate_expression(extra)?;
22476 }
22477 self.write(")");
22478 if f.with_ordinality {
22479 self.write_space();
22480 if self.config.unnest_with_ordinality {
22481 self.write_keyword("WITH ORDINALITY");
22483 } else if f.offset_alias.is_some() {
22484 if let Some(ref alias) = f.alias {
22487 self.write_keyword("AS");
22488 self.write_space();
22489 self.generate_identifier(alias)?;
22490 self.write_space();
22491 }
22492 self.write_keyword("WITH OFFSET");
22493 if let Some(ref offset_alias) = f.offset_alias {
22494 self.write_space();
22495 self.write_keyword("AS");
22496 self.write_space();
22497 self.generate_identifier(offset_alias)?;
22498 }
22499 } else {
22500 self.write_keyword("WITH OFFSET");
22502 if f.alias.is_none() {
22503 self.write(" AS offset");
22504 }
22505 }
22506 }
22507 if let Some(ref alias) = f.alias {
22508 let should_add_alias = if !f.with_ordinality {
22510 true
22511 } else if self.config.unnest_with_ordinality {
22512 true
22514 } else if f.offset_alias.is_some() {
22515 false
22517 } else {
22518 true
22520 };
22521 if should_add_alias {
22522 self.write_space();
22523 self.write_keyword("AS");
22524 self.write_space();
22525 self.generate_identifier(alias)?;
22526 }
22527 }
22528 Ok(())
22529 }
22530
22531 fn generate_array_filter(&mut self, f: &ArrayFilterFunc) -> Result<()> {
22532 self.write_keyword("FILTER");
22533 self.write("(");
22534 self.generate_expression(&f.this)?;
22535 self.write(", ");
22536 self.generate_expression(&f.filter)?;
22537 self.write(")");
22538 Ok(())
22539 }
22540
22541 fn generate_array_transform(&mut self, f: &ArrayTransformFunc) -> Result<()> {
22542 self.write_keyword("TRANSFORM");
22543 self.write("(");
22544 self.generate_expression(&f.this)?;
22545 self.write(", ");
22546 self.generate_expression(&f.transform)?;
22547 self.write(")");
22548 Ok(())
22549 }
22550
22551 fn generate_sequence(&mut self, name: &str, f: &SequenceFunc) -> Result<()> {
22552 self.write_keyword(name);
22553 self.write("(");
22554 self.generate_expression(&f.start)?;
22555 self.write(", ");
22556 self.generate_expression(&f.stop)?;
22557 if let Some(ref step) = f.step {
22558 self.write(", ");
22559 self.generate_expression(step)?;
22560 }
22561 self.write(")");
22562 Ok(())
22563 }
22564
22565 fn generate_struct_constructor(&mut self, f: &StructConstructor) -> Result<()> {
22568 self.write_keyword("STRUCT");
22569 self.write("(");
22570 for (i, (name, expr)) in f.fields.iter().enumerate() {
22571 if i > 0 {
22572 self.write(", ");
22573 }
22574 if let Some(ref id) = name {
22575 self.generate_identifier(id)?;
22576 self.write(" ");
22577 self.write_keyword("AS");
22578 self.write(" ");
22579 }
22580 self.generate_expression(expr)?;
22581 }
22582 self.write(")");
22583 Ok(())
22584 }
22585
22586 fn generate_struct_function_cross_dialect(&mut self, func: &Function) -> Result<()> {
22588 let mut names: Vec<Option<String>> = Vec::new();
22591 let mut values: Vec<&Expression> = Vec::new();
22592 let mut all_named = true;
22593
22594 for arg in &func.args {
22595 match arg {
22596 Expression::Alias(a) => {
22597 names.push(Some(a.alias.name.clone()));
22598 values.push(&a.this);
22599 }
22600 _ => {
22601 names.push(None);
22602 values.push(arg);
22603 all_named = false;
22604 }
22605 }
22606 }
22607
22608 if matches!(self.config.dialect, Some(DialectType::DuckDB)) {
22609 self.write("{");
22611 for (i, (name, value)) in names.iter().zip(values.iter()).enumerate() {
22612 if i > 0 {
22613 self.write(", ");
22614 }
22615 if let Some(n) = name {
22616 self.write("'");
22617 self.write(n);
22618 self.write("'");
22619 } else {
22620 self.write("'_");
22621 self.write(&i.to_string());
22622 self.write("'");
22623 }
22624 self.write(": ");
22625 self.generate_expression(value)?;
22626 }
22627 self.write("}");
22628 return Ok(());
22629 }
22630
22631 if matches!(self.config.dialect, Some(DialectType::Snowflake)) {
22632 self.write_keyword("OBJECT_CONSTRUCT");
22634 self.write("(");
22635 for (i, (name, value)) in names.iter().zip(values.iter()).enumerate() {
22636 if i > 0 {
22637 self.write(", ");
22638 }
22639 if let Some(n) = name {
22640 self.write("'");
22641 self.write(n);
22642 self.write("'");
22643 } else {
22644 self.write("'_");
22645 self.write(&i.to_string());
22646 self.write("'");
22647 }
22648 self.write(", ");
22649 self.generate_expression(value)?;
22650 }
22651 self.write(")");
22652 return Ok(());
22653 }
22654
22655 if matches!(
22656 self.config.dialect,
22657 Some(DialectType::Presto) | Some(DialectType::Trino)
22658 ) {
22659 if all_named && !names.is_empty() {
22660 self.write_keyword("CAST");
22663 self.write("(");
22664 self.write_keyword("ROW");
22665 self.write("(");
22666 for (i, value) in values.iter().enumerate() {
22667 if i > 0 {
22668 self.write(", ");
22669 }
22670 self.generate_expression(value)?;
22671 }
22672 self.write(")");
22673 self.write(" ");
22674 self.write_keyword("AS");
22675 self.write(" ");
22676 self.write_keyword("ROW");
22677 self.write("(");
22678 for (i, (name, value)) in names.iter().zip(values.iter()).enumerate() {
22679 if i > 0 {
22680 self.write(", ");
22681 }
22682 if let Some(n) = name {
22683 self.write(n);
22684 }
22685 self.write(" ");
22686 let type_str = Self::infer_sql_type_for_presto(value);
22687 self.write_keyword(&type_str);
22688 }
22689 self.write(")");
22690 self.write(")");
22691 } else {
22692 self.write_keyword("ROW");
22694 self.write("(");
22695 for (i, value) in values.iter().enumerate() {
22696 if i > 0 {
22697 self.write(", ");
22698 }
22699 self.generate_expression(value)?;
22700 }
22701 self.write(")");
22702 }
22703 return Ok(());
22704 }
22705
22706 self.write_keyword("ROW");
22708 self.write("(");
22709 for (i, value) in values.iter().enumerate() {
22710 if i > 0 {
22711 self.write(", ");
22712 }
22713 self.generate_expression(value)?;
22714 }
22715 self.write(")");
22716 Ok(())
22717 }
22718
22719 fn infer_sql_type_for_presto(expr: &Expression) -> String {
22721 match expr {
22722 Expression::Literal(lit)
22723 if matches!(lit.as_ref(), crate::expressions::Literal::String(_)) =>
22724 {
22725 "VARCHAR".to_string()
22726 }
22727 Expression::Literal(lit)
22728 if matches!(lit.as_ref(), crate::expressions::Literal::Number(_)) =>
22729 {
22730 let crate::expressions::Literal::Number(n) = lit.as_ref() else {
22731 unreachable!()
22732 };
22733 if n.contains('.') {
22734 "DOUBLE".to_string()
22735 } else {
22736 "INTEGER".to_string()
22737 }
22738 }
22739 Expression::Boolean(_) => "BOOLEAN".to_string(),
22740 Expression::Literal(lit)
22741 if matches!(lit.as_ref(), crate::expressions::Literal::Date(_)) =>
22742 {
22743 "DATE".to_string()
22744 }
22745 Expression::Literal(lit)
22746 if matches!(lit.as_ref(), crate::expressions::Literal::Timestamp(_)) =>
22747 {
22748 "TIMESTAMP".to_string()
22749 }
22750 Expression::Literal(lit)
22751 if matches!(lit.as_ref(), crate::expressions::Literal::Datetime(_)) =>
22752 {
22753 "TIMESTAMP".to_string()
22754 }
22755 Expression::Array(_) | Expression::ArrayFunc(_) => {
22756 "ARRAY(VARCHAR)".to_string()
22758 }
22759 Expression::Struct(_) | Expression::StructFunc(_) => "ROW".to_string(),
22761 Expression::Function(f) => {
22762 if f.name.eq_ignore_ascii_case("STRUCT") {
22763 "ROW".to_string()
22764 } else if f.name.eq_ignore_ascii_case("CURRENT_DATE") {
22765 "DATE".to_string()
22766 } else if f.name.eq_ignore_ascii_case("CURRENT_TIMESTAMP")
22767 || f.name.eq_ignore_ascii_case("NOW")
22768 {
22769 "TIMESTAMP".to_string()
22770 } else {
22771 "VARCHAR".to_string()
22772 }
22773 }
22774 _ => "VARCHAR".to_string(),
22775 }
22776 }
22777
22778 fn generate_struct_extract(&mut self, f: &StructExtractFunc) -> Result<()> {
22779 if matches!(self.config.dialect, Some(DialectType::DuckDB)) {
22781 self.write_keyword("STRUCT_EXTRACT");
22782 self.write("(");
22783 self.generate_expression(&f.this)?;
22784 self.write(", ");
22785 self.write("'");
22787 self.write(&f.field.name);
22788 self.write("'");
22789 self.write(")");
22790 return Ok(());
22791 }
22792 self.generate_expression(&f.this)?;
22793 self.write(".");
22794 self.generate_identifier(&f.field)
22795 }
22796
22797 fn generate_named_struct(&mut self, f: &NamedStructFunc) -> Result<()> {
22798 if matches!(
22799 self.config.dialect,
22800 Some(DialectType::Spark | DialectType::Databricks)
22801 ) {
22802 self.write_keyword("STRUCT");
22803 self.write("(");
22804 for (i, (name, value)) in f.pairs.iter().enumerate() {
22805 if i > 0 {
22806 self.write(", ");
22807 }
22808 self.generate_expression(value)?;
22809 self.write(" ");
22810 self.write_keyword("AS");
22811 self.write(" ");
22812 if let Expression::Literal(lit) = name {
22813 if let Literal::String(field_name) = lit.as_ref() {
22814 self.generate_identifier(&Identifier::new(field_name))?;
22815 } else {
22816 self.generate_expression(name)?;
22817 }
22818 } else {
22819 self.generate_expression(name)?;
22820 }
22821 }
22822 self.write(")");
22823 return Ok(());
22824 }
22825
22826 self.write_keyword("NAMED_STRUCT");
22827 self.write("(");
22828 for (i, (name, value)) in f.pairs.iter().enumerate() {
22829 if i > 0 {
22830 self.write(", ");
22831 }
22832 self.generate_expression(name)?;
22833 self.write(", ");
22834 self.generate_expression(value)?;
22835 }
22836 self.write(")");
22837 Ok(())
22838 }
22839
22840 fn generate_map_constructor(&mut self, f: &MapConstructor) -> Result<()> {
22843 if f.curly_brace_syntax {
22844 if f.with_map_keyword {
22846 self.write_keyword("MAP");
22847 self.write(" ");
22848 }
22849 self.write("{");
22850 for (i, (key, val)) in f.keys.iter().zip(f.values.iter()).enumerate() {
22851 if i > 0 {
22852 self.write(", ");
22853 }
22854 self.generate_expression(key)?;
22855 self.write(": ");
22856 self.generate_expression(val)?;
22857 }
22858 self.write("}");
22859 } else {
22860 self.write_keyword("MAP");
22862 self.write("(");
22863 self.write_keyword("ARRAY");
22864 self.write("[");
22865 for (i, key) in f.keys.iter().enumerate() {
22866 if i > 0 {
22867 self.write(", ");
22868 }
22869 self.generate_expression(key)?;
22870 }
22871 self.write("], ");
22872 self.write_keyword("ARRAY");
22873 self.write("[");
22874 for (i, val) in f.values.iter().enumerate() {
22875 if i > 0 {
22876 self.write(", ");
22877 }
22878 self.generate_expression(val)?;
22879 }
22880 self.write("])");
22881 }
22882 Ok(())
22883 }
22884
22885 fn generate_transform_func(&mut self, name: &str, f: &TransformFunc) -> Result<()> {
22886 self.write_keyword(name);
22887 self.write("(");
22888 self.generate_expression(&f.this)?;
22889 self.write(", ");
22890 self.generate_expression(&f.transform)?;
22891 self.write(")");
22892 Ok(())
22893 }
22894
22895 fn generate_json_extract(&mut self, name: &str, f: &JsonExtractFunc) -> Result<()> {
22898 use crate::dialects::DialectType;
22899
22900 let use_arrow = f.arrow_syntax && self.dialect_supports_json_arrow();
22902
22903 if use_arrow {
22904 self.generate_expression(&f.this)?;
22906 if name == "JSON_EXTRACT_SCALAR" || name == "JSON_EXTRACT_PATH_TEXT" {
22907 self.write(" ->> ");
22908 } else {
22909 self.write(" -> ");
22910 }
22911 self.generate_expression(&f.path)?;
22912 return Ok(());
22913 }
22914
22915 if f.hash_arrow_syntax
22917 && matches!(
22918 self.config.dialect,
22919 Some(DialectType::PostgreSQL) | Some(DialectType::Redshift)
22920 )
22921 {
22922 self.generate_expression(&f.this)?;
22923 self.write(" #>> ");
22924 self.generate_expression(&f.path)?;
22925 return Ok(());
22926 }
22927
22928 let func_name = if matches!(self.config.dialect, Some(DialectType::Redshift)) {
22931 match name {
22932 "JSON_EXTRACT_SCALAR"
22933 | "JSON_EXTRACT_PATH_TEXT"
22934 | "JSON_EXTRACT"
22935 | "JSON_EXTRACT_PATH" => "JSON_EXTRACT_PATH_TEXT",
22936 _ => name,
22937 }
22938 } else if matches!(self.config.dialect, Some(DialectType::PostgreSQL)) {
22939 match name {
22940 "JSON_EXTRACT_SCALAR" | "JSON_EXTRACT_PATH_TEXT" => "JSON_EXTRACT_PATH_TEXT",
22941 "JSON_EXTRACT" | "JSON_EXTRACT_PATH" => "JSON_EXTRACT_PATH",
22942 _ => name,
22943 }
22944 } else {
22945 name
22946 };
22947
22948 self.write_keyword(func_name);
22949 self.write("(");
22950 if matches!(self.config.dialect, Some(DialectType::Redshift)) {
22952 if let Expression::Cast(ref cast) = f.this {
22953 if matches!(cast.to, crate::expressions::DataType::Json) {
22954 self.generate_expression(&cast.this)?;
22955 } else {
22956 self.generate_expression(&f.this)?;
22957 }
22958 } else {
22959 self.generate_expression(&f.this)?;
22960 }
22961 } else {
22962 self.generate_expression(&f.this)?;
22963 }
22964 if matches!(
22967 self.config.dialect,
22968 Some(DialectType::PostgreSQL) | Some(DialectType::Redshift)
22969 ) && (func_name == "JSON_EXTRACT_PATH" || func_name == "JSON_EXTRACT_PATH_TEXT")
22970 {
22971 if let Expression::Literal(ref lit) = f.path {
22972 if let Literal::String(ref s) = lit.as_ref() {
22973 let parts = Self::decompose_json_path(s);
22974 for part in &parts {
22975 self.write(", '");
22976 self.write(part);
22977 self.write("'");
22978 }
22979 }
22980 } else {
22981 self.write(", ");
22982 self.generate_expression(&f.path)?;
22983 }
22984 } else {
22985 self.write(", ");
22986 self.generate_expression(&f.path)?;
22987 }
22988
22989 if let Some(ref wrapper) = f.wrapper_option {
22992 self.write_space();
22993 self.write_keyword(wrapper);
22994 }
22995 if let Some(ref quotes) = f.quotes_option {
22996 self.write_space();
22997 self.write_keyword(quotes);
22998 if f.on_scalar_string {
22999 self.write_space();
23000 self.write_keyword("ON SCALAR STRING");
23001 }
23002 }
23003 if let Some(ref on_err) = f.on_error {
23004 self.write_space();
23005 self.write_keyword(on_err);
23006 }
23007 if let Some(ref ret_type) = f.returning {
23008 self.write_space();
23009 self.write_keyword("RETURNING");
23010 self.write_space();
23011 self.generate_data_type(ret_type)?;
23012 }
23013
23014 self.write(")");
23015 Ok(())
23016 }
23017
23018 fn dialect_supports_json_arrow(&self) -> bool {
23020 use crate::dialects::DialectType;
23021 match self.config.dialect {
23022 Some(DialectType::PostgreSQL) => true,
23024 Some(DialectType::MySQL) => true,
23025 Some(DialectType::DuckDB) => true,
23026 Some(DialectType::CockroachDB) => true,
23027 Some(DialectType::StarRocks) => true,
23028 Some(DialectType::SQLite) => true,
23029 _ => false,
23031 }
23032 }
23033
23034 fn generate_json_path(&mut self, name: &str, f: &JsonPathFunc) -> Result<()> {
23035 use crate::dialects::DialectType;
23036
23037 if matches!(
23039 self.config.dialect,
23040 Some(DialectType::PostgreSQL) | Some(DialectType::Redshift)
23041 ) && name == "JSON_EXTRACT_PATH"
23042 {
23043 self.generate_expression(&f.this)?;
23044 self.write(" #> ");
23045 if f.paths.len() == 1 {
23046 self.generate_expression(&f.paths[0])?;
23047 } else {
23048 self.write_keyword("ARRAY");
23050 self.write("[");
23051 for (i, path) in f.paths.iter().enumerate() {
23052 if i > 0 {
23053 self.write(", ");
23054 }
23055 self.generate_expression(path)?;
23056 }
23057 self.write("]");
23058 }
23059 return Ok(());
23060 }
23061
23062 self.write_keyword(name);
23063 self.write("(");
23064 self.generate_expression(&f.this)?;
23065 for path in &f.paths {
23066 self.write(", ");
23067 self.generate_expression(path)?;
23068 }
23069 self.write(")");
23070 Ok(())
23071 }
23072
23073 fn generate_json_object(&mut self, f: &JsonObjectFunc) -> Result<()> {
23074 use crate::dialects::DialectType;
23075
23076 self.write_keyword("JSON_OBJECT");
23077 self.write("(");
23078 if f.star {
23079 self.write("*");
23080 } else {
23081 let use_comma_syntax = self.config.json_key_value_pair_sep == ","
23085 || matches!(
23086 self.config.dialect,
23087 Some(DialectType::BigQuery)
23088 | Some(DialectType::MySQL)
23089 | Some(DialectType::SQLite)
23090 );
23091
23092 for (i, (key, value)) in f.pairs.iter().enumerate() {
23093 if i > 0 {
23094 self.write(", ");
23095 }
23096 self.generate_expression(key)?;
23097 if use_comma_syntax {
23098 self.write(", ");
23099 } else {
23100 self.write(": ");
23101 }
23102 self.generate_expression(value)?;
23103 }
23104 }
23105 if let Some(null_handling) = f.null_handling {
23106 self.write_space();
23107 match null_handling {
23108 JsonNullHandling::NullOnNull => self.write_keyword("NULL ON NULL"),
23109 JsonNullHandling::AbsentOnNull => self.write_keyword("ABSENT ON NULL"),
23110 }
23111 }
23112 if f.with_unique_keys {
23113 self.write_space();
23114 self.write_keyword("WITH UNIQUE KEYS");
23115 }
23116 if let Some(ref ret_type) = f.returning_type {
23117 self.write_space();
23118 self.write_keyword("RETURNING");
23119 self.write_space();
23120 self.generate_data_type(ret_type)?;
23121 if f.format_json {
23122 self.write_space();
23123 self.write_keyword("FORMAT JSON");
23124 }
23125 if let Some(ref enc) = f.encoding {
23126 self.write_space();
23127 self.write_keyword("ENCODING");
23128 self.write_space();
23129 self.write(enc);
23130 }
23131 }
23132 self.write(")");
23133 Ok(())
23134 }
23135
23136 fn generate_json_modify(&mut self, name: &str, f: &JsonModifyFunc) -> Result<()> {
23137 self.write_keyword(name);
23138 self.write("(");
23139 self.generate_expression(&f.this)?;
23140 for (path, value) in &f.path_values {
23141 self.write(", ");
23142 self.generate_expression(path)?;
23143 self.write(", ");
23144 self.generate_expression(value)?;
23145 }
23146 self.write(")");
23147 Ok(())
23148 }
23149
23150 fn generate_json_array_agg(&mut self, f: &JsonArrayAggFunc) -> Result<()> {
23151 self.write_keyword("JSON_ARRAYAGG");
23152 self.write("(");
23153 self.generate_expression(&f.this)?;
23154 if let Some(ref order_by) = f.order_by {
23155 self.write_space();
23156 self.write_keyword("ORDER BY");
23157 self.write_space();
23158 for (i, ord) in order_by.iter().enumerate() {
23159 if i > 0 {
23160 self.write(", ");
23161 }
23162 self.generate_ordered(ord)?;
23163 }
23164 }
23165 if let Some(null_handling) = f.null_handling {
23166 self.write_space();
23167 match null_handling {
23168 JsonNullHandling::NullOnNull => self.write_keyword("NULL ON NULL"),
23169 JsonNullHandling::AbsentOnNull => self.write_keyword("ABSENT ON NULL"),
23170 }
23171 }
23172 self.write(")");
23173 if let Some(ref filter) = f.filter {
23174 self.write_space();
23175 self.write_keyword("FILTER");
23176 self.write("(");
23177 self.write_keyword("WHERE");
23178 self.write_space();
23179 self.generate_expression(filter)?;
23180 self.write(")");
23181 }
23182 Ok(())
23183 }
23184
23185 fn generate_json_object_agg(&mut self, f: &JsonObjectAggFunc) -> Result<()> {
23186 self.write_keyword("JSON_OBJECTAGG");
23187 self.write("(");
23188 self.generate_expression(&f.key)?;
23189 self.write(": ");
23190 self.generate_expression(&f.value)?;
23191 if let Some(null_handling) = f.null_handling {
23192 self.write_space();
23193 match null_handling {
23194 JsonNullHandling::NullOnNull => self.write_keyword("NULL ON NULL"),
23195 JsonNullHandling::AbsentOnNull => self.write_keyword("ABSENT ON NULL"),
23196 }
23197 }
23198 self.write(")");
23199 if let Some(ref filter) = f.filter {
23200 self.write_space();
23201 self.write_keyword("FILTER");
23202 self.write("(");
23203 self.write_keyword("WHERE");
23204 self.write_space();
23205 self.generate_expression(filter)?;
23206 self.write(")");
23207 }
23208 Ok(())
23209 }
23210
23211 fn generate_convert(&mut self, f: &ConvertFunc) -> Result<()> {
23214 use crate::dialects::DialectType;
23215
23216 if self.config.dialect == Some(DialectType::Redshift) {
23218 self.write_keyword("CAST");
23219 self.write("(");
23220 self.generate_expression(&f.this)?;
23221 self.write_space();
23222 self.write_keyword("AS");
23223 self.write_space();
23224 self.generate_data_type(&f.to)?;
23225 self.write(")");
23226 return Ok(());
23227 }
23228
23229 self.write_keyword("CONVERT");
23230 self.write("(");
23231 self.generate_data_type(&f.to)?;
23232 self.write(", ");
23233 self.generate_expression(&f.this)?;
23234 if let Some(ref style) = f.style {
23235 self.write(", ");
23236 self.generate_expression(style)?;
23237 }
23238 self.write(")");
23239 Ok(())
23240 }
23241
23242 fn generate_lambda(&mut self, f: &LambdaExpr) -> Result<()> {
23245 if f.colon {
23246 self.write_keyword("LAMBDA");
23248 self.write_space();
23249 for (i, param) in f.parameters.iter().enumerate() {
23250 if i > 0 {
23251 self.write(", ");
23252 }
23253 self.generate_identifier(param)?;
23254 }
23255 self.write(" : ");
23256 } else {
23257 if f.parameters.len() == 1 {
23259 self.generate_identifier(&f.parameters[0])?;
23260 } else {
23261 self.write("(");
23262 for (i, param) in f.parameters.iter().enumerate() {
23263 if i > 0 {
23264 self.write(", ");
23265 }
23266 self.generate_identifier(param)?;
23267 }
23268 self.write(")");
23269 }
23270 self.write(" -> ");
23271 }
23272 if matches!(self.config.dialect, Some(DialectType::ClickHouse)) {
23273 if let Expression::Lambda(inner) = &f.body {
23274 self.generate_lambda_with_parenthesized_single_param(inner)?;
23275 return Ok(());
23276 }
23277 }
23278
23279 self.generate_expression(&f.body)
23280 }
23281
23282 fn generate_lambda_with_parenthesized_single_param(&mut self, f: &LambdaExpr) -> Result<()> {
23283 if f.colon {
23284 return self.generate_lambda(f);
23285 }
23286
23287 self.write("(");
23288 for (i, param) in f.parameters.iter().enumerate() {
23289 if i > 0 {
23290 self.write(", ");
23291 }
23292 self.generate_identifier(param)?;
23293 }
23294 self.write(") -> ");
23295 self.generate_expression(&f.body)
23296 }
23297
23298 fn generate_named_argument(&mut self, f: &NamedArgument) -> Result<()> {
23299 self.generate_identifier(&f.name)?;
23300 match f.separator {
23301 NamedArgSeparator::DArrow => self.write(" => "),
23302 NamedArgSeparator::ColonEq => self.write(" := "),
23303 NamedArgSeparator::Eq => self.write(" = "),
23304 }
23305 self.generate_expression(&f.value)
23306 }
23307
23308 fn generate_table_argument(&mut self, f: &TableArgument) -> Result<()> {
23309 self.write_keyword(&f.prefix);
23310 self.write(" ");
23311 self.generate_expression(&f.this)
23312 }
23313
23314 fn generate_parameter(&mut self, f: &Parameter) -> Result<()> {
23315 match f.style {
23316 ParameterStyle::Question => self.write("?"),
23317 ParameterStyle::Dollar => {
23318 if let Some(idx) = f.index {
23319 if matches!(
23320 self.config.dialect,
23321 Some(DialectType::TSQL) | Some(DialectType::Fabric)
23322 ) {
23323 self.write("@P");
23324 self.write(&idx.to_string());
23325 } else {
23326 self.write("$");
23327 self.write(&idx.to_string());
23328 }
23329 } else {
23330 self.write("$");
23331 if let Some(ref name) = f.name {
23332 self.write(name);
23334 }
23335 }
23336 }
23337 ParameterStyle::DollarBrace => {
23338 self.write("${");
23340 if let Some(ref name) = f.name {
23341 self.write(name);
23342 }
23343 if let Some(ref expr) = f.expression {
23344 self.write(":");
23345 self.write(expr);
23346 }
23347 self.write("}");
23348 }
23349 ParameterStyle::Colon => {
23350 self.write(":");
23351 if let Some(idx) = f.index {
23352 self.write(&idx.to_string());
23353 } else if let Some(ref name) = f.name {
23354 self.write(name);
23355 }
23356 }
23357 ParameterStyle::At => {
23358 self.write("@");
23359 if let Some(ref name) = f.name {
23360 if f.string_quoted {
23361 self.write("'");
23362 self.write(name);
23363 self.write("'");
23364 } else if f.quoted {
23365 self.write("\"");
23366 self.write(name);
23367 self.write("\"");
23368 } else {
23369 self.write(name);
23370 }
23371 }
23372 }
23373 ParameterStyle::DoubleAt => {
23374 self.write("@@");
23375 if let Some(ref name) = f.name {
23376 self.write(name);
23377 }
23378 }
23379 ParameterStyle::DoubleDollar => {
23380 self.write("$$");
23381 if let Some(ref name) = f.name {
23382 self.write(name);
23383 }
23384 }
23385 ParameterStyle::Percent => {
23386 if let Some(ref name) = f.name {
23387 self.write("%(");
23389 self.write(name);
23390 self.write(")s");
23391 } else {
23392 self.write("%s");
23394 }
23395 }
23396 ParameterStyle::Brace => {
23397 self.write("{");
23400 if let Some(ref name) = f.name {
23401 self.write(name);
23402 }
23403 if let Some(ref expr) = f.expression {
23404 self.write(": ");
23405 self.write(expr);
23406 }
23407 self.write("}");
23408 }
23409 }
23410 Ok(())
23411 }
23412
23413 fn generate_placeholder(&mut self, f: &Placeholder) -> Result<()> {
23414 self.write("?");
23415 if let Some(idx) = f.index {
23416 self.write(&idx.to_string());
23417 }
23418 Ok(())
23419 }
23420
23421 fn generate_sql_comment(&mut self, f: &SqlComment) -> Result<()> {
23422 if f.is_block {
23423 self.write("/*");
23424 self.write(&f.text);
23425 self.write("*/");
23426 } else {
23427 self.write("--");
23428 self.write(&f.text);
23429 }
23430 Ok(())
23431 }
23432
23433 fn generate_similar_to(&mut self, f: &SimilarToExpr) -> Result<()> {
23436 self.generate_expression(&f.this)?;
23437 if f.not {
23438 self.write_space();
23439 self.write_keyword("NOT");
23440 }
23441 self.write_space();
23442 self.write_keyword("SIMILAR TO");
23443 self.write_space();
23444 self.generate_expression(&f.pattern)?;
23445 if let Some(ref escape) = f.escape {
23446 self.write_space();
23447 self.write_keyword("ESCAPE");
23448 self.write_space();
23449 self.generate_expression(escape)?;
23450 }
23451 Ok(())
23452 }
23453
23454 fn generate_quantified(&mut self, name: &str, f: &QuantifiedExpr) -> Result<()> {
23455 self.generate_expression(&f.this)?;
23456 self.write_space();
23457 if let Some(op) = &f.op {
23459 match op {
23460 QuantifiedOp::Eq => self.write("="),
23461 QuantifiedOp::Neq => self.write("<>"),
23462 QuantifiedOp::Lt => self.write("<"),
23463 QuantifiedOp::Lte => self.write("<="),
23464 QuantifiedOp::Gt => self.write(">"),
23465 QuantifiedOp::Gte => self.write(">="),
23466 }
23467 self.write_space();
23468 }
23469 self.write_keyword(name);
23470
23471 if matches!(&f.subquery, Expression::Subquery(_)) {
23473 self.write_space();
23474 self.generate_expression(&f.subquery)?;
23475 } else {
23476 let is_statement = matches!(
23477 &f.subquery,
23478 Expression::Select(_)
23479 | Expression::Union(_)
23480 | Expression::Intersect(_)
23481 | Expression::Except(_)
23482 );
23483 if is_statement
23484 && !self.config.quantified_no_paren_space
23485 && matches!(self.config.dialect, Some(DialectType::ClickHouse))
23486 {
23487 self.write_space();
23488 }
23489 self.write("(");
23490
23491 if self.config.pretty && is_statement {
23492 self.write_newline();
23493 self.indent_level += 1;
23494 self.write_indent();
23495 }
23496 self.generate_expression(&f.subquery)?;
23497 if self.config.pretty && is_statement {
23498 self.write_newline();
23499 self.indent_level -= 1;
23500 self.write_indent();
23501 }
23502 self.write(")");
23503 }
23504 Ok(())
23505 }
23506
23507 fn generate_overlaps(&mut self, f: &OverlapsExpr) -> Result<()> {
23508 if let (Some(this), Some(expr)) = (&f.this, &f.expression) {
23510 self.generate_expression(this)?;
23511 self.write_space();
23512 self.write_keyword("OVERLAPS");
23513 self.write_space();
23514 self.generate_expression(expr)?;
23515 } else if let (Some(ls), Some(le), Some(rs), Some(re)) =
23516 (&f.left_start, &f.left_end, &f.right_start, &f.right_end)
23517 {
23518 self.write("(");
23520 self.generate_expression(ls)?;
23521 self.write(", ");
23522 self.generate_expression(le)?;
23523 self.write(")");
23524 self.write_space();
23525 self.write_keyword("OVERLAPS");
23526 self.write_space();
23527 self.write("(");
23528 self.generate_expression(rs)?;
23529 self.write(", ");
23530 self.generate_expression(re)?;
23531 self.write(")");
23532 }
23533 Ok(())
23534 }
23535
23536 fn generate_try_cast(&mut self, cast: &Cast) -> Result<()> {
23539 use crate::dialects::DialectType;
23540
23541 if matches!(self.config.dialect, Some(DialectType::SingleStore)) {
23543 self.generate_expression(&cast.this)?;
23544 self.write(" !:> ");
23545 self.generate_data_type(&cast.to)?;
23546 return Ok(());
23547 }
23548
23549 if matches!(self.config.dialect, Some(DialectType::Teradata)) {
23551 self.write_keyword("TRYCAST");
23552 self.write("(");
23553 self.generate_expression(&cast.this)?;
23554 self.write_space();
23555 self.write_keyword("AS");
23556 self.write_space();
23557 self.generate_data_type(&cast.to)?;
23558 self.write(")");
23559 return Ok(());
23560 }
23561
23562 let keyword = if matches!(
23564 self.config.dialect,
23565 Some(DialectType::Hive)
23566 | Some(DialectType::MySQL)
23567 | Some(DialectType::SQLite)
23568 | Some(DialectType::Oracle)
23569 | Some(DialectType::ClickHouse)
23570 | Some(DialectType::Redshift)
23571 | Some(DialectType::PostgreSQL)
23572 | Some(DialectType::StarRocks)
23573 | Some(DialectType::Doris)
23574 ) {
23575 "CAST"
23576 } else {
23577 "TRY_CAST"
23578 };
23579
23580 self.write_keyword(keyword);
23581 self.write("(");
23582 self.generate_expression(&cast.this)?;
23583 self.write_space();
23584 self.write_keyword("AS");
23585 self.write_space();
23586 self.generate_data_type(&cast.to)?;
23587
23588 if let Some(format) = &cast.format {
23590 self.write_space();
23591 self.write_keyword("FORMAT");
23592 self.write_space();
23593 self.generate_expression(format)?;
23594 }
23595
23596 self.write(")");
23597 Ok(())
23598 }
23599
23600 fn generate_safe_cast(&mut self, cast: &Cast) -> Result<()> {
23601 self.write_keyword("SAFE_CAST");
23602 self.write("(");
23603 self.generate_expression(&cast.this)?;
23604 self.write_space();
23605 self.write_keyword("AS");
23606 self.write_space();
23607 self.generate_data_type(&cast.to)?;
23608
23609 if let Some(format) = &cast.format {
23611 self.write_space();
23612 self.write_keyword("FORMAT");
23613 self.write_space();
23614 self.generate_expression(format)?;
23615 }
23616
23617 self.write(")");
23618 Ok(())
23619 }
23620
23621 fn generate_subscript(&mut self, s: &Subscript) -> Result<()> {
23624 let needs_parens = matches!(&s.this, Expression::JsonExtract(ref f) if f.arrow_syntax);
23628 if needs_parens {
23629 self.write("(");
23630 }
23631 self.generate_expression(&s.this)?;
23632 if needs_parens {
23633 self.write(")");
23634 }
23635 self.write("[");
23636 self.generate_expression(&s.index)?;
23637 self.write("]");
23638 Ok(())
23639 }
23640
23641 fn generate_dot_access(&mut self, d: &DotAccess) -> Result<()> {
23642 self.generate_expression(&d.this)?;
23643 let use_colon = matches!(self.config.dialect, Some(DialectType::Snowflake))
23646 && matches!(
23647 &d.this,
23648 Expression::Cast(_) | Expression::SafeCast(_) | Expression::TryCast(_)
23649 );
23650 if use_colon {
23651 self.write(":");
23652 } else {
23653 self.write(".");
23654 }
23655 self.generate_identifier(&d.field)
23656 }
23657
23658 fn generate_method_call(&mut self, m: &MethodCall) -> Result<()> {
23659 self.generate_expression(&m.this)?;
23660 self.write(".");
23661 if m.method.quoted {
23664 let q = self.config.identifier_quote;
23665 self.write(&format!("{}{}{}", q, m.method.name, q));
23666 } else {
23667 self.write(&m.method.name);
23668 }
23669 self.write("(");
23670 for (i, arg) in m.args.iter().enumerate() {
23671 if i > 0 {
23672 self.write(", ");
23673 }
23674 self.generate_expression(arg)?;
23675 }
23676 self.write(")");
23677 Ok(())
23678 }
23679
23680 fn generate_array_slice(&mut self, s: &ArraySlice) -> Result<()> {
23681 let needs_parens = matches!(
23684 &s.this,
23685 Expression::JsonExtract(f) if f.arrow_syntax
23686 ) || matches!(
23687 &s.this,
23688 Expression::JsonExtractScalar(f) if f.arrow_syntax
23689 );
23690
23691 if needs_parens {
23692 self.write("(");
23693 }
23694 self.generate_expression(&s.this)?;
23695 if needs_parens {
23696 self.write(")");
23697 }
23698 self.write("[");
23699 if let Some(start) = &s.start {
23700 self.generate_expression(start)?;
23701 }
23702 self.write(":");
23703 if let Some(end) = &s.end {
23704 self.generate_expression(end)?;
23705 }
23706 self.write("]");
23707 Ok(())
23708 }
23709
23710 fn generate_binary_op(&mut self, op: &BinaryOp, operator: &str) -> Result<()> {
23711 match &op.left {
23715 Expression::Column(col) => {
23716 if let Some(table) = &col.table {
23719 self.generate_identifier(table)?;
23720 self.write(".");
23721 }
23722 self.generate_identifier(&col.name)?;
23723 if col.join_mark && self.config.supports_column_join_marks {
23725 self.write(" (+)");
23726 }
23727 if op.left_comments.is_empty() {
23729 for comment in &col.trailing_comments {
23730 self.write_space();
23731 self.write_formatted_comment(comment);
23732 }
23733 }
23734 }
23735 Expression::Add(inner_op)
23736 | Expression::Sub(inner_op)
23737 | Expression::Mul(inner_op)
23738 | Expression::Div(inner_op)
23739 | Expression::Concat(inner_op) => {
23740 self.generate_binary_op_no_trailing(inner_op, match &op.left {
23742 Expression::Add(_) => "+",
23743 Expression::Sub(_) => "-",
23744 Expression::Mul(_) => "*",
23745 Expression::Div(_) => "/",
23746 Expression::Concat(_) => "||",
23747 _ => unreachable!("op.left variant already matched by outer arm as Add/Sub/Mul/Div/Concat"),
23748 })?;
23749 }
23750 _ => {
23751 self.generate_expression(&op.left)?;
23752 }
23753 }
23754 for comment in &op.left_comments {
23756 self.write_space();
23757 self.write_formatted_comment(comment);
23758 }
23759 if self.config.pretty
23760 && matches!(self.config.dialect, Some(DialectType::Snowflake))
23761 && (operator == "AND" || operator == "OR")
23762 {
23763 self.write_newline();
23764 self.write_indent();
23765 self.write_keyword(operator);
23766 } else {
23767 self.write_space();
23768 if operator.chars().all(|c| c.is_alphabetic()) {
23769 self.write_keyword(operator);
23770 } else {
23771 self.write(operator);
23772 }
23773 }
23774 for comment in &op.operator_comments {
23776 self.write_space();
23777 self.write_formatted_comment(comment);
23778 }
23779 self.write_space();
23780 self.generate_expression(&op.right)?;
23781 for comment in &op.trailing_comments {
23783 self.write_space();
23784 self.write_formatted_comment(comment);
23785 }
23786 Ok(())
23787 }
23788
23789 fn generate_connector_op(&mut self, op: &BinaryOp, connector: ConnectorOperator) -> Result<()> {
23790 let keyword = connector.keyword();
23791 let Some(terms) = self.flatten_connector_terms(op, connector) else {
23792 return self.generate_binary_op(op, keyword);
23793 };
23794
23795 let wrap_clickhouse_or_term = |generator: &mut Self, term: &Expression| -> Result<()> {
23796 let should_wrap = matches!(connector, ConnectorOperator::Or)
23797 && matches!(generator.config.dialect, Some(DialectType::ClickHouse))
23798 && matches!(
23799 generator.config.source_dialect,
23800 Some(DialectType::ClickHouse)
23801 )
23802 && matches!(term, Expression::And(_));
23803 if should_wrap {
23804 generator.write("(");
23805 generator.generate_expression(term)?;
23806 generator.write(")");
23807 } else {
23808 generator.generate_expression(term)?;
23809 }
23810 Ok(())
23811 };
23812
23813 wrap_clickhouse_or_term(self, terms[0])?;
23814 for term in terms.iter().skip(1) {
23815 if self.config.pretty && matches!(self.config.dialect, Some(DialectType::Snowflake)) {
23816 self.write_newline();
23817 self.write_indent();
23818 self.write_keyword(keyword);
23819 } else {
23820 self.write_space();
23821 self.write_keyword(keyword);
23822 }
23823 self.write_space();
23824 wrap_clickhouse_or_term(self, term)?;
23825 }
23826
23827 Ok(())
23828 }
23829
23830 fn flatten_connector_terms<'a>(
23831 &self,
23832 root: &'a BinaryOp,
23833 connector: ConnectorOperator,
23834 ) -> Option<Vec<&'a Expression>> {
23835 if !root.left_comments.is_empty()
23836 || !root.operator_comments.is_empty()
23837 || !root.trailing_comments.is_empty()
23838 {
23839 return None;
23840 }
23841
23842 let mut terms = Vec::new();
23843 let mut stack: Vec<&Expression> = vec![&root.right, &root.left];
23844
23845 while let Some(expr) = stack.pop() {
23846 match (connector, expr) {
23847 (ConnectorOperator::And, Expression::And(inner))
23848 if inner.left_comments.is_empty()
23849 && inner.operator_comments.is_empty()
23850 && inner.trailing_comments.is_empty() =>
23851 {
23852 stack.push(&inner.right);
23853 stack.push(&inner.left);
23854 }
23855 (ConnectorOperator::Or, Expression::Or(inner))
23856 if inner.left_comments.is_empty()
23857 && inner.operator_comments.is_empty()
23858 && inner.trailing_comments.is_empty() =>
23859 {
23860 stack.push(&inner.right);
23861 stack.push(&inner.left);
23862 }
23863 _ => terms.push(expr),
23864 }
23865 }
23866
23867 if terms.len() > 1 {
23868 Some(terms)
23869 } else {
23870 None
23871 }
23872 }
23873
23874 fn missing_closing_parens_outside_quotes(sql: &str) -> usize {
23875 let mut depth = 0usize;
23876 let mut quote: Option<char> = None;
23877 let mut chars = sql.chars().peekable();
23878
23879 while let Some(ch) = chars.next() {
23880 if let Some(quote_char) = quote {
23881 if ch == '\\' {
23882 chars.next();
23883 } else if ch == quote_char {
23884 if quote_char == '\'' && chars.peek() == Some(&'\'') {
23885 chars.next();
23886 } else {
23887 quote = None;
23888 }
23889 }
23890 continue;
23891 }
23892
23893 match ch {
23894 '\'' | '"' | '`' => quote = Some(ch),
23895 '(' => depth += 1,
23896 ')' => depth = depth.saturating_sub(1),
23897 _ => {}
23898 }
23899 }
23900
23901 depth
23902 }
23903
23904 fn generate_like_op(&mut self, op: &LikeOp, operator: &str) -> Result<()> {
23906 self.generate_like_op_inner(op, operator, false)
23907 }
23908
23909 fn generate_like_op_negated(&mut self, op: &LikeOp, operator: &str) -> Result<()> {
23910 self.generate_like_op_inner(op, operator, true)
23911 }
23912
23913 fn generate_like_op_inner(&mut self, op: &LikeOp, operator: &str, negated: bool) -> Result<()> {
23914 if negated
23915 && matches!(
23916 self.config.dialect,
23917 Some(DialectType::ClickHouse)
23918 | Some(DialectType::DataFusion)
23919 | Some(DialectType::TSQL)
23920 | Some(DialectType::Fabric)
23921 )
23922 {
23923 self.write_keyword("NOT");
23924 self.write_space();
23925 return self.generate_like_op_inner(op, operator, false);
23926 }
23927
23928 if matches!(self.config.dialect, Some(DialectType::ClickHouse)) {
23929 if let Expression::Star(star) = &op.left {
23930 if star
23931 .except
23932 .as_ref()
23933 .is_some_and(|except| !except.is_empty())
23934 {
23935 if let Some(table) = &star.table {
23936 self.generate_identifier(table)?;
23937 self.write(".");
23938 }
23939 self.write("*");
23940 self.write_space();
23941 self.write_keyword(operator);
23942 if let Some(quantifier) = &op.quantifier {
23943 self.write_space();
23944 self.write_keyword(quantifier);
23945 self.write_space();
23946 } else {
23947 self.write_space();
23948 }
23949 self.generate_expression(&op.right)?;
23950 if let Some(escape) = &op.escape {
23951 self.write_space();
23952 self.write_keyword("ESCAPE");
23953 self.write_space();
23954 self.generate_expression(escape)?;
23955 }
23956 if let Some(except) = &star.except {
23957 self.write_space();
23958 self.write_keyword("EXCEPT");
23959 self.write(" (");
23960 for (i, col) in except.iter().enumerate() {
23961 if i > 0 {
23962 self.write(", ");
23963 }
23964 self.generate_identifier(col)?;
23965 }
23966 self.write(")");
23967 }
23968 return Ok(());
23969 }
23970 }
23971 }
23972
23973 self.generate_expression(&op.left)?;
23974 self.write_space();
23975 if negated {
23976 self.write_keyword("NOT");
23977 self.write_space();
23978 }
23979 if operator == "ILIKE" && matches!(self.config.dialect, Some(DialectType::Drill)) {
23981 self.write("`ILIKE`");
23982 } else {
23983 self.write_keyword(operator);
23984 }
23985 if let Some(quantifier) = &op.quantifier {
23986 self.write_space();
23987 self.write_keyword(quantifier);
23988 let is_any =
23993 quantifier.eq_ignore_ascii_case("ANY") || quantifier.eq_ignore_ascii_case("SOME");
23994 if !(is_any && matches!(&op.right, Expression::Paren(_))) {
23995 self.write_space();
23996 }
23997 } else {
23998 self.write_space();
23999 }
24000 self.generate_expression(&op.right)?;
24001 if let Some(escape) = &op.escape {
24002 self.write_space();
24003 self.write_keyword("ESCAPE");
24004 self.write_space();
24005 self.generate_expression(escape)?;
24006 }
24007 Ok(())
24008 }
24009
24010 fn generate_null_safe_eq(&mut self, op: &BinaryOp) -> Result<()> {
24013 use crate::dialects::DialectType;
24014 self.generate_expression(&op.left)?;
24015 self.write_space();
24016 if matches!(self.config.dialect, Some(DialectType::MySQL)) {
24017 self.write("<=>");
24018 } else {
24019 self.write_keyword("IS NOT DISTINCT FROM");
24020 }
24021 self.write_space();
24022 self.generate_expression(&op.right)?;
24023 Ok(())
24024 }
24025
24026 fn generate_null_safe_neq(&mut self, op: &BinaryOp) -> Result<()> {
24028 self.generate_expression(&op.left)?;
24029 self.write_space();
24030 self.write_keyword("IS DISTINCT FROM");
24031 self.write_space();
24032 self.generate_expression(&op.right)?;
24033 Ok(())
24034 }
24035
24036 fn generate_binary_op_no_trailing(&mut self, op: &BinaryOp, operator: &str) -> Result<()> {
24038 match &op.left {
24040 Expression::Column(col) => {
24041 if let Some(table) = &col.table {
24042 self.generate_identifier(table)?;
24043 self.write(".");
24044 }
24045 self.generate_identifier(&col.name)?;
24046 if col.join_mark && self.config.supports_column_join_marks {
24048 self.write(" (+)");
24049 }
24050 }
24051 Expression::Add(inner_op)
24052 | Expression::Sub(inner_op)
24053 | Expression::Mul(inner_op)
24054 | Expression::Div(inner_op)
24055 | Expression::Concat(inner_op) => {
24056 self.generate_binary_op_no_trailing(inner_op, match &op.left {
24057 Expression::Add(_) => "+",
24058 Expression::Sub(_) => "-",
24059 Expression::Mul(_) => "*",
24060 Expression::Div(_) => "/",
24061 Expression::Concat(_) => "||",
24062 _ => unreachable!("op.left variant already matched by outer arm as Add/Sub/Mul/Div/Concat"),
24063 })?;
24064 }
24065 _ => {
24066 self.generate_expression(&op.left)?;
24067 }
24068 }
24069 for comment in &op.left_comments {
24071 self.write_space();
24072 self.write_formatted_comment(comment);
24073 }
24074 self.write_space();
24075 if operator.chars().all(|c| c.is_alphabetic()) {
24076 self.write_keyword(operator);
24077 } else {
24078 self.write(operator);
24079 }
24080 for comment in &op.operator_comments {
24082 self.write_space();
24083 self.write_formatted_comment(comment);
24084 }
24085 self.write_space();
24086 match &op.right {
24089 Expression::Column(col) => {
24090 if let Some(table) = &col.table {
24091 self.generate_identifier(table)?;
24092 self.write(".");
24093 }
24094 self.generate_identifier(&col.name)?;
24095 if col.join_mark && self.config.supports_column_join_marks {
24097 self.write(" (+)");
24098 }
24099 }
24100 _ => {
24101 self.generate_expression(&op.right)?;
24102 }
24103 }
24104 Ok(())
24106 }
24107
24108 fn generate_unary_op(&mut self, op: &UnaryOp, operator: &str) -> Result<()> {
24109 if operator.chars().all(|c| c.is_alphabetic()) {
24110 self.write_keyword(operator);
24111 self.write_space();
24112 } else {
24113 self.write(operator);
24114 if matches!(&op.this, Expression::Neg(_) | Expression::BitwiseNot(_)) {
24116 self.write_space();
24117 }
24118 }
24119 self.generate_expression(&op.this)
24120 }
24121
24122 fn generate_in(&mut self, in_expr: &In) -> Result<()> {
24123 let is_generic =
24127 self.config.dialect.is_none() || self.config.dialect == Some(DialectType::Generic);
24128 let use_prefix_not =
24129 in_expr.not && is_generic && self.config.not_in_style == NotInStyle::Prefix;
24130 if use_prefix_not {
24131 self.write_keyword("NOT");
24132 self.write_space();
24133 }
24134 self.generate_expression(&in_expr.this)?;
24135 if in_expr.global {
24136 self.write_space();
24137 self.write_keyword("GLOBAL");
24138 }
24139 if in_expr.not && !use_prefix_not {
24140 self.write_space();
24141 self.write_keyword("NOT");
24142 }
24143 self.write_space();
24144 self.write_keyword("IN");
24145
24146 if let Some(unnest_expr) = &in_expr.unnest {
24148 self.write_space();
24149 self.write_keyword("UNNEST");
24150 self.write("(");
24151 self.generate_expression(unnest_expr)?;
24152 self.write(")");
24153 return Ok(());
24154 }
24155
24156 if let Some(query) = &in_expr.query {
24157 let is_bare = in_expr.expressions.is_empty()
24160 && !matches!(
24161 query,
24162 Expression::Select(_)
24163 | Expression::Union(_)
24164 | Expression::Intersect(_)
24165 | Expression::Except(_)
24166 | Expression::Subquery(_)
24167 );
24168 if is_bare {
24169 self.write_space();
24171 self.generate_expression(query)?;
24172 } else {
24173 self.write(" (");
24175 let is_statement = matches!(
24176 query,
24177 Expression::Select(_)
24178 | Expression::Union(_)
24179 | Expression::Intersect(_)
24180 | Expression::Except(_)
24181 | Expression::Subquery(_)
24182 );
24183 if self.config.pretty && is_statement {
24184 self.write_newline();
24185 self.indent_level += 1;
24186 self.write_indent();
24187 }
24188 self.generate_expression(query)?;
24189 if self.config.pretty && is_statement {
24190 self.write_newline();
24191 self.indent_level -= 1;
24192 self.write_indent();
24193 }
24194 self.write(")");
24195 }
24196 } else {
24197 let is_duckdb = matches!(
24201 self.config.dialect,
24202 Some(crate::dialects::DialectType::DuckDB)
24203 );
24204 let is_clickhouse = matches!(
24205 self.config.dialect,
24206 Some(crate::dialects::DialectType::ClickHouse)
24207 );
24208 let single_expr = in_expr.expressions.len() == 1;
24209 if is_clickhouse && single_expr {
24210 if let Expression::Array(arr) = &in_expr.expressions[0] {
24211 self.write(" (");
24213 for (i, expr) in arr.expressions.iter().enumerate() {
24214 if i > 0 {
24215 self.write(", ");
24216 }
24217 self.generate_expression(expr)?;
24218 }
24219 self.write(")");
24220 } else if in_expr.is_field {
24221 self.write_space();
24222 self.generate_expression(&in_expr.expressions[0])?;
24223 } else {
24224 self.write(" (");
24225 self.generate_expression(&in_expr.expressions[0])?;
24226 self.write(")");
24227 }
24228 } else {
24229 let is_bare_ref = single_expr
24230 && matches!(
24231 &in_expr.expressions[0],
24232 Expression::Column(_) | Expression::Identifier(_) | Expression::Dot(_)
24233 );
24234 if (is_duckdb && is_bare_ref) || (in_expr.is_field && single_expr) {
24235 self.write_space();
24238 self.generate_expression(&in_expr.expressions[0])?;
24239 } else {
24240 self.write(" (");
24242 for (i, expr) in in_expr.expressions.iter().enumerate() {
24243 if i > 0 {
24244 self.write(", ");
24245 }
24246 self.generate_expression(expr)?;
24247 }
24248 self.write(")");
24249 }
24250 }
24251 }
24252
24253 Ok(())
24254 }
24255
24256 fn generate_between(&mut self, between: &Between) -> Result<()> {
24257 let use_prefix_not = between.not
24259 && (self.config.dialect.is_none() || self.config.dialect == Some(DialectType::Generic));
24260 if use_prefix_not {
24261 self.write_keyword("NOT");
24262 self.write_space();
24263 }
24264 self.generate_expression(&between.this)?;
24265 if between.not && !use_prefix_not {
24266 self.write_space();
24267 self.write_keyword("NOT");
24268 }
24269 self.write_space();
24270 self.write_keyword("BETWEEN");
24271 if let Some(sym) = between.symmetric {
24273 if sym {
24274 self.write(" SYMMETRIC");
24275 } else {
24276 self.write(" ASYMMETRIC");
24277 }
24278 }
24279 self.write_space();
24280 self.generate_expression(&between.low)?;
24281 self.write_space();
24282 self.write_keyword("AND");
24283 self.write_space();
24284 self.generate_expression(&between.high)
24285 }
24286
24287 fn generate_is_null(&mut self, is_null: &IsNull) -> Result<()> {
24288 let use_prefix_not = is_null.not
24290 && (self.config.dialect.is_none()
24291 || self.config.dialect == Some(DialectType::Generic)
24292 || (is_null.postfix_form && self.config.dialect != Some(DialectType::PostgreSQL)));
24293 if use_prefix_not {
24294 self.write_keyword("NOT");
24296 self.write_space();
24297 self.generate_expression(&is_null.this)?;
24298 self.write_space();
24299 self.write_keyword("IS");
24300 self.write_space();
24301 self.write_keyword("NULL");
24302 } else {
24303 self.generate_expression(&is_null.this)?;
24304 self.write_space();
24305 self.write_keyword("IS");
24306 if is_null.not {
24307 self.write_space();
24308 self.write_keyword("NOT");
24309 }
24310 self.write_space();
24311 self.write_keyword("NULL");
24312 }
24313 Ok(())
24314 }
24315
24316 fn generate_is_true(&mut self, is_true: &IsTrueFalse) -> Result<()> {
24317 self.generate_expression(&is_true.this)?;
24318 self.write_space();
24319 self.write_keyword("IS");
24320 if is_true.not {
24321 self.write_space();
24322 self.write_keyword("NOT");
24323 }
24324 self.write_space();
24325 self.write_keyword("TRUE");
24326 Ok(())
24327 }
24328
24329 fn generate_is_false(&mut self, is_false: &IsTrueFalse) -> Result<()> {
24330 self.generate_expression(&is_false.this)?;
24331 self.write_space();
24332 self.write_keyword("IS");
24333 if is_false.not {
24334 self.write_space();
24335 self.write_keyword("NOT");
24336 }
24337 self.write_space();
24338 self.write_keyword("FALSE");
24339 Ok(())
24340 }
24341
24342 fn generate_is_json(&mut self, is_json: &IsJson) -> Result<()> {
24343 self.generate_expression(&is_json.this)?;
24344 self.write_space();
24345 self.write_keyword("IS");
24346 if is_json.negated {
24347 self.write_space();
24348 self.write_keyword("NOT");
24349 }
24350 self.write_space();
24351 self.write_keyword("JSON");
24352
24353 if let Some(ref json_type) = is_json.json_type {
24355 self.write_space();
24356 self.write_keyword(json_type);
24357 }
24358
24359 match &is_json.unique_keys {
24361 Some(JsonUniqueKeys::With) => {
24362 self.write_space();
24363 self.write_keyword("WITH UNIQUE KEYS");
24364 }
24365 Some(JsonUniqueKeys::Without) => {
24366 self.write_space();
24367 self.write_keyword("WITHOUT UNIQUE KEYS");
24368 }
24369 Some(JsonUniqueKeys::Shorthand) => {
24370 self.write_space();
24371 self.write_keyword("UNIQUE KEYS");
24372 }
24373 None => {}
24374 }
24375
24376 Ok(())
24377 }
24378
24379 fn generate_is(&mut self, is_expr: &BinaryOp) -> Result<()> {
24380 self.generate_expression(&is_expr.left)?;
24381 self.write_space();
24382 self.write_keyword("IS");
24383 self.write_space();
24384 self.generate_expression(&is_expr.right)
24385 }
24386
24387 fn generate_exists(&mut self, exists: &Exists) -> Result<()> {
24388 if exists.not {
24389 self.write_keyword("NOT");
24390 self.write_space();
24391 }
24392 self.write_keyword("EXISTS");
24393 self.write("(");
24394 let is_statement = matches!(
24395 &exists.this,
24396 Expression::Select(_)
24397 | Expression::Union(_)
24398 | Expression::Intersect(_)
24399 | Expression::Except(_)
24400 );
24401 if self.config.pretty && is_statement {
24402 self.write_newline();
24403 self.indent_level += 1;
24404 self.write_indent();
24405 self.generate_expression(&exists.this)?;
24406 self.write_newline();
24407 self.indent_level -= 1;
24408 self.write_indent();
24409 self.write(")");
24410 } else {
24411 self.generate_expression(&exists.this)?;
24412 self.write(")");
24413 }
24414 Ok(())
24415 }
24416
24417 fn generate_member_of(&mut self, op: &BinaryOp) -> Result<()> {
24418 self.generate_expression(&op.left)?;
24419 self.write_space();
24420 self.write_keyword("MEMBER OF");
24421 self.write("(");
24422 self.generate_expression(&op.right)?;
24423 self.write(")");
24424 Ok(())
24425 }
24426
24427 fn generate_subquery(&mut self, subquery: &Subquery) -> Result<()> {
24428 if subquery.lateral {
24429 self.write_keyword("LATERAL");
24430 self.write_space();
24431 }
24432
24433 let skip_outer_parens = if let Expression::Paren(ref p) = &subquery.this {
24437 matches!(
24438 &p.this,
24439 Expression::Select(_)
24440 | Expression::Union(_)
24441 | Expression::Intersect(_)
24442 | Expression::Except(_)
24443 | Expression::Subquery(_)
24444 )
24445 } else {
24446 false
24447 };
24448
24449 let is_statement = matches!(
24451 &subquery.this,
24452 Expression::Select(_)
24453 | Expression::Union(_)
24454 | Expression::Intersect(_)
24455 | Expression::Except(_)
24456 | Expression::Merge(_)
24457 );
24458
24459 if !skip_outer_parens {
24460 self.write("(");
24461 if self.config.pretty && is_statement {
24462 self.write_newline();
24463 self.indent_level += 1;
24464 self.write_indent();
24465 }
24466 }
24467 self.generate_expression(&subquery.this)?;
24468
24469 if subquery.modifiers_inside {
24471 if let Some(order_by) = &subquery.order_by {
24473 self.write_space();
24474 self.write_keyword("ORDER BY");
24475 self.write_space();
24476 for (i, ord) in order_by.expressions.iter().enumerate() {
24477 if i > 0 {
24478 self.write(", ");
24479 }
24480 self.generate_ordered(ord)?;
24481 }
24482 }
24483
24484 if let Some(limit) = &subquery.limit {
24485 self.write_space();
24486 self.write_keyword("LIMIT");
24487 self.write_space();
24488 self.generate_expression(&limit.this)?;
24489 if limit.percent {
24490 self.write_space();
24491 self.write_keyword("PERCENT");
24492 }
24493 }
24494
24495 if let Some(offset) = &subquery.offset {
24496 self.write_space();
24497 self.write_keyword("OFFSET");
24498 self.write_space();
24499 self.generate_expression(&offset.this)?;
24500 }
24501 }
24502
24503 if !skip_outer_parens {
24504 if self.config.pretty && is_statement {
24505 self.write_newline();
24506 self.indent_level -= 1;
24507 self.write_indent();
24508 }
24509 self.write(")");
24510 }
24511
24512 if !subquery.modifiers_inside {
24514 if let Some(order_by) = &subquery.order_by {
24515 self.write_space();
24516 self.write_keyword("ORDER BY");
24517 self.write_space();
24518 for (i, ord) in order_by.expressions.iter().enumerate() {
24519 if i > 0 {
24520 self.write(", ");
24521 }
24522 self.generate_ordered(ord)?;
24523 }
24524 }
24525
24526 if let Some(limit) = &subquery.limit {
24527 self.write_space();
24528 self.write_keyword("LIMIT");
24529 self.write_space();
24530 self.generate_expression(&limit.this)?;
24531 if limit.percent {
24532 self.write_space();
24533 self.write_keyword("PERCENT");
24534 }
24535 }
24536
24537 if let Some(offset) = &subquery.offset {
24538 self.write_space();
24539 self.write_keyword("OFFSET");
24540 self.write_space();
24541 self.generate_expression(&offset.this)?;
24542 }
24543
24544 if let Some(distribute_by) = &subquery.distribute_by {
24546 self.write_space();
24547 self.write_keyword("DISTRIBUTE BY");
24548 self.write_space();
24549 for (i, expr) in distribute_by.expressions.iter().enumerate() {
24550 if i > 0 {
24551 self.write(", ");
24552 }
24553 self.generate_expression(expr)?;
24554 }
24555 }
24556
24557 if let Some(sort_by) = &subquery.sort_by {
24559 self.write_space();
24560 self.write_keyword("SORT BY");
24561 self.write_space();
24562 for (i, ord) in sort_by.expressions.iter().enumerate() {
24563 if i > 0 {
24564 self.write(", ");
24565 }
24566 self.generate_ordered(ord)?;
24567 }
24568 }
24569
24570 if let Some(cluster_by) = &subquery.cluster_by {
24572 self.write_space();
24573 self.write_keyword("CLUSTER BY");
24574 self.write_space();
24575 for (i, ord) in cluster_by.expressions.iter().enumerate() {
24576 if i > 0 {
24577 self.write(", ");
24578 }
24579 self.generate_ordered(ord)?;
24580 }
24581 }
24582 }
24583
24584 if let Some(alias) = &subquery.alias {
24585 self.write_space();
24586 let skip_as = matches!(self.config.dialect, Some(DialectType::Oracle))
24587 || (matches!(self.config.dialect, Some(DialectType::ClickHouse))
24588 && !subquery.alias_explicit_as);
24589 if !skip_as {
24590 if matches!(self.config.dialect, Some(DialectType::ClickHouse)) {
24591 self.write(subquery.alias_keyword.as_deref().unwrap_or("AS"));
24592 } else {
24593 self.write_keyword("AS");
24594 }
24595 self.write_space();
24596 }
24597 self.generate_identifier(alias)?;
24598 if !subquery.column_aliases.is_empty() {
24599 self.write("(");
24600 for (i, col) in subquery.column_aliases.iter().enumerate() {
24601 if i > 0 {
24602 self.write(", ");
24603 }
24604 self.generate_identifier(col)?;
24605 }
24606 self.write(")");
24607 }
24608 }
24609 for comment in &subquery.trailing_comments {
24611 self.write(" ");
24612 self.write_formatted_comment(comment);
24613 }
24614 Ok(())
24615 }
24616
24617 fn generate_pivot(&mut self, pivot: &Pivot) -> Result<()> {
24618 if let Some(ref with) = pivot.with {
24620 self.generate_with(with)?;
24621 self.write_space();
24622 }
24623
24624 let direction = if pivot.unpivot { "UNPIVOT" } else { "PIVOT" };
24625
24626 let is_redshift_unpivot = pivot.unpivot
24630 && pivot.expressions.is_empty()
24631 && pivot.fields.is_empty()
24632 && pivot.using.is_empty()
24633 && pivot.into.is_none()
24634 && !matches!(&pivot.this, Expression::Null(_));
24635
24636 if is_redshift_unpivot {
24637 self.write_keyword("UNPIVOT");
24639 self.write_space();
24640 self.generate_expression(&pivot.this)?;
24641 if let Some(alias) = &pivot.alias {
24643 self.write_space();
24644 self.write_keyword("AS");
24645 self.write_space();
24646 self.write(&alias.name);
24648 }
24649 return Ok(());
24650 }
24651
24652 let is_simplified = !pivot.using.is_empty()
24654 || pivot.into.is_some()
24655 || (pivot.fields.is_empty()
24656 && !pivot.expressions.is_empty()
24657 && !matches!(&pivot.this, Expression::Null(_)));
24658
24659 if is_simplified {
24660 self.write_keyword(direction);
24664 self.write_space();
24665 self.generate_expression(&pivot.this)?;
24666
24667 if !pivot.expressions.is_empty() {
24668 self.write_space();
24669 self.write_keyword("ON");
24670 self.write_space();
24671 for (i, expr) in pivot.expressions.iter().enumerate() {
24672 if i > 0 {
24673 self.write(", ");
24674 }
24675 self.generate_expression(expr)?;
24676 }
24677 }
24678
24679 if let Some(into) = &pivot.into {
24681 self.write_space();
24682 self.write_keyword("INTO");
24683 self.write_space();
24684 self.generate_expression(into)?;
24685 }
24686
24687 if !pivot.using.is_empty() {
24689 self.write_space();
24690 self.write_keyword("USING");
24691 self.write_space();
24692 for (i, expr) in pivot.using.iter().enumerate() {
24693 if i > 0 {
24694 self.write(", ");
24695 }
24696 self.generate_expression(expr)?;
24697 }
24698 }
24699
24700 if let Some(group) = &pivot.group {
24702 self.write_space();
24703 self.generate_expression(group)?;
24704 }
24705 } else {
24706 if !matches!(&pivot.this, Expression::Null(_)) {
24711 self.generate_expression(&pivot.this)?;
24712 self.write_space();
24713 }
24714 self.write_keyword(direction);
24715 self.write("(");
24716
24717 for (i, expr) in pivot.expressions.iter().enumerate() {
24719 if i > 0 {
24720 self.write(", ");
24721 }
24722 self.generate_expression(expr)?;
24723 }
24724
24725 if !pivot.fields.is_empty() {
24727 if !pivot.expressions.is_empty() {
24728 self.write_space();
24729 }
24730 self.write_keyword("FOR");
24731 self.write_space();
24732 for (i, field) in pivot.fields.iter().enumerate() {
24733 if i > 0 {
24734 self.write_space();
24735 }
24736 self.generate_expression(field)?;
24738 }
24739 }
24740
24741 if let Some(default_val) = &pivot.default_on_null {
24743 self.write_space();
24744 self.write_keyword("DEFAULT ON NULL");
24745 self.write(" (");
24746 self.generate_expression(default_val)?;
24747 self.write(")");
24748 }
24749
24750 if let Some(group) = &pivot.group {
24752 self.write_space();
24753 self.generate_expression(group)?;
24754 }
24755
24756 self.write(")");
24757 }
24758
24759 if let Some(alias) = &pivot.alias {
24761 self.write_space();
24762 self.write_keyword("AS");
24763 self.write_space();
24764 self.generate_identifier(alias)?;
24765 self.generate_alias_column_list(&pivot.alias_columns)?;
24766 }
24767
24768 Ok(())
24769 }
24770
24771 fn generate_unpivot(&mut self, unpivot: &Unpivot) -> Result<()> {
24772 self.generate_expression(&unpivot.this)?;
24773 self.write_space();
24774 self.write_keyword("UNPIVOT");
24775 if let Some(include) = unpivot.include_nulls {
24777 self.write_space();
24778 if include {
24779 self.write_keyword("INCLUDE NULLS");
24780 } else {
24781 self.write_keyword("EXCLUDE NULLS");
24782 }
24783 self.write_space();
24784 }
24785 self.write("(");
24786 if unpivot.value_column_parenthesized {
24787 self.write("(");
24788 }
24789 self.generate_identifier(&unpivot.value_column)?;
24790 for extra_col in &unpivot.extra_value_columns {
24792 self.write(", ");
24793 self.generate_identifier(extra_col)?;
24794 }
24795 if unpivot.value_column_parenthesized {
24796 self.write(")");
24797 }
24798 self.write_space();
24799 self.write_keyword("FOR");
24800 self.write_space();
24801 self.generate_identifier(&unpivot.name_column)?;
24802 self.write_space();
24803 self.write_keyword("IN");
24804 self.write(" (");
24805 for (i, col) in unpivot.columns.iter().enumerate() {
24806 if i > 0 {
24807 self.write(", ");
24808 }
24809 self.generate_expression(col)?;
24810 }
24811 self.write("))");
24812 if let Some(alias) = &unpivot.alias {
24813 self.write_space();
24814 self.write_keyword("AS");
24815 self.write_space();
24816 self.generate_identifier(alias)?;
24817 self.generate_alias_column_list(&unpivot.alias_columns)?;
24818 }
24819 Ok(())
24820 }
24821
24822 fn generate_alias_column_list(&mut self, columns: &[Identifier]) -> Result<()> {
24823 if columns.is_empty() {
24824 return Ok(());
24825 }
24826
24827 self.write("(");
24828 for (i, column) in columns.iter().enumerate() {
24829 if i > 0 {
24830 self.write(", ");
24831 }
24832 self.generate_identifier(column)?;
24833 }
24834 self.write(")");
24835 Ok(())
24836 }
24837
24838 fn generate_values(&mut self, values: &Values) -> Result<()> {
24839 self.write_keyword("VALUES");
24840 for (i, row) in values.expressions.iter().enumerate() {
24841 if i > 0 {
24842 self.write(",");
24843 }
24844 self.write(" (");
24845 for (j, expr) in row.expressions.iter().enumerate() {
24846 if j > 0 {
24847 self.write(", ");
24848 }
24849 self.generate_expression(expr)?;
24850 }
24851 self.write(")");
24852 }
24853 if let Some(alias) = &values.alias {
24854 self.write_space();
24855 self.write_keyword("AS");
24856 self.write_space();
24857 self.generate_identifier(alias)?;
24858 if !values.column_aliases.is_empty() {
24859 self.write("(");
24860 for (i, col) in values.column_aliases.iter().enumerate() {
24861 if i > 0 {
24862 self.write(", ");
24863 }
24864 self.generate_identifier(col)?;
24865 }
24866 self.write(")");
24867 }
24868 }
24869 Ok(())
24870 }
24871
24872 fn generate_array(&mut self, arr: &Array) -> Result<()> {
24873 let needs_inheritance = matches!(
24875 self.config.dialect,
24876 Some(DialectType::DuckDB)
24877 | Some(DialectType::Spark)
24878 | Some(DialectType::Databricks)
24879 | Some(DialectType::Hive)
24880 | Some(DialectType::Snowflake)
24881 | Some(DialectType::Presto)
24882 | Some(DialectType::Trino)
24883 );
24884 let propagated: Vec<Expression>;
24885 let expressions = if needs_inheritance && arr.expressions.len() > 1 {
24886 propagated = Self::inherit_struct_field_names(&arr.expressions);
24887 &propagated
24888 } else {
24889 &arr.expressions
24890 };
24891
24892 let use_parens =
24895 self.config.dialect.is_none() || self.config.dialect == Some(DialectType::Generic);
24896 if !self.config.array_bracket_only {
24897 self.write_keyword("ARRAY");
24898 }
24899 if use_parens {
24900 self.write("(");
24901 } else {
24902 self.write("[");
24903 }
24904 for (i, expr) in expressions.iter().enumerate() {
24905 if i > 0 {
24906 self.write(", ");
24907 }
24908 self.generate_expression(expr)?;
24909 }
24910 if use_parens {
24911 self.write(")");
24912 } else {
24913 self.write("]");
24914 }
24915 Ok(())
24916 }
24917
24918 fn generate_tuple(&mut self, tuple: &Tuple) -> Result<()> {
24919 if tuple.expressions.len() == 2 {
24922 if let Expression::TableAlias(_) = &tuple.expressions[1] {
24923 self.generate_expression(&tuple.expressions[0])?;
24925 self.write_space();
24926 self.write_keyword("AS");
24927 self.write_space();
24928 self.generate_expression(&tuple.expressions[1])?;
24929 return Ok(());
24930 }
24931 }
24932
24933 let expand_tuple = if self.config.pretty && tuple.expressions.len() > 1 {
24936 let mut expr_strings: Vec<String> = Vec::with_capacity(tuple.expressions.len());
24937 for expr in &tuple.expressions {
24938 expr_strings.push(self.generate_to_string(expr)?);
24939 }
24940 self.too_wide(&expr_strings)
24941 } else {
24942 false
24943 };
24944
24945 if expand_tuple {
24946 self.write("(");
24947 self.write_newline();
24948 self.indent_level += 1;
24949 for (i, expr) in tuple.expressions.iter().enumerate() {
24950 if i > 0 {
24951 self.write(",");
24952 self.write_newline();
24953 }
24954 self.write_indent();
24955 self.generate_expression(expr)?;
24956 }
24957 self.indent_level -= 1;
24958 self.write_newline();
24959 self.write_indent();
24960 self.write(")");
24961 } else {
24962 self.write("(");
24963 for (i, expr) in tuple.expressions.iter().enumerate() {
24964 if i > 0 {
24965 self.write(", ");
24966 }
24967 self.generate_expression(expr)?;
24968 }
24969 self.write(")");
24970 }
24971 Ok(())
24972 }
24973
24974 fn generate_pipe_operator(&mut self, pipe: &PipeOperator) -> Result<()> {
24975 self.generate_expression(&pipe.this)?;
24976 self.write(" |> ");
24977 self.generate_expression(&pipe.expression)?;
24978 Ok(())
24979 }
24980
24981 fn generate_ordered(&mut self, ordered: &Ordered) -> Result<()> {
24982 let unsupported_tsql_null_ordering = ordered.nulls_first.is_some()
24983 && !self.config.null_ordering_supported
24984 && matches!(
24985 self.config.dialect,
24986 Some(DialectType::TSQL) | Some(DialectType::Fabric)
24987 );
24988 let random_ordering = matches!(ordered.this, Expression::Rand(_) | Expression::Random(_));
24989 let emulate_tsql_null_ordering = if let Some(nulls_first) = ordered.nulls_first {
24990 let target_default_nulls_first = !ordered.desc;
24991
24992 unsupported_tsql_null_ordering
24993 && nulls_first != target_default_nulls_first
24994 && !random_ordering
24995 } else {
24996 false
24997 };
24998
24999 if emulate_tsql_null_ordering {
25000 if Self::is_integer_ordering_literal(&ordered.this) {
25001 let nulls_order = if ordered.nulls_first == Some(true) {
25002 "NULLS FIRST"
25003 } else {
25004 "NULLS LAST"
25005 };
25006 self.unsupported(format!(
25007 "'{nulls_order}' translation not supported with positional ordering"
25008 ))?;
25009 } else {
25010 self.write_keyword("CASE WHEN");
25011 self.write_space();
25012 self.generate_expression(&ordered.this)?;
25013 self.write_space();
25014 self.write_keyword("IS NULL THEN 1 ELSE 0 END");
25015 if ordered.nulls_first == Some(true) {
25016 self.write_space();
25017 self.write_keyword("DESC");
25018 }
25019 self.write(", ");
25020 }
25021 }
25022
25023 self.generate_expression(&ordered.this)?;
25024 if ordered.desc {
25025 self.write_space();
25026 self.write_keyword("DESC");
25027 } else if ordered.explicit_asc {
25028 self.write_space();
25029 self.write_keyword("ASC");
25030 }
25031 if let Some(nulls_first) = ordered.nulls_first {
25032 if !unsupported_tsql_null_ordering
25033 && (self.config.null_ordering_supported
25034 || !matches!(self.config.dialect, Some(DialectType::Fabric)))
25035 {
25036 let is_asc = !ordered.desc;
25050 let is_nulls_are_large = matches!(
25051 self.config.dialect,
25052 Some(DialectType::Oracle)
25053 | Some(DialectType::PostgreSQL)
25054 | Some(DialectType::Redshift)
25055 | Some(DialectType::Snowflake)
25056 );
25057 let is_nulls_are_last = matches!(
25058 self.config.dialect,
25059 Some(DialectType::Dremio)
25060 | Some(DialectType::DuckDB)
25061 | Some(DialectType::Presto)
25062 | Some(DialectType::Trino)
25063 | Some(DialectType::Athena)
25064 | Some(DialectType::ClickHouse)
25065 | Some(DialectType::Drill)
25066 | Some(DialectType::Exasol)
25067 );
25068
25069 let is_default_nulls = if is_nulls_are_large {
25071 (is_asc && !nulls_first) || (!is_asc && nulls_first)
25073 } else if is_nulls_are_last {
25074 !nulls_first
25076 } else {
25077 false
25078 };
25079
25080 if !is_default_nulls {
25081 self.write_space();
25082 self.write_keyword("NULLS");
25083 self.write_space();
25084 self.write_keyword(if nulls_first { "FIRST" } else { "LAST" });
25085 }
25086 }
25087 }
25088 if let Some(ref with_fill) = ordered.with_fill {
25090 self.write_space();
25091 self.generate_with_fill(with_fill)?;
25092 }
25093 Ok(())
25094 }
25095
25096 fn is_integer_ordering_literal(expr: &Expression) -> bool {
25097 matches!(
25098 expr,
25099 Expression::Literal(lit)
25100 if matches!(lit.as_ref(), Literal::Number(n) if n.parse::<u64>().is_ok())
25101 )
25102 }
25103
25104 fn write_clickhouse_type(&mut self, type_str: &str) {
25106 if self.clickhouse_nullable_depth < 0 {
25107 self.write(type_str);
25109 } else {
25110 self.write(&format!("Nullable({})", type_str));
25111 }
25112 }
25113
25114 fn write_type_with_length(&mut self, name: &str, length: Option<u32>) {
25115 self.write_keyword(name);
25116 if let Some(length) = length {
25117 self.write(&format!("({length})"));
25118 }
25119 }
25120
25121 fn write_oracle_number(&mut self, precision: Option<u32>, scale: Option<i32>) -> Result<()> {
25122 use crate::dialects::DialectType;
25123
25124 if matches!(self.config.dialect, Some(DialectType::Oracle) | None) {
25125 self.write_keyword("NUMBER");
25126 if precision.is_some() || scale.is_some() {
25127 self.write("(");
25128 if let Some(precision) = precision {
25129 self.write(&precision.to_string());
25130 } else {
25131 self.write("*");
25132 }
25133 if let Some(scale) = scale {
25134 self.write(&format!(", {scale}"));
25135 }
25136 self.write(")");
25137 }
25138 return Ok(());
25139 }
25140
25141 let target = self.config.dialect;
25142 match (precision, scale) {
25143 (None, None) => match target {
25144 Some(DialectType::PostgreSQL) | Some(DialectType::Materialize) => {
25145 self.write_keyword("NUMERIC");
25146 }
25147 Some(DialectType::MySQL)
25148 | Some(DialectType::SingleStore)
25149 | Some(DialectType::TiDB) => {
25150 self.unsupported(
25151 "Oracle NUMBER without precision or scale has no exact MySQL mapping",
25152 )?;
25153 self.write_keyword("DECIMAL(65, 30)");
25154 }
25155 Some(DialectType::TSQL) | Some(DialectType::Fabric) => {
25156 self.unsupported(
25157 "Oracle NUMBER without precision or scale has no exact T-SQL mapping",
25158 )?;
25159 self.write_keyword("DECIMAL(38, 10)");
25160 }
25161 _ => self.write_keyword("DECIMAL"),
25162 },
25163 (Some(precision), None) | (Some(precision), Some(0)) => {
25164 if precision <= 9 {
25165 self.write_keyword("INT");
25166 } else if precision <= 18 {
25167 self.write_keyword("BIGINT");
25168 } else {
25169 self.write(&format!("DECIMAL({precision}, 0)"));
25170 }
25171 }
25172 (Some(precision), Some(scale)) if scale < 0 => match target {
25173 Some(DialectType::PostgreSQL) | Some(DialectType::Materialize) => {
25174 self.write(&format!("NUMERIC({precision}, {scale})"));
25175 }
25176 Some(DialectType::MySQL)
25177 | Some(DialectType::SingleStore)
25178 | Some(DialectType::TiDB) => {
25179 self.unsupported(format!(
25180 "Oracle NUMBER({precision}, {scale}) negative-scale rounding cannot be enforced by MySQL"
25181 ))?;
25182 let width = precision.saturating_add(scale.unsigned_abs()).min(65);
25183 self.write(&format!("DECIMAL({width}, 0)"));
25184 }
25185 Some(DialectType::TSQL) | Some(DialectType::Fabric) => {
25186 self.unsupported(format!(
25187 "Oracle NUMBER({precision}, {scale}) negative-scale rounding cannot be enforced by T-SQL"
25188 ))?;
25189 let width = precision.saturating_add(scale.unsigned_abs()).min(38);
25190 self.write(&format!("DECIMAL({width}, 0)"));
25191 }
25192 _ => {
25193 self.unsupported(format!(
25194 "Oracle NUMBER({precision}, {scale}) negative-scale rounding may not be supported"
25195 ))?;
25196 let width = precision.saturating_add(scale.unsigned_abs());
25197 self.write(&format!("DECIMAL({width}, 0)"));
25198 }
25199 },
25200 (Some(precision), Some(scale)) => {
25201 let mut target_precision = precision;
25202 let mut target_scale = u32::try_from(scale).unwrap_or_default();
25203 let limits = match target {
25204 Some(DialectType::MySQL)
25205 | Some(DialectType::SingleStore)
25206 | Some(DialectType::TiDB) => Some((65, 30, "MySQL")),
25207 Some(DialectType::TSQL) | Some(DialectType::Fabric) => Some((38, 38, "T-SQL")),
25208 _ => None,
25209 };
25210 if let Some((max_precision, max_scale, dialect_name)) = limits {
25211 let requested_precision = target_precision;
25212 let requested_scale = target_scale;
25213 target_scale = target_scale.min(max_scale);
25214 target_precision = target_precision.max(target_scale).min(max_precision);
25215 if target_precision != requested_precision || target_scale != requested_scale {
25216 self.unsupported(format!(
25217 "Oracle NUMBER({precision}, {scale}) exceeds {dialect_name} DECIMAL limits"
25218 ))?;
25219 }
25220 }
25221 self.write(&format!("DECIMAL({target_precision}, {target_scale})"));
25222 }
25223 (None, Some(scale)) => {
25224 self.unsupported(format!(
25225 "Oracle NUMBER(*, {scale}) has no exact target mapping"
25226 ))?;
25227 self.write_keyword("DECIMAL");
25228 }
25229 }
25230 Ok(())
25231 }
25232
25233 fn write_oracle_character(
25234 &mut self,
25235 kind: OracleCharacterKind,
25236 length: Option<u32>,
25237 semantics: Option<OracleCharacterLengthSemantics>,
25238 ) -> Result<()> {
25239 use crate::dialects::DialectType;
25240
25241 if matches!(self.config.dialect, Some(DialectType::Oracle) | None) {
25242 let name = match kind {
25243 OracleCharacterKind::Char => "CHAR",
25244 OracleCharacterKind::VarChar => "VARCHAR2",
25245 OracleCharacterKind::NChar => "NCHAR",
25246 OracleCharacterKind::NVarChar => "NVARCHAR2",
25247 };
25248 self.write_keyword(name);
25249 if let Some(length) = length {
25250 self.write(&format!("({length}"));
25251 if let Some(semantics) = semantics {
25252 self.write(match semantics {
25253 OracleCharacterLengthSemantics::Byte => " BYTE",
25254 OracleCharacterLengthSemantics::Char => " CHAR",
25255 });
25256 }
25257 self.write(")");
25258 }
25259 return Ok(());
25260 }
25261
25262 let mut target_kind = kind;
25263 match self.config.dialect {
25264 Some(DialectType::TSQL) | Some(DialectType::Fabric)
25265 if semantics == Some(OracleCharacterLengthSemantics::Char)
25266 && matches!(
25267 kind,
25268 OracleCharacterKind::Char | OracleCharacterKind::VarChar
25269 ) =>
25270 {
25271 self.unsupported(
25272 "Oracle CHAR length semantics require a national-character approximation in T-SQL",
25273 )?;
25274 target_kind = match kind {
25275 OracleCharacterKind::Char => OracleCharacterKind::NChar,
25276 OracleCharacterKind::VarChar => OracleCharacterKind::NVarChar,
25277 _ => kind,
25278 };
25279 }
25280 Some(DialectType::PostgreSQL) | Some(DialectType::Materialize)
25281 if matches!(
25282 kind,
25283 OracleCharacterKind::NChar | OracleCharacterKind::NVarChar
25284 ) =>
25285 {
25286 target_kind = match kind {
25287 OracleCharacterKind::NChar => OracleCharacterKind::Char,
25288 OracleCharacterKind::NVarChar => OracleCharacterKind::VarChar,
25289 _ => kind,
25290 };
25291 }
25292 _ => {}
25293 }
25294
25295 if semantics == Some(OracleCharacterLengthSemantics::Byte)
25296 && matches!(
25297 self.config.dialect,
25298 Some(DialectType::MySQL)
25299 | Some(DialectType::SingleStore)
25300 | Some(DialectType::TiDB)
25301 | Some(DialectType::PostgreSQL)
25302 | Some(DialectType::Materialize)
25303 )
25304 {
25305 self.unsupported(
25306 "Oracle BYTE character length semantics cannot be enforced by the target type",
25307 )?;
25308 }
25309
25310 let name = match target_kind {
25311 OracleCharacterKind::Char => "CHAR",
25312 OracleCharacterKind::VarChar => "VARCHAR",
25313 OracleCharacterKind::NChar => "NCHAR",
25314 OracleCharacterKind::NVarChar => "NVARCHAR",
25315 };
25316 let length = if matches!(
25317 target_kind,
25318 OracleCharacterKind::Char | OracleCharacterKind::NChar
25319 ) {
25320 Some(length.unwrap_or(1))
25321 } else {
25322 length
25323 };
25324 self.write_type_with_length(name, length);
25325 Ok(())
25326 }
25327
25328 fn oracle_timestamp_precision(&mut self, precision: Option<u32>, maximum: u32) -> Result<u32> {
25329 let requested = precision.unwrap_or(6);
25330 if requested > maximum {
25331 self.unsupported(format!(
25332 "Oracle timestamp precision {requested} exceeds the target maximum of {maximum}"
25333 ))?;
25334 }
25335 Ok(requested.min(maximum))
25336 }
25337
25338 fn write_oracle_data_type(&mut self, data_type: &OracleDataType) -> Result<()> {
25339 use crate::dialects::DialectType;
25340
25341 match data_type {
25342 OracleDataType::Number { precision, scale } => {
25343 self.write_oracle_number(*precision, *scale)?;
25344 }
25345 OracleDataType::BinaryFloat => match self.config.dialect {
25346 Some(DialectType::Oracle) | None => self.write_keyword("BINARY_FLOAT"),
25347 Some(DialectType::TSQL)
25348 | Some(DialectType::Fabric)
25349 | Some(DialectType::PostgreSQL)
25350 | Some(DialectType::Materialize) => self.write_keyword("REAL"),
25351 _ => self.write_keyword("FLOAT"),
25352 },
25353 OracleDataType::BinaryDouble => match self.config.dialect {
25354 Some(DialectType::Oracle) | None => self.write_keyword("BINARY_DOUBLE"),
25355 Some(DialectType::TSQL) | Some(DialectType::Fabric) => self.write_keyword("FLOAT"),
25356 Some(DialectType::PostgreSQL) | Some(DialectType::Materialize) => {
25357 self.write_keyword("DOUBLE PRECISION")
25358 }
25359 _ => self.write_keyword("DOUBLE"),
25360 },
25361 OracleDataType::Float { precision } => {
25362 if matches!(self.config.dialect, Some(DialectType::Oracle) | None) {
25363 self.write_keyword("FLOAT");
25364 if let Some(precision) = precision {
25365 self.write(&format!("({precision})"));
25366 }
25367 } else {
25368 let precision = precision.unwrap_or(126);
25369 match self.config.dialect {
25370 Some(DialectType::TSQL) | Some(DialectType::Fabric) => {
25371 if precision > 53 {
25372 self.unsupported(format!(
25373 "Oracle FLOAT({precision}) exceeds T-SQL FLOAT precision"
25374 ))?;
25375 }
25376 self.write(&format!("FLOAT({})", precision.min(53)));
25377 }
25378 Some(DialectType::PostgreSQL) | Some(DialectType::Materialize) => {
25379 self.write_keyword(if precision <= 24 {
25380 "REAL"
25381 } else {
25382 "DOUBLE PRECISION"
25383 });
25384 }
25385 Some(DialectType::MySQL)
25386 | Some(DialectType::SingleStore)
25387 | Some(DialectType::TiDB) => {
25388 self.write_keyword(if precision <= 24 { "FLOAT" } else { "DOUBLE" });
25389 }
25390 _ => self.write_keyword("DOUBLE PRECISION"),
25391 }
25392 }
25393 }
25394 OracleDataType::Character {
25395 kind,
25396 length,
25397 semantics,
25398 } => self.write_oracle_character(*kind, *length, *semantics)?,
25399 OracleDataType::Date => match self.config.dialect {
25400 Some(DialectType::Oracle) | None => self.write_keyword("DATE"),
25401 Some(DialectType::MySQL)
25402 | Some(DialectType::SingleStore)
25403 | Some(DialectType::TiDB) => self.write_keyword("DATETIME"),
25404 Some(DialectType::TSQL) | Some(DialectType::Fabric) => {
25405 self.write_keyword("DATETIME2(0)")
25406 }
25407 _ => self.write_keyword("TIMESTAMP(0)"),
25408 },
25409 OracleDataType::Timestamp {
25410 precision,
25411 timezone,
25412 } => {
25413 if matches!(self.config.dialect, Some(DialectType::Oracle) | None) {
25414 self.write_keyword("TIMESTAMP");
25415 if let Some(precision) = precision {
25416 self.write(&format!("({precision})"));
25417 }
25418 match timezone {
25419 OracleTimestampTimeZone::None => {}
25420 OracleTimestampTimeZone::WithTimeZone => {
25421 self.write_keyword(" WITH TIME ZONE")
25422 }
25423 OracleTimestampTimeZone::WithLocalTimeZone => {
25424 self.write_keyword(" WITH LOCAL TIME ZONE")
25425 }
25426 }
25427 } else {
25428 match self.config.dialect {
25429 Some(DialectType::MySQL)
25430 | Some(DialectType::SingleStore)
25431 | Some(DialectType::TiDB) => {
25432 let precision = self.oracle_timestamp_precision(*precision, 6)?;
25433 match timezone {
25434 OracleTimestampTimeZone::None => {
25435 self.write(&format!("DATETIME({precision})"));
25436 }
25437 OracleTimestampTimeZone::WithTimeZone => {
25438 self.unsupported(
25439 "Oracle TIMESTAMP WITH TIME ZONE loses its time zone in MySQL",
25440 )?;
25441 self.write(&format!("DATETIME({precision})"));
25442 }
25443 OracleTimestampTimeZone::WithLocalTimeZone => {
25444 self.unsupported(
25445 "Oracle TIMESTAMP WITH LOCAL TIME ZONE has only an approximate MySQL mapping",
25446 )?;
25447 self.write(&format!("TIMESTAMP({precision})"));
25448 }
25449 }
25450 }
25451 Some(DialectType::TSQL) | Some(DialectType::Fabric) => {
25452 let precision = self.oracle_timestamp_precision(*precision, 7)?;
25453 match timezone {
25454 OracleTimestampTimeZone::None => {
25455 self.write(&format!("DATETIME2({precision})"));
25456 }
25457 OracleTimestampTimeZone::WithTimeZone => {
25458 self.write(&format!("DATETIMEOFFSET({precision})"));
25459 }
25460 OracleTimestampTimeZone::WithLocalTimeZone => {
25461 self.unsupported(
25462 "Oracle TIMESTAMP WITH LOCAL TIME ZONE loses session time-zone semantics in T-SQL",
25463 )?;
25464 self.write(&format!("DATETIME2({precision})"));
25465 }
25466 }
25467 }
25468 Some(DialectType::PostgreSQL) | Some(DialectType::Materialize) => {
25469 let precision = self.oracle_timestamp_precision(*precision, 6)?;
25470 match timezone {
25471 OracleTimestampTimeZone::None => {
25472 self.write(&format!("TIMESTAMP({precision})"));
25473 }
25474 OracleTimestampTimeZone::WithTimeZone => {
25475 self.write(&format!("TIMESTAMPTZ({precision})"));
25476 }
25477 OracleTimestampTimeZone::WithLocalTimeZone => {
25478 self.unsupported(
25479 "Oracle TIMESTAMP WITH LOCAL TIME ZONE has only an approximate PostgreSQL mapping",
25480 )?;
25481 self.write(&format!("TIMESTAMPTZ({precision})"));
25482 }
25483 }
25484 }
25485 _ => {
25486 let precision = precision.unwrap_or(6);
25487 let name = if matches!(timezone, OracleTimestampTimeZone::None) {
25488 "TIMESTAMP"
25489 } else {
25490 "TIMESTAMPTZ"
25491 };
25492 self.write(&format!("{name}({precision})"));
25493 }
25494 }
25495 }
25496 }
25497 OracleDataType::IntervalYearToMonth { year_precision } => {
25498 if matches!(self.config.dialect, Some(DialectType::Oracle) | None) {
25499 self.write_keyword("INTERVAL YEAR");
25500 if let Some(precision) = year_precision {
25501 self.write(&format!("({precision})"));
25502 }
25503 self.write_keyword(" TO MONTH");
25504 } else if matches!(
25505 self.config.dialect,
25506 Some(DialectType::MySQL)
25507 | Some(DialectType::SingleStore)
25508 | Some(DialectType::TiDB)
25509 | Some(DialectType::TSQL)
25510 | Some(DialectType::Fabric)
25511 ) {
25512 self.unsupported(
25513 "Oracle INTERVAL YEAR TO MONTH has no native target column type",
25514 )?;
25515 self.write_keyword("VARCHAR(30)");
25516 } else {
25517 if year_precision.is_some() {
25518 self.unsupported(
25519 "Oracle INTERVAL YEAR leading precision cannot be preserved",
25520 )?;
25521 }
25522 self.write_keyword("INTERVAL YEAR TO MONTH");
25523 }
25524 }
25525 OracleDataType::IntervalDayToSecond {
25526 day_precision,
25527 fractional_seconds_precision,
25528 } => {
25529 if matches!(self.config.dialect, Some(DialectType::Oracle) | None) {
25530 self.write_keyword("INTERVAL DAY");
25531 if let Some(precision) = day_precision {
25532 self.write(&format!("({precision})"));
25533 }
25534 self.write_keyword(" TO SECOND");
25535 if let Some(precision) = fractional_seconds_precision {
25536 self.write(&format!("({precision})"));
25537 }
25538 } else if matches!(
25539 self.config.dialect,
25540 Some(DialectType::MySQL)
25541 | Some(DialectType::SingleStore)
25542 | Some(DialectType::TiDB)
25543 | Some(DialectType::TSQL)
25544 | Some(DialectType::Fabric)
25545 ) {
25546 self.unsupported(
25547 "Oracle INTERVAL DAY TO SECOND has no native target column type",
25548 )?;
25549 self.write_keyword("VARCHAR(30)");
25550 } else {
25551 if day_precision.is_some() {
25552 self.unsupported(
25553 "Oracle INTERVAL DAY leading precision cannot be preserved",
25554 )?;
25555 }
25556 self.write_keyword("INTERVAL");
25557 if let Some(precision) = fractional_seconds_precision {
25558 self.write(&format!("({precision})"));
25559 }
25560 self.write_keyword(" DAY TO SECOND");
25561 }
25562 }
25563 OracleDataType::Clob { national } => match self.config.dialect {
25564 Some(DialectType::Oracle) | None => {
25565 self.write_keyword(if *national { "NCLOB" } else { "CLOB" })
25566 }
25567 Some(DialectType::MySQL)
25568 | Some(DialectType::SingleStore)
25569 | Some(DialectType::TiDB) => self.write_keyword("LONGTEXT"),
25570 Some(DialectType::TSQL) | Some(DialectType::Fabric) => {
25571 self.write_keyword(if *national {
25572 "NVARCHAR(MAX)"
25573 } else {
25574 "VARCHAR(MAX)"
25575 });
25576 }
25577 _ => self.write_keyword("TEXT"),
25578 },
25579 OracleDataType::Blob => match self.config.dialect {
25580 Some(DialectType::Oracle) | None => self.write_keyword("BLOB"),
25581 Some(DialectType::MySQL)
25582 | Some(DialectType::SingleStore)
25583 | Some(DialectType::TiDB) => self.write_keyword("LONGBLOB"),
25584 Some(DialectType::TSQL) | Some(DialectType::Fabric) => {
25585 self.write_keyword("VARBINARY(MAX)")
25586 }
25587 Some(DialectType::PostgreSQL) | Some(DialectType::Materialize) => {
25588 self.write_keyword("BYTEA")
25589 }
25590 _ => self.write_keyword("BLOB"),
25591 },
25592 OracleDataType::Raw { length } => match self.config.dialect {
25593 Some(DialectType::Oracle) | None => self.write_type_with_length("RAW", *length),
25594 Some(DialectType::PostgreSQL) | Some(DialectType::Materialize) => {
25595 if length.is_some() {
25596 self.unsupported("Oracle RAW length constraint is lost in PostgreSQL")?;
25597 }
25598 self.write_keyword("BYTEA");
25599 }
25600 _ => self.write_type_with_length("VARBINARY", *length),
25601 },
25602 OracleDataType::Long { raw } => {
25603 if matches!(self.config.dialect, Some(DialectType::Oracle) | None) {
25604 self.write_keyword(if *raw { "LONG RAW" } else { "LONG" });
25605 } else if *raw {
25606 match self.config.dialect {
25607 Some(DialectType::MySQL)
25608 | Some(DialectType::SingleStore)
25609 | Some(DialectType::TiDB) => self.write_keyword("LONGBLOB"),
25610 Some(DialectType::TSQL) | Some(DialectType::Fabric) => {
25611 self.write_keyword("VARBINARY(MAX)")
25612 }
25613 Some(DialectType::PostgreSQL) | Some(DialectType::Materialize) => {
25614 self.write_keyword("BYTEA")
25615 }
25616 _ => self.write_keyword("BLOB"),
25617 }
25618 } else {
25619 match self.config.dialect {
25620 Some(DialectType::MySQL)
25621 | Some(DialectType::SingleStore)
25622 | Some(DialectType::TiDB) => self.write_keyword("LONGTEXT"),
25623 Some(DialectType::TSQL) | Some(DialectType::Fabric) => {
25624 self.write_keyword("VARCHAR(MAX)")
25625 }
25626 _ => self.write_keyword("TEXT"),
25627 }
25628 }
25629 }
25630 OracleDataType::RowId => {
25631 if matches!(self.config.dialect, Some(DialectType::Oracle) | None) {
25632 self.write_keyword("ROWID");
25633 } else {
25634 self.unsupported(
25635 "Oracle ROWID physical row identity is reduced to its text representation",
25636 )?;
25637 self.write_keyword("CHAR(18)");
25638 }
25639 }
25640 }
25641 Ok(())
25642 }
25643
25644 fn generate_data_type(&mut self, dt: &DataType) -> Result<()> {
25645 use crate::dialects::DialectType;
25646
25647 match dt {
25648 DataType::Boolean => {
25649 match self.config.dialect {
25651 Some(DialectType::TSQL) => self.write_keyword("BIT"),
25652 Some(DialectType::MySQL) => self.write_keyword("BOOLEAN"), Some(DialectType::Oracle) => {
25654 self.write_keyword("NUMBER(1)")
25656 }
25657 Some(DialectType::ClickHouse) => self.write("Bool"), _ => self.write_keyword("BOOLEAN"),
25659 }
25660 }
25661 DataType::TinyInt { length } => {
25662 match self.config.dialect {
25666 Some(DialectType::PostgreSQL)
25667 | Some(DialectType::Redshift)
25668 | Some(DialectType::Oracle)
25669 | Some(DialectType::Exasol) => {
25670 self.write_keyword("SMALLINT");
25671 }
25672 Some(DialectType::Teradata) => {
25673 self.write_keyword("BYTEINT");
25675 }
25676 Some(DialectType::Dremio) => {
25677 self.write_keyword("INT");
25679 }
25680 Some(DialectType::ClickHouse) => {
25681 self.write_clickhouse_type("Int8");
25682 }
25683 _ => {
25684 self.write_keyword("TINYINT");
25685 }
25686 }
25687 if let Some(n) = length {
25688 if !matches!(
25689 self.config.dialect,
25690 Some(DialectType::Dremio) | Some(DialectType::ClickHouse)
25691 ) {
25692 self.write(&format!("({})", n));
25693 }
25694 }
25695 }
25696 DataType::SmallInt { length } => {
25697 match self.config.dialect {
25699 Some(DialectType::Dremio) => {
25700 self.write_keyword("INT");
25701 }
25702 Some(DialectType::SQLite) | Some(DialectType::Drill) => {
25703 self.write_keyword("INTEGER");
25704 }
25705 Some(DialectType::BigQuery) => {
25706 self.write_keyword("INT64");
25707 }
25708 Some(DialectType::ClickHouse) => {
25709 self.write_clickhouse_type("Int16");
25710 }
25711 _ => {
25712 self.write_keyword("SMALLINT");
25713 if let Some(n) = length {
25714 self.write(&format!("({})", n));
25715 }
25716 }
25717 }
25718 }
25719 DataType::Int {
25720 length,
25721 integer_spelling: _,
25722 } => {
25723 if matches!(self.config.dialect, Some(DialectType::BigQuery)) {
25725 self.write_keyword("INT64");
25726 } else if matches!(self.config.dialect, Some(DialectType::ClickHouse)) {
25727 self.write_clickhouse_type("Int32");
25728 } else {
25729 let use_integer = match self.config.dialect {
25731 Some(DialectType::TSQL)
25732 | Some(DialectType::Fabric)
25733 | Some(DialectType::Presto)
25734 | Some(DialectType::Trino)
25735 | Some(DialectType::SQLite)
25736 | Some(DialectType::Redshift) => true,
25737 _ => false,
25738 };
25739 if use_integer {
25740 self.write_keyword("INTEGER");
25741 } else {
25742 self.write_keyword("INT");
25743 }
25744 if let Some(n) = length {
25745 self.write(&format!("({})", n));
25746 }
25747 }
25748 }
25749 DataType::BigInt { length } => {
25750 match self.config.dialect {
25752 Some(DialectType::Oracle) => {
25753 self.write_keyword("INT");
25755 }
25756 Some(DialectType::ClickHouse) => {
25757 self.write_clickhouse_type("Int64");
25758 }
25759 _ => {
25760 self.write_keyword("BIGINT");
25761 if let Some(n) = length {
25762 self.write(&format!("({})", n));
25763 }
25764 }
25765 }
25766 }
25767 DataType::Float {
25768 precision,
25769 scale,
25770 real_spelling,
25771 } => {
25772 if matches!(self.config.dialect, Some(DialectType::ClickHouse)) {
25776 self.write_clickhouse_type("Float32");
25777 } else if *real_spelling
25778 && !matches!(
25779 self.config.dialect,
25780 Some(DialectType::Spark)
25781 | Some(DialectType::Databricks)
25782 | Some(DialectType::Hive)
25783 | Some(DialectType::Snowflake)
25784 | Some(DialectType::MySQL)
25785 | Some(DialectType::BigQuery)
25786 )
25787 {
25788 self.write_keyword("REAL")
25789 } else {
25790 match self.config.dialect {
25791 Some(DialectType::PostgreSQL) => self.write_keyword("REAL"),
25792 Some(DialectType::BigQuery) => self.write_keyword("FLOAT64"),
25793 _ => self.write_keyword("FLOAT"),
25794 }
25795 }
25796 if !matches!(
25799 self.config.dialect,
25800 Some(DialectType::Spark)
25801 | Some(DialectType::Databricks)
25802 | Some(DialectType::Hive)
25803 | Some(DialectType::Presto)
25804 | Some(DialectType::Trino)
25805 ) {
25806 if let Some(p) = precision {
25807 self.write(&format!("({}", p));
25808 if let Some(s) = scale {
25809 self.write(&format!(", {})", s));
25810 } else {
25811 self.write(")");
25812 }
25813 }
25814 }
25815 }
25816 DataType::Double { precision, scale } => {
25817 match self.config.dialect {
25819 Some(DialectType::TSQL) | Some(DialectType::Fabric) => {
25820 self.write_keyword("FLOAT")
25821 } Some(DialectType::Oracle) => self.write_keyword("DOUBLE PRECISION"),
25823 Some(DialectType::ClickHouse) => self.write_clickhouse_type("Float64"),
25824 Some(DialectType::BigQuery) => self.write_keyword("FLOAT64"),
25825 Some(DialectType::SQLite) => self.write_keyword("REAL"),
25826 Some(DialectType::PostgreSQL)
25827 | Some(DialectType::Redshift)
25828 | Some(DialectType::Teradata)
25829 | Some(DialectType::Materialize) => self.write_keyword("DOUBLE PRECISION"),
25830 _ => self.write_keyword("DOUBLE"),
25831 }
25832 if let Some(p) = precision {
25834 self.write(&format!("({}", p));
25835 if let Some(s) = scale {
25836 self.write(&format!(", {})", s));
25837 } else {
25838 self.write(")");
25839 }
25840 }
25841 }
25842 DataType::Decimal { precision, scale } => {
25843 match self.config.dialect {
25845 Some(DialectType::ClickHouse) => {
25846 self.write("Decimal");
25847 if let Some(p) = precision {
25848 self.write(&format!("({}", p));
25849 if let Some(s) = scale {
25850 self.write(&format!(", {}", s));
25851 }
25852 self.write(")");
25853 }
25854 }
25855 Some(DialectType::Oracle) => {
25856 self.write_keyword("NUMBER");
25858 if let Some(p) = precision {
25859 self.write(&format!("({}", p));
25860 if let Some(s) = scale {
25861 self.write(&format!(", {}", s));
25862 }
25863 self.write(")");
25864 }
25865 }
25866 Some(DialectType::BigQuery) => {
25867 self.write_keyword("NUMERIC");
25869 if let Some(p) = precision {
25870 self.write(&format!("({}", p));
25871 if let Some(s) = scale {
25872 self.write(&format!(", {}", s));
25873 }
25874 self.write(")");
25875 }
25876 }
25877 _ => {
25878 self.write_keyword("DECIMAL");
25879 if let Some(p) = precision {
25880 self.write(&format!("({}", p));
25881 if let Some(s) = scale {
25882 self.write(&format!(", {}", s));
25883 }
25884 self.write(")");
25885 }
25886 }
25887 }
25888 }
25889 DataType::Oracle { oracle_type } => {
25890 self.write_oracle_data_type(oracle_type)?;
25891 }
25892 DataType::Char { length } => {
25893 match self.config.dialect {
25895 Some(DialectType::DuckDB) | Some(DialectType::SQLite) => {
25896 self.write_keyword("TEXT");
25898 }
25899 Some(DialectType::Hive)
25900 | Some(DialectType::Spark)
25901 | Some(DialectType::Databricks) => {
25902 if length.is_some()
25905 && !matches!(self.config.dialect, Some(DialectType::Hive))
25906 {
25907 self.write_keyword("CHAR");
25908 if let Some(n) = length {
25909 self.write(&format!("({})", n));
25910 }
25911 } else {
25912 self.write_keyword("STRING");
25913 }
25914 }
25915 Some(DialectType::Dremio) => {
25916 self.write_keyword("VARCHAR");
25918 if let Some(n) = length {
25919 self.write(&format!("({})", n));
25920 }
25921 }
25922 _ => {
25923 self.write_keyword("CHAR");
25924 if let Some(n) = length {
25925 self.write(&format!("({})", n));
25926 }
25927 }
25928 }
25929 }
25930 DataType::VarChar {
25931 length,
25932 parenthesized_length,
25933 } => {
25934 match self.config.dialect {
25936 Some(DialectType::Oracle) => {
25937 self.write_keyword("VARCHAR2");
25938 if let Some(n) = length {
25939 self.write(&format!("({})", n));
25940 }
25941 }
25942 Some(DialectType::DuckDB) => {
25943 self.write_keyword("TEXT");
25945 if let Some(n) = length {
25946 self.write(&format!("({})", n));
25947 }
25948 }
25949 Some(DialectType::SQLite) => {
25950 self.write_keyword("TEXT");
25952 if let Some(n) = length {
25953 self.write(&format!("({})", n));
25954 }
25955 }
25956 Some(DialectType::MySQL) if length.is_none() => {
25957 self.write_keyword("TEXT");
25959 }
25960 Some(DialectType::Hive)
25961 | Some(DialectType::Spark)
25962 | Some(DialectType::Databricks)
25963 if length.is_none() =>
25964 {
25965 self.write_keyword("STRING");
25967 }
25968 _ => {
25969 self.write_keyword("VARCHAR");
25970 if let Some(n) = length {
25971 if *parenthesized_length {
25973 self.write(&format!("(({}))", n));
25974 } else {
25975 self.write(&format!("({})", n));
25976 }
25977 }
25978 }
25979 }
25980 }
25981 DataType::Text => {
25982 match self.config.dialect {
25984 Some(DialectType::Oracle) => self.write_keyword("CLOB"),
25985 Some(DialectType::TSQL) | Some(DialectType::Fabric) => {
25986 self.write_keyword("VARCHAR(MAX)")
25987 }
25988 Some(DialectType::BigQuery) => self.write_keyword("STRING"),
25989 Some(DialectType::Snowflake)
25990 | Some(DialectType::Dremio)
25991 | Some(DialectType::Drill) => self.write_keyword("VARCHAR"),
25992 Some(DialectType::Exasol) => self.write_keyword("LONG VARCHAR"),
25993 Some(DialectType::Presto)
25994 | Some(DialectType::Trino)
25995 | Some(DialectType::Athena) => self.write_keyword("VARCHAR"),
25996 Some(DialectType::Spark)
25997 | Some(DialectType::Databricks)
25998 | Some(DialectType::Hive) => self.write_keyword("STRING"),
25999 Some(DialectType::Redshift) => self.write_keyword("VARCHAR(MAX)"),
26000 Some(DialectType::StarRocks) | Some(DialectType::Doris) => {
26001 self.write_keyword("STRING")
26002 }
26003 Some(DialectType::ClickHouse) => self.write_clickhouse_type("String"),
26004 _ => self.write_keyword("TEXT"),
26005 }
26006 }
26007 DataType::TextWithLength { length } => {
26008 match self.config.dialect {
26010 Some(DialectType::Oracle) => self.write(&format!("CLOB({})", length)),
26011 Some(DialectType::Hive)
26012 | Some(DialectType::Spark)
26013 | Some(DialectType::Databricks) => {
26014 self.write(&format!("VARCHAR({})", length));
26015 }
26016 Some(DialectType::Redshift) => self.write(&format!("VARCHAR({})", length)),
26017 Some(DialectType::BigQuery) => self.write(&format!("STRING({})", length)),
26018 Some(DialectType::Snowflake)
26019 | Some(DialectType::Presto)
26020 | Some(DialectType::Trino)
26021 | Some(DialectType::Athena)
26022 | Some(DialectType::Drill)
26023 | Some(DialectType::Dremio) => {
26024 self.write(&format!("VARCHAR({})", length));
26025 }
26026 Some(DialectType::TSQL) | Some(DialectType::Fabric) => {
26027 self.write(&format!("VARCHAR({})", length))
26028 }
26029 Some(DialectType::StarRocks) | Some(DialectType::Doris) => {
26030 self.write(&format!("STRING({})", length))
26031 }
26032 Some(DialectType::ClickHouse) => self.write_clickhouse_type("String"),
26033 _ => self.write(&format!("TEXT({})", length)),
26034 }
26035 }
26036 DataType::String { length } => {
26037 match self.config.dialect {
26039 Some(DialectType::ClickHouse) => {
26040 self.write("String");
26042 if let Some(n) = length {
26043 self.write(&format!("({})", n));
26044 }
26045 }
26046 Some(DialectType::BigQuery)
26047 | Some(DialectType::Hive)
26048 | Some(DialectType::Spark)
26049 | Some(DialectType::Databricks)
26050 | Some(DialectType::StarRocks)
26051 | Some(DialectType::Doris) => {
26052 self.write_keyword("STRING");
26053 if let Some(n) = length {
26054 self.write(&format!("({})", n));
26055 }
26056 }
26057 Some(DialectType::PostgreSQL) => {
26058 if let Some(n) = length {
26060 self.write_keyword("VARCHAR");
26061 self.write(&format!("({})", n));
26062 } else {
26063 self.write_keyword("TEXT");
26064 }
26065 }
26066 Some(DialectType::Redshift) => {
26067 if let Some(n) = length {
26069 self.write_keyword("VARCHAR");
26070 self.write(&format!("({})", n));
26071 } else {
26072 self.write_keyword("VARCHAR(MAX)");
26073 }
26074 }
26075 Some(DialectType::MySQL) => {
26076 if let Some(n) = length {
26078 self.write_keyword("VARCHAR");
26079 self.write(&format!("({})", n));
26080 } else {
26081 self.write_keyword("TEXT");
26082 }
26083 }
26084 Some(DialectType::TSQL) | Some(DialectType::Fabric) => {
26085 if let Some(n) = length {
26087 self.write_keyword("VARCHAR");
26088 self.write(&format!("({})", n));
26089 } else {
26090 self.write_keyword("VARCHAR(MAX)");
26091 }
26092 }
26093 Some(DialectType::Oracle) => {
26094 self.write_keyword("CLOB");
26096 }
26097 Some(DialectType::DuckDB) | Some(DialectType::Materialize) => {
26098 self.write_keyword("TEXT");
26100 if let Some(n) = length {
26101 self.write(&format!("({})", n));
26102 }
26103 }
26104 Some(DialectType::Presto)
26105 | Some(DialectType::Trino)
26106 | Some(DialectType::Drill)
26107 | Some(DialectType::Dremio) => {
26108 self.write_keyword("VARCHAR");
26110 if let Some(n) = length {
26111 self.write(&format!("({})", n));
26112 }
26113 }
26114 Some(DialectType::Snowflake) => {
26115 self.write_keyword("STRING");
26118 if let Some(n) = length {
26119 self.write(&format!("({})", n));
26120 }
26121 }
26122 _ => {
26123 self.write_keyword("STRING");
26125 if let Some(n) = length {
26126 self.write(&format!("({})", n));
26127 }
26128 }
26129 }
26130 }
26131 DataType::Binary { length } => {
26132 match self.config.dialect {
26134 Some(DialectType::PostgreSQL) | Some(DialectType::Materialize) => {
26135 self.write_keyword("BYTEA");
26136 if let Some(n) = length {
26137 self.write(&format!("({})", n));
26138 }
26139 }
26140 Some(DialectType::Redshift) => {
26141 self.write_keyword("VARBYTE");
26142 if let Some(n) = length {
26143 self.write(&format!("({})", n));
26144 }
26145 }
26146 Some(DialectType::DuckDB)
26147 | Some(DialectType::SQLite)
26148 | Some(DialectType::Oracle) => {
26149 self.write_keyword("BLOB");
26151 if let Some(n) = length {
26152 self.write(&format!("({})", n));
26153 }
26154 }
26155 Some(DialectType::Presto)
26156 | Some(DialectType::Trino)
26157 | Some(DialectType::Athena)
26158 | Some(DialectType::Drill)
26159 | Some(DialectType::Dremio) => {
26160 self.write_keyword("VARBINARY");
26162 if let Some(n) = length {
26163 self.write(&format!("({})", n));
26164 }
26165 }
26166 Some(DialectType::ClickHouse) => {
26167 if self.clickhouse_nullable_depth < 0 {
26169 self.write("BINARY");
26170 } else {
26171 self.write("Nullable(BINARY");
26172 }
26173 if let Some(n) = length {
26174 self.write(&format!("({})", n));
26175 }
26176 if self.clickhouse_nullable_depth >= 0 {
26177 self.write(")");
26178 }
26179 }
26180 _ => {
26181 self.write_keyword("BINARY");
26182 if let Some(n) = length {
26183 self.write(&format!("({})", n));
26184 }
26185 }
26186 }
26187 }
26188 DataType::VarBinary { length } => {
26189 match self.config.dialect {
26191 Some(DialectType::PostgreSQL) | Some(DialectType::Materialize) => {
26192 self.write_keyword("BYTEA");
26193 if let Some(n) = length {
26194 self.write(&format!("({})", n));
26195 }
26196 }
26197 Some(DialectType::Redshift) => {
26198 self.write_keyword("VARBYTE");
26199 if let Some(n) = length {
26200 self.write(&format!("({})", n));
26201 }
26202 }
26203 Some(DialectType::DuckDB)
26204 | Some(DialectType::SQLite)
26205 | Some(DialectType::Oracle) => {
26206 self.write_keyword("BLOB");
26208 if let Some(n) = length {
26209 self.write(&format!("({})", n));
26210 }
26211 }
26212 Some(DialectType::Exasol) => {
26213 self.write_keyword("VARCHAR");
26215 }
26216 Some(DialectType::Spark)
26217 | Some(DialectType::Hive)
26218 | Some(DialectType::Databricks) => {
26219 self.write_keyword("BINARY");
26221 if let Some(n) = length {
26222 self.write(&format!("({})", n));
26223 }
26224 }
26225 Some(DialectType::ClickHouse) => {
26226 self.write_clickhouse_type("String");
26228 }
26229 _ => {
26230 self.write_keyword("VARBINARY");
26231 if let Some(n) = length {
26232 self.write(&format!("({})", n));
26233 }
26234 }
26235 }
26236 }
26237 DataType::Blob => {
26238 match self.config.dialect {
26240 Some(DialectType::PostgreSQL) => self.write_keyword("BYTEA"),
26241 Some(DialectType::Redshift) => self.write_keyword("VARBYTE"),
26242 Some(DialectType::TSQL) | Some(DialectType::Fabric) => {
26243 self.write_keyword("VARBINARY")
26244 }
26245 Some(DialectType::BigQuery) => self.write_keyword("BYTES"),
26246 Some(DialectType::Exasol) => self.write_keyword("VARCHAR"),
26247 Some(DialectType::Presto)
26248 | Some(DialectType::Trino)
26249 | Some(DialectType::Athena) => self.write_keyword("VARBINARY"),
26250 Some(DialectType::DuckDB) => {
26251 self.write_keyword("VARBINARY");
26254 }
26255 Some(DialectType::Spark)
26256 | Some(DialectType::Databricks)
26257 | Some(DialectType::Hive) => self.write_keyword("BINARY"),
26258 Some(DialectType::ClickHouse) => {
26259 self.write("Nullable(String)");
26263 }
26264 _ => self.write_keyword("BLOB"),
26265 }
26266 }
26267 DataType::Bit { length } => {
26268 match self.config.dialect {
26270 Some(DialectType::Dremio)
26271 | Some(DialectType::Spark)
26272 | Some(DialectType::Databricks)
26273 | Some(DialectType::Hive)
26274 | Some(DialectType::Snowflake)
26275 | Some(DialectType::BigQuery)
26276 | Some(DialectType::Presto)
26277 | Some(DialectType::Trino)
26278 | Some(DialectType::ClickHouse)
26279 | Some(DialectType::Redshift) => {
26280 self.write_keyword("BOOLEAN");
26282 }
26283 _ => {
26284 self.write_keyword("BIT");
26285 if let Some(n) = length {
26286 self.write(&format!("({})", n));
26287 }
26288 }
26289 }
26290 }
26291 DataType::VarBit { length } => {
26292 self.write_keyword("VARBIT");
26293 if let Some(n) = length {
26294 self.write(&format!("({})", n));
26295 }
26296 }
26297 DataType::Date => self.write_keyword("DATE"),
26298 DataType::Time {
26299 precision,
26300 timezone,
26301 } => {
26302 if *timezone {
26303 match self.config.dialect {
26305 Some(DialectType::DuckDB) => {
26306 self.write_keyword("TIMETZ");
26308 }
26309 Some(DialectType::PostgreSQL) => {
26310 self.write_keyword("TIMETZ");
26312 if let Some(p) = precision {
26313 self.write(&format!("({})", p));
26314 }
26315 }
26316 _ => {
26317 self.write_keyword("TIME");
26319 if let Some(p) = precision {
26320 self.write(&format!("({})", p));
26321 }
26322 self.write_keyword(" WITH TIME ZONE");
26323 }
26324 }
26325 } else {
26326 if matches!(
26328 self.config.dialect,
26329 Some(DialectType::Spark)
26330 | Some(DialectType::Databricks)
26331 | Some(DialectType::Hive)
26332 ) {
26333 self.write_keyword("TIMESTAMP");
26334 } else {
26335 self.write_keyword("TIME");
26336 if let Some(p) = precision {
26337 self.write(&format!("({})", p));
26338 }
26339 }
26340 }
26341 }
26342 DataType::Timestamp {
26343 precision,
26344 timezone,
26345 } => {
26346 match self.config.dialect {
26348 Some(DialectType::Snowflake) if *timezone => {
26349 self.write_keyword("TIMESTAMPTZ");
26350 if let Some(p) = precision {
26351 self.write(&format!("({})", p));
26352 }
26353 }
26354 Some(DialectType::ClickHouse) => {
26355 self.write("DateTime");
26356 if let Some(p) = precision {
26357 self.write(&format!("({})", p));
26358 }
26359 }
26360 Some(DialectType::TSQL) => {
26361 if *timezone {
26362 self.write_keyword("DATETIMEOFFSET");
26363 } else {
26364 self.write_keyword("DATETIME2");
26365 }
26366 if let Some(p) = precision {
26367 self.write(&format!("({})", p));
26368 }
26369 }
26370 Some(DialectType::MySQL) => {
26371 self.write_keyword("TIMESTAMP");
26373 if let Some(p) = precision {
26374 self.write(&format!("({})", p));
26375 }
26376 }
26377 Some(DialectType::Doris) | Some(DialectType::StarRocks) => {
26378 self.write_keyword("DATETIME");
26380 if let Some(p) = precision {
26381 self.write(&format!("({})", p));
26382 }
26383 }
26384 Some(DialectType::BigQuery) => {
26385 if *timezone {
26387 self.write_keyword("TIMESTAMP");
26388 } else {
26389 self.write_keyword("DATETIME");
26390 }
26391 }
26392 Some(DialectType::DuckDB) => {
26393 if *timezone {
26395 self.write_keyword("TIMESTAMPTZ");
26396 } else {
26397 self.write_keyword("TIMESTAMP");
26398 if let Some(p) = precision {
26399 self.write(&format!("({})", p));
26400 }
26401 }
26402 }
26403 _ => {
26404 if *timezone && !self.config.tz_to_with_time_zone {
26405 self.write_keyword("TIMESTAMPTZ");
26407 if let Some(p) = precision {
26408 self.write(&format!("({})", p));
26409 }
26410 } else {
26411 self.write_keyword("TIMESTAMP");
26412 if let Some(p) = precision {
26413 self.write(&format!("({})", p));
26414 }
26415 if *timezone {
26416 self.write_space();
26417 self.write_keyword("WITH TIME ZONE");
26418 }
26419 }
26420 }
26421 }
26422 }
26423 DataType::Interval { unit, to } => {
26424 self.write_keyword("INTERVAL");
26425 if let Some(u) = unit {
26426 self.write_space();
26427 self.write_keyword(u);
26428 }
26429 if let Some(t) = to {
26431 self.write_space();
26432 self.write_keyword("TO");
26433 self.write_space();
26434 self.write_keyword(t);
26435 }
26436 }
26437 DataType::Json => {
26438 match self.config.dialect {
26440 Some(DialectType::Oracle) => self.write_keyword("JSON"), Some(DialectType::TSQL) => self.write_keyword("NVARCHAR(MAX)"), Some(DialectType::MySQL) => self.write_keyword("JSON"),
26443 Some(DialectType::Snowflake) => self.write_keyword("VARIANT"),
26444 _ => self.write_keyword("JSON"),
26445 }
26446 }
26447 DataType::JsonB => {
26448 match self.config.dialect {
26450 Some(DialectType::PostgreSQL) => self.write_keyword("JSONB"),
26451 Some(DialectType::Doris) => self.write_keyword("JSONB"),
26452 Some(DialectType::Snowflake) => self.write_keyword("VARIANT"),
26453 Some(DialectType::TSQL) => self.write_keyword("NVARCHAR(MAX)"),
26454 Some(DialectType::DuckDB) => self.write_keyword("JSON"), _ => self.write_keyword("JSON"), }
26457 }
26458 DataType::Uuid => {
26459 match self.config.dialect {
26461 Some(DialectType::TSQL) => self.write_keyword("UNIQUEIDENTIFIER"),
26462 Some(DialectType::MySQL) => self.write_keyword("CHAR(36)"),
26463 Some(DialectType::Oracle) => self.write_keyword("RAW(16)"),
26464 Some(DialectType::BigQuery)
26465 | Some(DialectType::Spark)
26466 | Some(DialectType::Databricks) => self.write_keyword("STRING"),
26467 _ => self.write_keyword("UUID"),
26468 }
26469 }
26470 DataType::Array {
26471 element_type,
26472 dimension,
26473 } => {
26474 match self.config.dialect {
26476 Some(DialectType::PostgreSQL)
26477 | Some(DialectType::Redshift)
26478 | Some(DialectType::DuckDB) => {
26479 self.generate_data_type(element_type)?;
26481 if let Some(dim) = dimension {
26482 self.write(&format!("[{}]", dim));
26483 } else {
26484 self.write("[]");
26485 }
26486 }
26487 Some(DialectType::BigQuery) => {
26488 self.write_keyword("ARRAY<");
26489 self.generate_data_type(element_type)?;
26490 self.write(">");
26491 }
26492 Some(DialectType::Snowflake)
26493 | Some(DialectType::Presto)
26494 | Some(DialectType::Trino)
26495 | Some(DialectType::ClickHouse) => {
26496 if matches!(self.config.dialect, Some(DialectType::ClickHouse)) {
26498 self.write("Array(");
26499 } else {
26500 self.write_keyword("ARRAY(");
26501 }
26502 self.generate_data_type(element_type)?;
26503 self.write(")");
26504 }
26505 Some(DialectType::TSQL)
26506 | Some(DialectType::MySQL)
26507 | Some(DialectType::Oracle) => {
26508 match self.config.dialect {
26511 Some(DialectType::MySQL) => self.write_keyword("JSON"),
26512 Some(DialectType::TSQL) => self.write_keyword("NVARCHAR(MAX)"),
26513 _ => self.write_keyword("JSON"),
26514 }
26515 }
26516 _ => {
26517 self.write_keyword("ARRAY<");
26519 self.generate_data_type(element_type)?;
26520 self.write(">");
26521 }
26522 }
26523 }
26524 DataType::List { element_type } => {
26525 self.generate_data_type(element_type)?;
26527 self.write_keyword(" LIST");
26528 }
26529 DataType::Map {
26530 key_type,
26531 value_type,
26532 } => {
26533 match self.config.dialect {
26535 Some(DialectType::Materialize) => {
26536 self.write_keyword("MAP[");
26538 self.generate_data_type(key_type)?;
26539 self.write(" => ");
26540 self.generate_data_type(value_type)?;
26541 self.write("]");
26542 }
26543 Some(DialectType::Snowflake)
26544 | Some(DialectType::RisingWave)
26545 | Some(DialectType::DuckDB)
26546 | Some(DialectType::Presto)
26547 | Some(DialectType::Trino)
26548 | Some(DialectType::Athena) => {
26549 self.write_keyword("MAP(");
26550 self.generate_data_type(key_type)?;
26551 self.write(", ");
26552 self.generate_data_type(value_type)?;
26553 self.write(")");
26554 }
26555 Some(DialectType::ClickHouse) => {
26556 self.write("Map(");
26559 self.clickhouse_nullable_depth = -1; self.generate_data_type(key_type)?;
26561 self.clickhouse_nullable_depth = 0;
26562 self.write(", ");
26563 self.generate_data_type(value_type)?;
26564 self.write(")");
26565 }
26566 _ => {
26567 self.write_keyword("MAP<");
26568 self.generate_data_type(key_type)?;
26569 self.write(", ");
26570 self.generate_data_type(value_type)?;
26571 self.write(">");
26572 }
26573 }
26574 }
26575 DataType::Vector {
26576 element_type,
26577 dimension,
26578 } => {
26579 if matches!(self.config.dialect, Some(DialectType::SingleStore)) {
26580 self.write_keyword("VECTOR(");
26582 if let Some(dim) = dimension {
26583 self.write(&dim.to_string());
26584 }
26585 let type_alias = element_type.as_ref().and_then(|et| match et.as_ref() {
26587 DataType::TinyInt { .. } => Some("I8"),
26588 DataType::SmallInt { .. } => Some("I16"),
26589 DataType::Int { .. } => Some("I32"),
26590 DataType::BigInt { .. } => Some("I64"),
26591 DataType::Float { .. } => Some("F32"),
26592 DataType::Double { .. } => Some("F64"),
26593 _ => None,
26594 });
26595 if let Some(alias) = type_alias {
26596 if dimension.is_some() {
26597 self.write(", ");
26598 }
26599 self.write(alias);
26600 }
26601 self.write(")");
26602 } else {
26603 self.write_keyword("VECTOR(");
26605 if let Some(ref et) = element_type {
26606 self.generate_data_type(et)?;
26607 if dimension.is_some() {
26608 self.write(", ");
26609 }
26610 }
26611 if let Some(dim) = dimension {
26612 self.write(&dim.to_string());
26613 }
26614 self.write(")");
26615 }
26616 }
26617 DataType::Object { fields, modifier } => {
26618 self.write_keyword("OBJECT(");
26619 for (i, (name, dt, not_null)) in fields.iter().enumerate() {
26620 if i > 0 {
26621 self.write(", ");
26622 }
26623 self.write(name);
26624 self.write(" ");
26625 self.generate_data_type(dt)?;
26626 if *not_null {
26627 self.write_keyword(" NOT NULL");
26628 }
26629 }
26630 self.write(")");
26631 if let Some(mod_str) = modifier {
26632 self.write(" ");
26633 self.write_keyword(mod_str);
26634 }
26635 }
26636 DataType::Struct { fields, nested } => {
26637 match self.config.dialect {
26639 Some(DialectType::Snowflake) => {
26640 self.write_keyword("OBJECT(");
26642 for (i, field) in fields.iter().enumerate() {
26643 if i > 0 {
26644 self.write(", ");
26645 }
26646 if !field.name.is_empty() {
26647 self.write(&field.name);
26648 self.write(" ");
26649 }
26650 self.generate_data_type(&field.data_type)?;
26651 }
26652 self.write(")");
26653 }
26654 Some(DialectType::Presto) | Some(DialectType::Trino) => {
26655 self.write_keyword("ROW(");
26657 for (i, field) in fields.iter().enumerate() {
26658 if i > 0 {
26659 self.write(", ");
26660 }
26661 if !field.name.is_empty() {
26662 self.write(&field.name);
26663 self.write(" ");
26664 }
26665 self.generate_data_type(&field.data_type)?;
26666 }
26667 self.write(")");
26668 }
26669 Some(DialectType::DuckDB) => {
26670 self.write_keyword("STRUCT(");
26672 for (i, field) in fields.iter().enumerate() {
26673 if i > 0 {
26674 self.write(", ");
26675 }
26676 if !field.name.is_empty() {
26677 self.write(&field.name);
26678 self.write(" ");
26679 }
26680 self.generate_data_type(&field.data_type)?;
26681 }
26682 self.write(")");
26683 }
26684 Some(DialectType::ClickHouse) => {
26685 self.write("Tuple(");
26687 for (i, field) in fields.iter().enumerate() {
26688 if i > 0 {
26689 self.write(", ");
26690 }
26691 if !field.name.is_empty() {
26692 self.write(&field.name);
26693 self.write(" ");
26694 }
26695 self.generate_data_type(&field.data_type)?;
26696 }
26697 self.write(")");
26698 }
26699 Some(DialectType::SingleStore) => {
26700 self.write_keyword("RECORD(");
26702 for (i, field) in fields.iter().enumerate() {
26703 if i > 0 {
26704 self.write(", ");
26705 }
26706 if !field.name.is_empty() {
26707 self.write(&field.name);
26708 self.write(" ");
26709 }
26710 self.generate_data_type(&field.data_type)?;
26711 }
26712 self.write(")");
26713 }
26714 _ => {
26715 let force_angle_brackets = matches!(
26717 self.config.dialect,
26718 Some(DialectType::Hive)
26719 | Some(DialectType::Spark)
26720 | Some(DialectType::Databricks)
26721 );
26722 if *nested && !force_angle_brackets {
26723 self.write_keyword("STRUCT(");
26724 for (i, field) in fields.iter().enumerate() {
26725 if i > 0 {
26726 self.write(", ");
26727 }
26728 if !field.name.is_empty() {
26729 self.write(&field.name);
26730 self.write(" ");
26731 }
26732 self.generate_data_type(&field.data_type)?;
26733 }
26734 self.write(")");
26735 } else {
26736 self.write_keyword("STRUCT<");
26737 for (i, field) in fields.iter().enumerate() {
26738 if i > 0 {
26739 self.write(", ");
26740 }
26741 if !field.name.is_empty() {
26742 self.write(&field.name);
26744 self.write(self.config.struct_field_sep);
26745 }
26746 self.generate_data_type(&field.data_type)?;
26748 if let Some(comment) = &field.comment {
26750 self.write(" COMMENT '");
26751 self.write(comment);
26752 self.write("'");
26753 }
26754 if !field.options.is_empty() {
26756 self.write(" ");
26757 self.generate_options_clause(&field.options)?;
26758 }
26759 }
26760 self.write(">");
26761 }
26762 }
26763 }
26764 }
26765 DataType::Enum {
26766 values,
26767 assignments,
26768 } => {
26769 if self.config.dialect == Some(DialectType::ClickHouse) {
26772 self.write("Enum(");
26773 } else {
26774 self.write_keyword("ENUM(");
26775 }
26776 for (i, val) in values.iter().enumerate() {
26777 if i > 0 {
26778 self.write(", ");
26779 }
26780 self.write("'");
26781 self.write(val);
26782 self.write("'");
26783 if let Some(Some(assignment)) = assignments.get(i) {
26784 self.write(" = ");
26785 self.write(assignment);
26786 }
26787 }
26788 self.write(")");
26789 }
26790 DataType::Set { values } => {
26791 self.write_keyword("SET(");
26793 for (i, val) in values.iter().enumerate() {
26794 if i > 0 {
26795 self.write(", ");
26796 }
26797 self.write("'");
26798 self.write(val);
26799 self.write("'");
26800 }
26801 self.write(")");
26802 }
26803 DataType::Union { fields } => {
26804 self.write_keyword("UNION(");
26806 for (i, (name, dt)) in fields.iter().enumerate() {
26807 if i > 0 {
26808 self.write(", ");
26809 }
26810 if !name.is_empty() {
26811 self.write(name);
26812 self.write(" ");
26813 }
26814 self.generate_data_type(dt)?;
26815 }
26816 self.write(")");
26817 }
26818 DataType::Nullable { inner } => {
26819 if matches!(self.config.dialect, Some(DialectType::ClickHouse)) {
26821 self.write("Nullable(");
26822 let saved_depth = self.clickhouse_nullable_depth;
26824 self.clickhouse_nullable_depth = -1;
26825 self.generate_data_type(inner)?;
26826 self.clickhouse_nullable_depth = saved_depth;
26827 self.write(")");
26828 } else {
26829 match inner.as_ref() {
26831 DataType::Custom { name } if name.eq_ignore_ascii_case("DATETIME") => {
26832 self.generate_data_type(&DataType::Timestamp {
26833 precision: None,
26834 timezone: false,
26835 })?;
26836 }
26837 _ => {
26838 self.generate_data_type(inner)?;
26839 }
26840 }
26841 }
26842 }
26843 DataType::Custom { name } => {
26844 let name_upper = name.to_ascii_uppercase();
26846 match self.config.dialect {
26847 Some(DialectType::ClickHouse) => {
26848 let (base_upper, suffix) = if let Some(idx) = name.find('(') {
26849 (name_upper[..idx].to_string(), &name[idx..])
26850 } else {
26851 (name_upper.clone(), "")
26852 };
26853 let mapped = match base_upper.as_str() {
26854 "DATETIME" | "TIMESTAMPTZ" | "TIMESTAMP" | "TIMESTAMPNTZ"
26855 | "SMALLDATETIME" | "DATETIME2" => "DateTime",
26856 "DATETIME64" => "DateTime64",
26857 "DATE32" => "Date32",
26858 "INT" => "Int32",
26859 "MEDIUMINT" => "Int32",
26860 "INT8" => "Int8",
26861 "INT16" => "Int16",
26862 "INT32" => "Int32",
26863 "INT64" => "Int64",
26864 "INT128" => "Int128",
26865 "INT256" => "Int256",
26866 "UINT8" => "UInt8",
26867 "UINT16" => "UInt16",
26868 "UINT32" => "UInt32",
26869 "UINT64" => "UInt64",
26870 "UINT128" => "UInt128",
26871 "UINT256" => "UInt256",
26872 "FLOAT32" => "Float32",
26873 "FLOAT64" => "Float64",
26874 "DECIMAL32" => "Decimal32",
26875 "DECIMAL64" => "Decimal64",
26876 "DECIMAL128" => "Decimal128",
26877 "DECIMAL256" => "Decimal256",
26878 "ENUM" => "Enum",
26879 "ENUM8" => "Enum8",
26880 "ENUM16" => "Enum16",
26881 "FIXEDSTRING" => "FixedString",
26882 "NESTED" => "Nested",
26883 "LOWCARDINALITY" => "LowCardinality",
26884 "NULLABLE" => "Nullable",
26885 "IPV4" => "IPv4",
26886 "IPV6" => "IPv6",
26887 "POINT" => "Point",
26888 "RING" => "Ring",
26889 "LINESTRING" => "LineString",
26890 "MULTILINESTRING" => "MultiLineString",
26891 "POLYGON" => "Polygon",
26892 "MULTIPOLYGON" => "MultiPolygon",
26893 "AGGREGATEFUNCTION" => "AggregateFunction",
26894 "SIMPLEAGGREGATEFUNCTION" => "SimpleAggregateFunction",
26895 "DYNAMIC" => "Dynamic",
26896 _ => "",
26897 };
26898 if mapped.is_empty() {
26899 self.write(name);
26900 } else {
26901 self.write(mapped);
26902 if matches!(base_upper.as_str(), "ENUM8" | "ENUM16")
26903 && !suffix.is_empty()
26904 {
26905 let escaped_suffix = suffix
26906 .replace('\\', "\\\\")
26907 .replace('\t', "\\t")
26908 .replace('\n', "\\n")
26909 .replace('\r', "\\r");
26910 self.write(&escaped_suffix);
26911 } else {
26912 self.write(suffix);
26913 }
26914 }
26915 }
26916 Some(DialectType::MySQL)
26917 if name_upper == "TIMESTAMPTZ" || name_upper == "TIMESTAMPLTZ" =>
26918 {
26919 self.write_keyword("TIMESTAMP");
26921 }
26922 Some(DialectType::Snowflake) => {
26923 let (base_upper, suffix) = if let Some(idx) = name.find('(') {
26924 (name_upper[..idx].to_string(), &name[idx..])
26925 } else {
26926 (name_upper.clone(), "")
26927 };
26928
26929 match base_upper.as_str() {
26930 "TIMESTAMPNTZ" | "TIMESTAMP_NTZ" => {
26931 self.write_keyword("TIMESTAMPNTZ");
26932 self.write(suffix);
26933 }
26934 "TIMESTAMPLTZ" | "TIMESTAMP_LTZ" => {
26935 self.write_keyword("TIMESTAMPLTZ");
26936 self.write(suffix);
26937 }
26938 "TIMESTAMPTZ" | "TIMESTAMP_TZ" => {
26939 self.write_keyword("TIMESTAMPTZ");
26940 self.write(suffix);
26941 }
26942 _ => self.write(name),
26943 }
26944 }
26945 Some(DialectType::Fabric) => {
26946 let (base_upper, args_str) = if let Some(idx) = name.find('(') {
26947 (name_upper[..idx].to_string(), Some(&name[idx..]))
26948 } else {
26949 (name_upper.clone(), None)
26950 };
26951
26952 match base_upper.as_str() {
26953 "NVARCHAR" => {
26954 self.write_keyword("VARCHAR");
26955 if let Some(args) = args_str {
26956 self.write(args);
26957 }
26958 }
26959 "NCHAR" => {
26960 self.write_keyword("CHAR");
26961 if let Some(args) = args_str {
26962 self.write(args);
26963 }
26964 }
26965 _ => self.write(name),
26966 }
26967 }
26968 Some(DialectType::TSQL) if name_upper == "VARIANT" => {
26969 self.write_keyword("SQL_VARIANT");
26970 }
26971 Some(DialectType::DuckDB) if name_upper == "DECFLOAT" => {
26972 self.write_keyword("DECIMAL(38, 5)");
26973 }
26974 Some(DialectType::Exasol) => {
26975 match name_upper.as_str() {
26977 "LONGBLOB" | "MEDIUMBLOB" | "TINYBLOB" => self.write_keyword("VARCHAR"),
26979 "LONGTEXT" | "MEDIUMTEXT" | "TINYTEXT" => self.write_keyword("VARCHAR"),
26981 "MEDIUMINT" => self.write_keyword("INT"),
26983 "DECIMAL32" | "DECIMAL64" | "DECIMAL128" | "DECIMAL256" => {
26985 self.write_keyword("DECIMAL")
26986 }
26987 "DATETIME" => self.write_keyword("TIMESTAMP"),
26989 "TIMESTAMPLTZ" => self.write_keyword("TIMESTAMP WITH LOCAL TIME ZONE"),
26990 _ => self.write(name),
26991 }
26992 }
26993 Some(DialectType::Dremio) => {
26994 match name_upper.as_str() {
26996 "TIMESTAMPNTZ" | "DATETIME" => self.write_keyword("TIMESTAMP"),
26997 "ARRAY" => self.write_keyword("LIST"),
26998 "NCHAR" => self.write_keyword("VARCHAR"),
26999 _ => self.write(name),
27000 }
27001 }
27002 _ => {
27004 let (base_upper, _args_str) = if let Some(idx) = name_upper.find('(') {
27006 (name_upper[..idx].to_string(), Some(&name[idx..]))
27007 } else {
27008 (name_upper.clone(), None)
27009 };
27010
27011 match base_upper.as_str() {
27012 "INT64"
27013 if !matches!(self.config.dialect, Some(DialectType::BigQuery)) =>
27014 {
27015 self.write_keyword("BIGINT");
27016 }
27017 "FLOAT64"
27018 if !matches!(self.config.dialect, Some(DialectType::BigQuery)) =>
27019 {
27020 self.write_keyword("DOUBLE");
27021 }
27022 "BOOL"
27023 if !matches!(self.config.dialect, Some(DialectType::BigQuery)) =>
27024 {
27025 self.write_keyword("BOOLEAN");
27026 }
27027 "BYTES"
27028 if matches!(
27029 self.config.dialect,
27030 Some(DialectType::Spark)
27031 | Some(DialectType::Hive)
27032 | Some(DialectType::Databricks)
27033 ) =>
27034 {
27035 self.write_keyword("BINARY");
27036 }
27037 "BYTES"
27038 if !matches!(self.config.dialect, Some(DialectType::BigQuery)) =>
27039 {
27040 self.write_keyword("VARBINARY");
27041 }
27042 "DATETIME2" | "SMALLDATETIME"
27044 if !matches!(
27045 self.config.dialect,
27046 Some(DialectType::TSQL) | Some(DialectType::Fabric)
27047 ) =>
27048 {
27049 if matches!(
27051 self.config.dialect,
27052 Some(DialectType::PostgreSQL) | Some(DialectType::Redshift)
27053 ) {
27054 self.write_keyword("TIMESTAMP");
27055 if let Some(args) = _args_str {
27056 self.write(args);
27057 }
27058 } else {
27059 self.write_keyword("TIMESTAMP");
27060 }
27061 }
27062 "DATETIMEOFFSET"
27064 if !matches!(
27065 self.config.dialect,
27066 Some(DialectType::TSQL) | Some(DialectType::Fabric)
27067 ) =>
27068 {
27069 if matches!(
27070 self.config.dialect,
27071 Some(DialectType::PostgreSQL) | Some(DialectType::Redshift)
27072 ) {
27073 self.write_keyword("TIMESTAMPTZ");
27074 if let Some(args) = _args_str {
27075 self.write(args);
27076 }
27077 } else {
27078 self.write_keyword("TIMESTAMPTZ");
27079 }
27080 }
27081 "UNIQUEIDENTIFIER"
27083 if !matches!(
27084 self.config.dialect,
27085 Some(DialectType::TSQL) | Some(DialectType::Fabric)
27086 ) =>
27087 {
27088 match self.config.dialect {
27089 Some(DialectType::Spark)
27090 | Some(DialectType::Databricks)
27091 | Some(DialectType::Hive) => self.write_keyword("STRING"),
27092 _ => self.write_keyword("UUID"),
27093 }
27094 }
27095 "BIT"
27097 if !matches!(
27098 self.config.dialect,
27099 Some(DialectType::TSQL)
27100 | Some(DialectType::Fabric)
27101 | Some(DialectType::PostgreSQL)
27102 | Some(DialectType::MySQL)
27103 | Some(DialectType::DuckDB)
27104 ) =>
27105 {
27106 self.write_keyword("BOOLEAN");
27107 }
27108 "NVARCHAR"
27110 if !matches!(
27111 self.config.dialect,
27112 Some(DialectType::TSQL) | Some(DialectType::Fabric)
27113 ) =>
27114 {
27115 match self.config.dialect {
27116 Some(DialectType::Oracle) => {
27117 self.write_keyword("NVARCHAR2");
27119 if let Some(args) = _args_str {
27120 self.write(args);
27121 }
27122 }
27123 Some(DialectType::BigQuery) => {
27124 self.write_keyword("STRING");
27126 }
27127 Some(DialectType::SQLite) | Some(DialectType::DuckDB) => {
27128 self.write_keyword("TEXT");
27129 if let Some(args) = _args_str {
27130 self.write(args);
27131 }
27132 }
27133 Some(DialectType::Hive) => {
27134 self.write_keyword("STRING");
27136 }
27137 Some(DialectType::Spark) | Some(DialectType::Databricks) => {
27138 if _args_str.is_some() {
27139 self.write_keyword("VARCHAR");
27140 self.write(_args_str.unwrap());
27141 } else {
27142 self.write_keyword("STRING");
27143 }
27144 }
27145 _ => {
27146 self.write_keyword("VARCHAR");
27147 if let Some(args) = _args_str {
27148 self.write(args);
27149 }
27150 }
27151 }
27152 }
27153 "NCHAR"
27155 if !matches!(
27156 self.config.dialect,
27157 Some(DialectType::TSQL) | Some(DialectType::Fabric)
27158 ) =>
27159 {
27160 match self.config.dialect {
27161 Some(DialectType::Oracle) => {
27162 self.write_keyword("NCHAR");
27164 if let Some(args) = _args_str {
27165 self.write(args);
27166 }
27167 }
27168 Some(DialectType::BigQuery) => {
27169 self.write_keyword("STRING");
27171 }
27172 Some(DialectType::Hive) => {
27173 self.write_keyword("STRING");
27175 }
27176 Some(DialectType::SQLite) | Some(DialectType::DuckDB) => {
27177 self.write_keyword("TEXT");
27178 if let Some(args) = _args_str {
27179 self.write(args);
27180 }
27181 }
27182 Some(DialectType::Spark) | Some(DialectType::Databricks) => {
27183 if _args_str.is_some() {
27184 self.write_keyword("CHAR");
27185 self.write(_args_str.unwrap());
27186 } else {
27187 self.write_keyword("STRING");
27188 }
27189 }
27190 _ => {
27191 self.write_keyword("CHAR");
27192 if let Some(args) = _args_str {
27193 self.write(args);
27194 }
27195 }
27196 }
27197 }
27198 "LONGTEXT" | "MEDIUMTEXT" | "TINYTEXT" => match self.config.dialect {
27201 Some(DialectType::MySQL)
27202 | Some(DialectType::SingleStore)
27203 | Some(DialectType::TiDB) => self.write_keyword(&base_upper),
27204 Some(DialectType::Spark)
27205 | Some(DialectType::Databricks)
27206 | Some(DialectType::Hive) => self.write_keyword("TEXT"),
27207 Some(DialectType::BigQuery) => self.write_keyword("STRING"),
27208 Some(DialectType::Presto)
27209 | Some(DialectType::Trino)
27210 | Some(DialectType::Athena) => self.write_keyword("VARCHAR"),
27211 Some(DialectType::Snowflake)
27212 | Some(DialectType::Redshift)
27213 | Some(DialectType::Dremio) => self.write_keyword("VARCHAR"),
27214 _ => self.write_keyword("TEXT"),
27215 },
27216 "LONGBLOB" | "MEDIUMBLOB" | "TINYBLOB" => match self.config.dialect {
27219 Some(DialectType::MySQL)
27220 | Some(DialectType::SingleStore)
27221 | Some(DialectType::TiDB) => self.write_keyword(&base_upper),
27222 Some(DialectType::Spark)
27223 | Some(DialectType::Databricks)
27224 | Some(DialectType::Hive) => self.write_keyword("BLOB"),
27225 Some(DialectType::DuckDB) => self.write_keyword("VARBINARY"),
27226 Some(DialectType::BigQuery) => self.write_keyword("BYTES"),
27227 Some(DialectType::Presto)
27228 | Some(DialectType::Trino)
27229 | Some(DialectType::Athena) => self.write_keyword("VARBINARY"),
27230 Some(DialectType::Snowflake)
27231 | Some(DialectType::Redshift)
27232 | Some(DialectType::Dremio) => self.write_keyword("VARBINARY"),
27233 _ => self.write_keyword("BLOB"),
27234 },
27235 "LONGVARCHAR" => match self.config.dialect {
27237 Some(DialectType::SQLite) => self.write_keyword("TEXT"),
27238 _ => self.write_keyword("VARCHAR"),
27239 },
27240 "DATETIME" => {
27242 match self.config.dialect {
27243 Some(DialectType::MySQL)
27244 | Some(DialectType::Doris)
27245 | Some(DialectType::StarRocks)
27246 | Some(DialectType::TSQL)
27247 | Some(DialectType::Fabric)
27248 | Some(DialectType::BigQuery)
27249 | Some(DialectType::SQLite)
27250 | Some(DialectType::Snowflake) => {
27251 self.write_keyword("DATETIME");
27252 if let Some(args) = _args_str {
27253 self.write(args);
27254 }
27255 }
27256 Some(_) => {
27257 self.write_keyword("TIMESTAMP");
27259 if let Some(args) = _args_str {
27260 self.write(args);
27261 }
27262 }
27263 None => {
27264 self.write(name);
27266 }
27267 }
27268 }
27269 "VARCHAR2"
27271 if !matches!(self.config.dialect, Some(DialectType::Oracle)) =>
27272 {
27273 match self.config.dialect {
27274 Some(DialectType::DuckDB) | Some(DialectType::SQLite) => {
27275 self.write_keyword("TEXT");
27276 }
27277 Some(DialectType::Hive)
27278 | Some(DialectType::Spark)
27279 | Some(DialectType::Databricks)
27280 | Some(DialectType::BigQuery)
27281 | Some(DialectType::ClickHouse)
27282 | Some(DialectType::StarRocks)
27283 | Some(DialectType::Doris) => {
27284 self.write_keyword("STRING");
27285 }
27286 _ => {
27287 self.write_keyword("VARCHAR");
27288 if let Some(args) = _args_str {
27289 self.write(args);
27290 }
27291 }
27292 }
27293 }
27294 "NVARCHAR2"
27295 if !matches!(self.config.dialect, Some(DialectType::Oracle)) =>
27296 {
27297 match self.config.dialect {
27298 Some(DialectType::DuckDB) | Some(DialectType::SQLite) => {
27299 self.write_keyword("TEXT");
27300 }
27301 Some(DialectType::Hive)
27302 | Some(DialectType::Spark)
27303 | Some(DialectType::Databricks)
27304 | Some(DialectType::BigQuery)
27305 | Some(DialectType::ClickHouse)
27306 | Some(DialectType::StarRocks)
27307 | Some(DialectType::Doris) => {
27308 self.write_keyword("STRING");
27309 }
27310 _ => {
27311 self.write_keyword("VARCHAR");
27312 if let Some(args) = _args_str {
27313 self.write(args);
27314 }
27315 }
27316 }
27317 }
27318 _ => self.write(name),
27319 }
27320 }
27321 }
27322 }
27323 DataType::Geometry { subtype, srid } => {
27324 match self.config.dialect {
27326 Some(DialectType::MySQL) => {
27327 if let Some(sub) = subtype {
27329 self.write_keyword(sub);
27330 if let Some(s) = srid {
27331 self.write(" SRID ");
27332 self.write(&s.to_string());
27333 }
27334 } else {
27335 self.write_keyword("GEOMETRY");
27336 }
27337 }
27338 Some(DialectType::BigQuery) => {
27339 self.write_keyword("GEOGRAPHY");
27341 }
27342 Some(DialectType::Teradata) => {
27343 self.write_keyword("ST_GEOMETRY");
27345 if subtype.is_some() || srid.is_some() {
27346 self.write("(");
27347 if let Some(sub) = subtype {
27348 self.write_keyword(sub);
27349 }
27350 if let Some(s) = srid {
27351 if subtype.is_some() {
27352 self.write(", ");
27353 }
27354 self.write(&s.to_string());
27355 }
27356 self.write(")");
27357 }
27358 }
27359 _ => {
27360 self.write_keyword("GEOMETRY");
27362 if subtype.is_some() || srid.is_some() {
27363 self.write("(");
27364 if let Some(sub) = subtype {
27365 self.write_keyword(sub);
27366 }
27367 if let Some(s) = srid {
27368 if subtype.is_some() {
27369 self.write(", ");
27370 }
27371 self.write(&s.to_string());
27372 }
27373 self.write(")");
27374 }
27375 }
27376 }
27377 }
27378 DataType::Geography { subtype, srid } => {
27379 match self.config.dialect {
27381 Some(DialectType::MySQL) => {
27382 if let Some(sub) = subtype {
27384 self.write_keyword(sub);
27385 } else {
27386 self.write_keyword("GEOMETRY");
27387 }
27388 let effective_srid = srid.unwrap_or(4326);
27390 self.write(" SRID ");
27391 self.write(&effective_srid.to_string());
27392 }
27393 Some(DialectType::BigQuery) => {
27394 self.write_keyword("GEOGRAPHY");
27396 }
27397 Some(DialectType::Snowflake) => {
27398 self.write_keyword("GEOGRAPHY");
27400 }
27401 _ => {
27402 self.write_keyword("GEOGRAPHY");
27404 if subtype.is_some() || srid.is_some() {
27405 self.write("(");
27406 if let Some(sub) = subtype {
27407 self.write_keyword(sub);
27408 }
27409 if let Some(s) = srid {
27410 if subtype.is_some() {
27411 self.write(", ");
27412 }
27413 self.write(&s.to_string());
27414 }
27415 self.write(")");
27416 }
27417 }
27418 }
27419 }
27420 DataType::CharacterSet { name } => {
27421 self.write_keyword("CHAR CHARACTER SET ");
27423 self.write(name);
27424 }
27425 _ => self.write("UNKNOWN"),
27426 }
27427 Ok(())
27428 }
27429
27430 #[inline]
27433 fn write(&mut self, s: &str) {
27434 self.output.push_str(s);
27435 }
27436
27437 #[inline]
27438 fn write_space(&mut self) {
27439 self.output.push(' ');
27440 }
27441
27442 #[inline]
27443 fn write_keyword(&mut self, keyword: &str) {
27444 if self.config.uppercase_keywords {
27445 self.output.push_str(keyword);
27446 } else {
27447 for b in keyword.bytes() {
27448 self.output.push(b.to_ascii_lowercase() as char);
27449 }
27450 }
27451 }
27452
27453 fn write_func_name(&mut self, name: &str) {
27455 let normalized = self.normalize_func_name(name);
27456 self.output.push_str(normalized.as_ref());
27457 }
27458
27459 fn convert_strptime_to_exasol_format(format: &str) -> String {
27463 let mut result = String::new();
27464 let chars: Vec<char> = format.chars().collect();
27465 let mut i = 0;
27466 while i < chars.len() {
27467 if chars[i] == '%' && i + 1 < chars.len() {
27468 let spec = chars[i + 1];
27469 let exasol_spec = match spec {
27470 'Y' => "YYYY",
27471 'y' => "YY",
27472 'm' => "MM",
27473 'd' => "DD",
27474 'H' => "HH",
27475 'M' => "MI",
27476 'S' => "SS",
27477 'a' => "DY", 'A' => "DAY", 'b' => "MON", 'B' => "MONTH", 'I' => "H12", 'u' => "ID", 'V' => "IW", 'G' => "IYYY", 'W' => "UW", 'U' => "UW", 'z' => "Z", _ => {
27489 result.push('%');
27491 result.push(spec);
27492 i += 2;
27493 continue;
27494 }
27495 };
27496 result.push_str(exasol_spec);
27497 i += 2;
27498 } else {
27499 result.push(chars[i]);
27500 i += 1;
27501 }
27502 }
27503 result
27504 }
27505
27506 fn convert_strptime_to_postgres_format(format: &str) -> String {
27510 let mut result = String::new();
27511 let chars: Vec<char> = format.chars().collect();
27512 let mut i = 0;
27513 while i < chars.len() {
27514 if chars[i] == '%' && i + 1 < chars.len() {
27515 if chars[i + 1] == '-' && i + 2 < chars.len() {
27517 let spec = chars[i + 2];
27518 let pg_spec = match spec {
27519 'd' => "FMDD",
27520 'm' => "FMMM",
27521 'H' => "FMHH24",
27522 'M' => "FMMI",
27523 'S' => "FMSS",
27524 _ => {
27525 result.push('%');
27526 result.push('-');
27527 result.push(spec);
27528 i += 3;
27529 continue;
27530 }
27531 };
27532 result.push_str(pg_spec);
27533 i += 3;
27534 continue;
27535 }
27536 let spec = chars[i + 1];
27537 let pg_spec = match spec {
27538 'Y' => "YYYY",
27539 'y' => "YY",
27540 'm' => "MM",
27541 'd' => "DD",
27542 'H' => "HH24",
27543 'I' => "HH12",
27544 'M' => "MI",
27545 'S' => "SS",
27546 'f' => "US", 'u' => "D", 'j' => "DDD", 'z' => "OF", 'Z' => "TZ", 'A' => "TMDay", 'a' => "TMDy", 'b' => "TMMon", 'B' => "TMMonth", 'U' => "WW", _ => {
27557 result.push('%');
27559 result.push(spec);
27560 i += 2;
27561 continue;
27562 }
27563 };
27564 result.push_str(pg_spec);
27565 i += 2;
27566 } else {
27567 result.push(chars[i]);
27568 i += 1;
27569 }
27570 }
27571 result
27572 }
27573
27574 fn write_limit_expr(&mut self, expr: &Expression) -> Result<()> {
27576 if self.config.limit_only_literals {
27577 if let Some(value) = Self::try_evaluate_constant(expr) {
27578 self.write(&value.to_string());
27579 return Ok(());
27580 }
27581 }
27582 self.generate_expression(expr)
27583 }
27584
27585 fn is_noop_limit_expr(expr: &Expression) -> bool {
27586 match expr {
27587 Expression::Null(_) => true,
27588 Expression::Identifier(identifier) => identifier.name.eq_ignore_ascii_case("ALL"),
27589 Expression::Column(column) => {
27590 column.table.is_none() && column.name.name.eq_ignore_ascii_case("ALL")
27591 }
27592 Expression::Var(var) => var.this.eq_ignore_ascii_case("ALL"),
27593 Expression::Paren(paren) => Self::is_noop_limit_expr(&paren.this),
27594 _ => false,
27595 }
27596 }
27597
27598 fn write_formatted_comment(&mut self, comment: &str) {
27602 let content = if comment.starts_with("/*") && comment.ends_with("*/") {
27605 &comment[2..comment.len() - 2]
27608 } else if comment.starts_with("--") {
27609 &comment[2..]
27612 } else {
27613 comment
27615 };
27616 if content.trim().is_empty() {
27618 return;
27619 }
27620 let sanitized = content.replace("*/", "* /").replace("/*", "/ *");
27623 let content = &sanitized;
27624 self.output.push_str("/*");
27626 if !content.starts_with(' ') {
27627 self.output.push(' ');
27628 }
27629 self.output.push_str(content);
27630 if !content.ends_with(' ') {
27631 self.output.push(' ');
27632 }
27633 self.output.push_str("*/");
27634 }
27635
27636 fn escape_block_for_single_quote(&self, block: &str) -> String {
27639 let escape_backslash = matches!(
27640 self.config.dialect,
27641 Some(crate::dialects::DialectType::Snowflake)
27642 );
27643 let mut escaped = String::with_capacity(block.len() + 4);
27644 for ch in block.chars() {
27645 if ch == '\'' {
27646 escaped.push('\\');
27647 escaped.push('\'');
27648 } else if escape_backslash && ch == '\\' {
27649 escaped.push('\\');
27650 escaped.push('\\');
27651 } else {
27652 escaped.push(ch);
27653 }
27654 }
27655 escaped
27656 }
27657
27658 fn write_newline(&mut self) {
27659 self.output.push('\n');
27660 }
27661
27662 fn write_indent(&mut self) {
27663 for _ in 0..self.indent_level {
27664 self.output.push_str(self.config.indent);
27665 }
27666 }
27667
27668 fn too_wide(&self, args: &[String]) -> bool {
27674 args.iter().map(|s| s.len()).sum::<usize>() > self.config.max_text_width
27675 }
27676
27677 fn generate_to_string(&self, expr: &Expression) -> Result<String> {
27680 let config = GeneratorConfig {
27681 pretty: false,
27682 dialect: self.config.dialect,
27683 ..Default::default()
27684 };
27685 let mut gen = Generator::with_config(config);
27686 gen.generate_expression(expr)?;
27687 Ok(gen.output)
27688 }
27689
27690 fn write_clause_condition(&mut self, keyword: &str, condition: &Expression) -> Result<()> {
27693 if self.config.pretty {
27694 self.write_newline();
27695 self.write_indent();
27696 self.write_keyword(keyword);
27697 self.write_newline();
27698 self.indent_level += 1;
27699 self.write_indent();
27700 self.generate_expression(condition)?;
27701 self.indent_level -= 1;
27702 } else {
27703 self.write_space();
27704 self.write_keyword(keyword);
27705 self.write_space();
27706 self.generate_expression(condition)?;
27707 }
27708 Ok(())
27709 }
27710
27711 fn write_clause_expressions(&mut self, keyword: &str, exprs: &[Expression]) -> Result<()> {
27714 if exprs.is_empty() {
27715 return Ok(());
27716 }
27717
27718 if self.config.pretty {
27719 self.write_newline();
27720 self.write_indent();
27721 self.write_keyword(keyword);
27722 self.write_newline();
27723 self.indent_level += 1;
27724 for (i, expr) in exprs.iter().enumerate() {
27725 if i > 0 {
27726 self.write(",");
27727 self.write_newline();
27728 }
27729 self.write_indent();
27730 self.generate_expression(expr)?;
27731 }
27732 self.indent_level -= 1;
27733 } else {
27734 self.write_space();
27735 self.write_keyword(keyword);
27736 self.write_space();
27737 for (i, expr) in exprs.iter().enumerate() {
27738 if i > 0 {
27739 self.write(", ");
27740 }
27741 self.generate_expression(expr)?;
27742 }
27743 }
27744 Ok(())
27745 }
27746
27747 fn write_order_clause(&mut self, keyword: &str, orderings: &[Ordered]) -> Result<()> {
27749 if orderings.is_empty() {
27750 return Ok(());
27751 }
27752
27753 if self.config.pretty {
27754 self.write_newline();
27755 self.write_indent();
27756 self.write_keyword(keyword);
27757 self.write_newline();
27758 self.indent_level += 1;
27759 for (i, ordered) in orderings.iter().enumerate() {
27760 if i > 0 {
27761 self.write(",");
27762 self.write_newline();
27763 }
27764 self.write_indent();
27765 self.generate_ordered(ordered)?;
27766 }
27767 self.indent_level -= 1;
27768 } else {
27769 self.write_space();
27770 self.write_keyword(keyword);
27771 self.write_space();
27772 for (i, ordered) in orderings.iter().enumerate() {
27773 if i > 0 {
27774 self.write(", ");
27775 }
27776 self.generate_ordered(ordered)?;
27777 }
27778 }
27779 Ok(())
27780 }
27781
27782 fn write_window_clause(&mut self, windows: &[NamedWindow]) -> Result<()> {
27784 if windows.is_empty() {
27785 return Ok(());
27786 }
27787
27788 if self.config.pretty {
27789 self.write_newline();
27790 self.write_indent();
27791 self.write_keyword("WINDOW");
27792 self.write_newline();
27793 self.indent_level += 1;
27794 for (i, named_window) in windows.iter().enumerate() {
27795 if i > 0 {
27796 self.write(",");
27797 self.write_newline();
27798 }
27799 self.write_indent();
27800 self.generate_identifier(&named_window.name)?;
27801 self.write_space();
27802 self.write_keyword("AS");
27803 self.write(" (");
27804 self.generate_over(&named_window.spec)?;
27805 self.write(")");
27806 }
27807 self.indent_level -= 1;
27808 } else {
27809 self.write_space();
27810 self.write_keyword("WINDOW");
27811 self.write_space();
27812 for (i, named_window) in windows.iter().enumerate() {
27813 if i > 0 {
27814 self.write(", ");
27815 }
27816 self.generate_identifier(&named_window.name)?;
27817 self.write_space();
27818 self.write_keyword("AS");
27819 self.write(" (");
27820 self.generate_over(&named_window.spec)?;
27821 self.write(")");
27822 }
27823 }
27824 Ok(())
27825 }
27826
27827 fn generate_ai_agg(&mut self, e: &AIAgg) -> Result<()> {
27829 self.write_keyword("AI_AGG");
27831 self.write("(");
27832 self.generate_expression(&e.this)?;
27833 self.write(", ");
27834 self.generate_expression(&e.expression)?;
27835 self.write(")");
27836 Ok(())
27837 }
27838
27839 fn generate_ai_classify(&mut self, e: &AIClassify) -> Result<()> {
27840 self.write_keyword("AI_CLASSIFY");
27842 self.write("(");
27843 self.generate_expression(&e.this)?;
27844 if let Some(categories) = &e.categories {
27845 self.write(", ");
27846 self.generate_expression(categories)?;
27847 }
27848 if let Some(config) = &e.config {
27849 self.write(", ");
27850 self.generate_expression(config)?;
27851 }
27852 self.write(")");
27853 Ok(())
27854 }
27855
27856 fn generate_add_partition(&mut self, e: &AddPartition) -> Result<()> {
27857 self.write_keyword("ADD");
27859 self.write_space();
27860 if e.exists {
27861 self.write_keyword("IF NOT EXISTS");
27862 self.write_space();
27863 }
27864 self.generate_expression(&e.this)?;
27865 if let Some(location) = &e.location {
27866 self.write_space();
27867 self.generate_expression(location)?;
27868 }
27869 Ok(())
27870 }
27871
27872 fn generate_algorithm_property(&mut self, e: &AlgorithmProperty) -> Result<()> {
27873 self.write_keyword("ALGORITHM");
27875 self.write("=");
27876 self.generate_expression(&e.this)?;
27877 Ok(())
27878 }
27879
27880 fn generate_aliases(&mut self, e: &Aliases) -> Result<()> {
27881 self.generate_expression(&e.this)?;
27883 self.write_space();
27884 self.write_keyword("AS");
27885 self.write(" (");
27886 for (i, expr) in e.expressions.iter().enumerate() {
27887 if i > 0 {
27888 self.write(", ");
27889 }
27890 self.generate_expression(expr)?;
27891 }
27892 self.write(")");
27893 Ok(())
27894 }
27895
27896 fn generate_allowed_values_property(&mut self, e: &AllowedValuesProperty) -> Result<()> {
27897 self.write_keyword("ALLOWED_VALUES");
27899 self.write_space();
27900 for (i, expr) in e.expressions.iter().enumerate() {
27901 if i > 0 {
27902 self.write(", ");
27903 }
27904 self.generate_expression(expr)?;
27905 }
27906 Ok(())
27907 }
27908
27909 fn generate_alter_column(&mut self, e: &AlterColumn) -> Result<()> {
27910 self.write_keyword("ALTER COLUMN");
27912 self.write_space();
27913 self.generate_expression(&e.this)?;
27914
27915 if let Some(dtype) = &e.dtype {
27916 self.write_space();
27917 self.write_keyword("SET DATA TYPE");
27918 self.write_space();
27919 self.generate_expression(dtype)?;
27920 if let Some(collate) = &e.collate {
27921 self.write_space();
27922 self.write_keyword("COLLATE");
27923 self.write_space();
27924 self.generate_expression(collate)?;
27925 }
27926 if let Some(using) = &e.using {
27927 self.write_space();
27928 self.write_keyword("USING");
27929 self.write_space();
27930 self.generate_expression(using)?;
27931 }
27932 } else if let Some(default) = &e.default {
27933 self.write_space();
27934 self.write_keyword("SET DEFAULT");
27935 self.write_space();
27936 self.generate_expression(default)?;
27937 } else if let Some(comment) = &e.comment {
27938 self.write_space();
27939 self.write_keyword("COMMENT");
27940 self.write_space();
27941 self.generate_expression(comment)?;
27942 } else if let Some(drop) = &e.drop {
27943 self.write_space();
27944 self.write_keyword("DROP");
27945 self.write_space();
27946 self.generate_expression(drop)?;
27947 } else if let Some(visible) = &e.visible {
27948 self.write_space();
27949 self.generate_expression(visible)?;
27950 } else if let Some(rename_to) = &e.rename_to {
27951 self.write_space();
27952 self.write_keyword("RENAME TO");
27953 self.write_space();
27954 self.generate_expression(rename_to)?;
27955 } else if let Some(allow_null) = &e.allow_null {
27956 self.write_space();
27957 self.generate_expression(allow_null)?;
27958 }
27959 Ok(())
27960 }
27961
27962 fn generate_alter_session(&mut self, e: &AlterSession) -> Result<()> {
27963 self.write_keyword("ALTER SESSION");
27965 self.write_space();
27966 if e.unset.is_some() {
27967 self.write_keyword("UNSET");
27968 } else {
27969 self.write_keyword("SET");
27970 }
27971 self.write_space();
27972 for (i, expr) in e.expressions.iter().enumerate() {
27973 if i > 0 {
27974 self.write(", ");
27975 }
27976 self.generate_expression(expr)?;
27977 }
27978 Ok(())
27979 }
27980
27981 fn generate_alter_set(&mut self, e: &AlterSet) -> Result<()> {
27982 self.write_keyword("SET");
27984
27985 if let Some(opt) = &e.option {
27987 self.write_space();
27988 self.generate_expression(opt)?;
27989 }
27990
27991 if !e.expressions.is_empty() {
27994 let is_properties = e
27996 .expressions
27997 .iter()
27998 .any(|expr| matches!(expr, Expression::Eq(_)));
27999 if is_properties && e.option.is_none() {
28000 self.write_space();
28001 self.write_keyword("PROPERTIES");
28002 }
28003 self.write_space();
28004 for (i, expr) in e.expressions.iter().enumerate() {
28005 if i > 0 {
28006 self.write(", ");
28007 }
28008 self.generate_expression(expr)?;
28009 }
28010 }
28011
28012 if let Some(file_format) = &e.file_format {
28014 self.write(" ");
28015 self.write_keyword("STAGE_FILE_FORMAT");
28016 self.write(" = (");
28017 self.generate_space_separated_properties(file_format)?;
28018 self.write(")");
28019 }
28020
28021 if let Some(copy_options) = &e.copy_options {
28023 self.write(" ");
28024 self.write_keyword("STAGE_COPY_OPTIONS");
28025 self.write(" = (");
28026 self.generate_space_separated_properties(copy_options)?;
28027 self.write(")");
28028 }
28029
28030 if let Some(tag) = &e.tag {
28032 self.write(" ");
28033 self.write_keyword("TAG");
28034 self.write(" ");
28035 self.generate_expression(tag)?;
28036 }
28037
28038 Ok(())
28039 }
28040
28041 fn generate_space_separated_properties(&mut self, expr: &Expression) -> Result<()> {
28043 match expr {
28044 Expression::Tuple(t) => {
28045 for (i, prop) in t.expressions.iter().enumerate() {
28046 if i > 0 {
28047 self.write(" ");
28048 }
28049 self.generate_expression(prop)?;
28050 }
28051 }
28052 _ => {
28053 self.generate_expression(expr)?;
28054 }
28055 }
28056 Ok(())
28057 }
28058
28059 fn generate_alter_sort_key(&mut self, e: &AlterSortKey) -> Result<()> {
28060 self.write_keyword("ALTER");
28062 if e.compound.is_some() {
28063 self.write_space();
28064 self.write_keyword("COMPOUND");
28065 }
28066 self.write_space();
28067 self.write_keyword("SORTKEY");
28068 self.write_space();
28069 if let Some(this) = &e.this {
28070 self.generate_expression(this)?;
28071 } else if !e.expressions.is_empty() {
28072 self.write("(");
28073 for (i, expr) in e.expressions.iter().enumerate() {
28074 if i > 0 {
28075 self.write(", ");
28076 }
28077 self.generate_expression(expr)?;
28078 }
28079 self.write(")");
28080 }
28081 Ok(())
28082 }
28083
28084 fn generate_analyze(&mut self, e: &Analyze) -> Result<()> {
28085 self.write_keyword("ANALYZE");
28087 if !e.options.is_empty() {
28088 self.write_space();
28089 for (i, opt) in e.options.iter().enumerate() {
28090 if i > 0 {
28091 self.write_space();
28092 }
28093 if let Expression::Identifier(id) = opt {
28095 self.write_keyword(&id.name);
28096 } else {
28097 self.generate_expression(opt)?;
28098 }
28099 }
28100 }
28101 if let Some(kind) = &e.kind {
28102 self.write_space();
28103 self.write_keyword(kind);
28104 }
28105 if let Some(this) = &e.this {
28106 self.write_space();
28107 self.generate_expression(this)?;
28108 }
28109 if !e.columns.is_empty() {
28111 self.write("(");
28112 for (i, col) in e.columns.iter().enumerate() {
28113 if i > 0 {
28114 self.write(", ");
28115 }
28116 self.write(col);
28117 }
28118 self.write(")");
28119 }
28120 if let Some(partition) = &e.partition {
28121 self.write_space();
28122 self.generate_expression(partition)?;
28123 }
28124 if let Some(mode) = &e.mode {
28125 self.write_space();
28126 self.generate_expression(mode)?;
28127 }
28128 if let Some(expression) = &e.expression {
28129 self.write_space();
28130 self.generate_expression(expression)?;
28131 }
28132 if !e.properties.is_empty() {
28133 self.write_space();
28134 self.write_keyword(self.config.with_properties_prefix);
28135 self.write(" (");
28136 for (i, prop) in e.properties.iter().enumerate() {
28137 if i > 0 {
28138 self.write(", ");
28139 }
28140 self.generate_expression(prop)?;
28141 }
28142 self.write(")");
28143 }
28144 Ok(())
28145 }
28146
28147 fn generate_analyze_delete(&mut self, e: &AnalyzeDelete) -> Result<()> {
28148 self.write_keyword("DELETE");
28150 if let Some(kind) = &e.kind {
28151 self.write_space();
28152 self.write_keyword(kind);
28153 }
28154 self.write_space();
28155 self.write_keyword("STATISTICS");
28156 Ok(())
28157 }
28158
28159 fn generate_analyze_histogram(&mut self, e: &AnalyzeHistogram) -> Result<()> {
28160 if let Expression::Identifier(id) = e.this.as_ref() {
28163 self.write_keyword(&id.name);
28164 } else {
28165 self.generate_expression(&e.this)?;
28166 }
28167 self.write_space();
28168 self.write_keyword("HISTOGRAM ON");
28169 self.write_space();
28170 for (i, expr) in e.expressions.iter().enumerate() {
28171 if i > 0 {
28172 self.write(", ");
28173 }
28174 self.generate_expression(expr)?;
28175 }
28176 if let Some(expression) = &e.expression {
28177 self.write_space();
28178 self.generate_expression(expression)?;
28179 }
28180 if let Some(update_options) = &e.update_options {
28181 self.write_space();
28182 self.generate_expression(update_options)?;
28183 self.write_space();
28184 self.write_keyword("UPDATE");
28185 }
28186 Ok(())
28187 }
28188
28189 fn generate_analyze_list_chained_rows(&mut self, e: &AnalyzeListChainedRows) -> Result<()> {
28190 self.write_keyword("LIST CHAINED ROWS");
28192 if let Some(expression) = &e.expression {
28193 self.write_space();
28194 self.write_keyword("INTO");
28195 self.write_space();
28196 self.generate_expression(expression)?;
28197 }
28198 Ok(())
28199 }
28200
28201 fn generate_analyze_sample(&mut self, e: &AnalyzeSample) -> Result<()> {
28202 self.write_keyword("SAMPLE");
28204 self.write_space();
28205 if let Some(sample) = &e.sample {
28206 self.generate_expression(sample)?;
28207 self.write_space();
28208 }
28209 self.write_keyword(&e.kind);
28210 Ok(())
28211 }
28212
28213 fn generate_analyze_statistics(&mut self, e: &AnalyzeStatistics) -> Result<()> {
28214 self.write_keyword(&e.kind);
28216 if let Some(option) = &e.option {
28217 self.write_space();
28218 self.generate_expression(option)?;
28219 }
28220 self.write_space();
28221 self.write_keyword("STATISTICS");
28222 if let Some(this) = &e.this {
28223 self.write_space();
28224 self.generate_expression(this)?;
28225 }
28226 if !e.expressions.is_empty() {
28227 self.write_space();
28228 for (i, expr) in e.expressions.iter().enumerate() {
28229 if i > 0 {
28230 self.write(", ");
28231 }
28232 self.generate_expression(expr)?;
28233 }
28234 }
28235 Ok(())
28236 }
28237
28238 fn generate_analyze_validate(&mut self, e: &AnalyzeValidate) -> Result<()> {
28239 self.write_keyword("VALIDATE");
28241 self.write_space();
28242 self.write_keyword(&e.kind);
28243 if let Some(this) = &e.this {
28244 self.write_space();
28245 if let Expression::Identifier(id) = this.as_ref() {
28247 self.write_keyword(&id.name);
28248 } else {
28249 self.generate_expression(this)?;
28250 }
28251 }
28252 if let Some(expression) = &e.expression {
28253 self.write_space();
28254 self.write_keyword("INTO");
28255 self.write_space();
28256 self.generate_expression(expression)?;
28257 }
28258 Ok(())
28259 }
28260
28261 fn generate_analyze_with(&mut self, e: &AnalyzeWith) -> Result<()> {
28262 self.write_keyword("WITH");
28264 self.write_space();
28265 for (i, expr) in e.expressions.iter().enumerate() {
28266 if i > 0 {
28267 self.write(", ");
28268 }
28269 self.generate_expression(expr)?;
28270 }
28271 Ok(())
28272 }
28273
28274 fn generate_anonymous(&mut self, e: &Anonymous) -> Result<()> {
28275 self.generate_expression(&e.this)?;
28278 self.write("(");
28279 for (i, arg) in e.expressions.iter().enumerate() {
28280 if i > 0 {
28281 self.write(", ");
28282 }
28283 self.generate_expression(arg)?;
28284 }
28285 self.write(")");
28286 Ok(())
28287 }
28288
28289 fn generate_anonymous_agg_func(&mut self, e: &AnonymousAggFunc) -> Result<()> {
28290 self.generate_expression(&e.this)?;
28292 self.write("(");
28293 for (i, arg) in e.expressions.iter().enumerate() {
28294 if i > 0 {
28295 self.write(", ");
28296 }
28297 self.generate_expression(arg)?;
28298 }
28299 self.write(")");
28300 Ok(())
28301 }
28302
28303 fn generate_apply(&mut self, e: &Apply) -> Result<()> {
28304 self.generate_expression(&e.this)?;
28306 self.write_space();
28307 self.write_keyword("APPLY");
28308 self.write("(");
28309 self.generate_expression(&e.expression)?;
28310 self.write(")");
28311 Ok(())
28312 }
28313
28314 fn generate_approx_percentile_estimate(&mut self, e: &ApproxPercentileEstimate) -> Result<()> {
28315 self.write_keyword("APPROX_PERCENTILE_ESTIMATE");
28317 self.write("(");
28318 self.generate_expression(&e.this)?;
28319 if let Some(percentile) = &e.percentile {
28320 self.write(", ");
28321 self.generate_expression(percentile)?;
28322 }
28323 self.write(")");
28324 Ok(())
28325 }
28326
28327 fn generate_approx_quantile(&mut self, e: &ApproxQuantile) -> Result<()> {
28328 self.write_keyword("APPROX_QUANTILE");
28330 self.write("(");
28331 self.generate_expression(&e.this)?;
28332 if let Some(quantile) = &e.quantile {
28333 self.write(", ");
28334 self.generate_expression(quantile)?;
28335 }
28336 if let Some(accuracy) = &e.accuracy {
28337 self.write(", ");
28338 self.generate_expression(accuracy)?;
28339 }
28340 if let Some(weight) = &e.weight {
28341 self.write(", ");
28342 self.generate_expression(weight)?;
28343 }
28344 self.write(")");
28345 Ok(())
28346 }
28347
28348 fn generate_approx_quantiles(&mut self, e: &ApproxQuantiles) -> Result<()> {
28349 self.write_keyword("APPROX_QUANTILES");
28351 self.write("(");
28352 self.generate_expression(&e.this)?;
28353 if let Some(expression) = &e.expression {
28354 self.write(", ");
28355 self.generate_expression(expression)?;
28356 }
28357 self.write(")");
28358 Ok(())
28359 }
28360
28361 fn generate_approx_top_k(&mut self, e: &ApproxTopK) -> Result<()> {
28362 self.write_keyword("APPROX_TOP_K");
28364 self.write("(");
28365 self.generate_expression(&e.this)?;
28366 if let Some(expression) = &e.expression {
28367 self.write(", ");
28368 self.generate_expression(expression)?;
28369 }
28370 if let Some(counters) = &e.counters {
28371 self.write(", ");
28372 self.generate_expression(counters)?;
28373 }
28374 self.write(")");
28375 Ok(())
28376 }
28377
28378 fn generate_approx_top_k_accumulate(&mut self, e: &ApproxTopKAccumulate) -> Result<()> {
28379 self.write_keyword("APPROX_TOP_K_ACCUMULATE");
28381 self.write("(");
28382 self.generate_expression(&e.this)?;
28383 if let Some(expression) = &e.expression {
28384 self.write(", ");
28385 self.generate_expression(expression)?;
28386 }
28387 self.write(")");
28388 Ok(())
28389 }
28390
28391 fn generate_approx_top_k_combine(&mut self, e: &ApproxTopKCombine) -> Result<()> {
28392 self.write_keyword("APPROX_TOP_K_COMBINE");
28394 self.write("(");
28395 self.generate_expression(&e.this)?;
28396 if let Some(expression) = &e.expression {
28397 self.write(", ");
28398 self.generate_expression(expression)?;
28399 }
28400 self.write(")");
28401 Ok(())
28402 }
28403
28404 fn generate_approx_top_k_estimate(&mut self, e: &ApproxTopKEstimate) -> Result<()> {
28405 self.write_keyword("APPROX_TOP_K_ESTIMATE");
28407 self.write("(");
28408 self.generate_expression(&e.this)?;
28409 if let Some(expression) = &e.expression {
28410 self.write(", ");
28411 self.generate_expression(expression)?;
28412 }
28413 self.write(")");
28414 Ok(())
28415 }
28416
28417 fn generate_approx_top_sum(&mut self, e: &ApproxTopSum) -> Result<()> {
28418 self.write_keyword("APPROX_TOP_SUM");
28420 self.write("(");
28421 self.generate_expression(&e.this)?;
28422 self.write(", ");
28423 self.generate_expression(&e.expression)?;
28424 if let Some(count) = &e.count {
28425 self.write(", ");
28426 self.generate_expression(count)?;
28427 }
28428 self.write(")");
28429 Ok(())
28430 }
28431
28432 fn generate_arg_max(&mut self, e: &ArgMax) -> Result<()> {
28433 self.write_keyword("ARG_MAX");
28435 self.write("(");
28436 self.generate_expression(&e.this)?;
28437 self.write(", ");
28438 self.generate_expression(&e.expression)?;
28439 if let Some(count) = &e.count {
28440 self.write(", ");
28441 self.generate_expression(count)?;
28442 }
28443 self.write(")");
28444 Ok(())
28445 }
28446
28447 fn generate_arg_min(&mut self, e: &ArgMin) -> Result<()> {
28448 self.write_keyword("ARG_MIN");
28450 self.write("(");
28451 self.generate_expression(&e.this)?;
28452 self.write(", ");
28453 self.generate_expression(&e.expression)?;
28454 if let Some(count) = &e.count {
28455 self.write(", ");
28456 self.generate_expression(count)?;
28457 }
28458 self.write(")");
28459 Ok(())
28460 }
28461
28462 fn generate_array_all(&mut self, e: &ArrayAll) -> Result<()> {
28463 self.write_keyword("ARRAY_ALL");
28465 self.write("(");
28466 self.generate_expression(&e.this)?;
28467 self.write(", ");
28468 self.generate_expression(&e.expression)?;
28469 self.write(")");
28470 Ok(())
28471 }
28472
28473 fn generate_array_any(&mut self, e: &ArrayAny) -> Result<()> {
28474 self.write_keyword("ARRAY_ANY");
28476 self.write("(");
28477 self.generate_expression(&e.this)?;
28478 self.write(", ");
28479 self.generate_expression(&e.expression)?;
28480 self.write(")");
28481 Ok(())
28482 }
28483
28484 fn generate_array_construct_compact(&mut self, e: &ArrayConstructCompact) -> Result<()> {
28485 self.write_keyword("ARRAY_CONSTRUCT_COMPACT");
28487 self.write("(");
28488 for (i, expr) in e.expressions.iter().enumerate() {
28489 if i > 0 {
28490 self.write(", ");
28491 }
28492 self.generate_expression(expr)?;
28493 }
28494 self.write(")");
28495 Ok(())
28496 }
28497
28498 fn generate_array_sum(&mut self, e: &ArraySum) -> Result<()> {
28499 if matches!(self.config.dialect, Some(DialectType::ClickHouse)) {
28501 self.write("arraySum");
28502 } else {
28503 self.write_keyword("ARRAY_SUM");
28504 }
28505 self.write("(");
28506 self.generate_expression(&e.this)?;
28507 if let Some(expression) = &e.expression {
28508 self.write(", ");
28509 self.generate_expression(expression)?;
28510 }
28511 self.write(")");
28512 Ok(())
28513 }
28514
28515 fn generate_at_index(&mut self, e: &AtIndex) -> Result<()> {
28516 self.generate_expression(&e.this)?;
28518 self.write_space();
28519 self.write_keyword("AT");
28520 self.write_space();
28521 self.generate_expression(&e.expression)?;
28522 Ok(())
28523 }
28524
28525 fn generate_attach(&mut self, e: &Attach) -> Result<()> {
28526 self.write_keyword("ATTACH");
28528 if e.exists {
28529 self.write_space();
28530 self.write_keyword("IF NOT EXISTS");
28531 }
28532 self.write_space();
28533 self.generate_expression(&e.this)?;
28534 if !e.expressions.is_empty() {
28535 self.write(" (");
28536 for (i, expr) in e.expressions.iter().enumerate() {
28537 if i > 0 {
28538 self.write(", ");
28539 }
28540 self.generate_expression(expr)?;
28541 }
28542 self.write(")");
28543 }
28544 Ok(())
28545 }
28546
28547 fn generate_attach_option(&mut self, e: &AttachOption) -> Result<()> {
28548 self.generate_expression(&e.this)?;
28551 if let Some(expression) = &e.expression {
28552 self.write_space();
28553 self.generate_expression(expression)?;
28554 }
28555 Ok(())
28556 }
28557
28558 fn generate_auto_increment_keyword(
28562 &mut self,
28563 col: &crate::expressions::ColumnDef,
28564 ) -> Result<()> {
28565 use crate::dialects::DialectType;
28566 if matches!(self.config.dialect, Some(DialectType::Redshift)) {
28567 self.write_keyword("IDENTITY");
28568 if col.auto_increment_start.is_some() || col.auto_increment_increment.is_some() {
28569 self.write("(");
28570 if let Some(ref start) = col.auto_increment_start {
28571 self.generate_expression(start)?;
28572 } else {
28573 self.write("0");
28574 }
28575 self.write(", ");
28576 if let Some(ref inc) = col.auto_increment_increment {
28577 self.generate_expression(inc)?;
28578 } else {
28579 self.write("1");
28580 }
28581 self.write(")");
28582 }
28583 } else if matches!(
28584 self.config.dialect,
28585 Some(DialectType::Snowflake) | Some(DialectType::SQLite)
28586 ) {
28587 self.write_keyword("AUTOINCREMENT");
28588 if let Some(ref start) = col.auto_increment_start {
28589 self.write_space();
28590 self.write_keyword("START");
28591 self.write_space();
28592 self.generate_expression(start)?;
28593 }
28594 if let Some(ref inc) = col.auto_increment_increment {
28595 self.write_space();
28596 self.write_keyword("INCREMENT");
28597 self.write_space();
28598 self.generate_expression(inc)?;
28599 }
28600 if let Some(order) = col.auto_increment_order {
28601 self.write_space();
28602 if order {
28603 self.write_keyword("ORDER");
28604 } else {
28605 self.write_keyword("NOORDER");
28606 }
28607 }
28608 } else if matches!(self.config.dialect, Some(DialectType::PostgreSQL)) {
28609 self.write_keyword("GENERATED BY DEFAULT AS IDENTITY");
28610 if col.auto_increment_start.is_some() || col.auto_increment_increment.is_some() {
28611 self.write(" (");
28612 let mut first = true;
28613 if let Some(ref start) = col.auto_increment_start {
28614 self.write_keyword("START WITH");
28615 self.write_space();
28616 self.generate_expression(start)?;
28617 first = false;
28618 }
28619 if let Some(ref inc) = col.auto_increment_increment {
28620 if !first {
28621 self.write_space();
28622 }
28623 self.write_keyword("INCREMENT BY");
28624 self.write_space();
28625 self.generate_expression(inc)?;
28626 }
28627 self.write(")");
28628 }
28629 } else if matches!(self.config.dialect, Some(DialectType::Databricks)) {
28630 if col.auto_increment_start.is_some() || col.auto_increment_increment.is_some() {
28633 self.write_keyword("GENERATED BY DEFAULT AS IDENTITY");
28634 } else {
28635 self.write_keyword("GENERATED ALWAYS AS IDENTITY");
28636 }
28637 if col.auto_increment_start.is_some() || col.auto_increment_increment.is_some() {
28638 self.write(" (");
28639 let mut first = true;
28640 if let Some(ref start) = col.auto_increment_start {
28641 self.write_keyword("START WITH");
28642 self.write_space();
28643 self.generate_expression(start)?;
28644 first = false;
28645 }
28646 if let Some(ref inc) = col.auto_increment_increment {
28647 if !first {
28648 self.write_space();
28649 }
28650 self.write_keyword("INCREMENT BY");
28651 self.write_space();
28652 self.generate_expression(inc)?;
28653 }
28654 self.write(")");
28655 }
28656 } else if matches!(
28657 self.config.dialect,
28658 Some(DialectType::TSQL) | Some(DialectType::Fabric)
28659 ) {
28660 self.write_keyword("IDENTITY");
28661 if col.auto_increment_start.is_some() || col.auto_increment_increment.is_some() {
28662 self.write("(");
28663 if let Some(ref start) = col.auto_increment_start {
28664 self.generate_expression(start)?;
28665 } else {
28666 self.write("0");
28667 }
28668 self.write(", ");
28669 if let Some(ref inc) = col.auto_increment_increment {
28670 self.generate_expression(inc)?;
28671 } else {
28672 self.write("1");
28673 }
28674 self.write(")");
28675 }
28676 } else {
28677 self.write_keyword("AUTO_INCREMENT");
28678 if let Some(ref start) = col.auto_increment_start {
28679 self.write_space();
28680 self.write_keyword("START");
28681 self.write_space();
28682 self.generate_expression(start)?;
28683 }
28684 if let Some(ref inc) = col.auto_increment_increment {
28685 self.write_space();
28686 self.write_keyword("INCREMENT");
28687 self.write_space();
28688 self.generate_expression(inc)?;
28689 }
28690 if let Some(order) = col.auto_increment_order {
28691 self.write_space();
28692 if order {
28693 self.write_keyword("ORDER");
28694 } else {
28695 self.write_keyword("NOORDER");
28696 }
28697 }
28698 }
28699 Ok(())
28700 }
28701
28702 fn generate_tidb_auto_random(&mut self, auto_random: &TiDBAutoRandom) -> Result<()> {
28703 let is_tidb = matches!(self.config.dialect, Some(DialectType::TiDB));
28704 let is_mysql = matches!(self.config.dialect, Some(DialectType::MySQL));
28705
28706 if !is_tidb && !is_mysql {
28707 return self
28708 .write_unsupported_comment("AUTO_RANDOM is only supported by the TiDB dialect");
28709 }
28710 if is_mysql {
28711 self.unsupported("MySQL ignores TiDB AUTO_RANDOM executable comments")?;
28712 }
28713
28714 let use_comment = auto_random.executable_comment || is_mysql;
28715 if use_comment {
28716 self.write("/*T![auto_rand] ");
28717 }
28718 self.write_keyword("AUTO_RANDOM");
28719 if let Some(shard_bits) = auto_random.shard_bits {
28720 self.write("(");
28721 self.write(&shard_bits.to_string());
28722 if let Some(range_bits) = auto_random.range_bits {
28723 self.write(", ");
28724 self.write(&range_bits.to_string());
28725 }
28726 self.write(")");
28727 }
28728 if use_comment {
28729 self.write(" */");
28730 }
28731 Ok(())
28732 }
28733
28734 fn generate_tidb_table_option(&mut self, option: &TiDBTableOption, force: bool) -> Result<()> {
28735 let is_tidb = matches!(self.config.dialect, Some(DialectType::TiDB));
28736 let is_mysql = matches!(self.config.dialect, Some(DialectType::MySQL));
28737 if !is_tidb && !is_mysql {
28738 return self.write_unsupported_comment(
28739 "TiDB table options are not supported by the target dialect",
28740 );
28741 }
28742 if is_mysql {
28743 self.unsupported("MySQL ignores TiDB table-option executable comments")?;
28744 }
28745
28746 let use_comment = option.executable_comment || is_mysql;
28747 if use_comment {
28748 match option.kind {
28749 TiDBTableOptionKind::Ttl { .. }
28750 | TiDBTableOptionKind::TtlEnable { .. }
28751 | TiDBTableOptionKind::TtlJobInterval { .. } => self.write("/*T![ttl] "),
28752 TiDBTableOptionKind::PlacementPolicy { .. } => self.write("/*T![placement] "),
28753 _ => self.write("/*T! "),
28754 }
28755 }
28756 if force {
28757 self.write_keyword("FORCE");
28758 self.write_space();
28759 }
28760 match &option.kind {
28761 TiDBTableOptionKind::ShardRowIdBits { bits } => {
28762 self.write_keyword("SHARD_ROW_ID_BITS");
28763 self.write("=");
28764 self.write(&bits.to_string());
28765 }
28766 TiDBTableOptionKind::PreSplitRegions { regions } => {
28767 self.write_keyword("PRE_SPLIT_REGIONS");
28768 self.write("=");
28769 self.write(®ions.to_string());
28770 }
28771 TiDBTableOptionKind::AutoRandomBase { value } => {
28772 self.write_keyword("AUTO_RANDOM_BASE");
28773 self.write("=");
28774 self.write(&value.to_string());
28775 }
28776 TiDBTableOptionKind::PlacementPolicy { policy } => {
28777 self.write_keyword("PLACEMENT POLICY");
28778 self.write("=");
28779 if let Some(policy) = policy {
28780 self.generate_identifier(policy)?;
28781 } else {
28782 self.write_keyword("DEFAULT");
28783 }
28784 }
28785 TiDBTableOptionKind::Ttl {
28786 column,
28787 interval,
28788 enabled,
28789 } => {
28790 self.write_keyword("TTL");
28791 self.write("=");
28792 self.generate_identifier(column)?;
28793 self.write(" + ");
28794 self.generate_tidb_ttl_interval(interval)?;
28795 if let Some(enabled) = enabled {
28796 self.write_space();
28797 self.write_keyword("TTL_ENABLE");
28798 self.write("='");
28799 self.write(if *enabled { "ON" } else { "OFF" });
28800 self.write("'");
28801 }
28802 }
28803 TiDBTableOptionKind::TtlEnable { enabled } => {
28804 self.write_keyword("TTL_ENABLE");
28805 self.write("='");
28806 self.write(if *enabled { "ON" } else { "OFF" });
28807 self.write("'");
28808 }
28809 TiDBTableOptionKind::TtlJobInterval { interval } => {
28810 self.write_keyword("TTL_JOB_INTERVAL");
28811 self.write("=");
28812 self.generate_string_literal(interval)?;
28813 }
28814 }
28815 if use_comment {
28816 self.write(" */");
28817 }
28818 Ok(())
28819 }
28820
28821 fn generate_tidb_ttl_interval(&mut self, interval: &Interval) -> Result<()> {
28822 self.write_keyword("INTERVAL");
28823 if let Some(value) = &interval.this {
28824 self.write_space();
28825 if let Expression::Literal(literal) = value {
28826 if let Literal::String(value) = literal.as_ref() {
28827 if value.parse::<f64>().is_ok() {
28828 self.write(value);
28829 } else {
28830 self.generate_string_literal(value)?;
28831 }
28832 } else {
28833 self.generate_expression(value)?;
28834 }
28835 } else {
28836 self.generate_expression(value)?;
28837 }
28838 }
28839 if let Some(unit) = &interval.unit {
28840 self.write_space();
28841 self.write_interval_unit_spec(unit)?;
28842 }
28843 Ok(())
28844 }
28845
28846 fn generate_auto_increment_property(&mut self, e: &AutoIncrementProperty) -> Result<()> {
28847 self.write_keyword("AUTO_INCREMENT");
28849 self.write("=");
28850 self.generate_expression(&e.this)?;
28851 Ok(())
28852 }
28853
28854 fn generate_auto_refresh_property(&mut self, e: &AutoRefreshProperty) -> Result<()> {
28855 self.write_keyword("AUTO_REFRESH");
28857 self.write("=");
28858 self.generate_expression(&e.this)?;
28859 Ok(())
28860 }
28861
28862 fn generate_backup_property(&mut self, e: &BackupProperty) -> Result<()> {
28863 self.write_keyword("BACKUP");
28865 self.write_space();
28866 self.generate_expression(&e.this)?;
28867 Ok(())
28868 }
28869
28870 fn generate_base64_decode_binary(&mut self, e: &Base64DecodeBinary) -> Result<()> {
28871 self.write_keyword("BASE64_DECODE_BINARY");
28873 self.write("(");
28874 self.generate_expression(&e.this)?;
28875 if let Some(alphabet) = &e.alphabet {
28876 self.write(", ");
28877 self.generate_expression(alphabet)?;
28878 }
28879 self.write(")");
28880 Ok(())
28881 }
28882
28883 fn generate_base64_decode_string(&mut self, e: &Base64DecodeString) -> Result<()> {
28884 self.write_keyword("BASE64_DECODE_STRING");
28886 self.write("(");
28887 self.generate_expression(&e.this)?;
28888 if let Some(alphabet) = &e.alphabet {
28889 self.write(", ");
28890 self.generate_expression(alphabet)?;
28891 }
28892 self.write(")");
28893 Ok(())
28894 }
28895
28896 fn generate_base64_encode(&mut self, e: &Base64Encode) -> Result<()> {
28897 self.write_keyword("BASE64_ENCODE");
28899 self.write("(");
28900 self.generate_expression(&e.this)?;
28901 if let Some(max_line_length) = &e.max_line_length {
28902 self.write(", ");
28903 self.generate_expression(max_line_length)?;
28904 }
28905 if let Some(alphabet) = &e.alphabet {
28906 self.write(", ");
28907 self.generate_expression(alphabet)?;
28908 }
28909 self.write(")");
28910 Ok(())
28911 }
28912
28913 fn generate_block_compression_property(&mut self, e: &BlockCompressionProperty) -> Result<()> {
28914 self.write_keyword("BLOCKCOMPRESSION");
28916 self.write("=");
28917 if let Some(autotemp) = &e.autotemp {
28918 self.write_keyword("AUTOTEMP");
28919 self.write("(");
28920 self.generate_expression(autotemp)?;
28921 self.write(")");
28922 }
28923 if let Some(always) = &e.always {
28924 self.generate_expression(always)?;
28925 }
28926 if let Some(default) = &e.default {
28927 self.generate_expression(default)?;
28928 }
28929 if let Some(manual) = &e.manual {
28930 self.generate_expression(manual)?;
28931 }
28932 if let Some(never) = &e.never {
28933 self.generate_expression(never)?;
28934 }
28935 Ok(())
28936 }
28937
28938 fn generate_booland(&mut self, e: &Booland) -> Result<()> {
28939 self.write("((");
28941 self.generate_expression(&e.this)?;
28942 self.write(") ");
28943 self.write_keyword("AND");
28944 self.write(" (");
28945 self.generate_expression(&e.expression)?;
28946 self.write("))");
28947 Ok(())
28948 }
28949
28950 fn generate_boolor(&mut self, e: &Boolor) -> Result<()> {
28951 self.write("((");
28953 self.generate_expression(&e.this)?;
28954 self.write(") ");
28955 self.write_keyword("OR");
28956 self.write(" (");
28957 self.generate_expression(&e.expression)?;
28958 self.write("))");
28959 Ok(())
28960 }
28961
28962 fn generate_build_property(&mut self, e: &BuildProperty) -> Result<()> {
28963 self.write_keyword("BUILD");
28965 self.write_space();
28966 self.generate_expression(&e.this)?;
28967 Ok(())
28968 }
28969
28970 fn generate_byte_string(&mut self, e: &ByteString) -> Result<()> {
28971 self.generate_expression(&e.this)?;
28973 Ok(())
28974 }
28975
28976 fn generate_case_specific_column_constraint(
28977 &mut self,
28978 e: &CaseSpecificColumnConstraint,
28979 ) -> Result<()> {
28980 if e.not_.is_some() {
28982 self.write_keyword("NOT");
28983 self.write_space();
28984 }
28985 self.write_keyword("CASESPECIFIC");
28986 Ok(())
28987 }
28988
28989 fn generate_cast_to_str_type(&mut self, e: &CastToStrType) -> Result<()> {
28990 self.write_keyword("CAST");
28992 self.write("(");
28993 self.generate_expression(&e.this)?;
28994 if self.config.dialect == Some(DialectType::ClickHouse) {
28995 self.write(", ");
28997 } else {
28998 self.write_space();
28999 self.write_keyword("AS");
29000 self.write_space();
29001 }
29002 if let Some(to) = &e.to {
29003 self.generate_expression(to)?;
29004 }
29005 self.write(")");
29006 Ok(())
29007 }
29008
29009 fn generate_changes(&mut self, e: &Changes) -> Result<()> {
29010 self.write_keyword("CHANGES");
29013 self.write(" (");
29014 if let Some(information) = &e.information {
29015 self.write_keyword("INFORMATION");
29016 self.write(" => ");
29017 self.generate_expression(information)?;
29018 }
29019 self.write(")");
29020 if let Some(at_before) = &e.at_before {
29022 self.write(" ");
29023 self.generate_expression(at_before)?;
29024 }
29025 if let Some(end) = &e.end {
29026 self.write(" ");
29027 self.generate_expression(end)?;
29028 }
29029 Ok(())
29030 }
29031
29032 fn generate_character_set_column_constraint(
29033 &mut self,
29034 e: &CharacterSetColumnConstraint,
29035 ) -> Result<()> {
29036 self.write_keyword("CHARACTER SET");
29038 self.write_space();
29039 self.generate_expression(&e.this)?;
29040 Ok(())
29041 }
29042
29043 fn generate_character_set_property(&mut self, e: &CharacterSetProperty) -> Result<()> {
29044 if e.default.is_some() {
29046 self.write_keyword("DEFAULT");
29047 self.write_space();
29048 }
29049 self.write_keyword("CHARACTER SET");
29050 self.write("=");
29051 self.generate_expression(&e.this)?;
29052 Ok(())
29053 }
29054
29055 fn generate_check_column_constraint(&mut self, e: &CheckColumnConstraint) -> Result<()> {
29056 self.write_keyword("CHECK");
29058 self.write(" (");
29059 self.generate_expression(&e.this)?;
29060 self.write(")");
29061 if e.enforced.is_some() {
29062 self.write_space();
29063 self.write_keyword("ENFORCED");
29064 }
29065 Ok(())
29066 }
29067
29068 fn generate_assume_column_constraint(&mut self, e: &AssumeColumnConstraint) -> Result<()> {
29069 self.write_keyword("ASSUME");
29071 self.write(" (");
29072 self.generate_expression(&e.this)?;
29073 self.write(")");
29074 Ok(())
29075 }
29076
29077 fn generate_check_json(&mut self, e: &CheckJson) -> Result<()> {
29078 self.write_keyword("CHECK_JSON");
29080 self.write("(");
29081 self.generate_expression(&e.this)?;
29082 self.write(")");
29083 Ok(())
29084 }
29085
29086 fn generate_check_xml(&mut self, e: &CheckXml) -> Result<()> {
29087 self.write_keyword("CHECK_XML");
29089 self.write("(");
29090 self.generate_expression(&e.this)?;
29091 self.write(")");
29092 Ok(())
29093 }
29094
29095 fn generate_checksum_property(&mut self, e: &ChecksumProperty) -> Result<()> {
29096 self.write_keyword("CHECKSUM");
29098 self.write("=");
29099 if e.on.is_some() {
29100 self.write_keyword("ON");
29101 } else if e.default.is_some() {
29102 self.write_keyword("DEFAULT");
29103 } else {
29104 self.write_keyword("OFF");
29105 }
29106 Ok(())
29107 }
29108
29109 fn generate_clone(&mut self, e: &Clone) -> Result<()> {
29110 if e.shallow.is_some() {
29112 self.write_keyword("SHALLOW");
29113 self.write_space();
29114 }
29115 if e.copy.is_some() {
29116 self.write_keyword("COPY");
29117 } else {
29118 self.write_keyword("CLONE");
29119 }
29120 self.write_space();
29121 self.generate_expression(&e.this)?;
29122 Ok(())
29123 }
29124
29125 fn generate_cluster_by(&mut self, e: &ClusterBy) -> Result<()> {
29126 self.write_keyword("CLUSTER BY");
29128 self.write(" (");
29129 for (i, ord) in e.expressions.iter().enumerate() {
29130 if i > 0 {
29131 self.write(", ");
29132 }
29133 self.generate_ordered(ord)?;
29134 }
29135 self.write(")");
29136 Ok(())
29137 }
29138
29139 fn generate_cluster_by_columns_property(&mut self, e: &ClusterByColumnsProperty) -> Result<()> {
29140 self.write_keyword("CLUSTER BY");
29142 self.write_space();
29143 for (i, col) in e.columns.iter().enumerate() {
29144 if i > 0 {
29145 self.write(", ");
29146 }
29147 self.generate_identifier(col)?;
29148 }
29149 Ok(())
29150 }
29151
29152 fn generate_clustered_by_property(&mut self, e: &ClusteredByProperty) -> Result<()> {
29153 self.write_keyword("CLUSTERED BY");
29155 self.write(" (");
29156 for (i, expr) in e.expressions.iter().enumerate() {
29157 if i > 0 {
29158 self.write(", ");
29159 }
29160 self.generate_expression(expr)?;
29161 }
29162 self.write(")");
29163 if let Some(sorted_by) = &e.sorted_by {
29164 self.write_space();
29165 self.write_keyword("SORTED BY");
29166 self.write(" (");
29167 if let Expression::Tuple(t) = sorted_by.as_ref() {
29169 for (i, expr) in t.expressions.iter().enumerate() {
29170 if i > 0 {
29171 self.write(", ");
29172 }
29173 self.generate_expression(expr)?;
29174 }
29175 } else {
29176 self.generate_expression(sorted_by)?;
29177 }
29178 self.write(")");
29179 }
29180 if let Some(buckets) = &e.buckets {
29181 self.write_space();
29182 self.write_keyword("INTO");
29183 self.write_space();
29184 self.generate_expression(buckets)?;
29185 self.write_space();
29186 self.write_keyword("BUCKETS");
29187 }
29188 Ok(())
29189 }
29190
29191 fn generate_collate_property(&mut self, e: &CollateProperty) -> Result<()> {
29192 if e.default.is_some() {
29196 self.write_keyword("DEFAULT");
29197 self.write_space();
29198 }
29199 self.write_keyword("COLLATE");
29200 match self.config.dialect {
29202 Some(DialectType::BigQuery) => self.write_space(),
29203 _ => self.write("="),
29204 }
29205 self.generate_expression(&e.this)?;
29206 Ok(())
29207 }
29208
29209 fn generate_column_constraint(&mut self, e: &ColumnConstraint) -> Result<()> {
29210 match e {
29212 ColumnConstraint::NotNull => {
29213 self.write_keyword("NOT NULL");
29214 }
29215 ColumnConstraint::Null => {
29216 self.write_keyword("NULL");
29217 }
29218 ColumnConstraint::Unique => {
29219 self.write_keyword("UNIQUE");
29220 }
29221 ColumnConstraint::PrimaryKey => {
29222 self.write_keyword("PRIMARY KEY");
29223 }
29224 ColumnConstraint::Default(expr) => {
29225 self.write_keyword("DEFAULT");
29226 self.write_space();
29227 self.generate_expression(expr)?;
29228 }
29229 ColumnConstraint::Check(expr) => {
29230 self.write_keyword("CHECK");
29231 self.write(" (");
29232 self.generate_expression(expr)?;
29233 self.write(")");
29234 }
29235 ColumnConstraint::References(fk_ref) => {
29236 if fk_ref.has_foreign_key_keywords {
29237 self.write_keyword("FOREIGN KEY");
29238 self.write_space();
29239 }
29240 self.write_keyword("REFERENCES");
29241 self.write_space();
29242 self.generate_table(&fk_ref.table)?;
29243 if !fk_ref.columns.is_empty() {
29244 self.write(" (");
29245 for (i, col) in fk_ref.columns.iter().enumerate() {
29246 if i > 0 {
29247 self.write(", ");
29248 }
29249 self.generate_identifier(col)?;
29250 }
29251 self.write(")");
29252 }
29253 }
29254 ColumnConstraint::GeneratedAsIdentity(gen) => {
29255 self.write_keyword("GENERATED");
29256 self.write_space();
29257 if gen.always {
29258 self.write_keyword("ALWAYS");
29259 } else {
29260 self.write_keyword("BY DEFAULT");
29261 if gen.on_null {
29262 self.write_space();
29263 self.write_keyword("ON NULL");
29264 }
29265 }
29266 self.write_space();
29267 self.write_keyword("AS IDENTITY");
29268 }
29269 ColumnConstraint::Collate(collation) => {
29270 self.write_keyword("COLLATE");
29271 self.write_space();
29272 self.generate_identifier(collation)?;
29273 }
29274 ColumnConstraint::Comment(comment) => {
29275 self.write_keyword("COMMENT");
29276 self.write(" '");
29277 self.write(comment);
29278 self.write("'");
29279 }
29280 ColumnConstraint::ComputedColumn(cc) => {
29281 self.generate_computed_column_inline(cc)?;
29282 }
29283 ColumnConstraint::GeneratedAsRow(gar) => {
29284 self.generate_generated_as_row_inline(gar)?;
29285 }
29286 ColumnConstraint::Tags(tags) => {
29287 self.write_keyword("TAG");
29288 self.write(" (");
29289 for (i, expr) in tags.expressions.iter().enumerate() {
29290 if i > 0 {
29291 self.write(", ");
29292 }
29293 self.generate_expression(expr)?;
29294 }
29295 self.write(")");
29296 }
29297 ColumnConstraint::Path(path_expr) => {
29298 self.write_keyword("PATH");
29299 self.write_space();
29300 self.generate_expression(path_expr)?;
29301 }
29302 }
29303 Ok(())
29304 }
29305
29306 fn generate_column_position(&mut self, e: &ColumnPosition) -> Result<()> {
29307 match e {
29309 ColumnPosition::First => {
29310 self.write_keyword("FIRST");
29311 }
29312 ColumnPosition::After(ident) => {
29313 self.write_keyword("AFTER");
29314 self.write_space();
29315 self.generate_identifier(ident)?;
29316 }
29317 }
29318 Ok(())
29319 }
29320
29321 fn generate_column_prefix(&mut self, e: &ColumnPrefix) -> Result<()> {
29322 self.generate_expression(&e.this)?;
29324 self.write("(");
29325 self.generate_expression(&e.expression)?;
29326 self.write(")");
29327 Ok(())
29328 }
29329
29330 fn generate_columns(&mut self, e: &Columns) -> Result<()> {
29331 if let Some(ref unpack) = e.unpack {
29334 if let Expression::Boolean(b) = unpack.as_ref() {
29335 if b.value {
29336 self.write("*");
29337 }
29338 }
29339 }
29340 self.write_keyword("COLUMNS");
29341 self.write("(");
29342 self.generate_expression(&e.this)?;
29343 self.write(")");
29344 Ok(())
29345 }
29346
29347 fn generate_combined_agg_func(&mut self, e: &CombinedAggFunc) -> Result<()> {
29348 self.generate_expression(&e.this)?;
29350 self.write("(");
29351 for (i, expr) in e.expressions.iter().enumerate() {
29352 if i > 0 {
29353 self.write(", ");
29354 }
29355 self.generate_expression(expr)?;
29356 }
29357 self.write(")");
29358 Ok(())
29359 }
29360
29361 fn generate_combined_parameterized_agg(&mut self, e: &CombinedParameterizedAgg) -> Result<()> {
29362 self.generate_expression(&e.this)?;
29364 self.write("(");
29365 for (i, param) in e.params.iter().enumerate() {
29366 if i > 0 {
29367 self.write(", ");
29368 }
29369 self.generate_expression(param)?;
29370 }
29371 self.write(")(");
29372 for (i, expr) in e.expressions.iter().enumerate() {
29373 if i > 0 {
29374 self.write(", ");
29375 }
29376 self.generate_expression(expr)?;
29377 }
29378 self.write(")");
29379 Ok(())
29380 }
29381
29382 fn generate_commit(&mut self, e: &Commit) -> Result<()> {
29383 self.write_keyword("COMMIT");
29385
29386 if e.this.is_none()
29388 && matches!(
29389 self.config.dialect,
29390 Some(DialectType::TSQL) | Some(DialectType::Fabric)
29391 )
29392 {
29393 self.write_space();
29394 self.write_keyword("TRANSACTION");
29395 }
29396
29397 if let Some(this) = &e.this {
29399 let is_transaction_marker = matches!(
29401 this.as_ref(),
29402 Expression::Identifier(id) if id.name == "TRANSACTION"
29403 );
29404
29405 self.write_space();
29406 self.write_keyword("TRANSACTION");
29407
29408 if !is_transaction_marker {
29410 self.write_space();
29411 self.generate_expression(this)?;
29412 }
29413 }
29414
29415 if let Some(durability) = &e.durability {
29417 self.write_space();
29418 self.write_keyword("WITH");
29419 self.write(" (");
29420 self.write_keyword("DELAYED_DURABILITY");
29421 self.write(" = ");
29422 if let Expression::Boolean(BooleanLiteral { value: true }) = durability.as_ref() {
29423 self.write_keyword("ON");
29424 } else {
29425 self.write_keyword("OFF");
29426 }
29427 self.write(")");
29428 }
29429
29430 if let Some(chain) = &e.chain {
29432 self.write_space();
29433 if let Expression::Boolean(BooleanLiteral { value: false }) = chain.as_ref() {
29434 self.write_keyword("AND NO CHAIN");
29435 } else {
29436 self.write_keyword("AND CHAIN");
29437 }
29438 }
29439 Ok(())
29440 }
29441
29442 fn generate_comprehension(&mut self, e: &Comprehension) -> Result<()> {
29443 self.write("[");
29445 self.generate_expression(&e.this)?;
29446 self.write_space();
29447 self.write_keyword("FOR");
29448 self.write_space();
29449 self.generate_expression(&e.expression)?;
29450 if let Some(pos) = &e.position {
29452 self.write(", ");
29453 self.generate_expression(pos)?;
29454 }
29455 if let Some(iterator) = &e.iterator {
29456 self.write_space();
29457 self.write_keyword("IN");
29458 self.write_space();
29459 self.generate_expression(iterator)?;
29460 }
29461 if let Some(condition) = &e.condition {
29462 self.write_space();
29463 self.write_keyword("IF");
29464 self.write_space();
29465 self.generate_expression(condition)?;
29466 }
29467 self.write("]");
29468 Ok(())
29469 }
29470
29471 fn generate_compress(&mut self, e: &Compress) -> Result<()> {
29472 self.write_keyword("COMPRESS");
29474 self.write("(");
29475 self.generate_expression(&e.this)?;
29476 if let Some(method) = &e.method {
29477 self.write(", '");
29478 self.write(method);
29479 self.write("'");
29480 }
29481 self.write(")");
29482 Ok(())
29483 }
29484
29485 fn generate_compress_column_constraint(&mut self, e: &CompressColumnConstraint) -> Result<()> {
29486 self.write_keyword("COMPRESS");
29488 if let Some(this) = &e.this {
29489 self.write_space();
29490 self.generate_expression(this)?;
29491 }
29492 Ok(())
29493 }
29494
29495 fn generate_computed_column_constraint(&mut self, e: &ComputedColumnConstraint) -> Result<()> {
29496 self.write_keyword("AS");
29498 self.write_space();
29499 self.generate_expression(&e.this)?;
29500 if e.not_null.is_some() {
29501 self.write_space();
29502 self.write_keyword("PERSISTED NOT NULL");
29503 } else if e.persisted.is_some() {
29504 self.write_space();
29505 self.write_keyword("PERSISTED");
29506 }
29507 Ok(())
29508 }
29509
29510 fn generate_computed_column_inline(&mut self, cc: &ComputedColumn) -> Result<()> {
29514 let computed_expr = if matches!(
29515 self.config.dialect,
29516 Some(DialectType::TSQL) | Some(DialectType::Fabric)
29517 ) {
29518 match &*cc.expression {
29519 Expression::Year(y) if !matches!(&y.this, Expression::Cast(c) if matches!(c.to, DataType::Date)) =>
29520 {
29521 let wrapped = Expression::Cast(Box::new(Cast {
29522 this: y.this.clone(),
29523 to: DataType::Date,
29524 trailing_comments: Vec::new(),
29525 double_colon_syntax: false,
29526 format: None,
29527 default: None,
29528 inferred_type: None,
29529 }));
29530 Expression::Year(Box::new(UnaryFunc::new(wrapped)))
29531 }
29532 Expression::Function(f)
29533 if f.name.eq_ignore_ascii_case("YEAR")
29534 && f.args.len() == 1
29535 && !matches!(&f.args[0], Expression::Cast(c) if matches!(c.to, DataType::Date)) =>
29536 {
29537 let wrapped = Expression::Cast(Box::new(Cast {
29538 this: f.args[0].clone(),
29539 to: DataType::Date,
29540 trailing_comments: Vec::new(),
29541 double_colon_syntax: false,
29542 format: None,
29543 default: None,
29544 inferred_type: None,
29545 }));
29546 Expression::Function(Box::new(Function::new("YEAR".to_string(), vec![wrapped])))
29547 }
29548 _ => *cc.expression.clone(),
29549 }
29550 } else {
29551 *cc.expression.clone()
29552 };
29553
29554 match cc.persistence_kind.as_deref() {
29555 Some("STORED") | Some("VIRTUAL") => {
29556 self.write_keyword("GENERATED ALWAYS AS");
29558 self.write(" (");
29559 self.generate_expression(&computed_expr)?;
29560 self.write(")");
29561 self.write_space();
29562 if cc.persisted {
29563 self.write_keyword("STORED");
29564 } else {
29565 self.write_keyword("VIRTUAL");
29566 }
29567 }
29568 Some("PERSISTED") => {
29569 self.write_keyword("AS");
29571 self.write(" (");
29572 self.generate_expression(&computed_expr)?;
29573 self.write(")");
29574 self.write_space();
29575 self.write_keyword("PERSISTED");
29576 if let Some(ref dt) = cc.data_type {
29578 self.write_space();
29579 self.generate_data_type(dt)?;
29580 }
29581 if cc.not_null {
29582 self.write_space();
29583 self.write_keyword("NOT NULL");
29584 }
29585 }
29586 _ => {
29587 if matches!(
29590 self.config.dialect,
29591 Some(DialectType::Spark)
29592 | Some(DialectType::Databricks)
29593 | Some(DialectType::Hive)
29594 ) {
29595 self.write_keyword("GENERATED ALWAYS AS");
29596 self.write(" (");
29597 self.generate_expression(&computed_expr)?;
29598 self.write(")");
29599 } else if matches!(
29600 self.config.dialect,
29601 Some(DialectType::TSQL) | Some(DialectType::Fabric)
29602 ) {
29603 self.write_keyword("AS");
29604 let omit_parens = matches!(computed_expr, Expression::Year(_))
29605 || matches!(&computed_expr, Expression::Function(f) if f.name.eq_ignore_ascii_case("YEAR"));
29606 if omit_parens {
29607 self.write_space();
29608 self.generate_expression(&computed_expr)?;
29609 } else {
29610 self.write(" (");
29611 self.generate_expression(&computed_expr)?;
29612 self.write(")");
29613 }
29614 } else {
29615 self.write_keyword("AS");
29616 self.write(" (");
29617 self.generate_expression(&computed_expr)?;
29618 self.write(")");
29619 }
29620 }
29621 }
29622 Ok(())
29623 }
29624
29625 fn generate_generated_as_row_inline(&mut self, gar: &GeneratedAsRow) -> Result<()> {
29628 self.write_keyword("GENERATED ALWAYS AS ROW ");
29629 if gar.start {
29630 self.write_keyword("START");
29631 } else {
29632 self.write_keyword("END");
29633 }
29634 if gar.hidden {
29635 self.write_space();
29636 self.write_keyword("HIDDEN");
29637 }
29638 Ok(())
29639 }
29640
29641 fn generate_system_versioning_content(
29643 &mut self,
29644 e: &WithSystemVersioningProperty,
29645 ) -> Result<()> {
29646 let mut parts = Vec::new();
29647
29648 if let Some(this) = &e.this {
29649 let mut s = String::from("HISTORY_TABLE=");
29650 let mut gen = Generator::with_arc_config(self.config.clone());
29651 gen.generate_expression(this)?;
29652 s.push_str(&gen.output);
29653 parts.push(s);
29654 }
29655
29656 if let Some(data_consistency) = &e.data_consistency {
29657 let mut s = String::from("DATA_CONSISTENCY_CHECK=");
29658 let mut gen = Generator::with_arc_config(self.config.clone());
29659 gen.generate_expression(data_consistency)?;
29660 s.push_str(&gen.output);
29661 parts.push(s);
29662 }
29663
29664 if let Some(retention_period) = &e.retention_period {
29665 let mut s = String::from("HISTORY_RETENTION_PERIOD=");
29666 let mut gen = Generator::with_arc_config(self.config.clone());
29667 gen.generate_expression(retention_period)?;
29668 s.push_str(&gen.output);
29669 parts.push(s);
29670 }
29671
29672 self.write_keyword("SYSTEM_VERSIONING");
29673 self.write("=");
29674
29675 if !parts.is_empty() {
29676 self.write_keyword("ON");
29677 self.write("(");
29678 self.write(&parts.join(", "));
29679 self.write(")");
29680 } else if e.on.is_some() {
29681 self.write_keyword("ON");
29682 } else {
29683 self.write_keyword("OFF");
29684 }
29685
29686 Ok(())
29687 }
29688
29689 fn generate_conditional_insert(&mut self, e: &ConditionalInsert) -> Result<()> {
29690 if e.else_.is_some() {
29693 self.write_keyword("ELSE");
29694 self.write_space();
29695 } else if let Some(expression) = &e.expression {
29696 self.write_keyword("WHEN");
29697 self.write_space();
29698 self.generate_expression(expression)?;
29699 self.write_space();
29700 self.write_keyword("THEN");
29701 self.write_space();
29702 }
29703
29704 if let Expression::Insert(insert) = e.this.as_ref() {
29707 self.write_keyword("INTO");
29708 self.write_space();
29709 self.generate_table(&insert.table)?;
29710
29711 if !insert.columns.is_empty() {
29713 self.write(" (");
29714 for (i, col) in insert.columns.iter().enumerate() {
29715 if i > 0 {
29716 self.write(", ");
29717 }
29718 self.generate_identifier(col)?;
29719 }
29720 self.write(")");
29721 }
29722
29723 if !insert.values.is_empty() {
29725 self.write_space();
29726 self.write_keyword("VALUES");
29727 for (row_idx, row) in insert.values.iter().enumerate() {
29728 if row_idx > 0 {
29729 self.write(", ");
29730 }
29731 self.write(" (");
29732 for (i, val) in row.iter().enumerate() {
29733 if i > 0 {
29734 self.write(", ");
29735 }
29736 self.generate_expression(val)?;
29737 }
29738 self.write(")");
29739 }
29740 }
29741 } else {
29742 self.generate_expression(&e.this)?;
29744 }
29745 Ok(())
29746 }
29747
29748 fn generate_constraint(&mut self, e: &Constraint) -> Result<()> {
29749 self.write_keyword("CONSTRAINT");
29751 self.write_space();
29752 self.generate_expression(&e.this)?;
29753 if !e.expressions.is_empty() {
29754 self.write_space();
29755 for (i, expr) in e.expressions.iter().enumerate() {
29756 if i > 0 {
29757 self.write_space();
29758 }
29759 self.generate_expression(expr)?;
29760 }
29761 }
29762 Ok(())
29763 }
29764
29765 fn generate_convert_timezone(&mut self, e: &ConvertTimezone) -> Result<()> {
29766 self.write_keyword("CONVERT_TIMEZONE");
29768 self.write("(");
29769 let mut first = true;
29770 if let Some(source_tz) = &e.source_tz {
29771 self.generate_expression(source_tz)?;
29772 first = false;
29773 }
29774 if let Some(target_tz) = &e.target_tz {
29775 if !first {
29776 self.write(", ");
29777 }
29778 self.generate_expression(target_tz)?;
29779 first = false;
29780 }
29781 if let Some(timestamp) = &e.timestamp {
29782 if !first {
29783 self.write(", ");
29784 }
29785 self.generate_expression(timestamp)?;
29786 }
29787 self.write(")");
29788 Ok(())
29789 }
29790
29791 fn generate_convert_to_charset(&mut self, e: &ConvertToCharset) -> Result<()> {
29792 self.write_keyword("CONVERT");
29794 self.write("(");
29795 self.generate_expression(&e.this)?;
29796 if let Some(dest) = &e.dest {
29797 self.write_space();
29798 self.write_keyword("USING");
29799 self.write_space();
29800 self.generate_expression(dest)?;
29801 }
29802 self.write(")");
29803 Ok(())
29804 }
29805
29806 fn generate_copy(&mut self, e: &CopyStmt) -> Result<()> {
29807 self.write_keyword("COPY");
29808 if e.is_into {
29809 self.write_space();
29810 self.write_keyword("INTO");
29811 }
29812 self.write_space();
29813
29814 if let Expression::Literal(lit) = &e.this {
29816 if let Literal::String(s) = lit.as_ref() {
29817 if s.starts_with('@') {
29818 self.write(s);
29819 } else {
29820 self.generate_expression(&e.this)?;
29821 }
29822 }
29823 } else {
29824 self.generate_expression(&e.this)?;
29825 }
29826
29827 if e.kind {
29829 if self.config.pretty {
29831 self.write_newline();
29832 } else {
29833 self.write_space();
29834 }
29835 self.write_keyword("FROM");
29836 self.write_space();
29837 } else if !e.files.is_empty() {
29838 if self.config.pretty {
29840 self.write_newline();
29841 } else {
29842 self.write_space();
29843 }
29844 self.write_keyword("TO");
29845 self.write_space();
29846 }
29847
29848 for (i, file) in e.files.iter().enumerate() {
29850 if i > 0 {
29851 self.write_space();
29852 }
29853 if let Expression::Literal(lit) = file {
29855 if let Literal::String(s) = lit.as_ref() {
29856 if s.starts_with('@') {
29857 self.write(s);
29858 } else {
29859 self.generate_expression(file)?;
29860 }
29861 }
29862 } else if let Expression::Identifier(id) = file {
29863 if id.quoted {
29865 self.write("`");
29866 self.write(&id.name);
29867 self.write("`");
29868 } else {
29869 self.generate_expression(file)?;
29870 }
29871 } else {
29872 self.generate_expression(file)?;
29873 }
29874 }
29875
29876 if !e.with_wrapped {
29878 if let Some(ref creds) = e.credentials {
29879 if let Some(ref storage) = creds.storage {
29880 if self.config.pretty {
29881 self.write_newline();
29882 } else {
29883 self.write_space();
29884 }
29885 self.write_keyword("STORAGE_INTEGRATION");
29886 self.write(" = ");
29887 self.write(storage);
29888 }
29889 if creds.credentials.is_empty() {
29890 if self.config.pretty {
29892 self.write_newline();
29893 } else {
29894 self.write_space();
29895 }
29896 self.write_keyword("CREDENTIALS");
29897 self.write(" = ()");
29898 } else {
29899 if self.config.pretty {
29900 self.write_newline();
29901 } else {
29902 self.write_space();
29903 }
29904 self.write_keyword("CREDENTIALS");
29905 if creds.credentials.len() == 1 && creds.credentials[0].0.is_empty() {
29908 self.write(" '");
29910 self.write(&creds.credentials[0].1);
29911 self.write("'");
29912 } else {
29913 self.write(" = (");
29915 for (i, (k, v)) in creds.credentials.iter().enumerate() {
29916 if i > 0 {
29917 self.write_space();
29918 }
29919 self.write(k);
29920 self.write("='");
29921 self.write(v);
29922 self.write("'");
29923 }
29924 self.write(")");
29925 }
29926 }
29927 if let Some(ref encryption) = creds.encryption {
29928 self.write_space();
29929 self.write_keyword("ENCRYPTION");
29930 self.write(" = ");
29931 self.write(encryption);
29932 }
29933 }
29934 }
29935
29936 if !e.params.is_empty() {
29938 if e.with_wrapped {
29939 self.write_space();
29941 self.write_keyword("WITH");
29942 self.write(" (");
29943 for (i, param) in e.params.iter().enumerate() {
29944 if i > 0 {
29945 self.write(", ");
29946 }
29947 self.generate_copy_param_with_format(param)?;
29948 }
29949 self.write(")");
29950 } else {
29951 for param in &e.params {
29955 if self.config.pretty {
29956 self.write_newline();
29957 } else {
29958 self.write_space();
29959 }
29960 self.write(¶m.name);
29962 if let Some(ref value) = param.value {
29963 if param.eq {
29965 self.write(" = ");
29966 } else {
29967 self.write(" ");
29968 }
29969 if !param.values.is_empty() {
29970 self.write("(");
29971 for (i, v) in param.values.iter().enumerate() {
29972 if i > 0 {
29973 self.write_space();
29974 }
29975 self.generate_copy_nested_param(v)?;
29976 }
29977 self.write(")");
29978 } else {
29979 self.generate_copy_param_value(value)?;
29981 }
29982 } else if !param.values.is_empty() {
29983 if param.eq {
29985 self.write(" = (");
29986 } else {
29987 self.write(" (");
29988 }
29989 let is_key_value_pairs = param
29994 .values
29995 .first()
29996 .map_or(false, |v| matches!(v, Expression::Eq(_)));
29997 let sep = if is_key_value_pairs && param.eq {
29998 " "
29999 } else {
30000 ", "
30001 };
30002 for (i, v) in param.values.iter().enumerate() {
30003 if i > 0 {
30004 self.write(sep);
30005 }
30006 self.generate_copy_nested_param(v)?;
30007 }
30008 self.write(")");
30009 }
30010 }
30011 }
30012 }
30013
30014 Ok(())
30015 }
30016
30017 fn generate_copy_param_with_format(&mut self, param: &CopyParameter) -> Result<()> {
30020 self.write_keyword(¶m.name);
30021 if !param.values.is_empty() {
30022 self.write(" = (");
30024 for (i, v) in param.values.iter().enumerate() {
30025 if i > 0 {
30026 self.write(", ");
30027 }
30028 self.generate_copy_nested_param(v)?;
30029 }
30030 self.write(")");
30031 } else if let Some(ref value) = param.value {
30032 if param.eq {
30033 self.write(" = ");
30034 } else {
30035 self.write(" ");
30036 }
30037 self.generate_expression(value)?;
30038 }
30039 Ok(())
30040 }
30041
30042 fn generate_copy_nested_param(&mut self, expr: &Expression) -> Result<()> {
30044 match expr {
30045 Expression::Eq(eq) => {
30046 match &eq.left {
30048 Expression::Column(c) => self.write(&c.name.name),
30049 _ => self.generate_expression(&eq.left)?,
30050 }
30051 self.write("=");
30052 match &eq.right {
30054 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
30055 let Literal::String(s) = lit.as_ref() else {
30056 unreachable!()
30057 };
30058 self.write("'");
30059 self.write(s);
30060 self.write("'");
30061 }
30062 Expression::Tuple(t) => {
30063 self.write("(");
30065 if self.config.pretty {
30066 self.write_newline();
30067 self.indent_level += 1;
30068 for (i, item) in t.expressions.iter().enumerate() {
30069 if i > 0 {
30070 self.write(", ");
30071 }
30072 self.write_indent();
30073 self.generate_expression(item)?;
30074 }
30075 self.write_newline();
30076 self.indent_level -= 1;
30077 } else {
30078 for (i, item) in t.expressions.iter().enumerate() {
30079 if i > 0 {
30080 self.write(", ");
30081 }
30082 self.generate_expression(item)?;
30083 }
30084 }
30085 self.write(")");
30086 }
30087 _ => self.generate_expression(&eq.right)?,
30088 }
30089 Ok(())
30090 }
30091 Expression::Column(c) => {
30092 self.write(&c.name.name);
30094 Ok(())
30095 }
30096 _ => self.generate_expression(expr),
30097 }
30098 }
30099
30100 fn generate_copy_param_value(&mut self, expr: &Expression) -> Result<()> {
30103 match expr {
30104 Expression::Column(c) => {
30105 if c.name.quoted {
30107 self.write("\"");
30108 self.write(&c.name.name);
30109 self.write("\"");
30110 } else {
30111 self.write(&c.name.name);
30112 }
30113 Ok(())
30114 }
30115 Expression::Identifier(id) => {
30116 if id.quoted {
30118 self.write("\"");
30119 self.write(&id.name);
30120 self.write("\"");
30121 } else {
30122 self.write(&id.name);
30123 }
30124 Ok(())
30125 }
30126 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
30127 let Literal::String(s) = lit.as_ref() else {
30128 unreachable!()
30129 };
30130 self.write("'");
30132 self.write(s);
30133 self.write("'");
30134 Ok(())
30135 }
30136 _ => self.generate_expression(expr),
30137 }
30138 }
30139
30140 fn generate_copy_parameter(&mut self, e: &CopyParameter) -> Result<()> {
30141 self.write_keyword(&e.name);
30142 if let Some(ref value) = e.value {
30143 if e.eq {
30144 self.write(" = ");
30145 } else {
30146 self.write(" ");
30147 }
30148 self.generate_expression(value)?;
30149 }
30150 if !e.values.is_empty() {
30151 if e.eq {
30152 self.write(" = ");
30153 } else {
30154 self.write(" ");
30155 }
30156 self.write("(");
30157 for (i, v) in e.values.iter().enumerate() {
30158 if i > 0 {
30159 self.write(", ");
30160 }
30161 self.generate_expression(v)?;
30162 }
30163 self.write(")");
30164 }
30165 Ok(())
30166 }
30167
30168 fn generate_corr(&mut self, e: &Corr) -> Result<()> {
30169 self.write_keyword("CORR");
30171 self.write("(");
30172 self.generate_expression(&e.this)?;
30173 self.write(", ");
30174 self.generate_expression(&e.expression)?;
30175 self.write(")");
30176 Ok(())
30177 }
30178
30179 fn generate_cosine_distance(&mut self, e: &CosineDistance) -> Result<()> {
30180 self.write_keyword("COSINE_DISTANCE");
30182 self.write("(");
30183 self.generate_expression(&e.this)?;
30184 self.write(", ");
30185 self.generate_expression(&e.expression)?;
30186 self.write(")");
30187 Ok(())
30188 }
30189
30190 fn generate_covar_pop(&mut self, e: &CovarPop) -> Result<()> {
30191 self.write_keyword("COVAR_POP");
30193 self.write("(");
30194 self.generate_expression(&e.this)?;
30195 self.write(", ");
30196 self.generate_expression(&e.expression)?;
30197 self.write(")");
30198 Ok(())
30199 }
30200
30201 fn generate_covar_samp(&mut self, e: &CovarSamp) -> Result<()> {
30202 self.write_keyword("COVAR_SAMP");
30204 self.write("(");
30205 self.generate_expression(&e.this)?;
30206 self.write(", ");
30207 self.generate_expression(&e.expression)?;
30208 self.write(")");
30209 Ok(())
30210 }
30211
30212 fn generate_credentials(&mut self, e: &Credentials) -> Result<()> {
30213 self.write_keyword("CREDENTIALS");
30215 self.write(" (");
30216 for (i, (key, value)) in e.credentials.iter().enumerate() {
30217 if i > 0 {
30218 self.write(", ");
30219 }
30220 self.write(key);
30221 self.write("='");
30222 self.write(value);
30223 self.write("'");
30224 }
30225 self.write(")");
30226 Ok(())
30227 }
30228
30229 fn generate_credentials_property(&mut self, e: &CredentialsProperty) -> Result<()> {
30230 self.write_keyword("CREDENTIALS");
30232 self.write("=(");
30233 for (i, expr) in e.expressions.iter().enumerate() {
30234 if i > 0 {
30235 self.write(", ");
30236 }
30237 self.generate_expression(expr)?;
30238 }
30239 self.write(")");
30240 Ok(())
30241 }
30242
30243 fn generate_cte(&mut self, e: &Cte) -> Result<()> {
30244 use crate::dialects::DialectType;
30245
30246 if matches!(self.config.dialect, Some(DialectType::ClickHouse)) && !e.alias_first {
30249 self.generate_expression(&e.this)?;
30250 self.write_space();
30251 self.write_keyword("AS");
30252 self.write_space();
30253 self.generate_identifier(&e.alias)?;
30254 return Ok(());
30255 }
30256 self.write(&e.alias.name);
30257
30258 let skip_cte_columns = matches!(self.config.dialect, Some(DialectType::BigQuery));
30260
30261 if !e.columns.is_empty() && !skip_cte_columns {
30262 self.write("(");
30263 for (i, col) in e.columns.iter().enumerate() {
30264 if i > 0 {
30265 self.write(", ");
30266 }
30267 self.write(&col.name);
30268 }
30269 self.write(")");
30270 }
30271 if !e.key_expressions.is_empty() {
30273 self.write_space();
30274 self.write_keyword("USING KEY");
30275 self.write(" (");
30276 for (i, key) in e.key_expressions.iter().enumerate() {
30277 if i > 0 {
30278 self.write(", ");
30279 }
30280 self.write(&key.name);
30281 }
30282 self.write(")");
30283 }
30284 self.write_space();
30285 self.write_keyword("AS");
30286 self.write_space();
30287 if let Some(materialized) = e.materialized {
30288 if materialized {
30289 self.write_keyword("MATERIALIZED");
30290 } else {
30291 self.write_keyword("NOT MATERIALIZED");
30292 }
30293 self.write_space();
30294 }
30295 self.write("(");
30296 self.generate_expression(&e.this)?;
30297 self.write(")");
30298 Ok(())
30299 }
30300
30301 fn generate_cube(&mut self, e: &Cube) -> Result<()> {
30302 if e.expressions.is_empty() {
30304 self.write_keyword("WITH CUBE");
30305 } else {
30306 self.write_keyword("CUBE");
30307 self.write("(");
30308 for (i, expr) in e.expressions.iter().enumerate() {
30309 if i > 0 {
30310 self.write(", ");
30311 }
30312 self.generate_expression(expr)?;
30313 }
30314 self.write(")");
30315 }
30316 Ok(())
30317 }
30318
30319 fn generate_current_datetime(&mut self, e: &CurrentDatetime) -> Result<()> {
30320 self.write_keyword("CURRENT_DATETIME");
30322 if let Some(this) = &e.this {
30323 self.write("(");
30324 self.generate_expression(this)?;
30325 self.write(")");
30326 }
30327 Ok(())
30328 }
30329
30330 fn generate_current_schema(&mut self, _e: &CurrentSchema) -> Result<()> {
30331 self.write_keyword("CURRENT_SCHEMA");
30333 Ok(())
30334 }
30335
30336 fn generate_current_schemas(&mut self, e: &CurrentSchemas) -> Result<()> {
30337 self.write_keyword("CURRENT_SCHEMAS");
30339 self.write("(");
30340 if !matches!(
30342 self.config.dialect,
30343 Some(crate::dialects::DialectType::Snowflake)
30344 ) {
30345 if let Some(this) = &e.this {
30346 self.generate_expression(this)?;
30347 }
30348 }
30349 self.write(")");
30350 Ok(())
30351 }
30352
30353 fn generate_current_user(&mut self, e: &CurrentUser) -> Result<()> {
30354 self.write_keyword("CURRENT_USER");
30356 let needs_parens = e.this.is_some()
30358 || matches!(
30359 self.config.dialect,
30360 Some(DialectType::Snowflake)
30361 | Some(DialectType::Spark)
30362 | Some(DialectType::Hive)
30363 | Some(DialectType::DuckDB)
30364 | Some(DialectType::BigQuery)
30365 | Some(DialectType::MySQL)
30366 | Some(DialectType::Databricks)
30367 );
30368 if needs_parens {
30369 self.write("()");
30370 }
30371 Ok(())
30372 }
30373
30374 fn generate_d_pipe(&mut self, e: &DPipe) -> Result<()> {
30375 if self.config.dialect == Some(DialectType::Solr) {
30377 self.generate_expression(&e.this)?;
30378 self.write(" ");
30379 self.write_keyword("OR");
30380 self.write(" ");
30381 self.generate_expression(&e.expression)?;
30382 } else if self.config.dialect == Some(DialectType::MySQL) {
30383 self.generate_mysql_concat_from_dpipe(e)?;
30384 } else {
30385 self.generate_expression(&e.this)?;
30387 self.write(" || ");
30388 self.generate_expression(&e.expression)?;
30389 }
30390 Ok(())
30391 }
30392
30393 fn generate_data_blocksize_property(&mut self, e: &DataBlocksizeProperty) -> Result<()> {
30394 self.write_keyword("DATABLOCKSIZE");
30396 self.write("=");
30397 if let Some(size) = e.size {
30398 self.write(&size.to_string());
30399 if let Some(units) = &e.units {
30400 self.write_space();
30401 self.generate_expression(units)?;
30402 }
30403 } else if e.minimum.is_some() {
30404 self.write_keyword("MINIMUM");
30405 } else if e.maximum.is_some() {
30406 self.write_keyword("MAXIMUM");
30407 } else if e.default.is_some() {
30408 self.write_keyword("DEFAULT");
30409 }
30410 Ok(())
30411 }
30412
30413 fn generate_data_deletion_property(&mut self, e: &DataDeletionProperty) -> Result<()> {
30414 self.write_keyword("DATA_DELETION");
30416 self.write("=");
30417
30418 let is_on = matches!(&*e.on, Expression::Boolean(BooleanLiteral { value: true }));
30419 let has_options = e.filter_column.is_some() || e.retention_period.is_some();
30420
30421 if is_on {
30422 self.write_keyword("ON");
30423 if has_options {
30424 self.write("(");
30425 let mut first = true;
30426 if let Some(filter_column) = &e.filter_column {
30427 self.write_keyword("FILTER_COLUMN");
30428 self.write("=");
30429 self.generate_expression(filter_column)?;
30430 first = false;
30431 }
30432 if let Some(retention_period) = &e.retention_period {
30433 if !first {
30434 self.write(", ");
30435 }
30436 self.write_keyword("RETENTION_PERIOD");
30437 self.write("=");
30438 self.generate_expression(retention_period)?;
30439 }
30440 self.write(")");
30441 }
30442 } else {
30443 self.write_keyword("OFF");
30444 }
30445 Ok(())
30446 }
30447
30448 fn generate_date_func(&mut self, e: &UnaryFunc) -> Result<()> {
30452 use crate::dialects::DialectType;
30453 use crate::expressions::Literal;
30454
30455 match self.config.dialect {
30456 Some(DialectType::Exasol) => {
30458 self.write_keyword("TO_DATE");
30459 self.write("(");
30460 match &e.this {
30462 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
30463 let Literal::String(s) = lit.as_ref() else {
30464 unreachable!()
30465 };
30466 self.write("'");
30467 self.write(s);
30468 self.write("'");
30469 }
30470 _ => {
30471 self.generate_expression(&e.this)?;
30472 }
30473 }
30474 self.write(")");
30475 }
30476 _ => {
30478 self.write_keyword("DATE");
30479 self.write("(");
30480 self.generate_expression(&e.this)?;
30481 self.write(")");
30482 }
30483 }
30484 Ok(())
30485 }
30486
30487 fn generate_date_bin(&mut self, e: &DateBin) -> Result<()> {
30488 self.write_keyword("DATE_BIN");
30490 self.write("(");
30491 self.generate_expression(&e.this)?;
30492 self.write(", ");
30493 self.generate_expression(&e.expression)?;
30494 if let Some(origin) = &e.origin {
30495 self.write(", ");
30496 self.generate_expression(origin)?;
30497 }
30498 self.write(")");
30499 Ok(())
30500 }
30501
30502 fn generate_date_format_column_constraint(
30503 &mut self,
30504 e: &DateFormatColumnConstraint,
30505 ) -> Result<()> {
30506 self.write_keyword("FORMAT");
30508 self.write_space();
30509 self.generate_expression(&e.this)?;
30510 Ok(())
30511 }
30512
30513 fn generate_date_from_parts(&mut self, e: &DateFromParts) -> Result<()> {
30514 self.write_keyword("DATE_FROM_PARTS");
30516 self.write("(");
30517 let mut first = true;
30518 if let Some(year) = &e.year {
30519 self.generate_expression(year)?;
30520 first = false;
30521 }
30522 if let Some(month) = &e.month {
30523 if !first {
30524 self.write(", ");
30525 }
30526 self.generate_expression(month)?;
30527 first = false;
30528 }
30529 if let Some(day) = &e.day {
30530 if !first {
30531 self.write(", ");
30532 }
30533 self.generate_expression(day)?;
30534 }
30535 self.write(")");
30536 Ok(())
30537 }
30538
30539 fn generate_datetime(&mut self, e: &Datetime) -> Result<()> {
30540 self.write_keyword("DATETIME");
30542 self.write("(");
30543 self.generate_expression(&e.this)?;
30544 if let Some(expr) = &e.expression {
30545 self.write(", ");
30546 self.generate_expression(expr)?;
30547 }
30548 self.write(")");
30549 Ok(())
30550 }
30551
30552 fn generate_datetime_add(&mut self, e: &DatetimeAdd) -> Result<()> {
30553 self.write_keyword("DATETIME_ADD");
30555 self.write("(");
30556 self.generate_expression(&e.this)?;
30557 self.write(", ");
30558 self.generate_expression(&e.expression)?;
30559 if let Some(unit) = &e.unit {
30560 self.write(", ");
30561 self.write_keyword(unit);
30562 }
30563 self.write(")");
30564 Ok(())
30565 }
30566
30567 fn generate_datetime_diff(&mut self, e: &DatetimeDiff) -> Result<()> {
30568 self.write_keyword("DATETIME_DIFF");
30570 self.write("(");
30571 self.generate_expression(&e.this)?;
30572 self.write(", ");
30573 self.generate_expression(&e.expression)?;
30574 if let Some(unit) = &e.unit {
30575 self.write(", ");
30576 self.write_keyword(unit);
30577 }
30578 self.write(")");
30579 Ok(())
30580 }
30581
30582 fn generate_datetime_sub(&mut self, e: &DatetimeSub) -> Result<()> {
30583 self.write_keyword("DATETIME_SUB");
30585 self.write("(");
30586 self.generate_expression(&e.this)?;
30587 self.write(", ");
30588 self.generate_expression(&e.expression)?;
30589 if let Some(unit) = &e.unit {
30590 self.write(", ");
30591 self.write_keyword(unit);
30592 }
30593 self.write(")");
30594 Ok(())
30595 }
30596
30597 fn generate_datetime_trunc(&mut self, e: &DatetimeTrunc) -> Result<()> {
30598 self.write_keyword("DATETIME_TRUNC");
30600 self.write("(");
30601 self.generate_expression(&e.this)?;
30602 self.write(", ");
30603 self.write_keyword(&e.unit);
30604 if let Some(zone) = &e.zone {
30605 self.write(", ");
30606 self.generate_expression(zone)?;
30607 }
30608 self.write(")");
30609 Ok(())
30610 }
30611
30612 fn generate_dayname(&mut self, e: &Dayname) -> Result<()> {
30613 self.write_keyword("DAYNAME");
30615 self.write("(");
30616 self.generate_expression(&e.this)?;
30617 self.write(")");
30618 Ok(())
30619 }
30620
30621 fn generate_declare(&mut self, e: &Declare) -> Result<()> {
30622 self.write_keyword("DECLARE");
30624 self.write_space();
30625 if e.replace {
30626 self.write_keyword("OR");
30627 self.write_space();
30628 self.write_keyword("REPLACE");
30629 self.write_space();
30630 }
30631 for (i, expr) in e.expressions.iter().enumerate() {
30632 if i > 0 {
30633 self.write(", ");
30634 }
30635 self.generate_expression(expr)?;
30636 }
30637 Ok(())
30638 }
30639
30640 fn generate_declare_item(&mut self, e: &DeclareItem) -> Result<()> {
30641 use crate::dialects::DialectType;
30642
30643 self.generate_expression(&e.this)?;
30645 for name in &e.additional_names {
30647 self.write(", ");
30648 self.generate_expression(name)?;
30649 }
30650 if let Some(kind) = &e.kind {
30651 self.write_space();
30652 match self.config.dialect {
30656 Some(DialectType::BigQuery) => {
30657 self.write(kind);
30658 }
30659 Some(DialectType::TSQL) => {
30660 let is_complex_table = kind.starts_with("TABLE")
30664 && (kind.contains("CLUSTERED") || kind.contains("INDEX"));
30665 if is_complex_table {
30666 self.write(kind);
30667 } else if kind == "INT" {
30668 self.write("INTEGER");
30669 } else if kind.starts_with("TABLE") {
30670 let normalized = kind
30672 .replace(" INT ", " INTEGER ")
30673 .replace(" INT,", " INTEGER,")
30674 .replace(" INT)", " INTEGER)")
30675 .replace("(INT ", "(INTEGER ");
30676 self.write(&normalized);
30677 } else {
30678 self.write(kind);
30679 }
30680 }
30681 _ => {
30682 if e.has_as {
30683 self.write_keyword("AS");
30684 self.write_space();
30685 }
30686 self.write(kind);
30687 }
30688 }
30689 }
30690 if let Some(default) = &e.default {
30691 match self.config.dialect {
30693 Some(DialectType::BigQuery) => {
30694 self.write_space();
30695 self.write_keyword("DEFAULT");
30696 self.write_space();
30697 }
30698 _ => {
30699 self.write(" = ");
30700 }
30701 }
30702 self.generate_expression(default)?;
30703 }
30704 Ok(())
30705 }
30706
30707 fn generate_decode_case(&mut self, e: &DecodeCase) -> Result<()> {
30708 self.write_keyword("DECODE");
30710 self.write("(");
30711 for (i, expr) in e.expressions.iter().enumerate() {
30712 if i > 0 {
30713 self.write(", ");
30714 }
30715 self.generate_expression(expr)?;
30716 }
30717 self.write(")");
30718 Ok(())
30719 }
30720
30721 fn generate_decompress_binary(&mut self, e: &DecompressBinary) -> Result<()> {
30722 self.write_keyword("DECOMPRESS");
30724 self.write("(");
30725 self.generate_expression(&e.this)?;
30726 self.write(", '");
30727 self.write(&e.method);
30728 self.write("')");
30729 Ok(())
30730 }
30731
30732 fn generate_decompress_string(&mut self, e: &DecompressString) -> Result<()> {
30733 self.write_keyword("DECOMPRESS");
30735 self.write("(");
30736 self.generate_expression(&e.this)?;
30737 self.write(", '");
30738 self.write(&e.method);
30739 self.write("')");
30740 Ok(())
30741 }
30742
30743 fn generate_decrypt(&mut self, e: &Decrypt) -> Result<()> {
30744 self.write_keyword("DECRYPT");
30746 self.write("(");
30747 self.generate_expression(&e.this)?;
30748 if let Some(passphrase) = &e.passphrase {
30749 self.write(", ");
30750 self.generate_expression(passphrase)?;
30751 }
30752 if let Some(aad) = &e.aad {
30753 self.write(", ");
30754 self.generate_expression(aad)?;
30755 }
30756 if let Some(method) = &e.encryption_method {
30757 self.write(", ");
30758 self.generate_expression(method)?;
30759 }
30760 self.write(")");
30761 Ok(())
30762 }
30763
30764 fn generate_decrypt_raw(&mut self, e: &DecryptRaw) -> Result<()> {
30765 self.write_keyword("DECRYPT_RAW");
30767 self.write("(");
30768 self.generate_expression(&e.this)?;
30769 if let Some(key) = &e.key {
30770 self.write(", ");
30771 self.generate_expression(key)?;
30772 }
30773 if let Some(iv) = &e.iv {
30774 self.write(", ");
30775 self.generate_expression(iv)?;
30776 }
30777 if let Some(aad) = &e.aad {
30778 self.write(", ");
30779 self.generate_expression(aad)?;
30780 }
30781 if let Some(method) = &e.encryption_method {
30782 self.write(", ");
30783 self.generate_expression(method)?;
30784 }
30785 self.write(")");
30786 Ok(())
30787 }
30788
30789 fn generate_definer_property(&mut self, e: &DefinerProperty) -> Result<()> {
30790 self.write_keyword("DEFINER");
30792 self.write(" = ");
30793 self.generate_expression(&e.this)?;
30794 Ok(())
30795 }
30796
30797 fn generate_detach(&mut self, e: &Detach) -> Result<()> {
30798 self.write_keyword("DETACH");
30800 if e.exists {
30801 self.write_keyword(" DATABASE IF EXISTS");
30802 }
30803 self.write_space();
30804 self.generate_expression(&e.this)?;
30805 Ok(())
30806 }
30807
30808 fn generate_dict_property(&mut self, e: &DictProperty) -> Result<()> {
30809 let property_name = match e.this.as_ref() {
30810 Expression::Identifier(id) => id.name.as_str(),
30811 Expression::Var(v) => v.this.as_str(),
30812 _ => "DICTIONARY",
30813 };
30814 self.write_keyword(property_name);
30815 self.write("(");
30816 self.write(&e.kind);
30817 if let Some(settings) = &e.settings {
30818 self.write("(");
30819 if let Expression::Tuple(t) = settings.as_ref() {
30820 if self.config.pretty && !t.expressions.is_empty() {
30821 self.write_newline();
30822 self.indent_level += 1;
30823 for (i, pair) in t.expressions.iter().enumerate() {
30824 if i > 0 {
30825 self.write(",");
30826 self.write_newline();
30827 }
30828 self.write_indent();
30829 if let Expression::Tuple(pair_tuple) = pair {
30830 if let Some(k) = pair_tuple.expressions.first() {
30831 self.generate_expression(k)?;
30832 }
30833 if let Some(v) = pair_tuple.expressions.get(1) {
30834 self.write(" ");
30835 self.generate_expression(v)?;
30836 }
30837 } else {
30838 self.generate_expression(pair)?;
30839 }
30840 }
30841 self.indent_level -= 1;
30842 self.write_newline();
30843 self.write_indent();
30844 } else {
30845 for (i, pair) in t.expressions.iter().enumerate() {
30846 if i > 0 {
30847 self.write(" ");
30849 }
30850 if let Expression::Tuple(pair_tuple) = pair {
30851 if let Some(k) = pair_tuple.expressions.first() {
30852 self.generate_expression(k)?;
30853 }
30854 if let Some(v) = pair_tuple.expressions.get(1) {
30855 self.write(" ");
30856 self.generate_expression(v)?;
30857 }
30858 } else {
30859 self.generate_expression(pair)?;
30860 }
30861 }
30862 }
30863 } else {
30864 self.generate_expression(settings)?;
30865 }
30866 self.write(")");
30867 } else {
30868 self.write("()");
30870 }
30871 self.write(")");
30872 Ok(())
30873 }
30874
30875 fn generate_dict_range(&mut self, e: &DictRange) -> Result<()> {
30876 let property_name = match e.this.as_ref() {
30877 Expression::Identifier(id) => id.name.as_str(),
30878 Expression::Var(v) => v.this.as_str(),
30879 _ => "RANGE",
30880 };
30881 self.write_keyword(property_name);
30882 self.write("(");
30883 if let Some(min) = &e.min {
30884 self.write_keyword("MIN");
30885 self.write_space();
30886 self.generate_expression(min)?;
30887 }
30888 if let Some(max) = &e.max {
30889 self.write_space();
30890 self.write_keyword("MAX");
30891 self.write_space();
30892 self.generate_expression(max)?;
30893 }
30894 self.write(")");
30895 Ok(())
30896 }
30897
30898 fn generate_directory(&mut self, e: &Directory) -> Result<()> {
30899 if e.local.is_some() {
30901 self.write_keyword("LOCAL ");
30902 }
30903 self.write_keyword("DIRECTORY");
30904 self.write_space();
30905 self.generate_expression(&e.this)?;
30906 if let Some(row_format) = &e.row_format {
30907 self.write_space();
30908 self.generate_expression(row_format)?;
30909 }
30910 Ok(())
30911 }
30912
30913 fn generate_dist_key_property(&mut self, e: &DistKeyProperty) -> Result<()> {
30914 self.write_keyword("DISTKEY");
30916 self.write("(");
30917 self.generate_expression(&e.this)?;
30918 self.write(")");
30919 Ok(())
30920 }
30921
30922 fn generate_dist_style_property(&mut self, e: &DistStyleProperty) -> Result<()> {
30923 self.write_keyword("DISTSTYLE");
30925 self.write_space();
30926 self.generate_expression(&e.this)?;
30927 Ok(())
30928 }
30929
30930 fn generate_distribute_by(&mut self, e: &DistributeBy) -> Result<()> {
30931 self.write_keyword("DISTRIBUTE BY");
30933 self.write_space();
30934 for (i, expr) in e.expressions.iter().enumerate() {
30935 if i > 0 {
30936 self.write(", ");
30937 }
30938 self.generate_expression(expr)?;
30939 }
30940 Ok(())
30941 }
30942
30943 fn generate_distributed_by_property(&mut self, e: &DistributedByProperty) -> Result<()> {
30944 self.write_keyword("DISTRIBUTED BY");
30946 self.write_space();
30947 self.write(&e.kind);
30948 if !e.expressions.is_empty() {
30949 self.write(" (");
30950 for (i, expr) in e.expressions.iter().enumerate() {
30951 if i > 0 {
30952 self.write(", ");
30953 }
30954 self.generate_expression(expr)?;
30955 }
30956 self.write(")");
30957 }
30958 if let Some(buckets) = &e.buckets {
30959 self.write_space();
30960 self.write_keyword("BUCKETS");
30961 self.write_space();
30962 self.generate_expression(buckets)?;
30963 }
30964 if let Some(order) = &e.order {
30965 self.write_space();
30966 self.generate_expression(order)?;
30967 }
30968 Ok(())
30969 }
30970
30971 fn generate_dot_product(&mut self, e: &DotProduct) -> Result<()> {
30972 self.write_keyword("DOT_PRODUCT");
30974 self.write("(");
30975 self.generate_expression(&e.this)?;
30976 self.write(", ");
30977 self.generate_expression(&e.expression)?;
30978 self.write(")");
30979 Ok(())
30980 }
30981
30982 fn generate_drop_partition(&mut self, e: &DropPartition) -> Result<()> {
30983 self.write_keyword("DROP");
30985 if e.exists {
30986 self.write_keyword(" IF EXISTS ");
30987 } else {
30988 self.write_space();
30989 }
30990 for (i, expr) in e.expressions.iter().enumerate() {
30991 if i > 0 {
30992 self.write(", ");
30993 }
30994 self.generate_expression(expr)?;
30995 }
30996 Ok(())
30997 }
30998
30999 fn generate_duplicate_key_property(&mut self, e: &DuplicateKeyProperty) -> Result<()> {
31000 self.write_keyword("DUPLICATE KEY");
31002 self.write(" (");
31003 for (i, expr) in e.expressions.iter().enumerate() {
31004 if i > 0 {
31005 self.write(", ");
31006 }
31007 self.generate_expression(expr)?;
31008 }
31009 self.write(")");
31010 Ok(())
31011 }
31012
31013 fn generate_elt(&mut self, e: &Elt) -> Result<()> {
31014 self.write_keyword("ELT");
31016 self.write("(");
31017 self.generate_expression(&e.this)?;
31018 for expr in &e.expressions {
31019 self.write(", ");
31020 self.generate_expression(expr)?;
31021 }
31022 self.write(")");
31023 Ok(())
31024 }
31025
31026 fn generate_encode(&mut self, e: &Encode) -> Result<()> {
31027 self.write_keyword("ENCODE");
31029 self.write("(");
31030 self.generate_expression(&e.this)?;
31031 if let Some(charset) = &e.charset {
31032 self.write(", ");
31033 self.generate_expression(charset)?;
31034 }
31035 self.write(")");
31036 Ok(())
31037 }
31038
31039 fn generate_encode_property(&mut self, e: &EncodeProperty) -> Result<()> {
31040 if e.key.is_some() {
31042 self.write_keyword("KEY ");
31043 }
31044 self.write_keyword("ENCODE");
31045 self.write_space();
31046 self.generate_expression(&e.this)?;
31047 if !e.properties.is_empty() {
31048 self.write(" (");
31049 for (i, prop) in e.properties.iter().enumerate() {
31050 if i > 0 {
31051 self.write(", ");
31052 }
31053 self.generate_expression(prop)?;
31054 }
31055 self.write(")");
31056 }
31057 Ok(())
31058 }
31059
31060 fn generate_encrypt(&mut self, e: &Encrypt) -> Result<()> {
31061 self.write_keyword("ENCRYPT");
31063 self.write("(");
31064 self.generate_expression(&e.this)?;
31065 if let Some(passphrase) = &e.passphrase {
31066 self.write(", ");
31067 self.generate_expression(passphrase)?;
31068 }
31069 if let Some(aad) = &e.aad {
31070 self.write(", ");
31071 self.generate_expression(aad)?;
31072 }
31073 if let Some(method) = &e.encryption_method {
31074 self.write(", ");
31075 self.generate_expression(method)?;
31076 }
31077 self.write(")");
31078 Ok(())
31079 }
31080
31081 fn generate_encrypt_raw(&mut self, e: &EncryptRaw) -> Result<()> {
31082 self.write_keyword("ENCRYPT_RAW");
31084 self.write("(");
31085 self.generate_expression(&e.this)?;
31086 if let Some(key) = &e.key {
31087 self.write(", ");
31088 self.generate_expression(key)?;
31089 }
31090 if let Some(iv) = &e.iv {
31091 self.write(", ");
31092 self.generate_expression(iv)?;
31093 }
31094 if let Some(aad) = &e.aad {
31095 self.write(", ");
31096 self.generate_expression(aad)?;
31097 }
31098 if let Some(method) = &e.encryption_method {
31099 self.write(", ");
31100 self.generate_expression(method)?;
31101 }
31102 self.write(")");
31103 Ok(())
31104 }
31105
31106 fn generate_engine_property(&mut self, e: &EngineProperty) -> Result<()> {
31107 self.write_keyword("ENGINE");
31109 if matches!(self.config.dialect, Some(DialectType::ClickHouse)) {
31110 self.write("=");
31111 } else {
31112 self.write(" = ");
31113 }
31114 self.generate_expression(&e.this)?;
31115 Ok(())
31116 }
31117
31118 fn generate_enviroment_property(&mut self, e: &EnviromentProperty) -> Result<()> {
31119 self.write_keyword("ENVIRONMENT");
31121 self.write(" (");
31122 for (i, expr) in e.expressions.iter().enumerate() {
31123 if i > 0 {
31124 self.write(", ");
31125 }
31126 self.generate_expression(expr)?;
31127 }
31128 self.write(")");
31129 Ok(())
31130 }
31131
31132 fn generate_ephemeral_column_constraint(
31133 &mut self,
31134 e: &EphemeralColumnConstraint,
31135 ) -> Result<()> {
31136 self.write_keyword("EPHEMERAL");
31138 if let Some(this) = &e.this {
31139 self.write_space();
31140 self.generate_expression(this)?;
31141 }
31142 Ok(())
31143 }
31144
31145 fn generate_equal_null(&mut self, e: &EqualNull) -> Result<()> {
31146 self.write_keyword("EQUAL_NULL");
31148 self.write("(");
31149 self.generate_expression(&e.this)?;
31150 self.write(", ");
31151 self.generate_expression(&e.expression)?;
31152 self.write(")");
31153 Ok(())
31154 }
31155
31156 fn generate_euclidean_distance(&mut self, e: &EuclideanDistance) -> Result<()> {
31157 use crate::dialects::DialectType;
31158
31159 match self.config.dialect {
31161 Some(DialectType::PostgreSQL) | Some(DialectType::Redshift) => {
31162 self.generate_expression(&e.this)?;
31163 self.write(" <-> ");
31164 self.generate_expression(&e.expression)?;
31165 }
31166 _ => {
31167 self.write_keyword("EUCLIDEAN_DISTANCE");
31169 self.write("(");
31170 self.generate_expression(&e.this)?;
31171 self.write(", ");
31172 self.generate_expression(&e.expression)?;
31173 self.write(")");
31174 }
31175 }
31176 Ok(())
31177 }
31178
31179 fn generate_execute_as_property(&mut self, e: &ExecuteAsProperty) -> Result<()> {
31180 self.write_keyword("EXECUTE AS");
31182 self.write_space();
31183 self.generate_expression(&e.this)?;
31184 Ok(())
31185 }
31186
31187 fn generate_export(&mut self, e: &Export) -> Result<()> {
31188 self.write_keyword("EXPORT DATA");
31190 if let Some(connection) = &e.connection {
31191 self.write_space();
31192 self.write_keyword("WITH CONNECTION");
31193 self.write_space();
31194 self.generate_expression(connection)?;
31195 }
31196 if !e.options.is_empty() {
31197 self.write_space();
31198 self.generate_options_clause(&e.options)?;
31199 }
31200 self.write_space();
31201 self.write_keyword("AS");
31202 self.write_space();
31203 self.generate_expression(&e.this)?;
31204 Ok(())
31205 }
31206
31207 fn generate_external_property(&mut self, e: &ExternalProperty) -> Result<()> {
31208 self.write_keyword("EXTERNAL");
31210 if let Some(this) = &e.this {
31211 self.write_space();
31212 self.generate_expression(this)?;
31213 }
31214 Ok(())
31215 }
31216
31217 fn generate_fallback_property(&mut self, e: &FallbackProperty) -> Result<()> {
31218 if e.no.is_some() {
31220 self.write_keyword("NO ");
31221 }
31222 self.write_keyword("FALLBACK");
31223 if e.protection.is_some() {
31224 self.write_keyword(" PROTECTION");
31225 }
31226 Ok(())
31227 }
31228
31229 fn generate_farm_fingerprint(&mut self, e: &FarmFingerprint) -> Result<()> {
31230 self.write_keyword("FARM_FINGERPRINT");
31232 self.write("(");
31233 for (i, expr) in e.expressions.iter().enumerate() {
31234 if i > 0 {
31235 self.write(", ");
31236 }
31237 self.generate_expression(expr)?;
31238 }
31239 self.write(")");
31240 Ok(())
31241 }
31242
31243 fn generate_features_at_time(&mut self, e: &FeaturesAtTime) -> Result<()> {
31244 self.write_keyword("FEATURES_AT_TIME");
31246 self.write("(");
31247 self.generate_expression(&e.this)?;
31248 if let Some(time) = &e.time {
31249 self.write(", ");
31250 self.generate_expression(time)?;
31251 }
31252 if let Some(num_rows) = &e.num_rows {
31253 self.write(", ");
31254 self.generate_expression(num_rows)?;
31255 }
31256 if let Some(ignore_nulls) = &e.ignore_feature_nulls {
31257 self.write(", ");
31258 self.generate_expression(ignore_nulls)?;
31259 }
31260 self.write(")");
31261 Ok(())
31262 }
31263
31264 fn generate_fetch(&mut self, e: &Fetch) -> Result<()> {
31265 let use_limit = !e.percent
31267 && !e.with_ties
31268 && e.count.is_some()
31269 && matches!(
31270 self.config.dialect,
31271 Some(DialectType::Spark)
31272 | Some(DialectType::Hive)
31273 | Some(DialectType::DuckDB)
31274 | Some(DialectType::SQLite)
31275 | Some(DialectType::MySQL)
31276 | Some(DialectType::BigQuery)
31277 | Some(DialectType::Databricks)
31278 | Some(DialectType::StarRocks)
31279 | Some(DialectType::Doris)
31280 | Some(DialectType::Athena)
31281 | Some(DialectType::ClickHouse)
31282 );
31283
31284 if use_limit {
31285 self.write_keyword("LIMIT");
31286 self.write_space();
31287 self.generate_expression(e.count.as_ref().unwrap())?;
31288 return Ok(());
31289 }
31290
31291 self.write_keyword("FETCH");
31293 if !e.direction.is_empty() {
31294 self.write_space();
31295 self.write_keyword(&e.direction);
31296 }
31297 if let Some(count) = &e.count {
31298 self.write_space();
31299 self.generate_expression(count)?;
31300 }
31301 if e.percent {
31303 self.write_keyword(" PERCENT");
31304 }
31305 if e.rows {
31306 self.write_keyword(" ROWS");
31307 }
31308 if e.with_ties {
31309 self.write_keyword(" WITH TIES");
31310 } else if e.rows {
31311 self.write_keyword(" ONLY");
31312 } else {
31313 self.write_keyword(" ROWS ONLY");
31314 }
31315 Ok(())
31316 }
31317
31318 fn generate_file_format_property(&mut self, e: &FileFormatProperty) -> Result<()> {
31319 if e.hive_format.is_some() {
31323 self.write_keyword("STORED AS");
31325 self.write_space();
31326 if let Some(this) = &e.this {
31327 if let Expression::Identifier(id) = this.as_ref() {
31329 self.write_keyword(&id.name.to_ascii_uppercase());
31330 } else {
31331 self.generate_expression(this)?;
31332 }
31333 }
31334 } else if matches!(self.config.dialect, Some(DialectType::Hive)) {
31335 self.write_keyword("STORED AS");
31337 self.write_space();
31338 if let Some(this) = &e.this {
31339 if let Expression::Identifier(id) = this.as_ref() {
31340 self.write_keyword(&id.name.to_ascii_uppercase());
31341 } else {
31342 self.generate_expression(this)?;
31343 }
31344 }
31345 } else if matches!(
31346 self.config.dialect,
31347 Some(DialectType::Spark) | Some(DialectType::Databricks)
31348 ) {
31349 self.write_keyword("USING");
31351 self.write_space();
31352 if let Some(this) = &e.this {
31353 self.generate_expression(this)?;
31354 }
31355 } else {
31356 self.write_keyword("FILE_FORMAT");
31358 self.write(" = ");
31359 if let Some(this) = &e.this {
31360 self.generate_expression(this)?;
31361 } else if !e.expressions.is_empty() {
31362 self.write("(");
31363 for (i, expr) in e.expressions.iter().enumerate() {
31364 if i > 0 {
31365 self.write(", ");
31366 }
31367 self.generate_expression(expr)?;
31368 }
31369 self.write(")");
31370 }
31371 }
31372 Ok(())
31373 }
31374
31375 fn generate_filter(&mut self, e: &Filter) -> Result<()> {
31376 self.generate_expression(&e.this)?;
31378 self.write_space();
31379 self.write_keyword("FILTER");
31380 self.write("(");
31381 self.write_keyword("WHERE");
31382 self.write_space();
31383 self.generate_expression(&e.expression)?;
31384 self.write(")");
31385 Ok(())
31386 }
31387
31388 fn generate_float64(&mut self, e: &Float64) -> Result<()> {
31389 self.write_keyword("FLOAT64");
31391 self.write("(");
31392 self.generate_expression(&e.this)?;
31393 if let Some(expr) = &e.expression {
31394 self.write(", ");
31395 self.generate_expression(expr)?;
31396 }
31397 self.write(")");
31398 Ok(())
31399 }
31400
31401 fn generate_for_in(&mut self, e: &ForIn) -> Result<()> {
31402 self.write_keyword("FOR");
31404 self.write_space();
31405 self.generate_expression(&e.this)?;
31406 self.write_space();
31407 self.write_keyword("DO");
31408 self.write_space();
31409 self.generate_expression(&e.expression)?;
31410 Ok(())
31411 }
31412
31413 fn generate_foreign_key(&mut self, e: &ForeignKey) -> Result<()> {
31414 self.write_keyword("FOREIGN KEY");
31416 if !e.expressions.is_empty() {
31417 self.write(" (");
31418 for (i, expr) in e.expressions.iter().enumerate() {
31419 if i > 0 {
31420 self.write(", ");
31421 }
31422 self.generate_expression(expr)?;
31423 }
31424 self.write(")");
31425 }
31426 if let Some(reference) = &e.reference {
31427 self.write_space();
31428 self.generate_expression(reference)?;
31429 }
31430 if let Some(delete) = &e.delete {
31431 self.write_space();
31432 self.write_keyword("ON DELETE");
31433 self.write_space();
31434 self.generate_expression(delete)?;
31435 }
31436 if let Some(update) = &e.update {
31437 self.write_space();
31438 self.write_keyword("ON UPDATE");
31439 self.write_space();
31440 self.generate_expression(update)?;
31441 }
31442 if !e.options.is_empty() {
31443 self.write_space();
31444 for (i, opt) in e.options.iter().enumerate() {
31445 if i > 0 {
31446 self.write_space();
31447 }
31448 self.generate_expression(opt)?;
31449 }
31450 }
31451 Ok(())
31452 }
31453
31454 fn generate_format(&mut self, e: &Format) -> Result<()> {
31455 self.write_keyword("FORMAT");
31457 self.write("(");
31458 self.generate_expression(&e.this)?;
31459 for expr in &e.expressions {
31460 self.write(", ");
31461 self.generate_expression(expr)?;
31462 }
31463 self.write(")");
31464 Ok(())
31465 }
31466
31467 fn generate_format_phrase(&mut self, e: &FormatPhrase) -> Result<()> {
31468 self.generate_expression(&e.this)?;
31470 self.write(" (");
31471 self.write_keyword("FORMAT");
31472 self.write(" '");
31473 self.write(&e.format);
31474 self.write("')");
31475 Ok(())
31476 }
31477
31478 fn generate_freespace_property(&mut self, e: &FreespaceProperty) -> Result<()> {
31479 self.write_keyword("FREESPACE");
31481 self.write("=");
31482 self.generate_expression(&e.this)?;
31483 if e.percent.is_some() {
31484 self.write_keyword(" PERCENT");
31485 }
31486 Ok(())
31487 }
31488
31489 fn generate_from(&mut self, e: &From) -> Result<()> {
31490 self.write_keyword("FROM");
31492 self.write_space();
31493
31494 use crate::dialects::DialectType;
31498 let has_tablesample = e
31499 .expressions
31500 .iter()
31501 .any(|expr| matches!(expr, Expression::TableSample(_)));
31502 let is_cross_join_dialect = matches!(
31503 self.config.dialect,
31504 Some(DialectType::BigQuery)
31505 | Some(DialectType::Hive)
31506 | Some(DialectType::Spark)
31507 | Some(DialectType::Databricks)
31508 | Some(DialectType::SQLite)
31509 | Some(DialectType::ClickHouse)
31510 );
31511 let source_is_same_as_target2 = self.config.source_dialect.is_some()
31512 && self.config.source_dialect == self.config.dialect;
31513 let source_is_cross_join_dialect2 = matches!(
31514 self.config.source_dialect,
31515 Some(DialectType::BigQuery)
31516 | Some(DialectType::Hive)
31517 | Some(DialectType::Spark)
31518 | Some(DialectType::Databricks)
31519 | Some(DialectType::SQLite)
31520 | Some(DialectType::ClickHouse)
31521 );
31522 let use_cross_join = !has_tablesample
31523 && is_cross_join_dialect
31524 && (source_is_same_as_target2
31525 || source_is_cross_join_dialect2
31526 || self.config.source_dialect.is_none());
31527
31528 let wrap_values_in_parens = self.config.dialect.is_none()
31531 || matches!(
31532 self.config.dialect,
31533 Some(
31534 DialectType::Generic
31535 | DialectType::Snowflake
31536 | DialectType::Presto
31537 | DialectType::Trino
31538 | DialectType::Athena
31539 )
31540 );
31541
31542 for (i, expr) in e.expressions.iter().enumerate() {
31543 if i > 0 {
31544 if use_cross_join {
31545 self.write(" CROSS JOIN ");
31546 } else {
31547 self.write(", ");
31548 }
31549 }
31550 self.generate_from_source(expr, wrap_values_in_parens)?;
31551 let leading = Self::extract_table_leading_comments(expr);
31554 for comment in &leading {
31555 self.write_space();
31556 self.write_formatted_comment(comment);
31557 }
31558 }
31559 Ok(())
31560 }
31561
31562 fn generate_from_source(&mut self, expr: &Expression, wrap_values: bool) -> Result<()> {
31563 if wrap_values {
31564 if let Expression::Values(values) = expr {
31565 let mut inner_values = values.as_ref().clone();
31566 let alias = inner_values.alias.take();
31567 let column_aliases = std::mem::take(&mut inner_values.column_aliases);
31568
31569 self.write("(");
31570 self.generate_values(&inner_values)?;
31571 self.write(")");
31572
31573 if let Some(alias) = alias {
31574 self.write_space();
31575 self.write_keyword("AS");
31576 self.write_space();
31577 self.generate_identifier(&alias)?;
31578 self.generate_alias_column_list(&column_aliases)?;
31579 }
31580 return Ok(());
31581 }
31582 }
31583
31584 self.generate_expression(expr)
31585 }
31586
31587 fn extract_table_leading_comments(expr: &Expression) -> Vec<String> {
31589 match expr {
31590 Expression::Table(t) => t.leading_comments.clone(),
31591 Expression::Pivot(p) => {
31592 if let Expression::Table(t) = &p.this {
31593 t.leading_comments.clone()
31594 } else {
31595 Vec::new()
31596 }
31597 }
31598 _ => Vec::new(),
31599 }
31600 }
31601
31602 fn generate_from_base(&mut self, e: &FromBase) -> Result<()> {
31603 self.write_keyword("FROM_BASE");
31605 self.write("(");
31606 self.generate_expression(&e.this)?;
31607 self.write(", ");
31608 self.generate_expression(&e.expression)?;
31609 self.write(")");
31610 Ok(())
31611 }
31612
31613 fn generate_from_time_zone(&mut self, e: &FromTimeZone) -> Result<()> {
31614 self.generate_expression(&e.this)?;
31616 if let Some(zone) = &e.zone {
31617 self.write_space();
31618 self.write_keyword("AT TIME ZONE");
31619 self.write_space();
31620 self.generate_expression(zone)?;
31621 self.write_space();
31622 self.write_keyword("AT TIME ZONE");
31623 self.write(" 'UTC'");
31624 }
31625 Ok(())
31626 }
31627
31628 fn generate_gap_fill(&mut self, e: &GapFill) -> Result<()> {
31629 self.write_keyword("GAP_FILL");
31631 self.write("(");
31632 self.generate_expression(&e.this)?;
31633 if let Some(ts_column) = &e.ts_column {
31634 self.write(", ");
31635 self.generate_expression(ts_column)?;
31636 }
31637 if let Some(bucket_width) = &e.bucket_width {
31638 self.write(", ");
31639 self.generate_expression(bucket_width)?;
31640 }
31641 if let Some(partitioning_columns) = &e.partitioning_columns {
31642 self.write(", ");
31643 self.generate_expression(partitioning_columns)?;
31644 }
31645 if let Some(value_columns) = &e.value_columns {
31646 self.write(", ");
31647 self.generate_expression(value_columns)?;
31648 }
31649 self.write(")");
31650 Ok(())
31651 }
31652
31653 fn generate_generate_date_array(&mut self, e: &GenerateDateArray) -> Result<()> {
31654 self.write_keyword("GENERATE_DATE_ARRAY");
31656 self.write("(");
31657 let mut first = true;
31658 if let Some(start) = &e.start {
31659 self.generate_expression(start)?;
31660 first = false;
31661 }
31662 if let Some(end) = &e.end {
31663 if !first {
31664 self.write(", ");
31665 }
31666 self.generate_expression(end)?;
31667 first = false;
31668 }
31669 if let Some(step) = &e.step {
31670 if !first {
31671 self.write(", ");
31672 }
31673 self.generate_expression(step)?;
31674 }
31675 self.write(")");
31676 Ok(())
31677 }
31678
31679 fn generate_generate_embedding(&mut self, e: &GenerateEmbedding) -> Result<()> {
31680 self.write_keyword("ML.GENERATE_EMBEDDING");
31682 self.write("(");
31683 self.generate_expression(&e.this)?;
31684 self.write(", ");
31685 self.generate_expression(&e.expression)?;
31686 if let Some(params) = &e.params_struct {
31687 self.write(", ");
31688 self.generate_expression(params)?;
31689 }
31690 self.write(")");
31691 Ok(())
31692 }
31693
31694 fn generate_generate_series(&mut self, e: &GenerateSeries) -> Result<()> {
31695 let fn_name = match self.config.dialect {
31697 Some(DialectType::Presto)
31698 | Some(DialectType::Trino)
31699 | Some(DialectType::Athena)
31700 | Some(DialectType::Spark)
31701 | Some(DialectType::Databricks)
31702 | Some(DialectType::Hive) => "SEQUENCE",
31703 _ => "GENERATE_SERIES",
31704 };
31705 self.write_keyword(fn_name);
31706 self.write("(");
31707 let mut first = true;
31708 if let Some(start) = &e.start {
31709 self.generate_expression(start)?;
31710 first = false;
31711 }
31712 if let Some(end) = &e.end {
31713 if !first {
31714 self.write(", ");
31715 }
31716 self.generate_expression(end)?;
31717 first = false;
31718 }
31719 if let Some(step) = &e.step {
31720 if !first {
31721 self.write(", ");
31722 }
31723 if matches!(
31726 self.config.dialect,
31727 Some(DialectType::Presto) | Some(DialectType::Trino) | Some(DialectType::Athena)
31728 ) {
31729 if let Some(converted) = self.convert_week_interval_to_day(step) {
31730 self.generate_expression(&converted)?;
31731 } else {
31732 self.generate_expression(step)?;
31733 }
31734 } else {
31735 self.generate_expression(step)?;
31736 }
31737 }
31738 self.write(")");
31739 Ok(())
31740 }
31741
31742 fn convert_week_interval_to_day(&self, expr: &Expression) -> Option<Expression> {
31745 use crate::expressions::*;
31746 if let Expression::Interval(ref iv) = expr {
31747 let (is_week, count_str) = if let Some(IntervalUnitSpec::Simple {
31749 unit: IntervalUnit::Week,
31750 ..
31751 }) = &iv.unit
31752 {
31753 let count = match &iv.this {
31755 Some(Expression::Literal(lit)) => match lit.as_ref() {
31756 Literal::String(s) | Literal::Number(s) => s.clone(),
31757 _ => return None,
31758 },
31759 _ => return None,
31760 };
31761 (true, count)
31762 } else if iv.unit.is_none() {
31763 if let Some(Expression::Literal(lit)) = &iv.this {
31765 if let Literal::String(s) = lit.as_ref() {
31766 let parts: Vec<&str> = s.trim().splitn(2, char::is_whitespace).collect();
31767 if parts.len() == 2 && parts[1].eq_ignore_ascii_case("WEEK") {
31768 (true, parts[0].to_string())
31769 } else {
31770 (false, String::new())
31771 }
31772 } else {
31773 (false, String::new())
31774 }
31775 } else {
31776 (false, String::new())
31777 }
31778 } else {
31779 (false, String::new())
31780 };
31781
31782 if is_week {
31783 let count_expr = Expression::Literal(Box::new(Literal::Number(count_str)));
31785 let day_interval = Expression::Interval(Box::new(Interval {
31786 this: Some(Expression::Literal(Box::new(Literal::String(
31787 "7".to_string(),
31788 )))),
31789 unit: Some(IntervalUnitSpec::Simple {
31790 unit: IntervalUnit::Day,
31791 use_plural: false,
31792 }),
31793 }));
31794 let mul = Expression::Mul(Box::new(BinaryOp {
31795 left: count_expr,
31796 right: day_interval,
31797 left_comments: vec![],
31798 operator_comments: vec![],
31799 trailing_comments: vec![],
31800 inferred_type: None,
31801 }));
31802 return Some(Expression::Paren(Box::new(Paren {
31803 this: mul,
31804 trailing_comments: vec![],
31805 })));
31806 }
31807 }
31808 None
31809 }
31810
31811 fn generate_generate_timestamp_array(&mut self, e: &GenerateTimestampArray) -> Result<()> {
31812 self.write_keyword("GENERATE_TIMESTAMP_ARRAY");
31814 self.write("(");
31815 let mut first = true;
31816 if let Some(start) = &e.start {
31817 self.generate_expression(start)?;
31818 first = false;
31819 }
31820 if let Some(end) = &e.end {
31821 if !first {
31822 self.write(", ");
31823 }
31824 self.generate_expression(end)?;
31825 first = false;
31826 }
31827 if let Some(step) = &e.step {
31828 if !first {
31829 self.write(", ");
31830 }
31831 self.generate_expression(step)?;
31832 }
31833 self.write(")");
31834 Ok(())
31835 }
31836
31837 fn generate_generated_as_identity_column_constraint(
31838 &mut self,
31839 e: &GeneratedAsIdentityColumnConstraint,
31840 ) -> Result<()> {
31841 use crate::dialects::DialectType;
31842
31843 if matches!(self.config.dialect, Some(DialectType::Snowflake)) {
31845 self.write_keyword("AUTOINCREMENT");
31846 if let Some(start) = &e.start {
31847 self.write_keyword(" START ");
31848 self.generate_expression(start)?;
31849 }
31850 if let Some(increment) = &e.increment {
31851 self.write_keyword(" INCREMENT ");
31852 self.generate_expression(increment)?;
31853 }
31854 return Ok(());
31855 }
31856
31857 self.write_keyword("GENERATED");
31859 if let Some(this) = &e.this {
31860 if let Expression::Boolean(b) = this.as_ref() {
31862 if b.value {
31863 self.write_keyword(" ALWAYS");
31864 } else {
31865 self.write_keyword(" BY DEFAULT");
31866 if e.on_null.is_some() {
31867 self.write_keyword(" ON NULL");
31868 }
31869 }
31870 } else {
31871 self.write_keyword(" ALWAYS");
31872 }
31873 }
31874 self.write_keyword(" AS IDENTITY");
31875 let has_options = e.start.is_some()
31877 || e.increment.is_some()
31878 || e.minvalue.is_some()
31879 || e.maxvalue.is_some();
31880 if has_options {
31881 self.write(" (");
31882 let mut first = true;
31883 if let Some(start) = &e.start {
31884 self.write_keyword("START WITH ");
31885 self.generate_expression(start)?;
31886 first = false;
31887 }
31888 if let Some(increment) = &e.increment {
31889 if !first {
31890 self.write(" ");
31891 }
31892 self.write_keyword("INCREMENT BY ");
31893 self.generate_expression(increment)?;
31894 first = false;
31895 }
31896 if let Some(minvalue) = &e.minvalue {
31897 if !first {
31898 self.write(" ");
31899 }
31900 self.write_keyword("MINVALUE ");
31901 self.generate_expression(minvalue)?;
31902 first = false;
31903 }
31904 if let Some(maxvalue) = &e.maxvalue {
31905 if !first {
31906 self.write(" ");
31907 }
31908 self.write_keyword("MAXVALUE ");
31909 self.generate_expression(maxvalue)?;
31910 }
31911 self.write(")");
31912 }
31913 Ok(())
31914 }
31915
31916 fn generate_generated_as_row_column_constraint(
31917 &mut self,
31918 e: &GeneratedAsRowColumnConstraint,
31919 ) -> Result<()> {
31920 self.write_keyword("GENERATED ALWAYS AS ROW ");
31922 if e.start.is_some() {
31923 self.write_keyword("START");
31924 } else {
31925 self.write_keyword("END");
31926 }
31927 if e.hidden.is_some() {
31928 self.write_keyword(" HIDDEN");
31929 }
31930 Ok(())
31931 }
31932
31933 fn generate_get(&mut self, e: &Get) -> Result<()> {
31934 self.write_keyword("GET");
31936 self.write_space();
31937 self.generate_expression(&e.this)?;
31938 if let Some(target) = &e.target {
31939 self.write_space();
31940 self.generate_expression(target)?;
31941 }
31942 for prop in &e.properties {
31943 self.write_space();
31944 self.generate_expression(prop)?;
31945 }
31946 Ok(())
31947 }
31948
31949 fn generate_get_extract(&mut self, e: &GetExtract) -> Result<()> {
31950 self.generate_expression(&e.this)?;
31952 self.write("[");
31953 self.generate_expression(&e.expression)?;
31954 self.write("]");
31955 Ok(())
31956 }
31957
31958 fn generate_getbit(&mut self, e: &Getbit) -> Result<()> {
31959 self.write_keyword("GETBIT");
31961 self.write("(");
31962 self.generate_expression(&e.this)?;
31963 self.write(", ");
31964 self.generate_expression(&e.expression)?;
31965 self.write(")");
31966 Ok(())
31967 }
31968
31969 fn generate_grant_principal(&mut self, e: &GrantPrincipal) -> Result<()> {
31970 if e.is_role {
31972 self.write_keyword("ROLE");
31973 self.write_space();
31974 } else if e.is_group {
31975 self.write_keyword("GROUP");
31976 self.write_space();
31977 } else if e.is_share {
31978 self.write_keyword("SHARE");
31979 self.write_space();
31980 }
31981 self.write(&e.name.name);
31982 Ok(())
31983 }
31984
31985 fn generate_grant_privilege(&mut self, e: &GrantPrivilege) -> Result<()> {
31986 self.generate_expression(&e.this)?;
31988 if !e.expressions.is_empty() {
31989 self.write("(");
31990 for (i, expr) in e.expressions.iter().enumerate() {
31991 if i > 0 {
31992 self.write(", ");
31993 }
31994 self.generate_expression(expr)?;
31995 }
31996 self.write(")");
31997 }
31998 Ok(())
31999 }
32000
32001 fn generate_group(&mut self, e: &Group) -> Result<()> {
32002 self.write_keyword("GROUP BY");
32004 match e.all {
32006 Some(true) => {
32007 self.write_space();
32008 self.write_keyword("ALL");
32009 }
32010 Some(false) => {
32011 self.write_space();
32012 self.write_keyword("DISTINCT");
32013 }
32014 None => {}
32015 }
32016 if !e.expressions.is_empty() {
32017 self.write_space();
32018 for (i, expr) in e.expressions.iter().enumerate() {
32019 if i > 0 {
32020 self.write(", ");
32021 }
32022 self.generate_expression(expr)?;
32023 }
32024 }
32025 if let Some(cube) = &e.cube {
32027 if !e.expressions.is_empty() {
32028 self.write(", ");
32029 } else {
32030 self.write_space();
32031 }
32032 self.generate_expression(cube)?;
32033 }
32034 if let Some(rollup) = &e.rollup {
32035 if !e.expressions.is_empty() || e.cube.is_some() {
32036 self.write(", ");
32037 } else {
32038 self.write_space();
32039 }
32040 self.generate_expression(rollup)?;
32041 }
32042 if let Some(grouping_sets) = &e.grouping_sets {
32043 if !e.expressions.is_empty() || e.cube.is_some() || e.rollup.is_some() {
32044 self.write(", ");
32045 } else {
32046 self.write_space();
32047 }
32048 self.generate_expression(grouping_sets)?;
32049 }
32050 if let Some(totals) = &e.totals {
32051 self.write_space();
32052 self.write_keyword("WITH TOTALS");
32053 self.generate_expression(totals)?;
32054 }
32055 Ok(())
32056 }
32057
32058 fn generate_group_by(&mut self, e: &GroupBy) -> Result<()> {
32059 self.write_keyword("GROUP BY");
32061 match e.all {
32063 Some(true) => {
32064 self.write_space();
32065 self.write_keyword("ALL");
32066 }
32067 Some(false) => {
32068 self.write_space();
32069 self.write_keyword("DISTINCT");
32070 }
32071 None => {}
32072 }
32073
32074 let mut trailing_cube = false;
32077 let mut trailing_rollup = false;
32078 let mut regular_expressions: Vec<&Expression> = Vec::new();
32079
32080 for expr in &e.expressions {
32081 match expr {
32082 Expression::Cube(c) if c.expressions.is_empty() => {
32083 trailing_cube = true;
32084 }
32085 Expression::Rollup(r) if r.expressions.is_empty() => {
32086 trailing_rollup = true;
32087 }
32088 _ => {
32089 regular_expressions.push(expr);
32090 }
32091 }
32092 }
32093
32094 if self.config.pretty {
32096 self.write_newline();
32097 self.indent_level += 1;
32098 for (i, expr) in regular_expressions.iter().enumerate() {
32099 if i > 0 {
32100 self.write(",");
32101 self.write_newline();
32102 }
32103 self.write_indent();
32104 self.generate_expression(expr)?;
32105 }
32106 self.indent_level -= 1;
32107 } else {
32108 self.write_space();
32109 for (i, expr) in regular_expressions.iter().enumerate() {
32110 if i > 0 {
32111 self.write(", ");
32112 }
32113 self.generate_expression(expr)?;
32114 }
32115 }
32116
32117 if trailing_cube {
32119 self.write_space();
32120 self.write_keyword("WITH CUBE");
32121 } else if trailing_rollup {
32122 self.write_space();
32123 self.write_keyword("WITH ROLLUP");
32124 }
32125
32126 if e.totals {
32128 self.write_space();
32129 self.write_keyword("WITH TOTALS");
32130 }
32131
32132 Ok(())
32133 }
32134
32135 fn generate_grouping(&mut self, e: &Grouping) -> Result<()> {
32136 let function_name = if e.expressions.len() > 1
32137 && matches!(
32138 self.config.dialect,
32139 Some(DialectType::TSQL | DialectType::Fabric)
32140 ) {
32141 "GROUPING_ID"
32142 } else {
32143 "GROUPING"
32144 };
32145 self.write_keyword(function_name);
32146 self.write("(");
32147 for (i, expr) in e.expressions.iter().enumerate() {
32148 if i > 0 {
32149 self.write(", ");
32150 }
32151 self.generate_expression(expr)?;
32152 }
32153 self.write(")");
32154 Ok(())
32155 }
32156
32157 fn generate_grouping_id(&mut self, e: &GroupingId) -> Result<()> {
32158 self.write_keyword("GROUPING_ID");
32160 self.write("(");
32161 for (i, expr) in e.expressions.iter().enumerate() {
32162 if i > 0 {
32163 self.write(", ");
32164 }
32165 self.generate_expression(expr)?;
32166 }
32167 self.write(")");
32168 Ok(())
32169 }
32170
32171 fn generate_grouping_sets(&mut self, e: &GroupingSets) -> Result<()> {
32172 self.write_keyword("GROUPING SETS");
32174 self.write(" (");
32175 for (i, expr) in e.expressions.iter().enumerate() {
32176 if i > 0 {
32177 self.write(", ");
32178 }
32179 self.generate_expression(expr)?;
32180 }
32181 self.write(")");
32182 Ok(())
32183 }
32184
32185 fn generate_hash_agg(&mut self, e: &HashAgg) -> Result<()> {
32186 self.write_keyword("HASH_AGG");
32188 self.write("(");
32189 self.generate_expression(&e.this)?;
32190 for expr in &e.expressions {
32191 self.write(", ");
32192 self.generate_expression(expr)?;
32193 }
32194 self.write(")");
32195 Ok(())
32196 }
32197
32198 fn generate_having(&mut self, e: &Having) -> Result<()> {
32199 self.write_keyword("HAVING");
32201 self.write_space();
32202 self.generate_expression(&e.this)?;
32203 Ok(())
32204 }
32205
32206 fn generate_having_max(&mut self, e: &HavingMax) -> Result<()> {
32207 self.generate_expression(&e.this)?;
32209 self.write_space();
32210 self.write_keyword("HAVING");
32211 self.write_space();
32212 if e.max.is_some() {
32213 self.write_keyword("MAX");
32214 } else {
32215 self.write_keyword("MIN");
32216 }
32217 self.write_space();
32218 self.generate_expression(&e.expression)?;
32219 Ok(())
32220 }
32221
32222 fn generate_heredoc(&mut self, e: &Heredoc) -> Result<()> {
32223 use crate::dialects::DialectType;
32224 if matches!(self.config.dialect, Some(DialectType::DuckDB)) {
32226 if let Expression::Literal(ref lit) = *e.this {
32228 if let Literal::String(ref s) = lit.as_ref() {
32229 return self.generate_string_literal(s);
32230 }
32231 }
32232 }
32233 if matches!(
32235 self.config.dialect,
32236 Some(DialectType::PostgreSQL) | Some(DialectType::Redshift)
32237 ) {
32238 self.write("$");
32239 if let Some(tag) = &e.tag {
32240 self.generate_expression(tag)?;
32241 }
32242 self.write("$");
32243 self.generate_expression(&e.this)?;
32244 self.write("$");
32245 if let Some(tag) = &e.tag {
32246 self.generate_expression(tag)?;
32247 }
32248 self.write("$");
32249 return Ok(());
32250 }
32251 self.write("$");
32253 if let Some(tag) = &e.tag {
32254 self.generate_expression(tag)?;
32255 }
32256 self.write("$");
32257 self.generate_expression(&e.this)?;
32258 self.write("$");
32259 if let Some(tag) = &e.tag {
32260 self.generate_expression(tag)?;
32261 }
32262 self.write("$");
32263 Ok(())
32264 }
32265
32266 fn generate_hex_encode(&mut self, e: &HexEncode) -> Result<()> {
32267 self.write_keyword("HEX_ENCODE");
32269 self.write("(");
32270 self.generate_expression(&e.this)?;
32271 self.write(")");
32272 Ok(())
32273 }
32274
32275 fn generate_historical_data(&mut self, e: &HistoricalData) -> Result<()> {
32276 match e.this.as_ref() {
32279 Expression::Identifier(id) => self.write(&id.name),
32280 other => self.generate_expression(other)?,
32281 }
32282 self.write(" (");
32283 self.write(&e.kind);
32284 self.write(" => ");
32285 self.generate_expression(&e.expression)?;
32286 self.write(")");
32287 Ok(())
32288 }
32289
32290 fn generate_hll(&mut self, e: &Hll) -> Result<()> {
32291 self.write_keyword("HLL");
32293 self.write("(");
32294 self.generate_expression(&e.this)?;
32295 for expr in &e.expressions {
32296 self.write(", ");
32297 self.generate_expression(expr)?;
32298 }
32299 self.write(")");
32300 Ok(())
32301 }
32302
32303 fn generate_in_out_column_constraint(&mut self, e: &InOutColumnConstraint) -> Result<()> {
32304 if e.input_.is_some() && e.output.is_some() {
32306 self.write_keyword("IN OUT");
32307 } else if e.input_.is_some() {
32308 self.write_keyword("IN");
32309 } else if e.output.is_some() {
32310 self.write_keyword("OUT");
32311 }
32312 Ok(())
32313 }
32314
32315 fn generate_include_property(&mut self, e: &IncludeProperty) -> Result<()> {
32316 self.write_keyword("INCLUDE");
32318 self.write_space();
32319 self.generate_expression(&e.this)?;
32320 if let Some(column_def) = &e.column_def {
32321 self.write_space();
32322 self.generate_expression(column_def)?;
32323 }
32324 if let Some(alias) = &e.alias {
32325 self.write_space();
32326 self.write_keyword("AS");
32327 self.write_space();
32328 self.write(alias);
32329 }
32330 Ok(())
32331 }
32332
32333 fn generate_index(&mut self, e: &Index) -> Result<()> {
32334 if e.unique {
32336 self.write_keyword("UNIQUE");
32337 self.write_space();
32338 }
32339 if e.primary.is_some() {
32340 self.write_keyword("PRIMARY");
32341 self.write_space();
32342 }
32343 if e.amp.is_some() {
32344 self.write_keyword("AMP");
32345 self.write_space();
32346 }
32347 if e.table.is_none() {
32348 self.write_keyword("INDEX");
32349 self.write_space();
32350 }
32351 if let Some(name) = &e.this {
32352 self.generate_expression(name)?;
32353 self.write_space();
32354 }
32355 if let Some(table) = &e.table {
32356 self.write_keyword("ON");
32357 self.write_space();
32358 self.generate_expression(table)?;
32359 }
32360 if !e.params.is_empty() {
32361 self.write("(");
32362 for (i, param) in e.params.iter().enumerate() {
32363 if i > 0 {
32364 self.write(", ");
32365 }
32366 self.generate_expression(param)?;
32367 }
32368 self.write(")");
32369 }
32370 Ok(())
32371 }
32372
32373 fn generate_index_column_constraint(&mut self, e: &IndexColumnConstraint) -> Result<()> {
32374 if let Some(kind) = &e.kind {
32376 self.write(kind);
32377 self.write_space();
32378 }
32379 self.write_keyword("INDEX");
32380 if let Some(this) = &e.this {
32381 self.write_space();
32382 self.generate_expression(this)?;
32383 }
32384 if let Some(index_type) = &e.index_type {
32385 self.write_space();
32386 self.write_keyword("USING");
32387 self.write_space();
32388 self.generate_expression(index_type)?;
32389 }
32390 if !e.expressions.is_empty() {
32391 self.write(" (");
32392 for (i, expr) in e.expressions.iter().enumerate() {
32393 if i > 0 {
32394 self.write(", ");
32395 }
32396 self.generate_expression(expr)?;
32397 }
32398 self.write(")");
32399 }
32400 for opt in &e.options {
32401 self.write_space();
32402 self.generate_expression(opt)?;
32403 }
32404 Ok(())
32405 }
32406
32407 fn generate_index_constraint_option(&mut self, e: &IndexConstraintOption) -> Result<()> {
32408 if let Some(key_block_size) = &e.key_block_size {
32410 self.write_keyword("KEY_BLOCK_SIZE");
32411 self.write(" = ");
32412 self.generate_expression(key_block_size)?;
32413 } else if let Some(using) = &e.using {
32414 self.write_keyword("USING");
32415 self.write_space();
32416 self.generate_expression(using)?;
32417 } else if let Some(parser) = &e.parser {
32418 self.write_keyword("WITH PARSER");
32419 self.write_space();
32420 self.generate_expression(parser)?;
32421 } else if let Some(comment) = &e.comment {
32422 self.write_keyword("COMMENT");
32423 self.write_space();
32424 self.generate_expression(comment)?;
32425 } else if let Some(visible) = &e.visible {
32426 self.generate_expression(visible)?;
32427 } else if let Some(engine_attr) = &e.engine_attr {
32428 self.write_keyword("ENGINE_ATTRIBUTE");
32429 self.write(" = ");
32430 self.generate_expression(engine_attr)?;
32431 } else if let Some(secondary_engine_attr) = &e.secondary_engine_attr {
32432 self.write_keyword("SECONDARY_ENGINE_ATTRIBUTE");
32433 self.write(" = ");
32434 self.generate_expression(secondary_engine_attr)?;
32435 }
32436 Ok(())
32437 }
32438
32439 fn generate_index_parameters(&mut self, e: &IndexParameters) -> Result<()> {
32440 if let Some(using) = &e.using {
32442 self.write_keyword("USING");
32443 self.write_space();
32444 self.generate_expression(using)?;
32445 }
32446 if !e.columns.is_empty() {
32447 self.write("(");
32448 for (i, col) in e.columns.iter().enumerate() {
32449 if i > 0 {
32450 self.write(", ");
32451 }
32452 self.generate_expression(col)?;
32453 }
32454 self.write(")");
32455 }
32456 if let Some(partition_by) = &e.partition_by {
32457 self.write_space();
32458 self.write_keyword("PARTITION BY");
32459 self.write_space();
32460 self.generate_expression(partition_by)?;
32461 }
32462 if let Some(where_) = &e.where_ {
32463 self.write_space();
32464 self.generate_expression(where_)?;
32465 }
32466 if let Some(include) = &e.include {
32467 self.write_space();
32468 self.write_keyword("INCLUDE");
32469 self.write(" (");
32470 self.generate_expression(include)?;
32471 self.write(")");
32472 }
32473 if let Some(with_storage) = &e.with_storage {
32474 self.write_space();
32475 self.write_keyword("WITH");
32476 self.write(" (");
32477 self.generate_expression(with_storage)?;
32478 self.write(")");
32479 }
32480 if let Some(tablespace) = &e.tablespace {
32481 self.write_space();
32482 self.write_keyword("USING INDEX TABLESPACE");
32483 self.write_space();
32484 self.generate_expression(tablespace)?;
32485 }
32486 Ok(())
32487 }
32488
32489 fn generate_index_table_hint(&mut self, e: &IndexTableHint) -> Result<()> {
32490 if let Expression::Identifier(id) = &*e.this {
32494 self.write_keyword(&id.name);
32495 } else {
32496 self.generate_expression(&e.this)?;
32497 }
32498 self.write_space();
32499 self.write_keyword("INDEX");
32500 if let Some(target) = &e.target {
32501 self.write_space();
32502 self.write_keyword("FOR");
32503 self.write_space();
32504 if let Expression::Identifier(id) = &**target {
32505 self.write_keyword(&id.name);
32506 } else {
32507 self.generate_expression(target)?;
32508 }
32509 }
32510 self.write(" (");
32512 for (i, expr) in e.expressions.iter().enumerate() {
32513 if i > 0 {
32514 self.write(", ");
32515 }
32516 self.generate_expression(expr)?;
32517 }
32518 self.write(")");
32519 Ok(())
32520 }
32521
32522 fn generate_inherits_property(&mut self, e: &InheritsProperty) -> Result<()> {
32523 self.write_keyword("INHERITS");
32525 self.write(" (");
32526 for (i, expr) in e.expressions.iter().enumerate() {
32527 if i > 0 {
32528 self.write(", ");
32529 }
32530 self.generate_expression(expr)?;
32531 }
32532 self.write(")");
32533 Ok(())
32534 }
32535
32536 fn generate_input_model_property(&mut self, e: &InputModelProperty) -> Result<()> {
32537 self.write_keyword("INPUT");
32539 self.write("(");
32540 self.generate_expression(&e.this)?;
32541 self.write(")");
32542 Ok(())
32543 }
32544
32545 fn generate_input_output_format(&mut self, e: &InputOutputFormat) -> Result<()> {
32546 if let Some(input_format) = &e.input_format {
32548 self.write_keyword("INPUTFORMAT");
32549 self.write_space();
32550 self.generate_expression(input_format)?;
32551 }
32552 if let Some(output_format) = &e.output_format {
32553 if e.input_format.is_some() {
32554 self.write(" ");
32555 }
32556 self.write_keyword("OUTPUTFORMAT");
32557 self.write_space();
32558 self.generate_expression(output_format)?;
32559 }
32560 Ok(())
32561 }
32562
32563 fn generate_install(&mut self, e: &Install) -> Result<()> {
32564 if e.force.is_some() {
32566 self.write_keyword("FORCE");
32567 self.write_space();
32568 }
32569 self.write_keyword("INSTALL");
32570 self.write_space();
32571 self.generate_expression(&e.this)?;
32572 if let Some(from) = &e.from_ {
32573 self.write_space();
32574 self.write_keyword("FROM");
32575 self.write_space();
32576 self.generate_expression(from)?;
32577 }
32578 Ok(())
32579 }
32580
32581 fn generate_interval_op(&mut self, e: &IntervalOp) -> Result<()> {
32582 self.write_keyword("INTERVAL");
32584 self.write_space();
32585 self.generate_expression(&e.expression)?;
32587 if let Some(unit) = &e.unit {
32588 self.write_space();
32589 self.write(unit);
32590 }
32591 Ok(())
32592 }
32593
32594 fn generate_interval_span(&mut self, e: &IntervalSpan) -> Result<()> {
32595 self.write(&format!("{:?}", e.this).to_ascii_uppercase());
32597 self.write_space();
32598 self.write_keyword("TO");
32599 self.write_space();
32600 self.write(&format!("{:?}", e.expression).to_ascii_uppercase());
32601 Ok(())
32602 }
32603
32604 fn generate_into_clause(&mut self, e: &IntoClause) -> Result<()> {
32605 self.write_keyword("INTO");
32607 if e.temporary {
32608 self.write_keyword(" TEMPORARY");
32609 }
32610 if e.unlogged.is_some() {
32611 self.write_keyword(" UNLOGGED");
32612 }
32613 if let Some(this) = &e.this {
32614 self.write_space();
32615 self.generate_expression(this)?;
32616 }
32617 if !e.expressions.is_empty() {
32618 self.write(" (");
32619 for (i, expr) in e.expressions.iter().enumerate() {
32620 if i > 0 {
32621 self.write(", ");
32622 }
32623 self.generate_expression(expr)?;
32624 }
32625 self.write(")");
32626 }
32627 Ok(())
32628 }
32629
32630 fn generate_introducer(&mut self, e: &Introducer) -> Result<()> {
32631 self.generate_expression(&e.this)?;
32633 self.write_space();
32634 self.generate_expression(&e.expression)?;
32635 Ok(())
32636 }
32637
32638 fn generate_isolated_loading_property(&mut self, e: &IsolatedLoadingProperty) -> Result<()> {
32639 self.write_keyword("WITH");
32641 if e.no.is_some() {
32642 self.write_keyword(" NO");
32643 }
32644 if e.concurrent.is_some() {
32645 self.write_keyword(" CONCURRENT");
32646 }
32647 self.write_keyword(" ISOLATED LOADING");
32648 if let Some(target) = &e.target {
32649 self.write_space();
32650 self.generate_expression(target)?;
32651 }
32652 Ok(())
32653 }
32654
32655 fn generate_json(&mut self, e: &JSON) -> Result<()> {
32656 self.write_keyword("JSON");
32658 if let Some(this) = &e.this {
32659 self.write_space();
32660 self.generate_expression(this)?;
32661 }
32662 if let Some(with_) = &e.with_ {
32663 if let Expression::Boolean(b) = with_.as_ref() {
32665 if b.value {
32666 self.write_keyword(" WITH");
32667 } else {
32668 self.write_keyword(" WITHOUT");
32669 }
32670 }
32671 }
32672 if e.unique {
32673 self.write_keyword(" UNIQUE KEYS");
32674 }
32675 Ok(())
32676 }
32677
32678 fn generate_json_array(&mut self, e: &JSONArray) -> Result<()> {
32679 self.write_keyword("JSON_ARRAY");
32681 self.write("(");
32682 for (i, expr) in e.expressions.iter().enumerate() {
32683 if i > 0 {
32684 self.write(", ");
32685 }
32686 self.generate_expression(expr)?;
32687 }
32688 if let Some(null_handling) = &e.null_handling {
32689 self.write_space();
32690 self.generate_expression(null_handling)?;
32691 }
32692 if let Some(return_type) = &e.return_type {
32693 self.write_space();
32694 self.write_keyword("RETURNING");
32695 self.write_space();
32696 self.generate_expression(return_type)?;
32697 }
32698 if e.strict.is_some() {
32699 self.write_space();
32700 self.write_keyword("STRICT");
32701 }
32702 self.write(")");
32703 Ok(())
32704 }
32705
32706 fn generate_json_array_agg_struct(&mut self, e: &JSONArrayAgg) -> Result<()> {
32707 self.write_keyword("JSON_ARRAYAGG");
32709 self.write("(");
32710 self.generate_expression(&e.this)?;
32711 if let Some(order) = &e.order {
32712 self.write_space();
32713 if let Expression::OrderBy(ob) = order.as_ref() {
32715 self.write_keyword("ORDER BY");
32716 self.write_space();
32717 for (i, ord) in ob.expressions.iter().enumerate() {
32718 if i > 0 {
32719 self.write(", ");
32720 }
32721 self.generate_ordered(ord)?;
32722 }
32723 } else {
32724 self.generate_expression(order)?;
32726 }
32727 }
32728 if let Some(null_handling) = &e.null_handling {
32729 self.write_space();
32730 self.generate_expression(null_handling)?;
32731 }
32732 if let Some(return_type) = &e.return_type {
32733 self.write_space();
32734 self.write_keyword("RETURNING");
32735 self.write_space();
32736 self.generate_expression(return_type)?;
32737 }
32738 if e.strict.is_some() {
32739 self.write_space();
32740 self.write_keyword("STRICT");
32741 }
32742 self.write(")");
32743 Ok(())
32744 }
32745
32746 fn generate_json_object_agg_struct(&mut self, e: &JSONObjectAgg) -> Result<()> {
32747 self.write_keyword("JSON_OBJECTAGG");
32749 self.write("(");
32750 for (i, expr) in e.expressions.iter().enumerate() {
32751 if i > 0 {
32752 self.write(", ");
32753 }
32754 self.generate_expression(expr)?;
32755 }
32756 if let Some(null_handling) = &e.null_handling {
32757 self.write_space();
32758 self.generate_expression(null_handling)?;
32759 }
32760 if let Some(unique_keys) = &e.unique_keys {
32761 self.write_space();
32762 if let Expression::Boolean(b) = unique_keys.as_ref() {
32763 if b.value {
32764 self.write_keyword("WITH UNIQUE KEYS");
32765 } else {
32766 self.write_keyword("WITHOUT UNIQUE KEYS");
32767 }
32768 }
32769 }
32770 if let Some(return_type) = &e.return_type {
32771 self.write_space();
32772 self.write_keyword("RETURNING");
32773 self.write_space();
32774 self.generate_expression(return_type)?;
32775 }
32776 self.write(")");
32777 Ok(())
32778 }
32779
32780 fn generate_json_array_append(&mut self, e: &JSONArrayAppend) -> Result<()> {
32781 self.write_keyword("JSON_ARRAY_APPEND");
32783 self.write("(");
32784 self.generate_expression(&e.this)?;
32785 for expr in &e.expressions {
32786 self.write(", ");
32787 self.generate_expression(expr)?;
32788 }
32789 self.write(")");
32790 Ok(())
32791 }
32792
32793 fn generate_json_array_contains(&mut self, e: &JSONArrayContains) -> Result<()> {
32794 self.write_keyword("JSON_ARRAY_CONTAINS");
32796 self.write("(");
32797 self.generate_expression(&e.this)?;
32798 self.write(", ");
32799 self.generate_expression(&e.expression)?;
32800 self.write(")");
32801 Ok(())
32802 }
32803
32804 fn generate_json_array_insert(&mut self, e: &JSONArrayInsert) -> Result<()> {
32805 self.write_keyword("JSON_ARRAY_INSERT");
32807 self.write("(");
32808 self.generate_expression(&e.this)?;
32809 for expr in &e.expressions {
32810 self.write(", ");
32811 self.generate_expression(expr)?;
32812 }
32813 self.write(")");
32814 Ok(())
32815 }
32816
32817 fn generate_jsonb_exists(&mut self, e: &JSONBExists) -> Result<()> {
32818 self.write_keyword("JSONB_EXISTS");
32820 self.write("(");
32821 self.generate_expression(&e.this)?;
32822 if let Some(path) = &e.path {
32823 self.write(", ");
32824 self.generate_expression(path)?;
32825 }
32826 self.write(")");
32827 Ok(())
32828 }
32829
32830 fn generate_jsonb_extract_scalar(&mut self, e: &JSONBExtractScalar) -> Result<()> {
32831 self.write_keyword("JSONB_EXTRACT_SCALAR");
32833 self.write("(");
32834 self.generate_expression(&e.this)?;
32835 self.write(", ");
32836 self.generate_expression(&e.expression)?;
32837 self.write(")");
32838 Ok(())
32839 }
32840
32841 fn generate_jsonb_object_agg(&mut self, e: &JSONBObjectAgg) -> Result<()> {
32842 self.write_keyword("JSONB_OBJECT_AGG");
32844 self.write("(");
32845 self.generate_expression(&e.this)?;
32846 self.write(", ");
32847 self.generate_expression(&e.expression)?;
32848 self.write(")");
32849 Ok(())
32850 }
32851
32852 fn generate_json_column_def(&mut self, e: &JSONColumnDef) -> Result<()> {
32853 if let Some(nested_schema) = &e.nested_schema {
32855 self.write_keyword("NESTED");
32856 if let Some(path) = &e.path {
32857 self.write_space();
32858 self.write_keyword("PATH");
32859 self.write_space();
32860 self.generate_expression(path)?;
32861 }
32862 self.write_space();
32863 self.generate_expression(nested_schema)?;
32864 } else {
32865 if let Some(this) = &e.this {
32866 self.generate_expression(this)?;
32867 }
32868 if let Some(kind) = &e.kind {
32869 self.write_space();
32870 self.write(kind);
32871 }
32872 if e.format_json {
32873 self.write_space();
32874 self.write_keyword("FORMAT JSON");
32875 }
32876 if let Some(path) = &e.path {
32877 self.write_space();
32878 self.write_keyword("PATH");
32879 self.write_space();
32880 self.generate_expression(path)?;
32881 }
32882 if e.ordinality.is_some() {
32883 self.write_keyword(" FOR ORDINALITY");
32884 }
32885 }
32886 Ok(())
32887 }
32888
32889 fn generate_json_exists(&mut self, e: &JSONExists) -> Result<()> {
32890 self.write_keyword("JSON_EXISTS");
32892 self.write("(");
32893 self.generate_expression(&e.this)?;
32894 if let Some(path) = &e.path {
32895 self.write(", ");
32896 self.generate_expression(path)?;
32897 }
32898 if let Some(passing) = &e.passing {
32899 self.write_space();
32900 self.write_keyword("PASSING");
32901 self.write_space();
32902 self.generate_expression(passing)?;
32903 }
32904 if let Some(on_condition) = &e.on_condition {
32905 self.write_space();
32906 self.generate_expression(on_condition)?;
32907 }
32908 self.write(")");
32909 Ok(())
32910 }
32911
32912 fn generate_json_cast(&mut self, e: &JSONCast) -> Result<()> {
32913 self.generate_expression(&e.this)?;
32914 self.write(".:");
32915 if Self::data_type_has_nested_expressions(&e.to) {
32919 let saved = std::mem::take(&mut self.output);
32921 self.generate_data_type(&e.to)?;
32922 let type_sql = std::mem::replace(&mut self.output, saved);
32923 self.write("\"");
32924 self.write(&type_sql);
32925 self.write("\"");
32926 } else {
32927 self.generate_data_type(&e.to)?;
32928 }
32929 Ok(())
32930 }
32931
32932 fn data_type_has_nested_expressions(dt: &DataType) -> bool {
32935 matches!(
32936 dt,
32937 DataType::Array { .. } | DataType::Map { .. } | DataType::Struct { .. }
32938 )
32939 }
32940
32941 fn generate_json_extract_array(&mut self, e: &JSONExtractArray) -> Result<()> {
32942 self.write_keyword("JSON_EXTRACT_ARRAY");
32944 self.write("(");
32945 self.generate_expression(&e.this)?;
32946 if let Some(expr) = &e.expression {
32947 self.write(", ");
32948 self.generate_expression(expr)?;
32949 }
32950 self.write(")");
32951 Ok(())
32952 }
32953
32954 fn generate_json_extract_quote(&mut self, e: &JSONExtractQuote) -> Result<()> {
32955 if let Some(option) = &e.option {
32957 self.generate_expression(option)?;
32958 self.write_space();
32959 }
32960 self.write_keyword("QUOTES");
32961 if e.scalar.is_some() {
32962 self.write_keyword(" SCALAR_ONLY");
32963 }
32964 Ok(())
32965 }
32966
32967 fn generate_json_extract_scalar(&mut self, e: &JSONExtractScalar) -> Result<()> {
32968 self.write_keyword("JSON_EXTRACT_SCALAR");
32970 self.write("(");
32971 self.generate_expression(&e.this)?;
32972 self.write(", ");
32973 self.generate_expression(&e.expression)?;
32974 self.write(")");
32975 Ok(())
32976 }
32977
32978 fn generate_json_extract_path(&mut self, e: &JSONExtract) -> Result<()> {
32979 if e.variant_extract.is_some() {
32983 use crate::dialects::DialectType;
32984 if matches!(self.config.dialect, Some(DialectType::Databricks)) {
32985 self.generate_expression(&e.this)?;
32989 self.write(":");
32990 match e.expression.as_ref() {
32991 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
32992 let Literal::String(s) = lit.as_ref() else {
32993 unreachable!()
32994 };
32995 self.write_databricks_json_path(s);
32996 }
32997 _ => {
32998 self.generate_expression(&e.expression)?;
33000 }
33001 }
33002 } else {
33003 self.write_keyword("GET_PATH");
33005 self.write("(");
33006 self.generate_expression(&e.this)?;
33007 self.write(", ");
33008 self.generate_expression(&e.expression)?;
33009 self.write(")");
33010 }
33011 } else {
33012 self.write_keyword("JSON_EXTRACT");
33013 self.write("(");
33014 self.generate_expression(&e.this)?;
33015 self.write(", ");
33016 self.generate_expression(&e.expression)?;
33017 for expr in &e.expressions {
33018 self.write(", ");
33019 self.generate_expression(expr)?;
33020 }
33021 self.write(")");
33022 }
33023 Ok(())
33024 }
33025
33026 fn write_databricks_json_path(&mut self, path: &str) {
33030 if path.starts_with("[\"") || path.starts_with("['") {
33033 self.write(path);
33034 return;
33035 }
33036 let mut first = true;
33040 for segment in path.split('.') {
33041 if !first {
33042 self.write(".");
33043 }
33044 first = false;
33045 if let Some(bracket_pos) = segment.find('[') {
33047 let key = &segment[..bracket_pos];
33048 let subscript = &segment[bracket_pos..];
33049 if key.is_empty() {
33050 self.write(segment);
33052 } else if Self::is_safe_json_path_key(key) {
33053 self.write(key);
33054 self.write(subscript);
33055 } else {
33056 self.write("[\"");
33057 self.write(key);
33058 self.write("\"]");
33059 self.write(subscript);
33060 }
33061 } else if Self::is_safe_json_path_key(segment) {
33062 self.write(segment);
33063 } else {
33064 self.write("[\"");
33065 self.write(segment);
33066 self.write("\"]");
33067 }
33068 }
33069 }
33070
33071 fn is_safe_json_path_key(key: &str) -> bool {
33074 if key.is_empty() {
33075 return false;
33076 }
33077 let mut chars = key.chars();
33078 let first = chars.next().unwrap();
33079 if first != '_' && !first.is_ascii_alphabetic() {
33080 return false;
33081 }
33082 chars.all(|c| c == '_' || c.is_ascii_alphanumeric())
33083 }
33084
33085 fn generate_json_format(&mut self, e: &JSONFormat) -> Result<()> {
33086 if let Some(this) = &e.this {
33089 self.generate_expression(this)?;
33090 self.write_space();
33091 }
33092 self.write_keyword("FORMAT JSON");
33093 Ok(())
33094 }
33095
33096 fn generate_json_key_value(&mut self, e: &JSONKeyValue) -> Result<()> {
33097 self.generate_expression(&e.this)?;
33099 self.write(": ");
33100 self.generate_expression(&e.expression)?;
33101 Ok(())
33102 }
33103
33104 fn generate_json_keys(&mut self, e: &JSONKeys) -> Result<()> {
33105 self.write_keyword("JSON_KEYS");
33107 self.write("(");
33108 self.generate_expression(&e.this)?;
33109 if let Some(expr) = &e.expression {
33110 self.write(", ");
33111 self.generate_expression(expr)?;
33112 }
33113 for expr in &e.expressions {
33114 self.write(", ");
33115 self.generate_expression(expr)?;
33116 }
33117 self.write(")");
33118 Ok(())
33119 }
33120
33121 fn generate_json_keys_at_depth(&mut self, e: &JSONKeysAtDepth) -> Result<()> {
33122 self.write_keyword("JSON_KEYS");
33124 self.write("(");
33125 self.generate_expression(&e.this)?;
33126 if let Some(expr) = &e.expression {
33127 self.write(", ");
33128 self.generate_expression(expr)?;
33129 }
33130 self.write(")");
33131 Ok(())
33132 }
33133
33134 fn generate_json_path_expr(&mut self, e: &JSONPath) -> Result<()> {
33135 let mut path_str = String::new();
33138 for expr in &e.expressions {
33139 match expr {
33140 Expression::JSONPathRoot(_) => {
33141 path_str.push('$');
33142 }
33143 Expression::JSONPathKey(k) => {
33144 if let Expression::Literal(lit) = k.this.as_ref() {
33146 if let crate::expressions::Literal::String(s) = lit.as_ref() {
33147 path_str.push('.');
33148 let needs_quoting = s.chars().any(|c| !c.is_alphanumeric() && c != '_');
33150 if needs_quoting {
33151 path_str.push('"');
33152 path_str.push_str(s);
33153 path_str.push('"');
33154 } else {
33155 path_str.push_str(s);
33156 }
33157 }
33158 }
33159 }
33160 Expression::JSONPathSubscript(s) => {
33161 if let Expression::Literal(lit) = s.this.as_ref() {
33163 if let crate::expressions::Literal::Number(n) = lit.as_ref() {
33164 path_str.push('[');
33165 path_str.push_str(n);
33166 path_str.push(']');
33167 }
33168 }
33169 }
33170 _ => {
33171 let mut temp_gen = Self::with_arc_config(self.config.clone());
33173 temp_gen.generate_expression(expr)?;
33174 path_str.push_str(&temp_gen.output);
33175 }
33176 }
33177 }
33178 self.write("'");
33180 self.write(&path_str);
33181 self.write("'");
33182 Ok(())
33183 }
33184
33185 fn generate_json_path_filter(&mut self, e: &JSONPathFilter) -> Result<()> {
33186 self.write("?(");
33188 self.generate_expression(&e.this)?;
33189 self.write(")");
33190 Ok(())
33191 }
33192
33193 fn generate_json_path_key(&mut self, e: &JSONPathKey) -> Result<()> {
33194 self.write(".");
33196 self.generate_expression(&e.this)?;
33197 Ok(())
33198 }
33199
33200 fn generate_json_path_recursive(&mut self, e: &JSONPathRecursive) -> Result<()> {
33201 self.write("..");
33203 if let Some(this) = &e.this {
33204 self.generate_expression(this)?;
33205 }
33206 Ok(())
33207 }
33208
33209 fn generate_json_path_root(&mut self) -> Result<()> {
33210 self.write("$");
33212 Ok(())
33213 }
33214
33215 fn generate_json_path_script(&mut self, e: &JSONPathScript) -> Result<()> {
33216 self.write("(");
33218 self.generate_expression(&e.this)?;
33219 self.write(")");
33220 Ok(())
33221 }
33222
33223 fn generate_json_path_selector(&mut self, e: &JSONPathSelector) -> Result<()> {
33224 self.generate_expression(&e.this)?;
33226 Ok(())
33227 }
33228
33229 fn generate_json_path_slice(&mut self, e: &JSONPathSlice) -> Result<()> {
33230 self.write("[");
33232 if let Some(start) = &e.start {
33233 self.generate_expression(start)?;
33234 }
33235 self.write(":");
33236 if let Some(end) = &e.end {
33237 self.generate_expression(end)?;
33238 }
33239 if let Some(step) = &e.step {
33240 self.write(":");
33241 self.generate_expression(step)?;
33242 }
33243 self.write("]");
33244 Ok(())
33245 }
33246
33247 fn generate_json_path_subscript(&mut self, e: &JSONPathSubscript) -> Result<()> {
33248 self.write("[");
33250 self.generate_expression(&e.this)?;
33251 self.write("]");
33252 Ok(())
33253 }
33254
33255 fn generate_json_path_union(&mut self, e: &JSONPathUnion) -> Result<()> {
33256 self.write("[");
33258 for (i, expr) in e.expressions.iter().enumerate() {
33259 if i > 0 {
33260 self.write(", ");
33261 }
33262 self.generate_expression(expr)?;
33263 }
33264 self.write("]");
33265 Ok(())
33266 }
33267
33268 fn generate_json_remove(&mut self, e: &JSONRemove) -> Result<()> {
33269 self.write_keyword("JSON_REMOVE");
33271 self.write("(");
33272 self.generate_expression(&e.this)?;
33273 for expr in &e.expressions {
33274 self.write(", ");
33275 self.generate_expression(expr)?;
33276 }
33277 self.write(")");
33278 Ok(())
33279 }
33280
33281 fn generate_json_schema(&mut self, e: &JSONSchema) -> Result<()> {
33282 self.write_keyword("COLUMNS");
33285 self.write("(");
33286
33287 if self.config.pretty && !e.expressions.is_empty() {
33288 let mut expr_strings: Vec<String> = Vec::with_capacity(e.expressions.len());
33290 for expr in &e.expressions {
33291 let mut temp_gen = Generator::with_arc_config(self.config.clone());
33292 temp_gen.generate_expression(expr)?;
33293 expr_strings.push(temp_gen.output);
33294 }
33295
33296 if self.too_wide(&expr_strings) {
33298 self.write_newline();
33300 self.indent_level += 1;
33301 for (i, expr_str) in expr_strings.iter().enumerate() {
33302 if i > 0 {
33303 self.write(",");
33304 self.write_newline();
33305 }
33306 self.write_indent();
33307 self.write(expr_str);
33308 }
33309 self.write_newline();
33310 self.indent_level -= 1;
33311 self.write_indent();
33312 } else {
33313 for (i, expr_str) in expr_strings.iter().enumerate() {
33315 if i > 0 {
33316 self.write(", ");
33317 }
33318 self.write(expr_str);
33319 }
33320 }
33321 } else {
33322 for (i, expr) in e.expressions.iter().enumerate() {
33324 if i > 0 {
33325 self.write(", ");
33326 }
33327 self.generate_expression(expr)?;
33328 }
33329 }
33330 self.write(")");
33331 Ok(())
33332 }
33333
33334 fn generate_json_set(&mut self, e: &JSONSet) -> Result<()> {
33335 self.write_keyword("JSON_SET");
33337 self.write("(");
33338 self.generate_expression(&e.this)?;
33339 for expr in &e.expressions {
33340 self.write(", ");
33341 self.generate_expression(expr)?;
33342 }
33343 self.write(")");
33344 Ok(())
33345 }
33346
33347 fn generate_json_strip_nulls(&mut self, e: &JSONStripNulls) -> Result<()> {
33348 self.write_keyword("JSON_STRIP_NULLS");
33350 self.write("(");
33351 self.generate_expression(&e.this)?;
33352 if let Some(expr) = &e.expression {
33353 self.write(", ");
33354 self.generate_expression(expr)?;
33355 }
33356 self.write(")");
33357 Ok(())
33358 }
33359
33360 fn generate_json_table(&mut self, e: &JSONTable) -> Result<()> {
33361 self.write_keyword("JSON_TABLE");
33363 self.write("(");
33364 self.generate_expression(&e.this)?;
33365 if let Some(path) = &e.path {
33366 self.write(", ");
33367 self.generate_expression(path)?;
33368 }
33369 if let Some(error_handling) = &e.error_handling {
33370 self.write_space();
33371 self.generate_expression(error_handling)?;
33372 }
33373 if let Some(empty_handling) = &e.empty_handling {
33374 self.write_space();
33375 self.generate_expression(empty_handling)?;
33376 }
33377 if let Some(schema) = &e.schema {
33378 self.write_space();
33379 self.generate_expression(schema)?;
33380 }
33381 self.write(")");
33382 Ok(())
33383 }
33384
33385 fn generate_json_type(&mut self, e: &JSONType) -> Result<()> {
33386 self.write_keyword("JSON_TYPE");
33388 self.write("(");
33389 self.generate_expression(&e.this)?;
33390 self.write(")");
33391 Ok(())
33392 }
33393
33394 fn generate_json_value(&mut self, e: &JSONValue) -> Result<()> {
33395 self.write_keyword("JSON_VALUE");
33397 self.write("(");
33398 self.generate_expression(&e.this)?;
33399 if let Some(path) = &e.path {
33400 self.write(", ");
33401 self.generate_expression(path)?;
33402 }
33403 if let Some(returning) = &e.returning {
33404 self.write_space();
33405 self.write_keyword("RETURNING");
33406 self.write_space();
33407 self.generate_expression(returning)?;
33408 }
33409 if let Some(on_condition) = &e.on_condition {
33410 self.write_space();
33411 self.generate_expression(on_condition)?;
33412 }
33413 self.write(")");
33414 Ok(())
33415 }
33416
33417 fn generate_json_value_array(&mut self, e: &JSONValueArray) -> Result<()> {
33418 self.write_keyword("JSON_VALUE_ARRAY");
33420 self.write("(");
33421 self.generate_expression(&e.this)?;
33422 self.write(")");
33423 Ok(())
33424 }
33425
33426 fn generate_jarowinkler_similarity(&mut self, e: &JarowinklerSimilarity) -> Result<()> {
33427 self.write_keyword("JAROWINKLER_SIMILARITY");
33429 self.write("(");
33430 self.generate_expression(&e.this)?;
33431 self.write(", ");
33432 self.generate_expression(&e.expression)?;
33433 self.write(")");
33434 Ok(())
33435 }
33436
33437 fn generate_join_hint(&mut self, e: &JoinHint) -> Result<()> {
33438 self.generate_expression(&e.this)?;
33440 self.write("(");
33441 for (i, expr) in e.expressions.iter().enumerate() {
33442 if i > 0 {
33443 self.write(", ");
33444 }
33445 self.generate_expression(expr)?;
33446 }
33447 self.write(")");
33448 Ok(())
33449 }
33450
33451 fn generate_journal_property(&mut self, e: &JournalProperty) -> Result<()> {
33452 if e.no.is_some() {
33454 self.write_keyword("NO ");
33455 }
33456 if let Some(local) = &e.local {
33457 self.generate_expression(local)?;
33458 self.write_space();
33459 }
33460 if e.dual.is_some() {
33461 self.write_keyword("DUAL ");
33462 }
33463 if e.before.is_some() {
33464 self.write_keyword("BEFORE ");
33465 }
33466 if e.after.is_some() {
33467 self.write_keyword("AFTER ");
33468 }
33469 self.write_keyword("JOURNAL");
33470 Ok(())
33471 }
33472
33473 fn generate_language_property(&mut self, e: &LanguageProperty) -> Result<()> {
33474 self.write_keyword("LANGUAGE");
33476 self.write_space();
33477 self.generate_expression(&e.this)?;
33478 Ok(())
33479 }
33480
33481 fn generate_lateral(&mut self, e: &Lateral) -> Result<()> {
33482 if e.view.is_some() {
33484 self.write_keyword("LATERAL VIEW");
33486 if e.outer.is_some() {
33487 self.write_space();
33488 self.write_keyword("OUTER");
33489 }
33490 self.write_space();
33491 self.generate_expression(&e.this)?;
33492 if let Some(alias) = &e.alias {
33493 self.write_space();
33494 self.write(alias);
33495 }
33496 } else {
33497 self.write_keyword("LATERAL");
33499 self.write_space();
33500 self.generate_expression(&e.this)?;
33501 if e.ordinality.is_some() {
33502 self.write_space();
33503 self.write_keyword("WITH ORDINALITY");
33504 }
33505 if let Some(alias) = &e.alias {
33506 self.write_space();
33507 self.write_keyword("AS");
33508 self.write_space();
33509 self.write(alias);
33510 if !e.column_aliases.is_empty() {
33511 self.write("(");
33512 for (i, col) in e.column_aliases.iter().enumerate() {
33513 if i > 0 {
33514 self.write(", ");
33515 }
33516 self.write(col);
33517 }
33518 self.write(")");
33519 }
33520 }
33521 }
33522 Ok(())
33523 }
33524
33525 fn generate_like_property(&mut self, e: &LikeProperty) -> Result<()> {
33526 self.write_keyword("LIKE");
33528 self.write_space();
33529 self.generate_expression(&e.this)?;
33530 for expr in &e.expressions {
33531 self.write_space();
33532 self.generate_expression(expr)?;
33533 }
33534 Ok(())
33535 }
33536
33537 fn generate_limit(&mut self, e: &Limit) -> Result<()> {
33538 self.write_keyword("LIMIT");
33539 self.write_space();
33540 self.write_limit_expr(&e.this)?;
33541 if e.percent {
33542 self.write_space();
33543 self.write_keyword("PERCENT");
33544 }
33545 for comment in &e.comments {
33547 self.write(" ");
33548 self.write_formatted_comment(comment);
33549 }
33550 Ok(())
33551 }
33552
33553 fn generate_limit_options(&mut self, e: &LimitOptions) -> Result<()> {
33554 if e.percent.is_some() {
33556 self.write_keyword(" PERCENT");
33557 }
33558 if e.rows.is_some() {
33559 self.write_keyword(" ROWS");
33560 }
33561 if e.with_ties.is_some() {
33562 self.write_keyword(" WITH TIES");
33563 } else if e.rows.is_some() {
33564 self.write_keyword(" ONLY");
33565 }
33566 Ok(())
33567 }
33568
33569 fn generate_list(&mut self, e: &List) -> Result<()> {
33570 use crate::dialects::DialectType;
33571 let is_materialize = matches!(self.config.dialect, Some(DialectType::Materialize));
33572
33573 if e.expressions.len() == 1 {
33575 if let Expression::Select(_) = &e.expressions[0] {
33576 self.write_keyword("LIST");
33577 self.write("(");
33578 self.generate_expression(&e.expressions[0])?;
33579 self.write(")");
33580 return Ok(());
33581 }
33582 }
33583
33584 if is_materialize {
33586 self.write_keyword("LIST");
33587 self.write("[");
33588 for (i, expr) in e.expressions.iter().enumerate() {
33589 if i > 0 {
33590 self.write(", ");
33591 }
33592 self.generate_expression(expr)?;
33593 }
33594 self.write("]");
33595 } else {
33596 self.write_keyword("LIST");
33598 self.write("(");
33599 for (i, expr) in e.expressions.iter().enumerate() {
33600 if i > 0 {
33601 self.write(", ");
33602 }
33603 self.generate_expression(expr)?;
33604 }
33605 self.write(")");
33606 }
33607 Ok(())
33608 }
33609
33610 fn generate_tomap(&mut self, e: &ToMap) -> Result<()> {
33611 if let Expression::Select(_) = &*e.this {
33613 self.write_keyword("MAP");
33614 self.write("(");
33615 self.generate_expression(&e.this)?;
33616 self.write(")");
33617 return Ok(());
33618 }
33619
33620 let is_duckdb = matches!(self.config.dialect, Some(DialectType::DuckDB));
33621
33622 self.write_keyword("MAP");
33624 if is_duckdb {
33625 self.write(" {");
33626 } else {
33627 self.write("[");
33628 }
33629 if let Expression::Struct(s) = &*e.this {
33630 for (i, (_, expr)) in s.fields.iter().enumerate() {
33631 if i > 0 {
33632 self.write(", ");
33633 }
33634 if let Expression::PropertyEQ(op) = expr {
33635 self.generate_expression(&op.left)?;
33636 if is_duckdb {
33637 self.write(": ");
33638 } else {
33639 self.write(" => ");
33640 }
33641 self.generate_expression(&op.right)?;
33642 } else {
33643 self.generate_expression(expr)?;
33644 }
33645 }
33646 }
33647 if is_duckdb {
33648 self.write("}");
33649 } else {
33650 self.write("]");
33651 }
33652 Ok(())
33653 }
33654
33655 fn generate_localtime(&mut self, e: &Localtime) -> Result<()> {
33656 self.write_keyword("LOCALTIME");
33658 if let Some(precision) = &e.this {
33659 self.write("(");
33660 self.generate_expression(precision)?;
33661 self.write(")");
33662 }
33663 Ok(())
33664 }
33665
33666 fn generate_localtimestamp(&mut self, e: &Localtimestamp) -> Result<()> {
33667 self.write_keyword("LOCALTIMESTAMP");
33669 if let Some(precision) = &e.this {
33670 self.write("(");
33671 self.generate_expression(precision)?;
33672 self.write(")");
33673 }
33674 Ok(())
33675 }
33676
33677 fn generate_location_property(&mut self, e: &LocationProperty) -> Result<()> {
33678 self.write_keyword("LOCATION");
33680 self.write_space();
33681 self.generate_expression(&e.this)?;
33682 Ok(())
33683 }
33684
33685 fn generate_lock(&mut self, e: &Lock) -> Result<()> {
33686 if e.update.is_some() {
33688 if e.key.is_some() {
33689 self.write_keyword("FOR NO KEY UPDATE");
33690 } else {
33691 self.write_keyword("FOR UPDATE");
33692 }
33693 } else {
33694 if e.key.is_some() {
33695 self.write_keyword("FOR KEY SHARE");
33696 } else {
33697 self.write_keyword("FOR SHARE");
33698 }
33699 }
33700 if !e.expressions.is_empty() {
33701 self.write_keyword(" OF ");
33702 for (i, expr) in e.expressions.iter().enumerate() {
33703 if i > 0 {
33704 self.write(", ");
33705 }
33706 self.generate_expression(expr)?;
33707 }
33708 }
33709 if let Some(wait) = &e.wait {
33714 match wait.as_ref() {
33715 Expression::Boolean(b) => {
33716 if b.value {
33717 self.write_keyword(" NOWAIT");
33718 } else {
33719 self.write_keyword(" SKIP LOCKED");
33720 }
33721 }
33722 _ => {
33723 self.write_keyword(" WAIT ");
33725 self.generate_expression(wait)?;
33726 }
33727 }
33728 }
33729 Ok(())
33730 }
33731
33732 fn generate_lock_property(&mut self, e: &LockProperty) -> Result<()> {
33733 self.write_keyword("LOCK");
33735 self.write_space();
33736 self.generate_expression(&e.this)?;
33737 Ok(())
33738 }
33739
33740 fn generate_locking_property(&mut self, e: &LockingProperty) -> Result<()> {
33741 self.write_keyword("LOCKING");
33743 self.write_space();
33744 self.write(&e.kind);
33745 if let Some(this) = &e.this {
33746 self.write_space();
33747 self.generate_expression(this)?;
33748 }
33749 if let Some(for_or_in) = &e.for_or_in {
33750 self.write_space();
33751 self.generate_expression(for_or_in)?;
33752 }
33753 if let Some(lock_type) = &e.lock_type {
33754 self.write_space();
33755 self.generate_expression(lock_type)?;
33756 }
33757 if e.override_.is_some() {
33758 self.write_keyword(" OVERRIDE");
33759 }
33760 Ok(())
33761 }
33762
33763 fn generate_locking_statement(&mut self, e: &LockingStatement) -> Result<()> {
33764 self.generate_expression(&e.this)?;
33766 self.write_space();
33767 self.generate_expression(&e.expression)?;
33768 Ok(())
33769 }
33770
33771 fn generate_log_property(&mut self, e: &LogProperty) -> Result<()> {
33772 if e.no.is_some() {
33774 self.write_keyword("NO ");
33775 }
33776 self.write_keyword("LOG");
33777 Ok(())
33778 }
33779
33780 fn generate_md5_digest(&mut self, e: &MD5Digest) -> Result<()> {
33781 self.write_keyword("MD5");
33783 self.write("(");
33784 self.generate_expression(&e.this)?;
33785 for expr in &e.expressions {
33786 self.write(", ");
33787 self.generate_expression(expr)?;
33788 }
33789 self.write(")");
33790 Ok(())
33791 }
33792
33793 fn generate_ml_forecast(&mut self, e: &MLForecast) -> Result<()> {
33794 self.write_keyword("ML.FORECAST");
33796 self.write("(");
33797 self.generate_expression(&e.this)?;
33798 if let Some(expression) = &e.expression {
33799 self.write(", ");
33800 self.generate_expression(expression)?;
33801 }
33802 if let Some(params) = &e.params_struct {
33803 self.write(", ");
33804 self.generate_expression(params)?;
33805 }
33806 self.write(")");
33807 Ok(())
33808 }
33809
33810 fn generate_ml_translate(&mut self, e: &MLTranslate) -> Result<()> {
33811 self.write_keyword("ML.TRANSLATE");
33813 self.write("(");
33814 self.generate_expression(&e.this)?;
33815 self.write(", ");
33816 self.generate_expression(&e.expression)?;
33817 if let Some(params) = &e.params_struct {
33818 self.write(", ");
33819 self.generate_expression(params)?;
33820 }
33821 self.write(")");
33822 Ok(())
33823 }
33824
33825 fn generate_make_interval(&mut self, e: &MakeInterval) -> Result<()> {
33826 self.write_keyword("MAKE_INTERVAL");
33828 self.write("(");
33829 let mut first = true;
33830 if let Some(year) = &e.year {
33831 self.write("years => ");
33832 self.generate_expression(year)?;
33833 first = false;
33834 }
33835 if let Some(month) = &e.month {
33836 if !first {
33837 self.write(", ");
33838 }
33839 self.write("months => ");
33840 self.generate_expression(month)?;
33841 first = false;
33842 }
33843 if let Some(week) = &e.week {
33844 if !first {
33845 self.write(", ");
33846 }
33847 self.write("weeks => ");
33848 self.generate_expression(week)?;
33849 first = false;
33850 }
33851 if let Some(day) = &e.day {
33852 if !first {
33853 self.write(", ");
33854 }
33855 self.write("days => ");
33856 self.generate_expression(day)?;
33857 first = false;
33858 }
33859 if let Some(hour) = &e.hour {
33860 if !first {
33861 self.write(", ");
33862 }
33863 self.write("hours => ");
33864 self.generate_expression(hour)?;
33865 first = false;
33866 }
33867 if let Some(minute) = &e.minute {
33868 if !first {
33869 self.write(", ");
33870 }
33871 self.write("mins => ");
33872 self.generate_expression(minute)?;
33873 first = false;
33874 }
33875 if let Some(second) = &e.second {
33876 if !first {
33877 self.write(", ");
33878 }
33879 self.write("secs => ");
33880 self.generate_expression(second)?;
33881 }
33882 self.write(")");
33883 Ok(())
33884 }
33885
33886 fn generate_manhattan_distance(&mut self, e: &ManhattanDistance) -> Result<()> {
33887 self.write_keyword("MANHATTAN_DISTANCE");
33889 self.write("(");
33890 self.generate_expression(&e.this)?;
33891 self.write(", ");
33892 self.generate_expression(&e.expression)?;
33893 self.write(")");
33894 Ok(())
33895 }
33896
33897 fn generate_map(&mut self, e: &Map) -> Result<()> {
33898 self.write_keyword("MAP");
33900 self.write("(");
33901 for (i, (key, value)) in e.keys.iter().zip(e.values.iter()).enumerate() {
33902 if i > 0 {
33903 self.write(", ");
33904 }
33905 self.generate_expression(key)?;
33906 self.write(", ");
33907 self.generate_expression(value)?;
33908 }
33909 self.write(")");
33910 Ok(())
33911 }
33912
33913 fn generate_map_cat(&mut self, e: &MapCat) -> Result<()> {
33914 self.write_keyword("MAP_CAT");
33916 self.write("(");
33917 self.generate_expression(&e.this)?;
33918 self.write(", ");
33919 self.generate_expression(&e.expression)?;
33920 self.write(")");
33921 Ok(())
33922 }
33923
33924 fn generate_map_delete(&mut self, e: &MapDelete) -> Result<()> {
33925 self.write_keyword("MAP_DELETE");
33927 self.write("(");
33928 self.generate_expression(&e.this)?;
33929 for expr in &e.expressions {
33930 self.write(", ");
33931 self.generate_expression(expr)?;
33932 }
33933 self.write(")");
33934 Ok(())
33935 }
33936
33937 fn generate_map_insert(&mut self, e: &MapInsert) -> Result<()> {
33938 self.write_keyword("MAP_INSERT");
33940 self.write("(");
33941 self.generate_expression(&e.this)?;
33942 if let Some(key) = &e.key {
33943 self.write(", ");
33944 self.generate_expression(key)?;
33945 }
33946 if let Some(value) = &e.value {
33947 self.write(", ");
33948 self.generate_expression(value)?;
33949 }
33950 if let Some(update_flag) = &e.update_flag {
33951 self.write(", ");
33952 self.generate_expression(update_flag)?;
33953 }
33954 self.write(")");
33955 Ok(())
33956 }
33957
33958 fn generate_map_pick(&mut self, e: &MapPick) -> Result<()> {
33959 self.write_keyword("MAP_PICK");
33961 self.write("(");
33962 self.generate_expression(&e.this)?;
33963 for expr in &e.expressions {
33964 self.write(", ");
33965 self.generate_expression(expr)?;
33966 }
33967 self.write(")");
33968 Ok(())
33969 }
33970
33971 fn generate_masking_policy_column_constraint(
33972 &mut self,
33973 e: &MaskingPolicyColumnConstraint,
33974 ) -> Result<()> {
33975 self.write_keyword("MASKING POLICY");
33977 self.write_space();
33978 self.generate_expression(&e.this)?;
33979 if !e.expressions.is_empty() {
33980 self.write_keyword(" USING");
33981 self.write(" (");
33982 for (i, expr) in e.expressions.iter().enumerate() {
33983 if i > 0 {
33984 self.write(", ");
33985 }
33986 self.generate_expression(expr)?;
33987 }
33988 self.write(")");
33989 }
33990 Ok(())
33991 }
33992
33993 fn generate_match_against(&mut self, e: &MatchAgainst) -> Result<()> {
33994 if matches!(
33995 self.config.dialect,
33996 Some(DialectType::PostgreSQL) | Some(DialectType::Redshift)
33997 ) {
33998 if e.expressions.len() > 1 {
33999 self.write("(");
34000 }
34001 for (i, expr) in e.expressions.iter().enumerate() {
34002 if i > 0 {
34003 self.write_keyword(" OR ");
34004 }
34005 self.generate_expression(expr)?;
34006 self.write_space();
34007 self.write("@@");
34008 self.write_space();
34009 self.generate_expression(&e.this)?;
34010 }
34011 if e.expressions.len() > 1 {
34012 self.write(")");
34013 }
34014 return Ok(());
34015 }
34016
34017 self.write_keyword("MATCH");
34019 self.write("(");
34020 for (i, expr) in e.expressions.iter().enumerate() {
34021 if i > 0 {
34022 self.write(", ");
34023 }
34024 self.generate_expression(expr)?;
34025 }
34026 self.write(")");
34027 self.write_keyword(" AGAINST");
34028 self.write("(");
34029 self.generate_expression(&e.this)?;
34030 if let Some(modifier) = &e.modifier {
34031 self.write_space();
34032 self.generate_expression(modifier)?;
34033 }
34034 self.write(")");
34035 Ok(())
34036 }
34037
34038 fn generate_match_recognize_measure(&mut self, e: &MatchRecognizeMeasure) -> Result<()> {
34039 if let Some(window_frame) = &e.window_frame {
34041 self.write(&format!("{:?}", window_frame).to_ascii_uppercase());
34042 self.write_space();
34043 }
34044 self.generate_expression(&e.this)?;
34045 Ok(())
34046 }
34047
34048 fn generate_materialized_property(&mut self, e: &MaterializedProperty) -> Result<()> {
34049 self.write_keyword("MATERIALIZED");
34051 if let Some(this) = &e.this {
34052 self.write_space();
34053 self.generate_expression(this)?;
34054 }
34055 Ok(())
34056 }
34057
34058 fn generate_merge(&mut self, e: &Merge) -> Result<()> {
34059 if let Some(with_) = &e.with_ {
34062 if let Expression::With(with_clause) = with_.as_ref() {
34063 self.generate_with(with_clause)?;
34064 self.write_space();
34065 } else {
34066 self.generate_expression(with_)?;
34067 self.write_space();
34068 }
34069 }
34070 self.write_keyword("MERGE INTO");
34071 self.write_space();
34072 if matches!(self.config.dialect, Some(crate::DialectType::Oracle)) {
34073 if let Expression::Alias(alias) = e.this.as_ref() {
34074 self.generate_expression(&alias.this)?;
34075 self.write_space();
34076 self.generate_identifier(&alias.alias)?;
34077 } else {
34078 self.generate_expression(&e.this)?;
34079 }
34080 } else {
34081 self.generate_expression(&e.this)?;
34082 }
34083
34084 if self.config.pretty {
34086 self.write_newline();
34087 self.write_indent();
34088 } else {
34089 self.write_space();
34090 }
34091 self.write_keyword("USING");
34092 self.write_space();
34093 self.generate_expression(&e.using)?;
34094
34095 if let Some(on) = &e.on {
34097 if self.config.pretty {
34098 self.write_newline();
34099 self.write_indent();
34100 } else {
34101 self.write_space();
34102 }
34103 self.write_keyword("ON");
34104 self.write_space();
34105 self.generate_expression(on)?;
34106 }
34107 if let Some(using_cond) = &e.using_cond {
34109 self.write_space();
34110 self.write_keyword("USING");
34111 self.write_space();
34112 self.write("(");
34113 if let Expression::Tuple(tuple) = using_cond.as_ref() {
34115 for (i, col) in tuple.expressions.iter().enumerate() {
34116 if i > 0 {
34117 self.write(", ");
34118 }
34119 self.generate_expression(col)?;
34120 }
34121 } else {
34122 self.generate_expression(using_cond)?;
34123 }
34124 self.write(")");
34125 }
34126 let saved_merge_strip = std::mem::take(&mut self.merge_strip_qualifiers);
34128 if matches!(
34129 self.config.dialect,
34130 Some(crate::DialectType::PostgreSQL)
34131 | Some(crate::DialectType::Redshift)
34132 | Some(crate::DialectType::Trino)
34133 | Some(crate::DialectType::Presto)
34134 | Some(crate::DialectType::Athena)
34135 ) {
34136 let mut names = Vec::new();
34137 match e.this.as_ref() {
34138 Expression::Alias(a) => {
34139 if let Expression::Table(t) = &a.this {
34141 names.push(t.name.name.clone());
34142 } else if let Expression::Identifier(id) = &a.this {
34143 names.push(id.name.clone());
34144 }
34145 names.push(a.alias.name.clone());
34146 }
34147 Expression::Table(t) => {
34148 names.push(t.name.name.clone());
34149 }
34150 Expression::Identifier(id) => {
34151 names.push(id.name.clone());
34152 }
34153 _ => {}
34154 }
34155 self.merge_strip_qualifiers = names;
34156 }
34157
34158 if let Some(whens) = &e.whens {
34160 if self.config.pretty {
34161 self.write_newline();
34162 self.write_indent();
34163 } else {
34164 self.write_space();
34165 }
34166 self.generate_expression(whens)?;
34167 }
34168
34169 self.merge_strip_qualifiers = saved_merge_strip;
34171
34172 if let Some(returning) = &e.returning {
34174 if self.config.pretty {
34175 self.write_newline();
34176 self.write_indent();
34177 } else {
34178 self.write_space();
34179 }
34180 self.generate_expression(returning)?;
34181 }
34182 Ok(())
34183 }
34184
34185 fn generate_merge_block_ratio_property(&mut self, e: &MergeBlockRatioProperty) -> Result<()> {
34186 if e.no.is_some() {
34188 self.write_keyword("NO MERGEBLOCKRATIO");
34189 } else if e.default.is_some() {
34190 self.write_keyword("DEFAULT MERGEBLOCKRATIO");
34191 } else {
34192 self.write_keyword("MERGEBLOCKRATIO");
34193 self.write("=");
34194 if let Some(this) = &e.this {
34195 self.generate_expression(this)?;
34196 }
34197 if e.percent.is_some() {
34198 self.write_keyword(" PERCENT");
34199 }
34200 }
34201 Ok(())
34202 }
34203
34204 fn generate_merge_tree_ttl(&mut self, e: &MergeTreeTTL) -> Result<()> {
34205 self.write_keyword("TTL");
34207 let pretty_clickhouse = self.config.pretty
34208 && matches!(
34209 self.config.dialect,
34210 Some(crate::dialects::DialectType::ClickHouse)
34211 );
34212
34213 if pretty_clickhouse {
34214 self.write_newline();
34215 self.indent_level += 1;
34216 for (i, expr) in e.expressions.iter().enumerate() {
34217 if i > 0 {
34218 self.write(",");
34219 self.write_newline();
34220 }
34221 self.write_indent();
34222 self.generate_expression(expr)?;
34223 }
34224 self.indent_level -= 1;
34225 } else {
34226 self.write_space();
34227 for (i, expr) in e.expressions.iter().enumerate() {
34228 if i > 0 {
34229 self.write(", ");
34230 }
34231 self.generate_expression(expr)?;
34232 }
34233 }
34234
34235 if let Some(where_) = &e.where_ {
34236 if pretty_clickhouse {
34237 self.write_newline();
34238 if let Expression::Where(w) = where_.as_ref() {
34239 self.write_indent();
34240 self.write_keyword("WHERE");
34241 self.write_newline();
34242 self.indent_level += 1;
34243 self.write_indent();
34244 self.generate_expression(&w.this)?;
34245 self.indent_level -= 1;
34246 } else {
34247 self.write_indent();
34248 self.generate_expression(where_)?;
34249 }
34250 } else {
34251 self.write_space();
34252 self.generate_expression(where_)?;
34253 }
34254 }
34255 if let Some(group) = &e.group {
34256 if pretty_clickhouse {
34257 self.write_newline();
34258 if let Expression::Group(g) = group.as_ref() {
34259 self.write_indent();
34260 self.write_keyword("GROUP BY");
34261 self.write_newline();
34262 self.indent_level += 1;
34263 for (i, expr) in g.expressions.iter().enumerate() {
34264 if i > 0 {
34265 self.write(",");
34266 self.write_newline();
34267 }
34268 self.write_indent();
34269 self.generate_expression(expr)?;
34270 }
34271 self.indent_level -= 1;
34272 } else {
34273 self.write_indent();
34274 self.generate_expression(group)?;
34275 }
34276 } else {
34277 self.write_space();
34278 self.generate_expression(group)?;
34279 }
34280 }
34281 if let Some(aggregates) = &e.aggregates {
34282 if pretty_clickhouse {
34283 self.write_newline();
34284 self.write_indent();
34285 self.write_keyword("SET");
34286 self.write_newline();
34287 self.indent_level += 1;
34288 if let Expression::Tuple(t) = aggregates.as_ref() {
34289 for (i, agg) in t.expressions.iter().enumerate() {
34290 if i > 0 {
34291 self.write(",");
34292 self.write_newline();
34293 }
34294 self.write_indent();
34295 self.generate_expression(agg)?;
34296 }
34297 } else {
34298 self.write_indent();
34299 self.generate_expression(aggregates)?;
34300 }
34301 self.indent_level -= 1;
34302 } else {
34303 self.write_space();
34304 self.write_keyword("SET");
34305 self.write_space();
34306 if let Expression::Tuple(t) = aggregates.as_ref() {
34307 for (i, agg) in t.expressions.iter().enumerate() {
34308 if i > 0 {
34309 self.write(", ");
34310 }
34311 self.generate_expression(agg)?;
34312 }
34313 } else {
34314 self.generate_expression(aggregates)?;
34315 }
34316 }
34317 }
34318 Ok(())
34319 }
34320
34321 fn generate_merge_tree_ttl_action(&mut self, e: &MergeTreeTTLAction) -> Result<()> {
34322 self.generate_expression(&e.this)?;
34324 if e.delete.is_some() {
34325 self.write_keyword(" DELETE");
34326 }
34327 if let Some(recompress) = &e.recompress {
34328 self.write_keyword(" RECOMPRESS ");
34329 self.generate_expression(recompress)?;
34330 }
34331 if let Some(to_disk) = &e.to_disk {
34332 self.write_keyword(" TO DISK ");
34333 self.generate_expression(to_disk)?;
34334 }
34335 if let Some(to_volume) = &e.to_volume {
34336 self.write_keyword(" TO VOLUME ");
34337 self.generate_expression(to_volume)?;
34338 }
34339 Ok(())
34340 }
34341
34342 fn generate_minhash(&mut self, e: &Minhash) -> Result<()> {
34343 self.write_keyword("MINHASH");
34345 self.write("(");
34346 self.generate_expression(&e.this)?;
34347 for expr in &e.expressions {
34348 self.write(", ");
34349 self.generate_expression(expr)?;
34350 }
34351 self.write(")");
34352 Ok(())
34353 }
34354
34355 fn generate_model_attribute(&mut self, e: &ModelAttribute) -> Result<()> {
34356 self.generate_expression(&e.this)?;
34358 self.write("!");
34359 self.generate_expression(&e.expression)?;
34360 Ok(())
34361 }
34362
34363 fn generate_monthname(&mut self, e: &Monthname) -> Result<()> {
34364 self.write_keyword("MONTHNAME");
34366 self.write("(");
34367 self.generate_expression(&e.this)?;
34368 self.write(")");
34369 Ok(())
34370 }
34371
34372 fn generate_multitable_inserts(&mut self, e: &MultitableInserts) -> Result<()> {
34373 for comment in &e.leading_comments {
34375 self.write_formatted_comment(comment);
34376 if self.config.pretty {
34377 self.write_newline();
34378 self.write_indent();
34379 } else {
34380 self.write_space();
34381 }
34382 }
34383 self.write_keyword("INSERT");
34385 if e.overwrite {
34386 self.write_space();
34387 self.write_keyword("OVERWRITE");
34388 }
34389 self.write_space();
34390 self.write(&e.kind);
34391 if self.config.pretty {
34392 self.indent_level += 1;
34393 for expr in &e.expressions {
34394 self.write_newline();
34395 self.write_indent();
34396 self.generate_expression(expr)?;
34397 }
34398 self.indent_level -= 1;
34399 } else {
34400 for expr in &e.expressions {
34401 self.write_space();
34402 self.generate_expression(expr)?;
34403 }
34404 }
34405 if let Some(source) = &e.source {
34406 if self.config.pretty {
34407 self.write_newline();
34408 self.write_indent();
34409 } else {
34410 self.write_space();
34411 }
34412 self.generate_expression(source)?;
34413 }
34414 Ok(())
34415 }
34416
34417 fn generate_next_value_for(&mut self, e: &NextValueFor) -> Result<()> {
34418 self.write_keyword("NEXT VALUE FOR");
34420 self.write_space();
34421 self.generate_expression(&e.this)?;
34422 if let Some(order) = &e.order {
34423 self.write_space();
34424 self.write_keyword("OVER");
34425 self.write(" (");
34426 self.generate_expression(order)?;
34427 self.write(")");
34428 }
34429 Ok(())
34430 }
34431
34432 fn generate_normal(&mut self, e: &Normal) -> Result<()> {
34433 self.write_keyword("NORMAL");
34435 self.write("(");
34436 self.generate_expression(&e.this)?;
34437 if let Some(stddev) = &e.stddev {
34438 self.write(", ");
34439 self.generate_expression(stddev)?;
34440 }
34441 if let Some(gen) = &e.gen {
34442 self.write(", ");
34443 self.generate_expression(gen)?;
34444 }
34445 self.write(")");
34446 Ok(())
34447 }
34448
34449 fn generate_normalize(&mut self, e: &Normalize) -> Result<()> {
34450 if e.is_casefold.is_some() {
34452 self.write_keyword("NORMALIZE_AND_CASEFOLD");
34453 } else {
34454 self.write_keyword("NORMALIZE");
34455 }
34456 self.write("(");
34457 self.generate_expression(&e.this)?;
34458 if let Some(form) = &e.form {
34459 self.write(", ");
34460 self.generate_expression(form)?;
34461 }
34462 self.write(")");
34463 Ok(())
34464 }
34465
34466 fn generate_not_null_column_constraint(&mut self, e: &NotNullColumnConstraint) -> Result<()> {
34467 if e.allow_null.is_none() {
34469 self.write_keyword("NOT ");
34470 }
34471 self.write_keyword("NULL");
34472 Ok(())
34473 }
34474
34475 fn generate_nullif(&mut self, e: &Nullif) -> Result<()> {
34476 self.write_keyword("NULLIF");
34478 self.write("(");
34479 self.generate_expression(&e.this)?;
34480 self.write(", ");
34481 self.generate_expression(&e.expression)?;
34482 self.write(")");
34483 Ok(())
34484 }
34485
34486 fn generate_number_to_str(&mut self, e: &NumberToStr) -> Result<()> {
34487 self.write_keyword("FORMAT");
34489 self.write("(");
34490 self.generate_expression(&e.this)?;
34491 self.write(", '");
34492 self.write(&e.format);
34493 self.write("'");
34494 if let Some(culture) = &e.culture {
34495 self.write(", ");
34496 self.generate_expression(culture)?;
34497 }
34498 self.write(")");
34499 Ok(())
34500 }
34501
34502 fn generate_object_agg(&mut self, e: &ObjectAgg) -> Result<()> {
34503 self.write_keyword("OBJECT_AGG");
34505 self.write("(");
34506 self.generate_expression(&e.this)?;
34507 self.write(", ");
34508 self.generate_expression(&e.expression)?;
34509 self.write(")");
34510 Ok(())
34511 }
34512
34513 fn generate_object_identifier(&mut self, e: &ObjectIdentifier) -> Result<()> {
34514 self.generate_expression(&e.this)?;
34516 Ok(())
34517 }
34518
34519 fn generate_object_insert(&mut self, e: &ObjectInsert) -> Result<()> {
34520 self.write_keyword("OBJECT_INSERT");
34522 self.write("(");
34523 self.generate_expression(&e.this)?;
34524 if let Some(key) = &e.key {
34525 self.write(", ");
34526 self.generate_expression(key)?;
34527 }
34528 if let Some(value) = &e.value {
34529 self.write(", ");
34530 self.generate_expression(value)?;
34531 }
34532 if let Some(update_flag) = &e.update_flag {
34533 self.write(", ");
34534 self.generate_expression(update_flag)?;
34535 }
34536 self.write(")");
34537 Ok(())
34538 }
34539
34540 fn generate_offset(&mut self, e: &Offset) -> Result<()> {
34541 self.write_keyword("OFFSET");
34543 self.write_space();
34544 self.generate_expression(&e.this)?;
34545 if e.rows == Some(true)
34547 && matches!(
34548 self.config.dialect,
34549 Some(crate::dialects::DialectType::TSQL)
34550 | Some(crate::dialects::DialectType::Oracle)
34551 )
34552 {
34553 self.write_space();
34554 self.write_keyword("ROWS");
34555 }
34556 Ok(())
34557 }
34558
34559 fn generate_qualify(&mut self, e: &Qualify) -> Result<()> {
34560 self.write_keyword("QUALIFY");
34562 self.write_space();
34563 self.generate_expression(&e.this)?;
34564 Ok(())
34565 }
34566
34567 fn generate_on_cluster(&mut self, e: &OnCluster) -> Result<()> {
34568 self.write_keyword("ON CLUSTER");
34570 self.write_space();
34571 self.generate_expression(&e.this)?;
34572 Ok(())
34573 }
34574
34575 fn generate_on_commit_property(&mut self, e: &OnCommitProperty) -> Result<()> {
34576 self.write_keyword("ON COMMIT");
34578 if e.delete.is_some() {
34579 self.write_keyword(" DELETE ROWS");
34580 } else {
34581 self.write_keyword(" PRESERVE ROWS");
34582 }
34583 Ok(())
34584 }
34585
34586 fn generate_on_condition(&mut self, e: &OnCondition) -> Result<()> {
34587 if let Some(empty) = &e.empty {
34589 self.generate_expression(empty)?;
34590 self.write_keyword(" ON EMPTY");
34591 }
34592 if let Some(error) = &e.error {
34593 if e.empty.is_some() {
34594 self.write_space();
34595 }
34596 self.generate_expression(error)?;
34597 self.write_keyword(" ON ERROR");
34598 }
34599 if let Some(null) = &e.null {
34600 if e.empty.is_some() || e.error.is_some() {
34601 self.write_space();
34602 }
34603 self.generate_expression(null)?;
34604 self.write_keyword(" ON NULL");
34605 }
34606 Ok(())
34607 }
34608
34609 fn generate_on_conflict(&mut self, e: &OnConflict) -> Result<()> {
34610 if matches!(self.config.dialect, Some(DialectType::Materialize)) {
34612 return Ok(());
34613 }
34614 if e.duplicate.is_some() {
34616 self.write_keyword("ON DUPLICATE KEY UPDATE");
34618 for (i, expr) in e.expressions.iter().enumerate() {
34619 if i > 0 {
34620 self.write(",");
34621 }
34622 self.write_space();
34623 self.generate_expression(expr)?;
34624 }
34625 return Ok(());
34626 } else {
34627 self.write_keyword("ON CONFLICT");
34628 }
34629 if let Some(constraint) = &e.constraint {
34630 self.write_keyword(" ON CONSTRAINT ");
34631 self.generate_expression(constraint)?;
34632 }
34633 if let Some(conflict_keys) = &e.conflict_keys {
34634 if let Expression::Tuple(t) = conflict_keys.as_ref() {
34636 self.write("(");
34637 for (i, expr) in t.expressions.iter().enumerate() {
34638 if i > 0 {
34639 self.write(", ");
34640 }
34641 self.generate_expression(expr)?;
34642 }
34643 self.write(")");
34644 } else {
34645 self.write("(");
34646 self.generate_expression(conflict_keys)?;
34647 self.write(")");
34648 }
34649 }
34650 if let Some(index_predicate) = &e.index_predicate {
34651 self.write_keyword(" WHERE ");
34652 self.generate_expression(index_predicate)?;
34653 }
34654 if let Some(action) = &e.action {
34655 if let Expression::Identifier(id) = action.as_ref() {
34657 if id.name.eq_ignore_ascii_case("NOTHING") {
34658 self.write_keyword(" DO NOTHING");
34659 } else {
34660 self.write_keyword(" DO ");
34661 self.generate_expression(action)?;
34662 }
34663 } else if let Expression::Tuple(t) = action.as_ref() {
34664 self.write_keyword(" DO UPDATE SET ");
34666 for (i, expr) in t.expressions.iter().enumerate() {
34667 if i > 0 {
34668 self.write(", ");
34669 }
34670 self.generate_expression(expr)?;
34671 }
34672 } else {
34673 self.write_keyword(" DO ");
34674 self.generate_expression(action)?;
34675 }
34676 }
34677 if let Some(where_) = &e.where_ {
34679 self.write_keyword(" WHERE ");
34680 self.generate_expression(where_)?;
34681 }
34682 Ok(())
34683 }
34684
34685 fn generate_on_property(&mut self, e: &OnProperty) -> Result<()> {
34686 self.write_keyword("ON");
34688 self.write_space();
34689 self.generate_expression(&e.this)?;
34690 Ok(())
34691 }
34692
34693 fn generate_opclass(&mut self, e: &Opclass) -> Result<()> {
34694 self.generate_expression(&e.this)?;
34696 self.write_space();
34697 self.generate_expression(&e.expression)?;
34698 Ok(())
34699 }
34700
34701 fn generate_open_json(&mut self, e: &OpenJSON) -> Result<()> {
34702 self.write_keyword("OPENJSON");
34704 self.write("(");
34705 self.generate_expression(&e.this)?;
34706 if let Some(path) = &e.path {
34707 self.write(", ");
34708 self.generate_expression(path)?;
34709 }
34710 self.write(")");
34711 if !e.expressions.is_empty() {
34712 self.write_keyword(" WITH");
34713 if self.config.pretty {
34714 self.write(" (\n");
34715 self.indent_level += 2;
34716 for (i, expr) in e.expressions.iter().enumerate() {
34717 if i > 0 {
34718 self.write(",\n");
34719 }
34720 self.write_indent();
34721 self.generate_expression(expr)?;
34722 }
34723 self.write("\n");
34724 self.indent_level -= 2;
34725 self.write(")");
34726 } else {
34727 self.write(" (");
34728 for (i, expr) in e.expressions.iter().enumerate() {
34729 if i > 0 {
34730 self.write(", ");
34731 }
34732 self.generate_expression(expr)?;
34733 }
34734 self.write(")");
34735 }
34736 }
34737 Ok(())
34738 }
34739
34740 fn generate_open_json_column_def(&mut self, e: &OpenJSONColumnDef) -> Result<()> {
34741 self.generate_expression(&e.this)?;
34743 self.write_space();
34744 if let Some(ref dt) = e.data_type {
34746 self.generate_data_type(dt)?;
34747 } else if !e.kind.is_empty() {
34748 self.write(&e.kind);
34749 }
34750 if let Some(path) = &e.path {
34751 self.write_space();
34752 self.generate_expression(path)?;
34753 }
34754 if e.as_json.is_some() {
34755 self.write_keyword(" AS JSON");
34756 }
34757 Ok(())
34758 }
34759
34760 fn generate_operator(&mut self, e: &Operator) -> Result<()> {
34761 self.generate_expression(&e.this)?;
34763 self.write_space();
34764 if let Some(op) = &e.operator {
34765 self.write_keyword("OPERATOR");
34766 self.write("(");
34767 self.generate_expression(op)?;
34768 self.write(")");
34769 }
34770 for comment in &e.comments {
34772 self.write_space();
34773 self.write_formatted_comment(comment);
34774 }
34775 self.write_space();
34776 self.generate_expression(&e.expression)?;
34777 Ok(())
34778 }
34779
34780 fn generate_order_by(&mut self, e: &OrderBy) -> Result<()> {
34781 self.write_keyword("ORDER BY");
34783 let pretty_clickhouse_single_paren = self.config.pretty
34784 && matches!(self.config.dialect, Some(DialectType::ClickHouse))
34785 && e.expressions.len() == 1
34786 && matches!(e.expressions[0].this, Expression::Paren(ref p) if !matches!(p.this, Expression::Tuple(_)));
34787 let clickhouse_single_tuple = matches!(self.config.dialect, Some(DialectType::ClickHouse))
34788 && e.expressions.len() == 1
34789 && matches!(e.expressions[0].this, Expression::Tuple(_))
34790 && !e.expressions[0].desc
34791 && e.expressions[0].nulls_first.is_none();
34792
34793 if pretty_clickhouse_single_paren {
34794 self.write_space();
34795 if let Expression::Paren(p) = &e.expressions[0].this {
34796 self.write("(");
34797 self.write_newline();
34798 self.indent_level += 1;
34799 self.write_indent();
34800 self.generate_expression(&p.this)?;
34801 self.indent_level -= 1;
34802 self.write_newline();
34803 self.write(")");
34804 }
34805 return Ok(());
34806 }
34807
34808 if clickhouse_single_tuple {
34809 self.write_space();
34810 if let Expression::Tuple(t) = &e.expressions[0].this {
34811 self.write("(");
34812 for (i, expr) in t.expressions.iter().enumerate() {
34813 if i > 0 {
34814 self.write(", ");
34815 }
34816 self.generate_expression(expr)?;
34817 }
34818 self.write(")");
34819 }
34820 return Ok(());
34821 }
34822
34823 self.write_space();
34824 for (i, ordered) in e.expressions.iter().enumerate() {
34825 if i > 0 {
34826 self.write(", ");
34827 }
34828 self.generate_expression(&ordered.this)?;
34829 if ordered.desc {
34830 self.write_space();
34831 self.write_keyword("DESC");
34832 } else if ordered.explicit_asc {
34833 self.write_space();
34834 self.write_keyword("ASC");
34835 }
34836 if let Some(nulls_first) = ordered.nulls_first {
34837 let skip_nulls_last =
34839 !nulls_first && matches!(self.config.dialect, Some(DialectType::Dremio));
34840 if !skip_nulls_last {
34841 self.write_space();
34842 self.write_keyword("NULLS");
34843 self.write_space();
34844 if nulls_first {
34845 self.write_keyword("FIRST");
34846 } else {
34847 self.write_keyword("LAST");
34848 }
34849 }
34850 }
34851 }
34852 Ok(())
34853 }
34854
34855 fn generate_output_model_property(&mut self, e: &OutputModelProperty) -> Result<()> {
34856 self.write_keyword("OUTPUT");
34858 self.write("(");
34859 if self.config.pretty {
34860 self.indent_level += 1;
34861 self.write_newline();
34862 self.write_indent();
34863 self.generate_expression(&e.this)?;
34864 self.indent_level -= 1;
34865 self.write_newline();
34866 } else {
34867 self.generate_expression(&e.this)?;
34868 }
34869 self.write(")");
34870 Ok(())
34871 }
34872
34873 fn generate_overflow_truncate_behavior(&mut self, e: &OverflowTruncateBehavior) -> Result<()> {
34874 self.write_keyword("TRUNCATE");
34876 if let Some(this) = &e.this {
34877 self.write_space();
34878 self.generate_expression(this)?;
34879 }
34880 if e.with_count.is_some() {
34881 self.write_keyword(" WITH COUNT");
34882 } else {
34883 self.write_keyword(" WITHOUT COUNT");
34884 }
34885 Ok(())
34886 }
34887
34888 fn generate_parameterized_agg(&mut self, e: &ParameterizedAgg) -> Result<()> {
34889 self.generate_expression(&e.this)?;
34891 self.write("(");
34892 for (i, expr) in e.expressions.iter().enumerate() {
34893 if i > 0 {
34894 self.write(", ");
34895 }
34896 self.generate_expression(expr)?;
34897 }
34898 self.write(")(");
34899 for (i, param) in e.params.iter().enumerate() {
34900 if i > 0 {
34901 self.write(", ");
34902 }
34903 self.generate_expression(param)?;
34904 }
34905 self.write(")");
34906 Ok(())
34907 }
34908
34909 fn generate_parse_datetime(&mut self, e: &ParseDatetime) -> Result<()> {
34910 self.write_keyword("PARSE_DATETIME");
34912 self.write("(");
34913 if let Some(format) = &e.format {
34914 self.write("'");
34915 self.write(format);
34916 self.write("', ");
34917 }
34918 self.generate_expression(&e.this)?;
34919 if let Some(zone) = &e.zone {
34920 self.write(", ");
34921 self.generate_expression(zone)?;
34922 }
34923 self.write(")");
34924 Ok(())
34925 }
34926
34927 fn generate_parse_ip(&mut self, e: &ParseIp) -> Result<()> {
34928 self.write_keyword("PARSE_IP");
34930 self.write("(");
34931 self.generate_expression(&e.this)?;
34932 if let Some(type_) = &e.type_ {
34933 self.write(", ");
34934 self.generate_expression(type_)?;
34935 }
34936 if let Some(permissive) = &e.permissive {
34937 self.write(", ");
34938 self.generate_expression(permissive)?;
34939 }
34940 self.write(")");
34941 Ok(())
34942 }
34943
34944 fn generate_parse_json(&mut self, e: &ParseJSON) -> Result<()> {
34945 self.write_keyword("PARSE_JSON");
34947 self.write("(");
34948 self.generate_expression(&e.this)?;
34949 if let Some(expression) = &e.expression {
34950 self.write(", ");
34951 self.generate_expression(expression)?;
34952 }
34953 self.write(")");
34954 Ok(())
34955 }
34956
34957 fn generate_parse_time(&mut self, e: &ParseTime) -> Result<()> {
34958 self.write_keyword("PARSE_TIME");
34960 self.write("(");
34961 self.write(&format!("'{}'", e.format));
34962 self.write(", ");
34963 self.generate_expression(&e.this)?;
34964 self.write(")");
34965 Ok(())
34966 }
34967
34968 fn generate_parse_url(&mut self, e: &ParseUrl) -> Result<()> {
34969 self.write_keyword("PARSE_URL");
34971 self.write("(");
34972 self.generate_expression(&e.this)?;
34973 if let Some(part) = &e.part_to_extract {
34974 self.write(", ");
34975 self.generate_expression(part)?;
34976 }
34977 if let Some(key) = &e.key {
34978 self.write(", ");
34979 self.generate_expression(key)?;
34980 }
34981 if let Some(permissive) = &e.permissive {
34982 self.write(", ");
34983 self.generate_expression(permissive)?;
34984 }
34985 self.write(")");
34986 Ok(())
34987 }
34988
34989 fn generate_partition_expr(&mut self, e: &Partition) -> Result<()> {
34990 if e.subpartition {
34992 self.write_keyword("SUBPARTITION");
34993 } else {
34994 self.write_keyword("PARTITION");
34995 }
34996 self.write("(");
34997 for (i, expr) in e.expressions.iter().enumerate() {
34998 if i > 0 {
34999 self.write(", ");
35000 }
35001 self.generate_expression(expr)?;
35002 }
35003 self.write(")");
35004 Ok(())
35005 }
35006
35007 fn generate_partition_bound_spec(&mut self, e: &PartitionBoundSpec) -> Result<()> {
35008 if let Some(this) = &e.this {
35010 if let Some(expression) = &e.expression {
35011 self.write_keyword("WITH");
35013 self.write(" (");
35014 self.write_keyword("MODULUS");
35015 self.write_space();
35016 self.generate_expression(this)?;
35017 self.write(", ");
35018 self.write_keyword("REMAINDER");
35019 self.write_space();
35020 self.generate_expression(expression)?;
35021 self.write(")");
35022 } else {
35023 self.write_keyword("IN");
35025 self.write(" (");
35026 self.generate_partition_bound_values(this)?;
35027 self.write(")");
35028 }
35029 } else if let (Some(from), Some(to)) = (&e.from_expressions, &e.to_expressions) {
35030 self.write_keyword("FROM");
35032 self.write(" (");
35033 self.generate_partition_bound_values(from)?;
35034 self.write(") ");
35035 self.write_keyword("TO");
35036 self.write(" (");
35037 self.generate_partition_bound_values(to)?;
35038 self.write(")");
35039 }
35040 Ok(())
35041 }
35042
35043 fn generate_partition_bound_values(&mut self, expr: &Expression) -> Result<()> {
35046 if let Expression::Tuple(t) = expr {
35047 for (i, e) in t.expressions.iter().enumerate() {
35048 if i > 0 {
35049 self.write(", ");
35050 }
35051 self.generate_expression(e)?;
35052 }
35053 Ok(())
35054 } else {
35055 self.generate_expression(expr)
35056 }
35057 }
35058
35059 fn generate_partition_by_list_property(&mut self, e: &PartitionByListProperty) -> Result<()> {
35060 self.write_keyword("PARTITION BY LIST");
35062 if let Some(partition_exprs) = &e.partition_expressions {
35063 self.write(" (");
35064 self.generate_doris_partition_expressions(partition_exprs)?;
35066 self.write(")");
35067 }
35068 if let Some(create_exprs) = &e.create_expressions {
35069 self.write(" (");
35070 self.generate_doris_partition_definitions(create_exprs)?;
35072 self.write(")");
35073 }
35074 Ok(())
35075 }
35076
35077 fn generate_partition_by_range_property(&mut self, e: &PartitionByRangeProperty) -> Result<()> {
35078 self.write_keyword("PARTITION BY RANGE");
35080 if let Some(partition_exprs) = &e.partition_expressions {
35081 self.write(" (");
35082 self.generate_doris_partition_expressions(partition_exprs)?;
35084 self.write(")");
35085 }
35086 if let Some(create_exprs) = &e.create_expressions {
35087 self.write(" (");
35088 self.generate_doris_partition_definitions(create_exprs)?;
35090 self.write(")");
35091 }
35092 Ok(())
35093 }
35094
35095 fn generate_doris_partition_expressions(&mut self, expr: &Expression) -> Result<()> {
35097 if let Expression::Tuple(t) = expr {
35098 for (i, e) in t.expressions.iter().enumerate() {
35099 if i > 0 {
35100 self.write(", ");
35101 }
35102 self.generate_expression(e)?;
35103 }
35104 } else {
35105 self.generate_expression(expr)?;
35106 }
35107 Ok(())
35108 }
35109
35110 fn generate_doris_partition_definitions(&mut self, expr: &Expression) -> Result<()> {
35112 match expr {
35113 Expression::Tuple(t) => {
35114 for (i, part) in t.expressions.iter().enumerate() {
35116 if i > 0 {
35117 self.write(", ");
35118 }
35119 if let Expression::Partition(p) = part {
35121 for (j, inner) in p.expressions.iter().enumerate() {
35122 if j > 0 {
35123 self.write(", ");
35124 }
35125 self.generate_expression(inner)?;
35126 }
35127 } else {
35128 self.generate_expression(part)?;
35129 }
35130 }
35131 }
35132 Expression::PartitionByRangePropertyDynamic(_) => {
35133 self.generate_expression(expr)?;
35135 }
35136 _ => {
35137 self.generate_expression(expr)?;
35138 }
35139 }
35140 Ok(())
35141 }
35142
35143 fn generate_partition_by_range_property_dynamic(
35144 &mut self,
35145 e: &PartitionByRangePropertyDynamic,
35146 ) -> Result<()> {
35147 if e.use_start_end {
35148 if let Some(start) = &e.start {
35150 self.write_keyword("START");
35151 self.write(" (");
35152 self.generate_expression(start)?;
35153 self.write(")");
35154 }
35155 if let Some(end) = &e.end {
35156 self.write_space();
35157 self.write_keyword("END");
35158 self.write(" (");
35159 self.generate_expression(end)?;
35160 self.write(")");
35161 }
35162 if let Some(every) = &e.every {
35163 self.write_space();
35164 self.write_keyword("EVERY");
35165 self.write(" (");
35166 self.generate_doris_interval(every)?;
35168 self.write(")");
35169 }
35170 } else {
35171 if let Some(start) = &e.start {
35173 self.write_keyword("FROM");
35174 self.write(" (");
35175 self.generate_expression(start)?;
35176 self.write(")");
35177 }
35178 if let Some(end) = &e.end {
35179 self.write_space();
35180 self.write_keyword("TO");
35181 self.write(" (");
35182 self.generate_expression(end)?;
35183 self.write(")");
35184 }
35185 if let Some(every) = &e.every {
35186 self.write_space();
35187 self.generate_doris_interval(every)?;
35189 }
35190 }
35191 Ok(())
35192 }
35193
35194 fn generate_doris_interval(&mut self, expr: &Expression) -> Result<()> {
35196 if let Expression::Interval(interval) = expr {
35197 self.write_keyword("INTERVAL");
35198 if let Some(ref value) = interval.this {
35199 self.write_space();
35200 match value {
35204 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(s) if s.chars().all(|c| c.is_ascii_digit() || c == '.' || c == '-') && !s.is_empty()) => {
35205 if let Literal::String(s) = lit.as_ref() {
35206 self.write(s);
35207 }
35208 }
35209 _ => {
35210 self.generate_expression(value)?;
35211 }
35212 }
35213 }
35214 if let Some(ref unit_spec) = interval.unit {
35215 self.write_space();
35216 self.write_interval_unit_spec(unit_spec)?;
35217 }
35218 Ok(())
35219 } else {
35220 self.generate_expression(expr)
35221 }
35222 }
35223
35224 fn generate_partition_by_truncate(&mut self, e: &PartitionByTruncate) -> Result<()> {
35225 self.write_keyword("TRUNCATE");
35227 self.write("(");
35228 self.generate_expression(&e.expression)?;
35229 self.write(", ");
35230 self.generate_expression(&e.this)?;
35231 self.write(")");
35232 Ok(())
35233 }
35234
35235 fn generate_partition_list(&mut self, e: &PartitionList) -> Result<()> {
35236 self.write_keyword("PARTITION");
35238 self.write_space();
35239 self.generate_expression(&e.this)?;
35240 self.write_space();
35241 self.write_keyword("VALUES IN");
35242 self.write(" (");
35243 for (i, expr) in e.expressions.iter().enumerate() {
35244 if i > 0 {
35245 self.write(", ");
35246 }
35247 self.generate_expression(expr)?;
35248 }
35249 self.write(")");
35250 Ok(())
35251 }
35252
35253 fn generate_partition_range(&mut self, e: &PartitionRange) -> Result<()> {
35254 if e.expressions.is_empty() && e.expression.is_some() {
35257 self.generate_expression(&e.this)?;
35259 self.write_space();
35260 self.write_keyword("TO");
35261 self.write_space();
35262 self.generate_expression(e.expression.as_ref().unwrap())?;
35263 return Ok(());
35264 }
35265
35266 self.write_keyword("PARTITION");
35268 self.write_space();
35269 self.generate_expression(&e.this)?;
35270 self.write_space();
35271
35272 if e.expressions.len() == 1 {
35274 self.write_keyword("VALUES LESS THAN");
35276 self.write(" (");
35277 self.generate_expression(&e.expressions[0])?;
35278 self.write(")");
35279 } else if !e.expressions.is_empty() {
35280 self.write_keyword("VALUES");
35282 self.write(" [");
35283 for (i, expr) in e.expressions.iter().enumerate() {
35284 if i > 0 {
35285 self.write(", ");
35286 }
35287 if let Expression::Tuple(t) = expr {
35289 self.write("(");
35290 for (j, inner) in t.expressions.iter().enumerate() {
35291 if j > 0 {
35292 self.write(", ");
35293 }
35294 self.generate_expression(inner)?;
35295 }
35296 self.write(")");
35297 } else {
35298 self.write("(");
35299 self.generate_expression(expr)?;
35300 self.write(")");
35301 }
35302 }
35303 self.write(")");
35304 }
35305 Ok(())
35306 }
35307
35308 fn generate_partitioned_by_bucket(&mut self, e: &PartitionedByBucket) -> Result<()> {
35309 self.write_keyword("BUCKET");
35311 self.write("(");
35312 self.generate_expression(&e.this)?;
35313 self.write(", ");
35314 self.generate_expression(&e.expression)?;
35315 self.write(")");
35316 Ok(())
35317 }
35318
35319 fn generate_partition_by_property(&mut self, e: &PartitionByProperty) -> Result<()> {
35320 self.write_keyword("PARTITION BY");
35322 self.write_space();
35323 for (i, expr) in e.expressions.iter().enumerate() {
35324 if i > 0 {
35325 self.write(", ");
35326 }
35327 self.generate_expression(expr)?;
35328 }
35329 Ok(())
35330 }
35331
35332 fn generate_partitioned_by_property(&mut self, e: &PartitionedByProperty) -> Result<()> {
35333 if matches!(
35335 self.config.dialect,
35336 Some(crate::dialects::DialectType::Teradata)
35337 | Some(crate::dialects::DialectType::ClickHouse)
35338 ) {
35339 self.write_keyword("PARTITION BY");
35340 } else {
35341 self.write_keyword("PARTITIONED BY");
35342 }
35343 self.write_space();
35344 if self.config.pretty {
35346 if let Expression::Tuple(ref tuple) = *e.this {
35347 self.write("(");
35348 self.write_newline();
35349 self.indent_level += 1;
35350 for (i, expr) in tuple.expressions.iter().enumerate() {
35351 if i > 0 {
35352 self.write(",");
35353 self.write_newline();
35354 }
35355 self.write_indent();
35356 self.generate_expression(expr)?;
35357 }
35358 self.indent_level -= 1;
35359 self.write_newline();
35360 self.write(")");
35361 } else {
35362 self.generate_expression(&e.this)?;
35363 }
35364 } else {
35365 self.generate_expression(&e.this)?;
35366 }
35367 Ok(())
35368 }
35369
35370 fn generate_partitioned_of_property(&mut self, e: &PartitionedOfProperty) -> Result<()> {
35371 self.write_keyword("PARTITION OF");
35373 self.write_space();
35374 self.generate_expression(&e.this)?;
35375 if let Expression::PartitionBoundSpec(_) = e.expression.as_ref() {
35377 self.write_space();
35378 self.write_keyword("FOR VALUES");
35379 self.write_space();
35380 self.generate_expression(&e.expression)?;
35381 } else {
35382 self.write_space();
35383 self.write_keyword("DEFAULT");
35384 }
35385 Ok(())
35386 }
35387
35388 fn generate_period_for_system_time_constraint(
35389 &mut self,
35390 e: &PeriodForSystemTimeConstraint,
35391 ) -> Result<()> {
35392 self.write_keyword("PERIOD FOR SYSTEM_TIME");
35394 self.write(" (");
35395 self.generate_expression(&e.this)?;
35396 self.write(", ");
35397 self.generate_expression(&e.expression)?;
35398 self.write(")");
35399 Ok(())
35400 }
35401
35402 fn generate_pivot_alias(&mut self, e: &PivotAlias) -> Result<()> {
35403 self.generate_expression(&e.this)?;
35406 self.write_space();
35407 self.write_keyword("AS");
35408 self.write_space();
35409 if self.config.unpivot_aliases_are_identifiers {
35411 match &e.alias {
35412 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
35413 let Literal::String(s) = lit.as_ref() else {
35414 unreachable!()
35415 };
35416 self.generate_identifier(&Identifier::new(s.clone()))?;
35418 }
35419 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
35420 let Literal::Number(n) = lit.as_ref() else {
35421 unreachable!()
35422 };
35423 let mut id = Identifier::new(n.clone());
35425 id.quoted = true;
35426 self.generate_identifier(&id)?;
35427 }
35428 other => {
35429 self.generate_expression(other)?;
35430 }
35431 }
35432 } else {
35433 self.generate_expression(&e.alias)?;
35434 }
35435 Ok(())
35436 }
35437
35438 fn generate_pivot_any(&mut self, e: &PivotAny) -> Result<()> {
35439 self.write_keyword("ANY");
35441 if let Some(this) = &e.this {
35442 self.write_space();
35443 self.generate_expression(this)?;
35444 }
35445 Ok(())
35446 }
35447
35448 fn generate_predict(&mut self, e: &Predict) -> Result<()> {
35449 self.write_keyword("ML.PREDICT");
35451 self.write("(");
35452 self.write_keyword("MODEL");
35453 self.write_space();
35454 self.generate_expression(&e.this)?;
35455 self.write(", ");
35456 self.generate_expression(&e.expression)?;
35457 if let Some(params) = &e.params_struct {
35458 self.write(", ");
35459 self.generate_expression(params)?;
35460 }
35461 self.write(")");
35462 Ok(())
35463 }
35464
35465 fn generate_previous_day(&mut self, e: &PreviousDay) -> Result<()> {
35466 self.write_keyword("PREVIOUS_DAY");
35468 self.write("(");
35469 self.generate_expression(&e.this)?;
35470 self.write(", ");
35471 self.generate_expression(&e.expression)?;
35472 self.write(")");
35473 Ok(())
35474 }
35475
35476 fn generate_primary_key(&mut self, e: &PrimaryKey) -> Result<()> {
35477 self.write_keyword("PRIMARY KEY");
35479 if let Some(name) = &e.this {
35480 self.write_space();
35481 self.generate_expression(name)?;
35482 }
35483 if !e.expressions.is_empty() {
35484 self.write(" (");
35485 for (i, expr) in e.expressions.iter().enumerate() {
35486 if i > 0 {
35487 self.write(", ");
35488 }
35489 self.generate_expression(expr)?;
35490 }
35491 self.write(")");
35492 }
35493 if let Some(include) = &e.include {
35494 self.write_space();
35495 self.generate_expression(include)?;
35496 }
35497 if !e.options.is_empty() {
35498 self.write_space();
35499 for (i, opt) in e.options.iter().enumerate() {
35500 if i > 0 {
35501 self.write_space();
35502 }
35503 self.generate_expression(opt)?;
35504 }
35505 }
35506 Ok(())
35507 }
35508
35509 fn generate_primary_key_column_constraint(
35510 &mut self,
35511 _e: &PrimaryKeyColumnConstraint,
35512 ) -> Result<()> {
35513 self.write_keyword("PRIMARY KEY");
35515 Ok(())
35516 }
35517
35518 fn generate_path_column_constraint(&mut self, e: &PathColumnConstraint) -> Result<()> {
35519 self.write_keyword("PATH");
35521 self.write_space();
35522 self.generate_expression(&e.this)?;
35523 Ok(())
35524 }
35525
35526 fn generate_projection_def(&mut self, e: &ProjectionDef) -> Result<()> {
35527 self.write_keyword("PROJECTION");
35529 self.write_space();
35530 self.generate_expression(&e.this)?;
35531 self.write(" (");
35532 self.generate_expression(&e.expression)?;
35533 self.write(")");
35534 Ok(())
35535 }
35536
35537 fn generate_properties(&mut self, e: &Properties) -> Result<()> {
35538 for (i, prop) in e.expressions.iter().enumerate() {
35540 if i > 0 {
35541 self.write(", ");
35542 }
35543 self.generate_expression(prop)?;
35544 }
35545 Ok(())
35546 }
35547
35548 fn generate_property(&mut self, e: &Property) -> Result<()> {
35549 self.generate_expression(&e.this)?;
35551 if let Some(value) = &e.value {
35552 self.write("=");
35553 self.generate_expression(value)?;
35554 }
35555 Ok(())
35556 }
35557
35558 fn generate_options_property(&mut self, e: &OptionsProperty) -> Result<()> {
35559 self.write_keyword("OPTIONS");
35560 if e.entries.is_empty() {
35561 self.write(" ()");
35562 return Ok(());
35563 }
35564
35565 if self.config.pretty {
35566 self.write(" (");
35567 self.write_newline();
35568 self.indent_level += 1;
35569 for (i, entry) in e.entries.iter().enumerate() {
35570 if i > 0 {
35571 self.write(",");
35572 self.write_newline();
35573 }
35574 self.write_indent();
35575 self.generate_identifier(&entry.key)?;
35576 self.write("=");
35577 self.generate_expression(&entry.value)?;
35578 }
35579 self.indent_level -= 1;
35580 self.write_newline();
35581 self.write(")");
35582 } else {
35583 self.write(" (");
35584 for (i, entry) in e.entries.iter().enumerate() {
35585 if i > 0 {
35586 self.write(", ");
35587 }
35588 self.generate_identifier(&entry.key)?;
35589 self.write("=");
35590 self.generate_expression(&entry.value)?;
35591 }
35592 self.write(")");
35593 }
35594 Ok(())
35595 }
35596
35597 fn generate_options_clause(&mut self, options: &[Expression]) -> Result<()> {
35599 self.write_keyword("OPTIONS");
35600 self.write(" (");
35601 for (i, opt) in options.iter().enumerate() {
35602 if i > 0 {
35603 self.write(", ");
35604 }
35605 self.generate_option_expression(opt)?;
35606 }
35607 self.write(")");
35608 Ok(())
35609 }
35610
35611 fn generate_properties_clause(&mut self, properties: &[Expression]) -> Result<()> {
35613 self.write_keyword("PROPERTIES");
35614 self.write(" (");
35615 for (i, prop) in properties.iter().enumerate() {
35616 if i > 0 {
35617 self.write(", ");
35618 }
35619 self.generate_option_expression(prop)?;
35620 }
35621 self.write(")");
35622 Ok(())
35623 }
35624
35625 fn generate_environment_clause(&mut self, environment: &[Expression]) -> Result<()> {
35627 self.write_keyword("ENVIRONMENT");
35628 self.write(" (");
35629 for (i, env_item) in environment.iter().enumerate() {
35630 if i > 0 {
35631 self.write(", ");
35632 }
35633 self.generate_environment_expression(env_item)?;
35634 }
35635 self.write(")");
35636 Ok(())
35637 }
35638
35639 fn generate_environment_expression(&mut self, expr: &Expression) -> Result<()> {
35641 match expr {
35642 Expression::Eq(eq) => {
35643 self.generate_expression(&eq.left)?;
35645 self.write(" = ");
35646 self.generate_expression(&eq.right)?;
35647 Ok(())
35648 }
35649 _ => self.generate_expression(expr),
35650 }
35651 }
35652
35653 fn generate_tblproperties_clause(&mut self, options: &[Expression]) -> Result<()> {
35655 self.write_keyword("TBLPROPERTIES");
35656 if self.config.pretty {
35657 self.write(" (");
35658 self.write_newline();
35659 self.indent_level += 1;
35660 for (i, opt) in options.iter().enumerate() {
35661 if i > 0 {
35662 self.write(",");
35663 self.write_newline();
35664 }
35665 self.write_indent();
35666 self.generate_option_expression(opt)?;
35667 }
35668 self.indent_level -= 1;
35669 self.write_newline();
35670 self.write(")");
35671 } else {
35672 self.write(" (");
35673 for (i, opt) in options.iter().enumerate() {
35674 if i > 0 {
35675 self.write(", ");
35676 }
35677 self.generate_option_expression(opt)?;
35678 }
35679 self.write(")");
35680 }
35681 Ok(())
35682 }
35683
35684 fn generate_option_expression(&mut self, expr: &Expression) -> Result<()> {
35686 match expr {
35687 Expression::Eq(eq) => {
35688 self.generate_expression(&eq.left)?;
35690 self.write("=");
35691 self.generate_expression(&eq.right)?;
35692 Ok(())
35693 }
35694 _ => self.generate_expression(expr),
35695 }
35696 }
35697
35698 fn generate_pseudo_type(&mut self, e: &PseudoType) -> Result<()> {
35699 self.generate_expression(&e.this)?;
35701 Ok(())
35702 }
35703
35704 fn generate_put(&mut self, e: &PutStmt) -> Result<()> {
35705 self.write_keyword("PUT");
35707 self.write_space();
35708
35709 if e.source_quoted {
35711 self.write("'");
35712 self.write(&e.source);
35713 self.write("'");
35714 } else {
35715 self.write(&e.source);
35716 }
35717
35718 self.write_space();
35719
35720 if let Expression::Literal(lit) = &e.target {
35722 if let Literal::String(s) = lit.as_ref() {
35723 self.write(s);
35724 }
35725 } else {
35726 self.generate_expression(&e.target)?;
35727 }
35728
35729 for param in &e.params {
35731 self.write_space();
35732 self.write(¶m.name);
35733 if let Some(ref value) = param.value {
35734 self.write("=");
35735 self.generate_expression(value)?;
35736 }
35737 }
35738
35739 Ok(())
35740 }
35741
35742 fn generate_quantile(&mut self, e: &Quantile) -> Result<()> {
35743 self.write_keyword("QUANTILE");
35745 self.write("(");
35746 self.generate_expression(&e.this)?;
35747 if let Some(quantile) = &e.quantile {
35748 self.write(", ");
35749 self.generate_expression(quantile)?;
35750 }
35751 self.write(")");
35752 Ok(())
35753 }
35754
35755 fn generate_query_band(&mut self, e: &QueryBand) -> Result<()> {
35756 if matches!(
35758 self.config.dialect,
35759 Some(crate::dialects::DialectType::Teradata)
35760 ) {
35761 self.write_keyword("SET");
35762 self.write_space();
35763 }
35764 self.write_keyword("QUERY_BAND");
35765 self.write(" = ");
35766 self.generate_expression(&e.this)?;
35767 if e.update.is_some() {
35768 self.write_space();
35769 self.write_keyword("UPDATE");
35770 }
35771 if let Some(scope) = &e.scope {
35772 self.write_space();
35773 self.write_keyword("FOR");
35774 self.write_space();
35775 self.generate_expression(scope)?;
35776 }
35777 Ok(())
35778 }
35779
35780 fn generate_query_option(&mut self, e: &QueryOption) -> Result<()> {
35781 self.generate_expression(&e.this)?;
35783 if let Some(expression) = &e.expression {
35784 self.write(" = ");
35785 self.generate_expression(expression)?;
35786 }
35787 Ok(())
35788 }
35789
35790 fn generate_query_transform(&mut self, e: &QueryTransform) -> Result<()> {
35791 self.write_keyword("TRANSFORM");
35793 self.write("(");
35794 for (i, expr) in e.expressions.iter().enumerate() {
35795 if i > 0 {
35796 self.write(", ");
35797 }
35798 self.generate_expression(expr)?;
35799 }
35800 self.write(")");
35801 if let Some(row_format_before) = &e.row_format_before {
35802 self.write_space();
35803 self.generate_expression(row_format_before)?;
35804 }
35805 if let Some(record_writer) = &e.record_writer {
35806 self.write_space();
35807 self.write_keyword("RECORDWRITER");
35808 self.write_space();
35809 self.generate_expression(record_writer)?;
35810 }
35811 if let Some(command_script) = &e.command_script {
35812 self.write_space();
35813 self.write_keyword("USING");
35814 self.write_space();
35815 self.generate_expression(command_script)?;
35816 }
35817 if let Some(schema) = &e.schema {
35818 self.write_space();
35819 self.write_keyword("AS");
35820 self.write_space();
35821 self.generate_expression(schema)?;
35822 }
35823 if let Some(row_format_after) = &e.row_format_after {
35824 self.write_space();
35825 self.generate_expression(row_format_after)?;
35826 }
35827 if let Some(record_reader) = &e.record_reader {
35828 self.write_space();
35829 self.write_keyword("RECORDREADER");
35830 self.write_space();
35831 self.generate_expression(record_reader)?;
35832 }
35833 Ok(())
35834 }
35835
35836 fn generate_randn(&mut self, e: &Randn) -> Result<()> {
35837 self.write_keyword("RANDN");
35839 self.write("(");
35840 if let Some(this) = &e.this {
35841 self.generate_expression(this)?;
35842 }
35843 self.write(")");
35844 Ok(())
35845 }
35846
35847 fn generate_randstr(&mut self, e: &Randstr) -> Result<()> {
35848 self.write_keyword("RANDSTR");
35850 self.write("(");
35851 self.generate_expression(&e.this)?;
35852 if let Some(generator) = &e.generator {
35853 self.write(", ");
35854 self.generate_expression(generator)?;
35855 }
35856 self.write(")");
35857 Ok(())
35858 }
35859
35860 fn generate_range_bucket(&mut self, e: &RangeBucket) -> Result<()> {
35861 self.write_keyword("RANGE_BUCKET");
35863 self.write("(");
35864 self.generate_expression(&e.this)?;
35865 self.write(", ");
35866 self.generate_expression(&e.expression)?;
35867 self.write(")");
35868 Ok(())
35869 }
35870
35871 fn generate_range_n(&mut self, e: &RangeN) -> Result<()> {
35872 self.write_keyword("RANGE_N");
35874 self.write("(");
35875 self.generate_expression(&e.this)?;
35876 self.write_space();
35877 self.write_keyword("BETWEEN");
35878 self.write_space();
35879 for (i, expr) in e.expressions.iter().enumerate() {
35880 if i > 0 {
35881 self.write(", ");
35882 }
35883 self.generate_expression(expr)?;
35884 }
35885 if let Some(each) = &e.each {
35886 self.write_space();
35887 self.write_keyword("EACH");
35888 self.write_space();
35889 self.generate_expression(each)?;
35890 }
35891 self.write(")");
35892 Ok(())
35893 }
35894
35895 fn generate_read_csv(&mut self, e: &ReadCSV) -> Result<()> {
35896 self.write_keyword("READ_CSV");
35898 self.write("(");
35899 self.generate_expression(&e.this)?;
35900 for expr in &e.expressions {
35901 self.write(", ");
35902 self.generate_expression(expr)?;
35903 }
35904 self.write(")");
35905 Ok(())
35906 }
35907
35908 fn generate_read_parquet(&mut self, e: &ReadParquet) -> Result<()> {
35909 self.write_keyword("READ_PARQUET");
35911 self.write("(");
35912 for (i, expr) in e.expressions.iter().enumerate() {
35913 if i > 0 {
35914 self.write(", ");
35915 }
35916 self.generate_expression(expr)?;
35917 }
35918 self.write(")");
35919 Ok(())
35920 }
35921
35922 fn generate_recursive_with_search(&mut self, e: &RecursiveWithSearch) -> Result<()> {
35923 if e.kind == "CYCLE" {
35926 self.write_keyword("CYCLE");
35927 } else {
35928 self.write_keyword("SEARCH");
35929 self.write_space();
35930 self.write(&e.kind);
35931 self.write_space();
35932 self.write_keyword("FIRST BY");
35933 }
35934 self.write_space();
35935 self.generate_expression(&e.this)?;
35936 self.write_space();
35937 self.write_keyword("SET");
35938 self.write_space();
35939 self.generate_expression(&e.expression)?;
35940 if let Some(using) = &e.using {
35941 self.write_space();
35942 self.write_keyword("USING");
35943 self.write_space();
35944 self.generate_expression(using)?;
35945 }
35946 Ok(())
35947 }
35948
35949 fn generate_reduce(&mut self, e: &Reduce) -> Result<()> {
35950 self.write_keyword("REDUCE");
35952 self.write("(");
35953 self.generate_expression(&e.this)?;
35954 if let Some(initial) = &e.initial {
35955 self.write(", ");
35956 self.generate_expression(initial)?;
35957 }
35958 if let Some(merge) = &e.merge {
35959 self.write(", ");
35960 self.generate_expression(merge)?;
35961 }
35962 if let Some(finish) = &e.finish {
35963 self.write(", ");
35964 self.generate_expression(finish)?;
35965 }
35966 self.write(")");
35967 Ok(())
35968 }
35969
35970 fn generate_reference(&mut self, e: &Reference) -> Result<()> {
35971 self.write_keyword("REFERENCES");
35973 self.write_space();
35974 self.generate_expression(&e.this)?;
35975 if !e.expressions.is_empty() {
35976 self.write(" (");
35977 for (i, expr) in e.expressions.iter().enumerate() {
35978 if i > 0 {
35979 self.write(", ");
35980 }
35981 self.generate_expression(expr)?;
35982 }
35983 self.write(")");
35984 }
35985 for opt in &e.options {
35986 self.write_space();
35987 self.generate_expression(opt)?;
35988 }
35989 Ok(())
35990 }
35991
35992 fn generate_refresh(&mut self, e: &Refresh) -> Result<()> {
35993 self.write_keyword("REFRESH");
35995 if !e.kind.is_empty() {
35996 self.write_space();
35997 self.write_keyword(&e.kind);
35998 }
35999 self.write_space();
36000 self.generate_expression(&e.this)?;
36001 Ok(())
36002 }
36003
36004 fn generate_refresh_trigger_property(&mut self, e: &RefreshTriggerProperty) -> Result<()> {
36005 self.write_keyword("REFRESH");
36007 self.write_space();
36008 self.write_keyword(&e.method);
36009
36010 if let Some(ref kind) = e.kind {
36011 self.write_space();
36012 self.write_keyword("ON");
36013 self.write_space();
36014 self.write_keyword(kind);
36015
36016 if let Some(ref every) = e.every {
36018 self.write_space();
36019 self.write_keyword("EVERY");
36020 self.write_space();
36021 self.generate_expression(every)?;
36022 if let Some(ref unit) = e.unit {
36023 self.write_space();
36024 self.write_keyword(unit);
36025 }
36026 }
36027
36028 if let Some(ref starts) = e.starts {
36030 self.write_space();
36031 self.write_keyword("STARTS");
36032 self.write_space();
36033 self.generate_expression(starts)?;
36034 }
36035 }
36036 Ok(())
36037 }
36038
36039 fn generate_regexp_count(&mut self, e: &RegexpCount) -> Result<()> {
36040 self.write_keyword("REGEXP_COUNT");
36042 self.write("(");
36043 self.generate_expression(&e.this)?;
36044 self.write(", ");
36045 self.generate_expression(&e.expression)?;
36046 if let Some(position) = &e.position {
36047 self.write(", ");
36048 self.generate_expression(position)?;
36049 }
36050 if let Some(parameters) = &e.parameters {
36051 self.write(", ");
36052 self.generate_expression(parameters)?;
36053 }
36054 self.write(")");
36055 Ok(())
36056 }
36057
36058 fn generate_regexp_extract_all(&mut self, e: &RegexpExtractAll) -> Result<()> {
36059 self.write_keyword("REGEXP_EXTRACT_ALL");
36061 self.write("(");
36062 self.generate_expression(&e.this)?;
36063 self.write(", ");
36064 self.generate_expression(&e.expression)?;
36065 if let Some(group) = &e.group {
36066 self.write(", ");
36067 self.generate_expression(group)?;
36068 }
36069 self.write(")");
36070 Ok(())
36071 }
36072
36073 fn generate_regexp_full_match(&mut self, e: &RegexpFullMatch) -> Result<()> {
36074 self.write_keyword("REGEXP_FULL_MATCH");
36076 self.write("(");
36077 self.generate_expression(&e.this)?;
36078 self.write(", ");
36079 self.generate_expression(&e.expression)?;
36080 self.write(")");
36081 Ok(())
36082 }
36083
36084 fn generate_regexp_i_like(&mut self, e: &RegexpILike) -> Result<()> {
36085 use crate::dialects::DialectType;
36086 if matches!(
36088 self.config.dialect,
36089 Some(DialectType::PostgreSQL) | Some(DialectType::Redshift)
36090 ) && e.flag.is_none()
36091 {
36092 self.generate_expression(&e.this)?;
36093 self.write(" ~* ");
36094 self.generate_expression(&e.expression)?;
36095 } else if matches!(self.config.dialect, Some(DialectType::ClickHouse)) && e.flag.is_none() {
36096 self.write("match(");
36100 self.generate_expression(&e.this)?;
36101 self.write(", ");
36102 if let Expression::Literal(lit) = e.expression.as_ref() {
36103 if let Literal::String(s) = lit.as_ref() {
36104 let insensitive =
36105 Expression::Literal(Box::new(Literal::String(format!("(?i){s}"))));
36106 self.generate_expression(&insensitive)?;
36107 self.write(")");
36108 return Ok(());
36109 }
36110 }
36111 self.write("concat('(?i)', ");
36112 self.generate_expression(&e.expression)?;
36113 self.write("))");
36114 return Ok(());
36115 } else if matches!(self.config.dialect, Some(DialectType::Snowflake)) {
36116 self.write_keyword("REGEXP_LIKE");
36118 self.write("(");
36119 self.generate_expression(&e.this)?;
36120 self.write(", ");
36121 self.generate_expression(&e.expression)?;
36122 self.write(", ");
36123 if let Some(flag) = &e.flag {
36124 self.generate_expression(flag)?;
36125 } else {
36126 self.write("'i'");
36127 }
36128 self.write(")");
36129 } else {
36130 self.generate_expression(&e.this)?;
36132 self.write_space();
36133 self.write_keyword("REGEXP_ILIKE");
36134 self.write_space();
36135 self.generate_expression(&e.expression)?;
36136 if let Some(flag) = &e.flag {
36137 self.write(", ");
36138 self.generate_expression(flag)?;
36139 }
36140 }
36141 Ok(())
36142 }
36143
36144 fn generate_regexp_instr(&mut self, e: &RegexpInstr) -> Result<()> {
36145 self.write_keyword("REGEXP_INSTR");
36147 self.write("(");
36148 self.generate_expression(&e.this)?;
36149 self.write(", ");
36150 self.generate_expression(&e.expression)?;
36151 if let Some(position) = &e.position {
36152 self.write(", ");
36153 self.generate_expression(position)?;
36154 }
36155 if let Some(occurrence) = &e.occurrence {
36156 self.write(", ");
36157 self.generate_expression(occurrence)?;
36158 }
36159 if let Some(option) = &e.option {
36160 self.write(", ");
36161 self.generate_expression(option)?;
36162 }
36163 if let Some(parameters) = &e.parameters {
36164 self.write(", ");
36165 self.generate_expression(parameters)?;
36166 }
36167 if let Some(group) = &e.group {
36168 self.write(", ");
36169 self.generate_expression(group)?;
36170 }
36171 self.write(")");
36172 Ok(())
36173 }
36174
36175 fn generate_regexp_split(&mut self, e: &RegexpSplit) -> Result<()> {
36176 self.write_keyword("REGEXP_SPLIT");
36178 self.write("(");
36179 self.generate_expression(&e.this)?;
36180 self.write(", ");
36181 self.generate_expression(&e.expression)?;
36182 if let Some(limit) = &e.limit {
36183 self.write(", ");
36184 self.generate_expression(limit)?;
36185 }
36186 self.write(")");
36187 Ok(())
36188 }
36189
36190 fn generate_regr_avgx(&mut self, e: &RegrAvgx) -> Result<()> {
36191 self.write_keyword("REGR_AVGX");
36193 self.write("(");
36194 self.generate_expression(&e.this)?;
36195 self.write(", ");
36196 self.generate_expression(&e.expression)?;
36197 self.write(")");
36198 Ok(())
36199 }
36200
36201 fn generate_regr_avgy(&mut self, e: &RegrAvgy) -> Result<()> {
36202 self.write_keyword("REGR_AVGY");
36204 self.write("(");
36205 self.generate_expression(&e.this)?;
36206 self.write(", ");
36207 self.generate_expression(&e.expression)?;
36208 self.write(")");
36209 Ok(())
36210 }
36211
36212 fn generate_regr_count(&mut self, e: &RegrCount) -> Result<()> {
36213 self.write_keyword("REGR_COUNT");
36215 self.write("(");
36216 self.generate_expression(&e.this)?;
36217 self.write(", ");
36218 self.generate_expression(&e.expression)?;
36219 self.write(")");
36220 Ok(())
36221 }
36222
36223 fn generate_regr_intercept(&mut self, e: &RegrIntercept) -> Result<()> {
36224 self.write_keyword("REGR_INTERCEPT");
36226 self.write("(");
36227 self.generate_expression(&e.this)?;
36228 self.write(", ");
36229 self.generate_expression(&e.expression)?;
36230 self.write(")");
36231 Ok(())
36232 }
36233
36234 fn generate_regr_r2(&mut self, e: &RegrR2) -> Result<()> {
36235 self.write_keyword("REGR_R2");
36237 self.write("(");
36238 self.generate_expression(&e.this)?;
36239 self.write(", ");
36240 self.generate_expression(&e.expression)?;
36241 self.write(")");
36242 Ok(())
36243 }
36244
36245 fn generate_regr_slope(&mut self, e: &RegrSlope) -> Result<()> {
36246 self.write_keyword("REGR_SLOPE");
36248 self.write("(");
36249 self.generate_expression(&e.this)?;
36250 self.write(", ");
36251 self.generate_expression(&e.expression)?;
36252 self.write(")");
36253 Ok(())
36254 }
36255
36256 fn generate_regr_sxx(&mut self, e: &RegrSxx) -> Result<()> {
36257 self.write_keyword("REGR_SXX");
36259 self.write("(");
36260 self.generate_expression(&e.this)?;
36261 self.write(", ");
36262 self.generate_expression(&e.expression)?;
36263 self.write(")");
36264 Ok(())
36265 }
36266
36267 fn generate_regr_sxy(&mut self, e: &RegrSxy) -> Result<()> {
36268 self.write_keyword("REGR_SXY");
36270 self.write("(");
36271 self.generate_expression(&e.this)?;
36272 self.write(", ");
36273 self.generate_expression(&e.expression)?;
36274 self.write(")");
36275 Ok(())
36276 }
36277
36278 fn generate_regr_syy(&mut self, e: &RegrSyy) -> Result<()> {
36279 self.write_keyword("REGR_SYY");
36281 self.write("(");
36282 self.generate_expression(&e.this)?;
36283 self.write(", ");
36284 self.generate_expression(&e.expression)?;
36285 self.write(")");
36286 Ok(())
36287 }
36288
36289 fn generate_regr_valx(&mut self, e: &RegrValx) -> Result<()> {
36290 self.write_keyword("REGR_VALX");
36292 self.write("(");
36293 self.generate_expression(&e.this)?;
36294 self.write(", ");
36295 self.generate_expression(&e.expression)?;
36296 self.write(")");
36297 Ok(())
36298 }
36299
36300 fn generate_regr_valy(&mut self, e: &RegrValy) -> Result<()> {
36301 self.write_keyword("REGR_VALY");
36303 self.write("(");
36304 self.generate_expression(&e.this)?;
36305 self.write(", ");
36306 self.generate_expression(&e.expression)?;
36307 self.write(")");
36308 Ok(())
36309 }
36310
36311 fn generate_remote_with_connection_model_property(
36312 &mut self,
36313 e: &RemoteWithConnectionModelProperty,
36314 ) -> Result<()> {
36315 self.write_keyword("REMOTE WITH CONNECTION");
36317 self.write_space();
36318 self.generate_expression(&e.this)?;
36319 Ok(())
36320 }
36321
36322 fn generate_rename_column(&mut self, e: &RenameColumn) -> Result<()> {
36323 self.write_keyword("RENAME COLUMN");
36325 if e.exists {
36326 self.write_space();
36327 self.write_keyword("IF EXISTS");
36328 }
36329 self.write_space();
36330 self.generate_expression(&e.this)?;
36331 if let Some(to) = &e.to {
36332 self.write_space();
36333 self.write_keyword("TO");
36334 self.write_space();
36335 self.generate_expression(to)?;
36336 }
36337 Ok(())
36338 }
36339
36340 fn generate_replace_partition(&mut self, e: &ReplacePartition) -> Result<()> {
36341 self.write_keyword("REPLACE PARTITION");
36343 self.write_space();
36344 self.generate_expression(&e.expression)?;
36345 if let Some(source) = &e.source {
36346 self.write_space();
36347 self.write_keyword("FROM");
36348 self.write_space();
36349 self.generate_expression(source)?;
36350 }
36351 Ok(())
36352 }
36353
36354 fn generate_returning(&mut self, e: &Returning) -> Result<()> {
36355 let keyword = match self.config.dialect {
36358 Some(DialectType::TSQL) | Some(DialectType::Fabric) => "OUTPUT",
36359 _ => "RETURNING",
36360 };
36361 self.write_keyword(keyword);
36362 self.write_space();
36363 for (i, expr) in e.expressions.iter().enumerate() {
36364 if i > 0 {
36365 self.write(", ");
36366 }
36367 self.generate_expression(expr)?;
36368 }
36369 if let Some(into) = &e.into {
36370 self.write_space();
36371 self.write_keyword("INTO");
36372 self.write_space();
36373 self.generate_expression(into)?;
36374 }
36375 Ok(())
36376 }
36377
36378 fn generate_output_clause(&mut self, output: &OutputClause) -> Result<()> {
36379 self.write_space();
36381 self.write_keyword("OUTPUT");
36382 self.write_space();
36383 for (i, expr) in output.columns.iter().enumerate() {
36384 if i > 0 {
36385 self.write(", ");
36386 }
36387 self.generate_expression(expr)?;
36388 }
36389 if let Some(into_table) = &output.into_table {
36390 self.write_space();
36391 self.write_keyword("INTO");
36392 self.write_space();
36393 self.generate_expression(into_table)?;
36394 }
36395 Ok(())
36396 }
36397
36398 fn generate_returns_property(&mut self, e: &ReturnsProperty) -> Result<()> {
36399 self.write_keyword("RETURNS");
36401 if e.is_table.is_some() {
36402 self.write_space();
36403 self.write_keyword("TABLE");
36404 }
36405 if let Some(table) = &e.table {
36406 self.write_space();
36407 self.generate_expression(table)?;
36408 } else if let Some(this) = &e.this {
36409 self.write_space();
36410 self.generate_expression(this)?;
36411 }
36412 if e.null.is_some() {
36413 self.write_space();
36414 self.write_keyword("NULL ON NULL INPUT");
36415 }
36416 Ok(())
36417 }
36418
36419 fn generate_rollback(&mut self, e: &Rollback) -> Result<()> {
36420 self.write_keyword("ROLLBACK");
36422
36423 if e.this.is_none()
36425 && matches!(
36426 self.config.dialect,
36427 Some(DialectType::TSQL) | Some(DialectType::Fabric)
36428 )
36429 {
36430 self.write_space();
36431 self.write_keyword("TRANSACTION");
36432 }
36433
36434 if let Some(this) = &e.this {
36436 let is_transaction_marker = matches!(
36438 this.as_ref(),
36439 Expression::Identifier(id) if id.name == "TRANSACTION"
36440 );
36441
36442 self.write_space();
36443 self.write_keyword("TRANSACTION");
36444
36445 if !is_transaction_marker {
36447 self.write_space();
36448 self.generate_expression(this)?;
36449 }
36450 }
36451
36452 if let Some(savepoint) = &e.savepoint {
36454 self.write_space();
36455 self.write_keyword("TO");
36456 self.write_space();
36457 self.generate_expression(savepoint)?;
36458 }
36459 Ok(())
36460 }
36461
36462 fn generate_rollup(&mut self, e: &Rollup) -> Result<()> {
36463 if e.expressions.is_empty() {
36465 self.write_keyword("WITH ROLLUP");
36466 } else {
36467 self.write_keyword("ROLLUP");
36468 self.write("(");
36469 for (i, expr) in e.expressions.iter().enumerate() {
36470 if i > 0 {
36471 self.write(", ");
36472 }
36473 self.generate_expression(expr)?;
36474 }
36475 self.write(")");
36476 }
36477 Ok(())
36478 }
36479
36480 fn generate_row_format_delimited_property(
36481 &mut self,
36482 e: &RowFormatDelimitedProperty,
36483 ) -> Result<()> {
36484 self.write_keyword("ROW FORMAT DELIMITED");
36486 if let Some(fields) = &e.fields {
36487 self.write_space();
36488 self.write_keyword("FIELDS TERMINATED BY");
36489 self.write_space();
36490 self.generate_expression(fields)?;
36491 }
36492 if let Some(escaped) = &e.escaped {
36493 self.write_space();
36494 self.write_keyword("ESCAPED BY");
36495 self.write_space();
36496 self.generate_expression(escaped)?;
36497 }
36498 if let Some(items) = &e.collection_items {
36499 self.write_space();
36500 self.write_keyword("COLLECTION ITEMS TERMINATED BY");
36501 self.write_space();
36502 self.generate_expression(items)?;
36503 }
36504 if let Some(keys) = &e.map_keys {
36505 self.write_space();
36506 self.write_keyword("MAP KEYS TERMINATED BY");
36507 self.write_space();
36508 self.generate_expression(keys)?;
36509 }
36510 if let Some(lines) = &e.lines {
36511 self.write_space();
36512 self.write_keyword("LINES TERMINATED BY");
36513 self.write_space();
36514 self.generate_expression(lines)?;
36515 }
36516 if let Some(null) = &e.null {
36517 self.write_space();
36518 self.write_keyword("NULL DEFINED AS");
36519 self.write_space();
36520 self.generate_expression(null)?;
36521 }
36522 if let Some(serde) = &e.serde {
36523 self.write_space();
36524 self.generate_expression(serde)?;
36525 }
36526 Ok(())
36527 }
36528
36529 fn generate_row_format_property(&mut self, e: &RowFormatProperty) -> Result<()> {
36530 self.write_keyword("ROW FORMAT");
36532 self.write_space();
36533 self.generate_expression(&e.this)?;
36534 Ok(())
36535 }
36536
36537 fn generate_row_format_serde_property(&mut self, e: &RowFormatSerdeProperty) -> Result<()> {
36538 self.write_keyword("ROW FORMAT SERDE");
36540 self.write_space();
36541 self.generate_expression(&e.this)?;
36542 if let Some(props) = &e.serde_properties {
36543 self.write_space();
36544 self.generate_expression(props)?;
36546 }
36547 Ok(())
36548 }
36549
36550 fn generate_sha2(&mut self, e: &SHA2) -> Result<()> {
36551 self.write_keyword("SHA2");
36553 self.write("(");
36554 self.generate_expression(&e.this)?;
36555 if let Some(length) = e.length {
36556 self.write(", ");
36557 self.write(&length.to_string());
36558 }
36559 self.write(")");
36560 Ok(())
36561 }
36562
36563 fn generate_sha2_digest(&mut self, e: &SHA2Digest) -> Result<()> {
36564 self.write_keyword("SHA2_DIGEST");
36566 self.write("(");
36567 self.generate_expression(&e.this)?;
36568 if let Some(length) = e.length {
36569 self.write(", ");
36570 self.write(&length.to_string());
36571 }
36572 self.write(")");
36573 Ok(())
36574 }
36575
36576 fn generate_safe_add(&mut self, e: &SafeAdd) -> Result<()> {
36577 let name = if matches!(
36578 self.config.dialect,
36579 Some(crate::dialects::DialectType::Spark)
36580 | Some(crate::dialects::DialectType::Databricks)
36581 ) {
36582 "TRY_ADD"
36583 } else {
36584 "SAFE_ADD"
36585 };
36586 self.write_keyword(name);
36587 self.write("(");
36588 self.generate_expression(&e.this)?;
36589 self.write(", ");
36590 self.generate_expression(&e.expression)?;
36591 self.write(")");
36592 Ok(())
36593 }
36594
36595 fn generate_safe_divide(&mut self, e: &SafeDivide) -> Result<()> {
36596 self.write_keyword("SAFE_DIVIDE");
36598 self.write("(");
36599 self.generate_expression(&e.this)?;
36600 self.write(", ");
36601 self.generate_expression(&e.expression)?;
36602 self.write(")");
36603 Ok(())
36604 }
36605
36606 fn generate_safe_multiply(&mut self, e: &SafeMultiply) -> Result<()> {
36607 let name = if matches!(
36608 self.config.dialect,
36609 Some(crate::dialects::DialectType::Spark)
36610 | Some(crate::dialects::DialectType::Databricks)
36611 ) {
36612 "TRY_MULTIPLY"
36613 } else {
36614 "SAFE_MULTIPLY"
36615 };
36616 self.write_keyword(name);
36617 self.write("(");
36618 self.generate_expression(&e.this)?;
36619 self.write(", ");
36620 self.generate_expression(&e.expression)?;
36621 self.write(")");
36622 Ok(())
36623 }
36624
36625 fn generate_safe_subtract(&mut self, e: &SafeSubtract) -> Result<()> {
36626 let name = if matches!(
36627 self.config.dialect,
36628 Some(crate::dialects::DialectType::Spark)
36629 | Some(crate::dialects::DialectType::Databricks)
36630 ) {
36631 "TRY_SUBTRACT"
36632 } else {
36633 "SAFE_SUBTRACT"
36634 };
36635 self.write_keyword(name);
36636 self.write("(");
36637 self.generate_expression(&e.this)?;
36638 self.write(", ");
36639 self.generate_expression(&e.expression)?;
36640 self.write(")");
36641 Ok(())
36642 }
36643
36644 fn generate_sample_body(&mut self, sample: &Sample) -> Result<()> {
36647 if matches!(sample.method, SampleMethod::Bucket) {
36649 self.write(" (");
36650 self.write_keyword("BUCKET");
36651 self.write_space();
36652 if let Some(ref num) = sample.bucket_numerator {
36653 self.generate_expression(num)?;
36654 }
36655 self.write_space();
36656 self.write_keyword("OUT OF");
36657 self.write_space();
36658 if let Some(ref denom) = sample.bucket_denominator {
36659 self.generate_expression(denom)?;
36660 }
36661 if let Some(ref field) = sample.bucket_field {
36662 self.write_space();
36663 self.write_keyword("ON");
36664 self.write_space();
36665 self.generate_expression(field)?;
36666 }
36667 self.write(")");
36668 return Ok(());
36669 }
36670
36671 let is_snowflake = matches!(
36673 self.config.dialect,
36674 Some(crate::dialects::DialectType::Snowflake)
36675 );
36676 let is_postgres = matches!(
36677 self.config.dialect,
36678 Some(crate::dialects::DialectType::PostgreSQL)
36679 | Some(crate::dialects::DialectType::Redshift)
36680 );
36681 let is_databricks = matches!(
36683 self.config.dialect,
36684 Some(crate::dialects::DialectType::Databricks)
36685 );
36686 let is_spark = matches!(
36687 self.config.dialect,
36688 Some(crate::dialects::DialectType::Spark)
36689 );
36690 let suppress_method = is_databricks || is_spark || sample.suppress_method_output;
36691 let force_method = is_postgres && matches!(sample.method, SampleMethod::Bernoulli);
36693 if !suppress_method && (sample.explicit_method || is_snowflake || force_method) {
36694 self.write_space();
36695 if !sample.explicit_method && (is_snowflake || force_method) {
36696 self.write_keyword("BERNOULLI");
36698 } else {
36699 match sample.method {
36700 SampleMethod::Bernoulli => self.write_keyword("BERNOULLI"),
36701 SampleMethod::System => self.write_keyword("SYSTEM"),
36702 SampleMethod::Block => self.write_keyword("BLOCK"),
36703 SampleMethod::Row => self.write_keyword("ROW"),
36704 SampleMethod::Reservoir => self.write_keyword("RESERVOIR"),
36705 SampleMethod::Percent => self.write_keyword("SYSTEM"),
36706 SampleMethod::Bucket => {} }
36708 }
36709 }
36710
36711 let emit_size_no_parens = !self.config.tablesample_requires_parens;
36713 if emit_size_no_parens {
36714 self.write_space();
36715 match &sample.size {
36716 Expression::Tuple(tuple) => {
36717 for (i, expr) in tuple.expressions.iter().enumerate() {
36718 if i > 0 {
36719 self.write(", ");
36720 }
36721 self.generate_expression(expr)?;
36722 }
36723 }
36724 expr => self.generate_expression(expr)?,
36725 }
36726 } else {
36727 self.write(" (");
36728 self.generate_expression(&sample.size)?;
36729 }
36730
36731 let is_rows_method = matches!(
36733 sample.method,
36734 SampleMethod::Reservoir | SampleMethod::Row | SampleMethod::Bucket
36735 );
36736 let is_percent = matches!(
36737 sample.method,
36738 SampleMethod::Percent
36739 | SampleMethod::System
36740 | SampleMethod::Bernoulli
36741 | SampleMethod::Block
36742 );
36743
36744 let is_presto = matches!(
36748 self.config.dialect,
36749 Some(crate::dialects::DialectType::Presto)
36750 | Some(crate::dialects::DialectType::Trino)
36751 | Some(crate::dialects::DialectType::Athena)
36752 );
36753 let should_output_unit = if is_databricks || is_spark {
36754 is_percent || is_rows_method || sample.unit_after_size
36756 } else if is_snowflake || is_postgres || is_presto {
36757 sample.unit_after_size
36758 } else {
36759 sample.unit_after_size || (sample.explicit_method && (is_rows_method || is_percent))
36760 };
36761
36762 if should_output_unit {
36763 self.write_space();
36764 if sample.is_percent {
36765 self.write_keyword("PERCENT");
36766 } else if is_rows_method && !sample.unit_after_size {
36767 self.write_keyword("ROWS");
36768 } else if sample.unit_after_size {
36769 match sample.method {
36770 SampleMethod::Percent
36771 | SampleMethod::System
36772 | SampleMethod::Bernoulli
36773 | SampleMethod::Block => {
36774 self.write_keyword("PERCENT");
36775 }
36776 SampleMethod::Row | SampleMethod::Reservoir => {
36777 self.write_keyword("ROWS");
36778 }
36779 _ => self.write_keyword("ROWS"),
36780 }
36781 } else {
36782 self.write_keyword("PERCENT");
36783 }
36784 }
36785
36786 if matches!(self.config.dialect, Some(DialectType::ClickHouse)) {
36787 if let Some(ref offset) = sample.offset {
36788 self.write_space();
36789 self.write_keyword("OFFSET");
36790 self.write_space();
36791 self.generate_expression(offset)?;
36792 }
36793 }
36794 if !emit_size_no_parens {
36795 self.write(")");
36796 }
36797
36798 Ok(())
36799 }
36800
36801 fn generate_sample_property(&mut self, e: &SampleProperty) -> Result<()> {
36802 if matches!(self.config.dialect, Some(DialectType::ClickHouse)) {
36804 self.write_keyword("SAMPLE BY");
36805 } else {
36806 self.write_keyword("SAMPLE");
36807 }
36808 self.write_space();
36809 self.generate_expression(&e.this)?;
36810 Ok(())
36811 }
36812
36813 fn generate_schema(&mut self, e: &Schema) -> Result<()> {
36814 if let Some(this) = &e.this {
36816 self.generate_expression(this)?;
36817 }
36818 if !e.expressions.is_empty() {
36819 if e.this.is_some() {
36821 self.write_space();
36822 }
36823 self.write("(");
36824 for (i, expr) in e.expressions.iter().enumerate() {
36825 if i > 0 {
36826 self.write(", ");
36827 }
36828 self.generate_expression(expr)?;
36829 }
36830 self.write(")");
36831 }
36832 Ok(())
36833 }
36834
36835 fn generate_schema_comment_property(&mut self, e: &SchemaCommentProperty) -> Result<()> {
36836 self.write_keyword("COMMENT");
36838 self.write_space();
36839 self.generate_expression(&e.this)?;
36840 Ok(())
36841 }
36842
36843 fn generate_scope_resolution(&mut self, e: &ScopeResolution) -> Result<()> {
36844 if let Some(this) = &e.this {
36846 self.generate_expression(this)?;
36847 self.write("::");
36848 }
36849 self.generate_expression(&e.expression)?;
36850 Ok(())
36851 }
36852
36853 fn generate_search(&mut self, e: &Search) -> Result<()> {
36854 self.write_keyword("SEARCH");
36856 self.write("(");
36857 self.generate_expression(&e.this)?;
36858 self.write(", ");
36859 self.generate_expression(&e.expression)?;
36860 if let Some(json_scope) = &e.json_scope {
36861 self.write(", ");
36862 self.generate_expression(json_scope)?;
36863 }
36864 if let Some(analyzer) = &e.analyzer {
36865 self.write(", ");
36866 self.generate_expression(analyzer)?;
36867 }
36868 if let Some(analyzer_options) = &e.analyzer_options {
36869 self.write(", ");
36870 self.generate_expression(analyzer_options)?;
36871 }
36872 if let Some(search_mode) = &e.search_mode {
36873 self.write(", ");
36874 self.generate_expression(search_mode)?;
36875 }
36876 self.write(")");
36877 Ok(())
36878 }
36879
36880 fn generate_search_ip(&mut self, e: &SearchIp) -> Result<()> {
36881 self.write_keyword("SEARCH_IP");
36883 self.write("(");
36884 self.generate_expression(&e.this)?;
36885 self.write(", ");
36886 self.generate_expression(&e.expression)?;
36887 self.write(")");
36888 Ok(())
36889 }
36890
36891 fn generate_security_property(&mut self, e: &SecurityProperty) -> Result<()> {
36892 self.write_keyword("SECURITY");
36894 self.write_space();
36895 self.generate_expression(&e.this)?;
36896 Ok(())
36897 }
36898
36899 fn generate_semantic_view(&mut self, e: &SemanticView) -> Result<()> {
36900 self.write("SEMANTIC_VIEW(");
36902
36903 if self.config.pretty {
36904 self.write_newline();
36906 self.indent_level += 1;
36907 self.write_indent();
36908 self.generate_expression(&e.this)?;
36909
36910 if let Some(metrics) = &e.metrics {
36911 self.write_newline();
36912 self.write_indent();
36913 self.write_keyword("METRICS");
36914 self.write_space();
36915 self.generate_semantic_view_tuple(metrics)?;
36916 }
36917 if let Some(dimensions) = &e.dimensions {
36918 self.write_newline();
36919 self.write_indent();
36920 self.write_keyword("DIMENSIONS");
36921 self.write_space();
36922 self.generate_semantic_view_tuple(dimensions)?;
36923 }
36924 if let Some(facts) = &e.facts {
36925 self.write_newline();
36926 self.write_indent();
36927 self.write_keyword("FACTS");
36928 self.write_space();
36929 self.generate_semantic_view_tuple(facts)?;
36930 }
36931 if let Some(where_) = &e.where_ {
36932 self.write_newline();
36933 self.write_indent();
36934 self.write_keyword("WHERE");
36935 self.write_space();
36936 self.generate_expression(where_)?;
36937 }
36938 self.write_newline();
36939 self.indent_level -= 1;
36940 self.write_indent();
36941 } else {
36942 self.generate_expression(&e.this)?;
36944 if let Some(metrics) = &e.metrics {
36945 self.write_space();
36946 self.write_keyword("METRICS");
36947 self.write_space();
36948 self.generate_semantic_view_tuple(metrics)?;
36949 }
36950 if let Some(dimensions) = &e.dimensions {
36951 self.write_space();
36952 self.write_keyword("DIMENSIONS");
36953 self.write_space();
36954 self.generate_semantic_view_tuple(dimensions)?;
36955 }
36956 if let Some(facts) = &e.facts {
36957 self.write_space();
36958 self.write_keyword("FACTS");
36959 self.write_space();
36960 self.generate_semantic_view_tuple(facts)?;
36961 }
36962 if let Some(where_) = &e.where_ {
36963 self.write_space();
36964 self.write_keyword("WHERE");
36965 self.write_space();
36966 self.generate_expression(where_)?;
36967 }
36968 }
36969 self.write(")");
36970 Ok(())
36971 }
36972
36973 fn generate_semantic_view_tuple(&mut self, expr: &Expression) -> Result<()> {
36975 if let Expression::Tuple(t) = expr {
36976 for (i, e) in t.expressions.iter().enumerate() {
36977 if i > 0 {
36978 self.write(", ");
36979 }
36980 self.generate_expression(e)?;
36981 }
36982 } else {
36983 self.generate_expression(expr)?;
36984 }
36985 Ok(())
36986 }
36987
36988 fn generate_sequence_properties(&mut self, e: &SequenceProperties) -> Result<()> {
36989 if let Some(start) = &e.start {
36991 self.write_keyword("START WITH");
36992 self.write_space();
36993 self.generate_expression(start)?;
36994 }
36995 if let Some(increment) = &e.increment {
36996 self.write_space();
36997 self.write_keyword("INCREMENT BY");
36998 self.write_space();
36999 self.generate_expression(increment)?;
37000 }
37001 if let Some(minvalue) = &e.minvalue {
37002 self.write_space();
37003 self.write_keyword("MINVALUE");
37004 self.write_space();
37005 self.generate_expression(minvalue)?;
37006 }
37007 if let Some(maxvalue) = &e.maxvalue {
37008 self.write_space();
37009 self.write_keyword("MAXVALUE");
37010 self.write_space();
37011 self.generate_expression(maxvalue)?;
37012 }
37013 if let Some(cache) = &e.cache {
37014 self.write_space();
37015 self.write_keyword("CACHE");
37016 self.write_space();
37017 self.generate_expression(cache)?;
37018 }
37019 if let Some(owned) = &e.owned {
37020 self.write_space();
37021 self.write_keyword("OWNED BY");
37022 self.write_space();
37023 self.generate_expression(owned)?;
37024 }
37025 for opt in &e.options {
37026 self.write_space();
37027 self.generate_expression(opt)?;
37028 }
37029 Ok(())
37030 }
37031
37032 fn generate_serde_properties(&mut self, e: &SerdeProperties) -> Result<()> {
37033 if e.with_.is_some() {
37035 self.write_keyword("WITH");
37036 self.write_space();
37037 }
37038 self.write_keyword("SERDEPROPERTIES");
37039 self.write(" (");
37040 for (i, expr) in e.expressions.iter().enumerate() {
37041 if i > 0 {
37042 self.write(", ");
37043 }
37044 match expr {
37046 Expression::Eq(eq) => {
37047 self.generate_expression(&eq.left)?;
37048 self.write("=");
37049 self.generate_expression(&eq.right)?;
37050 }
37051 _ => self.generate_expression(expr)?,
37052 }
37053 }
37054 self.write(")");
37055 Ok(())
37056 }
37057
37058 fn generate_session_parameter(&mut self, e: &SessionParameter) -> Result<()> {
37059 self.write("@@");
37061 if let Some(kind) = &e.kind {
37062 self.write(kind);
37063 self.write(".");
37064 }
37065 self.generate_expression(&e.this)?;
37066 Ok(())
37067 }
37068
37069 fn generate_set(&mut self, e: &Set) -> Result<()> {
37070 if e.unset.is_some() {
37072 self.write_keyword("UNSET");
37073 } else {
37074 self.write_keyword("SET");
37075 }
37076 if e.tag.is_some() {
37077 self.write_space();
37078 self.write_keyword("TAG");
37079 }
37080 if !e.expressions.is_empty() {
37081 self.write_space();
37082 for (i, expr) in e.expressions.iter().enumerate() {
37083 if i > 0 {
37084 self.write(", ");
37085 }
37086 self.generate_expression(expr)?;
37087 }
37088 }
37089 Ok(())
37090 }
37091
37092 fn generate_set_config_property(&mut self, e: &SetConfigProperty) -> Result<()> {
37093 self.write_keyword("SET");
37095 self.write_space();
37096 self.generate_expression(&e.this)?;
37097 Ok(())
37098 }
37099
37100 fn generate_set_item(&mut self, e: &SetItem) -> Result<()> {
37101 if let Some(kind) = &e.kind {
37103 self.write_keyword(kind);
37104 self.write_space();
37105 }
37106 self.generate_expression(&e.name)?;
37107 self.write(" = ");
37108 self.generate_expression(&e.value)?;
37109 Ok(())
37110 }
37111
37112 fn generate_set_operation(&mut self, e: &SetOperation) -> Result<()> {
37113 if let Some(with_) = &e.with_ {
37115 self.generate_expression(with_)?;
37116 self.write_space();
37117 }
37118 self.generate_expression(&e.this)?;
37119 self.write_space();
37120 if let Some(kind) = &e.kind {
37122 self.write_keyword(kind);
37123 }
37124 if e.distinct {
37125 self.write_space();
37126 self.write_keyword("DISTINCT");
37127 } else {
37128 self.write_space();
37129 self.write_keyword("ALL");
37130 }
37131 if e.by_name.is_some() {
37132 self.write_space();
37133 self.write_keyword("BY NAME");
37134 }
37135 self.write_space();
37136 self.generate_expression(&e.expression)?;
37137 Ok(())
37138 }
37139
37140 fn generate_set_property(&mut self, e: &SetProperty) -> Result<()> {
37141 if e.multi.is_some() {
37143 self.write_keyword("MULTISET");
37144 } else {
37145 self.write_keyword("SET");
37146 }
37147 Ok(())
37148 }
37149
37150 fn generate_settings_property(&mut self, e: &SettingsProperty) -> Result<()> {
37151 self.write_keyword("SETTINGS");
37153 if self.config.pretty && e.expressions.len() > 1 {
37154 self.indent_level += 1;
37156 for (i, expr) in e.expressions.iter().enumerate() {
37157 if i > 0 {
37158 self.write(",");
37159 }
37160 self.write_newline();
37161 self.write_indent();
37162 self.generate_expression(expr)?;
37163 }
37164 self.indent_level -= 1;
37165 } else {
37166 self.write_space();
37167 for (i, expr) in e.expressions.iter().enumerate() {
37168 if i > 0 {
37169 self.write(", ");
37170 }
37171 self.generate_expression(expr)?;
37172 }
37173 }
37174 Ok(())
37175 }
37176
37177 fn generate_sharing_property(&mut self, e: &SharingProperty) -> Result<()> {
37178 self.write_keyword("SHARING");
37180 if let Some(this) = &e.this {
37181 self.write(" = ");
37182 self.generate_expression(this)?;
37183 }
37184 Ok(())
37185 }
37186
37187 fn generate_slice(&mut self, e: &Slice) -> Result<()> {
37188 if let Some(begin) = &e.this {
37190 self.generate_expression(begin)?;
37191 }
37192 self.write(":");
37193 if let Some(end) = &e.expression {
37194 self.generate_expression(end)?;
37195 }
37196 if let Some(step) = &e.step {
37197 self.write(":");
37198 self.generate_expression(step)?;
37199 }
37200 Ok(())
37201 }
37202
37203 fn generate_sort_array(&mut self, e: &SortArray) -> Result<()> {
37204 self.write_keyword("SORT_ARRAY");
37206 self.write("(");
37207 self.generate_expression(&e.this)?;
37208 if let Some(asc) = &e.asc {
37209 self.write(", ");
37210 self.generate_expression(asc)?;
37211 }
37212 self.write(")");
37213 Ok(())
37214 }
37215
37216 fn generate_sort_by(&mut self, e: &SortBy) -> Result<()> {
37217 self.write_keyword("SORT BY");
37219 self.write_space();
37220 for (i, expr) in e.expressions.iter().enumerate() {
37221 if i > 0 {
37222 self.write(", ");
37223 }
37224 self.generate_ordered(expr)?;
37225 }
37226 Ok(())
37227 }
37228
37229 fn generate_sort_key_property(&mut self, e: &SortKeyProperty) -> Result<()> {
37230 if e.compound.is_some() {
37232 self.write_keyword("COMPOUND");
37233 self.write_space();
37234 }
37235 self.write_keyword("SORTKEY");
37236 self.write("(");
37237 if let Expression::Tuple(t) = e.this.as_ref() {
37239 for (i, expr) in t.expressions.iter().enumerate() {
37240 if i > 0 {
37241 self.write(", ");
37242 }
37243 self.generate_expression(expr)?;
37244 }
37245 } else {
37246 self.generate_expression(&e.this)?;
37247 }
37248 self.write(")");
37249 Ok(())
37250 }
37251
37252 fn generate_split_part(&mut self, e: &SplitPart) -> Result<()> {
37253 self.write_keyword("SPLIT_PART");
37255 self.write("(");
37256 self.generate_expression(&e.this)?;
37257 if let Some(delimiter) = &e.delimiter {
37258 self.write(", ");
37259 self.generate_expression(delimiter)?;
37260 }
37261 if let Some(part_index) = &e.part_index {
37262 self.write(", ");
37263 self.generate_expression(part_index)?;
37264 }
37265 self.write(")");
37266 Ok(())
37267 }
37268
37269 fn generate_sql_read_write_property(&mut self, e: &SqlReadWriteProperty) -> Result<()> {
37270 self.generate_expression(&e.this)?;
37272 Ok(())
37273 }
37274
37275 fn generate_sql_security_property(&mut self, e: &SqlSecurityProperty) -> Result<()> {
37276 self.write_keyword("SQL SECURITY");
37278 self.write_space();
37279 self.generate_expression(&e.this)?;
37280 Ok(())
37281 }
37282
37283 fn generate_st_distance(&mut self, e: &StDistance) -> Result<()> {
37284 self.write_keyword("ST_DISTANCE");
37286 self.write("(");
37287 self.generate_expression(&e.this)?;
37288 self.write(", ");
37289 self.generate_expression(&e.expression)?;
37290 if let Some(use_spheroid) = &e.use_spheroid {
37291 self.write(", ");
37292 self.generate_expression(use_spheroid)?;
37293 }
37294 self.write(")");
37295 Ok(())
37296 }
37297
37298 fn generate_st_point(&mut self, e: &StPoint) -> Result<()> {
37299 self.write_keyword("ST_POINT");
37301 self.write("(");
37302 self.generate_expression(&e.this)?;
37303 self.write(", ");
37304 self.generate_expression(&e.expression)?;
37305 self.write(")");
37306 Ok(())
37307 }
37308
37309 fn generate_stability_property(&mut self, e: &StabilityProperty) -> Result<()> {
37310 self.generate_expression(&e.this)?;
37312 Ok(())
37313 }
37314
37315 fn generate_standard_hash(&mut self, e: &StandardHash) -> Result<()> {
37316 self.write_keyword("STANDARD_HASH");
37318 self.write("(");
37319 self.generate_expression(&e.this)?;
37320 if let Some(expression) = &e.expression {
37321 self.write(", ");
37322 self.generate_expression(expression)?;
37323 }
37324 self.write(")");
37325 Ok(())
37326 }
37327
37328 fn generate_storage_handler_property(&mut self, e: &StorageHandlerProperty) -> Result<()> {
37329 self.write_keyword("STORED BY");
37331 self.write_space();
37332 self.generate_expression(&e.this)?;
37333 Ok(())
37334 }
37335
37336 fn generate_str_position(&mut self, e: &StrPosition) -> Result<()> {
37337 use crate::dialects::DialectType;
37340 if matches!(self.config.dialect, Some(DialectType::Snowflake)) {
37341 self.write_keyword("CHARINDEX");
37343 self.write("(");
37344 if let Some(substr) = &e.substr {
37345 self.generate_expression(substr)?;
37346 self.write(", ");
37347 }
37348 self.generate_expression(&e.this)?;
37349 if let Some(position) = &e.position {
37350 self.write(", ");
37351 self.generate_expression(position)?;
37352 }
37353 self.write(")");
37354 } else if matches!(self.config.dialect, Some(DialectType::ClickHouse)) {
37355 self.write_keyword("POSITION");
37356 self.write("(");
37357 self.generate_expression(&e.this)?;
37358 if let Some(substr) = &e.substr {
37359 self.write(", ");
37360 self.generate_expression(substr)?;
37361 }
37362 if let Some(position) = &e.position {
37363 self.write(", ");
37364 self.generate_expression(position)?;
37365 }
37366 if let Some(occurrence) = &e.occurrence {
37367 self.write(", ");
37368 self.generate_expression(occurrence)?;
37369 }
37370 self.write(")");
37371 } else if matches!(
37372 self.config.dialect,
37373 Some(DialectType::SQLite)
37374 | Some(DialectType::Oracle)
37375 | Some(DialectType::BigQuery)
37376 | Some(DialectType::Teradata)
37377 ) {
37378 self.write_keyword("INSTR");
37379 self.write("(");
37380 self.generate_expression(&e.this)?;
37381 if let Some(substr) = &e.substr {
37382 self.write(", ");
37383 self.generate_expression(substr)?;
37384 }
37385 if let Some(position) = &e.position {
37386 self.write(", ");
37387 self.generate_expression(position)?;
37388 } else if e.occurrence.is_some() {
37389 self.write(", 1");
37392 }
37393 if let Some(occurrence) = &e.occurrence {
37394 self.write(", ");
37395 self.generate_expression(occurrence)?;
37396 }
37397 self.write(")");
37398 } else if matches!(
37399 self.config.dialect,
37400 Some(DialectType::MySQL)
37401 | Some(DialectType::SingleStore)
37402 | Some(DialectType::Doris)
37403 | Some(DialectType::StarRocks)
37404 | Some(DialectType::Hive)
37405 | Some(DialectType::Spark)
37406 | Some(DialectType::Databricks)
37407 ) {
37408 self.write_keyword("LOCATE");
37410 self.write("(");
37411 if let Some(substr) = &e.substr {
37412 self.generate_expression(substr)?;
37413 self.write(", ");
37414 }
37415 self.generate_expression(&e.this)?;
37416 if let Some(position) = &e.position {
37417 self.write(", ");
37418 self.generate_expression(position)?;
37419 }
37420 self.write(")");
37421 } else if matches!(
37422 self.config.dialect,
37423 Some(DialectType::TSQL) | Some(DialectType::Fabric)
37424 ) {
37425 self.write_keyword("CHARINDEX");
37427 self.write("(");
37428 if let Some(substr) = &e.substr {
37429 self.generate_expression(substr)?;
37430 self.write(", ");
37431 }
37432 self.generate_expression(&e.this)?;
37433 if let Some(position) = &e.position {
37434 self.write(", ");
37435 self.generate_expression(position)?;
37436 }
37437 self.write(")");
37438 } else if matches!(
37439 self.config.dialect,
37440 Some(DialectType::PostgreSQL)
37441 | Some(DialectType::Materialize)
37442 | Some(DialectType::RisingWave)
37443 | Some(DialectType::Redshift)
37444 ) {
37445 self.write_keyword("POSITION");
37447 self.write("(");
37448 if let Some(substr) = &e.substr {
37449 self.generate_expression(substr)?;
37450 self.write(" IN ");
37451 }
37452 self.generate_expression(&e.this)?;
37453 self.write(")");
37454 } else {
37455 self.write_keyword("STRPOS");
37456 self.write("(");
37457 self.generate_expression(&e.this)?;
37458 if let Some(substr) = &e.substr {
37459 self.write(", ");
37460 self.generate_expression(substr)?;
37461 }
37462 if let Some(position) = &e.position {
37463 self.write(", ");
37464 self.generate_expression(position)?;
37465 }
37466 if let Some(occurrence) = &e.occurrence {
37467 self.write(", ");
37468 self.generate_expression(occurrence)?;
37469 }
37470 self.write(")");
37471 }
37472 Ok(())
37473 }
37474
37475 fn generate_str_to_date(&mut self, e: &StrToDate) -> Result<()> {
37476 match self.config.dialect {
37477 Some(DialectType::TSQL) | Some(DialectType::Fabric) => {
37478 self.generate_tsql_str_to_temporal(&e.this, e.format.as_deref(), "DATE")?;
37479 }
37480 Some(DialectType::Spark) | Some(DialectType::Databricks) | Some(DialectType::Hive) => {
37481 self.write_keyword("TO_DATE");
37483 self.write("(");
37484 self.generate_expression(&e.this)?;
37485 if let Some(format) = &e.format {
37486 self.write(", '");
37487 self.write(&Self::strftime_to_java_format(format));
37488 self.write("'");
37489 }
37490 self.write(")");
37491 }
37492 Some(DialectType::DuckDB) => {
37493 self.write_keyword("CAST");
37495 self.write("(");
37496 self.write_keyword("STRPTIME");
37497 self.write("(");
37498 self.generate_expression(&e.this)?;
37499 if let Some(format) = &e.format {
37500 self.write(", '");
37501 self.write(format);
37502 self.write("'");
37503 }
37504 self.write(")");
37505 self.write_keyword(" AS ");
37506 self.write_keyword("DATE");
37507 self.write(")");
37508 }
37509 Some(DialectType::PostgreSQL) | Some(DialectType::Redshift) => {
37510 self.write_keyword("TO_DATE");
37512 self.write("(");
37513 self.generate_expression(&e.this)?;
37514 if let Some(format) = &e.format {
37515 self.write(", '");
37516 self.write(&Self::strftime_to_postgres_format(format));
37517 self.write("'");
37518 }
37519 self.write(")");
37520 }
37521 Some(DialectType::BigQuery) => {
37522 self.write_keyword("PARSE_DATE");
37524 self.write("(");
37525 if let Some(format) = &e.format {
37526 self.write("'");
37527 self.write(format);
37528 self.write("'");
37529 self.write(", ");
37530 }
37531 self.generate_expression(&e.this)?;
37532 self.write(")");
37533 }
37534 Some(DialectType::Teradata) => {
37535 self.write_keyword("CAST");
37537 self.write("(");
37538 self.generate_expression(&e.this)?;
37539 self.write_keyword(" AS ");
37540 self.write_keyword("DATE");
37541 if let Some(format) = &e.format {
37542 self.write_keyword(" FORMAT ");
37543 self.write("'");
37544 self.write(&Self::strftime_to_teradata_format(format));
37545 self.write("'");
37546 }
37547 self.write(")");
37548 }
37549 _ => {
37550 self.write_keyword("STR_TO_DATE");
37552 self.write("(");
37553 self.generate_expression(&e.this)?;
37554 if let Some(format) = &e.format {
37555 self.write(", '");
37556 self.write(format);
37557 self.write("'");
37558 }
37559 self.write(")");
37560 }
37561 }
37562 Ok(())
37563 }
37564
37565 fn strftime_to_teradata_format(fmt: &str) -> String {
37567 let mut result = String::with_capacity(fmt.len() * 2);
37568 let bytes = fmt.as_bytes();
37569 let len = bytes.len();
37570 let mut i = 0;
37571 while i < len {
37572 if bytes[i] == b'%' && i + 1 < len {
37573 let replacement = match bytes[i + 1] {
37574 b'Y' => "YYYY",
37575 b'y' => "YY",
37576 b'm' => "MM",
37577 b'B' => "MMMM",
37578 b'b' => "MMM",
37579 b'd' => "DD",
37580 b'j' => "DDD",
37581 b'H' => "HH",
37582 b'M' => "MI",
37583 b'S' => "SS",
37584 b'f' => "SSSSSS",
37585 b'A' => "EEEE",
37586 b'a' => "EEE",
37587 _ => {
37588 result.push('%');
37589 i += 1;
37590 continue;
37591 }
37592 };
37593 result.push_str(replacement);
37594 i += 2;
37595 } else {
37596 result.push(bytes[i] as char);
37597 i += 1;
37598 }
37599 }
37600 result
37601 }
37602
37603 pub fn strftime_to_java_format_static(fmt: &str) -> String {
37606 Self::strftime_to_java_format_with_padding(fmt, true)
37607 }
37608
37609 pub fn strftime_to_java_format_non_padded_static(fmt: &str) -> String {
37612 Self::strftime_to_java_format_with_padding(fmt, false)
37613 }
37614
37615 fn strftime_to_java_format(fmt: &str) -> String {
37617 Self::strftime_to_java_format_with_padding(fmt, true)
37618 }
37619
37620 fn strftime_to_java_format_non_padded(fmt: &str) -> String {
37621 Self::strftime_to_java_format_with_padding(fmt, false)
37622 }
37623
37624 fn strftime_to_java_format_with_padding(fmt: &str, padded: bool) -> String {
37625 let mut result = String::with_capacity(fmt.len() * 2);
37626 let bytes = fmt.as_bytes();
37627 let len = bytes.len();
37628 let mut i = 0;
37629 while i < len {
37630 if bytes[i] == b'\\' && i + 1 < len {
37631 result.push('\\');
37634 if bytes[i + 1] == b'\'' {
37635 result.push_str("''");
37636 } else {
37637 result.push(bytes[i + 1] as char);
37638 }
37639 i += 2;
37640 } else if bytes[i] == b'%' && i + 1 < len {
37641 if bytes[i + 1] == b'-' && i + 2 < len {
37643 let replacement = match bytes[i + 2] {
37644 b'd' => "d",
37645 b'm' => "M",
37646 b'H' => "H",
37647 b'I' => "h",
37648 b'M' => "m",
37649 b'S' => "s",
37650 _ => {
37651 result.push('%');
37652 i += 1;
37653 continue;
37654 }
37655 };
37656 result.push_str(replacement);
37657 i += 3;
37658 } else {
37659 let replacement = match bytes[i + 1] {
37660 b'Y' => "yyyy",
37661 b'y' => "yy",
37662 b'm' => {
37663 if padded {
37664 "MM"
37665 } else {
37666 "M"
37667 }
37668 }
37669 b'B' => "MMMM",
37670 b'b' => "MMM",
37671 b'd' => {
37672 if padded {
37673 "dd"
37674 } else {
37675 "d"
37676 }
37677 }
37678 b'j' => "DDD",
37679 b'H' => {
37680 if padded {
37681 "HH"
37682 } else {
37683 "H"
37684 }
37685 }
37686 b'M' => {
37687 if padded {
37688 "mm"
37689 } else {
37690 "m"
37691 }
37692 }
37693 b'S' => {
37694 if padded {
37695 "ss"
37696 } else {
37697 "s"
37698 }
37699 }
37700 b'f' => "SSSSSS",
37701 b'A' => "EEEE",
37702 b'a' => "EEE",
37703 _ => {
37704 result.push('%');
37705 i += 1;
37706 continue;
37707 }
37708 };
37709 result.push_str(replacement);
37710 i += 2;
37711 }
37712 } else {
37713 result.push(bytes[i] as char);
37714 i += 1;
37715 }
37716 }
37717 result
37718 }
37719
37720 fn strftime_to_tsql_format(fmt: &str) -> String {
37723 let mut result = String::with_capacity(fmt.len() * 2);
37724 let bytes = fmt.as_bytes();
37725 let len = bytes.len();
37726 let mut i = 0;
37727 while i < len {
37728 if bytes[i] == b'%' && i + 1 < len {
37729 if bytes[i + 1] == b'-' && i + 2 < len {
37731 let replacement = match bytes[i + 2] {
37732 b'd' => "d",
37733 b'm' => "M",
37734 b'H' => "H",
37735 b'M' => "m",
37736 b'S' => "s",
37737 _ => {
37738 result.push('%');
37739 i += 1;
37740 continue;
37741 }
37742 };
37743 result.push_str(replacement);
37744 i += 3;
37745 } else {
37746 let replacement = match bytes[i + 1] {
37747 b'Y' => "yyyy",
37748 b'y' => "yy",
37749 b'm' => "MM",
37750 b'B' => "MMMM",
37751 b'b' => "MMM",
37752 b'd' => "dd",
37753 b'j' => "DDD",
37754 b'H' => "HH",
37755 b'I' => "hh",
37756 b'M' => "mm",
37757 b'S' => "ss",
37758 b'f' => "ffffff",
37759 b'A' => "dddd",
37760 b'a' => "ddd",
37761 _ => {
37762 result.push('%');
37763 i += 1;
37764 continue;
37765 }
37766 };
37767 result.push_str(replacement);
37768 i += 2;
37769 }
37770 } else {
37771 result.push(bytes[i] as char);
37772 i += 1;
37773 }
37774 }
37775 result
37776 }
37777
37778 fn tsql_convert_style_for_strftime(fmt: &str) -> Option<u16> {
37779 match fmt.trim() {
37780 "%b %d %Y %-I:%M%p" => Some(100),
37781 "%m/%d/%y" => Some(1),
37782 "%y.%m.%d" => Some(2),
37783 "%d/%m/%y" => Some(3),
37784 "%d.%m.%y" => Some(4),
37785 "%d-%m-%y" => Some(5),
37786 "%d %b %y" => Some(6),
37787 "%b %d, %y" => Some(7),
37788 "%H:%M:%S" => Some(108),
37789 "%b %d %Y %-I:%M:%S:%f%p" => Some(109),
37790 "%m-%d-%y" => Some(10),
37791 "%y/%m/%d" => Some(11),
37792 "%y%m%d" => Some(12),
37793 "%d %b %Y %H:%M:%S:%f" => Some(113),
37794 "%H:%M:%S:%f" => Some(114),
37795 "%m/%d/%Y" => Some(101),
37796 "%Y.%m.%d" => Some(102),
37797 "%d/%m/%Y" => Some(103),
37798 "%d.%m.%Y" => Some(104),
37799 "%d-%m-%Y" => Some(105),
37800 "%d %b %Y" => Some(106),
37801 "%b %d, %Y" => Some(107),
37802 "%m-%d-%Y" => Some(110),
37803 "%Y/%m/%d" => Some(111),
37804 "%Y%m%d" => Some(112),
37805 "%Y-%m-%d %H:%M:%S" => Some(120),
37806 "%Y-%m-%d %H:%M:%S.%f" => Some(121),
37807 "%Y-%m-%dT%H:%M:%S" | "%Y-%m-%dT%H:%M:%S.%f" => Some(126),
37808 "%Y-%m-%d" => Some(23),
37809 _ => None,
37810 }
37811 }
37812
37813 fn postgres_year_is_outside_tsql_range(value: &str, format: &str) -> bool {
37814 fn component_is_outside(component: &str, forced_negative: bool) -> bool {
37815 let component = component.trim().trim_end_matches(',');
37816 let (negative, digits) = match component.as_bytes().first() {
37817 Some(b'-') => (true, &component[1..]),
37818 Some(b'+') => (false, &component[1..]),
37819 _ => (false, component),
37820 };
37821
37822 if forced_negative || negative {
37823 return !digits.is_empty() && digits.bytes().all(|byte| byte.is_ascii_digit());
37824 }
37825
37826 if digits.is_empty() || !digits.bytes().all(|byte| byte.is_ascii_digit()) {
37827 return false;
37828 }
37829
37830 let significant_digits = digits.trim_start_matches('0');
37831 significant_digits.is_empty()
37832 || significant_digits.len() > 4
37833 || significant_digits
37834 .parse::<u16>()
37835 .is_ok_and(|year| year > 9999)
37836 }
37837
37838 let value = value.trim();
37839 let format = format.trim();
37840
37841 if format.starts_with("%Y") {
37842 let bytes = value.as_bytes();
37843 let digit_start = usize::from(matches!(bytes.first(), Some(b'-' | b'+')));
37844 let available_digits = bytes[digit_start..]
37845 .iter()
37846 .take_while(|byte| byte.is_ascii_digit())
37847 .count();
37848 if available_digits == 0 {
37849 return false;
37850 }
37851
37852 let digit_count = if format.starts_with("%Y%") {
37853 available_digits.min(4)
37854 } else {
37855 available_digits
37856 };
37857 return component_is_outside(&value[..digit_start + digit_count], false);
37858 }
37859
37860 if let Some(year_index) = format
37861 .split_whitespace()
37862 .position(|component| component == "%Y")
37863 {
37864 if let Some(component) = value.split_whitespace().nth(year_index) {
37865 return component_is_outside(component, false);
37866 }
37867 }
37868
37869 if format.ends_with("%Y") {
37870 for delimiter in ['/', '.', '-'] {
37871 if format.ends_with(&format!("{delimiter}%Y")) {
37872 if let Some((prefix, component)) = value.rsplit_once(delimiter) {
37873 let forced_negative = delimiter == '-' && prefix.ends_with('-');
37874 return component_is_outside(component, forced_negative);
37875 }
37876 }
37877 }
37878 }
37879
37880 false
37881 }
37882
37883 fn generate_tsql_str_to_temporal(
37884 &mut self,
37885 this: &Expression,
37886 format: Option<&str>,
37887 target_type: &str,
37888 ) -> Result<()> {
37889 if let Some(format) = format {
37890 if let Some(style) = Self::tsql_convert_style_for_strftime(format) {
37891 if target_type == "DATE"
37892 && matches!(self.config.source_dialect, Some(DialectType::PostgreSQL))
37893 {
37894 if let Expression::Literal(literal) = this {
37895 if let Literal::String(value) = literal.as_ref() {
37896 if Self::postgres_year_is_outside_tsql_range(value, format) {
37897 self.unsupported(
37898 "PostgreSQL TO_DATE literal is outside the T-SQL/Fabric DATE range 0001-01-01 through 9999-12-31",
37899 )?;
37900 }
37901 }
37902 }
37903 }
37904
37905 self.write_keyword("CONVERT");
37906 self.write("(");
37907 self.write_keyword(target_type);
37908 self.write(", ");
37909 self.generate_expression(this)?;
37910 self.write(", ");
37911 self.write(&style.to_string());
37912 self.write(")");
37913 return Ok(());
37914 }
37915
37916 self.unsupported(format!(
37917 "T-SQL/Fabric {target_type} parsing format '{format}' has no CONVERT style mapping"
37918 ))?;
37919 }
37920
37921 self.write_keyword("CAST");
37922 self.write("(");
37923 self.generate_expression(this)?;
37924 self.write(" AS ");
37925 self.write_keyword(target_type);
37926 self.write(")");
37927 Ok(())
37928 }
37929
37930 fn decompose_json_path(path: &str) -> Vec<String> {
37933 let mut parts = Vec::new();
37934 let path = if path.starts_with("$.") {
37936 &path[2..]
37937 } else if path.starts_with('$') {
37938 &path[1..]
37939 } else {
37940 path
37941 };
37942 if path.is_empty() {
37943 return parts;
37944 }
37945 let mut current = String::new();
37946 let chars: Vec<char> = path.chars().collect();
37947 let mut i = 0;
37948 while i < chars.len() {
37949 match chars[i] {
37950 '.' => {
37951 if !current.is_empty() {
37952 parts.push(current.clone());
37953 current.clear();
37954 }
37955 i += 1;
37956 }
37957 '[' => {
37958 if !current.is_empty() {
37959 parts.push(current.clone());
37960 current.clear();
37961 }
37962 i += 1;
37963 let mut bracket_content = String::new();
37965 while i < chars.len() && chars[i] != ']' {
37966 if chars[i] == '"' || chars[i] == '\'' {
37968 let quote = chars[i];
37969 i += 1;
37970 while i < chars.len() && chars[i] != quote {
37971 bracket_content.push(chars[i]);
37972 i += 1;
37973 }
37974 if i < chars.len() {
37975 i += 1;
37976 } } else {
37978 bracket_content.push(chars[i]);
37979 i += 1;
37980 }
37981 }
37982 if i < chars.len() {
37983 i += 1;
37984 } if bracket_content != "*" {
37987 parts.push(bracket_content);
37988 }
37989 }
37990 _ => {
37991 current.push(chars[i]);
37992 i += 1;
37993 }
37994 }
37995 }
37996 if !current.is_empty() {
37997 parts.push(current);
37998 }
37999 parts
38000 }
38001
38002 fn strftime_to_postgres_format(fmt: &str) -> String {
38004 let mut result = String::with_capacity(fmt.len() * 2);
38005 let bytes = fmt.as_bytes();
38006 let len = bytes.len();
38007 let mut i = 0;
38008 while i < len {
38009 if bytes[i] == b'%' && i + 1 < len {
38010 if bytes[i + 1] == b'-' && i + 2 < len {
38012 let replacement = match bytes[i + 2] {
38013 b'd' => "FMDD",
38014 b'm' => "FMMM",
38015 b'H' => "FMHH24",
38016 b'M' => "FMMI",
38017 b'S' => "FMSS",
38018 _ => {
38019 result.push('%');
38020 i += 1;
38021 continue;
38022 }
38023 };
38024 result.push_str(replacement);
38025 i += 3;
38026 } else {
38027 let replacement = match bytes[i + 1] {
38028 b'Y' => "YYYY",
38029 b'y' => "YY",
38030 b'm' => "MM",
38031 b'B' => "Month",
38032 b'b' => "Mon",
38033 b'd' => "DD",
38034 b'j' => "DDD",
38035 b'H' => "HH24",
38036 b'M' => "MI",
38037 b'S' => "SS",
38038 b'f' => "US",
38039 b'A' => "Day",
38040 b'a' => "Dy",
38041 _ => {
38042 result.push('%');
38043 i += 1;
38044 continue;
38045 }
38046 };
38047 result.push_str(replacement);
38048 i += 2;
38049 }
38050 } else {
38051 result.push(bytes[i] as char);
38052 i += 1;
38053 }
38054 }
38055 result
38056 }
38057
38058 fn strftime_to_snowflake_format(fmt: &str) -> String {
38060 let mut result = String::with_capacity(fmt.len() * 2);
38061 let bytes = fmt.as_bytes();
38062 let len = bytes.len();
38063 let mut i = 0;
38064 while i < len {
38065 if bytes[i] == b'%' && i + 1 < len {
38066 if bytes[i + 1] == b'-' && i + 2 < len {
38068 let replacement = match bytes[i + 2] {
38069 b'd' => "dd",
38070 b'm' => "mm",
38071 _ => {
38072 result.push('%');
38073 i += 1;
38074 continue;
38075 }
38076 };
38077 result.push_str(replacement);
38078 i += 3;
38079 } else {
38080 let replacement = match bytes[i + 1] {
38081 b'Y' => "yyyy",
38082 b'y' => "yy",
38083 b'm' => "mm",
38084 b'd' => "DD",
38085 b'H' => "hh24",
38086 b'M' => "mi",
38087 b'S' => "ss",
38088 b'f' => "ff",
38089 _ => {
38090 result.push('%');
38091 i += 1;
38092 continue;
38093 }
38094 };
38095 result.push_str(replacement);
38096 i += 2;
38097 }
38098 } else {
38099 result.push(bytes[i] as char);
38100 i += 1;
38101 }
38102 }
38103 result
38104 }
38105
38106 fn generate_str_to_map(&mut self, e: &StrToMap) -> Result<()> {
38107 self.write_keyword("STR_TO_MAP");
38109 self.write("(");
38110 self.generate_expression(&e.this)?;
38111 let needs_defaults = matches!(
38113 self.config.dialect,
38114 Some(DialectType::Spark) | Some(DialectType::Hive) | Some(DialectType::Databricks)
38115 );
38116 if let Some(pair_delim) = &e.pair_delim {
38117 self.write(", ");
38118 self.generate_expression(pair_delim)?;
38119 } else if needs_defaults {
38120 self.write(", ','");
38121 }
38122 if let Some(key_value_delim) = &e.key_value_delim {
38123 self.write(", ");
38124 self.generate_expression(key_value_delim)?;
38125 } else if needs_defaults {
38126 self.write(", ':'");
38127 }
38128 self.write(")");
38129 Ok(())
38130 }
38131
38132 fn generate_str_to_time(&mut self, e: &StrToTime) -> Result<()> {
38133 let is_strftime = e.format.contains('%');
38135 let to_strftime = |f: &str| -> String {
38137 if is_strftime {
38138 f.to_string()
38139 } else {
38140 Self::snowflake_format_to_strftime(f)
38141 }
38142 };
38143 let to_java = |f: &str| -> String {
38145 if is_strftime {
38146 Self::strftime_to_java_format(f)
38147 } else {
38148 Self::snowflake_format_to_spark(f)
38149 }
38150 };
38151 let to_pg = |f: &str| -> String {
38153 if is_strftime {
38154 Self::strftime_to_postgres_format(f)
38155 } else {
38156 Self::convert_strptime_to_postgres_format(f)
38157 }
38158 };
38159
38160 match self.config.dialect {
38161 Some(DialectType::Exasol) => {
38162 self.write_keyword("TO_DATE");
38163 self.write("(");
38164 self.generate_expression(&e.this)?;
38165 self.write(", '");
38166 self.write(&Self::convert_strptime_to_exasol_format(&e.format));
38167 self.write("'");
38168 self.write(")");
38169 }
38170 Some(DialectType::BigQuery) => {
38171 let fmt = to_strftime(&e.format);
38173 let fmt = fmt.replace("%Y-%m-%d", "%F").replace("%H:%M:%S", "%T");
38175 self.write_keyword("PARSE_TIMESTAMP");
38176 self.write("('");
38177 self.write(&fmt);
38178 self.write("', ");
38179 self.generate_expression(&e.this)?;
38180 self.write(")");
38181 }
38182 Some(DialectType::Hive) => {
38183 let java_fmt = if is_strftime {
38186 Self::strftime_to_java_format_non_padded(&e.format)
38187 } else {
38188 Self::snowflake_format_to_spark(&e.format)
38189 };
38190 if java_fmt == "yyyy-MM-dd HH:mm:ss"
38191 || java_fmt == "yyyy-MM-dd"
38192 || java_fmt == "yyyy-M-d H:m:s"
38193 || java_fmt == "yyyy-M-d"
38194 || e.format == "yyyy-MM-dd HH:mm:ss"
38195 || e.format == "yyyy-MM-dd"
38196 {
38197 self.write_keyword("CAST");
38198 self.write("(");
38199 self.generate_expression(&e.this)?;
38200 self.write(" ");
38201 self.write_keyword("AS TIMESTAMP");
38202 self.write(")");
38203 } else {
38204 self.write_keyword("CAST");
38206 self.write("(");
38207 self.write_keyword("FROM_UNIXTIME");
38208 self.write("(");
38209 self.write_keyword("UNIX_TIMESTAMP");
38210 self.write("(");
38211 self.generate_expression(&e.this)?;
38212 self.write(", '");
38213 self.write(&java_fmt);
38214 self.write("')");
38215 self.write(") ");
38216 self.write_keyword("AS TIMESTAMP");
38217 self.write(")");
38218 }
38219 }
38220 Some(DialectType::Spark) | Some(DialectType::Databricks) => {
38221 let java_fmt = if is_strftime {
38223 Self::strftime_to_java_format_non_padded(&e.format)
38224 } else {
38225 Self::snowflake_format_to_spark(&e.format)
38226 };
38227 self.write_keyword("TO_TIMESTAMP");
38228 self.write("(");
38229 self.generate_expression(&e.this)?;
38230 self.write(", '");
38231 self.write(&java_fmt);
38232 self.write("')");
38233 }
38234 Some(DialectType::MySQL) => {
38235 let mut fmt = to_strftime(&e.format);
38237 fmt = fmt.replace("%-d", "%e");
38239 fmt = fmt.replace("%-m", "%c");
38240 fmt = fmt.replace("%H:%M:%S", "%T");
38241 self.write_keyword("STR_TO_DATE");
38242 self.write("(");
38243 self.generate_expression(&e.this)?;
38244 self.write(", '");
38245 self.write(&fmt);
38246 self.write("')");
38247 }
38248 Some(DialectType::Drill) => {
38249 let java_fmt = to_java(&e.format);
38251 let java_fmt = java_fmt.replace('T', "''T''");
38253 self.write_keyword("TO_TIMESTAMP");
38254 self.write("(");
38255 self.generate_expression(&e.this)?;
38256 self.write(", '");
38257 self.write(&java_fmt);
38258 self.write("')");
38259 }
38260 Some(DialectType::Presto) | Some(DialectType::Trino) | Some(DialectType::Athena) => {
38261 let mut fmt = to_strftime(&e.format);
38263 fmt = fmt.replace("%-d", "%e");
38265 fmt = fmt.replace("%-m", "%c");
38266 fmt = fmt.replace("%H:%M:%S", "%T");
38267 self.write_keyword("DATE_PARSE");
38268 self.write("(");
38269 self.generate_expression(&e.this)?;
38270 self.write(", '");
38271 self.write(&fmt);
38272 self.write("')");
38273 }
38274 Some(DialectType::DuckDB) => {
38275 let fmt = to_strftime(&e.format);
38277 self.write_keyword("STRPTIME");
38278 self.write("(");
38279 self.generate_expression(&e.this)?;
38280 self.write(", '");
38281 self.write(&fmt);
38282 self.write("')");
38283 }
38284 Some(DialectType::PostgreSQL)
38285 | Some(DialectType::Redshift)
38286 | Some(DialectType::Materialize) => {
38287 let pg_fmt = to_pg(&e.format);
38289 self.write_keyword("TO_TIMESTAMP");
38290 self.write("(");
38291 self.generate_expression(&e.this)?;
38292 self.write(", '");
38293 self.write(&pg_fmt);
38294 self.write("')");
38295 }
38296 Some(DialectType::Oracle) => {
38297 let pg_fmt = to_pg(&e.format);
38299 self.write_keyword("TO_TIMESTAMP");
38300 self.write("(");
38301 self.generate_expression(&e.this)?;
38302 self.write(", '");
38303 self.write(&pg_fmt);
38304 self.write("')");
38305 }
38306 Some(DialectType::Snowflake) => {
38307 self.write_keyword("TO_TIMESTAMP");
38309 self.write("(");
38310 self.generate_expression(&e.this)?;
38311 self.write(", '");
38312 self.write(&e.format);
38313 self.write("')");
38314 }
38315 Some(DialectType::TSQL) | Some(DialectType::Fabric) => {
38316 self.generate_tsql_str_to_temporal(&e.this, Some(&e.format), "DATETIME2")?;
38317 }
38318 _ => {
38319 self.write_keyword("STR_TO_TIME");
38321 self.write("(");
38322 self.generate_expression(&e.this)?;
38323 self.write(", '");
38324 self.write(&e.format);
38325 self.write("'");
38326 self.write(")");
38327 }
38328 }
38329 Ok(())
38330 }
38331
38332 fn snowflake_format_to_strftime(format: &str) -> String {
38334 let mut result = String::new();
38335 let chars: Vec<char> = format.chars().collect();
38336 let mut i = 0;
38337 while i < chars.len() {
38338 let remaining = &format[i..];
38339 if remaining.starts_with("yyyy") {
38340 result.push_str("%Y");
38341 i += 4;
38342 } else if remaining.starts_with("yy") {
38343 result.push_str("%y");
38344 i += 2;
38345 } else if remaining.starts_with("mmmm") {
38346 result.push_str("%B"); i += 4;
38348 } else if remaining.starts_with("mon") {
38349 result.push_str("%b"); i += 3;
38351 } else if remaining.starts_with("mm") {
38352 result.push_str("%m");
38353 i += 2;
38354 } else if remaining.starts_with("DD") {
38355 result.push_str("%d");
38356 i += 2;
38357 } else if remaining.starts_with("dy") {
38358 result.push_str("%a"); i += 2;
38360 } else if remaining.starts_with("hh24") {
38361 result.push_str("%H");
38362 i += 4;
38363 } else if remaining.starts_with("hh12") {
38364 result.push_str("%I");
38365 i += 4;
38366 } else if remaining.starts_with("hh") {
38367 result.push_str("%H");
38368 i += 2;
38369 } else if remaining.starts_with("mi") {
38370 result.push_str("%M");
38371 i += 2;
38372 } else if remaining.starts_with("ss") {
38373 result.push_str("%S");
38374 i += 2;
38375 } else if remaining.starts_with("ff") {
38376 result.push_str("%f");
38378 i += 2;
38379 while i < chars.len() && chars[i].is_ascii_digit() {
38381 i += 1;
38382 }
38383 } else if remaining.starts_with("am") || remaining.starts_with("pm") {
38384 result.push_str("%p");
38385 i += 2;
38386 } else if remaining.starts_with("tz") {
38387 result.push_str("%Z");
38388 i += 2;
38389 } else {
38390 result.push(chars[i]);
38391 i += 1;
38392 }
38393 }
38394 result
38395 }
38396
38397 fn snowflake_format_to_spark(format: &str) -> String {
38399 let mut result = String::new();
38400 let chars: Vec<char> = format.chars().collect();
38401 let mut i = 0;
38402 while i < chars.len() {
38403 let remaining = &format[i..];
38404 if remaining.starts_with("yyyy") {
38405 result.push_str("yyyy");
38406 i += 4;
38407 } else if remaining.starts_with("yy") {
38408 result.push_str("yy");
38409 i += 2;
38410 } else if remaining.starts_with("mmmm") {
38411 result.push_str("MMMM"); i += 4;
38413 } else if remaining.starts_with("mon") {
38414 result.push_str("MMM"); i += 3;
38416 } else if remaining.starts_with("mm") {
38417 result.push('M');
38418 i += 2;
38419 } else if remaining.starts_with("DD") {
38420 result.push('d');
38421 i += 2;
38422 } else if remaining.starts_with("dy") {
38423 result.push_str("EEE"); i += 2;
38425 } else if remaining.starts_with("hh24") {
38426 result.push('H');
38427 i += 4;
38428 } else if remaining.starts_with("hh12") {
38429 result.push('h');
38430 i += 4;
38431 } else if remaining.starts_with("hh") {
38432 result.push_str("HH");
38433 i += 2;
38434 } else if remaining.starts_with("mi") {
38435 result.push('m');
38436 i += 2;
38437 } else if remaining.starts_with("ss") {
38438 result.push('s');
38439 i += 2;
38440 } else if remaining.starts_with("ff") {
38441 result.push_str("SSS"); i += 2;
38443 while i < chars.len() && chars[i].is_ascii_digit() {
38445 i += 1;
38446 }
38447 } else if remaining.starts_with("am") || remaining.starts_with("pm") {
38448 result.push_str("a");
38449 i += 2;
38450 } else if remaining.starts_with("tz") {
38451 result.push_str("z");
38452 i += 2;
38453 } else {
38454 result.push(chars[i]);
38455 i += 1;
38456 }
38457 }
38458 result
38459 }
38460
38461 fn generate_str_to_unix(&mut self, e: &StrToUnix) -> Result<()> {
38462 match self.config.dialect {
38463 Some(DialectType::DuckDB) => {
38464 self.write_keyword("EPOCH");
38466 self.write("(");
38467 self.write_keyword("STRPTIME");
38468 self.write("(");
38469 if let Some(this) = &e.this {
38470 self.generate_expression(this)?;
38471 }
38472 if let Some(format) = &e.format {
38473 self.write(", '");
38474 self.write(format);
38475 self.write("'");
38476 }
38477 self.write("))");
38478 }
38479 Some(DialectType::Hive) => {
38480 self.write_keyword("UNIX_TIMESTAMP");
38482 self.write("(");
38483 if let Some(this) = &e.this {
38484 self.generate_expression(this)?;
38485 }
38486 if let Some(format) = &e.format {
38487 let java_fmt = Self::strftime_to_java_format_non_padded(format);
38488 if java_fmt != "yyyy-MM-dd HH:mm:ss" {
38489 self.write(", '");
38490 self.write(&java_fmt);
38491 self.write("'");
38492 }
38493 }
38494 self.write(")");
38495 }
38496 Some(DialectType::Doris) | Some(DialectType::StarRocks) => {
38497 self.write_keyword("UNIX_TIMESTAMP");
38499 self.write("(");
38500 if let Some(this) = &e.this {
38501 self.generate_expression(this)?;
38502 }
38503 if let Some(format) = &e.format {
38504 self.write(", '");
38505 self.write(format);
38506 self.write("'");
38507 }
38508 self.write(")");
38509 }
38510 Some(DialectType::Presto) | Some(DialectType::Trino) => {
38511 let c_fmt = e.format.as_deref().unwrap_or("%Y-%m-%d %T");
38514 let java_fmt = Self::strftime_to_java_format(c_fmt);
38515 self.write_keyword("TO_UNIXTIME");
38516 self.write("(");
38517 self.write_keyword("COALESCE");
38518 self.write("(");
38519 self.write_keyword("TRY");
38520 self.write("(");
38521 self.write_keyword("DATE_PARSE");
38522 self.write("(");
38523 self.write_keyword("CAST");
38524 self.write("(");
38525 if let Some(this) = &e.this {
38526 self.generate_expression(this)?;
38527 }
38528 self.write(" ");
38529 self.write_keyword("AS VARCHAR");
38530 self.write("), '");
38531 self.write(c_fmt);
38532 self.write("')), ");
38533 self.write_keyword("PARSE_DATETIME");
38534 self.write("(");
38535 self.write_keyword("DATE_FORMAT");
38536 self.write("(");
38537 self.write_keyword("CAST");
38538 self.write("(");
38539 if let Some(this) = &e.this {
38540 self.generate_expression(this)?;
38541 }
38542 self.write(" ");
38543 self.write_keyword("AS TIMESTAMP");
38544 self.write("), '");
38545 self.write(c_fmt);
38546 self.write("'), '");
38547 self.write(&java_fmt);
38548 self.write("')))");
38549 }
38550 Some(DialectType::Spark) | Some(DialectType::Databricks) => {
38551 self.write_keyword("UNIX_TIMESTAMP");
38553 self.write("(");
38554 if let Some(this) = &e.this {
38555 self.generate_expression(this)?;
38556 }
38557 if let Some(format) = &e.format {
38558 let java_fmt = Self::strftime_to_java_format_non_padded(format);
38559 self.write(", '");
38560 self.write(&java_fmt);
38561 self.write("'");
38562 }
38563 self.write(")");
38564 }
38565 _ => {
38566 self.write_keyword("STR_TO_UNIX");
38568 self.write("(");
38569 if let Some(this) = &e.this {
38570 self.generate_expression(this)?;
38571 }
38572 if let Some(format) = &e.format {
38573 self.write(", '");
38574 self.write(format);
38575 self.write("'");
38576 }
38577 self.write(")");
38578 }
38579 }
38580 Ok(())
38581 }
38582
38583 fn generate_string_to_array(&mut self, e: &StringToArray) -> Result<()> {
38584 self.write_keyword("STRING_TO_ARRAY");
38586 self.write("(");
38587 self.generate_expression(&e.this)?;
38588 if let Some(expression) = &e.expression {
38589 self.write(", ");
38590 self.generate_expression(expression)?;
38591 }
38592 if let Some(null_val) = &e.null {
38593 self.write(", ");
38594 self.generate_expression(null_val)?;
38595 }
38596 self.write(")");
38597 Ok(())
38598 }
38599
38600 fn generate_struct(&mut self, e: &Struct) -> Result<()> {
38601 if matches!(self.config.dialect, Some(DialectType::Snowflake)) {
38602 self.write_keyword("OBJECT_CONSTRUCT");
38604 self.write("(");
38605 for (i, (name, expr)) in e.fields.iter().enumerate() {
38606 if i > 0 {
38607 self.write(", ");
38608 }
38609 if let Some(name) = name {
38610 self.write("'");
38611 self.write(name);
38612 self.write("'");
38613 self.write(", ");
38614 } else {
38615 self.write("'_");
38616 self.write(&i.to_string());
38617 self.write("'");
38618 self.write(", ");
38619 }
38620 self.generate_expression(expr)?;
38621 }
38622 self.write(")");
38623 } else if self.config.struct_curly_brace_notation {
38624 self.write("{");
38626 for (i, (name, expr)) in e.fields.iter().enumerate() {
38627 if i > 0 {
38628 self.write(", ");
38629 }
38630 if let Some(name) = name {
38631 self.write("'");
38633 self.write(name);
38634 self.write("'");
38635 self.write(": ");
38636 } else {
38637 self.write("'_");
38639 self.write(&i.to_string());
38640 self.write("'");
38641 self.write(": ");
38642 }
38643 self.generate_expression(expr)?;
38644 }
38645 self.write("}");
38646 } else {
38647 let value_as_name = matches!(
38651 self.config.dialect,
38652 Some(DialectType::BigQuery)
38653 | Some(DialectType::Spark)
38654 | Some(DialectType::Databricks)
38655 | Some(DialectType::Hive)
38656 );
38657 self.write_keyword("STRUCT");
38658 self.write("(");
38659 for (i, (name, expr)) in e.fields.iter().enumerate() {
38660 if i > 0 {
38661 self.write(", ");
38662 }
38663 if let Some(name) = name {
38664 if value_as_name {
38665 self.generate_expression(expr)?;
38667 self.write_space();
38668 self.write_keyword("AS");
38669 self.write_space();
38670 let needs_quoting = name.contains(' ') || name.contains('-');
38672 if needs_quoting {
38673 if matches!(
38674 self.config.dialect,
38675 Some(DialectType::Spark)
38676 | Some(DialectType::Databricks)
38677 | Some(DialectType::Hive)
38678 ) {
38679 self.write("`");
38680 self.write(name);
38681 self.write("`");
38682 } else {
38683 self.write(name);
38684 }
38685 } else {
38686 self.write(name);
38687 }
38688 } else {
38689 self.write(name);
38691 self.write_space();
38692 self.write_keyword("AS");
38693 self.write_space();
38694 self.generate_expression(expr)?;
38695 }
38696 } else {
38697 self.generate_expression(expr)?;
38698 }
38699 }
38700 self.write(")");
38701 }
38702 Ok(())
38703 }
38704
38705 fn generate_stuff(&mut self, e: &Stuff) -> Result<()> {
38706 self.write_keyword("STUFF");
38708 self.write("(");
38709 self.generate_expression(&e.this)?;
38710 if let Some(start) = &e.start {
38711 self.write(", ");
38712 self.generate_expression(start)?;
38713 }
38714 if let Some(length) = e.length {
38715 self.write(", ");
38716 self.write(&length.to_string());
38717 }
38718 self.write(", ");
38719 self.generate_expression(&e.expression)?;
38720 self.write(")");
38721 Ok(())
38722 }
38723
38724 fn generate_substring_index(&mut self, e: &SubstringIndex) -> Result<()> {
38725 self.write_keyword("SUBSTRING_INDEX");
38727 self.write("(");
38728 self.generate_expression(&e.this)?;
38729 if let Some(delimiter) = &e.delimiter {
38730 self.write(", ");
38731 self.generate_expression(delimiter)?;
38732 }
38733 if let Some(count) = &e.count {
38734 self.write(", ");
38735 self.generate_expression(count)?;
38736 }
38737 self.write(")");
38738 Ok(())
38739 }
38740
38741 fn generate_summarize(&mut self, e: &Summarize) -> Result<()> {
38742 self.write_keyword("SUMMARIZE");
38744 if e.table.is_some() {
38745 self.write_space();
38746 self.write_keyword("TABLE");
38747 }
38748 self.write_space();
38749 self.generate_expression(&e.this)?;
38750 Ok(())
38751 }
38752
38753 fn generate_systimestamp(&mut self, _e: &Systimestamp) -> Result<()> {
38754 self.write_keyword("SYSTIMESTAMP");
38756 Ok(())
38757 }
38758
38759 fn generate_table_alias(&mut self, e: &TableAlias) -> Result<()> {
38760 if let Some(this) = &e.this {
38762 self.generate_expression(this)?;
38763 }
38764 if !e.columns.is_empty() {
38765 self.write("(");
38766 for (i, col) in e.columns.iter().enumerate() {
38767 if i > 0 {
38768 self.write(", ");
38769 }
38770 self.generate_expression(col)?;
38771 }
38772 self.write(")");
38773 }
38774 Ok(())
38775 }
38776
38777 fn generate_table_from_rows(&mut self, e: &TableFromRows) -> Result<()> {
38778 self.write_keyword("TABLE");
38780 self.write("(");
38781 self.generate_expression(&e.this)?;
38782 self.write(")");
38783 if let Some(alias) = &e.alias {
38784 self.write_space();
38785 self.write_keyword("AS");
38786 self.write_space();
38787 self.write(alias);
38788 }
38789 Ok(())
38790 }
38791
38792 fn generate_rows_from(&mut self, e: &RowsFrom) -> Result<()> {
38793 self.write_keyword("ROWS FROM");
38795 self.write(" (");
38796 for (i, expr) in e.expressions.iter().enumerate() {
38797 if i > 0 {
38798 self.write(", ");
38799 }
38800 match expr {
38804 Expression::Tuple(tuple) if tuple.expressions.len() == 2 => {
38805 self.generate_expression(&tuple.expressions[0])?;
38807 self.write_space();
38808 self.write_keyword("AS");
38809 self.write_space();
38810 self.generate_expression(&tuple.expressions[1])?;
38811 }
38812 _ => {
38813 self.generate_expression(expr)?;
38814 }
38815 }
38816 }
38817 self.write(")");
38818 if e.ordinality {
38819 self.write_space();
38820 self.write_keyword("WITH ORDINALITY");
38821 }
38822 if let Some(alias) = &e.alias {
38823 self.write_space();
38824 self.write_keyword("AS");
38825 self.write_space();
38826 self.generate_expression(alias)?;
38827 }
38828 Ok(())
38829 }
38830
38831 fn generate_table_sample(&mut self, e: &TableSample) -> Result<()> {
38832 use crate::dialects::DialectType;
38833
38834 if let (Some(this), Some(sample)) = (&e.this, &e.sample) {
38836 if self.config.alias_post_tablesample {
38838 if let Expression::Subquery(ref s) = **this {
38840 if let Some(ref alias) = s.alias {
38841 let mut subquery_no_alias = (**s).clone();
38843 subquery_no_alias.alias = None;
38844 subquery_no_alias.column_aliases = Vec::new();
38845 self.generate_expression(&Expression::Subquery(Box::new(
38846 subquery_no_alias,
38847 )))?;
38848 self.write_space();
38849 self.write_keyword(self.config.tablesample_keywords);
38850 self.generate_sample_body(sample)?;
38851 if let Some(ref seed) = sample.seed {
38852 self.write_space();
38853 let use_seed = sample.use_seed_keyword
38854 && !matches!(
38855 self.config.dialect,
38856 Some(crate::dialects::DialectType::Databricks)
38857 | Some(crate::dialects::DialectType::Spark)
38858 );
38859 if use_seed {
38860 self.write_keyword("SEED");
38861 } else {
38862 self.write_keyword("REPEATABLE");
38863 }
38864 self.write(" (");
38865 self.generate_expression(seed)?;
38866 self.write(")");
38867 }
38868 self.write_space();
38869 self.write_keyword("AS");
38870 self.write_space();
38871 self.generate_identifier(alias)?;
38872 return Ok(());
38873 }
38874 } else if let Expression::Alias(ref a) = **this {
38875 self.generate_expression(&a.this)?;
38877 self.write_space();
38878 self.write_keyword(self.config.tablesample_keywords);
38879 self.generate_sample_body(sample)?;
38880 if let Some(ref seed) = sample.seed {
38881 self.write_space();
38882 let use_seed = sample.use_seed_keyword
38883 && !matches!(
38884 self.config.dialect,
38885 Some(crate::dialects::DialectType::Databricks)
38886 | Some(crate::dialects::DialectType::Spark)
38887 );
38888 if use_seed {
38889 self.write_keyword("SEED");
38890 } else {
38891 self.write_keyword("REPEATABLE");
38892 }
38893 self.write(" (");
38894 self.generate_expression(seed)?;
38895 self.write(")");
38896 }
38897 self.write_space();
38899 self.write_keyword("AS");
38900 self.write_space();
38901 self.generate_identifier(&a.alias)?;
38902 return Ok(());
38903 }
38904 }
38905 self.generate_expression(this)?;
38907 self.write_space();
38908 self.write_keyword(self.config.tablesample_keywords);
38909 self.generate_sample_body(sample)?;
38910 if let Some(ref seed) = sample.seed {
38912 self.write_space();
38913 let use_seed = sample.use_seed_keyword
38915 && !matches!(
38916 self.config.dialect,
38917 Some(crate::dialects::DialectType::Databricks)
38918 | Some(crate::dialects::DialectType::Spark)
38919 );
38920 if use_seed {
38921 self.write_keyword("SEED");
38922 } else {
38923 self.write_keyword("REPEATABLE");
38924 }
38925 self.write(" (");
38926 self.generate_expression(seed)?;
38927 self.write(")");
38928 }
38929 return Ok(());
38930 }
38931
38932 self.write_keyword(self.config.tablesample_keywords);
38934 if let Some(method) = &e.method {
38935 self.write_space();
38936 self.write_keyword(method);
38937 } else if matches!(self.config.dialect, Some(DialectType::Snowflake)) {
38938 self.write_space();
38940 self.write_keyword("BERNOULLI");
38941 }
38942 if let (Some(numerator), Some(denominator)) = (&e.bucket_numerator, &e.bucket_denominator) {
38943 self.write_space();
38944 self.write_keyword("BUCKET");
38945 self.write_space();
38946 self.generate_expression(numerator)?;
38947 self.write_space();
38948 self.write_keyword("OUT OF");
38949 self.write_space();
38950 self.generate_expression(denominator)?;
38951 if let Some(field) = &e.bucket_field {
38952 self.write_space();
38953 self.write_keyword("ON");
38954 self.write_space();
38955 self.generate_expression(field)?;
38956 }
38957 } else if !e.expressions.is_empty() {
38958 self.write(" (");
38959 for (i, expr) in e.expressions.iter().enumerate() {
38960 if i > 0 {
38961 self.write(", ");
38962 }
38963 self.generate_expression(expr)?;
38964 }
38965 self.write(")");
38966 } else if let Some(percent) = &e.percent {
38967 self.write(" (");
38968 self.generate_expression(percent)?;
38969 self.write_space();
38970 self.write_keyword("PERCENT");
38971 self.write(")");
38972 }
38973 Ok(())
38974 }
38975
38976 fn generate_tag(&mut self, e: &Tag) -> Result<()> {
38977 if let Some(prefix) = &e.prefix {
38979 self.generate_expression(prefix)?;
38980 }
38981 if let Some(this) = &e.this {
38982 self.generate_expression(this)?;
38983 }
38984 if let Some(postfix) = &e.postfix {
38985 self.generate_expression(postfix)?;
38986 }
38987 Ok(())
38988 }
38989
38990 fn generate_tags(&mut self, e: &Tags) -> Result<()> {
38991 self.write_keyword("TAG");
38993 self.write(" (");
38994 for (i, expr) in e.expressions.iter().enumerate() {
38995 if i > 0 {
38996 self.write(", ");
38997 }
38998 self.generate_expression(expr)?;
38999 }
39000 self.write(")");
39001 Ok(())
39002 }
39003
39004 fn generate_temporary_property(&mut self, e: &TemporaryProperty) -> Result<()> {
39005 if let Some(this) = &e.this {
39007 self.generate_expression(this)?;
39008 self.write_space();
39009 }
39010 self.write_keyword("TEMPORARY");
39011 Ok(())
39012 }
39013
39014 fn generate_time_func(&mut self, e: &UnaryFunc) -> Result<()> {
39017 self.write_keyword("TIME");
39019 self.write("(");
39020 self.generate_expression(&e.this)?;
39021 self.write(")");
39022 Ok(())
39023 }
39024
39025 fn generate_time_add(&mut self, e: &TimeAdd) -> Result<()> {
39026 self.write_keyword("TIME_ADD");
39028 self.write("(");
39029 self.generate_expression(&e.this)?;
39030 self.write(", ");
39031 self.generate_expression(&e.expression)?;
39032 if let Some(unit) = &e.unit {
39033 self.write(", ");
39034 self.write_keyword(unit);
39035 }
39036 self.write(")");
39037 Ok(())
39038 }
39039
39040 fn generate_time_diff(&mut self, e: &TimeDiff) -> Result<()> {
39041 self.write_keyword("TIME_DIFF");
39043 self.write("(");
39044 self.generate_expression(&e.this)?;
39045 self.write(", ");
39046 self.generate_expression(&e.expression)?;
39047 if let Some(unit) = &e.unit {
39048 self.write(", ");
39049 self.write_keyword(unit);
39050 }
39051 self.write(")");
39052 Ok(())
39053 }
39054
39055 fn generate_time_from_parts(&mut self, e: &TimeFromParts) -> Result<()> {
39056 self.write_keyword("TIME_FROM_PARTS");
39058 self.write("(");
39059 let mut first = true;
39060 if let Some(hour) = &e.hour {
39061 self.generate_expression(hour)?;
39062 first = false;
39063 }
39064 if let Some(minute) = &e.min {
39065 if !first {
39066 self.write(", ");
39067 }
39068 self.generate_expression(minute)?;
39069 first = false;
39070 }
39071 if let Some(second) = &e.sec {
39072 if !first {
39073 self.write(", ");
39074 }
39075 self.generate_expression(second)?;
39076 first = false;
39077 }
39078 if let Some(ns) = &e.nano {
39079 if !first {
39080 self.write(", ");
39081 }
39082 self.generate_expression(ns)?;
39083 }
39084 self.write(")");
39085 Ok(())
39086 }
39087
39088 fn generate_time_slice(&mut self, e: &TimeSlice) -> Result<()> {
39089 self.write_keyword("TIME_SLICE");
39091 self.write("(");
39092 self.generate_expression(&e.this)?;
39093 self.write(", ");
39094 self.generate_expression(&e.expression)?;
39095 self.write(", ");
39096 self.write_keyword(&e.unit);
39097 self.write(")");
39098 Ok(())
39099 }
39100
39101 fn generate_time_str_to_time(&mut self, e: &TimeStrToTime) -> Result<()> {
39102 self.write_keyword("TIME_STR_TO_TIME");
39104 self.write("(");
39105 self.generate_expression(&e.this)?;
39106 self.write(")");
39107 Ok(())
39108 }
39109
39110 fn generate_time_sub(&mut self, e: &TimeSub) -> Result<()> {
39111 self.write_keyword("TIME_SUB");
39113 self.write("(");
39114 self.generate_expression(&e.this)?;
39115 self.write(", ");
39116 self.generate_expression(&e.expression)?;
39117 if let Some(unit) = &e.unit {
39118 self.write(", ");
39119 self.write_keyword(unit);
39120 }
39121 self.write(")");
39122 Ok(())
39123 }
39124
39125 fn generate_time_to_str(&mut self, e: &TimeToStr) -> Result<()> {
39126 match self.config.dialect {
39127 Some(DialectType::Exasol) => {
39128 self.write_keyword("TO_CHAR");
39130 self.write("(");
39131 self.generate_expression(&e.this)?;
39132 self.write(", '");
39133 self.write(&Self::convert_strptime_to_exasol_format(&e.format));
39134 self.write("'");
39135 self.write(")");
39136 }
39137 Some(DialectType::PostgreSQL)
39138 | Some(DialectType::Redshift)
39139 | Some(DialectType::Materialize) => {
39140 self.write_keyword("TO_CHAR");
39142 self.write("(");
39143 self.generate_expression(&e.this)?;
39144 self.write(", '");
39145 self.write(&Self::convert_strptime_to_postgres_format(&e.format));
39146 self.write("'");
39147 self.write(")");
39148 }
39149 Some(DialectType::Oracle) => {
39150 self.write_keyword("TO_CHAR");
39152 self.write("(");
39153 self.generate_expression(&e.this)?;
39154 self.write(", '");
39155 self.write(&Self::convert_strptime_to_postgres_format(&e.format));
39156 self.write("'");
39157 self.write(")");
39158 }
39159 Some(DialectType::Drill) => {
39160 self.write_keyword("TO_CHAR");
39162 self.write("(");
39163 self.generate_expression(&e.this)?;
39164 self.write(", '");
39165 self.write(&Self::strftime_to_java_format(&e.format));
39166 self.write("'");
39167 self.write(")");
39168 }
39169 Some(DialectType::TSQL) | Some(DialectType::Fabric) => {
39170 self.write_keyword("FORMAT");
39172 self.write("(");
39173 self.generate_expression(&e.this)?;
39174 self.write(", '");
39175 self.write(&Self::strftime_to_tsql_format(&e.format));
39176 self.write("'");
39177 if let Some(culture) = &e.culture {
39178 self.write(", ");
39179 self.generate_expression(culture)?;
39180 }
39181 self.write(")");
39182 }
39183 Some(DialectType::DuckDB) => {
39184 self.write_keyword("STRFTIME");
39186 self.write("(");
39187 self.generate_expression(&e.this)?;
39188 self.write(", '");
39189 self.write(&e.format);
39190 self.write("'");
39191 self.write(")");
39192 }
39193 Some(DialectType::BigQuery) => {
39194 self.write_keyword("FORMAT_DATE");
39196 self.write("('");
39197 self.write(&e.format);
39198 self.write("', ");
39199 self.generate_expression(&e.this)?;
39200 self.write(")");
39201 }
39202 Some(DialectType::Hive) | Some(DialectType::Spark) | Some(DialectType::Databricks) => {
39203 self.write_keyword("DATE_FORMAT");
39205 self.write("(");
39206 self.generate_expression(&e.this)?;
39207 self.write(", '");
39208 self.write(&Self::strftime_to_java_format(&e.format));
39209 self.write("'");
39210 self.write(")");
39211 }
39212 Some(DialectType::Presto) | Some(DialectType::Trino) | Some(DialectType::Athena) => {
39213 self.write_keyword("DATE_FORMAT");
39215 self.write("(");
39216 self.generate_expression(&e.this)?;
39217 self.write(", '");
39218 self.write(&e.format);
39219 self.write("'");
39220 self.write(")");
39221 }
39222 Some(DialectType::Doris) | Some(DialectType::StarRocks) => {
39223 self.write_keyword("DATE_FORMAT");
39225 self.write("(");
39226 self.generate_expression(&e.this)?;
39227 self.write(", '");
39228 self.write(&e.format);
39229 self.write("'");
39230 self.write(")");
39231 }
39232 _ => {
39233 self.write_keyword("TIME_TO_STR");
39235 self.write("(");
39236 self.generate_expression(&e.this)?;
39237 self.write(", '");
39238 self.write(&e.format);
39239 self.write("'");
39240 self.write(")");
39241 }
39242 }
39243 Ok(())
39244 }
39245
39246 fn generate_time_to_unix(&mut self, e: &crate::expressions::UnaryFunc) -> Result<()> {
39247 match self.config.dialect {
39248 Some(DialectType::DuckDB) => {
39249 self.write_keyword("EPOCH");
39251 self.write("(");
39252 self.generate_expression(&e.this)?;
39253 self.write(")");
39254 }
39255 Some(DialectType::Hive)
39256 | Some(DialectType::Spark)
39257 | Some(DialectType::Databricks)
39258 | Some(DialectType::Doris)
39259 | Some(DialectType::StarRocks)
39260 | Some(DialectType::Drill) => {
39261 self.write_keyword("UNIX_TIMESTAMP");
39263 self.write("(");
39264 self.generate_expression(&e.this)?;
39265 self.write(")");
39266 }
39267 Some(DialectType::Presto) | Some(DialectType::Trino) => {
39268 self.write_keyword("TO_UNIXTIME");
39270 self.write("(");
39271 self.generate_expression(&e.this)?;
39272 self.write(")");
39273 }
39274 _ => {
39275 self.write_keyword("TIME_TO_UNIX");
39277 self.write("(");
39278 self.generate_expression(&e.this)?;
39279 self.write(")");
39280 }
39281 }
39282 Ok(())
39283 }
39284
39285 fn generate_time_str_to_date(&mut self, e: &crate::expressions::UnaryFunc) -> Result<()> {
39286 match self.config.dialect {
39287 Some(DialectType::Hive) => {
39288 self.write_keyword("TO_DATE");
39290 self.write("(");
39291 self.generate_expression(&e.this)?;
39292 self.write(")");
39293 }
39294 _ => {
39295 self.write_keyword("TIME_STR_TO_DATE");
39297 self.write("(");
39298 self.generate_expression(&e.this)?;
39299 self.write(")");
39300 }
39301 }
39302 Ok(())
39303 }
39304
39305 fn generate_time_trunc(&mut self, e: &TimeTrunc) -> Result<()> {
39306 self.write_keyword("TIME_TRUNC");
39308 self.write("(");
39309 self.generate_expression(&e.this)?;
39310 self.write(", ");
39311 self.write_keyword(&e.unit);
39312 self.write(")");
39313 Ok(())
39314 }
39315
39316 fn generate_time_unit(&mut self, e: &TimeUnit) -> Result<()> {
39317 if let Some(unit) = &e.unit {
39319 self.write_keyword(unit);
39320 }
39321 Ok(())
39322 }
39323
39324 fn generate_timestamp_func(&mut self, e: &TimestampFunc) -> Result<()> {
39328 use crate::dialects::DialectType;
39329 use crate::expressions::Literal;
39330
39331 match self.config.dialect {
39332 Some(DialectType::Exasol) => {
39334 self.write_keyword("TO_TIMESTAMP");
39335 self.write("(");
39336 if let Some(this) = &e.this {
39338 match this.as_ref() {
39339 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
39340 let Literal::String(s) = lit.as_ref() else {
39341 unreachable!()
39342 };
39343 self.write("'");
39344 self.write(s);
39345 self.write("'");
39346 }
39347 _ => {
39348 self.generate_expression(this)?;
39349 }
39350 }
39351 }
39352 self.write(")");
39353 }
39354 _ => {
39356 self.write_keyword("TIMESTAMP");
39357 self.write("(");
39358 if let Some(this) = &e.this {
39359 self.generate_expression(this)?;
39360 }
39361 if let Some(zone) = &e.zone {
39362 self.write(", ");
39363 self.generate_expression(zone)?;
39364 }
39365 self.write(")");
39366 }
39367 }
39368 Ok(())
39369 }
39370
39371 fn generate_timestamp_add(&mut self, e: &TimestampAdd) -> Result<()> {
39372 self.write_keyword("TIMESTAMP_ADD");
39374 self.write("(");
39375 self.generate_expression(&e.this)?;
39376 self.write(", ");
39377 self.generate_expression(&e.expression)?;
39378 if let Some(unit) = &e.unit {
39379 self.write(", ");
39380 self.write_keyword(unit);
39381 }
39382 self.write(")");
39383 Ok(())
39384 }
39385
39386 fn generate_timestamp_diff(&mut self, e: &TimestampDiff) -> Result<()> {
39387 self.write_keyword("TIMESTAMP_DIFF");
39389 self.write("(");
39390 self.generate_expression(&e.this)?;
39391 self.write(", ");
39392 self.generate_expression(&e.expression)?;
39393 if let Some(unit) = &e.unit {
39394 self.write(", ");
39395 self.write_keyword(unit);
39396 }
39397 self.write(")");
39398 Ok(())
39399 }
39400
39401 fn generate_timestamp_from_parts(&mut self, e: &TimestampFromParts) -> Result<()> {
39402 self.write_keyword("TIMESTAMP_FROM_PARTS");
39404 self.write("(");
39405 if let Some(this) = &e.this {
39406 self.generate_expression(this)?;
39407 }
39408 if let Some(expression) = &e.expression {
39409 self.write(", ");
39410 self.generate_expression(expression)?;
39411 }
39412 if let Some(zone) = &e.zone {
39413 self.write(", ");
39414 self.generate_expression(zone)?;
39415 }
39416 if let Some(milli) = &e.milli {
39417 self.write(", ");
39418 self.generate_expression(milli)?;
39419 }
39420 self.write(")");
39421 Ok(())
39422 }
39423
39424 fn generate_timestamp_sub(&mut self, e: &TimestampSub) -> Result<()> {
39425 self.write_keyword("TIMESTAMP_SUB");
39427 self.write("(");
39428 self.generate_expression(&e.this)?;
39429 self.write(", ");
39430 self.write_keyword("INTERVAL");
39431 self.write_space();
39432 self.generate_expression(&e.expression)?;
39433 if let Some(unit) = &e.unit {
39434 self.write_space();
39435 self.write_keyword(unit);
39436 }
39437 self.write(")");
39438 Ok(())
39439 }
39440
39441 fn generate_timestamp_tz_from_parts(&mut self, e: &TimestampTzFromParts) -> Result<()> {
39442 self.write_keyword("TIMESTAMP_TZ_FROM_PARTS");
39444 self.write("(");
39445 if let Some(zone) = &e.zone {
39446 self.generate_expression(zone)?;
39447 }
39448 self.write(")");
39449 Ok(())
39450 }
39451
39452 fn generate_to_binary(&mut self, e: &ToBinary) -> Result<()> {
39453 self.write_keyword("TO_BINARY");
39455 self.write("(");
39456 self.generate_expression(&e.this)?;
39457 if let Some(format) = &e.format {
39458 self.write(", '");
39459 self.write(format);
39460 self.write("'");
39461 }
39462 self.write(")");
39463 Ok(())
39464 }
39465
39466 fn generate_to_boolean(&mut self, e: &ToBoolean) -> Result<()> {
39467 self.write_keyword("TO_BOOLEAN");
39469 self.write("(");
39470 self.generate_expression(&e.this)?;
39471 self.write(")");
39472 Ok(())
39473 }
39474
39475 fn generate_to_char(&mut self, e: &ToChar) -> Result<()> {
39476 self.write_keyword("TO_CHAR");
39478 self.write("(");
39479 self.generate_expression(&e.this)?;
39480 if let Some(format) = &e.format {
39481 self.write(", '");
39482 self.write(format);
39483 self.write("'");
39484 }
39485 if let Some(nlsparam) = &e.nlsparam {
39486 self.write(", ");
39487 self.generate_expression(nlsparam)?;
39488 }
39489 self.write(")");
39490 Ok(())
39491 }
39492
39493 fn generate_to_decfloat(&mut self, e: &ToDecfloat) -> Result<()> {
39494 self.write_keyword("TO_DECFLOAT");
39496 self.write("(");
39497 self.generate_expression(&e.this)?;
39498 if let Some(format) = &e.format {
39499 self.write(", '");
39500 self.write(format);
39501 self.write("'");
39502 }
39503 self.write(")");
39504 Ok(())
39505 }
39506
39507 fn generate_to_double(&mut self, e: &ToDouble) -> Result<()> {
39508 self.write_keyword("TO_DOUBLE");
39510 self.write("(");
39511 self.generate_expression(&e.this)?;
39512 if let Some(format) = &e.format {
39513 self.write(", '");
39514 self.write(format);
39515 self.write("'");
39516 }
39517 self.write(")");
39518 Ok(())
39519 }
39520
39521 fn generate_to_file(&mut self, e: &ToFile) -> Result<()> {
39522 self.write_keyword("TO_FILE");
39524 self.write("(");
39525 self.generate_expression(&e.this)?;
39526 if let Some(path) = &e.path {
39527 self.write(", ");
39528 self.generate_expression(path)?;
39529 }
39530 self.write(")");
39531 Ok(())
39532 }
39533
39534 fn generate_to_number(&mut self, e: &ToNumber) -> Result<()> {
39535 let is_safe = e.safe.is_some();
39538 if is_safe {
39539 self.write_keyword("TRY_TO_NUMBER");
39540 } else {
39541 self.write_keyword("TO_NUMBER");
39542 }
39543 self.write("(");
39544 self.generate_expression(&e.this)?;
39545 let precision_is_snowflake_default = e.precision.is_none()
39546 || matches!(
39547 e.precision.as_deref(),
39548 Some(Expression::Literal(lit))
39549 if matches!(lit.as_ref(), Literal::Number(n) if n == "0")
39550 );
39551 let is_snowflake_default_precision =
39552 matches!(self.config.dialect, Some(DialectType::Snowflake))
39553 && e.nlsparam.is_none()
39554 && e.scale.is_none()
39555 && matches!(
39556 e.format.as_deref(),
39557 Some(Expression::Literal(lit))
39558 if matches!(lit.as_ref(), Literal::Number(n) if n == "38")
39559 )
39560 && precision_is_snowflake_default;
39561
39562 if !is_snowflake_default_precision {
39563 if let Some(format) = &e.format {
39564 self.write(", ");
39565 self.generate_expression(format)?;
39566 }
39567 if let Some(nlsparam) = &e.nlsparam {
39568 self.write(", ");
39569 self.generate_expression(nlsparam)?;
39570 }
39571 if let Some(precision) = &e.precision {
39572 self.write(", ");
39573 self.generate_expression(precision)?;
39574 }
39575 if let Some(scale) = &e.scale {
39576 self.write(", ");
39577 self.generate_expression(scale)?;
39578 }
39579 }
39580 self.write(")");
39581 Ok(())
39582 }
39583
39584 fn generate_to_table_property(&mut self, e: &ToTableProperty) -> Result<()> {
39585 self.write_keyword("TO_TABLE");
39587 self.write_space();
39588 self.generate_expression(&e.this)?;
39589 Ok(())
39590 }
39591
39592 fn generate_transaction(&mut self, e: &Transaction) -> Result<()> {
39593 let mark_text = e.mark.as_ref().map(|m| match m.as_ref() {
39595 Expression::Identifier(id) => id.name.clone(),
39596 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
39597 let Literal::String(s) = lit.as_ref() else {
39598 unreachable!()
39599 };
39600 s.clone()
39601 }
39602 _ => String::new(),
39603 });
39604
39605 let is_start = mark_text.as_ref().map_or(false, |s| s == "START");
39606 let has_transaction_keyword = mark_text.as_ref().map_or(false, |s| s == "TRANSACTION");
39607 let has_with_mark = e.mark.as_ref().map_or(false, |m| {
39608 matches!(m.as_ref(), Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)))
39609 });
39610
39611 let use_start_transaction = matches!(
39613 self.config.dialect,
39614 Some(DialectType::Presto) | Some(DialectType::Trino) | Some(DialectType::Athena)
39615 );
39616 let strip_transaction = matches!(
39618 self.config.dialect,
39619 Some(DialectType::Snowflake)
39620 | Some(DialectType::PostgreSQL)
39621 | Some(DialectType::Redshift)
39622 | Some(DialectType::MySQL)
39623 | Some(DialectType::Hive)
39624 | Some(DialectType::Spark)
39625 | Some(DialectType::Databricks)
39626 | Some(DialectType::DuckDB)
39627 | Some(DialectType::Oracle)
39628 | Some(DialectType::Doris)
39629 | Some(DialectType::StarRocks)
39630 | Some(DialectType::Materialize)
39631 | Some(DialectType::ClickHouse)
39632 );
39633
39634 if is_start || use_start_transaction {
39635 self.write_keyword("START TRANSACTION");
39637 if let Some(modes) = &e.modes {
39638 self.write_space();
39639 self.generate_expression(modes)?;
39640 }
39641 } else {
39642 self.write_keyword("BEGIN");
39644
39645 let is_kind = e.this.as_ref().map_or(false, |t| {
39647 if let Expression::Identifier(id) = t.as_ref() {
39648 id.name.eq_ignore_ascii_case("DEFERRED")
39649 || id.name.eq_ignore_ascii_case("IMMEDIATE")
39650 || id.name.eq_ignore_ascii_case("EXCLUSIVE")
39651 } else {
39652 false
39653 }
39654 });
39655
39656 if is_kind {
39658 if let Some(this) = &e.this {
39659 self.write_space();
39660 if let Expression::Identifier(id) = this.as_ref() {
39661 self.write_keyword(&id.name);
39662 }
39663 }
39664 }
39665
39666 if (has_transaction_keyword || has_with_mark) && !strip_transaction {
39668 self.write_space();
39669 self.write_keyword("TRANSACTION");
39670 }
39671
39672 if !is_kind {
39674 if let Some(this) = &e.this {
39675 self.write_space();
39676 self.generate_expression(this)?;
39677 }
39678 }
39679
39680 if has_with_mark {
39682 self.write_space();
39683 self.write_keyword("WITH MARK");
39684 if let Some(Expression::Literal(lit)) = e.mark.as_deref() {
39685 if let Literal::String(desc) = lit.as_ref() {
39686 if !desc.is_empty() {
39687 self.write_space();
39688 self.write(&format!("'{}'", desc));
39689 }
39690 }
39691 }
39692 }
39693
39694 if let Some(modes) = &e.modes {
39696 self.write_space();
39697 self.generate_expression(modes)?;
39698 }
39699 }
39700 Ok(())
39701 }
39702
39703 fn generate_transform(&mut self, e: &Transform) -> Result<()> {
39704 self.write_keyword("TRANSFORM");
39706 self.write("(");
39707 self.generate_expression(&e.this)?;
39708 self.write(", ");
39709 self.generate_expression(&e.expression)?;
39710 self.write(")");
39711 Ok(())
39712 }
39713
39714 fn generate_transform_model_property(&mut self, e: &TransformModelProperty) -> Result<()> {
39715 self.write_keyword("TRANSFORM");
39717 self.write("(");
39718 if self.config.pretty && !e.expressions.is_empty() {
39719 self.indent_level += 1;
39720 for (i, expr) in e.expressions.iter().enumerate() {
39721 if i > 0 {
39722 self.write(",");
39723 }
39724 self.write_newline();
39725 self.write_indent();
39726 self.generate_expression(expr)?;
39727 }
39728 self.indent_level -= 1;
39729 self.write_newline();
39730 self.write(")");
39731 } else {
39732 for (i, expr) in e.expressions.iter().enumerate() {
39733 if i > 0 {
39734 self.write(", ");
39735 }
39736 self.generate_expression(expr)?;
39737 }
39738 self.write(")");
39739 }
39740 Ok(())
39741 }
39742
39743 fn generate_transient_property(&mut self, e: &TransientProperty) -> Result<()> {
39744 use crate::dialects::DialectType;
39745 if let Some(this) = &e.this {
39747 self.generate_expression(this)?;
39748 if matches!(self.config.dialect, Some(DialectType::Snowflake) | None) {
39749 self.write_space();
39750 }
39751 }
39752 if matches!(self.config.dialect, Some(DialectType::Snowflake) | None) {
39753 self.write_keyword("TRANSIENT");
39754 }
39755 Ok(())
39756 }
39757
39758 fn generate_translate(&mut self, e: &Translate) -> Result<()> {
39759 self.write_keyword("TRANSLATE");
39761 self.write("(");
39762 self.generate_expression(&e.this)?;
39763 if let Some(from) = &e.from_ {
39764 self.write(", ");
39765 self.generate_expression(from)?;
39766 }
39767 if let Some(to) = &e.to {
39768 self.write(", ");
39769 self.generate_expression(to)?;
39770 }
39771 self.write(")");
39772 Ok(())
39773 }
39774
39775 fn generate_translate_characters(&mut self, e: &TranslateCharacters) -> Result<()> {
39776 self.write_keyword("TRANSLATE");
39778 self.write("(");
39779 self.generate_expression(&e.this)?;
39780 self.write_space();
39781 self.write_keyword("USING");
39782 self.write_space();
39783 self.generate_expression(&e.expression)?;
39784 if e.with_error.is_some() {
39785 self.write_space();
39786 self.write_keyword("WITH ERROR");
39787 }
39788 self.write(")");
39789 Ok(())
39790 }
39791
39792 fn generate_truncate_table(&mut self, e: &TruncateTable) -> Result<()> {
39793 self.write_keyword("TRUNCATE TABLE");
39795 self.write_space();
39796 for (i, expr) in e.expressions.iter().enumerate() {
39797 if i > 0 {
39798 self.write(", ");
39799 }
39800 self.generate_expression(expr)?;
39801 }
39802 Ok(())
39803 }
39804
39805 fn generate_try_base64_decode_binary(&mut self, e: &TryBase64DecodeBinary) -> Result<()> {
39806 self.write_keyword("TRY_BASE64_DECODE_BINARY");
39808 self.write("(");
39809 self.generate_expression(&e.this)?;
39810 if let Some(alphabet) = &e.alphabet {
39811 self.write(", ");
39812 self.generate_expression(alphabet)?;
39813 }
39814 self.write(")");
39815 Ok(())
39816 }
39817
39818 fn generate_try_base64_decode_string(&mut self, e: &TryBase64DecodeString) -> Result<()> {
39819 self.write_keyword("TRY_BASE64_DECODE_STRING");
39821 self.write("(");
39822 self.generate_expression(&e.this)?;
39823 if let Some(alphabet) = &e.alphabet {
39824 self.write(", ");
39825 self.generate_expression(alphabet)?;
39826 }
39827 self.write(")");
39828 Ok(())
39829 }
39830
39831 fn generate_try_to_decfloat(&mut self, e: &TryToDecfloat) -> Result<()> {
39832 self.write_keyword("TRY_TO_DECFLOAT");
39834 self.write("(");
39835 self.generate_expression(&e.this)?;
39836 if let Some(format) = &e.format {
39837 self.write(", '");
39838 self.write(format);
39839 self.write("'");
39840 }
39841 self.write(")");
39842 Ok(())
39843 }
39844
39845 fn generate_ts_or_ds_add(&mut self, e: &TsOrDsAdd) -> Result<()> {
39846 self.write_keyword("TS_OR_DS_ADD");
39848 self.write("(");
39849 self.generate_expression(&e.this)?;
39850 self.write(", ");
39851 self.generate_expression(&e.expression)?;
39852 if let Some(unit) = &e.unit {
39853 self.write(", ");
39854 self.write_keyword(unit);
39855 }
39856 if let Some(return_type) = &e.return_type {
39857 self.write(", ");
39858 self.generate_expression(return_type)?;
39859 }
39860 self.write(")");
39861 Ok(())
39862 }
39863
39864 fn generate_ts_or_ds_diff(&mut self, e: &TsOrDsDiff) -> Result<()> {
39865 self.write_keyword("TS_OR_DS_DIFF");
39867 self.write("(");
39868 self.generate_expression(&e.this)?;
39869 self.write(", ");
39870 self.generate_expression(&e.expression)?;
39871 if let Some(unit) = &e.unit {
39872 self.write(", ");
39873 self.write_keyword(unit);
39874 }
39875 self.write(")");
39876 Ok(())
39877 }
39878
39879 fn generate_ts_or_ds_to_date(&mut self, e: &TsOrDsToDate) -> Result<()> {
39880 let default_time_format = "%Y-%m-%d %H:%M:%S";
39881 let default_date_format = "%Y-%m-%d";
39882 let has_non_default_format = e.format.as_ref().map_or(false, |f| {
39883 f != default_time_format && f != default_date_format
39884 });
39885
39886 if has_non_default_format {
39887 let fmt = e.format.as_ref().unwrap();
39889 match self.config.dialect {
39890 Some(DialectType::MySQL) | Some(DialectType::StarRocks) => {
39891 let str_to_time = crate::expressions::StrToTime {
39894 this: Box::new((*e.this).clone()),
39895 format: fmt.clone(),
39896 zone: None,
39897 safe: None,
39898 target_type: None,
39899 };
39900 self.generate_str_to_time(&str_to_time)?;
39901 }
39902 Some(DialectType::Hive)
39903 | Some(DialectType::Spark)
39904 | Some(DialectType::Databricks) => {
39905 self.write_keyword("TO_DATE");
39907 self.write("(");
39908 self.generate_expression(&e.this)?;
39909 self.write(", '");
39910 self.write(&Self::strftime_to_java_format(fmt));
39911 self.write("')");
39912 }
39913 Some(DialectType::Snowflake) => {
39914 self.write_keyword("TO_DATE");
39916 self.write("(");
39917 self.generate_expression(&e.this)?;
39918 self.write(", '");
39919 self.write(&Self::strftime_to_snowflake_format(fmt));
39920 self.write("')");
39921 }
39922 Some(DialectType::Doris) => {
39923 self.write_keyword("TO_DATE");
39925 self.write("(");
39926 self.generate_expression(&e.this)?;
39927 self.write(")");
39928 }
39929 _ => {
39930 self.write_keyword("CAST");
39932 self.write("(");
39933 let str_to_time = crate::expressions::StrToTime {
39934 this: Box::new((*e.this).clone()),
39935 format: fmt.clone(),
39936 zone: None,
39937 safe: None,
39938 target_type: None,
39939 };
39940 self.generate_str_to_time(&str_to_time)?;
39941 self.write_keyword(" AS ");
39942 self.write_keyword("DATE");
39943 self.write(")");
39944 }
39945 }
39946 } else {
39947 match self.config.dialect {
39949 Some(DialectType::MySQL)
39950 | Some(DialectType::SQLite)
39951 | Some(DialectType::StarRocks) => {
39952 self.write_keyword("DATE");
39954 self.write("(");
39955 self.generate_expression(&e.this)?;
39956 self.write(")");
39957 }
39958 Some(DialectType::Hive)
39959 | Some(DialectType::Spark)
39960 | Some(DialectType::Databricks)
39961 | Some(DialectType::Snowflake)
39962 | Some(DialectType::Doris) => {
39963 self.write_keyword("TO_DATE");
39965 self.write("(");
39966 self.generate_expression(&e.this)?;
39967 self.write(")");
39968 }
39969 Some(DialectType::Presto)
39970 | Some(DialectType::Trino)
39971 | Some(DialectType::Athena) => {
39972 self.write_keyword("CAST");
39974 self.write("(");
39975 self.write_keyword("CAST");
39976 self.write("(");
39977 self.generate_expression(&e.this)?;
39978 self.write_keyword(" AS ");
39979 self.write_keyword("TIMESTAMP");
39980 self.write(")");
39981 self.write_keyword(" AS ");
39982 self.write_keyword("DATE");
39983 self.write(")");
39984 }
39985 Some(DialectType::ClickHouse) => {
39986 self.write_keyword("CAST");
39988 self.write("(");
39989 self.generate_expression(&e.this)?;
39990 self.write_keyword(" AS ");
39991 self.write("Nullable(DATE)");
39992 self.write(")");
39993 }
39994 _ => {
39995 self.write_keyword("CAST");
39997 self.write("(");
39998 self.generate_expression(&e.this)?;
39999 self.write_keyword(" AS ");
40000 self.write_keyword("DATE");
40001 self.write(")");
40002 }
40003 }
40004 }
40005 Ok(())
40006 }
40007
40008 fn generate_ts_or_ds_to_time(&mut self, e: &TsOrDsToTime) -> Result<()> {
40009 self.write_keyword("TS_OR_DS_TO_TIME");
40011 self.write("(");
40012 self.generate_expression(&e.this)?;
40013 if let Some(format) = &e.format {
40014 self.write(", '");
40015 self.write(format);
40016 self.write("'");
40017 }
40018 self.write(")");
40019 Ok(())
40020 }
40021
40022 fn generate_unhex(&mut self, e: &Unhex) -> Result<()> {
40023 self.write_keyword("UNHEX");
40025 self.write("(");
40026 self.generate_expression(&e.this)?;
40027 if let Some(expression) = &e.expression {
40028 self.write(", ");
40029 self.generate_expression(expression)?;
40030 }
40031 self.write(")");
40032 Ok(())
40033 }
40034
40035 fn generate_unicode_string(&mut self, e: &UnicodeString) -> Result<()> {
40036 self.write("U&");
40038 self.generate_expression(&e.this)?;
40039 if let Some(escape) = &e.escape {
40040 self.write_space();
40041 self.write_keyword("UESCAPE");
40042 self.write_space();
40043 self.generate_expression(escape)?;
40044 }
40045 Ok(())
40046 }
40047
40048 fn generate_uniform(&mut self, e: &Uniform) -> Result<()> {
40049 self.write_keyword("UNIFORM");
40051 self.write("(");
40052 self.generate_expression(&e.this)?;
40053 self.write(", ");
40054 self.generate_expression(&e.expression)?;
40055 if let Some(gen) = &e.gen {
40056 self.write(", ");
40057 self.generate_expression(gen)?;
40058 }
40059 if let Some(seed) = &e.seed {
40060 self.write(", ");
40061 self.generate_expression(seed)?;
40062 }
40063 self.write(")");
40064 Ok(())
40065 }
40066
40067 fn generate_unique_column_constraint(&mut self, e: &UniqueColumnConstraint) -> Result<()> {
40068 self.write_keyword("UNIQUE");
40070 if e.nulls.is_some() {
40072 self.write(" NULLS NOT DISTINCT");
40073 }
40074 if let Some(this) = &e.this {
40075 self.write_space();
40076 self.generate_expression(this)?;
40077 }
40078 if let Some(index_type) = &e.index_type {
40079 self.write(" USING ");
40080 self.generate_expression(index_type)?;
40081 }
40082 if let Some(on_conflict) = &e.on_conflict {
40083 self.write_space();
40084 self.generate_expression(on_conflict)?;
40085 }
40086 for opt in &e.options {
40087 self.write_space();
40088 self.generate_expression(opt)?;
40089 }
40090 Ok(())
40091 }
40092
40093 fn generate_unique_key_property(&mut self, e: &UniqueKeyProperty) -> Result<()> {
40094 self.write_keyword("UNIQUE KEY");
40096 self.write(" (");
40097 for (i, expr) in e.expressions.iter().enumerate() {
40098 if i > 0 {
40099 self.write(", ");
40100 }
40101 self.generate_expression(expr)?;
40102 }
40103 self.write(")");
40104 Ok(())
40105 }
40106
40107 fn generate_rollup_property(&mut self, e: &RollupProperty) -> Result<()> {
40108 self.write_keyword("ROLLUP");
40110 self.write(" (");
40111 for (i, index) in e.expressions.iter().enumerate() {
40112 if i > 0 {
40113 self.write(", ");
40114 }
40115 self.generate_identifier(&index.name)?;
40116 self.write("(");
40117 for (j, col) in index.expressions.iter().enumerate() {
40118 if j > 0 {
40119 self.write(", ");
40120 }
40121 self.generate_identifier(col)?;
40122 }
40123 self.write(")");
40124 }
40125 self.write(")");
40126 Ok(())
40127 }
40128
40129 fn generate_unix_to_str(&mut self, e: &UnixToStr) -> Result<()> {
40130 match self.config.dialect {
40131 Some(DialectType::DuckDB) => {
40132 self.write_keyword("STRFTIME");
40134 self.write("(");
40135 self.write_keyword("TO_TIMESTAMP");
40136 self.write("(");
40137 self.generate_expression(&e.this)?;
40138 self.write("), '");
40139 if let Some(format) = &e.format {
40140 self.write(format);
40141 }
40142 self.write("')");
40143 }
40144 Some(DialectType::Hive) => {
40145 self.write_keyword("FROM_UNIXTIME");
40147 self.write("(");
40148 self.generate_expression(&e.this)?;
40149 if let Some(format) = &e.format {
40150 if format != "yyyy-MM-dd HH:mm:ss" {
40151 self.write(", '");
40152 self.write(format);
40153 self.write("'");
40154 }
40155 }
40156 self.write(")");
40157 }
40158 Some(DialectType::Presto) | Some(DialectType::Trino) => {
40159 self.write_keyword("DATE_FORMAT");
40161 self.write("(");
40162 self.write_keyword("FROM_UNIXTIME");
40163 self.write("(");
40164 self.generate_expression(&e.this)?;
40165 self.write("), '");
40166 if let Some(format) = &e.format {
40167 self.write(format);
40168 }
40169 self.write("')");
40170 }
40171 Some(DialectType::Spark) | Some(DialectType::Databricks) => {
40172 self.write_keyword("FROM_UNIXTIME");
40174 self.write("(");
40175 self.generate_expression(&e.this)?;
40176 if let Some(format) = &e.format {
40177 self.write(", '");
40178 self.write(format);
40179 self.write("'");
40180 }
40181 self.write(")");
40182 }
40183 _ => {
40184 self.write_keyword("UNIX_TO_STR");
40186 self.write("(");
40187 self.generate_expression(&e.this)?;
40188 if let Some(format) = &e.format {
40189 self.write(", '");
40190 self.write(format);
40191 self.write("'");
40192 }
40193 self.write(")");
40194 }
40195 }
40196 Ok(())
40197 }
40198
40199 fn generate_unix_to_time(&mut self, e: &UnixToTime) -> Result<()> {
40200 use crate::dialects::DialectType;
40201 let scale = e.scale.unwrap_or(0); match self.config.dialect {
40204 Some(DialectType::Snowflake) => {
40205 self.write_keyword("TO_TIMESTAMP");
40207 self.write("(");
40208 self.generate_expression(&e.this)?;
40209 if let Some(s) = e.scale {
40210 if s > 0 {
40211 self.write(", ");
40212 self.write(&s.to_string());
40213 }
40214 }
40215 self.write(")");
40216 }
40217 Some(DialectType::BigQuery) => {
40218 match scale {
40221 0 => {
40222 self.write_keyword("TIMESTAMP_SECONDS");
40223 self.write("(");
40224 self.generate_expression(&e.this)?;
40225 self.write(")");
40226 }
40227 3 => {
40228 self.write_keyword("TIMESTAMP_MILLIS");
40229 self.write("(");
40230 self.generate_expression(&e.this)?;
40231 self.write(")");
40232 }
40233 6 => {
40234 self.write_keyword("TIMESTAMP_MICROS");
40235 self.write("(");
40236 self.generate_expression(&e.this)?;
40237 self.write(")");
40238 }
40239 _ => {
40240 self.write_keyword("TIMESTAMP_SECONDS");
40242 self.write("(CAST(");
40243 self.generate_expression(&e.this)?;
40244 self.write(&format!(" / POWER(10, {}) AS INT64))", scale));
40245 }
40246 }
40247 }
40248 Some(DialectType::Spark) => {
40249 match scale {
40254 0 => {
40255 self.write_keyword("CAST");
40256 self.write("(");
40257 self.write_keyword("FROM_UNIXTIME");
40258 self.write("(");
40259 self.generate_expression(&e.this)?;
40260 self.write(") ");
40261 self.write_keyword("AS TIMESTAMP");
40262 self.write(")");
40263 }
40264 3 => {
40265 self.write_keyword("TIMESTAMP_MILLIS");
40266 self.write("(");
40267 self.generate_expression(&e.this)?;
40268 self.write(")");
40269 }
40270 6 => {
40271 self.write_keyword("TIMESTAMP_MICROS");
40272 self.write("(");
40273 self.generate_expression(&e.this)?;
40274 self.write(")");
40275 }
40276 _ => {
40277 self.write_keyword("TIMESTAMP_SECONDS");
40278 self.write("(");
40279 self.generate_expression(&e.this)?;
40280 self.write(&format!(" / POWER(10, {}))", scale));
40281 }
40282 }
40283 }
40284 Some(DialectType::Databricks) => {
40285 match scale {
40289 0 => {
40290 self.write_keyword("CAST");
40291 self.write("(");
40292 self.write_keyword("FROM_UNIXTIME");
40293 self.write("(");
40294 self.generate_expression(&e.this)?;
40295 self.write(") ");
40296 self.write_keyword("AS TIMESTAMP");
40297 self.write(")");
40298 }
40299 3 => {
40300 self.write_keyword("TIMESTAMP_MILLIS");
40301 self.write("(");
40302 self.generate_expression(&e.this)?;
40303 self.write(")");
40304 }
40305 6 => {
40306 self.write_keyword("TIMESTAMP_MICROS");
40307 self.write("(");
40308 self.generate_expression(&e.this)?;
40309 self.write(")");
40310 }
40311 _ => {
40312 self.write_keyword("TIMESTAMP_SECONDS");
40313 self.write("(");
40314 self.generate_expression(&e.this)?;
40315 self.write(&format!(" / POWER(10, {}))", scale));
40316 }
40317 }
40318 }
40319 Some(DialectType::Hive) => {
40320 if scale == 0 {
40322 self.write_keyword("FROM_UNIXTIME");
40323 self.write("(");
40324 self.generate_expression(&e.this)?;
40325 self.write(")");
40326 } else {
40327 self.write_keyword("FROM_UNIXTIME");
40328 self.write("(");
40329 self.generate_expression(&e.this)?;
40330 self.write(&format!(" / POWER(10, {})", scale));
40331 self.write(")");
40332 }
40333 }
40334 Some(DialectType::Presto) | Some(DialectType::Trino) => {
40335 if scale == 0 {
40338 self.write_keyword("FROM_UNIXTIME");
40339 self.write("(");
40340 self.generate_expression(&e.this)?;
40341 self.write(")");
40342 } else {
40343 self.write_keyword("FROM_UNIXTIME");
40344 self.write("(CAST(");
40345 self.generate_expression(&e.this)?;
40346 self.write(&format!(" AS DOUBLE) / POW(10, {}))", scale));
40347 }
40348 }
40349 Some(DialectType::DuckDB) => {
40350 match scale {
40354 0 => {
40355 self.write_keyword("TO_TIMESTAMP");
40356 self.write("(");
40357 self.generate_expression(&e.this)?;
40358 self.write(")");
40359 }
40360 3 => {
40361 self.write_keyword("EPOCH_MS");
40362 self.write("(");
40363 self.generate_expression(&e.this)?;
40364 self.write(")");
40365 }
40366 6 => {
40367 self.write_keyword("MAKE_TIMESTAMP");
40368 self.write("(");
40369 self.generate_expression(&e.this)?;
40370 self.write(")");
40371 }
40372 _ => {
40373 self.write_keyword("TO_TIMESTAMP");
40374 self.write("(");
40375 self.generate_expression(&e.this)?;
40376 self.write(&format!(" / POWER(10, {}))", scale));
40377 self.write_keyword(" AT TIME ZONE");
40378 self.write(" 'UTC'");
40379 }
40380 }
40381 }
40382 Some(DialectType::Doris) | Some(DialectType::StarRocks) => {
40383 self.write_keyword("FROM_UNIXTIME");
40385 self.write("(");
40386 self.generate_expression(&e.this)?;
40387 self.write(")");
40388 }
40389 Some(DialectType::Oracle) => {
40390 self.write("TO_DATE('1970-01-01', 'YYYY-MM-DD') + (");
40392 self.generate_expression(&e.this)?;
40393 self.write(" / 86400)");
40394 }
40395 Some(DialectType::Redshift) => {
40396 self.write("(TIMESTAMP 'epoch' + ");
40399 if scale == 0 {
40400 self.generate_expression(&e.this)?;
40401 } else {
40402 self.write("(");
40403 self.generate_expression(&e.this)?;
40404 self.write(&format!(" / POWER(10, {}))", scale));
40405 }
40406 self.write(" * INTERVAL '1 SECOND')");
40407 }
40408 Some(DialectType::Exasol) => {
40409 self.write_keyword("FROM_POSIX_TIME");
40411 self.write("(");
40412 self.generate_expression(&e.this)?;
40413 self.write(")");
40414 }
40415 _ => {
40416 self.write_keyword("TO_TIMESTAMP");
40418 self.write("(");
40419 self.generate_expression(&e.this)?;
40420 if let Some(s) = e.scale {
40421 self.write(", ");
40422 self.write(&s.to_string());
40423 }
40424 self.write(")");
40425 }
40426 }
40427 Ok(())
40428 }
40429
40430 fn generate_unpivot_columns(&mut self, e: &UnpivotColumns) -> Result<()> {
40431 if !matches!(&*e.this, Expression::Null(_)) {
40433 self.write_keyword("NAME");
40434 self.write_space();
40435 self.generate_expression(&e.this)?;
40436 }
40437 if !e.expressions.is_empty() {
40438 self.write_space();
40439 self.write_keyword("VALUE");
40440 self.write_space();
40441 for (i, expr) in e.expressions.iter().enumerate() {
40442 if i > 0 {
40443 self.write(", ");
40444 }
40445 self.generate_expression(expr)?;
40446 }
40447 }
40448 Ok(())
40449 }
40450
40451 fn generate_user_defined_function(&mut self, e: &UserDefinedFunction) -> Result<()> {
40452 if e.wrapped.is_some() {
40454 self.write("(");
40455 }
40456 self.generate_expression(&e.this)?;
40457 if e.wrapped.is_some() {
40458 self.write(")");
40459 }
40460 self.write("(");
40461 for (i, expr) in e.expressions.iter().enumerate() {
40462 if i > 0 {
40463 self.write(", ");
40464 }
40465 self.generate_expression(expr)?;
40466 }
40467 self.write(")");
40468 Ok(())
40469 }
40470
40471 fn generate_using_template_property(&mut self, e: &UsingTemplateProperty) -> Result<()> {
40472 self.write_keyword("USING TEMPLATE");
40474 self.write_space();
40475 self.generate_expression(&e.this)?;
40476 Ok(())
40477 }
40478
40479 fn generate_utc_time(&mut self, _e: &UtcTime) -> Result<()> {
40480 self.write_keyword("UTC_TIME");
40482 Ok(())
40483 }
40484
40485 fn generate_utc_timestamp(&mut self, _e: &UtcTimestamp) -> Result<()> {
40486 if matches!(
40487 self.config.dialect,
40488 Some(crate::dialects::DialectType::ClickHouse)
40489 ) {
40490 self.write_keyword("CURRENT_TIMESTAMP");
40491 self.write("('UTC')");
40492 } else {
40493 self.write_keyword("UTC_TIMESTAMP");
40494 }
40495 Ok(())
40496 }
40497
40498 fn generate_uuid(&mut self, e: &Uuid) -> Result<()> {
40499 use crate::dialects::DialectType;
40500 let func_name = match self.config.dialect {
40502 Some(DialectType::Snowflake) => "UUID_STRING",
40503 Some(DialectType::PostgreSQL) | Some(DialectType::Redshift) => "GEN_RANDOM_UUID",
40504 Some(DialectType::BigQuery) => "GENERATE_UUID",
40505 _ => {
40506 if let Some(name) = &e.name {
40507 name.as_str()
40508 } else {
40509 "UUID"
40510 }
40511 }
40512 };
40513 self.write_keyword(func_name);
40514 self.write("(");
40515 if let Some(this) = &e.this {
40516 self.generate_expression(this)?;
40517 }
40518 self.write(")");
40519 Ok(())
40520 }
40521
40522 fn generate_var_map(&mut self, e: &VarMap) -> Result<()> {
40523 self.write_keyword("MAP");
40525 self.write("(");
40526 let mut first = true;
40527 for (k, v) in e.keys.iter().zip(e.values.iter()) {
40528 if !first {
40529 self.write(", ");
40530 }
40531 self.generate_expression(k)?;
40532 self.write(", ");
40533 self.generate_expression(v)?;
40534 first = false;
40535 }
40536 self.write(")");
40537 Ok(())
40538 }
40539
40540 fn generate_vector_search(&mut self, e: &VectorSearch) -> Result<()> {
40541 self.write_keyword("VECTOR_SEARCH");
40543 self.write("(");
40544 self.generate_expression(&e.this)?;
40545 if let Some(col) = &e.column_to_search {
40546 self.write(", ");
40547 self.generate_expression(col)?;
40548 }
40549 if let Some(query_table) = &e.query_table {
40550 self.write(", ");
40551 self.generate_expression(query_table)?;
40552 }
40553 if let Some(query_col) = &e.query_column_to_search {
40554 self.write(", ");
40555 self.generate_expression(query_col)?;
40556 }
40557 if let Some(top_k) = &e.top_k {
40558 self.write(", ");
40559 self.generate_expression(top_k)?;
40560 }
40561 if let Some(dist_type) = &e.distance_type {
40562 self.write(", ");
40563 self.generate_expression(dist_type)?;
40564 }
40565 self.write(")");
40566 Ok(())
40567 }
40568
40569 fn generate_version(&mut self, e: &Version) -> Result<()> {
40570 use crate::dialects::DialectType;
40576 if matches!(self.config.dialect, Some(DialectType::Dremio)) {
40577 self.write_keyword("AT");
40578 self.write_space();
40579 let name = match e.this.as_ref() {
40580 Expression::Identifier(ident) if ident.name.eq_ignore_ascii_case("VERSION") => {
40581 "SNAPSHOT"
40582 }
40583 _ => "TIMESTAMP",
40584 };
40585 self.write_keyword(name);
40586 if let Some(expression) = &e.expression {
40587 self.write_space();
40588 self.generate_expression(expression)?;
40589 }
40590 return Ok(());
40591 }
40592 let skip_for = matches!(
40593 self.config.dialect,
40594 Some(DialectType::Hive) | Some(DialectType::Spark) | Some(DialectType::Databricks)
40595 );
40596 if !skip_for {
40597 self.write_keyword("FOR");
40598 self.write_space();
40599 }
40600 match e.this.as_ref() {
40602 Expression::Identifier(ident) => {
40603 self.write_keyword(&ident.name);
40604 }
40605 _ => {
40606 self.generate_expression(&e.this)?;
40607 }
40608 }
40609 self.write_space();
40610 self.write_keyword(&e.kind);
40611 if let Some(expression) = &e.expression {
40612 self.write_space();
40613 self.generate_expression(expression)?;
40614 }
40615 Ok(())
40616 }
40617
40618 fn generate_view_attribute_property(&mut self, e: &ViewAttributeProperty) -> Result<()> {
40619 self.generate_expression(&e.this)?;
40621 Ok(())
40622 }
40623
40624 fn generate_volatile_property(&mut self, e: &VolatileProperty) -> Result<()> {
40625 if e.this.is_some() {
40627 self.write_keyword("NOT VOLATILE");
40628 } else {
40629 self.write_keyword("VOLATILE");
40630 }
40631 Ok(())
40632 }
40633
40634 fn generate_watermark_column_constraint(
40635 &mut self,
40636 e: &WatermarkColumnConstraint,
40637 ) -> Result<()> {
40638 self.write_keyword("WATERMARK FOR");
40640 self.write_space();
40641 self.generate_expression(&e.this)?;
40642 self.write_space();
40643 self.write_keyword("AS");
40644 self.write_space();
40645 self.generate_expression(&e.expression)?;
40646 Ok(())
40647 }
40648
40649 fn generate_week(&mut self, e: &Week) -> Result<()> {
40650 self.write_keyword("WEEK");
40652 self.write("(");
40653 self.generate_expression(&e.this)?;
40654 if let Some(mode) = &e.mode {
40655 self.write(", ");
40656 self.generate_expression(mode)?;
40657 }
40658 self.write(")");
40659 Ok(())
40660 }
40661
40662 fn generate_when(&mut self, e: &When) -> Result<()> {
40663 self.write_keyword("WHEN");
40667 self.write_space();
40668
40669 if let Some(matched) = &e.matched {
40671 match matched.as_ref() {
40673 Expression::Boolean(b) if b.value => {
40674 self.write_keyword("MATCHED");
40675 }
40676 _ => {
40677 self.write_keyword("NOT MATCHED");
40678 }
40679 }
40680 } else {
40681 self.write_keyword("NOT MATCHED");
40682 }
40683
40684 if self.config.matched_by_source {
40689 if let Some(source) = &e.source {
40690 if let Expression::Boolean(b) = source.as_ref() {
40691 if b.value {
40692 self.write_space();
40694 self.write_keyword("BY SOURCE");
40695 }
40696 } else {
40698 self.write_space();
40700 self.write_keyword("BY SOURCE");
40701 }
40702 }
40703 }
40704
40705 if let Some(condition) = &e.condition {
40707 self.write_space();
40708 self.write_keyword("AND");
40709 self.write_space();
40710 self.generate_expression(condition)?;
40711 }
40712
40713 self.write_space();
40714 self.write_keyword("THEN");
40715 self.write_space();
40716
40717 self.generate_merge_action(&e.then)?;
40720
40721 Ok(())
40722 }
40723
40724 fn generate_merge_action(&mut self, action: &Expression) -> Result<()> {
40725 match action {
40726 Expression::Tuple(tuple) => {
40727 let elements = &tuple.expressions;
40728 if elements.is_empty() {
40729 return self.generate_expression(action);
40730 }
40731 match &elements[0] {
40733 Expression::Var(v) if v.this == "INSERT" => {
40734 self.write_keyword("INSERT");
40735 if elements.len() > 1 && matches!(&elements[1], Expression::Star(_)) {
40737 self.write(" *");
40738 if let Some(Expression::Where(w)) = elements.get(2) {
40739 self.write_space();
40740 self.generate_where(w)?;
40741 }
40742 } else {
40743 let mut values_idx = 1;
40744 if elements.len() > 1 {
40746 if let Expression::Tuple(cols) = &elements[1] {
40747 if elements.len() > 2 {
40749 self.write(" (");
40751 for (i, col) in cols.expressions.iter().enumerate() {
40752 if i > 0 {
40753 self.write(", ");
40754 }
40755 if !self.merge_strip_qualifiers.is_empty() {
40757 let stripped = self.strip_merge_qualifier(col);
40758 self.generate_expression(&stripped)?;
40759 } else {
40760 self.generate_expression(col)?;
40761 }
40762 }
40763 self.write(")");
40764 values_idx = 2;
40765 } else {
40766 values_idx = 1;
40768 }
40769 }
40770 }
40771 let mut next_idx = values_idx;
40772 if values_idx < elements.len()
40774 && !matches!(&elements[values_idx], Expression::Where(_))
40775 {
40776 let is_row = matches!(&elements[values_idx], Expression::Var(v) if v.this == "ROW");
40778 if !is_row {
40779 self.write_space();
40780 self.write_keyword("VALUES");
40781 }
40782 self.write(" ");
40783 if let Expression::Tuple(vals) = &elements[values_idx] {
40784 self.write("(");
40785 for (i, val) in vals.expressions.iter().enumerate() {
40786 if i > 0 {
40787 self.write(", ");
40788 }
40789 self.generate_expression(val)?;
40790 }
40791 self.write(")");
40792 } else {
40793 self.generate_expression(&elements[values_idx])?;
40794 }
40795 next_idx += 1;
40796 }
40797 if let Some(Expression::Where(w)) = elements.get(next_idx) {
40798 self.write_space();
40799 self.generate_where(w)?;
40800 }
40801 } }
40803 Expression::Var(v) if v.this == "UPDATE" => {
40804 self.write_keyword("UPDATE");
40805 if elements.len() > 1 && matches!(&elements[1], Expression::Star(_)) {
40807 self.write(" *");
40808 if let Some(Expression::Where(w)) = elements.get(2) {
40809 self.write_space();
40810 self.generate_where(w)?;
40811 }
40812 } else if elements.len() > 1 {
40813 self.write_space();
40814 self.write_keyword("SET");
40815 if self.config.pretty {
40817 self.write_newline();
40818 self.indent_level += 1;
40819 self.write_indent();
40820 } else {
40821 self.write_space();
40822 }
40823 if let Expression::Tuple(assignments) = &elements[1] {
40824 for (i, assignment) in assignments.expressions.iter().enumerate() {
40825 if i > 0 {
40826 if self.config.pretty {
40827 self.write(",");
40828 self.write_newline();
40829 self.write_indent();
40830 } else {
40831 self.write(", ");
40832 }
40833 }
40834 if !self.merge_strip_qualifiers.is_empty() {
40836 self.generate_merge_set_assignment(assignment)?;
40837 } else {
40838 self.generate_expression(assignment)?;
40839 }
40840 }
40841 } else {
40842 self.generate_expression(&elements[1])?;
40843 }
40844 if self.config.pretty {
40845 self.indent_level -= 1;
40846 }
40847 if let Some(Expression::Where(w)) = elements.get(2) {
40848 self.write_space();
40849 self.generate_where(w)?;
40850 }
40851 }
40852 }
40853 Expression::Var(v) if v.this == "DELETE" => {
40854 self.write_keyword("DELETE");
40855 if let Some(Expression::Where(w)) = elements.get(1) {
40856 self.write_space();
40857 self.generate_where(w)?;
40858 }
40859 }
40860 _ => {
40861 self.generate_expression(action)?;
40863 }
40864 }
40865 }
40866 Expression::Var(v)
40867 if v.this == "INSERT"
40868 || v.this == "UPDATE"
40869 || v.this == "DELETE"
40870 || v.this == "DO NOTHING" =>
40871 {
40872 self.write_keyword(&v.this);
40873 }
40874 _ => {
40875 self.generate_expression(action)?;
40876 }
40877 }
40878 Ok(())
40879 }
40880
40881 fn generate_merge_set_assignment(&mut self, assignment: &Expression) -> Result<()> {
40883 match assignment {
40884 Expression::Eq(eq) => {
40885 let stripped_left = self.strip_merge_qualifier(&eq.left);
40887 self.generate_expression(&stripped_left)?;
40888 self.write(" = ");
40889 self.generate_expression(&eq.right)?;
40890 Ok(())
40891 }
40892 other => self.generate_expression(other),
40893 }
40894 }
40895
40896 fn strip_merge_qualifier(&self, expr: &Expression) -> Expression {
40898 match expr {
40899 Expression::Column(col) => {
40900 if let Some(ref table_ident) = col.table {
40901 if self
40902 .merge_strip_qualifiers
40903 .iter()
40904 .any(|n| n.eq_ignore_ascii_case(&table_ident.name))
40905 {
40906 let mut col = col.clone();
40908 col.table = None;
40909 return Expression::Column(col);
40910 }
40911 }
40912 expr.clone()
40913 }
40914 Expression::Dot(dot) => {
40915 if let Expression::Identifier(id) = &dot.this {
40917 if self
40918 .merge_strip_qualifiers
40919 .iter()
40920 .any(|n| n.eq_ignore_ascii_case(&id.name))
40921 {
40922 return Expression::Identifier(dot.field.clone());
40923 }
40924 }
40925 expr.clone()
40926 }
40927 _ => expr.clone(),
40928 }
40929 }
40930
40931 fn generate_whens(&mut self, e: &Whens) -> Result<()> {
40932 for (i, expr) in e.expressions.iter().enumerate() {
40934 if i > 0 {
40935 if self.config.pretty {
40937 self.write_newline();
40938 self.write_indent();
40939 } else {
40940 self.write_space();
40941 }
40942 }
40943 self.generate_expression(expr)?;
40944 }
40945 Ok(())
40946 }
40947
40948 fn generate_where(&mut self, e: &Where) -> Result<()> {
40949 self.write_keyword("WHERE");
40951 self.write_space();
40952 self.generate_expression(&e.this)?;
40953 Ok(())
40954 }
40955
40956 fn generate_width_bucket(&mut self, e: &WidthBucket) -> Result<()> {
40957 self.write_keyword("WIDTH_BUCKET");
40959 self.write("(");
40960 self.generate_expression(&e.this)?;
40961 if let Some(min_value) = &e.min_value {
40962 self.write(", ");
40963 self.generate_expression(min_value)?;
40964 }
40965 if let Some(max_value) = &e.max_value {
40966 self.write(", ");
40967 self.generate_expression(max_value)?;
40968 }
40969 if let Some(num_buckets) = &e.num_buckets {
40970 self.write(", ");
40971 self.generate_expression(num_buckets)?;
40972 }
40973 self.write(")");
40974 Ok(())
40975 }
40976
40977 fn generate_window(&mut self, e: &WindowSpec) -> Result<()> {
40978 self.generate_window_spec(e)
40980 }
40981
40982 fn generate_window_spec(&mut self, e: &WindowSpec) -> Result<()> {
40983 let mut has_content = false;
40985
40986 if !e.partition_by.is_empty() {
40988 self.write_keyword("PARTITION BY");
40989 self.write_space();
40990 for (i, expr) in e.partition_by.iter().enumerate() {
40991 if i > 0 {
40992 self.write(", ");
40993 }
40994 self.generate_expression(expr)?;
40995 }
40996 has_content = true;
40997 }
40998
40999 if !e.order_by.is_empty() {
41001 if has_content {
41002 self.write_space();
41003 }
41004 self.write_keyword("ORDER BY");
41005 self.write_space();
41006 for (i, ordered) in e.order_by.iter().enumerate() {
41007 if i > 0 {
41008 self.write(", ");
41009 }
41010 self.generate_expression(&ordered.this)?;
41011 if ordered.desc {
41012 self.write_space();
41013 self.write_keyword("DESC");
41014 } else if ordered.explicit_asc {
41015 self.write_space();
41016 self.write_keyword("ASC");
41017 }
41018 if let Some(nulls_first) = ordered.nulls_first {
41019 self.write_space();
41020 self.write_keyword("NULLS");
41021 self.write_space();
41022 if nulls_first {
41023 self.write_keyword("FIRST");
41024 } else {
41025 self.write_keyword("LAST");
41026 }
41027 }
41028 }
41029 has_content = true;
41030 }
41031
41032 if let Some(frame) = &e.frame {
41034 if has_content {
41035 self.write_space();
41036 }
41037 self.generate_window_frame(frame)?;
41038 }
41039
41040 Ok(())
41041 }
41042
41043 fn generate_with_data_property(&mut self, e: &WithDataProperty) -> Result<()> {
41044 self.write_keyword("WITH");
41046 self.write_space();
41047 if e.no.is_some() {
41048 self.write_keyword("NO");
41049 self.write_space();
41050 }
41051 self.write_keyword("DATA");
41052
41053 if let Some(statistics) = &e.statistics {
41055 self.write_space();
41056 self.write_keyword("AND");
41057 self.write_space();
41058 match statistics.as_ref() {
41060 Expression::Boolean(b) if !b.value => {
41061 self.write_keyword("NO");
41062 self.write_space();
41063 }
41064 _ => {}
41065 }
41066 self.write_keyword("STATISTICS");
41067 }
41068 Ok(())
41069 }
41070
41071 fn generate_with_fill(&mut self, e: &WithFill) -> Result<()> {
41072 self.write_keyword("WITH FILL");
41074
41075 if let Some(from_) = &e.from_ {
41076 self.write_space();
41077 self.write_keyword("FROM");
41078 self.write_space();
41079 self.generate_expression(from_)?;
41080 }
41081
41082 if let Some(to) = &e.to {
41083 self.write_space();
41084 self.write_keyword("TO");
41085 self.write_space();
41086 self.generate_expression(to)?;
41087 }
41088
41089 if let Some(step) = &e.step {
41090 self.write_space();
41091 self.write_keyword("STEP");
41092 self.write_space();
41093 self.generate_expression(step)?;
41094 }
41095
41096 if let Some(staleness) = &e.staleness {
41097 self.write_space();
41098 self.write_keyword("STALENESS");
41099 self.write_space();
41100 self.generate_expression(staleness)?;
41101 }
41102
41103 if let Some(interpolate) = &e.interpolate {
41104 self.write_space();
41105 self.write_keyword("INTERPOLATE");
41106 self.write(" (");
41107 self.generate_interpolate_item(interpolate)?;
41109 self.write(")");
41110 }
41111
41112 Ok(())
41113 }
41114
41115 fn generate_interpolate_item(&mut self, expr: &Expression) -> Result<()> {
41117 match expr {
41118 Expression::Alias(alias) => {
41119 self.generate_identifier(&alias.alias)?;
41121 self.write_space();
41122 self.write_keyword("AS");
41123 self.write_space();
41124 self.generate_expression(&alias.this)?;
41125 }
41126 Expression::Tuple(tuple) => {
41127 for (i, item) in tuple.expressions.iter().enumerate() {
41128 if i > 0 {
41129 self.write(", ");
41130 }
41131 self.generate_interpolate_item(item)?;
41132 }
41133 }
41134 other => {
41135 self.generate_expression(other)?;
41136 }
41137 }
41138 Ok(())
41139 }
41140
41141 fn generate_with_journal_table_property(&mut self, e: &WithJournalTableProperty) -> Result<()> {
41142 self.write_keyword("WITH JOURNAL TABLE");
41144 self.write("=");
41145 self.generate_expression(&e.this)?;
41146 Ok(())
41147 }
41148
41149 fn generate_with_operator(&mut self, e: &WithOperator) -> Result<()> {
41150 self.generate_expression(&e.this)?;
41152 self.write_space();
41153 self.write_keyword("WITH");
41154 self.write_space();
41155 self.write_keyword(&e.op);
41156 Ok(())
41157 }
41158
41159 fn generate_with_procedure_options(&mut self, e: &WithProcedureOptions) -> Result<()> {
41160 self.write_keyword("WITH");
41162 self.write_space();
41163 for (i, expr) in e.expressions.iter().enumerate() {
41164 if i > 0 {
41165 self.write(", ");
41166 }
41167 self.generate_expression(expr)?;
41168 }
41169 Ok(())
41170 }
41171
41172 fn generate_with_schema_binding_property(
41173 &mut self,
41174 e: &WithSchemaBindingProperty,
41175 ) -> Result<()> {
41176 self.write_keyword("WITH");
41178 self.write_space();
41179 self.generate_expression(&e.this)?;
41180 Ok(())
41181 }
41182
41183 fn generate_with_system_versioning_property(
41184 &mut self,
41185 e: &WithSystemVersioningProperty,
41186 ) -> Result<()> {
41187 let mut parts = Vec::new();
41193
41194 if let Some(this) = &e.this {
41195 let mut s = String::from("HISTORY_TABLE=");
41197 let mut gen = Generator::new();
41198 gen.generate_expression(this)?;
41199 s.push_str(&gen.output);
41200 parts.push(s);
41201 }
41202
41203 if let Some(data_consistency) = &e.data_consistency {
41204 let mut s = String::from("DATA_CONSISTENCY_CHECK=");
41205 let mut gen = Generator::new();
41206 gen.generate_expression(data_consistency)?;
41207 s.push_str(&gen.output);
41208 parts.push(s);
41209 }
41210
41211 if let Some(retention_period) = &e.retention_period {
41212 let mut s = String::from("HISTORY_RETENTION_PERIOD=");
41213 let mut gen = Generator::new();
41214 gen.generate_expression(retention_period)?;
41215 s.push_str(&gen.output);
41216 parts.push(s);
41217 }
41218
41219 self.write_keyword("SYSTEM_VERSIONING");
41220 self.write("=");
41221
41222 if !parts.is_empty() {
41223 self.write_keyword("ON");
41224 self.write("(");
41225 self.write(&parts.join(", "));
41226 self.write(")");
41227 } else if e.on.is_some() {
41228 self.write_keyword("ON");
41229 } else {
41230 self.write_keyword("OFF");
41231 }
41232
41233 if e.with_.is_some() {
41235 let inner = self.output.clone();
41236 self.output.clear();
41237 self.write("WITH(");
41238 self.write(&inner);
41239 self.write(")");
41240 }
41241
41242 Ok(())
41243 }
41244
41245 fn generate_with_table_hint(&mut self, e: &WithTableHint) -> Result<()> {
41246 self.write_keyword("WITH");
41248 self.write(" (");
41249 for (i, expr) in e.expressions.iter().enumerate() {
41250 if i > 0 {
41251 self.write(", ");
41252 }
41253 self.generate_expression(expr)?;
41254 }
41255 self.write(")");
41256 Ok(())
41257 }
41258
41259 fn generate_xml_element(&mut self, e: &XMLElement) -> Result<()> {
41260 self.write_keyword("XMLELEMENT");
41263 self.write("(");
41264
41265 if e.evalname.is_some() {
41266 self.write_keyword("EVALNAME");
41267 } else {
41268 self.write_keyword("NAME");
41269 }
41270 self.write_space();
41271 self.generate_expression(&e.this)?;
41272
41273 for expr in &e.expressions {
41274 self.write(", ");
41275 self.generate_expression(expr)?;
41276 }
41277 self.write(")");
41278 Ok(())
41279 }
41280
41281 fn generate_xml_get(&mut self, e: &XMLGet) -> Result<()> {
41282 self.write_keyword("XMLGET");
41284 self.write("(");
41285 self.generate_expression(&e.this)?;
41286 self.write(", ");
41287 self.generate_expression(&e.expression)?;
41288 if let Some(instance) = &e.instance {
41289 self.write(", ");
41290 self.generate_expression(instance)?;
41291 }
41292 self.write(")");
41293 Ok(())
41294 }
41295
41296 fn generate_xml_key_value_option(&mut self, e: &XMLKeyValueOption) -> Result<()> {
41297 self.generate_expression(&e.this)?;
41299 if let Some(expression) = &e.expression {
41300 self.write("(");
41301 self.generate_expression(expression)?;
41302 self.write(")");
41303 }
41304 Ok(())
41305 }
41306
41307 fn generate_xml_table(&mut self, e: &XMLTable) -> Result<()> {
41308 self.write_keyword("XMLTABLE");
41310 self.write("(");
41311
41312 if self.config.pretty {
41313 self.indent_level += 1;
41314 self.write_newline();
41315 self.write_indent();
41316 self.generate_expression(&e.this)?;
41317
41318 if let Some(passing) = &e.passing {
41319 self.write_newline();
41320 self.write_indent();
41321 self.write_keyword("PASSING");
41322 if let Expression::Tuple(tuple) = passing.as_ref() {
41323 for expr in &tuple.expressions {
41324 self.write_newline();
41325 self.indent_level += 1;
41326 self.write_indent();
41327 self.generate_expression(expr)?;
41328 self.indent_level -= 1;
41329 }
41330 } else {
41331 self.write_newline();
41332 self.indent_level += 1;
41333 self.write_indent();
41334 self.generate_expression(passing)?;
41335 self.indent_level -= 1;
41336 }
41337 }
41338
41339 if e.by_ref.is_some() {
41340 self.write_newline();
41341 self.write_indent();
41342 self.write_keyword("RETURNING SEQUENCE BY REF");
41343 }
41344
41345 if !e.columns.is_empty() {
41346 self.write_newline();
41347 self.write_indent();
41348 self.write_keyword("COLUMNS");
41349 for (i, col) in e.columns.iter().enumerate() {
41350 self.write_newline();
41351 self.indent_level += 1;
41352 self.write_indent();
41353 self.generate_expression(col)?;
41354 self.indent_level -= 1;
41355 if i < e.columns.len() - 1 {
41356 self.write(",");
41357 }
41358 }
41359 }
41360
41361 self.indent_level -= 1;
41362 self.write_newline();
41363 self.write_indent();
41364 self.write(")");
41365 return Ok(());
41366 }
41367
41368 if let Some(namespaces) = &e.namespaces {
41370 self.write_keyword("XMLNAMESPACES");
41371 self.write("(");
41372 if let Expression::Tuple(tuple) = namespaces.as_ref() {
41374 for (i, expr) in tuple.expressions.iter().enumerate() {
41375 if i > 0 {
41376 self.write(", ");
41377 }
41378 if !matches!(expr, Expression::Alias(_)) {
41381 self.write_keyword("DEFAULT");
41382 self.write_space();
41383 }
41384 self.generate_expression(expr)?;
41385 }
41386 } else {
41387 if !matches!(namespaces.as_ref(), Expression::Alias(_)) {
41389 self.write_keyword("DEFAULT");
41390 self.write_space();
41391 }
41392 self.generate_expression(namespaces)?;
41393 }
41394 self.write("), ");
41395 }
41396
41397 self.generate_expression(&e.this)?;
41399
41400 if let Some(passing) = &e.passing {
41402 self.write_space();
41403 self.write_keyword("PASSING");
41404 self.write_space();
41405 if let Expression::Tuple(tuple) = passing.as_ref() {
41407 for (i, expr) in tuple.expressions.iter().enumerate() {
41408 if i > 0 {
41409 self.write(", ");
41410 }
41411 self.generate_expression(expr)?;
41412 }
41413 } else {
41414 self.generate_expression(passing)?;
41415 }
41416 }
41417
41418 if e.by_ref.is_some() {
41420 self.write_space();
41421 self.write_keyword("RETURNING SEQUENCE BY REF");
41422 }
41423
41424 if !e.columns.is_empty() {
41426 self.write_space();
41427 self.write_keyword("COLUMNS");
41428 self.write_space();
41429 for (i, col) in e.columns.iter().enumerate() {
41430 if i > 0 {
41431 self.write(", ");
41432 }
41433 self.generate_expression(col)?;
41434 }
41435 }
41436
41437 self.write(")");
41438 Ok(())
41439 }
41440
41441 fn generate_xor(&mut self, e: &Xor) -> Result<()> {
41442 if let Some(this) = &e.this {
41445 self.generate_expression(this)?;
41446 if let Some(expression) = &e.expression {
41447 self.write_space();
41448 self.write_keyword("XOR");
41449 self.write_space();
41450 self.generate_expression(expression)?;
41451 }
41452 }
41453
41454 for (i, expr) in e.expressions.iter().enumerate() {
41456 if i > 0 || e.this.is_some() {
41457 self.write_space();
41458 self.write_keyword("XOR");
41459 self.write_space();
41460 }
41461 self.generate_expression(expr)?;
41462 }
41463 Ok(())
41464 }
41465
41466 fn generate_zipf(&mut self, e: &Zipf) -> Result<()> {
41467 self.write_keyword("ZIPF");
41469 self.write("(");
41470 self.generate_expression(&e.this)?;
41471 if let Some(elementcount) = &e.elementcount {
41472 self.write(", ");
41473 self.generate_expression(elementcount)?;
41474 }
41475 if let Some(gen) = &e.gen {
41476 self.write(", ");
41477 self.generate_expression(gen)?;
41478 }
41479 self.write(")");
41480 Ok(())
41481 }
41482}
41483
41484impl Default for Generator {
41485 fn default() -> Self {
41486 Self::new()
41487 }
41488}
41489
41490#[cfg(test)]
41491mod tests {
41492 use super::*;
41493 use crate::parser::Parser;
41494
41495 fn roundtrip(sql: &str) -> String {
41496 let ast = Parser::parse_sql(sql).unwrap();
41497 Generator::sql(&ast[0]).unwrap()
41498 }
41499
41500 #[test]
41501 fn test_simple_select() {
41502 let result = roundtrip("SELECT 1");
41503 assert_eq!(result, "SELECT 1");
41504 }
41505
41506 #[test]
41507 fn test_select_from() {
41508 let result = roundtrip("SELECT a, b FROM t");
41509 assert_eq!(result, "SELECT a, b FROM t");
41510 }
41511
41512 #[test]
41513 fn test_select_where() {
41514 let result = roundtrip("SELECT * FROM t WHERE x = 1");
41515 assert_eq!(result, "SELECT * FROM t WHERE x = 1");
41516 }
41517
41518 #[test]
41519 fn test_select_join() {
41520 let result = roundtrip("SELECT * FROM a JOIN b ON a.id = b.id");
41521 assert_eq!(result, "SELECT * FROM a JOIN b ON a.id = b.id");
41522 }
41523
41524 #[test]
41525 fn test_insert() {
41526 let result = roundtrip("INSERT INTO t (a, b) VALUES (1, 2)");
41527 assert_eq!(result, "INSERT INTO t (a, b) VALUES (1, 2)");
41528 }
41529
41530 #[test]
41531 fn test_pretty_print() {
41532 let ast = Parser::parse_sql("SELECT a, b FROM t WHERE x = 1").unwrap();
41533 let result = Generator::pretty_sql(&ast[0]).unwrap();
41534 assert!(result.contains('\n'));
41535 }
41536
41537 #[test]
41538 fn test_window_function() {
41539 let result = roundtrip("SELECT ROW_NUMBER() OVER (PARTITION BY category ORDER BY id)");
41540 assert_eq!(
41541 result,
41542 "SELECT ROW_NUMBER() OVER (PARTITION BY category ORDER BY id)"
41543 );
41544 }
41545
41546 #[test]
41547 fn test_window_function_with_frame() {
41548 let result = roundtrip("SELECT SUM(amount) OVER (ORDER BY order_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)");
41549 assert_eq!(result, "SELECT SUM(amount) OVER (ORDER BY order_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)");
41550 }
41551
41552 #[test]
41553 fn test_aggregate_with_filter() {
41554 let result = roundtrip("SELECT COUNT(*) FILTER (WHERE status = 1) FROM orders");
41555 assert_eq!(
41556 result,
41557 "SELECT COUNT(*) FILTER(WHERE status = 1) FROM orders"
41558 );
41559 }
41560
41561 #[test]
41562 fn test_subscript() {
41563 let result = roundtrip("SELECT arr[0]");
41564 assert_eq!(result, "SELECT arr[0]");
41565 }
41566
41567 #[test]
41569 fn test_create_table() {
41570 let result = roundtrip("CREATE TABLE users (id INT, name VARCHAR(100))");
41571 assert_eq!(result, "CREATE TABLE users (id INT, name VARCHAR(100))");
41572 }
41573
41574 #[test]
41575 fn test_create_table_with_constraints() {
41576 let result = roundtrip(
41577 "CREATE TABLE users (id INT PRIMARY KEY, email VARCHAR(255) UNIQUE NOT NULL)",
41578 );
41579 assert_eq!(
41580 result,
41581 "CREATE TABLE users (id INT PRIMARY KEY, email VARCHAR(255) UNIQUE NOT NULL)"
41582 );
41583 }
41584
41585 #[test]
41586 fn test_create_table_if_not_exists() {
41587 let result = roundtrip("CREATE TABLE IF NOT EXISTS t (id INT)");
41588 assert_eq!(result, "CREATE TABLE IF NOT EXISTS t (id INT)");
41589 }
41590
41591 #[test]
41592 fn test_drop_table() {
41593 let result = roundtrip("DROP TABLE users");
41594 assert_eq!(result, "DROP TABLE users");
41595 }
41596
41597 #[test]
41598 fn test_drop_table_if_exists_cascade() {
41599 let result = roundtrip("DROP TABLE IF EXISTS users CASCADE");
41600 assert_eq!(result, "DROP TABLE IF EXISTS users CASCADE");
41601 }
41602
41603 #[test]
41604 fn test_alter_table_add_column() {
41605 let result = roundtrip("ALTER TABLE users ADD COLUMN email VARCHAR(255)");
41606 assert_eq!(result, "ALTER TABLE users ADD COLUMN email VARCHAR(255)");
41607 }
41608
41609 #[test]
41610 fn test_alter_table_drop_column() {
41611 let result = roundtrip("ALTER TABLE users DROP COLUMN email");
41612 assert_eq!(result, "ALTER TABLE users DROP COLUMN email");
41613 }
41614
41615 #[test]
41616 fn test_create_index() {
41617 let result = roundtrip("CREATE INDEX idx_name ON users(name)");
41618 assert_eq!(result, "CREATE INDEX idx_name ON users(name)");
41619 }
41620
41621 #[test]
41622 fn test_create_unique_index() {
41623 let result = roundtrip("CREATE UNIQUE INDEX idx_email ON users(email)");
41624 assert_eq!(result, "CREATE UNIQUE INDEX idx_email ON users(email)");
41625 }
41626
41627 #[test]
41628 fn test_drop_index() {
41629 let result = roundtrip("DROP INDEX idx_name");
41630 assert_eq!(result, "DROP INDEX idx_name");
41631
41632 let result = roundtrip(r#"DROP INDEX IF EXISTS "idx_tokenKey__pb_users_auth_""#);
41633 assert_eq!(
41634 result,
41635 r#"DROP INDEX IF EXISTS "idx_tokenKey__pb_users_auth_""#
41636 );
41637
41638 let result = roundtrip(r#"DROP INDEX "public"."IdxMixed""#);
41639 assert_eq!(result, r#"DROP INDEX "public"."IdxMixed""#);
41640 }
41641
41642 #[test]
41643 fn test_create_view() {
41644 let result = roundtrip("CREATE VIEW active_users AS SELECT * FROM users WHERE active = 1");
41645 assert_eq!(
41646 result,
41647 "CREATE VIEW active_users AS SELECT * FROM users WHERE active = 1"
41648 );
41649 }
41650
41651 #[test]
41652 fn test_drop_view() {
41653 let result = roundtrip("DROP VIEW active_users");
41654 assert_eq!(result, "DROP VIEW active_users");
41655 }
41656
41657 #[test]
41658 fn test_truncate() {
41659 let result = roundtrip("TRUNCATE TABLE users");
41660 assert_eq!(result, "TRUNCATE TABLE users");
41661 }
41662
41663 #[test]
41664 fn test_string_literal_escaping_default() {
41665 let result = roundtrip("SELECT 'hello'");
41667 assert_eq!(result, "SELECT 'hello'");
41668
41669 let result = roundtrip("SELECT 'it''s a test'");
41671 assert_eq!(result, "SELECT 'it''s a test'");
41672 }
41673
41674 #[test]
41675 fn test_not_in_style_prefix_default_generic() {
41676 let result = roundtrip("SELECT id FROM users WHERE status NOT IN ('deleted', 'banned')");
41677 assert_eq!(
41678 result,
41679 "SELECT id FROM users WHERE NOT status IN ('deleted', 'banned')"
41680 );
41681 }
41682
41683 #[test]
41684 fn test_not_in_style_infix_generic_override() {
41685 let ast =
41686 Parser::parse_sql("SELECT id FROM users WHERE status NOT IN ('deleted', 'banned')")
41687 .unwrap();
41688 let config = GeneratorConfig {
41689 not_in_style: NotInStyle::Infix,
41690 ..Default::default()
41691 };
41692 let mut gen = Generator::with_config(config);
41693 let result = gen.generate(&ast[0]).unwrap();
41694 assert_eq!(
41695 result,
41696 "SELECT id FROM users WHERE status NOT IN ('deleted', 'banned')"
41697 );
41698 }
41699
41700 #[test]
41701 fn test_string_literal_escaping_mysql() {
41702 use crate::dialects::DialectType;
41703
41704 let config = GeneratorConfig {
41705 dialect: Some(DialectType::MySQL),
41706 ..Default::default()
41707 };
41708
41709 let ast = Parser::parse_sql("SELECT 'hello'").unwrap();
41710 let mut gen = Generator::with_config(config.clone());
41711 let result = gen.generate(&ast[0]).unwrap();
41712 assert_eq!(result, "SELECT 'hello'");
41713
41714 let ast = Parser::parse_sql("SELECT 'it''s'").unwrap();
41716 let mut gen = Generator::with_config(config.clone());
41717 let result = gen.generate(&ast[0]).unwrap();
41718 assert_eq!(result, "SELECT 'it''s'");
41719 }
41720
41721 #[test]
41722 fn test_string_literal_escaping_postgres() {
41723 use crate::dialects::DialectType;
41724
41725 let config = GeneratorConfig {
41726 dialect: Some(DialectType::PostgreSQL),
41727 ..Default::default()
41728 };
41729
41730 let ast = Parser::parse_sql("SELECT 'hello'").unwrap();
41731 let mut gen = Generator::with_config(config.clone());
41732 let result = gen.generate(&ast[0]).unwrap();
41733 assert_eq!(result, "SELECT 'hello'");
41734
41735 let ast = Parser::parse_sql("SELECT 'it''s'").unwrap();
41737 let mut gen = Generator::with_config(config.clone());
41738 let result = gen.generate(&ast[0]).unwrap();
41739 assert_eq!(result, "SELECT 'it''s'");
41740 }
41741
41742 #[test]
41743 fn test_string_literal_escaping_bigquery() {
41744 use crate::dialects::DialectType;
41745
41746 let config = GeneratorConfig {
41747 dialect: Some(DialectType::BigQuery),
41748 ..Default::default()
41749 };
41750
41751 let ast = Parser::parse_sql("SELECT 'hello'").unwrap();
41752 let mut gen = Generator::with_config(config.clone());
41753 let result = gen.generate(&ast[0]).unwrap();
41754 assert_eq!(result, "SELECT 'hello'");
41755
41756 let ast = Parser::parse_sql("SELECT 'it''s'").unwrap();
41758 let mut gen = Generator::with_config(config.clone());
41759 let result = gen.generate(&ast[0]).unwrap();
41760 assert_eq!(result, "SELECT 'it\\'s'");
41761 }
41762
41763 #[test]
41764 fn test_generate_deep_and_chain_without_stack_growth() {
41765 let mut expr = Expression::Eq(Box::new(BinaryOp::new(
41766 Expression::column("c0"),
41767 Expression::number(0),
41768 )));
41769
41770 for i in 1..2500 {
41771 let predicate = Expression::Eq(Box::new(BinaryOp::new(
41772 Expression::column(format!("c{i}")),
41773 Expression::number(i as i64),
41774 )));
41775 expr = Expression::And(Box::new(BinaryOp::new(expr, predicate)));
41776 }
41777
41778 let sql = Generator::sql(&expr).expect("deep AND chain should generate");
41779 assert!(sql.contains("c2499 = 2499"), "{}", sql);
41780 }
41781
41782 #[test]
41783 fn test_generate_deep_or_chain_without_stack_growth() {
41784 let mut expr = Expression::Eq(Box::new(BinaryOp::new(
41785 Expression::column("c0"),
41786 Expression::number(0),
41787 )));
41788
41789 for i in 1..2500 {
41790 let predicate = Expression::Eq(Box::new(BinaryOp::new(
41791 Expression::column(format!("c{i}")),
41792 Expression::number(i as i64),
41793 )));
41794 expr = Expression::Or(Box::new(BinaryOp::new(expr, predicate)));
41795 }
41796
41797 let sql = Generator::sql(&expr).expect("deep OR chain should generate");
41798 assert!(sql.contains("c2499 = 2499"), "{}", sql);
41799 }
41800}