@@ -206,6 +206,15 @@ pub trait Dialect: Send + Sync {
206206 false
207207 }
208208
209+ /// Unparse the unnest plan as `LATERAL FLATTEN(INPUT => expr, ...)`.
210+ ///
211+ /// Snowflake uses FLATTEN as a table function instead of the SQL-standard UNNEST.
212+ /// When this returns `true`, the unparser emits
213+ /// `LATERAL FLATTEN(INPUT => <col>, OUTER => <bool>)` in the FROM clause.
214+ fn unnest_as_lateral_flatten ( & self ) -> bool {
215+ false
216+ }
217+
209218 /// Allows the dialect to override column alias unparsing if the dialect has specific rules.
210219 /// Returns None if the default unparsing should be used, or Some(String) if there is
211220 /// a custom implementation for the alias.
@@ -664,6 +673,59 @@ impl BigQueryDialect {
664673 }
665674}
666675
676+ /// Dialect for Snowflake SQL.
677+ ///
678+ /// Key differences from the default dialect:
679+ /// - Uses double-quote identifier quoting
680+ /// - Supports `NULLS FIRST`/`NULLS LAST` in `ORDER BY`
681+ /// - Does not support empty select lists (`SELECT FROM t`)
682+ /// - Does not support column aliases in table alias definitions
683+ /// (Snowflake accepts the syntax but silently ignores the renames in join contexts)
684+ /// - Unparses `UNNEST` plans as `LATERAL FLATTEN(INPUT => expr, ...)`
685+ pub struct SnowflakeDialect { }
686+
687+ #[ expect( clippy:: new_without_default) ]
688+ impl SnowflakeDialect {
689+ #[ must_use]
690+ pub fn new ( ) -> Self {
691+ Self { }
692+ }
693+ }
694+
695+ impl Dialect for SnowflakeDialect {
696+ fn identifier_quote_style ( & self , _: & str ) -> Option < char > {
697+ Some ( '"' )
698+ }
699+
700+ fn supports_nulls_first_in_sort ( & self ) -> bool {
701+ true
702+ }
703+
704+ fn supports_empty_select_list ( & self ) -> bool {
705+ false
706+ }
707+
708+ fn supports_column_alias_in_table_alias ( & self ) -> bool {
709+ false
710+ }
711+
712+ fn timestamp_cast_dtype (
713+ & self ,
714+ _time_unit : & TimeUnit ,
715+ tz : & Option < Arc < str > > ,
716+ ) -> ast:: DataType {
717+ if tz. is_some ( ) {
718+ ast:: DataType :: Timestamp ( None , TimezoneInfo :: WithTimeZone )
719+ } else {
720+ ast:: DataType :: Timestamp ( None , TimezoneInfo :: None )
721+ }
722+ }
723+
724+ fn unnest_as_lateral_flatten ( & self ) -> bool {
725+ true
726+ }
727+ }
728+
667729pub struct CustomDialect {
668730 identifier_quote_style : Option < char > ,
669731 supports_nulls_first_in_sort : bool ,
@@ -686,6 +748,7 @@ pub struct CustomDialect {
686748 window_func_support_window_frame : bool ,
687749 full_qualified_col : bool ,
688750 unnest_as_table_factor : bool ,
751+ unnest_as_lateral_flatten : bool ,
689752}
690753
691754impl Default for CustomDialect {
@@ -715,6 +778,7 @@ impl Default for CustomDialect {
715778 window_func_support_window_frame : true ,
716779 full_qualified_col : false ,
717780 unnest_as_table_factor : false ,
781+ unnest_as_lateral_flatten : false ,
718782 }
719783 }
720784}
@@ -829,6 +893,10 @@ impl Dialect for CustomDialect {
829893 fn unnest_as_table_factor ( & self ) -> bool {
830894 self . unnest_as_table_factor
831895 }
896+
897+ fn unnest_as_lateral_flatten ( & self ) -> bool {
898+ self . unnest_as_lateral_flatten
899+ }
832900}
833901
834902/// `CustomDialectBuilder` to build `CustomDialect` using builder pattern
@@ -867,6 +935,7 @@ pub struct CustomDialectBuilder {
867935 window_func_support_window_frame : bool ,
868936 full_qualified_col : bool ,
869937 unnest_as_table_factor : bool ,
938+ unnest_as_lateral_flatten : bool ,
870939}
871940
872941impl Default for CustomDialectBuilder {
@@ -902,6 +971,7 @@ impl CustomDialectBuilder {
902971 window_func_support_window_frame : true ,
903972 full_qualified_col : false ,
904973 unnest_as_table_factor : false ,
974+ unnest_as_lateral_flatten : false ,
905975 }
906976 }
907977
@@ -929,6 +999,7 @@ impl CustomDialectBuilder {
929999 window_func_support_window_frame : self . window_func_support_window_frame ,
9301000 full_qualified_col : self . full_qualified_col ,
9311001 unnest_as_table_factor : self . unnest_as_table_factor ,
1002+ unnest_as_lateral_flatten : self . unnest_as_lateral_flatten ,
9321003 }
9331004 }
9341005
@@ -1075,4 +1146,12 @@ impl CustomDialectBuilder {
10751146 self . unnest_as_table_factor = unnest_as_table_factor;
10761147 self
10771148 }
1149+
1150+ pub fn with_unnest_as_lateral_flatten (
1151+ mut self ,
1152+ unnest_as_lateral_flatten : bool ,
1153+ ) -> Self {
1154+ self . unnest_as_lateral_flatten = unnest_as_lateral_flatten;
1155+ self
1156+ }
10781157}
0 commit comments