github-actions[bot] commented on code in PR #69176:
URL: https://github.com/apache/doris/pull/69176#discussion_r4323713695


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/RowLevelDmlCommand.java:
##########
@@ -80,10 +89,34 @@ public void run(ConnectContext ctx, StmtExecutor 
stmtExecutor) throws Exception
             Callable<Void> execute = () -> {
                 LogicalPlanAdapter logicalPlanAdapter = new 
LogicalPlanAdapter(plan, ctx.getStatementContext());
                 NereidsPlanner planner = new 
NereidsPlanner(ctx.getStatementContext());
+                if (op == RowLevelDmlOp.DELETE) {
+                    captureAnalyzedPlan(ctx);

Review Comment:
   [P2] Preserve physical slot provenance in fallback conflict filters
   
   This new capture also supplies the analyzed plan to 
`applyWriteConstraintIfPresent` after the metadata path falls back. Consider 
the analyzed mask plan:
   
   ```text
   DeleteSink
     Project(operation, row_id)
       Filter(a#masked = 1)
         Project(b AS a#masked, b, row_id)
           Scan(t)
   ```
   
   The exact extractor rejects the renamed slot, but fallback 
`extractWriteConstraint` still uses the loose extractor, which checks only the 
original table and emits physical `a = 1`. On an unpartitioned table with 
serializable delete isolation, a concurrent appended file containing 
`(a=0,b=1)` is then excluded from `RowDelta.conflictDetectionFilter`, so 
`validateNoConflictingDataFiles` misses a matching write. Previously a plain 
DELETE supplied no analyzed plan and left this conflict check unfiltered. 
Validate/rewrite projected slot provenance in the loose extractor too, or omit 
this conjunct conservatively. This is the newly activated fallback conflict 
consumer; the earlier projection thread covers direct metadata-file deletion.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/PositionDeleteRowLevelDmlTransform.java:
##########
@@ -209,10 +212,45 @@ public void finalizeSink(BaseExternalTableInsertExecutor 
executor, RowLevelDmlOp
 
     @Override
     public Optional<ConnectorPredicate> extractWriteConstraint(Plan 
analyzedPlan, TableIf table) {
+        return WriteConstraintExtractor.extract(analyzedPlan, table.getId(), 
syntheticColumnExclusion(table));

Review Comment:
   [P2] Distinguish the target relation from self-joined source scans
   
   The newly captured DELETE plan also makes this loose extractor visit filters 
inside a `USING` source. For example:
   
   ```sql
   DELETE FROM t d
   USING (SELECT id FROM t WHERE flag = 1) s
   WHERE d.id = s.id + 1
   ```
   
   The analyzed tree contains `Join(Scan(t d), Project(id, Filter(flag=1, 
Scan(t))))`. Both scans have the same table ID, so `isTargetOnlyPredicate` 
accepts the source-only `flag=1` conjunct and the fallback installs it as the 
target's `RowDelta.conflictDetectionFilter`. With rows `(id=1,flag=1)` and 
`(id=2,flag=0)`, the DELETE targets the second row, yet serializable validation 
excludes a concurrently appended `(id=2,flag=0)` file. The strict metadata 
extractor rejects the join, so this reaches the row-level commit; the earlier 
uncaptured plan left its conflict check unfiltered. Track the target scan's 
relation/slot identity, or omit source-subtree predicates conservatively. 
Matching physical column names alone cannot distinguish the two relation 
instances.



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