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.git


The following commit(s) were added to refs/heads/main by this push:
     new c89cb70781 Add Explicit Error Handling for Unsupported SQL `FETCH` 
Clause in Planner and CLI (#18691)
c89cb70781 is described below

commit c89cb70781dd3e8c52f7cbfff51c2b850900a132
Author: kosiew <[email protected]>
AuthorDate: Mon Dec 1 16:16:32 2025 +0800

    Add Explicit Error Handling for Unsupported SQL `FETCH` Clause in Planner 
and CLI (#18691)
    
    ## Which issue does this PR close?
    
    * Closes #17716.
    
    ## Rationale for this change
    
    The `FETCH NEXT` clause was being parsed without triggering an error,
    resulting in the CLI executing queries containing unsupported SQL
    syntax. This could mislead users into believing the feature is supported
    and undermine SQL correctness guarantees. Adding explicit handling
    ensures unsupported syntax fails fast with a clear and consistent error
    message.
    
    ## What changes are included in this PR?
    
    * Added explicit detection of the `FETCH` clause in `SqlToRel` and
    return a `not_impl_err!` when encountered.
    * Updated CLI integration tests to include a snapshot verifying that the
    CLI now returns an error when `FETCH` is used.
    * Added a SQL integration test confirming that the planner correctly
    rejects `FETCH`.
    * Updated user documentation to note that DataFusion does not currently
    support the SQL `FETCH` clause.
    
    ## Are these changes tested?
    
    Yes. The PR includes:
    
    * A new CLI integration test snapshot validating the error message.
    * A new SQL integration test (`fetch_clause_is_not_supported`) verifying
    planner behavior.
    
    ## Are there any user-facing changes?
    
    Yes. Queries using the SQL `FETCH` clause will now produce a clear error
    instead of executing unexpectedly. Documentation has been updated to
    reflect this behavior.
    
    ## LLM-generated code disclosure
    
    This pull request includes code that was generated with assistance from
    LLM.
    All LLM-generated code in this PR has been manually reviewed and tested.
---
 datafusion/sql/src/query.rs                   | 31 +++++++++++++++++++++------
 datafusion/sql/tests/sql_integration.rs       |  7 ++++++
 datafusion/sqllogictest/test_files/errors.slt |  5 +++++
 3 files changed, 36 insertions(+), 7 deletions(-)

diff --git a/datafusion/sql/src/query.rs b/datafusion/sql/src/query.rs
index d316550f4d..6a9267a9a5 100644
--- a/datafusion/sql/src/query.rs
+++ b/datafusion/sql/src/query.rs
@@ -46,17 +46,34 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
         let mut query_plan_context = outer_planner_context.clone();
         let planner_context = &mut query_plan_context;
 
-        if let Some(with) = query.with {
+        let Query {
+            with,
+            body,
+            order_by,
+            limit_clause,
+            fetch,
+            locks: _,
+            for_clause: _,
+            settings: _,
+            format_clause: _,
+            pipe_operators,
+        } = query;
+
+        if fetch.is_some() {
+            return not_impl_err!("FETCH clause is not supported yet");
+        }
+
+        if let Some(with) = with {
             self.plan_with_clause(with, planner_context)?;
         }
 
-        let set_expr = *query.body;
+        let set_expr = *body;
         let plan = match set_expr {
             SetExpr::Select(mut select) => {
                 let select_into = select.into.take();
                 let plan =
-                    self.select_to_plan(*select, query.order_by, 
planner_context)?;
-                let plan = self.limit(plan, query.limit_clause, 
planner_context)?;
+                    self.select_to_plan(*select, order_by.clone(), 
planner_context)?;
+                let plan = self.limit(plan, limit_clause.clone(), 
planner_context)?;
                 // Process the `SELECT INTO` after `LIMIT`.
                 self.select_into(plan, select_into)
             }
@@ -69,7 +86,7 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
                     let _guard = StackGuard::new(256 * 1024);
                     self.set_expr_to_plan(other, planner_context)
                 }?;
-                let oby_exprs = to_order_by_exprs(query.order_by)?;
+                let oby_exprs = to_order_by_exprs(order_by)?;
                 let order_by_rex = self.order_by_to_sort_expr(
                     oby_exprs,
                     plan.schema(),
@@ -78,11 +95,11 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
                     None,
                 )?;
                 let plan = self.order_by(plan, order_by_rex)?;
-                self.limit(plan, query.limit_clause, planner_context)
+                self.limit(plan, limit_clause, planner_context)
             }
         }?;
 
-        self.pipe_operators(plan, query.pipe_operators, planner_context)
+        self.pipe_operators(plan, pipe_operators, planner_context)
     }
 
     /// Apply pipe operators to a plan
diff --git a/datafusion/sql/tests/sql_integration.rs 
b/datafusion/sql/tests/sql_integration.rs
index 7615891be3..c52b09afce 100644
--- a/datafusion/sql/tests/sql_integration.rs
+++ b/datafusion/sql/tests/sql_integration.rs
@@ -3971,6 +3971,13 @@ Limit: skip=3, fetch=5
     );
 }
 
+#[test]
+fn fetch_clause_is_not_supported() {
+    let sql = "SELECT 1 FETCH NEXT 1 ROW ONLY";
+    let err = logical_plan(sql).unwrap_err();
+    assert_contains!(err.to_string(), "FETCH clause is not supported yet");
+}
+
 #[test]
 fn test_offset_before_limit() {
     let sql = "select id from person where person.id > 100 OFFSET 3 LIMIT 5;";
diff --git a/datafusion/sqllogictest/test_files/errors.slt 
b/datafusion/sqllogictest/test_files/errors.slt
index 41f747df5b..22430774bb 100644
--- a/datafusion/sqllogictest/test_files/errors.slt
+++ b/datafusion/sqllogictest/test_files/errors.slt
@@ -74,6 +74,11 @@ statement error DataFusion error: Error during planning: 
Unsupported compound id
 SELECT COUNT(*) FROM 
way.too.many.namespaces.as.ident.prefixes.aggregate_test_100
 
 
+# fetch_clause_not_supported
+statement error FETCH clause is not supported yet
+SELECT 1 FETCH NEXT 1 ROW ONLY
+
+
 
 #
 # Wrong scalar function signature


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to