LuciferYang opened a new issue, #9631:
URL: https://github.com/apache/paimon/issues/9631

   ### Search before asking
   
   - [x] I searched in the [issues](https://github.com/apache/paimon/issues) 
and found nothing similar.
   
   ### Paimon version
   
   master, `475be566f` (2.1-SNAPSHOT).
   
   ### Compute Engine
   
   Flink. `SupportsRowLevelOperationFlinkTableSink` is the only production user 
of this visitor.
   
   ### Minimal reproduce step
   
   This one is a contract problem rather than something I could trigger from 
SQL, and I want to be upfront about that.
   
   `OnlyPartitionKeyEqualVisitor` decides whether a DELETE can be executed by 
dropping partitions. It collects the equality literals into a map, one entry 
per partition key:
   
   ```java
   public Boolean visitEqual(FieldRef fieldRef, Object literal) {
       boolean contains = partitionKeys.contains(fieldRef.name());
       if (contains) {
           partitions.put(fieldRef.name(), literal.toString());
           return true;
       }
       return false;
   }
   ```
   
   Two equality predicates on the same key therefore overwrite each other, and 
the conjunction still reports "droppable". Feeding it `pt = 'a' AND pt = 'b'`:
   
   ```java
   OnlyPartitionKeyEqualVisitor visitor = new 
OnlyPartitionKeyEqualVisitor(Arrays.asList("pt", "dt"));
   Predicate contradiction = PredicateBuilder.and(equal(pt, "a"), equal(pt, 
"b"));
   contradiction.visit(visitor);   // true
   visitor.partitions();           // {pt=b}
   ```
   
   The Flink sink reads that as a partition drop of `pt = 'b'` and deletes 
every row in that partition, while the predicate itself matches nothing.
   
   What I could not do is get such a predicate to the sink from SQL. `DELETE 
FROM t WHERE pt = 'a' AND pt = 'b'` is folded to FALSE by Calcite's 
simplification before `applyDeleteFilters` runs, and `PredicateBuilder.and` 
does not merge equality predicates itself, so the visitor only sees two `Equal` 
leaves if something hands them over unfolded. So today the guarantee that this 
cannot happen lives in the planner, not in Paimon.
   
   ### What doesn't meet your expectations?
   
   The visitor reduces a conjunction of constraints to a last-write-wins map, 
which loses the information that the constraints conflict. For a decision whose 
consequence is dropping a whole partition, that seems worth deciding inside 
Paimon rather than relying on an external optimizer to never pass a 
contradiction through. A future engine version, another engine binding, or a 
caller that builds the predicate directly would not have that protection.
   
   ### Anything else?
   
   The same class already returns false for everything it does not understand 
(`visitIsNull`, `visitIn`, ranges, OR), so a conservative answer for a 
contradiction fits how it is written.
   
   ### Are you willing to submit a PR?
   
   - [x] I'm willing to submit a PR!
   


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

Reply via email to