github-actions[bot] commented on code in PR #66530:
URL: https://github.com/apache/doris/pull/66530#discussion_r3749204773
##########
fe/fe-connector/fe-connector-hive/src/main/java/org/apache/doris/connector/hive/HiveScanPlanProvider.java:
##########
@@ -238,6 +260,20 @@ public List<ConnectorScanRange> planScanForPartitionBatch(
ConnectorSession session,
ConnectorScanRequest request,
List<String> partitionBatch) {
+ if (session == null) {
+ return doPlanScanForPartitionBatch(session, request,
partitionBatch);
+ }
+ HiveScanReuseKey reuseKey = new
HiveScanReuseKey(session.getCatalogId(), session.getQueryId(),
+ (HiveTableHandle) request.getTableHandle(), partitionBatch);
+ return session.getStatementScope().computeIfAbsent(reuseKey,
Review Comment:
**[P2] Close batch-only statement scopes after the split pump quiesces**
This batch memo is never deterministically released for deferred Arrow
Flight scans. Batch mode calls `startSplit` without calling `getSplits`, but
the query-finish `statementScope::closeAll` callback is registered only in
`getSplits`; Arrow Flight also sets `returnResultFromLocal=false`, so
`StatementContext.close` deliberately skips its fallback. Its finalizer
therefore unregisters the query with no scope callback, leaving these lists
(and other scoped closeables) until GC. Register cleanup for coordinated batch
scans too, and cancel/join the submitted batch futures before closing because
`SplitAssignment.stop()` currently does neither.
##########
fe/fe-connector/fe-connector-iceberg/src/main/java/org/apache/doris/connector/iceberg/IcebergScanPlanProvider.java:
##########
@@ -418,8 +420,39 @@ public boolean supportsFileCache() {
*/
@Override
public List<ConnectorScanRange> planScan(ConnectorSession session,
ConnectorScanRequest request) {
- return planScanInternal(session, request.getTableHandle(),
request.getColumns(),
- request.getFilter(), request.isCountPushdown());
+ IcebergTableHandle icebergHandle = (IcebergTableHandle)
request.getTableHandle();
+ if (session == null) {
+ return planScanInternal(session, request.getTableHandle(),
request.getColumns(),
+ request.getFilter(), request.isCountPushdown());
+ }
+ if (icebergHandle.isSystemTable()) {
+ // System tables read connector metadata through their own
readers; never reuse them.
+ return planScanInternal(session, request.getTableHandle(),
request.getColumns(),
+ request.getFilter(), request.isCountPushdown());
+ }
+ // Statement-scoped reuse: within one statement the identical scan
(same table, same
+ // snapshot/ref/schema pin, same filter, same COUNT pushdown) plans
once and every
+ // duplicated relation shares the result. The scope is NONE for
offline planning and tests,
+ // in which case the loader runs on every call. Session variables are
constant within a
+ // statement and deliberately absent from the key.
+ //
+ // The ranges are memoized in a map HUNG INSIDE the statement scope
rather than cached
+ // directly: planScanInternal re-enters the scope itself (sharedTable
and the v3
+ // rewritableDeleteSupply are scope-backed), and a loader of the
scope's
+ // ConcurrentHashMap must not touch that map (same-bin re-entry throws
+ // IllegalStateException("Recursive update"); a mid-computation resize
silently drops the
+ // outer entry). The scope loader only constructs the memo map;
planning then runs on that
+ // separate map, so every scope call from planScanInternal is
top-level again. The memo
+ // key is catalog-scoped, which also isolates same-named tables across
a cross-catalog
+ // statement.
+ String memoKey = "iceberg.scan-reuse:" + session.getCatalogId() + ":"
+ session.getQueryId();
Review Comment:
**[P2] Reuse the Iceberg equality-delete preflight as well**
For every duplicate eager scan node, `getScanNodeProperties` independently
calls `hasApplicableEqualityDeletes(exactScan)`. When the snapshot summary is
positive or missing, that helper opens the exact filtered `scan.planFiles()`
and may traverse all selected tasks; this happens outside `scanReuse`, before
the later range plan reaches this memo. Thus equality-delete tables still
perform the expensive remote file-plan traversal once per alias even though
their ranges are reused. Please memoize applicability under the same
table/MVCC/filter/rewrite identity (or return it with the shared plan) and
cover two same-statement nodes with a `planFiles()` call-count test.
##########
fe/fe-connector/fe-connector-spi/src/main/java/org/apache/doris/connector/spi/ConnectorScanKeyUtils.java:
##########
@@ -0,0 +1,62 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.connector.spi;
+
+import org.apache.doris.connector.spi.pushdown.ConnectorAnd;
+import org.apache.doris.connector.spi.pushdown.ConnectorExpression;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Helpers for statement-scoped scan-reuse key construction.
+ */
+public final class ConnectorScanKeyUtils {
Review Comment:
**[P1] Reject newly built plugins on older API-5 FEs**
The String bridge repairs old-plugin -> new-FE calls, but the reverse
direction still breaks under the unchanged major. Every newly built connector
invokes `computeIfAbsent(Object, Supplier)`, which a pre-PR API-5 FE does not
provide; Iceberg and Paimon additionally link this new helper. Because plugin
ZIPs exclude `fe-connector-spi` and that package is parent-first, the old FE
admits the plugin and then fails with `NoSuchMethodError` or
`NoClassDefFoundError` on its first reused scan. Please bump the connector API
major and extend the frozen surface so incompatible plugins are rejected at
load time.
--
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]