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


##########
fe/fe-connector/fe-connector-paimon/src/main/java/org/apache/doris/connector/paimon/PaimonScanPlanProvider.java:
##########
@@ -2087,27 +2254,61 @@ static FileStoreTable 
legacyOrcSplitTable(FileStoreTable table, DataSplit split)
         return base;
     }
 
-    static boolean requiresLegacyOrcTimestampReader(Table table, 
Optional<List<RawFile>> rawFiles,
+    private static boolean requiresCrossFamilyTimestampReader(FileStoreTable 
table, Optional<List<RawFile>> rawFiles,
+            Set<Integer> readFieldIds, Map<Long, Boolean> schemaTimestamps) {
+        RowType readType = new RowType(table.rowType().getFields().stream()
+                .filter(field -> 
readFieldIds.contains(field.id())).collect(Collectors.toList()));
+        if (!containsTimestampType(readType)) {
+            return false;
+        }
+        for (RawFile file : rawFiles.get()) {
+            if (schemaTimestamps.computeIfAbsent(file.schemaId(), id -> 
hasTimestampPrecisionNarrowing(
+                    table.schemaManager().schema(id).logicalRowType(), 
readType, 0, true))) {
+                // Generic native casts round after zone conversion. The SDK 
keeps its conversion
+                // semantics while the JNI widened read type delays truncation 
until materialization.
+                return true;
+            }
+        }
+        return false;
+    }
+
+    static boolean requiresOrcTimestampReader(Table table, 
Optional<List<RawFile>> rawFiles,
             Set<Integer> readFieldIds, Map<Long, Boolean> schemaTimestamps) {
         if (readFieldIds.isEmpty() || !rawFiles.isPresent()
-                || rawFiles.get().stream().noneMatch(f -> 
f.path().endsWith(".orc"))
-                || !new org.apache.paimon.options.Options(table.options()).get(
-                        
org.apache.paimon.format.OrcOptions.ORC_TIMESTAMP_LTZ_LEGACY_TYPE)) {
+                || rawFiles.get().stream().noneMatch(f -> 
f.path().endsWith(".orc"))) {
             return false;
         }
         // Only fields present in a file require SDK timezone conversion. A 
newly added nullable LTZ
         // column reads as NULL in older files and must not disable their 
native metadata scans.
         FileStoreTable fileStoreTable = (FileStoreTable) table;
+        boolean legacyLtz = new 
org.apache.paimon.options.Options(table.options()).get(
+                
org.apache.paimon.format.OrcOptions.ORC_TIMESTAMP_LTZ_LEGACY_TYPE);
+        RowType readType = new 
RowType(fileStoreTable.rowType().getFields().stream()
+                .filter(field -> 
readFieldIds.contains(field.id())).collect(Collectors.toList()));

Review Comment:
   [P1] Translate read-field IDs into the selected fallback branch
   
   `readFieldIds` comes from the outer table, but `fileStoreTable` is the 
branch selected for this split. Paimon accepts fallback schemas with matching 
positional types and different field IDs. For example, start with `(pt#0, ts#1 
TIMESTAMP(9))`; fork, then drop/re-add `ts` as #2/p0 on main while fallback 
retains #1 and narrows p9 to p0. `SELECT ts` supplies `{2}`, so this filter 
removes fallback `ts#1` and both timestamp-routing helpers miss its historical 
narrowing. The ORC file stays native and `00:00:01.999999500` becomes 
`00:00:02`, rather than `00:00:01`. This can reach materialization without a 
missing-column failure: write fallback's p9 file under schema ID 2 after two 
option-only changes, matching main schema 2's same-name re-added field; the 
native history annotator assigns main's ID by name while retaining physical 
precision. Translate the read selection to each branch's ID domain before 
checking history, and cover independently evolved branch IDs with automatic 
routing. T
 his is a separate field-identity gap in the new FE routing guard, beyond the 
existing ordinary ORC precision issue.



##########
fe/fe-connector/fe-connector-paimon/src/main/java/org/apache/doris/connector/paimon/PaimonScanPlanProvider.java:
##########
@@ -1241,15 +1251,27 @@ public Map<String, String> getScanNodeProperties(
         // ("encodedStr is null"). Mirrors legacy 
PaimonScanNode.createScanRangeLocations, which always called
         // setPaimonPredicate(encodeObjectToString(predicates)) regardless of 
whether predicates was empty.
         List<org.apache.paimon.predicate.Predicate> predicates = 
Collections.emptyList();
+        // The same predicate must stay out of the BE Paimon reader: JNI 
materializes and repairs the
+        // value first, then the generic scan path evaluates the residual 
against the repaired column.
         if (filter.isPresent()) {
             RowType rowType = table.rowType();
-            PaimonPredicateConverter converter = new 
PaimonPredicateConverter(rowType);
+            PaimonPredicateConverter converter = new PaimonPredicateConverter(
+                    rowType, filterReadsTimestamp(rowType, filter.get())
+                            && requiresTimestampPrecisionRepair(session, 
table, paimonHandle));
             predicates = converter.convert(filter.get());
         }
         props.put("paimon.predicate", encodeObjectToString(predicates));
 
         // Paimon JDBC metastore options for BE (if applicable)
         Map<String, String> backendOptions = new 
LinkedHashMap<>(getBackendPaimonOptions());
+        Set<Integer> readFieldIds = scanReadFieldIds(table.rowType(), columns, 
filter);
+        boolean readsTimestamp = 
table.rowType().getFields().stream().anyMatch(field ->
+                readFieldIds.contains(field.id())
+                        && containsTimestampType(field.type()));
+        backendOptions.put(DORIS_TIMESTAMP_PRECISION_REPAIR, String.valueOf(
+                (readsTimestamp || new 
org.apache.paimon.options.Options(table.options()).get(

Review Comment:
   [P2] Check query-auth enablement on both fallback branches
   
   `table.options()` exposes the wrapped branch's options, while the other 
branch can independently enable query auth. With wrapped auth disabled, 
fallback auth enabled, and `SELECT id` with no SQL timestamp reference, this 
emits `doris.timestamp-precision-repair=false` even when a fallback policy 
reads an evolved timestamp. JNI then refuses to activate its hidden-policy 
repair. For a supported typed SDK policy comparing historical p6 
`00:00:01.000001`, narrowed to p4, with `00:00:01.0000`, Paimon's ordinary 
precision cast leaves the fraction and the policy rejects the matching logical 
row. The existing hidden-policy reader test manually passes `true`, and the FE 
test enables auth on the whole pair. Inspect branch-local auth settings, or let 
the actual split-carried policy activate repair, and cover integer-only output 
when auth is enabled exclusively on the secondary branch. This is a missed 
repair path in the new gate; remote JSON timestamp-policy end-to-end behavior 
has not been v
 alidated.



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