This is an automated email from the ASF dual-hosted git repository.
github-bot pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git
The following commit(s) were added to refs/heads/main by this push:
new 614ea06e Snowflake: Support SAMPLE clause on subqueries (#2164)
614ea06e is described below
commit 614ea06e31b415e012ac59afd8c90a723d8868b5
Author: finchxxia <[email protected]>
AuthorDate: Sat Jan 24 03:25:58 2026 +0800
Snowflake: Support SAMPLE clause on subqueries (#2164)
---
src/ast/query.rs | 6 ++++++
src/ast/spans.rs | 1 +
src/parser/mod.rs | 8 ++++++++
tests/sqlparser_common.rs | 6 +++++-
tests/sqlparser_snowflake.rs | 17 +++++++++++++++++
5 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/src/ast/query.rs b/src/ast/query.rs
index a1fc33b6..7ea4de19 100644
--- a/src/ast/query.rs
+++ b/src/ast/query.rs
@@ -1325,6 +1325,8 @@ pub enum TableFactor {
subquery: Box<Query>,
/// Optional alias for the derived table.
alias: Option<TableAlias>,
+ /// Optional table sample modifier
+ sample: Option<TableSampleKind>,
},
/// `TABLE(<expr>)[ AS <alias> ]`
TableFunction {
@@ -2071,6 +2073,7 @@ impl fmt::Display for TableFactor {
lateral,
subquery,
alias,
+ sample,
} => {
if *lateral {
write!(f, "LATERAL ")?;
@@ -2083,6 +2086,9 @@ impl fmt::Display for TableFactor {
if let Some(alias) = alias {
write!(f, " {alias}")?;
}
+ if let Some(TableSampleKind::AfterTableAlias(sample)) = sample
{
+ write!(f, " {sample}")?;
+ }
Ok(())
}
TableFactor::Function {
diff --git a/src/ast/spans.rs b/src/ast/spans.rs
index 1c5cc473..58d70a87 100644
--- a/src/ast/spans.rs
+++ b/src/ast/spans.rs
@@ -1915,6 +1915,7 @@ impl Spanned for TableFactor {
lateral: _,
subquery,
alias,
+ sample: _,
} => subquery
.span()
.union_opt(&alias.as_ref().map(|alias| alias.span())),
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index 586c2f6b..6fb06c64 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -15073,6 +15073,7 @@ impl<'a> Parser<'a> {
pipe_operators: vec![],
}),
alias,
+ sample: None,
})
} else if dialect_of!(self is BigQueryDialect | PostgreSqlDialect |
GenericDialect)
&& self.parse_keyword(Keyword::UNNEST)
@@ -15880,6 +15881,12 @@ impl<'a> Parser<'a> {
let subquery = self.parse_query()?;
self.expect_token(&Token::RParen)?;
let alias = self.maybe_parse_table_alias()?;
+
+ // Parse optional SAMPLE clause after alias
+ let sample = self
+ .maybe_parse_table_sample()?
+ .map(TableSampleKind::AfterTableAlias);
+
Ok(TableFactor::Derived {
lateral: match lateral {
Lateral => true,
@@ -15887,6 +15894,7 @@ impl<'a> Parser<'a> {
},
subquery,
alias,
+ sample,
})
}
diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs
index dcc92207..b2c41d97 100644
--- a/tests/sqlparser_common.rs
+++ b/tests/sqlparser_common.rs
@@ -512,7 +512,8 @@ fn parse_update_set_from() {
format_clause: None,
pipe_operators: vec![],
}),
- alias: table_alias(true, "t2")
+ alias: table_alias(true, "t2"),
+ sample: None,
},
joins: vec![]
}])),
@@ -7863,6 +7864,7 @@ fn parse_derived_tables() {
lateral: false,
subquery: Box::new(verified_query("(SELECT 1) UNION
(SELECT 2)")),
alias: table_alias(true, "t1"),
+ sample: None,
},
joins: vec![Join {
relation:
table_from_name(ObjectName::from(vec!["t2".into()])),
@@ -8871,6 +8873,7 @@ fn lateral_derived() {
lateral,
ref subquery,
alias: Some(ref alias),
+ sample: _,
} = join.relation
{
assert_eq!(lateral_in, lateral);
@@ -9950,6 +9953,7 @@ fn parse_merge() {
pipe_operators: vec![],
}),
alias: table_alias(true, "stg"),
+ sample: None,
}
);
assert_eq!(source, source_no_into);
diff --git a/tests/sqlparser_snowflake.rs b/tests/sqlparser_snowflake.rs
index ede912eb..cb5af621 100644
--- a/tests/sqlparser_snowflake.rs
+++ b/tests/sqlparser_snowflake.rs
@@ -3406,6 +3406,23 @@ fn test_table_sample() {
snowflake_and_generic().verified_stmt("SELECT id FROM mytable TABLESAMPLE
(10) SEED (1)");
}
+#[test]
+fn test_subquery_sample() {
+ // Test SAMPLE clause on subqueries (derived tables)
+ snowflake_and_generic().verified_stmt("SELECT * FROM (SELECT * FROM
mytable) SAMPLE (10)");
+ snowflake_and_generic()
+ .verified_stmt("SELECT * FROM (SELECT * FROM mytable) SAMPLE (10000
ROWS)");
+ snowflake_and_generic()
+ .verified_stmt("SELECT * FROM (SELECT * FROM mytable) AS t SAMPLE (50
PERCENT)");
+ // Nested subquery with SAMPLE
+ snowflake_and_generic().verified_stmt(
+ "SELECT * FROM (SELECT * FROM (SELECT report_from FROM mytable) SAMPLE
(10000 ROWS)) AS anon_1",
+ );
+ // SAMPLE with SEED on subquery
+ snowflake_and_generic()
+ .verified_stmt("SELECT * FROM (SELECT * FROM mytable) SAMPLE (10) SEED
(42)");
+}
+
#[test]
fn parse_ls_and_rm() {
snowflake().one_statement_parses_to("LS @~", "LIST @~");
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]