kosiew commented on code in PR #19884:
URL: https://github.com/apache/datafusion/pull/19884#discussion_r2707170578


##########
datafusion/core/src/physical_planner.rs:
##########
@@ -1907,24 +1907,48 @@ fn get_physical_expr_pair(
 }
 
 /// Extract filter predicates from a DML input plan (DELETE/UPDATE).
-/// Walks the logical plan tree and collects Filter predicates,
-/// splitting AND conjunctions into individual expressions.
+/// Walks the logical plan tree and collects Filter predicates and any filters
+/// pushed down into TableScan nodes, splitting AND conjunctions into 
individual expressions.
 /// Column qualifiers are stripped so expressions can be evaluated against
-/// the TableProvider's schema.
+/// the TableProvider's schema. Deduplicates filters to avoid passing the same
+/// predicate twice when filters appear in both Filter and TableScan nodes.
 ///
 fn extract_dml_filters(input: &Arc<LogicalPlan>) -> Result<Vec<Expr>> {
     let mut filters = Vec::new();
 
     input.apply(|node| {
-        if let LogicalPlan::Filter(filter) = node {
-            // Split AND predicates into individual expressions
-            
filters.extend(split_conjunction(&filter.predicate).into_iter().cloned());
+        match node {
+            LogicalPlan::Filter(filter) => {
+                // Split AND predicates into individual expressions
+                
filters.extend(split_conjunction(&filter.predicate).into_iter().cloned());
+            }
+            LogicalPlan::TableScan(TableScan {
+                filters: scan_filters,
+                ..
+            }) => {
+                for filter in scan_filters {
+                    
filters.extend(split_conjunction(filter).into_iter().cloned());
+                }
+            }
+            _ => {}
         }
         Ok(TreeNodeRecursion::Continue)
     })?;
 
-    // Strip table qualifiers from column references
-    filters.into_iter().map(strip_column_qualifiers).collect()
+    // Strip table qualifiers from column references and deduplicate.
+    // Deduplication is necessary because filters may appear in both Filter 
nodes
+    // and TableScan.filters when the optimizer pushes some predicates down.
+    // We deduplicate by (unqualified) expression to avoid passing the same 
filter twice.
+    let mut seen_filters = HashSet::new();
+    let deduped = filters

Review Comment:
   Addresssed via 
   Target Scan Scoping - 
https://github.com/apache/datafusion/pull/19884/commits/b66edf4774834e332bcdff85eb58f848b65a8a70
   Predicate-Level Validation - 
https://github.com/apache/datafusion/pull/19884/commits/cfc945d586e3daa9932b6f7710954f1675c639b3



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