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


##########
fe/fe-connector/fe-connector-jdbc/src/main/java/org/apache/doris/connector/jdbc/JdbcConnectorMetadata.java:
##########
@@ -163,7 +163,14 @@ public Optional<ConnectorTableStatistics> 
getTableStatistics(
     public Map<String, ConnectorColumnHandle> getColumnHandles(
             ConnectorSession session, ConnectorTableHandle handle) {
         if (handle instanceof PassthroughQueryTableHandle) {
-            return Collections.emptyMap();
+            Map<String, ConnectorColumnHandle> handles = new LinkedHashMap<>();
+            ConnectorTableSchema schema = getColumnsFromQuery(

Review Comment:
   [P3] Reuse the query TVF schema when building column handles. TVF binding 
already calls `getColumnsFromQuery` for this SQL, but each call here checks out 
another FE JDBC connection and prepares the full query just to read its 
metadata. `PluginDrivenScanNode` builds handles for the scan and again for scan 
properties, so an ordinary TVF can prepare the same SQL three times before BE 
reads any rows; EXPLAIN pays the same cost. Carry the bound schema or cache 
these handles for the statement.



##########
fe/fe-connector/fe-connector-jdbc/src/main/java/org/apache/doris/connector/jdbc/JdbcScanPlanProvider.java:
##########
@@ -67,7 +74,8 @@ public List<ConnectorScanRange> planScan(ConnectorSession 
session, ConnectorScan
         String querySql;
         if (handle instanceof PassthroughQueryTableHandle) {
             // Query passthrough from TVF — use the raw SQL directly
-            querySql = ((PassthroughQueryTableHandle) handle).getQuery();
+            querySql = new JdbcQueryBuilder(dbType).wrapPassthroughQuery(
+                    ((PassthroughQueryTableHandle) handle).getQuery(), 
columns, noBackslashEscapes.getAsBoolean());

Review Comment:
   [P3] Defer the SQL-mode lookup until a TVF query needs rewriting. For a 
MySQL/OceanBase TVF with no TIMESTAMPTZ column, `wrapPassthroughQuery` returns 
the original SQL, yet this eager supplier call checks out a FE JDBC connection 
and executes `SELECT @@SESSION.sql_mode`. Scan planning and scan-property 
serialization each call it, adding two remote round trips to an unchanged query 
and making EXPLAIN wait on them. Check whether a timestamp projection is needed 
before querying SQL mode, and reuse the result for both calls.



##########
fe/fe-connector/fe-connector-paimon/src/main/java/org/apache/doris/connector/paimon/PaimonScanPlanProvider.java:
##########
@@ -1927,6 +1951,84 @@ private static boolean projectsVariant(
                 .anyMatch(index -> containsVariant(rowType.getTypeAt(index)));
     }
 
+    private static Set<Integer> scanReadFieldIds(RowType rowType, 
List<ConnectorColumnHandle> columns,
+            Optional<ConnectorExpression> filter) {
+        Set<String> names = 
columns.stream().filter(PaimonColumnHandle.class::isInstance)
+                .map(PaimonColumnHandle.class::cast)
+                .filter(column -> !column.isMetadataColumn())
+                .map(column -> column.getName().toLowerCase(Locale.ROOT))
+                .collect(Collectors.toSet());
+        filter.ifPresent(expression -> collectFilterColumnNames(expression, 
names));
+        return rowType.getFields().stream()
+                .filter(field -> 
names.contains(field.name().toLowerCase(Locale.ROOT)))
+                .map(DataField::id).collect(Collectors.toSet());
+    }
+
+    private static void collectFilterColumnNames(ConnectorExpression 
expression, Set<String> names) {
+        if (expression instanceof ConnectorColumnRef) {
+            names.add(((ConnectorColumnRef) 
expression).getColumnName().toLowerCase(Locale.ROOT));
+        }
+        expression.getChildren().forEach(child -> 
collectFilterColumnNames(child, names));
+    }
+
+    static FileStoreTable legacyOrcSplitTable(FileStoreTable table, DataSplit 
split) {
+        FileStoreTable base = 
PaimonTableDecorators.unwrapToFallbackOrBase(table);
+        if (base instanceof FallbackReadFileStoreTable) {
+            FallbackReadFileStoreTable pair = (FallbackReadFileStoreTable) 
base;
+            boolean fallback = ((FallbackReadFileStoreTable.FallbackSplit) 
split).isFallback();
+            // Match the SDK reader's branch selection before reading either 
options or historical schemas.
+            return PaimonReaderOptions.isWrappedFirst(pair) != fallback ? 
pair.wrapped() : pair.other();
+        }
+        return base;
+    }
+
+    static boolean requiresLegacyOrcTimestampReader(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)) {
+            return false;
+        }
+        // Only decoded fields require SDK timezone conversion. Unread LTZ 
columns must not disable
+        // native splitting or metadata columns; stable field IDs also scope 
historical schemas after renames.
+        if (readsTimestampLtz(table.rowType(), readFieldIds)) {

Review Comment:
   [P2] Check each ORC file's schema before forcing the legacy LTZ reader. With 
`orc.timestamp-ltz.legacy.type=true`, a selected nullable LTZ column added 
after an older ORC file makes this current-row-type check return true even 
though that file has no LTZ bytes. The split is sent to JNI unnecessarily; for 
a primary-key file without `deleteRowCount`, `supportsJniPhysicalMetadata` is 
false, so a query also selecting `__paimon_file_path` fails during planning 
instead of using the native reader. Check the historical schema IDs first and 
route to JNI only for files containing a read LTZ field; cover an added-column 
evolution case.



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