Skip to content

Commit 614ea06

Browse files
authored
Snowflake: Support SAMPLE clause on subqueries (#2164)
1 parent e7a3019 commit 614ea06

File tree

5 files changed

+37
-1
lines changed

5 files changed

+37
-1
lines changed

src/ast/query.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,8 @@ pub enum TableFactor {
13251325
subquery: Box<Query>,
13261326
/// Optional alias for the derived table.
13271327
alias: Option<TableAlias>,
1328+
/// Optional table sample modifier
1329+
sample: Option<TableSampleKind>,
13281330
},
13291331
/// `TABLE(<expr>)[ AS <alias> ]`
13301332
TableFunction {
@@ -2071,6 +2073,7 @@ impl fmt::Display for TableFactor {
20712073
lateral,
20722074
subquery,
20732075
alias,
2076+
sample,
20742077
} => {
20752078
if *lateral {
20762079
write!(f, "LATERAL ")?;
@@ -2083,6 +2086,9 @@ impl fmt::Display for TableFactor {
20832086
if let Some(alias) = alias {
20842087
write!(f, " {alias}")?;
20852088
}
2089+
if let Some(TableSampleKind::AfterTableAlias(sample)) = sample {
2090+
write!(f, " {sample}")?;
2091+
}
20862092
Ok(())
20872093
}
20882094
TableFactor::Function {

src/ast/spans.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1915,6 +1915,7 @@ impl Spanned for TableFactor {
19151915
lateral: _,
19161916
subquery,
19171917
alias,
1918+
sample: _,
19181919
} => subquery
19191920
.span()
19201921
.union_opt(&alias.as_ref().map(|alias| alias.span())),

src/parser/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15073,6 +15073,7 @@ impl<'a> Parser<'a> {
1507315073
pipe_operators: vec![],
1507415074
}),
1507515075
alias,
15076+
sample: None,
1507615077
})
1507715078
} else if dialect_of!(self is BigQueryDialect | PostgreSqlDialect | GenericDialect)
1507815079
&& self.parse_keyword(Keyword::UNNEST)
@@ -15880,13 +15881,20 @@ impl<'a> Parser<'a> {
1588015881
let subquery = self.parse_query()?;
1588115882
self.expect_token(&Token::RParen)?;
1588215883
let alias = self.maybe_parse_table_alias()?;
15884+
15885+
// Parse optional SAMPLE clause after alias
15886+
let sample = self
15887+
.maybe_parse_table_sample()?
15888+
.map(TableSampleKind::AfterTableAlias);
15889+
1588315890
Ok(TableFactor::Derived {
1588415891
lateral: match lateral {
1588515892
Lateral => true,
1588615893
NotLateral => false,
1588715894
},
1588815895
subquery,
1588915896
alias,
15897+
sample,
1589015898
})
1589115899
}
1589215900

tests/sqlparser_common.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,8 @@ fn parse_update_set_from() {
512512
format_clause: None,
513513
pipe_operators: vec![],
514514
}),
515-
alias: table_alias(true, "t2")
515+
alias: table_alias(true, "t2"),
516+
sample: None,
516517
},
517518
joins: vec![]
518519
}])),
@@ -7863,6 +7864,7 @@ fn parse_derived_tables() {
78637864
lateral: false,
78647865
subquery: Box::new(verified_query("(SELECT 1) UNION (SELECT 2)")),
78657866
alias: table_alias(true, "t1"),
7867+
sample: None,
78667868
},
78677869
joins: vec![Join {
78687870
relation: table_from_name(ObjectName::from(vec!["t2".into()])),
@@ -8871,6 +8873,7 @@ fn lateral_derived() {
88718873
lateral,
88728874
ref subquery,
88738875
alias: Some(ref alias),
8876+
sample: _,
88748877
} = join.relation
88758878
{
88768879
assert_eq!(lateral_in, lateral);
@@ -9950,6 +9953,7 @@ fn parse_merge() {
99509953
pipe_operators: vec![],
99519954
}),
99529955
alias: table_alias(true, "stg"),
9956+
sample: None,
99539957
}
99549958
);
99559959
assert_eq!(source, source_no_into);

tests/sqlparser_snowflake.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3406,6 +3406,23 @@ fn test_table_sample() {
34063406
snowflake_and_generic().verified_stmt("SELECT id FROM mytable TABLESAMPLE (10) SEED (1)");
34073407
}
34083408

3409+
#[test]
3410+
fn test_subquery_sample() {
3411+
// Test SAMPLE clause on subqueries (derived tables)
3412+
snowflake_and_generic().verified_stmt("SELECT * FROM (SELECT * FROM mytable) SAMPLE (10)");
3413+
snowflake_and_generic()
3414+
.verified_stmt("SELECT * FROM (SELECT * FROM mytable) SAMPLE (10000 ROWS)");
3415+
snowflake_and_generic()
3416+
.verified_stmt("SELECT * FROM (SELECT * FROM mytable) AS t SAMPLE (50 PERCENT)");
3417+
// Nested subquery with SAMPLE
3418+
snowflake_and_generic().verified_stmt(
3419+
"SELECT * FROM (SELECT * FROM (SELECT report_from FROM mytable) SAMPLE (10000 ROWS)) AS anon_1",
3420+
);
3421+
// SAMPLE with SEED on subquery
3422+
snowflake_and_generic()
3423+
.verified_stmt("SELECT * FROM (SELECT * FROM mytable) SAMPLE (10) SEED (42)");
3424+
}
3425+
34093426
#[test]
34103427
fn parse_ls_and_rm() {
34113428
snowflake().one_statement_parses_to("LS @~", "LIST @~");

0 commit comments

Comments
 (0)