@@ -35,7 +35,7 @@ pub struct SnowflakeDialect;
35
35
impl Dialect for SnowflakeDialect {
36
36
// see https://docs.snowflake.com/en/sql-reference/identifiers-syntax.html
37
37
fn is_identifier_start ( & self , ch : char ) -> bool {
38
- ch. is_ascii_lowercase ( ) || ch. is_ascii_uppercase ( ) || ch == '_' || ch == '@' || ch == '%'
38
+ ch. is_ascii_lowercase ( ) || ch. is_ascii_uppercase ( ) || ch == '_'
39
39
}
40
40
41
41
fn is_identifier_part ( & self , ch : char ) -> bool {
@@ -44,8 +44,6 @@ impl Dialect for SnowflakeDialect {
44
44
|| ch. is_ascii_digit ( )
45
45
|| ch == '$'
46
46
|| ch == '_'
47
- || ch == '/'
48
- || ch == '~'
49
47
}
50
48
51
49
fn supports_within_after_array_aggregation ( & self ) -> bool {
@@ -148,8 +146,48 @@ pub fn parse_create_stage(
148
146
} )
149
147
}
150
148
149
+ pub fn parse_stage_name_identifier ( parser : & mut Parser ) -> Result < Ident , ParserError > {
150
+ let mut ident = String :: new ( ) ;
151
+ while let Some ( next_token) = parser. next_token_no_skip ( ) {
152
+ match & next_token. token {
153
+ Token :: Whitespace ( _) => break ,
154
+ Token :: Period => {
155
+ parser. prev_token ( ) ;
156
+ break ;
157
+ }
158
+ Token :: AtSign => ident. push ( '@' ) ,
159
+ Token :: Tilde => ident. push ( '~' ) ,
160
+ Token :: Mod => ident. push ( '%' ) ,
161
+ Token :: Div => ident. push ( '/' ) ,
162
+ Token :: Word ( w) => ident. push_str ( & w. value ) ,
163
+ _ => return parser. expected ( "stage name identifier" , parser. peek_token ( ) ) ,
164
+ }
165
+ }
166
+ Ok ( Ident :: new ( ident) )
167
+ }
168
+
169
+ pub fn parse_snowflake_stage_name ( parser : & mut Parser ) -> Result < ObjectName , ParserError > {
170
+ match parser. next_token ( ) . token {
171
+ Token :: AtSign => {
172
+ parser. prev_token ( ) ;
173
+ let mut idents = vec ! [ ] ;
174
+ loop {
175
+ idents. push ( parse_stage_name_identifier ( parser) ?) ;
176
+ if !parser. consume_token ( & Token :: Period ) {
177
+ break ;
178
+ }
179
+ }
180
+ Ok ( ObjectName ( idents) )
181
+ }
182
+ _ => {
183
+ parser. prev_token ( ) ;
184
+ Ok ( parser. parse_object_name ( ) ?)
185
+ }
186
+ }
187
+ }
188
+
151
189
pub fn parse_copy_into ( parser : & mut Parser ) -> Result < Statement , ParserError > {
152
- let into: ObjectName = parser . parse_object_name ( ) ?;
190
+ let into: ObjectName = parse_snowflake_stage_name ( parser ) ?;
153
191
let mut files: Vec < String > = vec ! [ ] ;
154
192
let mut from_transformations: Option < Vec < StageLoadSelectItem > > = None ;
155
193
let from_stage_alias;
@@ -165,7 +203,7 @@ pub fn parse_copy_into(parser: &mut Parser) -> Result<Statement, ParserError> {
165
203
from_transformations = parse_select_items_for_data_load ( parser) ?;
166
204
167
205
parser. expect_keyword ( Keyword :: FROM ) ?;
168
- from_stage = parser . parse_object_name ( ) ?;
206
+ from_stage = parse_snowflake_stage_name ( parser ) ?;
169
207
stage_params = parse_stage_params ( parser) ?;
170
208
171
209
// as
0 commit comments