1use std::{collections::HashMap, sync::Arc};
19
20use super::{
21 utils::character_length_to_sql, utils::date_part_to_sql,
22 utils::sqlite_date_trunc_to_sql, utils::sqlite_from_unixtime_to_sql, Unparser,
23};
24use arrow::datatypes::TimeUnit;
25use datafusion_common::Result;
26use datafusion_expr::Expr;
27use regex::Regex;
28use sqlparser::tokenizer::Span;
29use sqlparser::{
30 ast::{
31 self, BinaryOperator, Function, Ident, ObjectName, TimezoneInfo, WindowFrameBound,
32 },
33 keywords::ALL_KEYWORDS,
34};
35
36pub type ScalarFnToSqlHandler =
37 Box<dyn Fn(&Unparser, &[Expr]) -> Result<Option<ast::Expr>> + Send + Sync>;
38
39pub trait Dialect: Send + Sync {
49 fn identifier_quote_style(&self, _identifier: &str) -> Option<char>;
51
52 fn supports_nulls_first_in_sort(&self) -> bool {
54 true
55 }
56
57 fn use_timestamp_for_date64(&self) -> bool {
60 false
61 }
62
63 fn interval_style(&self) -> IntervalStyle {
64 IntervalStyle::PostgresVerbose
65 }
66
67 fn float64_ast_dtype(&self) -> ast::DataType {
70 ast::DataType::Double(ast::ExactNumberInfo::None)
71 }
72
73 fn utf8_cast_dtype(&self) -> ast::DataType {
76 ast::DataType::Varchar(None)
77 }
78
79 fn large_utf8_cast_dtype(&self) -> ast::DataType {
82 ast::DataType::Text
83 }
84
85 fn date_field_extract_style(&self) -> DateFieldExtractStyle {
87 DateFieldExtractStyle::DatePart
88 }
89
90 fn character_length_style(&self) -> CharacterLengthStyle {
92 CharacterLengthStyle::CharacterLength
93 }
94
95 fn int64_cast_dtype(&self) -> ast::DataType {
98 ast::DataType::BigInt(None)
99 }
100
101 fn int32_cast_dtype(&self) -> ast::DataType {
104 ast::DataType::Integer(None)
105 }
106
107 fn timestamp_cast_dtype(
111 &self,
112 _time_unit: &TimeUnit,
113 tz: &Option<Arc<str>>,
114 ) -> ast::DataType {
115 let tz_info = match tz {
116 Some(_) => TimezoneInfo::WithTimeZone,
117 None => TimezoneInfo::None,
118 };
119
120 ast::DataType::Timestamp(None, tz_info)
121 }
122
123 fn date32_cast_dtype(&self) -> ast::DataType {
126 ast::DataType::Date
127 }
128
129 fn supports_column_alias_in_table_alias(&self) -> bool {
132 true
133 }
134
135 fn requires_derived_table_alias(&self) -> bool {
138 false
139 }
140
141 fn division_operator(&self) -> BinaryOperator {
145 BinaryOperator::Divide
146 }
147
148 fn scalar_function_to_sql_overrides(
152 &self,
153 _unparser: &Unparser,
154 _func_name: &str,
155 _args: &[Expr],
156 ) -> Result<Option<ast::Expr>> {
157 Ok(None)
158 }
159
160 fn window_func_support_window_frame(
164 &self,
165 _func_name: &str,
166 _start_bound: &WindowFrameBound,
167 _end_bound: &WindowFrameBound,
168 ) -> bool {
169 true
170 }
171
172 fn with_custom_scalar_overrides(
175 self,
176 _handlers: Vec<(&str, ScalarFnToSqlHandler)>,
177 ) -> Self
178 where
179 Self: Sized,
180 {
181 unimplemented!("Custom scalar overrides are not supported by this dialect yet");
182 }
183
184 fn full_qualified_col(&self) -> bool {
189 false
190 }
191
192 fn unnest_as_table_factor(&self) -> bool {
198 false
199 }
200}
201
202#[derive(Clone, Copy)]
211pub enum IntervalStyle {
212 PostgresVerbose,
213 SQLStandard,
214 MySQL,
215}
216
217#[derive(Clone, Copy, PartialEq)]
225pub enum DateFieldExtractStyle {
226 DatePart,
227 Extract,
228 Strftime,
229}
230
231#[derive(Clone, Copy, PartialEq)]
237pub enum CharacterLengthStyle {
238 Length,
239 CharacterLength,
240}
241
242pub struct DefaultDialect {}
243
244impl Dialect for DefaultDialect {
245 fn identifier_quote_style(&self, identifier: &str) -> Option<char> {
246 let identifier_regex = Regex::new(r"^[a-zA-Z_][a-zA-Z0-9_]*$").unwrap();
247 let id_upper = identifier.to_uppercase();
248 if (id_upper != "ID" && ALL_KEYWORDS.contains(&id_upper.as_str()))
251 || !identifier_regex.is_match(identifier)
252 {
253 Some('"')
254 } else {
255 None
256 }
257 }
258}
259
260pub struct PostgreSqlDialect {}
261
262impl Dialect for PostgreSqlDialect {
263 fn identifier_quote_style(&self, _: &str) -> Option<char> {
264 Some('"')
265 }
266
267 fn interval_style(&self) -> IntervalStyle {
268 IntervalStyle::PostgresVerbose
269 }
270
271 fn float64_ast_dtype(&self) -> ast::DataType {
272 ast::DataType::DoublePrecision
273 }
274
275 fn scalar_function_to_sql_overrides(
276 &self,
277 unparser: &Unparser,
278 func_name: &str,
279 args: &[Expr],
280 ) -> Result<Option<ast::Expr>> {
281 if func_name == "round" {
282 return Ok(Some(
283 self.round_to_sql_enforce_numeric(unparser, func_name, args)?,
284 ));
285 }
286
287 Ok(None)
288 }
289}
290
291impl PostgreSqlDialect {
292 fn round_to_sql_enforce_numeric(
293 &self,
294 unparser: &Unparser,
295 func_name: &str,
296 args: &[Expr],
297 ) -> Result<ast::Expr> {
298 let mut args = unparser.function_args_to_sql(args)?;
299
300 if let Some(ast::FunctionArg::Unnamed(ast::FunctionArgExpr::Expr(expr))) =
302 args.first_mut()
303 {
304 if let ast::Expr::Cast { data_type, .. } = expr {
305 *data_type = ast::DataType::Numeric(ast::ExactNumberInfo::None);
307 } else {
308 *expr = ast::Expr::Cast {
310 kind: ast::CastKind::Cast,
311 expr: Box::new(expr.clone()),
312 data_type: ast::DataType::Numeric(ast::ExactNumberInfo::None),
313 format: None,
314 };
315 }
316 }
317
318 Ok(ast::Expr::Function(Function {
319 name: ObjectName::from(vec![Ident {
320 value: func_name.to_string(),
321 quote_style: None,
322 span: Span::empty(),
323 }]),
324 args: ast::FunctionArguments::List(ast::FunctionArgumentList {
325 duplicate_treatment: None,
326 args,
327 clauses: vec![],
328 }),
329 filter: None,
330 null_treatment: None,
331 over: None,
332 within_group: vec![],
333 parameters: ast::FunctionArguments::None,
334 uses_odbc_syntax: false,
335 }))
336 }
337}
338
339#[derive(Default)]
340pub struct DuckDBDialect {
341 custom_scalar_fn_overrides: HashMap<String, ScalarFnToSqlHandler>,
342}
343
344impl DuckDBDialect {
345 #[must_use]
346 pub fn new() -> Self {
347 Self {
348 custom_scalar_fn_overrides: HashMap::new(),
349 }
350 }
351}
352
353impl Dialect for DuckDBDialect {
354 fn identifier_quote_style(&self, _: &str) -> Option<char> {
355 Some('"')
356 }
357
358 fn character_length_style(&self) -> CharacterLengthStyle {
359 CharacterLengthStyle::Length
360 }
361
362 fn division_operator(&self) -> BinaryOperator {
363 BinaryOperator::DuckIntegerDivide
364 }
365
366 fn with_custom_scalar_overrides(
367 mut self,
368 handlers: Vec<(&str, ScalarFnToSqlHandler)>,
369 ) -> Self {
370 for (func_name, handler) in handlers {
371 self.custom_scalar_fn_overrides
372 .insert(func_name.to_string(), handler);
373 }
374 self
375 }
376
377 fn scalar_function_to_sql_overrides(
378 &self,
379 unparser: &Unparser,
380 func_name: &str,
381 args: &[Expr],
382 ) -> Result<Option<ast::Expr>> {
383 if let Some(handler) = self.custom_scalar_fn_overrides.get(func_name) {
384 return handler(unparser, args);
385 }
386
387 if func_name == "character_length" {
388 return character_length_to_sql(
389 unparser,
390 self.character_length_style(),
391 args,
392 );
393 }
394
395 Ok(None)
396 }
397}
398
399pub struct MySqlDialect {}
400
401impl Dialect for MySqlDialect {
402 fn identifier_quote_style(&self, _: &str) -> Option<char> {
403 Some('`')
404 }
405
406 fn supports_nulls_first_in_sort(&self) -> bool {
407 false
408 }
409
410 fn interval_style(&self) -> IntervalStyle {
411 IntervalStyle::MySQL
412 }
413
414 fn utf8_cast_dtype(&self) -> ast::DataType {
415 ast::DataType::Char(None)
416 }
417
418 fn large_utf8_cast_dtype(&self) -> ast::DataType {
419 ast::DataType::Char(None)
420 }
421
422 fn date_field_extract_style(&self) -> DateFieldExtractStyle {
423 DateFieldExtractStyle::Extract
424 }
425
426 fn int64_cast_dtype(&self) -> ast::DataType {
427 ast::DataType::Custom(ObjectName::from(vec![Ident::new("SIGNED")]), vec![])
428 }
429
430 fn int32_cast_dtype(&self) -> ast::DataType {
431 ast::DataType::Custom(ObjectName::from(vec![Ident::new("SIGNED")]), vec![])
432 }
433
434 fn timestamp_cast_dtype(
435 &self,
436 _time_unit: &TimeUnit,
437 _tz: &Option<Arc<str>>,
438 ) -> ast::DataType {
439 ast::DataType::Datetime(None)
440 }
441
442 fn requires_derived_table_alias(&self) -> bool {
443 true
444 }
445
446 fn scalar_function_to_sql_overrides(
447 &self,
448 unparser: &Unparser,
449 func_name: &str,
450 args: &[Expr],
451 ) -> Result<Option<ast::Expr>> {
452 if func_name == "date_part" {
453 return date_part_to_sql(unparser, self.date_field_extract_style(), args);
454 }
455
456 Ok(None)
457 }
458}
459
460pub struct SqliteDialect {}
461
462impl Dialect for SqliteDialect {
463 fn identifier_quote_style(&self, _: &str) -> Option<char> {
464 Some('`')
465 }
466
467 fn date_field_extract_style(&self) -> DateFieldExtractStyle {
468 DateFieldExtractStyle::Strftime
469 }
470
471 fn date32_cast_dtype(&self) -> ast::DataType {
472 ast::DataType::Text
473 }
474
475 fn character_length_style(&self) -> CharacterLengthStyle {
476 CharacterLengthStyle::Length
477 }
478
479 fn supports_column_alias_in_table_alias(&self) -> bool {
480 false
481 }
482
483 fn scalar_function_to_sql_overrides(
484 &self,
485 unparser: &Unparser,
486 func_name: &str,
487 args: &[Expr],
488 ) -> Result<Option<ast::Expr>> {
489 match func_name {
490 "date_part" => {
491 date_part_to_sql(unparser, self.date_field_extract_style(), args)
492 }
493 "character_length" => {
494 character_length_to_sql(unparser, self.character_length_style(), args)
495 }
496 "from_unixtime" => sqlite_from_unixtime_to_sql(unparser, args),
497 "date_trunc" => sqlite_date_trunc_to_sql(unparser, args),
498 _ => Ok(None),
499 }
500 }
501}
502
503pub struct CustomDialect {
504 identifier_quote_style: Option<char>,
505 supports_nulls_first_in_sort: bool,
506 use_timestamp_for_date64: bool,
507 interval_style: IntervalStyle,
508 float64_ast_dtype: ast::DataType,
509 utf8_cast_dtype: ast::DataType,
510 large_utf8_cast_dtype: ast::DataType,
511 date_field_extract_style: DateFieldExtractStyle,
512 character_length_style: CharacterLengthStyle,
513 int64_cast_dtype: ast::DataType,
514 int32_cast_dtype: ast::DataType,
515 timestamp_cast_dtype: ast::DataType,
516 timestamp_tz_cast_dtype: ast::DataType,
517 date32_cast_dtype: ast::DataType,
518 supports_column_alias_in_table_alias: bool,
519 requires_derived_table_alias: bool,
520 division_operator: BinaryOperator,
521 window_func_support_window_frame: bool,
522 full_qualified_col: bool,
523 unnest_as_table_factor: bool,
524}
525
526impl Default for CustomDialect {
527 fn default() -> Self {
528 Self {
529 identifier_quote_style: None,
530 supports_nulls_first_in_sort: true,
531 use_timestamp_for_date64: false,
532 interval_style: IntervalStyle::SQLStandard,
533 float64_ast_dtype: ast::DataType::Double(ast::ExactNumberInfo::None),
534 utf8_cast_dtype: ast::DataType::Varchar(None),
535 large_utf8_cast_dtype: ast::DataType::Text,
536 date_field_extract_style: DateFieldExtractStyle::DatePart,
537 character_length_style: CharacterLengthStyle::CharacterLength,
538 int64_cast_dtype: ast::DataType::BigInt(None),
539 int32_cast_dtype: ast::DataType::Integer(None),
540 timestamp_cast_dtype: ast::DataType::Timestamp(None, TimezoneInfo::None),
541 timestamp_tz_cast_dtype: ast::DataType::Timestamp(
542 None,
543 TimezoneInfo::WithTimeZone,
544 ),
545 date32_cast_dtype: ast::DataType::Date,
546 supports_column_alias_in_table_alias: true,
547 requires_derived_table_alias: false,
548 division_operator: BinaryOperator::Divide,
549 window_func_support_window_frame: true,
550 full_qualified_col: false,
551 unnest_as_table_factor: false,
552 }
553 }
554}
555
556impl CustomDialect {
557 #[deprecated(since = "41.0.0", note = "please use `CustomDialectBuilder` instead")]
559 pub fn new(identifier_quote_style: Option<char>) -> Self {
560 Self {
561 identifier_quote_style,
562 ..Default::default()
563 }
564 }
565}
566
567impl Dialect for CustomDialect {
568 fn identifier_quote_style(&self, _: &str) -> Option<char> {
569 self.identifier_quote_style
570 }
571
572 fn supports_nulls_first_in_sort(&self) -> bool {
573 self.supports_nulls_first_in_sort
574 }
575
576 fn use_timestamp_for_date64(&self) -> bool {
577 self.use_timestamp_for_date64
578 }
579
580 fn interval_style(&self) -> IntervalStyle {
581 self.interval_style
582 }
583
584 fn float64_ast_dtype(&self) -> ast::DataType {
585 self.float64_ast_dtype.clone()
586 }
587
588 fn utf8_cast_dtype(&self) -> ast::DataType {
589 self.utf8_cast_dtype.clone()
590 }
591
592 fn large_utf8_cast_dtype(&self) -> ast::DataType {
593 self.large_utf8_cast_dtype.clone()
594 }
595
596 fn date_field_extract_style(&self) -> DateFieldExtractStyle {
597 self.date_field_extract_style
598 }
599
600 fn character_length_style(&self) -> CharacterLengthStyle {
601 self.character_length_style
602 }
603
604 fn int64_cast_dtype(&self) -> ast::DataType {
605 self.int64_cast_dtype.clone()
606 }
607
608 fn int32_cast_dtype(&self) -> ast::DataType {
609 self.int32_cast_dtype.clone()
610 }
611
612 fn timestamp_cast_dtype(
613 &self,
614 _time_unit: &TimeUnit,
615 tz: &Option<Arc<str>>,
616 ) -> ast::DataType {
617 if tz.is_some() {
618 self.timestamp_tz_cast_dtype.clone()
619 } else {
620 self.timestamp_cast_dtype.clone()
621 }
622 }
623
624 fn date32_cast_dtype(&self) -> ast::DataType {
625 self.date32_cast_dtype.clone()
626 }
627
628 fn supports_column_alias_in_table_alias(&self) -> bool {
629 self.supports_column_alias_in_table_alias
630 }
631
632 fn scalar_function_to_sql_overrides(
633 &self,
634 unparser: &Unparser,
635 func_name: &str,
636 args: &[Expr],
637 ) -> Result<Option<ast::Expr>> {
638 match func_name {
639 "date_part" => {
640 date_part_to_sql(unparser, self.date_field_extract_style(), args)
641 }
642 "character_length" => {
643 character_length_to_sql(unparser, self.character_length_style(), args)
644 }
645 _ => Ok(None),
646 }
647 }
648
649 fn requires_derived_table_alias(&self) -> bool {
650 self.requires_derived_table_alias
651 }
652
653 fn division_operator(&self) -> BinaryOperator {
654 self.division_operator.clone()
655 }
656
657 fn window_func_support_window_frame(
658 &self,
659 _func_name: &str,
660 _start_bound: &WindowFrameBound,
661 _end_bound: &WindowFrameBound,
662 ) -> bool {
663 self.window_func_support_window_frame
664 }
665
666 fn full_qualified_col(&self) -> bool {
667 self.full_qualified_col
668 }
669
670 fn unnest_as_table_factor(&self) -> bool {
671 self.unnest_as_table_factor
672 }
673}
674
675pub struct CustomDialectBuilder {
690 identifier_quote_style: Option<char>,
691 supports_nulls_first_in_sort: bool,
692 use_timestamp_for_date64: bool,
693 interval_style: IntervalStyle,
694 float64_ast_dtype: ast::DataType,
695 utf8_cast_dtype: ast::DataType,
696 large_utf8_cast_dtype: ast::DataType,
697 date_field_extract_style: DateFieldExtractStyle,
698 character_length_style: CharacterLengthStyle,
699 int64_cast_dtype: ast::DataType,
700 int32_cast_dtype: ast::DataType,
701 timestamp_cast_dtype: ast::DataType,
702 timestamp_tz_cast_dtype: ast::DataType,
703 date32_cast_dtype: ast::DataType,
704 supports_column_alias_in_table_alias: bool,
705 requires_derived_table_alias: bool,
706 division_operator: BinaryOperator,
707 window_func_support_window_frame: bool,
708 full_qualified_col: bool,
709 unnest_as_table_factor: bool,
710}
711
712impl Default for CustomDialectBuilder {
713 fn default() -> Self {
714 Self::new()
715 }
716}
717
718impl CustomDialectBuilder {
719 pub fn new() -> Self {
720 Self {
721 identifier_quote_style: None,
722 supports_nulls_first_in_sort: true,
723 use_timestamp_for_date64: false,
724 interval_style: IntervalStyle::PostgresVerbose,
725 float64_ast_dtype: ast::DataType::Double(ast::ExactNumberInfo::None),
726 utf8_cast_dtype: ast::DataType::Varchar(None),
727 large_utf8_cast_dtype: ast::DataType::Text,
728 date_field_extract_style: DateFieldExtractStyle::DatePart,
729 character_length_style: CharacterLengthStyle::CharacterLength,
730 int64_cast_dtype: ast::DataType::BigInt(None),
731 int32_cast_dtype: ast::DataType::Integer(None),
732 timestamp_cast_dtype: ast::DataType::Timestamp(None, TimezoneInfo::None),
733 timestamp_tz_cast_dtype: ast::DataType::Timestamp(
734 None,
735 TimezoneInfo::WithTimeZone,
736 ),
737 date32_cast_dtype: ast::DataType::Date,
738 supports_column_alias_in_table_alias: true,
739 requires_derived_table_alias: false,
740 division_operator: BinaryOperator::Divide,
741 window_func_support_window_frame: true,
742 full_qualified_col: false,
743 unnest_as_table_factor: false,
744 }
745 }
746
747 pub fn build(self) -> CustomDialect {
748 CustomDialect {
749 identifier_quote_style: self.identifier_quote_style,
750 supports_nulls_first_in_sort: self.supports_nulls_first_in_sort,
751 use_timestamp_for_date64: self.use_timestamp_for_date64,
752 interval_style: self.interval_style,
753 float64_ast_dtype: self.float64_ast_dtype,
754 utf8_cast_dtype: self.utf8_cast_dtype,
755 large_utf8_cast_dtype: self.large_utf8_cast_dtype,
756 date_field_extract_style: self.date_field_extract_style,
757 character_length_style: self.character_length_style,
758 int64_cast_dtype: self.int64_cast_dtype,
759 int32_cast_dtype: self.int32_cast_dtype,
760 timestamp_cast_dtype: self.timestamp_cast_dtype,
761 timestamp_tz_cast_dtype: self.timestamp_tz_cast_dtype,
762 date32_cast_dtype: self.date32_cast_dtype,
763 supports_column_alias_in_table_alias: self
764 .supports_column_alias_in_table_alias,
765 requires_derived_table_alias: self.requires_derived_table_alias,
766 division_operator: self.division_operator,
767 window_func_support_window_frame: self.window_func_support_window_frame,
768 full_qualified_col: self.full_qualified_col,
769 unnest_as_table_factor: self.unnest_as_table_factor,
770 }
771 }
772
773 pub fn with_identifier_quote_style(mut self, identifier_quote_style: char) -> Self {
775 self.identifier_quote_style = Some(identifier_quote_style);
776 self
777 }
778
779 pub fn with_supports_nulls_first_in_sort(
781 mut self,
782 supports_nulls_first_in_sort: bool,
783 ) -> Self {
784 self.supports_nulls_first_in_sort = supports_nulls_first_in_sort;
785 self
786 }
787
788 pub fn with_use_timestamp_for_date64(
790 mut self,
791 use_timestamp_for_date64: bool,
792 ) -> Self {
793 self.use_timestamp_for_date64 = use_timestamp_for_date64;
794 self
795 }
796
797 pub fn with_interval_style(mut self, interval_style: IntervalStyle) -> Self {
799 self.interval_style = interval_style;
800 self
801 }
802
803 pub fn with_character_length_style(
805 mut self,
806 character_length_style: CharacterLengthStyle,
807 ) -> Self {
808 self.character_length_style = character_length_style;
809 self
810 }
811
812 pub fn with_float64_ast_dtype(mut self, float64_ast_dtype: ast::DataType) -> Self {
814 self.float64_ast_dtype = float64_ast_dtype;
815 self
816 }
817
818 pub fn with_utf8_cast_dtype(mut self, utf8_cast_dtype: ast::DataType) -> Self {
820 self.utf8_cast_dtype = utf8_cast_dtype;
821 self
822 }
823
824 pub fn with_large_utf8_cast_dtype(
826 mut self,
827 large_utf8_cast_dtype: ast::DataType,
828 ) -> Self {
829 self.large_utf8_cast_dtype = large_utf8_cast_dtype;
830 self
831 }
832
833 pub fn with_date_field_extract_style(
835 mut self,
836 date_field_extract_style: DateFieldExtractStyle,
837 ) -> Self {
838 self.date_field_extract_style = date_field_extract_style;
839 self
840 }
841
842 pub fn with_int64_cast_dtype(mut self, int64_cast_dtype: ast::DataType) -> Self {
844 self.int64_cast_dtype = int64_cast_dtype;
845 self
846 }
847
848 pub fn with_int32_cast_dtype(mut self, int32_cast_dtype: ast::DataType) -> Self {
850 self.int32_cast_dtype = int32_cast_dtype;
851 self
852 }
853
854 pub fn with_timestamp_cast_dtype(
856 mut self,
857 timestamp_cast_dtype: ast::DataType,
858 timestamp_tz_cast_dtype: ast::DataType,
859 ) -> Self {
860 self.timestamp_cast_dtype = timestamp_cast_dtype;
861 self.timestamp_tz_cast_dtype = timestamp_tz_cast_dtype;
862 self
863 }
864
865 pub fn with_date32_cast_dtype(mut self, date32_cast_dtype: ast::DataType) -> Self {
866 self.date32_cast_dtype = date32_cast_dtype;
867 self
868 }
869
870 pub fn with_supports_column_alias_in_table_alias(
872 mut self,
873 supports_column_alias_in_table_alias: bool,
874 ) -> Self {
875 self.supports_column_alias_in_table_alias = supports_column_alias_in_table_alias;
876 self
877 }
878
879 pub fn with_requires_derived_table_alias(
880 mut self,
881 requires_derived_table_alias: bool,
882 ) -> Self {
883 self.requires_derived_table_alias = requires_derived_table_alias;
884 self
885 }
886
887 pub fn with_division_operator(mut self, division_operator: BinaryOperator) -> Self {
888 self.division_operator = division_operator;
889 self
890 }
891
892 pub fn with_window_func_support_window_frame(
893 mut self,
894 window_func_support_window_frame: bool,
895 ) -> Self {
896 self.window_func_support_window_frame = window_func_support_window_frame;
897 self
898 }
899
900 pub fn with_full_qualified_col(mut self, full_qualified_col: bool) -> Self {
902 self.full_qualified_col = full_qualified_col;
903 self
904 }
905
906 pub fn with_unnest_as_table_factor(mut self, unnest_as_table_factor: bool) -> Self {
907 self.unnest_as_table_factor = unnest_as_table_factor;
908 self
909 }
910}