@@ -23,8 +23,8 @@ use crate::ast::helpers::stmt_data_loading::{
23
23
FileStagingCommand , StageLoadSelectItem , StageLoadSelectItemKind , StageParamsObject ,
24
24
} ;
25
25
use crate :: ast:: {
26
- ColumnOption , ColumnPolicy , ColumnPolicyProperty , CopyIntoSnowflakeKind , Ident ,
27
- IdentityParameters , IdentityProperty , IdentityPropertyFormatKind , IdentityPropertyKind ,
26
+ ColumnOption , ColumnPolicy , ColumnPolicyProperty , CopyIntoSnowflakeKind , DollarQuotedString ,
27
+ Ident , IdentityParameters , IdentityProperty , IdentityPropertyFormatKind , IdentityPropertyKind ,
28
28
IdentityPropertyOrder , ObjectName , ObjectNamePart , RowAccessPolicy , ShowObjects , SqlOption ,
29
29
Statement , TagsColumnOption , WrappedCollection ,
30
30
} ;
@@ -307,22 +307,22 @@ impl Dialect for SnowflakeDialect {
307
307
// they are not followed by other tokens that may change their meaning
308
308
// e.g. `SELECT * EXCEPT (col1) FROM tbl`
309
309
Keyword :: EXCEPT
310
- // e.g. `SELECT 1 LIMIT 5`
311
- | Keyword :: LIMIT
312
- // e.g. `SELECT 1 OFFSET 5 ROWS`
313
- | Keyword :: OFFSET
314
310
// e.g. `INSERT INTO t SELECT 1 RETURNING *`
315
311
| Keyword :: RETURNING if !matches ! ( parser. peek_token_ref( ) . token, Token :: Comma | Token :: EOF ) =>
316
312
{
317
313
false
318
314
}
319
315
316
+ // e.g. `SELECT 1 LIMIT 5` - not an alias
317
+ // e.g. `SELECT 1 OFFSET 5 ROWS` - not an alias
318
+ Keyword :: LIMIT | Keyword :: OFFSET if peek_for_limit_options ( parser) => false ,
319
+
320
320
// `FETCH` can be considered an alias as long as it's not followed by `FIRST`` or `NEXT`
321
321
// which would give it a different meanings, for example:
322
322
// `SELECT 1 FETCH FIRST 10 ROWS` - not an alias
323
323
// `SELECT 1 FETCH 10` - not an alias
324
324
Keyword :: FETCH if parser. peek_one_of_keywords ( & [ Keyword :: FIRST , Keyword :: NEXT ] ) . is_some ( )
325
- || matches ! ( parser. peek_token ( ) . token , Token :: Number ( _ , _ ) ) =>
325
+ || peek_for_limit_options ( parser) =>
326
326
{
327
327
false
328
328
}
@@ -358,7 +358,6 @@ impl Dialect for SnowflakeDialect {
358
358
| Keyword :: UNPIVOT
359
359
| Keyword :: EXCEPT
360
360
| Keyword :: MATCH_RECOGNIZE
361
- | Keyword :: OFFSET
362
361
if !matches ! ( parser. peek_token_ref( ) . token, Token :: SemiColon | Token :: EOF ) =>
363
362
{
364
363
false
@@ -367,14 +366,7 @@ impl Dialect for SnowflakeDialect {
367
366
// `LIMIT` can be considered an alias as long as it's not followed by a value. For example:
368
367
// `SELECT * FROM tbl LIMIT WHERE 1=1` - alias
369
368
// `SELECT * FROM tbl LIMIT 3` - not an alias
370
- Keyword :: LIMIT
371
- if matches ! (
372
- parser. peek_token( ) . token,
373
- Token :: Number ( _, _) | Token :: Placeholder ( _)
374
- ) =>
375
- {
376
- false
377
- }
369
+ Keyword :: LIMIT | Keyword :: OFFSET if peek_for_limit_options ( parser) => false ,
378
370
379
371
// `FETCH` can be considered an alias as long as it's not followed by `FIRST`` or `NEXT`
380
372
// which would give it a different meanings, for example:
@@ -384,10 +376,7 @@ impl Dialect for SnowflakeDialect {
384
376
if parser
385
377
. peek_one_of_keywords ( & [ Keyword :: FIRST , Keyword :: NEXT ] )
386
378
. is_some ( )
387
- || matches ! (
388
- parser. peek_token( ) . token,
389
- Token :: Number ( _, _) | Token :: Placeholder ( _)
390
- ) =>
379
+ || peek_for_limit_options ( parser) =>
391
380
{
392
381
false
393
382
}
@@ -487,6 +476,18 @@ impl Dialect for SnowflakeDialect {
487
476
}
488
477
}
489
478
479
+ // Peeks ahead to identify tokens that are expected after
480
+ // a LIMIT/FETCH keyword.
481
+ fn peek_for_limit_options ( parser : & Parser ) -> bool {
482
+ match & parser. peek_token_ref ( ) . token {
483
+ Token :: Number ( _, _) | Token :: Placeholder ( _) => true ,
484
+ Token :: SingleQuotedString ( val) if val. is_empty ( ) => true ,
485
+ Token :: DollarQuotedString ( DollarQuotedString { value, .. } ) if value. is_empty ( ) => true ,
486
+ Token :: Word ( w) if w. keyword == Keyword :: NULL => true ,
487
+ _ => false ,
488
+ }
489
+ }
490
+
490
491
fn parse_file_staging_command ( kw : Keyword , parser : & mut Parser ) -> Result < Statement , ParserError > {
491
492
let stage = parse_snowflake_stage_name ( parser) ?;
492
493
let pattern = if parser. parse_keyword ( Keyword :: PATTERN ) {
0 commit comments