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]

Reply via email to