1use std::{collections::HashMap, sync::Arc};
19
20use super::{
21 Unparser, utils::character_length_to_sql, utils::date_part_to_sql,
22 utils::sqlite_date_trunc_to_sql, utils::sqlite_from_unixtime_to_sql,
23};
24use arrow::array::timezone::Tz;
25use arrow::datatypes::TimeUnit;
26use chrono::DateTime;
27use datafusion_common::{Result, internal_err};
28use datafusion_expr::Expr;
29use regex::Regex;
30use sqlparser::tokenizer::Span;
31use sqlparser::{
32 ast::{
33 self, BinaryOperator, Function, Ident, ObjectName, TimezoneInfo, WindowFrameBound,
34 },
35 keywords::ALL_KEYWORDS,
36};
37
38pub type ScalarFnToSqlHandler =
39 Box<dyn Fn(&Unparser, &[Expr]) -> Result<Option<ast::Expr>> + Send + Sync>;
40
41pub trait Dialect: Send + Sync {
51 fn identifier_quote_style(&self, _identifier: &str) -> Option<char>;
53
54 fn use_array_keyword_for_array_literals(&self) -> bool {
56 false
57 }
58
59 fn supports_nulls_first_in_sort(&self) -> bool {
61 true
62 }
63
64 fn use_timestamp_for_date64(&self) -> bool {
67 false
68 }
69
70 fn interval_style(&self) -> IntervalStyle {
71 IntervalStyle::PostgresVerbose
72 }
73
74 fn float64_ast_dtype(&self) -> ast::DataType {
77 ast::DataType::Double(ast::ExactNumberInfo::None)
78 }
79
80 fn utf8_cast_dtype(&self) -> ast::DataType {
83 ast::DataType::Varchar(None)
84 }
85
86 fn large_utf8_cast_dtype(&self) -> ast::DataType {
89 ast::DataType::Text
90 }
91
92 fn date_field_extract_style(&self) -> DateFieldExtractStyle {
94 DateFieldExtractStyle::DatePart
95 }
96
97 fn distinct_from_style(&self) -> DistinctFromStyle {
99 DistinctFromStyle::FullText
100 }
101
102 fn character_length_style(&self) -> CharacterLengthStyle {
104 CharacterLengthStyle::CharacterLength
105 }
106
107 fn int64_cast_dtype(&self) -> ast::DataType {
110 ast::DataType::BigInt(None)
111 }
112
113 fn int8_cast_dtype(&self) -> ast::DataType {
116 ast::DataType::TinyInt(None)
117 }
118
119 fn int32_cast_dtype(&self) -> ast::DataType {
122 ast::DataType::Integer(None)
123 }
124
125 fn timestamp_cast_dtype(
129 &self,
130 _time_unit: &TimeUnit,
131 tz: &Option<Arc<str>>,
132 ) -> ast::DataType {
133 let tz_info = match tz {
134 Some(_) => TimezoneInfo::WithTimeZone,
135 None => TimezoneInfo::None,
136 };
137
138 ast::DataType::Timestamp(None, tz_info)
139 }
140
141 fn date32_cast_dtype(&self) -> ast::DataType {
144 ast::DataType::Date
145 }
146
147 fn supports_column_alias_in_table_alias(&self) -> bool {
150 true
151 }
152
153 fn requires_derived_table_alias(&self) -> bool {
156 false
157 }
158
159 fn division_operator(&self) -> BinaryOperator {
163 BinaryOperator::Divide
164 }
165
166 fn scalar_function_to_sql_overrides(
170 &self,
171 _unparser: &Unparser,
172 _func_name: &str,
173 _args: &[Expr],
174 ) -> Result<Option<ast::Expr>> {
175 Ok(None)
176 }
177
178 fn higher_order_function_to_sql_overrides(
182 &self,
183 _unparser: &Unparser,
184 _func_name: &str,
185 _args: &[Expr],
186 ) -> Result<Option<ast::Expr>> {
187 Ok(None)
188 }
189
190 fn window_func_support_window_frame(
194 &self,
195 _func_name: &str,
196 _start_bound: &WindowFrameBound,
197 _end_bound: &WindowFrameBound,
198 ) -> bool {
199 true
200 }
201
202 fn with_custom_scalar_overrides(
205 self,
206 _handlers: Vec<(&str, ScalarFnToSqlHandler)>,
207 ) -> Self
208 where
209 Self: Sized,
210 {
211 unimplemented!("Custom scalar overrides are not supported by this dialect yet");
212 }
213
214 fn full_qualified_col(&self) -> bool {
219 false
220 }
221
222 fn unnest_as_table_factor(&self) -> bool {
228 false
229 }
230
231 fn unnest_as_lateral_flatten(&self) -> bool {
237 false
238 }
239
240 fn col_alias_overrides(&self, _alias: &str) -> Result<Option<String>> {
244 Ok(None)
245 }
246
247 fn supports_qualify(&self) -> bool {
251 true
252 }
253
254 fn timestamp_with_tz_to_string(&self, dt: DateTime<Tz>, _unit: TimeUnit) -> String {
256 dt.to_rfc3339()
257 }
258
259 fn supports_empty_select_list(&self) -> bool {
286 false
287 }
288
289 fn string_literal_to_sql(&self, _s: &str) -> Option<ast::Expr> {
297 None
298 }
299}
300
301#[derive(Clone, Copy)]
310pub enum IntervalStyle {
311 PostgresVerbose,
312 SQLStandard,
313 MySQL,
314}
315
316#[derive(Clone, Copy, PartialEq)]
324pub enum DateFieldExtractStyle {
325 DatePart,
326 Extract,
327 Strftime,
328}
329
330#[derive(Clone, Copy, PartialEq)]
336pub enum CharacterLengthStyle {
337 Length,
338 CharacterLength,
339}
340
341#[derive(Clone, Copy, PartialEq)]
343pub enum DistinctFromStyle {
344 FullText,
346 Spaceship,
348}
349
350pub struct DefaultDialect {}
351
352impl Dialect for DefaultDialect {
353 fn identifier_quote_style(&self, identifier: &str) -> Option<char> {
354 let identifier_regex = Regex::new(r"^[a-zA-Z_][a-zA-Z0-9_]*$").unwrap();
355 let id_upper = identifier.to_uppercase();
356 let needs_quote = (id_upper != "ID" && ALL_KEYWORDS.contains(&id_upper.as_str()))
361 || !identifier_regex.is_match(identifier)
362 || identifier.chars().any(|c| c.is_ascii_uppercase());
363 if needs_quote { Some('"') } else { None }
364 }
365}
366
367pub struct PostgreSqlDialect {}
368
369impl Dialect for PostgreSqlDialect {
370 fn use_array_keyword_for_array_literals(&self) -> bool {
371 true
372 }
373
374 fn supports_qualify(&self) -> bool {
375 false
376 }
377
378 fn requires_derived_table_alias(&self) -> bool {
379 true
380 }
381
382 fn supports_empty_select_list(&self) -> bool {
383 true
384 }
385
386 fn identifier_quote_style(&self, _: &str) -> Option<char> {
387 Some('"')
388 }
389
390 fn interval_style(&self) -> IntervalStyle {
391 IntervalStyle::PostgresVerbose
392 }
393
394 fn float64_ast_dtype(&self) -> ast::DataType {
395 ast::DataType::DoublePrecision
396 }
397
398 fn int8_cast_dtype(&self) -> ast::DataType {
399 ast::DataType::SmallInt(None)
400 }
401
402 fn distinct_from_style(&self) -> DistinctFromStyle {
403 DistinctFromStyle::FullText
404 }
405
406 fn scalar_function_to_sql_overrides(
407 &self,
408 unparser: &Unparser,
409 func_name: &str,
410 args: &[Expr],
411 ) -> Result<Option<ast::Expr>> {
412 if func_name == "array_has" {
413 return self.array_has_to_sql_any(unparser, args);
414 }
415
416 if func_name == "round" {
417 return Ok(Some(
418 self.round_to_sql_enforce_numeric(unparser, func_name, args)?,
419 ));
420 }
421
422 Ok(None)
423 }
424}
425
426impl PostgreSqlDialect {
427 fn array_has_to_sql_any(
428 &self,
429 unparser: &Unparser,
430 args: &[Expr],
431 ) -> Result<Option<ast::Expr>> {
432 let [haystack, needle] = args else {
433 return internal_err!("array_has expected 2 arguments, got {}", args.len());
434 };
435
436 Ok(Some(ast::Expr::AnyOp {
437 left: Box::new(unparser.expr_to_sql_with_nesting(needle)?),
440 compare_op: BinaryOperator::Eq,
441 right: Box::new(unparser.expr_to_sql_with_nesting(haystack)?),
442 is_some: false,
443 }))
444 }
445
446 fn round_to_sql_enforce_numeric(
447 &self,
448 unparser: &Unparser,
449 func_name: &str,
450 args: &[Expr],
451 ) -> Result<ast::Expr> {
452 let mut args = unparser.function_args_to_sql(args)?;
453
454 if let Some(ast::FunctionArg::Unnamed(ast::FunctionArgExpr::Expr(expr))) =
456 args.first_mut()
457 {
458 if let ast::Expr::Cast { data_type, .. } = expr {
459 *data_type = ast::DataType::Numeric(ast::ExactNumberInfo::None);
461 } else {
462 *expr = ast::Expr::Cast {
464 kind: ast::CastKind::Cast,
465 expr: Box::new(expr.clone()),
466 data_type: ast::DataType::Numeric(ast::ExactNumberInfo::None),
467 array: false,
468 format: None,
469 };
470 }
471 }
472
473 Ok(ast::Expr::Function(Function {
474 name: ObjectName::from(vec![Ident {
475 value: func_name.to_string(),
476 quote_style: None,
477 span: Span::empty(),
478 }]),
479 args: ast::FunctionArguments::List(ast::FunctionArgumentList {
480 duplicate_treatment: None,
481 args,
482 clauses: vec![],
483 }),
484 filter: None,
485 null_treatment: None,
486 over: None,
487 within_group: vec![],
488 parameters: ast::FunctionArguments::None,
489 uses_odbc_syntax: false,
490 }))
491 }
492}
493
494#[derive(Default)]
495pub struct DuckDBDialect {
496 custom_scalar_fn_overrides: HashMap<String, ScalarFnToSqlHandler>,
497}
498
499impl DuckDBDialect {
500 #[must_use]
501 pub fn new() -> Self {
502 Self {
503 custom_scalar_fn_overrides: HashMap::new(),
504 }
505 }
506}
507
508impl Dialect for DuckDBDialect {
509 fn identifier_quote_style(&self, _: &str) -> Option<char> {
510 Some('"')
511 }
512
513 fn character_length_style(&self) -> CharacterLengthStyle {
514 CharacterLengthStyle::Length
515 }
516
517 fn division_operator(&self) -> BinaryOperator {
518 BinaryOperator::DuckIntegerDivide
519 }
520
521 fn with_custom_scalar_overrides(
522 mut self,
523 handlers: Vec<(&str, ScalarFnToSqlHandler)>,
524 ) -> Self {
525 for (func_name, handler) in handlers {
526 self.custom_scalar_fn_overrides
527 .insert(func_name.to_string(), handler);
528 }
529 self
530 }
531
532 fn scalar_function_to_sql_overrides(
533 &self,
534 unparser: &Unparser,
535 func_name: &str,
536 args: &[Expr],
537 ) -> Result<Option<ast::Expr>> {
538 if let Some(handler) = self.custom_scalar_fn_overrides.get(func_name) {
539 return handler(unparser, args);
540 }
541
542 if func_name == "character_length" {
543 return character_length_to_sql(
544 unparser,
545 self.character_length_style(),
546 args,
547 );
548 }
549
550 Ok(None)
551 }
552
553 fn distinct_from_style(&self) -> DistinctFromStyle {
554 DistinctFromStyle::FullText
555 }
556}
557
558pub struct MySqlDialect {}
559
560impl Dialect for MySqlDialect {
561 fn supports_qualify(&self) -> bool {
562 false
563 }
564
565 fn identifier_quote_style(&self, _: &str) -> Option<char> {
566 Some('`')
567 }
568
569 fn supports_nulls_first_in_sort(&self) -> bool {
570 false
571 }
572
573 fn interval_style(&self) -> IntervalStyle {
574 IntervalStyle::MySQL
575 }
576
577 fn utf8_cast_dtype(&self) -> ast::DataType {
578 ast::DataType::Char(None)
579 }
580
581 fn large_utf8_cast_dtype(&self) -> ast::DataType {
582 ast::DataType::Char(None)
583 }
584
585 fn date_field_extract_style(&self) -> DateFieldExtractStyle {
586 DateFieldExtractStyle::Extract
587 }
588
589 fn distinct_from_style(&self) -> DistinctFromStyle {
590 DistinctFromStyle::Spaceship
591 }
592
593 fn int64_cast_dtype(&self) -> ast::DataType {
594 ast::DataType::Custom(ObjectName::from(vec![Ident::new("SIGNED")]), vec![])
595 }
596
597 fn int32_cast_dtype(&self) -> ast::DataType {
598 ast::DataType::Custom(ObjectName::from(vec![Ident::new("SIGNED")]), vec![])
599 }
600
601 fn timestamp_cast_dtype(
602 &self,
603 _time_unit: &TimeUnit,
604 _tz: &Option<Arc<str>>,
605 ) -> ast::DataType {
606 ast::DataType::Datetime(None)
607 }
608
609 fn requires_derived_table_alias(&self) -> bool {
610 true
611 }
612
613 fn scalar_function_to_sql_overrides(
614 &self,
615 unparser: &Unparser,
616 func_name: &str,
617 args: &[Expr],
618 ) -> Result<Option<ast::Expr>> {
619 if func_name == "date_part" {
620 return date_part_to_sql(unparser, self.date_field_extract_style(), args);
621 }
622
623 Ok(None)
624 }
625}
626
627pub struct SqliteDialect {}
628
629impl Dialect for SqliteDialect {
630 fn supports_qualify(&self) -> bool {
631 false
632 }
633
634 fn identifier_quote_style(&self, _: &str) -> Option<char> {
635 Some('`')
636 }
637
638 fn date_field_extract_style(&self) -> DateFieldExtractStyle {
639 DateFieldExtractStyle::Strftime
640 }
641
642 fn date32_cast_dtype(&self) -> ast::DataType {
643 ast::DataType::Text
644 }
645
646 fn character_length_style(&self) -> CharacterLengthStyle {
647 CharacterLengthStyle::Length
648 }
649
650 fn distinct_from_style(&self) -> DistinctFromStyle {
651 DistinctFromStyle::FullText
652 }
653
654 fn supports_column_alias_in_table_alias(&self) -> bool {
655 false
656 }
657
658 fn timestamp_cast_dtype(
659 &self,
660 _time_unit: &TimeUnit,
661 _tz: &Option<Arc<str>>,
662 ) -> ast::DataType {
663 ast::DataType::Text
664 }
665
666 fn scalar_function_to_sql_overrides(
667 &self,
668 unparser: &Unparser,
669 func_name: &str,
670 args: &[Expr],
671 ) -> Result<Option<ast::Expr>> {
672 match func_name {
673 "date_part" => {
674 date_part_to_sql(unparser, self.date_field_extract_style(), args)
675 }
676 "character_length" => {
677 character_length_to_sql(unparser, self.character_length_style(), args)
678 }
679 "from_unixtime" => sqlite_from_unixtime_to_sql(unparser, args),
680 "date_trunc" => sqlite_date_trunc_to_sql(unparser, args),
681 _ => Ok(None),
682 }
683 }
684}
685
686#[derive(Default)]
687pub struct BigQueryDialect {}
688
689impl Dialect for BigQueryDialect {
690 fn identifier_quote_style(&self, _: &str) -> Option<char> {
691 Some('`')
692 }
693
694 fn col_alias_overrides(&self, alias: &str) -> Result<Option<String>> {
695 let special_chars: [char; 20] = [
698 '!', '"', '$', '(', ')', '*', ',', '.', '/', ';', '?', '@', '[', '\\', ']',
699 '^', '`', '{', '}', '~',
700 ];
701
702 if alias.chars().any(|c| special_chars.contains(&c)) {
703 let mut encoded_name = String::new();
704 for c in alias.chars() {
705 if special_chars.contains(&c) {
706 encoded_name.push_str(&format!("_{}", c as u32));
707 } else {
708 encoded_name.push(c);
709 }
710 }
711 Ok(Some(encoded_name))
712 } else {
713 Ok(Some(alias.to_string()))
714 }
715 }
716
717 fn unnest_as_table_factor(&self) -> bool {
718 true
719 }
720
721 fn supports_column_alias_in_table_alias(&self) -> bool {
722 false
723 }
724
725 fn float64_ast_dtype(&self) -> ast::DataType {
726 ast::DataType::Float64
727 }
728
729 fn utf8_cast_dtype(&self) -> ast::DataType {
730 ast::DataType::String(None)
731 }
732
733 fn large_utf8_cast_dtype(&self) -> ast::DataType {
734 ast::DataType::String(None)
735 }
736
737 fn timestamp_cast_dtype(
738 &self,
739 _time_unit: &TimeUnit,
740 _tz: &Option<Arc<str>>,
741 ) -> ast::DataType {
742 ast::DataType::Timestamp(None, TimezoneInfo::None)
743 }
744
745 fn date_field_extract_style(&self) -> DateFieldExtractStyle {
746 DateFieldExtractStyle::Extract
747 }
748
749 fn interval_style(&self) -> IntervalStyle {
750 IntervalStyle::SQLStandard
751 }
752
753 fn scalar_function_to_sql_overrides(
754 &self,
755 unparser: &Unparser,
756 func_name: &str,
757 args: &[Expr],
758 ) -> Result<Option<ast::Expr>> {
759 if func_name == "date_part" {
760 return date_part_to_sql(unparser, self.date_field_extract_style(), args);
761 }
762
763 Ok(None)
764 }
765}
766
767impl BigQueryDialect {
768 #[must_use]
769 pub fn new() -> Self {
770 Self {}
771 }
772}
773
774pub struct SnowflakeDialect {}
784
785#[expect(clippy::new_without_default)]
786impl SnowflakeDialect {
787 #[must_use]
788 pub fn new() -> Self {
789 Self {}
790 }
791}
792
793impl Dialect for SnowflakeDialect {
794 fn identifier_quote_style(&self, _: &str) -> Option<char> {
795 Some('"')
796 }
797
798 fn supports_nulls_first_in_sort(&self) -> bool {
799 true
800 }
801
802 fn supports_empty_select_list(&self) -> bool {
803 false
804 }
805
806 fn supports_column_alias_in_table_alias(&self) -> bool {
807 false
808 }
809
810 fn timestamp_cast_dtype(
811 &self,
812 _time_unit: &TimeUnit,
813 tz: &Option<Arc<str>>,
814 ) -> ast::DataType {
815 if tz.is_some() {
816 ast::DataType::Timestamp(None, TimezoneInfo::WithTimeZone)
817 } else {
818 ast::DataType::Timestamp(None, TimezoneInfo::None)
819 }
820 }
821
822 fn unnest_as_lateral_flatten(&self) -> bool {
823 true
824 }
825}
826
827pub struct CustomDialect {
828 identifier_quote_style: Option<char>,
829 supports_nulls_first_in_sort: bool,
830 use_timestamp_for_date64: bool,
831 interval_style: IntervalStyle,
832 float64_ast_dtype: ast::DataType,
833 utf8_cast_dtype: ast::DataType,
834 large_utf8_cast_dtype: ast::DataType,
835 date_field_extract_style: DateFieldExtractStyle,
836 character_length_style: CharacterLengthStyle,
837 int8_cast_dtype: ast::DataType,
838 int64_cast_dtype: ast::DataType,
839 int32_cast_dtype: ast::DataType,
840 timestamp_cast_dtype: ast::DataType,
841 timestamp_tz_cast_dtype: ast::DataType,
842 date32_cast_dtype: ast::DataType,
843 supports_column_alias_in_table_alias: bool,
844 requires_derived_table_alias: bool,
845 division_operator: BinaryOperator,
846 window_func_support_window_frame: bool,
847 full_qualified_col: bool,
848 unnest_as_table_factor: bool,
849 unnest_as_lateral_flatten: bool,
850}
851
852impl Default for CustomDialect {
853 fn default() -> Self {
854 Self {
855 identifier_quote_style: None,
856 supports_nulls_first_in_sort: true,
857 use_timestamp_for_date64: false,
858 interval_style: IntervalStyle::SQLStandard,
859 float64_ast_dtype: ast::DataType::Double(ast::ExactNumberInfo::None),
860 utf8_cast_dtype: ast::DataType::Varchar(None),
861 large_utf8_cast_dtype: ast::DataType::Text,
862 date_field_extract_style: DateFieldExtractStyle::DatePart,
863 character_length_style: CharacterLengthStyle::CharacterLength,
864 int8_cast_dtype: ast::DataType::TinyInt(None),
865 int64_cast_dtype: ast::DataType::BigInt(None),
866 int32_cast_dtype: ast::DataType::Integer(None),
867 timestamp_cast_dtype: ast::DataType::Timestamp(None, TimezoneInfo::None),
868 timestamp_tz_cast_dtype: ast::DataType::Timestamp(
869 None,
870 TimezoneInfo::WithTimeZone,
871 ),
872 date32_cast_dtype: ast::DataType::Date,
873 supports_column_alias_in_table_alias: true,
874 requires_derived_table_alias: false,
875 division_operator: BinaryOperator::Divide,
876 window_func_support_window_frame: true,
877 full_qualified_col: false,
878 unnest_as_table_factor: false,
879 unnest_as_lateral_flatten: false,
880 }
881 }
882}
883
884impl Dialect for CustomDialect {
885 fn identifier_quote_style(&self, _: &str) -> Option<char> {
886 self.identifier_quote_style
887 }
888
889 fn supports_nulls_first_in_sort(&self) -> bool {
890 self.supports_nulls_first_in_sort
891 }
892
893 fn use_timestamp_for_date64(&self) -> bool {
894 self.use_timestamp_for_date64
895 }
896
897 fn interval_style(&self) -> IntervalStyle {
898 self.interval_style
899 }
900
901 fn float64_ast_dtype(&self) -> ast::DataType {
902 self.float64_ast_dtype.clone()
903 }
904
905 fn utf8_cast_dtype(&self) -> ast::DataType {
906 self.utf8_cast_dtype.clone()
907 }
908
909 fn large_utf8_cast_dtype(&self) -> ast::DataType {
910 self.large_utf8_cast_dtype.clone()
911 }
912
913 fn date_field_extract_style(&self) -> DateFieldExtractStyle {
914 self.date_field_extract_style
915 }
916
917 fn character_length_style(&self) -> CharacterLengthStyle {
918 self.character_length_style
919 }
920
921 fn int64_cast_dtype(&self) -> ast::DataType {
922 self.int64_cast_dtype.clone()
923 }
924
925 fn int8_cast_dtype(&self) -> ast::DataType {
926 self.int8_cast_dtype.clone()
927 }
928
929 fn int32_cast_dtype(&self) -> ast::DataType {
930 self.int32_cast_dtype.clone()
931 }
932
933 fn timestamp_cast_dtype(
934 &self,
935 _time_unit: &TimeUnit,
936 tz: &Option<Arc<str>>,
937 ) -> ast::DataType {
938 if tz.is_some() {
939 self.timestamp_tz_cast_dtype.clone()
940 } else {
941 self.timestamp_cast_dtype.clone()
942 }
943 }
944
945 fn date32_cast_dtype(&self) -> ast::DataType {
946 self.date32_cast_dtype.clone()
947 }
948
949 fn supports_column_alias_in_table_alias(&self) -> bool {
950 self.supports_column_alias_in_table_alias
951 }
952
953 fn scalar_function_to_sql_overrides(
954 &self,
955 unparser: &Unparser,
956 func_name: &str,
957 args: &[Expr],
958 ) -> Result<Option<ast::Expr>> {
959 match func_name {
960 "date_part" => {
961 date_part_to_sql(unparser, self.date_field_extract_style(), args)
962 }
963 "character_length" => {
964 character_length_to_sql(unparser, self.character_length_style(), args)
965 }
966 _ => Ok(None),
967 }
968 }
969
970 fn requires_derived_table_alias(&self) -> bool {
971 self.requires_derived_table_alias
972 }
973
974 fn division_operator(&self) -> BinaryOperator {
975 self.division_operator.clone()
976 }
977
978 fn window_func_support_window_frame(
979 &self,
980 _func_name: &str,
981 _start_bound: &WindowFrameBound,
982 _end_bound: &WindowFrameBound,
983 ) -> bool {
984 self.window_func_support_window_frame
985 }
986
987 fn full_qualified_col(&self) -> bool {
988 self.full_qualified_col
989 }
990
991 fn unnest_as_table_factor(&self) -> bool {
992 self.unnest_as_table_factor
993 }
994
995 fn unnest_as_lateral_flatten(&self) -> bool {
996 self.unnest_as_lateral_flatten
997 }
998}
999
1000pub struct CustomDialectBuilder {
1015 identifier_quote_style: Option<char>,
1016 supports_nulls_first_in_sort: bool,
1017 use_timestamp_for_date64: bool,
1018 interval_style: IntervalStyle,
1019 float64_ast_dtype: ast::DataType,
1020 utf8_cast_dtype: ast::DataType,
1021 large_utf8_cast_dtype: ast::DataType,
1022 date_field_extract_style: DateFieldExtractStyle,
1023 character_length_style: CharacterLengthStyle,
1024 int8_cast_dtype: ast::DataType,
1025 int64_cast_dtype: ast::DataType,
1026 int32_cast_dtype: ast::DataType,
1027 timestamp_cast_dtype: ast::DataType,
1028 timestamp_tz_cast_dtype: ast::DataType,
1029 date32_cast_dtype: ast::DataType,
1030 supports_column_alias_in_table_alias: bool,
1031 requires_derived_table_alias: bool,
1032 division_operator: BinaryOperator,
1033 window_func_support_window_frame: bool,
1034 full_qualified_col: bool,
1035 unnest_as_table_factor: bool,
1036 unnest_as_lateral_flatten: bool,
1037}
1038
1039impl Default for CustomDialectBuilder {
1040 fn default() -> Self {
1041 Self::new()
1042 }
1043}
1044
1045impl CustomDialectBuilder {
1046 pub fn new() -> Self {
1047 Self {
1048 identifier_quote_style: None,
1049 supports_nulls_first_in_sort: true,
1050 use_timestamp_for_date64: false,
1051 interval_style: IntervalStyle::PostgresVerbose,
1052 float64_ast_dtype: ast::DataType::Double(ast::ExactNumberInfo::None),
1053 utf8_cast_dtype: ast::DataType::Varchar(None),
1054 large_utf8_cast_dtype: ast::DataType::Text,
1055 date_field_extract_style: DateFieldExtractStyle::DatePart,
1056 character_length_style: CharacterLengthStyle::CharacterLength,
1057 int8_cast_dtype: ast::DataType::TinyInt(None),
1058 int64_cast_dtype: ast::DataType::BigInt(None),
1059 int32_cast_dtype: ast::DataType::Integer(None),
1060 timestamp_cast_dtype: ast::DataType::Timestamp(None, TimezoneInfo::None),
1061 timestamp_tz_cast_dtype: ast::DataType::Timestamp(
1062 None,
1063 TimezoneInfo::WithTimeZone,
1064 ),
1065 date32_cast_dtype: ast::DataType::Date,
1066 supports_column_alias_in_table_alias: true,
1067 requires_derived_table_alias: false,
1068 division_operator: BinaryOperator::Divide,
1069 window_func_support_window_frame: true,
1070 full_qualified_col: false,
1071 unnest_as_table_factor: false,
1072 unnest_as_lateral_flatten: false,
1073 }
1074 }
1075
1076 pub fn build(self) -> CustomDialect {
1077 CustomDialect {
1078 identifier_quote_style: self.identifier_quote_style,
1079 supports_nulls_first_in_sort: self.supports_nulls_first_in_sort,
1080 use_timestamp_for_date64: self.use_timestamp_for_date64,
1081 interval_style: self.interval_style,
1082 float64_ast_dtype: self.float64_ast_dtype,
1083 utf8_cast_dtype: self.utf8_cast_dtype,
1084 large_utf8_cast_dtype: self.large_utf8_cast_dtype,
1085 date_field_extract_style: self.date_field_extract_style,
1086 character_length_style: self.character_length_style,
1087 int8_cast_dtype: self.int8_cast_dtype,
1088 int64_cast_dtype: self.int64_cast_dtype,
1089 int32_cast_dtype: self.int32_cast_dtype,
1090 timestamp_cast_dtype: self.timestamp_cast_dtype,
1091 timestamp_tz_cast_dtype: self.timestamp_tz_cast_dtype,
1092 date32_cast_dtype: self.date32_cast_dtype,
1093 supports_column_alias_in_table_alias: self
1094 .supports_column_alias_in_table_alias,
1095 requires_derived_table_alias: self.requires_derived_table_alias,
1096 division_operator: self.division_operator,
1097 window_func_support_window_frame: self.window_func_support_window_frame,
1098 full_qualified_col: self.full_qualified_col,
1099 unnest_as_table_factor: self.unnest_as_table_factor,
1100 unnest_as_lateral_flatten: self.unnest_as_lateral_flatten,
1101 }
1102 }
1103
1104 pub fn with_identifier_quote_style(mut self, identifier_quote_style: char) -> Self {
1106 self.identifier_quote_style = Some(identifier_quote_style);
1107 self
1108 }
1109
1110 pub fn with_supports_nulls_first_in_sort(
1112 mut self,
1113 supports_nulls_first_in_sort: bool,
1114 ) -> Self {
1115 self.supports_nulls_first_in_sort = supports_nulls_first_in_sort;
1116 self
1117 }
1118
1119 pub fn with_use_timestamp_for_date64(
1121 mut self,
1122 use_timestamp_for_date64: bool,
1123 ) -> Self {
1124 self.use_timestamp_for_date64 = use_timestamp_for_date64;
1125 self
1126 }
1127
1128 pub fn with_interval_style(mut self, interval_style: IntervalStyle) -> Self {
1130 self.interval_style = interval_style;
1131 self
1132 }
1133
1134 pub fn with_character_length_style(
1136 mut self,
1137 character_length_style: CharacterLengthStyle,
1138 ) -> Self {
1139 self.character_length_style = character_length_style;
1140 self
1141 }
1142
1143 pub fn with_int8_cast_dtype(mut self, int8_cast_dtype: ast::DataType) -> Self {
1145 self.int8_cast_dtype = int8_cast_dtype;
1146 self
1147 }
1148
1149 pub fn with_float64_ast_dtype(mut self, float64_ast_dtype: ast::DataType) -> Self {
1151 self.float64_ast_dtype = float64_ast_dtype;
1152 self
1153 }
1154
1155 pub fn with_utf8_cast_dtype(mut self, utf8_cast_dtype: ast::DataType) -> Self {
1157 self.utf8_cast_dtype = utf8_cast_dtype;
1158 self
1159 }
1160
1161 pub fn with_large_utf8_cast_dtype(
1163 mut self,
1164 large_utf8_cast_dtype: ast::DataType,
1165 ) -> Self {
1166 self.large_utf8_cast_dtype = large_utf8_cast_dtype;
1167 self
1168 }
1169
1170 pub fn with_date_field_extract_style(
1172 mut self,
1173 date_field_extract_style: DateFieldExtractStyle,
1174 ) -> Self {
1175 self.date_field_extract_style = date_field_extract_style;
1176 self
1177 }
1178
1179 pub fn with_int64_cast_dtype(mut self, int64_cast_dtype: ast::DataType) -> Self {
1181 self.int64_cast_dtype = int64_cast_dtype;
1182 self
1183 }
1184
1185 pub fn with_int32_cast_dtype(mut self, int32_cast_dtype: ast::DataType) -> Self {
1187 self.int32_cast_dtype = int32_cast_dtype;
1188 self
1189 }
1190
1191 pub fn with_timestamp_cast_dtype(
1193 mut self,
1194 timestamp_cast_dtype: ast::DataType,
1195 timestamp_tz_cast_dtype: ast::DataType,
1196 ) -> Self {
1197 self.timestamp_cast_dtype = timestamp_cast_dtype;
1198 self.timestamp_tz_cast_dtype = timestamp_tz_cast_dtype;
1199 self
1200 }
1201
1202 pub fn with_date32_cast_dtype(mut self, date32_cast_dtype: ast::DataType) -> Self {
1203 self.date32_cast_dtype = date32_cast_dtype;
1204 self
1205 }
1206
1207 pub fn with_supports_column_alias_in_table_alias(
1209 mut self,
1210 supports_column_alias_in_table_alias: bool,
1211 ) -> Self {
1212 self.supports_column_alias_in_table_alias = supports_column_alias_in_table_alias;
1213 self
1214 }
1215
1216 pub fn with_requires_derived_table_alias(
1217 mut self,
1218 requires_derived_table_alias: bool,
1219 ) -> Self {
1220 self.requires_derived_table_alias = requires_derived_table_alias;
1221 self
1222 }
1223
1224 pub fn with_division_operator(mut self, division_operator: BinaryOperator) -> Self {
1225 self.division_operator = division_operator;
1226 self
1227 }
1228
1229 pub fn with_window_func_support_window_frame(
1230 mut self,
1231 window_func_support_window_frame: bool,
1232 ) -> Self {
1233 self.window_func_support_window_frame = window_func_support_window_frame;
1234 self
1235 }
1236
1237 pub fn with_full_qualified_col(mut self, full_qualified_col: bool) -> Self {
1239 self.full_qualified_col = full_qualified_col;
1240 self
1241 }
1242
1243 pub fn with_unnest_as_table_factor(mut self, unnest_as_table_factor: bool) -> Self {
1244 self.unnest_as_table_factor = unnest_as_table_factor;
1245 self
1246 }
1247
1248 pub fn with_unnest_as_lateral_flatten(
1249 mut self,
1250 unnest_as_lateral_flatten: bool,
1251 ) -> Self {
1252 self.unnest_as_lateral_flatten = unnest_as_lateral_flatten;
1253 self
1254 }
1255}