Commit 192ceb6
Snowflake Unparser dialect and UNNEST support (#21593)
## Which issue does this PR close?
- Closes #21592.
## Rationale for this change
The SQL unparser needs a Snowflake dialect. Basic dialect settings
(identifier quoting, `NULLS FIRST`/`NULLS LAST`, timestamp types) are
straightforward, but `UNNEST` support required more than configuration.
Snowflake has no `UNNEST` keyword. Its equivalent, `LATERAL
FLATTEN(INPUT => expr)`, is a table function in the `FROM` clause with
output accessed via `alias."VALUE"`. This differs structurally from
standard SQL: the unparser must emit a `FROM`-clause table factor with a
`CROSS JOIN` instead of a `SELECT`-clause expression. It also must
rewrite column references to point at the FLATTEN output, and handle
several optimizer-produced plan shapes (intermediate `Limit`/`Sort`
nodes, `SubqueryAlias` wrappers, composed expressions wrapping the
unnest output, multi-expression projections). None of this can be
expressed through `CustomDialectBuilder`.
## What changes are included in this PR?
**`dialect.rs`** - New `SnowflakeDialect` with double-quote identifiers,
`NULLS FIRST`/`NULLS LAST`, no empty select lists, no column aliases in
table aliases, Snowflake timestamp types, and
`unnest_as_lateral_flatten()`. Also wired into
`CustomDialect`/`CustomDialectBuilder`.
**`ast.rs`** - New `FlattenRelationBuilder` that produces `LATERAL
FLATTEN(INPUT => expr, OUTER => bool)` table factors, parallel to the
existing `UnnestRelationBuilder`.
**`utils.rs`** - New `unproject_unnest_expr_as_flatten_value` transform
that rewrites unnest placeholder columns to `_unnest.VALUE` references.
**`plan.rs`** - Changes to `select_to_sql_recursively`:
- The `Projection` handler scans all expressions for unnest placeholders
(not just single-expression projections), then branches into the FLATTEN
path or the existing table-factor path.
- `peel_to_unnest_with_modifiers` walks through `Limit`/`Sort` nodes
between `Projection` and `Unnest`, applying their SQL modifiers to the
query builder. This handles an optimizer behavior where these nodes are
inserted between the two.
- `peel_to_inner_projection` walks through `SubqueryAlias` to find the
inner `Projection` that feeds an `Unnest`.
- `reconstruct_select_statement` gained FLATTEN-aware expression
rewriting and a `has_internal_unnest_alias` predicate to strip internal
`UNNEST(...)` display names.
- The `Unnest` handler rejects struct columns for the FLATTEN dialect
with a clear error.
## Are these changes tested?
Yes. 18 new tests covering:
- Simple inline arrays, string arrays, cross joins
- Implicit `FROM` (UNNEST in SELECT clause)
- User aliases, table aliases, literal + unnest
- Subselect source with filters and limit
- UDF result as FLATTEN input
- `Limit` between `Projection` and `Unnest`
- `Sort` between `Projection` and `Unnest`
- `Limit` + `SubqueryAlias` combined
- Composed expressions wrapping unnest output (e.g. `CAST`)
- Composed expressions with `Limit`
- Multi-expression projections
- Multi-expression projections with `Limit`
- `SubqueryAlias` between `Unnest` and inner `Projection`
## Are there any user-facing changes?
Yes. New public API surface:
- `SnowflakeDialect` struct and its constructor
- `Dialect::unnest_as_lateral_flatten()` method (default `false`)
- `CustomDialectBuilder::with_unnest_as_lateral_flatten()`
- `FlattenRelationBuilder` and `FLATTEN_DEFAULT_ALIAS` in the AST module
None of these are breaking changes, and all previous APIs should work.
New traits have default implementations to ease migrations.
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent 5f8b131 commit 192ceb6
7 files changed
Lines changed: 1418 additions & 43 deletions
File tree
- datafusion/sql
- src/unparser
- tests
- cases
- common
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
162 | 162 | | |
163 | 163 | | |
164 | 164 | | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
165 | 170 | | |
166 | 171 | | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
167 | 175 | | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
168 | 211 | | |
169 | 212 | | |
170 | 213 | | |
| |||
371 | 414 | | |
372 | 415 | | |
373 | 416 | | |
| 417 | + | |
| 418 | + | |
374 | 419 | | |
375 | 420 | | |
376 | 421 | | |
| |||
432 | 477 | | |
433 | 478 | | |
434 | 479 | | |
435 | | - | |
436 | 480 | | |
437 | 481 | | |
438 | 482 | | |
439 | 483 | | |
| 484 | + | |
440 | 485 | | |
441 | 486 | | |
442 | 487 | | |
| |||
458 | 503 | | |
459 | 504 | | |
460 | 505 | | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
461 | 511 | | |
462 | 512 | | |
463 | 513 | | |
| |||
474 | 524 | | |
475 | 525 | | |
476 | 526 | | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
477 | 530 | | |
478 | 531 | | |
479 | 532 | | |
| |||
484 | 537 | | |
485 | 538 | | |
486 | 539 | | |
| 540 | + | |
487 | 541 | | |
488 | 542 | | |
489 | 543 | | |
| |||
688 | 742 | | |
689 | 743 | | |
690 | 744 | | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
| 789 | + | |
| 790 | + | |
| 791 | + | |
| 792 | + | |
| 793 | + | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
| 801 | + | |
| 802 | + | |
| 803 | + | |
| 804 | + | |
| 805 | + | |
| 806 | + | |
| 807 | + | |
| 808 | + | |
| 809 | + | |
| 810 | + | |
| 811 | + | |
| 812 | + | |
| 813 | + | |
| 814 | + | |
| 815 | + | |
691 | 816 | | |
692 | 817 | | |
693 | 818 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
211 | 211 | | |
212 | 212 | | |
213 | 213 | | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
214 | 223 | | |
215 | 224 | | |
216 | 225 | | |
| |||
718 | 727 | | |
719 | 728 | | |
720 | 729 | | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
721 | 783 | | |
722 | 784 | | |
723 | 785 | | |
| |||
740 | 802 | | |
741 | 803 | | |
742 | 804 | | |
| 805 | + | |
743 | 806 | | |
744 | 807 | | |
745 | 808 | | |
| |||
769 | 832 | | |
770 | 833 | | |
771 | 834 | | |
| 835 | + | |
772 | 836 | | |
773 | 837 | | |
774 | 838 | | |
| |||
883 | 947 | | |
884 | 948 | | |
885 | 949 | | |
| 950 | + | |
| 951 | + | |
| 952 | + | |
| 953 | + | |
886 | 954 | | |
887 | 955 | | |
888 | 956 | | |
| |||
921 | 989 | | |
922 | 990 | | |
923 | 991 | | |
| 992 | + | |
924 | 993 | | |
925 | 994 | | |
926 | 995 | | |
| |||
956 | 1025 | | |
957 | 1026 | | |
958 | 1027 | | |
| 1028 | + | |
959 | 1029 | | |
960 | 1030 | | |
961 | 1031 | | |
| |||
983 | 1053 | | |
984 | 1054 | | |
985 | 1055 | | |
| 1056 | + | |
986 | 1057 | | |
987 | 1058 | | |
988 | 1059 | | |
| |||
1129 | 1200 | | |
1130 | 1201 | | |
1131 | 1202 | | |
| 1203 | + | |
| 1204 | + | |
| 1205 | + | |
| 1206 | + | |
| 1207 | + | |
| 1208 | + | |
| 1209 | + | |
| 1210 | + | |
1132 | 1211 | | |
0 commit comments