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


##########
fe/fe-core/src/main/java/org/apache/doris/datasource/FileQueryScanNode.java:
##########
@@ -718,6 +732,29 @@ public TableScanParams getScanParams() {
         return this.scanParams;
     }
 
+    /**
+     * Return metadata pinned for this scan relation.
+     */
+    protected Optional<MvccSnapshot> getRelationSnapshot() {
+        if (relationSnapshotInitialized) {
+            return relationSnapshot;
+        }
+        relationSnapshotInitialized = true;
+        TableIf targetTable = desc.getTable();
+        if (!(targetTable instanceof MvccTable)) {
+            return Optional.empty();
+        }
+        if (tableSnapshot != null || scanParams != null) {

Review Comment:
   [P1] Reuse the snapshot pinned while binding this relation
   
   For a branch/ref, this calls `loadSnapshot` again during physical scan 
initialization. The logical output and tuple slots were built from branch head 
S0, but if the branch advances before this call, schema params and the 
Paimon/Iceberg scan source come from S1. A rename can fail column mapping; 
without a rename the query can read S1 under a plan analyzed at S0, contrary to 
the `MvccTable` whole-query snapshot contract. Please carry the bound 
`MvccSnapshot` through logical-to-physical translation instead of re-resolving 
raw qualifiers, and test successive mocked loads returning different heads.



##########
fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalTable.java:
##########
@@ -178,6 +178,10 @@ public List<Column> getFullSchema() {
         return schemaCacheValue.map(SchemaCacheValue::getSchema).orElse(null);
     }
 
+    public List<Column> getFullSchema(Optional<MvccSnapshot> snapshot) {

Review Comment:
   [P1] Honor the relation snapshot for HMS Iceberg schemas
   
   `HMSExternalTable` implements `MvccTable` and returns an 
`IcebergMvccSnapshot`, but it inherits this overload, which discards that 
snapshot and calls the context-sensitive no-argument accessor. 
`LogicalFileScan.captureRelationSchema` also handles only the direct 
Iceberg/Paimon table classes. As a result, two HMS-Iceberg relations at 
different versions still derive both schemas from the last table-wide entry; 
across a rename, one side fails column mapping depending on relation order. 
Please implement snapshot-aware HMS-Iceberg schema access and select 
relation-local capture by MVCC capability, with a dual-version HMS test in both 
orders.



##########
fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergUtils.java:
##########
@@ -1467,7 +1464,9 @@ public static IcebergTableQueryInfo getQuerySpecSnapshot(
             return new IcebergTableQueryInfo(
                 snapshotRef.snapshotId(),
                 refName,
-                SnapshotUtil.schemaFor(table, refName).schemaId());
+                // Iceberg maps a branch name to the table's latest schema, so 
resolve the branch
+                // head snapshot directly to keep historical branch columns 
isolated.
+                SnapshotUtil.schemaFor(table, 
snapshotRef.snapshotId()).schemaId());

Review Comment:
   [P2] Plan historical Iceberg filters with the historical schema
   
   This correctly selects the branch-head snapshot schema, but downstream 
`IcebergScanNode` paths still convert conjuncts with `icebergTable.schema()`; 
the manifest-cache path also constructs metrics/residual evaluators from that 
current schema. A predicate on a renamed-away historical column therefore 
cannot be pushed, and a drop/re-add of the same name binds the new field ID 
instead of the queried historical ID, defeating field-ID-aware pruning. Please 
use the pinned snapshot ID and its schema consistently for filter conversion, 
evaluators, and the table scan, and add a rename or drop/re-add pruning test.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindSink.java:
##########
@@ -813,6 +813,8 @@ private Plan 
bindIcebergTableSink(MatchingContext<UnboundIcebergTableSink<Plan>>
             }
         }
 
+        // Iceberg branches share the table metadata schema, so writes use the 
latest schema

Review Comment:
   [P1] Bind branch-write targets from target-specific latest metadata
   
   The comment states the required contract, but every target lookup below 
(`getBaseSchema`, `getColumn`, and `getFullSchema`) is still backed by the 
statement's table-scoped snapshot. For `IcebergSink t@branch(b)(id,new_name) -> 
Project(id,old_name) -> Scan t FOR VERSION AS OF old`, binding the child 
overwrites that entry with the old source schema, so the sink rejects valid 
`new_name` or derives old target coercions. This affects both INSERT and 
OVERWRITE SELECT. Please use the target schema already collected before child 
binding (or another target-specific latest snapshot), and cover this plan shape.



##########
fe/fe-type/src/main/java/org/apache/doris/catalog/Type.java:
##########
@@ -482,18 +486,27 @@ public String hideVersionForVersionColumn(Boolean 
isToSql) {
             }
             return typeStr.toString();
         } else if (isArrayType()) {
-            String nestedDesc = ((ArrayType) 
this).getItemType().hideVersionForVersionColumn(isToSql);
+            String nestedDesc = ((ArrayType) this).getItemType()
+                    .hideVersionForVersionColumn(isToSql, showNestedComment);
             return "array<" + nestedDesc + ">";
         } else if (isMapType()) {
-            String keyDesc = ((MapType) 
this).getKeyType().hideVersionForVersionColumn(isToSql);
-            String valueDesc = ((MapType) 
this).getValueType().hideVersionForVersionColumn(isToSql);
+            String keyDesc = ((MapType) this).getKeyType()
+                    .hideVersionForVersionColumn(isToSql, showNestedComment);
+            String valueDesc = ((MapType) this).getValueType()
+                    .hideVersionForVersionColumn(isToSql, showNestedComment);
             return "map<" + keyDesc + "," + valueDesc + ">";
         } else if (isStructType()) {
             List<String> fieldDesc = new ArrayList<>();
             StructType structType = (StructType) this;
             for (int i = 0; i < structType.getFields().size(); i++) {
                 StructField field = structType.getFields().get(i);
-                fieldDesc.add(field.getName() + ":" + 
field.getType().hideVersionForVersionColumn(isToSql));
+                StringBuilder desc = new 
StringBuilder(field.getName()).append(":")

Review Comment:
   [P2] Preserve nested requiredness in DESCRIBE output
   
   This new manual struct rendering adds comments but omits the ` not null` 
suffix that `StructField.toSql` emits when `getContainsNull()` is false. The 
same patch now maps Iceberg nested fields with `x.isOptional()`, so 
`required_child` is preserved internally yet DESCRIBE renders it 
indistinguishably from an optional child. The new tests construct only optional 
nested fields. Please append ` not null` before the comment for required fields 
and add adjacent required/optional coverage with nested-comment display both 
enabled and disabled.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/StatementContext.java:
##########
@@ -986,7 +986,12 @@ public void loadSnapshots(TableIf specificTable, 
Optional<TableSnapshot> tableSn
             Optional<TableScanParams> scanParams) {
         if (specificTable instanceof MvccTable) {
             MvccTableInfo mvccTableInfo = new MvccTableInfo(specificTable);
-            if (!snapshots.containsKey(mvccTableInfo)) {
+            if (tableSnapshot.isPresent() || scanParams.isPresent()) {

Review Comment:
   [P1] Keep latest and historical snapshots relation-scoped
   
   Overwriting the sole `MvccTableInfo` key still breaks a statement that mixes 
an unqualified/latest relation with a historical relation. In latest-first 
order, the historical relation replaces the map entry and the latest scan later 
falls back to the old snapshot. In historical-first order, the unqualified 
relation deliberately does not restore latest and captures the old schema 
immediately. After schema evolution this can reject the latest columns or pair 
them with historical data in both Iceberg and Paimon. Please store a concrete 
snapshot per relation, including the unqualified latest relation, and add both 
relation orders to the dual-relation tests.



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