@@ -17,14 +17,12 @@ use alloc::{boxed::Box, format, string::ToString, vec, vec::Vec};
1717
1818use crate :: {
1919 ast:: {
20- Ident , Merge , MergeAction , MergeClause , MergeClauseKind , MergeInsertExpr , MergeInsertKind ,
21- MergeUpdateExpr , ObjectName , ObjectNamePart , OutputClause , SetExpr , Spanned , Statement ,
22- TableFactor ,
20+ Merge , MergeAction , MergeClause , MergeClauseKind , MergeInsertExpr , MergeInsertKind , MergeUpdateExpr , ObjectName , ObjectNamePart , OutputClause , SetExpr , Statement
2321 } ,
2422 dialect:: { BigQueryDialect , GenericDialect , MySqlDialect } ,
2523 keywords:: Keyword ,
2624 parser:: IsOptional ,
27- tokenizer:: { Location , TokenWithSpan } ,
25+ tokenizer:: TokenWithSpan ,
2826} ;
2927
3028use super :: { Parser , ParserError } ;
@@ -49,7 +47,7 @@ impl Parser<'_> {
4947 let source = self . parse_table_factor ( ) ?;
5048 self . expect_keyword_is ( Keyword :: ON ) ?;
5149 let on = self . parse_expr ( ) ?;
52- let clauses = self . parse_merge_clauses ( & table ) ?;
50+ let clauses = self . parse_merge_clauses ( ) ?;
5351 let output = match self . parse_one_of_keywords ( & [ Keyword :: OUTPUT , Keyword :: RETURNING ] ) {
5452 Some ( keyword) => Some ( self . parse_output ( keyword, self . get_current_token ( ) . clone ( ) ) ?) ,
5553 None => None ,
@@ -66,10 +64,7 @@ impl Parser<'_> {
6664 } ) )
6765 }
6866
69- fn parse_merge_clauses (
70- & mut self ,
71- target_table : & TableFactor ,
72- ) -> Result < Vec < MergeClause > , ParserError > {
67+ fn parse_merge_clauses ( & mut self ) -> Result < Vec < MergeClause > , ParserError > {
7368 let mut clauses = vec ! [ ] ;
7469 loop {
7570 if !( self . parse_keyword ( Keyword :: WHEN ) ) {
@@ -172,11 +167,7 @@ impl Parser<'_> {
172167 let insert_token = self . get_current_token ( ) . clone ( ) ;
173168 let is_mysql = dialect_of ! ( self is MySqlDialect ) ;
174169
175- let columns = self . parse_merge_clause_insert_columns (
176- target_table,
177- & clause_kind,
178- is_mysql,
179- ) ?;
170+ let columns = self . parse_merge_clause_insert_columns ( is_mysql) ?;
180171 let ( kind, kind_token) = if dialect_of ! ( self is BigQueryDialect | GenericDialect )
181172 && self . parse_keyword ( Keyword :: ROW )
182173 {
@@ -220,67 +211,27 @@ impl Parser<'_> {
220211 Ok ( clauses)
221212 }
222213
223- fn parse_merge_clause_insert_columns (
224- & mut self ,
225- target_table : & TableFactor ,
226- clause_kind : & MergeClauseKind ,
227- allow_empty : bool ,
228- ) -> Result < Vec < Ident > , ParserError > {
214+ fn parse_merge_clause_insert_columns ( & mut self , allow_empty : bool ) -> Result < Vec < ObjectName > , ParserError > {
229215 if self . dialect . supports_merge_insert_qualified_columns ( ) {
230- let cols =
231- self . parse_parenthesized_qualified_column_list ( IsOptional :: Optional , allow_empty) ?;
232- if let TableFactor :: Table { name, alias, .. } = target_table {
233- if let Some ( alias) = alias {
234- if alias. columns . is_empty ( ) {
235- // ~ only the alias is supported at this point
236- match unqualify_columns ( cols, None , Some ( & alias. name ) ) {
237- Ok ( column) => Ok ( column) ,
238- Err ( ( err, loc) ) => parser_err ! (
239- format_args!( "Invalid column for INSERT in a {clause_kind} merge clause: {err}" ) ,
240- loc
241- ) ,
242- }
243- } else {
244- parser_err ! (
245- format_args!( "Invalid target ALIAS for INSERT in a {clause_kind} merge clause; must be an identifier" ) ,
246- alias. name. span. start
247- )
248- }
249- } else {
250- // ~ allow the full qualifier, but also just the table name
251- if name. 0 . len ( ) == 1 {
252- match unqualify_columns ( cols, Some ( name) , None ) {
253- Ok ( column) => Ok ( column) ,
254- Err ( ( err, loc) ) => parser_err ! (
255- format_args!( "Invalid column for INSERT in a {clause_kind} merge clause: {err}" ) ,
256- loc)
257- }
258- } else if let Some ( unqualified_name) =
259- name. 0 . last ( ) . and_then ( ObjectNamePart :: as_ident)
260- {
261- match unqualify_columns ( cols, Some ( name) , Some ( unqualified_name) ) {
262- Ok ( column) => Ok ( column) ,
263- Err ( ( err, loc) ) => parser_err ! (
264- format_args!( "Invalid column for INSERT in a {clause_kind} merge clause: {err}" ) ,
265- loc)
266- }
267- } else {
268- parser_err ! (
269- format_args!( "Invalid target table NAME for INSERT in a {clause_kind} merge clause; must be an identifier" ) ,
270- name. span( ) . start
271- )
272- }
273- }
274- } else {
275- parser_err ! (
276- format_args!( "Invalid target for INSERT in a {clause_kind} merge clause; must be a TABLE identifier" ) ,
277- target_table. span( ) . start)
278- }
216+ self . parse_parenthesized_qualified_column_list ( IsOptional :: Optional , allow_empty)
279217 } else {
280- self . parse_parenthesized_column_list ( IsOptional :: Optional , allow_empty)
218+ self . parse_parenthesized_column_list_as_object_names ( IsOptional :: Optional , allow_empty)
281219 }
282220 }
283221
222+ /// Just like [Parser::parse_parenthesized_column_list] parses a
223+ /// parenthesized list of (simple) column names but returns them as object
224+ /// names.
225+ fn parse_parenthesized_column_list_as_object_names (
226+ & mut self ,
227+ optional : IsOptional ,
228+ allow_empty : bool ,
229+ ) -> Result < Vec < ObjectName > , ParserError > {
230+ self . parse_parenthesized_column_list_inner ( optional, allow_empty, |p| {
231+ p. parse_identifier ( ) . map ( |ident| ObjectName ( vec ! [ ObjectNamePart :: Identifier ( ident) ] ) )
232+ } )
233+ }
234+
284235 fn parse_output (
285236 & mut self ,
286237 start_keyword : Keyword ,
@@ -308,96 +259,3 @@ impl Parser<'_> {
308259 } )
309260 }
310261}
311-
312- /// Helper to unqualify a list of columns with either a qualified prefix
313- /// (`allowed_qualifier_1`) or a qualifier identifier (`allowed_qualifier_2`.)
314- ///
315- /// Oracle allows `INSERT ([qualifier.]column_name, ...)` in MERGE statements
316- /// with `qualifier` referring to the alias of the target table (if one is
317- /// present) or, if no alias is present, to the target table name itself -
318- /// either qualified or unqualified.
319- fn unqualify_columns (
320- columns : Vec < ObjectName > ,
321- allowed_qualifier_1 : Option < & ObjectName > ,
322- allowed_qualifier_2 : Option < & Ident > ,
323- ) -> Result < Vec < Ident > , ( & ' static str , Location ) > {
324- // ~ helper to turn a column name (part) into a plain `ident`
325- // possibly bailing with error
326- fn to_ident ( name : ObjectNamePart ) -> Result < Ident , ( & ' static str , Location ) > {
327- match name {
328- ObjectNamePart :: Identifier ( ident) => Ok ( ident) ,
329- ObjectNamePart :: Function ( _) => Err ( ( "not an identifier" , name. span ( ) . start ) ) ,
330- }
331- }
332-
333- // ~ helper to return the last part of `name` if it is
334- // preceded by `prefix`
335- fn unqualify_column (
336- mut name : ObjectName ,
337- prefix : & ObjectName ,
338- ) -> Result < ObjectNamePart , ObjectName > {
339- let mut name_iter = name. 0 . iter ( ) ;
340- let mut prefix_iter = prefix. 0 . iter ( ) ;
341- loop {
342- match ( name_iter. next ( ) , prefix_iter. next ( ) ) {
343- ( Some ( _) , None ) => {
344- if name_iter. next ( ) . is_none ( ) {
345- return Ok ( name. 0 . pop ( ) . expect ( "missing name part" ) ) ;
346- } else {
347- return Err ( name) ;
348- }
349- }
350- ( Some ( c) , Some ( q) ) if c == q => {
351- // ~ continue matching next part
352- }
353- _ => {
354- return Err ( name) ;
355- }
356- }
357- }
358- }
359-
360- let mut unqualified = Vec :: < Ident > :: with_capacity ( columns. len ( ) ) ;
361- for mut name in columns {
362- if name. 0 . is_empty ( ) {
363- return Err ( ( "empty column name" , name. span ( ) . start ) ) ;
364- }
365-
366- if name. 0 . len ( ) == 1 {
367- unqualified. push ( to_ident ( name. 0 . pop ( ) . expect ( "missing name part" ) ) ?) ;
368- continue ;
369- }
370-
371- // ~ try matching by the primary prefix
372- if let Some ( allowed_qualifier) = allowed_qualifier_1 {
373- match unqualify_column ( name, allowed_qualifier) {
374- Ok ( ident) => {
375- unqualified. push ( to_ident ( ident) ?) ;
376- continue ;
377- }
378- Err ( n) => {
379- // ~ continue trying with the alternate prefix below
380- name = n;
381- }
382- }
383- }
384-
385- // ~ try matching by the alternate prefix
386- if let Some ( allowed_qualifier) = allowed_qualifier_2 {
387- if name. 0 . len ( ) == 2
388- && name
389- . 0
390- . first ( )
391- . and_then ( ObjectNamePart :: as_ident)
392- . map ( |i| i == allowed_qualifier)
393- . unwrap_or ( false )
394- {
395- unqualified. push ( to_ident ( name. 0 . pop ( ) . expect ( "missing name part" ) ) ?) ;
396- continue ;
397- }
398- }
399-
400- return Err ( ( "not matching target table" , name. span ( ) . start ) ) ;
401- }
402- Ok ( unqualified)
403- }
0 commit comments