Skip to content

Commit 41e8bb7

Browse files
authored
Merge pull request #3 from finchxxia/feature/snowflake-multi-table-insert-v2
[Chore] use multi table insert type in struct
2 parents 9a2cd6e + fc5e207 commit 41e8bb7

7 files changed

Lines changed: 54 additions & 30 deletions

File tree

src/ast/dml.rs

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,14 @@ pub struct Insert {
9090
///
9191
/// [ClickHouse formats JSON insert](https://clickhouse.com/docs/en/interfaces/formats#json-inserting-data)
9292
pub format_clause: Option<InputFormatClause>,
93-
/// For multi-table insert: `INSERT FIRST` vs `INSERT ALL`
93+
/// For Snowflake multi-table insert: specifies the type (`ALL` or `FIRST`)
9494
///
95-
/// When `true`, this is an `INSERT FIRST` statement (only the first matching WHEN clause is executed).
96-
/// When `false` with non-empty `clauses`, this is an `INSERT ALL` statement.
95+
/// - `None` means this is a regular single-table INSERT
96+
/// - `Some(All)` means `INSERT ALL` (all matching WHEN clauses are executed)
97+
/// - `Some(First)` means `INSERT FIRST` (only the first matching WHEN clause is executed)
9798
///
9899
/// See: <https://docs.snowflake.com/en/sql-reference/sql/insert-multi-table>
99-
pub insert_first: bool,
100+
pub multi_table_insert_type: Option<MultiTableInsertType>,
100101
/// For multi-table insert: additional INTO clauses (unconditional)
101102
///
102103
/// Used for `INSERT ALL INTO t1 INTO t2 ... SELECT ...`
@@ -117,9 +118,7 @@ pub struct Insert {
117118

118119
impl Display for Insert {
119120
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120-
// Check if this is a Snowflake multi-table insert
121-
let is_multi_table = !self.multi_table_into_clauses.is_empty()
122-
|| !self.multi_table_when_clauses.is_empty();
121+
let is_multi_table = self.multi_table_insert_type.is_some();
123122

124123
// SQLite OR conflict has a special format: INSERT OR ... INTO table_name
125124
if let Some(on_conflict) = self.or {
@@ -148,8 +147,8 @@ impl Display for Insert {
148147
write!(f, " OVERWRITE")?;
149148
}
150149

151-
if is_multi_table {
152-
write!(f, " {}", if self.insert_first { "FIRST" } else { "ALL" })?;
150+
if let Some(insert_type) = &self.multi_table_insert_type {
151+
write!(f, " {}", insert_type)?;
153152
}
154153

155154
if self.into {
@@ -815,3 +814,25 @@ impl Display for MultiTableInsertValue {
815814
}
816815
}
817816
}
817+
818+
/// The type of multi-table INSERT statement(Snowflake).
819+
///
820+
/// See: <https://docs.snowflake.com/en/sql-reference/sql/insert-multi-table>
821+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
822+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
823+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
824+
pub enum MultiTableInsertType {
825+
/// `INSERT ALL` - all matching WHEN clauses are executed
826+
All,
827+
/// `INSERT FIRST` - only the first matching WHEN clause is executed
828+
First,
829+
}
830+
831+
impl Display for MultiTableInsertType {
832+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
833+
match self {
834+
MultiTableInsertType::All => write!(f, "ALL"),
835+
MultiTableInsertType::First => write!(f, "FIRST"),
836+
}
837+
}
838+
}

src/ast/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ pub use self::ddl::{
8181
};
8282
pub use self::dml::{
8383
Delete, Insert, Merge, MergeAction, MergeClause, MergeClauseKind, MergeInsertExpr,
84-
MergeInsertKind, MergeUpdateExpr, MultiTableInsertIntoClause, MultiTableInsertValue,
85-
MultiTableInsertValues, MultiTableInsertWhenClause, OutputClause, Update,
84+
MergeInsertKind, MergeUpdateExpr, MultiTableInsertIntoClause, MultiTableInsertType,
85+
MultiTableInsertValue, MultiTableInsertValues, MultiTableInsertWhenClause, OutputClause, Update,
8686
};
8787
pub use self::operator::{BinaryOperator, UnaryOperator};
8888
pub use self::query::{

src/ast/spans.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1306,7 +1306,7 @@ impl Spanned for Insert {
13061306
assignments,
13071307
settings: _, // todo, clickhouse specific
13081308
format_clause: _, // todo, clickhouse specific
1309-
insert_first: _, // snowflake multi-table insert
1309+
multi_table_insert_type: _, // snowflake multi-table insert
13101310
multi_table_into_clauses: _, // snowflake multi-table insert
13111311
multi_table_when_clauses: _, // snowflake multi-table insert
13121312
multi_table_else_clause: _, // snowflake multi-table insert

src/dialect/snowflake.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ use crate::ast::{
3131
ColumnPolicy, ColumnPolicyProperty, ContactEntry, CopyIntoSnowflakeKind, CreateTableLikeKind,
3232
DollarQuotedString, Ident, IdentityParameters, IdentityProperty, IdentityPropertyFormatKind,
3333
IdentityPropertyKind, IdentityPropertyOrder, InitializeKind, Insert, MultiTableInsertIntoClause,
34-
MultiTableInsertValue, MultiTableInsertValues, MultiTableInsertWhenClause, ObjectName,
35-
ObjectNamePart, RefreshModeKind, RowAccessPolicy, ShowObjects, SqlOption, Statement,
34+
MultiTableInsertType, MultiTableInsertValue, MultiTableInsertValues, MultiTableInsertWhenClause,
35+
ObjectName, ObjectNamePart, RefreshModeKind, RowAccessPolicy, ShowObjects, SqlOption, Statement,
3636
StorageSerializationPolicy, TableObject, TagsColumnOption, Value, WrappedCollection,
3737
};
3838
use crate::tokenizer::TokenWithSpan;
@@ -328,12 +328,15 @@ impl Dialect for SnowflakeDialect {
328328

329329
// Check for ALL or FIRST keyword
330330
if let Some(kw) = parser.parse_one_of_keywords(&[Keyword::ALL, Keyword::FIRST]) {
331-
let insert_first = kw == Keyword::FIRST;
331+
let multi_table_insert_type = match kw {
332+
Keyword::FIRST => MultiTableInsertType::First,
333+
_ => MultiTableInsertType::All,
334+
};
332335
return Some(parse_multi_table_insert(
333336
parser,
334337
insert_token,
335338
overwrite,
336-
insert_first,
339+
multi_table_insert_type,
337340
));
338341
}
339342

@@ -1677,7 +1680,7 @@ fn parse_multi_table_insert(
16771680
parser: &mut Parser,
16781681
insert_token: TokenWithSpan,
16791682
overwrite: bool,
1680-
insert_first: bool,
1683+
multi_table_insert_type: MultiTableInsertType,
16811684
) -> Result<Statement, ParserError> {
16821685
// Check if this is conditional (has WHEN clauses) or unconditional (direct INTO clauses)
16831686
let is_conditional = parser.peek_keyword(Keyword::WHEN);
@@ -1717,7 +1720,7 @@ fn parse_multi_table_insert(
17171720
insert_alias: None,
17181721
settings: None,
17191722
format_clause: None,
1720-
insert_first,
1723+
multi_table_insert_type: Some(multi_table_insert_type),
17211724
multi_table_into_clauses,
17221725
multi_table_when_clauses,
17231726
multi_table_else_clause,

src/parser/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16618,7 +16618,7 @@ impl<'a> Parser<'a> {
1661816618
insert_alias,
1661916619
settings,
1662016620
format_clause,
16621-
insert_first: false,
16621+
multi_table_insert_type: None,
1662216622
multi_table_into_clauses: vec![],
1662316623
multi_table_when_clauses: vec![],
1662416624
multi_table_else_clause: None,

tests/sqlparser_postgres.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5370,7 +5370,7 @@ fn test_simple_postgres_insert_with_alias() {
53705370
insert_alias: None,
53715371
settings: None,
53725372
format_clause: None,
5373-
insert_first: false,
5373+
multi_table_insert_type: None,
53745374
multi_table_into_clauses: vec![],
53755375
multi_table_when_clauses: vec![],
53765376
multi_table_else_clause: None,
@@ -5448,7 +5448,7 @@ fn test_simple_postgres_insert_with_alias() {
54485448
insert_alias: None,
54495449
settings: None,
54505450
format_clause: None,
5451-
insert_first: false,
5451+
multi_table_insert_type: None,
54525452
multi_table_into_clauses: vec![],
54535453
multi_table_when_clauses: vec![],
54545454
multi_table_else_clause: None,
@@ -5524,7 +5524,7 @@ fn test_simple_insert_with_quoted_alias() {
55245524
insert_alias: None,
55255525
settings: None,
55265526
format_clause: None,
5527-
insert_first: false,
5527+
multi_table_insert_type: None,
55285528
multi_table_into_clauses: vec![],
55295529
multi_table_when_clauses: vec![],
55305530
multi_table_else_clause: None,

tests/sqlparser_snowflake.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3616,7 +3616,7 @@ fn test_multi_table_insert_ast_unconditional() {
36163616

36173617
match stmt {
36183618
Statement::Insert(Insert {
3619-
insert_first,
3619+
multi_table_insert_type,
36203620
overwrite,
36213621
multi_table_into_clauses,
36223622
multi_table_when_clauses,
@@ -3625,7 +3625,7 @@ fn test_multi_table_insert_ast_unconditional() {
36253625
..
36263626
}) => {
36273627
// Should be INSERT ALL (not FIRST)
3628-
assert!(!insert_first);
3628+
assert_eq!(multi_table_insert_type, Some(MultiTableInsertType::All));
36293629
assert!(!overwrite);
36303630

36313631
// Should have 2 INTO clauses
@@ -3709,14 +3709,14 @@ fn test_multi_table_insert_ast_conditional() {
37093709

37103710
match stmt {
37113711
Statement::Insert(Insert {
3712-
insert_first,
3712+
multi_table_insert_type,
37133713
multi_table_into_clauses,
37143714
multi_table_when_clauses,
37153715
multi_table_else_clause,
37163716
..
37173717
}) => {
37183718
// Should be INSERT ALL (not FIRST)
3719-
assert!(!insert_first);
3719+
assert_eq!(multi_table_insert_type, Some(MultiTableInsertType::All));
37203720

37213721
// Unconditional INTO clauses should be empty for conditional insert
37223722
assert!(multi_table_into_clauses.is_empty());
@@ -3752,12 +3752,12 @@ fn test_multi_table_insert_ast_first() {
37523752

37533753
match stmt {
37543754
Statement::Insert(Insert {
3755-
insert_first,
3755+
multi_table_insert_type,
37563756
multi_table_when_clauses,
37573757
..
37583758
}) => {
37593759
// Should be INSERT FIRST
3760-
assert!(insert_first);
3760+
assert_eq!(multi_table_insert_type, Some(MultiTableInsertType::First));
37613761
assert_eq!(multi_table_when_clauses.len(), 2);
37623762
}
37633763
_ => panic!("Expected INSERT statement"),
@@ -3773,12 +3773,12 @@ fn test_multi_table_insert_ast_overwrite() {
37733773
match stmt {
37743774
Statement::Insert(Insert {
37753775
overwrite,
3776-
insert_first,
3776+
multi_table_insert_type,
37773777
multi_table_into_clauses,
37783778
..
37793779
}) => {
37803780
assert!(overwrite);
3781-
assert!(!insert_first);
3781+
assert_eq!(multi_table_insert_type, Some(MultiTableInsertType::All));
37823782
assert_eq!(multi_table_into_clauses.len(), 2);
37833783
}
37843784
_ => panic!("Expected INSERT statement"),

0 commit comments

Comments
 (0)