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


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalFileScan.java:
##########
@@ -65,6 +68,8 @@ public class LogicalFileScan extends LogicalCatalogRelation 
implements SupportPr
     protected final Optional<TableSnapshot> tableSnapshot;
     protected final Optional<TableScanParams> scanParams;
     protected final Optional<List<Slot>> cachedOutputs;
+    protected final Optional<List<Column>> relationSchema;
+    protected final Optional<MvccSnapshot> relationSnapshot;

Review Comment:
   [P1] Include the resolved snapshot in scan equality
   
   This new state is preserved by the generic copy paths, but 
`hasSameScanState` still compares only selected partitions, sample, and the raw 
snapshot/ref parameters. If branch `b` advances between two bindings, 
`t@branch(b)` can carry S0 and S1 while still comparing equal; 
`PullUpJoinFromUnionAll` may then hoist one scan from `Union(Join(A,t@b[S0]), 
Join(B,t@b[S1]))` and replace the second arm's data. Please either fence 
identical refs to one statement snapshot or include a stable resolved snapshot 
identity in semantic equality, with a rewrite test for distinct resolved heads.



##########
fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSExternalTable.java:
##########
@@ -392,6 +392,19 @@ public List<Column> getFullSchema() {
         return schemaCacheValue.map(SchemaCacheValue::getSchema).orElse(null);
     }
 
+    @Override
+    public List<Column> getFullSchema(Optional<MvccSnapshot> snapshot) {
+        makeSureInitialized();
+        // HMS can front snapshot-aware formats too; callers that pin a 
relation must not fall
+        // back to the table's current schema merely because its catalog type 
is HMS.
+        if (getDlaType() == DLAType.HUDI) {

Review Comment:
   [P1] Carry the snapshot through the specialized Hudi scan
   
   This overload is snapshot-aware, but the Hudi arm of `BindRelation` still 
creates `LogicalHudiScan` through its legacy path. That leaves its relation 
schema uncaptured, its logical/physical copies do not preserve the resolved 
snapshot, and `visitPhysicalHudiScan` never installs it on `HudiScanNode`; 
those paths fall back to the last table-scoped snapshot. A query mixing latest 
and historical Hudi relations across a column or partition-schema evolution can 
therefore bind or scan one side with the other side's metadata. Please carry 
both relation schema and snapshot through the Hudi-specific logical, physical, 
and translator path and cover both relation orders.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalFileScan.java:
##########
@@ -73,12 +78,24 @@ public LogicalFileScan(RelationId id, ExternalTable table, 
List<String> qualifie
             Collection<Slot> operativeSlots,
             Optional<TableSample> tableSample, Optional<TableSnapshot> 
tableSnapshot,
             Optional<TableScanParams> scanParams, Optional<List<Slot>> 
cachedOutputs) {
+        this(id, table, qualifier, operativeSlots, tableSample, tableSnapshot, 
scanParams, cachedOutputs,
+                MvccUtil.getSnapshotFromContext(table));
+    }
+
+    /**
+     * Constructor for a relation whose concrete snapshot was resolved during 
binding.
+     */
+    public LogicalFileScan(RelationId id, ExternalTable table, List<String> 
qualifier,
+            Collection<Slot> operativeSlots,
+            Optional<TableSample> tableSample, Optional<TableSnapshot> 
tableSnapshot,
+            Optional<TableScanParams> scanParams, Optional<List<Slot>> 
cachedOutputs,
+            Optional<MvccSnapshot> relationSnapshot) {
         this(id, table, qualifier,
-                
table.initSelectedPartitions(MvccUtil.getSnapshotFromContext(table)),
+                table.initSelectedPartitions(relationSnapshot),

Review Comment:
   [P1] Use the relation snapshot for partition pruning
   
   The partition map is now frozen from `relationSnapshot` here, but 
`PruneFileScanPartition` still fetches both partition-column lists from 
`StatementContext.getSnapshot(externalTable)`. After another version/ref of the 
same table is bound, that table-scoped entry can be S1 while this scan and its 
partition map are S0. With partition-schema/spec evolution, the rule then maps 
S1 columns into S0 output and can prune with null or wrong slots. Please use 
`scan.getRelationSnapshot()` for all pruning metadata and add a filtered 
dual-version case.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/StatementContext.java:
##########
@@ -982,15 +983,23 @@ public void addPlannerHook(PlannerHook plannerHook) {
      * @param tableSnapshot table snapshot info
      * @param scanParams table scan params (e.g., branch/tag for Iceberg 
tables)
      */
-    public void loadSnapshots(TableIf specificTable, Optional<TableSnapshot> 
tableSnapshot,
+    public Optional<MvccSnapshot> loadSnapshots(TableIf specificTable, 
Optional<TableSnapshot> tableSnapshot,
             Optional<TableScanParams> scanParams) {
-        if (specificTable instanceof MvccTable) {
-            MvccTableInfo mvccTableInfo = new MvccTableInfo(specificTable);
-            if (!snapshots.containsKey(mvccTableInfo)) {
-                snapshots.put(mvccTableInfo,
-                        ((MvccTable) 
specificTable).loadSnapshot(tableSnapshot, scanParams));
-            }
+        if (!(specificTable instanceof MvccTable)) {
+            return Optional.empty();
+        }
+        MvccTableInfo mvccTableInfo = new MvccTableInfo(specificTable);
+        MvccSnapshot snapshot;
+        if (tableSnapshot.isPresent() || scanParams.isPresent()) {
+            snapshot = ((MvccTable) specificTable).loadSnapshot(tableSnapshot, 
scanParams);
+        } else {
+            // Keep latest metadata separate: a historical relation may 
temporarily become the
+            // table-scoped snapshot, but it must not redefine what a later 
latest relation sees.
+            snapshot = latestSnapshots.computeIfAbsent(mvccTableInfo,

Review Comment:
   [P1] Preserve the snapshot injected by MTMV refresh
   
   `MTMVTask.beforeMTMVRefresh` captures each MVCC base-table snapshot, and 
every `exec` injects those exact values into a new `StatementContext` with 
`setSnapshot`. Because that setter fills only `snapshots`, this new cache is 
empty: the first unqualified binding reloads S1 here and overwrites the 
injected S0. This discards the task's captured execution fence, so later 
refresh batches or retries can bind a newer metadata generation than the one 
the task deliberately captured. Please make the injected latest snapshot 
authoritative for this cache and add an injection-then-unqualified-load test.



##########
regression-test/suites/external_table_p0/iceberg/test_iceberg_schema_dual_relation_matrix.groovy:
##########
@@ -93,10 +93,24 @@ suite("test_iceberg_schema_dual_relation_matrix",
             order by id
         """))
 
-        // Scenario TC07-join negative contract:
-        // two historical relations in one statement currently reuse the first 
schema.
-        test {
-            sql """
+        // Latest metadata must be restored even when a historical relation is 
bound first.
+        assertEquals([[1, "old-1", "old-1"]], sql("""

Review Comment:
   [P2] Record deterministic results in generated oracles
   
   These new matrix queries have exact, ordered expected rows, but they are 
asserted only in Groovy and none of the matrix suites has a generated `.out` 
artifact. That bypasses the repository's required `qt_`/result-generation 
workflow for determined outputs and makes the contract invisible to normal 
golden-result review. Please convert the deterministic positive-result checks 
to ordered `qt_` cases and generate the matching `.out` files; keep direct 
assertions only for genuinely dynamic metadata predicates.



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