NGA-TRAN commented on code in PR #17843:
URL: https://github.com/apache/datafusion/pull/17843#discussion_r2529891968


##########
datafusion/core/src/execution/context/mod.rs:
##########
@@ -1365,6 +1367,18 @@ impl SessionContext {
         self.state.write().register_udwf(Arc::new(f)).ok();
     }
 
+    #[cfg(feature = "sql")]
+    /// Registers a [`RelationPlanner`] to customize SQL table-factor planning.
+    ///
+    /// Planners are invoked in reverse registration order, allowing newer
+    /// planners to take precedence over existing ones.

Review Comment:
   This comment is important



##########
datafusion/sql/src/relation/mod.rs:
##########
@@ -24,19 +24,119 @@ use datafusion_common::{
     not_impl_err, plan_err, DFSchema, Diagnostic, Result, Span, Spans, 
TableReference,
 };
 use datafusion_expr::builder::subquery_alias;
+use datafusion_expr::planner::{
+    PlannedRelation, RelationPlannerContext, RelationPlanning,
+};
 use datafusion_expr::{expr::Unnest, Expr, LogicalPlan, LogicalPlanBuilder};
 use datafusion_expr::{Subquery, SubqueryAlias};
 use sqlparser::ast::{FunctionArg, FunctionArgExpr, Spanned, TableFactor};
 
 mod join;
 
+struct SqlToRelRelationContext<'a, 'b, S: ContextProvider> {

Review Comment:
   I had to review the tests and this a few times to really understand why 
things work that way. You’ve built a very powerful framework/extension with 
such a simple design—impressive work.
   
   A few thoughts:
   
   - If users know what they’re doing and register the relation planner in the 
correct reverse order, will everything consistently work as expected?
   
   - How do we test this assumption? Your example is mind‑blowing, but how can 
we be confident it will hold for any order of standard SQL?
   
   I believe it will work, but I keep asking myself: how do we know it will 
always work?
   
   
   ```rust
   let ctx = SessionContext::new();
   
   // Register custom planners for SQL syntax extensions
   ctx.register_relation_planner(Arc::new(TableSamplePlanner))?;
   ctx.register_relation_planner(Arc::new(MatchRecognizePlanner))?;
   ctx.register_relation_planner(Arc::new(PivotUnpivotPlanner))?;
   
   // Use multiple custom table modifiers together - even in nested JOINs or 
CTEs
   let df = ctx.sql(r#"
       WITH sampled_data AS (
           SELECT * FROM stock_prices 
           TABLESAMPLE BERNOULLI(10 PERCENT) REPEATABLE(42)
       )
       SELECT symbol, quarter, price
       FROM sampled_data
       MATCH_RECOGNIZE (
           PARTITION BY symbol ORDER BY time
           MEASURES LAST(price) AS price, quarter
           PATTERN (UP+ DOWN+)
           DEFINE 
               UP AS price > PREV(price), 
               DOWN AS price < PREV(price)
       ) AS patterns
       PIVOT (
           AVG(price) FOR quarter IN ('Q1', 'Q2', 'Q3', 'Q4')
       ) AS pivoted
   "#).await?;
   
   df.show().await?;
   ```



##########
datafusion/core/src/execution/session_state.rs:
##########
@@ -581,6 +586,24 @@ impl SessionState {
         &self.expr_planners
     }
 
+    #[cfg(feature = "sql")]
+    /// Returns the registered relation planners in priority order.
+    pub fn relation_planners(&self) -> &[Arc<dyn RelationPlanner>] {
+        &self.relation_planners
+    }
+
+    #[cfg(feature = "sql")]
+    /// Registers a [`RelationPlanner`] to customize SQL relation planning.
+    ///
+    /// Newly registered planners are given higher priority than existing ones.

Review Comment:
   👍 This is consistent with the comment above



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to