@@ -20,7 +20,7 @@ use crate::alloc::string::ToString;
2020use crate :: ast:: helpers:: key_value_options:: { KeyValueOption , KeyValueOptionType , KeyValueOptions } ;
2121use crate :: ast:: helpers:: stmt_create_table:: CreateTableBuilder ;
2222use crate :: ast:: helpers:: stmt_data_loading:: {
23- FileStagingCommand , StageLoadSelectItem , StageParamsObject ,
23+ FileStagingCommand , StageLoadSelectItem , StageLoadSelectItemKind , StageParamsObject ,
2424} ;
2525use crate :: ast:: {
2626 ColumnOption , ColumnPolicy , ColumnPolicyProperty , CopyIntoSnowflakeKind , Ident ,
@@ -30,7 +30,7 @@ use crate::ast::{
3030} ;
3131use crate :: dialect:: { Dialect , Precedence } ;
3232use crate :: keywords:: Keyword ;
33- use crate :: parser:: { Parser , ParserError } ;
33+ use crate :: parser:: { IsOptional , Parser , ParserError } ;
3434use crate :: tokenizer:: { Token , Word } ;
3535#[ cfg( not( feature = "std" ) ) ]
3636use alloc:: boxed:: Box ;
@@ -722,7 +722,7 @@ pub fn parse_copy_into(parser: &mut Parser) -> Result<Statement, ParserError> {
722722 } ;
723723
724724 let mut files: Vec < String > = vec ! [ ] ;
725- let mut from_transformations: Option < Vec < StageLoadSelectItem > > = None ;
725+ let mut from_transformations: Option < Vec < StageLoadSelectItemKind > > = None ;
726726 let mut from_stage_alias = None ;
727727 let mut from_stage = None ;
728728 let mut stage_params = StageParamsObject {
@@ -744,6 +744,11 @@ pub fn parse_copy_into(parser: &mut Parser) -> Result<Statement, ParserError> {
744744 stage_params = parse_stage_params ( parser) ?;
745745 }
746746
747+ let into_columns = match & parser. peek_token ( ) . token {
748+ Token :: LParen => Some ( parser. parse_parenthesized_column_list ( IsOptional :: Optional , true ) ?) ,
749+ _ => None ,
750+ } ;
751+
747752 parser. expect_keyword_is ( Keyword :: FROM ) ?;
748753 match parser. next_token ( ) . token {
749754 Token :: LParen if kind == CopyIntoSnowflakeKind :: Table => {
@@ -755,15 +760,10 @@ pub fn parse_copy_into(parser: &mut Parser) -> Result<Statement, ParserError> {
755760 from_stage = Some ( parse_snowflake_stage_name ( parser) ?) ;
756761 stage_params = parse_stage_params ( parser) ?;
757762
758- // as
759- from_stage_alias = if parser. parse_keyword ( Keyword :: AS ) {
760- Some ( match parser. next_token ( ) . token {
761- Token :: Word ( w) => Ok ( Ident :: new ( w. value ) ) ,
762- _ => parser. expected ( "stage alias" , parser. peek_token ( ) ) ,
763- } ?)
764- } else {
765- None
766- } ;
763+ // Parse an optional alias
764+ from_stage_alias = parser
765+ . maybe_parse_table_alias ( ) ?
766+ . map ( |table_alias| table_alias. name ) ;
767767 parser. expect_token ( & Token :: RParen ) ?;
768768 }
769769 Token :: LParen if kind == CopyIntoSnowflakeKind :: Location => {
@@ -846,6 +846,7 @@ pub fn parse_copy_into(parser: &mut Parser) -> Result<Statement, ParserError> {
846846 Ok ( Statement :: CopyIntoSnowflake {
847847 kind,
848848 into,
849+ into_columns,
849850 from_obj : from_stage,
850851 from_obj_alias : from_stage_alias,
851852 stage_params,
@@ -866,86 +867,97 @@ pub fn parse_copy_into(parser: &mut Parser) -> Result<Statement, ParserError> {
866867
867868fn parse_select_items_for_data_load (
868869 parser : & mut Parser ,
869- ) -> Result < Option < Vec < StageLoadSelectItem > > , ParserError > {
870- // [<alias>.]$<file_col_num>[.<element>] [ , [<alias>.]$<file_col_num>[.<element>] ... ]
871- let mut select_items: Vec < StageLoadSelectItem > = vec ! [ ] ;
870+ ) -> Result < Option < Vec < StageLoadSelectItemKind > > , ParserError > {
871+ let mut select_items: Vec < StageLoadSelectItemKind > = vec ! [ ] ;
872872 loop {
873- let mut alias: Option < Ident > = None ;
874- let mut file_col_num: i32 = 0 ;
875- let mut element: Option < Ident > = None ;
876- let mut item_as: Option < Ident > = None ;
873+ match parser. maybe_parse ( parse_select_item_for_data_load) ? {
874+ // [<alias>.]$<file_col_num>[.<element>] [ , [<alias>.]$<file_col_num>[.<element>] ... ]
875+ Some ( item) => select_items. push ( StageLoadSelectItemKind :: StageLoadSelectItem ( item) ) ,
876+ // Fallback, try to parse a standard SQL select item
877+ None => select_items. push ( StageLoadSelectItemKind :: SelectItem (
878+ parser. parse_select_item ( ) ?,
879+ ) ) ,
880+ }
881+ match parser. next_token ( ) . token {
882+ Token :: Comma => {
883+ // continue
884+ }
885+ _ => {
886+ parser. prev_token ( ) ; // need to move back
887+ break ;
888+ }
889+ }
890+ }
891+ Ok ( Some ( select_items) )
892+ }
877893
878- let next_token = parser. next_token ( ) ;
879- match next_token. token {
894+ fn parse_select_item_for_data_load (
895+ parser : & mut Parser ,
896+ ) -> Result < StageLoadSelectItem , ParserError > {
897+ let mut alias: Option < Ident > = None ;
898+ let mut file_col_num: i32 = 0 ;
899+ let mut element: Option < Ident > = None ;
900+ let mut item_as: Option < Ident > = None ;
901+
902+ let next_token = parser. next_token ( ) ;
903+ match next_token. token {
904+ Token :: Placeholder ( w) => {
905+ file_col_num = w. to_string ( ) . split_off ( 1 ) . parse :: < i32 > ( ) . map_err ( |e| {
906+ ParserError :: ParserError ( format ! ( "Could not parse '{w}' as i32: {e}" ) )
907+ } ) ?;
908+ Ok ( ( ) )
909+ }
910+ Token :: Word ( w) => {
911+ alias = Some ( Ident :: new ( w. value ) ) ;
912+ Ok ( ( ) )
913+ }
914+ _ => parser. expected ( "alias or file_col_num" , next_token) ,
915+ } ?;
916+
917+ if alias. is_some ( ) {
918+ parser. expect_token ( & Token :: Period ) ?;
919+ // now we get col_num token
920+ let col_num_token = parser. next_token ( ) ;
921+ match col_num_token. token {
880922 Token :: Placeholder ( w) => {
881923 file_col_num = w. to_string ( ) . split_off ( 1 ) . parse :: < i32 > ( ) . map_err ( |e| {
882924 ParserError :: ParserError ( format ! ( "Could not parse '{w}' as i32: {e}" ) )
883925 } ) ?;
884926 Ok ( ( ) )
885927 }
886- Token :: Word ( w) => {
887- alias = Some ( Ident :: new ( w. value ) ) ;
888- Ok ( ( ) )
889- }
890- _ => parser. expected ( "alias or file_col_num" , next_token) ,
928+ _ => parser. expected ( "file_col_num" , col_num_token) ,
891929 } ?;
930+ }
892931
893- if alias. is_some ( ) {
894- parser. expect_token ( & Token :: Period ) ?;
895- // now we get col_num token
896- let col_num_token = parser. next_token ( ) ;
897- match col_num_token. token {
898- Token :: Placeholder ( w) => {
899- file_col_num = w. to_string ( ) . split_off ( 1 ) . parse :: < i32 > ( ) . map_err ( |e| {
900- ParserError :: ParserError ( format ! ( "Could not parse '{w}' as i32: {e}" ) )
901- } ) ?;
902- Ok ( ( ) )
903- }
904- _ => parser. expected ( "file_col_num" , col_num_token) ,
905- } ?;
906- }
907-
908- // try extracting optional element
909- match parser. next_token ( ) . token {
910- Token :: Colon => {
911- // parse element
912- element = Some ( Ident :: new ( match parser. next_token ( ) . token {
913- Token :: Word ( w) => Ok ( w. value ) ,
914- _ => parser. expected ( "file_col_num" , parser. peek_token ( ) ) ,
915- } ?) ) ;
916- }
917- _ => {
918- // element not present move back
919- parser. prev_token ( ) ;
920- }
932+ // try extracting optional element
933+ match parser. next_token ( ) . token {
934+ Token :: Colon => {
935+ // parse element
936+ element = Some ( Ident :: new ( match parser. next_token ( ) . token {
937+ Token :: Word ( w) => Ok ( w. value ) ,
938+ _ => parser. expected ( "file_col_num" , parser. peek_token ( ) ) ,
939+ } ?) ) ;
921940 }
922-
923- // as
924- if parser. parse_keyword ( Keyword :: AS ) {
925- item_as = Some ( match parser. next_token ( ) . token {
926- Token :: Word ( w) => Ok ( Ident :: new ( w. value ) ) ,
927- _ => parser. expected ( "column item alias" , parser. peek_token ( ) ) ,
928- } ?) ;
941+ _ => {
942+ // element not present move back
943+ parser. prev_token ( ) ;
929944 }
945+ }
930946
931- select_items. push ( StageLoadSelectItem {
932- alias,
933- file_col_num,
934- element,
935- item_as,
936- } ) ;
937-
938- match parser. next_token ( ) . token {
939- Token :: Comma => {
940- // continue
941- }
942- _ => {
943- parser. prev_token ( ) ; // need to move back
944- break ;
945- }
946- }
947+ // as
948+ if parser. parse_keyword ( Keyword :: AS ) {
949+ item_as = Some ( match parser. next_token ( ) . token {
950+ Token :: Word ( w) => Ok ( Ident :: new ( w. value ) ) ,
951+ _ => parser. expected ( "column item alias" , parser. peek_token ( ) ) ,
952+ } ?) ;
947953 }
948- Ok ( Some ( select_items) )
954+
955+ Ok ( StageLoadSelectItem {
956+ alias,
957+ file_col_num,
958+ element,
959+ item_as,
960+ } )
949961}
950962
951963fn parse_stage_params ( parser : & mut Parser ) -> Result < StageParamsObject , ParserError > {
0 commit comments