Skip to content

Commit 9a2cd6e

Browse files
authored
Merge pull request #2 from finchxxia/feature/snowflake-multi-table-insert-v2
Feature/snowflake multi table insert v2
2 parents f7e30b9 + ec1b168 commit 9a2cd6e

2 files changed

Lines changed: 104 additions & 103 deletions

File tree

src/ast/dml.rs

Lines changed: 100 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -121,131 +121,143 @@ impl Display for Insert {
121121
let is_multi_table = !self.multi_table_into_clauses.is_empty()
122122
|| !self.multi_table_when_clauses.is_empty();
123123

124-
if is_multi_table {
125-
// Snowflake multi-table INSERT format
126-
write!(f, "INSERT")?;
127-
if self.overwrite {
128-
write!(f, " OVERWRITE")?;
129-
}
130-
if self.insert_first {
131-
write!(f, " FIRST")?;
124+
// SQLite OR conflict has a special format: INSERT OR ... INTO table_name
125+
if let Some(on_conflict) = self.or {
126+
let table_name: String = if let Some(alias) = &self.table_alias {
127+
format!("{0} AS {alias}", self.table)
132128
} else {
133-
write!(f, " ALL")?;
129+
self.table.to_string()
130+
};
131+
write!(f, "INSERT {on_conflict} INTO {table_name} ")?;
132+
} else {
133+
write!(
134+
f,
135+
"{}",
136+
if self.replace_into { "REPLACE" } else { "INSERT" }
137+
)?;
138+
139+
if let Some(priority) = self.priority {
140+
write!(f, " {priority}")?;
134141
}
135142

136-
// Unconditional multi-table insert: INTO clauses directly after ALL
137-
for into_clause in &self.multi_table_into_clauses {
138-
SpaceOrNewline.fmt(f)?;
139-
write!(f, "{}", into_clause)?;
143+
if self.ignore {
144+
write!(f, " IGNORE")?;
140145
}
141146

142-
// Conditional multi-table insert: WHEN clauses
143-
for when_clause in &self.multi_table_when_clauses {
144-
SpaceOrNewline.fmt(f)?;
145-
write!(f, "{}", when_clause)?;
147+
if self.overwrite {
148+
write!(f, " OVERWRITE")?;
146149
}
147150

148-
// ELSE clause
149-
if let Some(else_clauses) = &self.multi_table_else_clause {
150-
SpaceOrNewline.fmt(f)?;
151-
write!(f, "ELSE")?;
152-
for into_clause in else_clauses {
153-
SpaceOrNewline.fmt(f)?;
154-
write!(f, "{}", into_clause)?;
155-
}
151+
if is_multi_table {
152+
write!(f, " {}", if self.insert_first { "FIRST" } else { "ALL" })?;
156153
}
157154

158-
// Source query
159-
if let Some(source) = &self.source {
160-
SpaceOrNewline.fmt(f)?;
161-
source.fmt(f)?;
155+
if self.into {
156+
write!(f, " INTO")?;
162157
}
163-
return Ok(());
164-
}
165158

166-
// Standard INSERT format
167-
let table_name = if let Some(alias) = &self.table_alias {
168-
format!("{0} AS {alias}", self.table)
169-
} else {
170-
self.table.to_string()
171-
};
159+
if self.has_table_keyword {
160+
write!(f, " TABLE")?;
161+
}
172162

173-
if let Some(on_conflict) = self.or {
174-
write!(f, "INSERT {on_conflict} INTO {table_name} ")?;
175-
} else {
176-
write!(
177-
f,
178-
"{start}",
179-
start = if self.replace_into {
180-
"REPLACE"
163+
if !is_multi_table {
164+
let table_name = if let Some(alias) = &self.table_alias {
165+
format!("{0} AS {alias}", self.table)
181166
} else {
182-
"INSERT"
183-
},
184-
)?;
185-
if let Some(priority) = self.priority {
186-
write!(f, " {priority}",)?;
167+
self.table.to_string()
168+
};
169+
write!(f, " {table_name} ")?;
187170
}
188-
189-
write!(
190-
f,
191-
"{ignore}{over}{int}{tbl} {table_name} ",
192-
table_name = table_name,
193-
ignore = if self.ignore { " IGNORE" } else { "" },
194-
over = if self.overwrite { " OVERWRITE" } else { "" },
195-
int = if self.into { " INTO" } else { "" },
196-
tbl = if self.has_table_keyword { " TABLE" } else { "" },
197-
)?;
198171
}
199-
if !self.columns.is_empty() {
172+
173+
if !is_multi_table && !self.columns.is_empty() {
200174
write!(f, "({})", display_comma_separated(&self.columns))?;
201175
SpaceOrNewline.fmt(f)?;
202176
}
203-
if let Some(ref parts) = self.partitioned {
204-
if !parts.is_empty() {
205-
write!(f, "PARTITION ({})", display_comma_separated(parts))?;
206-
SpaceOrNewline.fmt(f)?;
177+
if !is_multi_table {
178+
if let Some(ref parts) = self.partitioned {
179+
if !parts.is_empty() {
180+
write!(f, "PARTITION ({})", display_comma_separated(parts))?;
181+
SpaceOrNewline.fmt(f)?;
182+
}
207183
}
208184
}
209-
if !self.after_columns.is_empty() {
185+
186+
if !is_multi_table && !self.after_columns.is_empty() {
210187
write!(f, "({})", display_comma_separated(&self.after_columns))?;
211188
SpaceOrNewline.fmt(f)?;
212189
}
213190

214-
if let Some(settings) = &self.settings {
215-
write!(f, "SETTINGS {}", display_comma_separated(settings))?;
191+
if !is_multi_table {
192+
if let Some(settings) = &self.settings {
193+
write!(f, "SETTINGS {}", display_comma_separated(settings))?;
194+
SpaceOrNewline.fmt(f)?;
195+
}
196+
}
197+
198+
for into_clause in &self.multi_table_into_clauses {
216199
SpaceOrNewline.fmt(f)?;
200+
write!(f, "{}", into_clause)?;
217201
}
218202

219-
if let Some(source) = &self.source {
220-
source.fmt(f)?;
221-
} else if !self.assignments.is_empty() {
222-
write!(f, "SET")?;
223-
indented_list(f, &self.assignments)?;
224-
} else if let Some(format_clause) = &self.format_clause {
225-
format_clause.fmt(f)?;
226-
} else if self.columns.is_empty() {
227-
write!(f, "DEFAULT VALUES")?;
203+
for when_clause in &self.multi_table_when_clauses {
204+
SpaceOrNewline.fmt(f)?;
205+
write!(f, "{}", when_clause)?;
228206
}
229207

230-
if let Some(insert_alias) = &self.insert_alias {
231-
write!(f, " AS {0}", insert_alias.row_alias)?;
208+
if let Some(else_clauses) = &self.multi_table_else_clause {
209+
SpaceOrNewline.fmt(f)?;
210+
write!(f, "ELSE")?;
211+
for into_clause in else_clauses {
212+
SpaceOrNewline.fmt(f)?;
213+
write!(f, "{}", into_clause)?;
214+
}
215+
}
232216

233-
if let Some(col_aliases) = &insert_alias.col_aliases {
234-
if !col_aliases.is_empty() {
235-
write!(f, " ({})", display_comma_separated(col_aliases))?;
217+
if is_multi_table {
218+
if let Some(source) = &self.source {
219+
SpaceOrNewline.fmt(f)?;
220+
source.fmt(f)?;
221+
}
222+
} else {
223+
if let Some(source) = &self.source {
224+
source.fmt(f)?;
225+
} else if !self.assignments.is_empty() {
226+
write!(f, "SET")?;
227+
indented_list(f, &self.assignments)?;
228+
} else if let Some(format_clause) = &self.format_clause {
229+
format_clause.fmt(f)?;
230+
} else if self.columns.is_empty() {
231+
write!(f, "DEFAULT VALUES")?;
232+
}
233+
}
234+
235+
if !is_multi_table {
236+
if let Some(insert_alias) = &self.insert_alias {
237+
write!(f, " AS {0}", insert_alias.row_alias)?;
238+
239+
if let Some(col_aliases) = &insert_alias.col_aliases {
240+
if !col_aliases.is_empty() {
241+
write!(f, " ({})", display_comma_separated(col_aliases))?;
242+
}
236243
}
237244
}
238245
}
239246

240-
if let Some(on) = &self.on {
241-
write!(f, "{on}")?;
247+
if !is_multi_table {
248+
if let Some(on) = &self.on {
249+
write!(f, "{on}")?;
250+
}
242251
}
243252

244-
if let Some(returning) = &self.returning {
245-
SpaceOrNewline.fmt(f)?;
246-
f.write_str("RETURNING")?;
247-
indented_list(f, returning)?;
253+
if !is_multi_table {
254+
if let Some(returning) = &self.returning {
255+
SpaceOrNewline.fmt(f)?;
256+
f.write_str("RETURNING")?;
257+
indented_list(f, returning)?;
258+
}
248259
}
260+
249261
Ok(())
250262
}
251263
}

src/dialect/snowflake.rs

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,21 +1746,10 @@ fn parse_multi_table_insert_into_clause(
17461746
) -> Result<MultiTableInsertIntoClause, ParserError> {
17471747
let table_name = parser.parse_object_name(false)?;
17481748

1749-
// Parse optional column list
1750-
let columns = if parser.peek_token() == Token::LParen && !parser.peek_keyword(Keyword::VALUES) {
1751-
// Check if this is a column list (not VALUES)
1752-
let peeked = parser.peek_tokens::<2>();
1753-
if peeked[0] == Token::LParen {
1754-
// Could be columns - try to parse
1755-
parser
1756-
.maybe_parse(|p| p.parse_parenthesized_column_list(IsOptional::Optional, false))?
1757-
.unwrap_or_default()
1758-
} else {
1759-
vec![]
1760-
}
1761-
} else {
1762-
vec![]
1763-
};
1749+
// Parse optional column list: ( <column_name> [, ...] )
1750+
let columns = parser
1751+
.maybe_parse(|p| p.parse_parenthesized_column_list(IsOptional::Mandatory, false))?
1752+
.unwrap_or_default();
17641753

17651754
// Parse optional VALUES clause
17661755
let values = if parser.parse_keyword(Keyword::VALUES) {

0 commit comments

Comments
 (0)