Skip to content

[improvement](fe) Default external scans to bounded split batches - #69683

Merged
924060929 merged 9 commits into
apache:masterfrom
924060929:codex/kr2-default-split-batch-8
Oct 29, 2026
Merged

924060929 merged 9 commits into
apache:masterfrom
924060929:codex/kr2-default-split-batch-8

Conversation

@924060929

@924060929 924060929 commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: None

Problem Summary: External scans currently enter Batch Mode only above 1024 partitions or files. Even in Batch Mode, a producer batch defaults to 128 splits and each backend queue is bounded by 32 batches. That couples the memory bound to batch size and delays small LIMIT scans while large groups are prepared.

This PR enables Batch Mode from one partition or file by default. It separates the Hive partition-processing batch size (split_partition_batch_size, default 16) from the Batch Mode trigger. Producers still assign and offer splits in batches, but each backend queue stores individual splits and enforces a capacity of 1024 splits; a partly full queue accepts only the available slots and wakes the producer when the consumer drains it. The producer batch defaults to 8 splits. The consumer still obeys the BE request batch size, while preserving cancellation, first-fetch limits, backpressure, and error propagation. The new connector SPI method advances the plugin API version to 25 and updates its recorded surface.

A slow Hive partition can outlast the one-second split-fetch RPC wait after another partition supplies the first split. FE now returns INCOMPLETE while production is still running, and BE retries after checking cancellation. A completed assignment still returns EOF, and producer failures remain errors. If a local LIMIT stops a scanner while other query branches remain active, its BE retry loop observes that scanner stop and exits without waiting for more splits.

In a matched, one-BE Release benchmark on the integrated test branch, refreshed-metadata LIMIT medians at split_batch_size=8 versus 32 were 75.8 vs 102.5 ms for Hive 10k partitions and 23.5 vs 30.6 ms for Iceberg 1000 manifests. Eight beat 32 in 11/12 paired blocks in each LIMIT scenario. Warm full scans had no stable winner among 8/16/32/64. These numbers select the producer batch size; they are not a fresh end-to-end benchmark of this rebased PR against current master.

Release note

External table Batch Mode now starts at one partition or file by default. The default producer batch size is 8 splits, queue capacity is 1024 splits per backend, and split_partition_batch_size controls Hive partition-processing batches separately.

Check List (For Author)

  • Test: Unit Test. Before rebasing onto current master, FE build and 10 focused FE test classes passed (162 tests). On the current PR head, SplitSourceTest passed 37/37 through run-fe-ut.sh. The Maven reactor and Checkstyle passed through build.sh --fe; its outer output-packaging step returned nonzero. The changed BE sources passed clang-format 16, header-hygiene validation and git diff --check. build.sh --be was attempted but stopped during CMake compiler-link detection because this Mac has not accepted the Xcode license, so the new BE test has not run locally. CI build is requested below.
  • Behavior changed: Yes, Batch Mode trigger and split-buffering defaults change as described above.
  • Does this need documentation: No separate doc PR; the connector scheduling document is updated here.

### What problem does this PR solve?

Issue Number: None

Problem Summary: External scans previously entered batch mode only above 1024 partitions or files. When enabled, each producer batch held 128 splits and each backend queue was bounded by 32 batches, so small LIMIT queries could wait for unnecessary work while the queue capacity depended on batch size. Enable batch mode from one partition or file, separate the Hive partition-processing size from that trigger, and store individual splits in a queue bounded by 1024 splits per backend. Producers still offer splits in batches; use eight splits per batch by default. In a matched one-BE Release benchmark on the integrated test branch, refreshed-metadata LIMIT medians at batch sizes 8 versus 32 were 75.8 versus 102.5 ms for Hive and 23.5 versus 30.6 ms for Iceberg. Warm full scans showed no stable winner across those sizes. Preserve request batch limits, cancellation, backpressure, and producer wakeups. The new connector SPI method advances the plugin API major version to 25.

### Release note

External table Batch Mode now starts at one partition or file by default. The default producer batch size is eight splits, queue capacity is 1024 splits per backend, and split_partition_batch_size controls Hive partition-processing batches separately.

### Check List (For Author)

- Test: Unit Test. Before rebasing onto current master, FE build and ten focused FE test classes passed (162 tests). On current master, ConnectorPluginSurfaceTest (2), ConnectorMetadataSurfaceTest (4), and HiveScanBatchModeTest (36) passed. FE-core Maven tests could not start locally because snapshot reactor artifacts were unresolved without -am; the full -am route requires an x86 grpc generator unavailable on this ARM host. One-BE Release benchmark results above were recorded on the integrated test branch.
- Behavior changed: Yes (Batch Mode thresholds and split buffering defaults change as described above)
- Does this need documentation: No (connector scheduling document updated in this commit)
@hello-stephen

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

@924060929

Copy link
Copy Markdown
Contributor Author

run buildall

@924060929

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Static review of PR #69683 at 5a8470c found one P2 regression: an awaited one-split fetch can return OK despite a producer failure already being published. The inline comment contains the triggering sequence and fix direction. There are no existing inline findings to carry forward and no additional user-provided focus points.

Critical checkpoint conclusions:

  1. Goal and evidence: defaults and split-level buffering implement the intended bounded batching; inspected tests cover partial offers, sizing and sync/streaming parity. Error preservation has the inline exception below.
  2. Scope and reuse: changes stay within scan scheduling, Hive request sizing, session settings, SPI versioning, documentation and their tests; existing producer adapters and scheduler are reused.
  3. Concurrency: split workers, FE fetch RPC threads and query cleanup share queue state under per-backend monitors; offsets retain partial offers. Callbacks run after releasing queue/listener locks, with registration/retry preventing capacity wakeup loss. No additional deadlock found; the awaited-fetch terminal check is the reported gap.
  4. Lifecycle: producers retain bounded pending batches, query cleanup signals waiters and closes sources cooperatively, and completion removes registrations. No new static initialization dependency found.
  5. Configuration: split_partition_batch_size is positive-validated, session/global configurable through existing variable machinery, forwarded between FEs and exposed to connectors without restart. Existing batch/queue settings now bound split counts as documented.
  6. Compatibility: the added SPI method is recorded and the connector API major advances to 25.0. Major-version gating remains in place; stored data formats and FE/BE RPC fields are unchanged.
  7. Thrift/protobuf: no generated definitions change; cross-branch field-ID comparison is inapplicable.
  8. Parallel paths: checked partition batching, file streaming and legacy addToQueue, Hive/MaxCompute partition scoping and Iceberg streaming exclusions; other connectors retain their opt-in gates.
  9. Conditions: sampling, empty partitions, missing slots, deferred Variant compatibility, Iceberg metadata COUNT and v3 exclusions retain their guards. Queue positivity and offset preconditions have concrete invariants.
  10. Tests: inspected unit coverage for partial acceptance, unique ranges, backpressure, wakeup registration, completion/failure/cancellation, first-fetch bounds, partition concurrency and invalid settings, plus regression sync/streaming comparisons. The awaited one-split/error interleaving needs coverage.
  11. Expected results: no expected-result files change; the regression edit adds setting save/restore and partition size only. No new result content needs validation.
  12. Observability: existing source/query IDs and failure logging remain; the generation profile now reports the effective clamped batch size. No additional instrumentation gap established.
  13. Transactions/persistence: no EditLog, replay, failover or transaction state changes; those checkpoints are inapplicable.
  14. Data writes/atomicity: no data-write behavior changes. Scan failure propagation is covered by the inline finding; no separate crash-related ownership issue established.
  15. FE/BE variable passing: the new setting controls FE planning only; existing session forwarding and split-source transport are sufficient.
  16. Performance and further review: queue storage is bounded per split, producer batches are capped by queue capacity, drains amortize locking, and Hive keeps bounded listing lanes. No additional concrete performance or correctness defect was established by the final source review.

All 22 changed paths and related producer, consumer, connector and cleanup paths were reviewed. Validation was static only: no builds, tests, benchmarks or runtime reproductions were run, and the PR's reported performance numbers were not independently verified. No unresolved source-review candidates or uncovered assigned scope remain.

Review converged after 2 round(s).

if (split != null) {
splitAssignment.notifyQueueSpace(backend);
pendingSplits = batch.iterator();
scanRanges.add(split);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Recheck terminal state after an awaited split

With split_initial_batch_size=1 (or a BE request size of 1), an empty-queue fetch waits in awaitSplit. A producer can enqueue a range and then publish a listing failure before the waiting RPC thread resumes. awaitSplit still polls that range, and adding it here fills the request, so the loop exits without another getAssignedSplits/isStop check. fetchSplitBatch consequently returns OK for an already-failed assignment. A LIMIT can consume that range and stop without another fetch; cleanup only logs the stop exception. Previously, the awaited batch remained pending until the loop rechecked terminal state. Apply the same error/cancellation recheck used by the bulk-drain branch after awaiting/notifying, and cover a one-split wait racing with producer failure.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 1145d3d. After an awaited split wakes and notifies queue-space listeners, the fetch now rechecks the assignment error and stop state before adding that split to the response. A deterministic one-split race test reproduced the old incorrect OK result for both producer failure and cancellation; both now pass. The complete SplitSourceTest class (33 tests) also passes via the existing Surefire classpath.

### What problem does this PR solve?

Issue Number: None

Problem Summary: A one-split BE fetch can wait for a range, then receive that range after its producer has already published a failure or cancellation. The new per-split queue path appended the awaited range and returned as soon as the request filled, without rechecking terminal state. Recheck after notifying queue space so an already-failed assignment returns its error and a stopped assignment discards the range. A deterministic two-case test reproduced the previous incorrect return and passes with the fix.

### Release note

None

### Check List (For Author)

- Test: Unit Test. The new race test failed in both cases before the fix, then passed in both cases afterward. All 33 SplitSourceTest cases passed using the prior Surefire classpath and JUnit launcher. The local FE-core Maven route is blocked by unresolved snapshot reactor artifacts; the full reactor needs an x86 gRPC generator unavailable on this ARM host.
- Behavior changed: Yes (an already-failed or cancelled one-split fetch no longer returns OK with a range)
- Does this need documentation: No
@924060929

Copy link
Copy Markdown
Contributor Author

run buildall

@924060929

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed all 22 changed files at head 1145d3da7bef2159379d59713f25be67ba8dc38b. No new actionable findings. Review converged in 1 round: both complete-review agents and the additional partial-offer/terminal-race reviewer returned NO_NEW_VALUABLE_FINDINGS; all candidates and initial risks received evidence-backed dispositions.

The existing P2 awaited-split thread is fixed on this head. After an awaited split, SplitSource now rechecks the assignment exception and stop state before adding the range, including a one-split request. The added deterministic test covers failure and cancellation at that boundary. No duplicate comment is posted, and no existing P0/P1 blocker remains.

Critical checkpoint conclusions:

  • Goal and proof: the implementation separates Hive partition work size from batch eligibility, bounds queues by individual splits, and retains partial offers. Unit tests target those mechanisms; their source supports the intended behavior, but they were not executed during this review.
  • Scope and reuse: changes are focused on scan scheduling, configuration, SPI compatibility, tests and documentation; they reuse the existing producer, scheduler and cleanup framework.
  • Concurrency and locking: traced FE dispatch -> split producers -> backend assignment/conversion -> per-BE queue -> split-fetch RPC -> BE scanners. Queue contents and waiter counts share a per-BE monitor; backend policy and producer scheduling retain their separate locks. Listener registration retries close the capacity-release race, callbacks run outside queue/listener monitors, and external listing/conversion stays outside queue locks. No introduced deadlock or lost wakeup was substantiated.
  • Lifecycle and failure: retained offsets survive suspension without reconversion or replay. Finalization waits for dispatched producers, publishes failures before completion, and closes scoped sources. Stop wakes consumers before resource closure and unregisters sources. RPC errors remain non-OK statuses; finished queues drain before EOF. No introduced lifecycle leak or suppressed failure was found. No static-initialization change applies.
  • Configuration: split_partition_batch_size has a positive-value checker, default 16, generic session export and forwarding. Settings are captured for each statement without restart. Effective producer batches use min(split_batch_size, split_queue_capacity); defaults and documentation agree on 8 and 1024 splits.
  • Compatibility: the new default SPI method, recorded plugin surface and API version assertion agree with connector API major 25. The existing version gate rejects mismatched plugins. No storage-format or wire-format change was introduced.
  • Thrift/protobuf IDs: no gensrc/thrift or gensrc/proto changes; cross-branch field-ID checks do not apply.
  • Parallel paths: checked cooperative and blocking producers, partition-batch Hive/MaxCompute, whole-scan Hive/Iceberg, and synchronous opt-outs. Required partition subsets remain scoped; TABLESAMPLE and deferred Variant checks retain their synchronous guards; servable Iceberg metadata counts remain synchronous. BE batch scanner concurrency is not capped by the small partition-count estimate.
  • Conditional boundaries: positive batch eligibility excludes empty partition selections, and Hive's batch cap preserves independent listing lanes. Partial/full queues, first/subsequent fetches, empty batches, completion, failure and cancellation were checked without finding a distinct introduced defect.
  • Test coverage: inspected partial-offer exact-once assertions, capacity-registration and terminal races, multi-BE streaming, first-fetch limits, empty/partial partition batches, session validation, SPI baselines and regression queries for pruning, LIMIT, joins, UNION and CTAS. The added tests exercise the changed behavior and negative boundaries.
  • Test results: no .out file changes. New expected counts, range sets and metadata batch sizes agree with the fixtures; runtime results and prior result-file generation were not verified.
  • Observability: existing generated-split counters, queue-capacity information and BE fetch timing remain; the generation profile now reports the effective producer batch size. No additional observability defect was identified.
  • Transaction and persistence: no edit-log, transaction or persisted-state change. The modified read path retains pinned snapshot/rewrite handles; transaction visibility, partition versions and MoW delete bitmaps are not modified.
  • Writes, atomicity and crashes: no new data-write protocol. Review of cancellation and cleanup found no newly introduced resource-retention or deadlock path; crash recovery behavior is unchanged by this diff.
  • FE-BE variables: the new partition-work setting is FE-only and needs no new wire field; existing split-source RPC semantics remain intact.
  • Performance and memory: per-BE queues are bounded by split count, producer lanes and retained batches are bounded, and drains amortize locking over at most 64 descriptions. No concrete new performance bug was substantiated. Latency, throughput and fairness were not measured.
  • Additional concerns: the final sweep rechecked every supplied changed path, candidate disposition and initial risk. No unresolved code-specific question or uncovered static-review scope remains.

No additional user focus was supplied. Validation was static inspection only: no builds, tests, benchmarks or runtime checks were run, and no repository source was modified. Convergence describes review coverage and candidate closure; it does not establish runtime performance or test success.

Review converged after 1 round(s).

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 28905 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 1145d3da7bef2159379d59713f25be67ba8dc38b, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17607	5227	5089	5089
q2	2162	302	251	251
q3	10255	1391	827	827
q4	4682	465	355	355
q5	7445	803	543	543
q6	181	181	150	150
q7	741	810	598	598
q8	9253	1377	1092	1092
q9	5535	4203	4197	4197
q10	6833	1298	1034	1034
q11	435	251	232	232
q12	646	405	280	280
q13	18091	3594	3064	3064
q14	274	276	250	250
q15	q16	747	716	690	690
q17	1213	763	590	590
q18	7082	6204	6113	6113
q19	1099	953	602	602
q20	390	336	225	225
q21	5422	2469	2461	2461
q22	390	325	262	262
Total cold run time: 100483 ms
Total hot run time: 28905 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	6008	5933	6154	5933
q2	762	618	553	553
q3	5663	5730	5317	5317
q4	1999	2161	1557	1557
q5	5799	5859	5654	5654
q6	244	190	147	147
q7	2268	2000	1788	1788
q8	2977	2626	2745	2626
q9	7963	7552	7538	7538
q10	3604	3606	3119	3119
q11	589	406	378	378
q12	682	649	500	500
q13	3272	3571	3054	3054
q14	283	281	262	262
q15	q16	648	680	635	635
q17	7712	7091	6850	6850
q18	12995	12242	12936	12242
q19	909	801	791	791
q20	2143	2137	1909	1909
q21	5609	4546	4682	4546
q22	505	456	396	396
Total cold run time: 72634 ms
Total hot run time: 65795 ms

…ests

### What problem does this PR solve?

Issue Number: None

Problem Summary: External scans now use batch mode by default. Batch EXPLAIN intentionally omits per-backend delete-file counts because only an initial subset of splits is planned. The Iceberg position-delete regression expected deleteFileNum from the default EXPLAIN and failed despite all result checks passing. Verify the approximate batch EXPLAIN separately, and request synchronous planning only in tests that assert complete delete-file detail.

### Release note

None

### Check List (For Author)

- Test: Manual test. Inspected the failed External Regression stacktrace and the FileScanNode/PluginDrivenScanNode EXPLAIN gate; git diff --check passed. External regression rerun is pending CI.
- Behavior changed: No (test expectations only)
- Does this need documentation: No
@924060929

Copy link
Copy Markdown
Contributor Author

run buildall

@924060929

Copy link
Copy Markdown
Contributor Author

/review

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 96.47% (82/85) 🎉
Increment coverage report
Complete coverage report

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed PR #69683 at head 0a415e5. No new actionable findings were verified across all 25 changed files and 76 diff hunks.

The existing P2 awaited-split terminal-state finding is fixed at this head: both awaited and bulk-drained splits recheck assignment failure/cancellation after capacity callbacks. The new parameterized test covers the one-split failure and cancellation cases. This issue is not reposted. No existing P0/P1 blocker remains to carry forward. No additional user focus was supplied.

Critical checkpoint conclusions:

  • Goal and evidence: the implementation separates the batch-mode trigger from Hive metadata batch size, bounds each BE queue by individual split count, and uses smaller producer batches. Unit and regression assertions cover the intended behavior; this review did not execute them.
  • Scope and reuse: changes are focused on split scheduling, settings, the SPI extension, documentation and related tests. Blocking and resumable producers share the same queue implementation.
  • Concurrency and locking: planner, SPLIT workers, FE fetch RPC threads and query cleanup were traced through the BE consumer. Queue state uses its per-BE monitor, assignment policy uses a separate lock, and producer scheduling flags use scheduleLock. Capacity callbacks run after queue/listener locks are released. No new lock inversion or external I/O inside those queue locks was found.
  • Lifecycle: residual offsets retain each converted split once; completion removes listeners and closes each source serially. Stop publishes terminal state and signals waiters before resource cleanup. The shared finalizer waits for dispatch and all admitted lanes. No new static initialization dependency or ownership cycle was found.
  • Configuration: split_partition_batch_size defaults to 16, rejects nonpositive values, is forwarded and exported to connector sessions generically, and is captured per query without restart. Effective producer size is clamped to queue capacity. The changed trigger, batch-size and queue-unit defaults are intentional and documented in the PR release note.
  • Compatibility: connector API major 25.0, its pinned test and recorded plugin surface agree; the loader rejects mismatched plugin majors. ConnectorMetadata is unchanged. FE-BE fetch request/status/EOF semantics and storage formats are unchanged.
  • Thrift/protobuf: no definitions or field IDs change; cross-branch field-ID comparison is not applicable.
  • Parallel paths: both blocking and resumable enqueue paths and both bulk and awaited fetch paths were checked. Hive/MaxCompute partition batching and Hive/Iceberg streaming were traced; Paimon/Hudi and other non-opted-in connectors remain synchronous.
  • Conditional guards: explicit batch-mode disable, empty/no-slot scans, sampling, deferred Variant checks, exact partition-metadata rules and Iceberg metadata-count/v3/system-table exclusions were checked. Hive partition claims remain disjoint and use positive operational batch/worker inputs.
  • Test coverage: source inspection covers partial enqueue/resume, exact split identities, queue bounds, terminal races, cancellation, EOF, independent backend channels, Hive metadata batches and concurrent listing. Existing Hive regression cases exercise empty/pruned scans, aggregation, LIMIT, joins, unions, CTAS and statement hints. Runtime coverage remains unverified.
  • Test results: no golden output is modified. Iceberg EXPLAIN checks distinguish approximate asynchronous split estimates from synchronous delete-file details. The Paimon synchronous hint is harmless. No new incorrect expected result was identified statically.
  • Observability: generation profiles report the effective producer batch size and queue capacity; existing HMS batch metrics, split-source RPC error context and cleanup logs remain available. No additional observability defect was identified.
  • Persistence and failover: no new persisted state or EditLog/transaction protocol changes are introduced; scheduling state is query-scoped.
  • Data writes and atomicity: production changes affect scan planning and buffering, not commit/write atomicity. Cancellation and completion retain the existing cleanup boundaries.
  • FE-BE variables: the new setting is consumed in FE planning and needs no new BE payload field; existing BE batch request limits and minimum split hints are preserved.
  • Performance and memory: per-split queues eliminate the batch-size multiplier in the queue bound; each producer retains at most one assigned batch. Bulk draining amortizes synchronization, Hive metadata requests stay bounded, and remote BE scanner concurrency is not capped by a small approximate partition count. Benchmark claims were not independently validated.
  • Core correctness and other issues: snapshot/rewrite pinning precedes asynchronous source creation, errors reach non-OK RPC status, and no new visibility, deletion or split-loss/duplication defect was verified. No internal visible-version/delete-bitmap logic or BE allocation accounting changes are involved.

Review converged in 1 round: all three assigned reviewers returned NO_NEW_VALUABLE_FINDINGS; every candidate and risk focus has an evidence-backed disposition, and the final coverage sweep found no remaining code-level gap. Validation was static only: no builds, tests, benchmarks or runtime stress checks were run, and repository source was not modified.

Review converged after 1 round(s).

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 28683 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 0a415e5aed528215074ef8a442493a5a2c5deaf6, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17611	5199	5064	5064
q2	2115	345	240	240
q3	10218	1385	825	825
q4	4672	458	332	332
q5	7438	800	525	525
q6	178	186	155	155
q7	743	792	598	598
q8	9280	1342	1035	1035
q9	5578	4198	4191	4191
q10	6817	1289	1015	1015
q11	444	252	227	227
q12	641	397	276	276
q13	18079	3539	3048	3048
q14	274	269	247	247
q15	q16	722	722	669	669
q17	1203	743	568	568
q18	6966	6179	6123	6123
q19	1109	960	595	595
q20	389	337	234	234
q21	4733	2442	2494	2442
q22	372	340	274	274
Total cold run time: 99582 ms
Total hot run time: 28683 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	5987	5897	5902	5897
q2	729	609	575	575
q3	5618	5745	5260	5260
q4	2296	2161	1564	1564
q5	5697	5733	5611	5611
q6	244	186	141	141
q7	2276	2010	1814	1814
q8	3017	2488	2504	2488
q9	7490	7434	7455	7434
q10	3642	3588	3166	3166
q11	598	431	393	393
q12	682	669	512	512
q13	3329	3635	3065	3065
q14	277	285	267	267
q15	q16	647	685	612	612
q17	7768	7083	6931	6931
q18	13112	12220	12879	12220
q19	921	786	794	786
q20	2128	2172	1917	1917
q21	5602	4737	4681	4681
q22	487	463	431	431
Total cold run time: 72547 ms
Total hot run time: 65765 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 152184 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 0a415e5aed528215074ef8a442493a5a2c5deaf6, data reload: false

query5	4319	576	448	448
query6	431	223	191	191
query7	4800	442	231	231
query8	315	164	151	151
query9	8773	3252	3269	3252
query10	474	334	257	257
query11	6027	3868	3606	3606
query12	145	92	88	88
query13	1250	454	343	343
query14	6118	3964	3668	3668
query14_1	3405	3436	3420	3420
query15	205	197	184	184
query16	949	432	397	397
query17	851	698	551	551
query18	2436	407	295	295
query19	194	165	130	130
query20	85	82	80	80
query21	203	126	103	103
query22	12850	13017	12887	12887
query23	13362	12804	12419	12419
query23_1	12445	12547	12545	12545
query24	7372	814	465	465
query24_1	486	497	478	478
query25	519	392	337	337
query26	1255	256	133	133
query27	2771	437	274	274
query28	4640	2078	2055	2055
query29	1539	572	426	426
query30	291	219	183	183
query31	1008	938	814	814
query32	141	91	85	85
query33	521	290	242	242
query34	921	867	516	516
query35	723	750	637	637
query36	807	855	722	722
query37	128	98	84	84
query38	1797	1778	1722	1722
query39	787	799	755	755
query39_1	742	747	746	746
query40	223	123	96	96
query41	66	69	62	62
query42	89	88	81	81
query43	352	366	319	319
query44	1367	718	743	718
query45	182	176	171	171
query46	857	984	588	588
query47	2949	3021	2940	2940
query48	303	314	232	232
query49	570	404	307	307
query50	677	289	227	227
query51	10566	10337	10519	10337
query52	81	89	81	81
query53	192	208	154	154
query54	243	208	193	193
query55	81	76	70	70
query56	270	219	217	217
query57	1656	1614	1558	1558
query58	294	277	262	262
query59	2135	2171	1951	1951
query60	287	257	239	239
query61	177	173	173	173
query62	398	332	295	295
query63	195	157	163	157
query64	2884	1044	884	884
query65	3343	3340	3281	3281
query66	1774	415	302	302
query67	20384	20162	20217	20162
query68	2984	1018	621	621
query69	402	300	246	246
query70	825	771	757	757
query71	293	225	217	217
query72	2679	2559	2301	2301
query73	530	531	295	295
query74	4657	4509	4377	4377
query75	2310	2293	1902	1902
query76	2315	1025	598	598
query77	349	366	269	269
query78	9859	9782	9237	9237
query79	988	900	541	541
query80	829	408	327	327
query81	578	315	272	272
query82	581	143	104	104
query83	298	199	190	190
query84	301	128	98	98
query85	958	419	377	377
query86	348	238	231	231
query87	1999	1967	1814	1814
query88	3841	2855	2849	2849
query89	333	288	241	241
query90	1733	168	166	166
query91	160	151	132	132
query92	94	92	91	91
query93	997	1005	584	584
query94	507	289	249	249
query95	566	327	373	327
query96	690	488	247	247
query97	2421	2434	2339	2339
query98	165	163	150	150
query99	768	762	642	642
Total cold run time: 234970 ms
Total hot run time: 152184 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 24.3 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 0a415e5aed528215074ef8a442493a5a2c5deaf6, data reload: false

query1	0.01	0.01	0.00
query2	0.10	0.05	0.05
query3	0.26	0.07	0.09
query4	1.61	0.10	0.10
query5	0.23	0.24	0.23
query6	1.16	0.68	0.67
query7	0.04	0.01	0.01
query8	0.06	0.04	0.05
query9	0.41	0.34	0.36
query10	0.58	0.59	0.61
query11	0.20	0.15	0.14
query12	0.19	0.15	0.15
query13	0.48	0.50	0.48
query14	1.02	1.01	1.02
query15	0.62	0.59	0.61
query16	0.35	0.34	0.35
query17	1.13	1.13	1.14
query18	0.20	0.20	0.19
query19	2.08	1.97	1.92
query20	0.02	0.02	0.01
query21	15.48	0.20	0.13
query22	4.89	0.06	0.06
query23	16.26	0.33	0.12
query24	2.72	0.47	0.43
query25	0.10	0.08	0.04
query26	1.22	0.21	0.16
query27	0.05	0.04	0.05
query28	3.36	0.78	0.37
query29	12.53	4.14	3.26
query30	0.28	0.13	0.10
query31	2.78	0.55	0.32
query32	3.23	0.60	0.50
query33	3.31	3.14	3.21
query34	15.49	4.01	3.43
query35	3.34	3.37	3.34
query36	0.55	0.44	0.42
query37	0.09	0.07	0.07
query38	0.05	0.05	0.04
query39	0.03	0.03	0.03
query40	0.17	0.15	0.15
query41	0.09	0.04	0.03
query42	0.04	0.03	0.03
query43	0.04	0.04	0.03
Total cold run time: 96.85 s
Total hot run time: 24.3 s

@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 55.29% (47/85) 🎉
Increment coverage report
Complete coverage report

### What problem does this PR solve?

Issue Number: None

Problem Summary: With partition.cache.ttl-second=0, Hive partition-name reads bypass cache, but the derived partition view still used its default 24-hour cache. Batch split planning slices that stale view, so an externally added partition was omitted from a full scan. The external regression returned only the old partition after a new partition was inserted. Let the derived view inherit the effective partition-name TTL when no view TTL is specified. Tests cover both the legacy and namespaced zero-TTL settings.

### Release note

Hive partition views now respect the partition-name cache TTL when a separate partition-view TTL is not set.

### Check List (For Author)

- Test: Unit Test. HiveConnectorPartitionViewCacheTest: 5 tests passed with JDK 17 using existing worktree classes and a JUnit launcher; the repository run-fe-ut.sh exited in env.sh before Maven, and direct module Maven was blocked by unresolved snapshot reactor artifacts. External regression rerun pending CI.
- Behavior changed: Yes (disabled Hive partition-name caching also disables derived view caching unless explicitly configured otherwise)
- Does this need documentation: No
@924060929

Copy link
Copy Markdown
Contributor Author

run buildall

@924060929

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One P2 availability regression remains: early dispatch of small Hive partition scans can turn a slow, still-running partition listing into a fatal split-fetch timeout. The inline finding traces a two-partition case end to end.

Static review covered all 27 changed paths and the relevant planner, connector, producer, RPC and BE consumers. No builds, tests or benchmarks were run.

Applicable critical checkpoints:

  • Goal: split-count queue bounds, smaller producer batches and independent Hive partition batches are implemented; the default-on path still has the timeout interaction reported inline.
  • Scope and reuse: changes are focused on scan scheduling, its cache prerequisite, SPI/config wiring and tests; the shared producer and cache helpers are reused.
  • Concurrency: producer tasks serialize residual offsets; queue contents/waiters use a per-backend monitor, policy assignment uses its own lock, and listener registration retries capacity. IO and resume callbacks stay outside queue locks; no new lock cycle was established.
  • Lifecycle: traced initialization, first-sample dispatch, producer completion, EOF, error and cancellation through FE RPC and BE consumption. Early dispatch versus the fetch deadline is the remaining defect; cleanup removes listeners and closes sources.
  • Configuration: positive-size checking, generic session extraction, statement forwarding and effective batch-size clamping are wired. New planning sessions observe overrides without restart.
  • Compatibility: connector API major 25 and the plugin surface baseline agree; the metadata-method surface is unchanged. FE/BE fetch messages and stored formats are unchanged.
  • Thrift/protobuf: no definition changes, so field-ID compatibility checks are not applicable.
  • Parallel paths: checked yielding and blocking producers, partition and whole-scan sources, Hive/MaxCompute partition batching, Iceberg streaming gates, and non-opted-in connectors. Sampling and deferred Variant checks retain synchronous planning.
  • Conditions: terminal checks, absent-key TTL precedence, positive size bounds and count/system-table gates have concrete purposes. Explicit partition-view TTL wins and refreshed partition records reach the engine conversion cache.
  • Test coverage: inspected partial offers, multi-backend identity, queue bounds, callback races, awaited failure/stop, EOF, Hive lane concurrency, TTL bypass, config validation and regression cases. A slow partition with consumption beginning before listing completion is missing.
  • Test results: changed assertions and EXPLAIN expectations match split-count queues and asynchronous profiles. No golden result files changed; inspected tests are not claimed as executed.
  • Observability: existing split counters, partition profiles and FE RPC errors remain available. Benchmark claims were not independently validated.
  • Persistence/failover: no EditLog, stored metadata format or transaction protocol changes.
  • Data writes/crashes: production write atomicity, MoW/delete bitmap and visible-version logic are untouched; scan stop/failure paths were checked for retained producer work.
  • FE/BE variables: the new partition-size knob is FE planning state and is forwarded between FEs; no new BE wire field is required.
  • Performance/memory: queues are bounded by split count, producers retain one residual assigned batch, and bulk drain limits each lock hold to 64 entries. No separate substantiated performance defect was found.
  • Other issues and user focus: no additional user focus was supplied. Existing thread 4387198347 is fixed by the awaited-split terminal recheck and its parameterized failure/cancellation test; it is not reposted. No existing P0/P1 blocker remains to carry forward.

Static-only limits: runtime timing and performance were not validated.

Review converged after 2 round(s).

+ "mode.",
needForward = true)
public int numPartitionsInBatchMode = 1024;
public int numPartitionsInBatchMode = 1;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Reconcile early dispatch with the one-second split-fetch deadline

With the new defaults, two selected Hive partitions become two one-partition producers. If producer A returns its sole range while producer B is still doing HMS/directory IO, SplitAssignment.init() releases the planner on A's sample. FileQueryScanNode creates a SplitSource for every BE, so a BE without a range waits only the default fetch_splits_max_wait_time_ms=1000; while B is still listing, SplitSource.getNextBatch() throws and the BE treats the resulting RPC error as query failure. Even one BE can hit this after consuming A. Previously this tiny scan either planned synchronously or used one streaming producer whose default batch of 128 collected both ranges before publishing the sample. Please reconcile the normal fetch wait with unfinished listing before enabling these defaults, and cover two partitions with one listing blocked beyond the fetch deadline after the other publishes its range.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 47241e4. When the per-RPC wait expires while split production is still running, FE now returns INCOMPLETE instead of a fatal timeout or an empty EOF batch. BE retries after checking query cancellation and releases the FE client between attempts. Completion still returns EOF, and producer failures remain errors. SplitSourceTest now covers a second partition that produces after the wait window, a backend with no initial assignment, EOF, and failure after a pending fetch (37/37 passed). The FE Maven reactor and Checkstyle passed; the BE build is left to buildall CI.

### What problem does this PR solve?

Issue Number: N/A

Related PR: apache#69683

Problem Summary: With the new batch-mode defaults, a Hive scan can dispatch after its first partition produces a split. If another partition is still listing files, a BE may exhaust its assigned ranges and reach the one-second split-fetch wait limit. FE previously returned a fatal timeout even though split production was still running. FE now returns a retryable INCOMPLETE status only for this temporary gap; BE retries after checking query cancellation and releases its FE RPC client between attempts. Completed scans still return EOF, while producer errors and cancellation retain their failure paths. The wait setting remains a per-RPC bound and now rejects nonpositive values to avoid a tight retry loop.

### Release note

External batch scans no longer fail solely because another partition takes longer than one split-fetch wait interval to list files.

### Check List (For Author)

- Test: Unit Test: SplitSourceTest 37/37 passed with the repository test script. FE Maven build and Checkstyle passed through build.sh --fe; the outer script returned nonzero during output packaging. BE clang-format 16 check and git diff --check passed. BE compilation was not run locally.
- Behavior changed: Yes. A temporary split gap produces a retryable response instead of a fatal timeout.
- Does this need documentation: No. The session variable description was updated in code.
@924060929

Copy link
Copy Markdown
Contributor Author

run buildall

@924060929

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Static review of all 29 changed files at 47241e4 found two new P2 regressions: an ungated pending response breaks old BE callers during rolling upgrades, and the BE retry loop ignores local scanner termination. Both findings are inline. No existing P0/P1 finding remains to carry forward.

Existing review context: thread 4387198347 is fixed by the awaited-split error/stop recheck. Thread 4396124903 is fixed for matching upgraded FE/BE versions by the pending-response/retry path; the distinct old-caller compatibility gap is reported inline. No additional user focus was supplied.

Critical checkpoint conclusions:

  1. Goal and proof: individual-split queue bounds, independent Hive partition batches and earlier asynchronous dispatch are implemented. Inspected tests target these controls and late production; mixed-version and local-stop cases are missing.
  2. Scope and clarity: production changes and adjacent partition-view TTL repair are focused on external scan scheduling.
  3. Concurrency and locking: FE producers, RPC consumers and cleanup share explicit queue/readiness/listener/resource synchronization; offsets preserve exact-once partial offers and callbacks run outside queue locks. No new lock inversion found. The prolonged BE mutex/worker hold after local stop is the second finding.
  4. Lifecycle: producer EOF/error/cancellation and query-finish source cleanup are wired; local scan termination does not reach the retry loop. No static initialization change.
  5. Configuration: new partition size and fetch interval have positive checkers; session capture/forwarding is reflective, so SET/SET_VAR reaches planning without restart. Queue capacity now counts splits; the effective producer batch respects that capacity.
  6. Compatibility: connector API and recorded plugin surface consistently advance to 25.0. The existing fetch RPC lacks pending-response capability negotiation, causing the first finding. No storage-format or function-symbol change.
  7. Thrift/protobuf IDs: no definitions changed.
  8. Parallel paths: resumable and blocking producers, bulk and awaited drains, Hive and MaxCompute partition batching, Hive/Iceberg streaming, synchronous fallback, and both BE file scanners were traced.
  9. Special conditions: offset preconditions, pending-versus-EOF, terminal checks, TTL precedence, sampling/Variant/count/snapshot fences have concrete purposes and preserve their intended paths.
  10. Test coverage: inspected queue, producer, concurrency, scan-node, connector, SPI and session tests plus changed regression suites. FE pending tests do not exercise the BE retry or an older caller. No tests or builds were run under this static-only contract.
  11. Expected results: no generated result files changed; modified EXPLAIN checks correctly request synchronous planning for full delete-file counts and approximate split reporting for streaming.
  12. Observability: effective batch size, queue capacity and GetSplitTime remain visible; existing errors preserve diagnostics except the old caller's unknown-error response described inline.
  13. Transactions and persistence: no EditLog, replay, commit or visible-version logic changed; existing snapshot/read fences remain.
  14. Data writes and crashes: production changes concern transient read-side scheduling; no persistent write atomicity change or additional data-loss path found.
  15. FE/BE passing: the new partition setting is FE-only and reaches connectors; source IDs and request limits remain unchanged. Pending-response support is not negotiated.
  16. Performance and memory: queues remain bounded per backend, lanes retain bounded in-flight batches, and bulk operations amortize locks. Clients return to cache between RPC attempts. Stopped scanners can nevertheless retain workers and fragment state as reported.
  17. Additional sweep: all changed paths, existing threads, candidates and three initial risk areas were rechecked; no other verified issue or unresolved source-level question remains.

The review converged after two rounds: all three reviewers returned NO_NEW_VALUABLE_FINDINGS in the final round, coverage is complete, and all candidates and risk items have evidence-backed dispositions. Validation is limited to source and test inspection; runtime, build, benchmark and test execution were not performed.

Review converged after 2 round(s).

return result;
} catch (SplitSource.SplitPendingException e) {
// The backend will retry; an empty OK batch would incorrectly mean EOF.
result.status = new TStatus(TStatusCode.INCOMPLETE);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Gate the pending response on backend support

A pre-change BE treats every non-OK split-fetch status as fatal, so during a rolling upgrade this unconditional INCOMPLETE makes the query fail with unknown error. No request capability or BE-version check protects it. With the new defaults, two Hive partitions can trigger this: A publishes its range while B lists past the one-second window. Before this PR, that small scan was synchronous, or one streaming producer collected both ranges before dispatch. The existing deadline thread is fixed for upgraded BEs; older callers still need a compatible path. Please negotiate support or gate asynchronous dispatch for old BEs, and cover upgraded FE + pre-change BE.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR targets master only, with no release-branch backport. Doris upgrades BE before FE, so an FE containing this change is deployed only after the BE that understands the INCOMPLETE retry response. Upgrading FE first against a pre-change BE is outside the supported order for this master-only change; there is no intermediate master release to support. I am keeping this PR focused and am not adding capability negotiation for that unsupported pairing.

? "unknown error"
: result.status.error_msgs[0]);
do {
RETURN_IF_CANCELLED(_state);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Let local scanner stop interrupt pending retries

RETURN_IF_CANCELLED only observes RuntimeState/query cancellation. A local LIMIT calls ScannerContext::stop_scanners, which sets scanner _should_stop without cancelling the enclosing query; FileScanner and FileScannerV2 check that flag only after this call returns. With parallel scanners (for example, a nested LIMIT above the serial-read threshold), A can satisfy the limit while B waits here for a slow partition and another query branch continues. B now retries across every wait window while holding _range_lock, a scan worker and the fragment context until listing or the entire query ends. Previously this call returned after one bounded fetch. Please observe local scan termination between retries or return control to the scanner, and cover this with RuntimeState still healthy.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 1f23f5b. Scanner::try_stop now publishes an atomic local stop signal, and FileScanner/FileScannerV2 pass it to the shared SplitSourceConnector. RemoteSplitSourceConnector checks it before each pending-response retry and returns no next range when a local LIMIT stops that scanner, even if RuntimeState and other query branches remain active. The new BE test covers a locally stopped scanner with an uncancelled RuntimeState. Header hygiene, clang-format 16, and diff checks pass. Local BE compilation and the test were blocked at CMake compiler-link detection by this Mac’s unaccepted Xcode license; buildall CI has been requested.

### What problem does this PR solve?

Issue Number: N/A

Related PR: apache#69683

Problem Summary: A LIMIT can stop a local scanner while other branches of the same query continue, leaving RuntimeState uncancelled. After a split-fetch RPC returns INCOMPLETE, RemoteSplitSourceConnector previously retried until more splits arrived or the query ended, holding a scan worker despite the scanner already being stopped. Pass the scanner's stop signal through SplitSourceConnector, make the signal atomic for cross-thread publication, and exit the retry loop with no next range when the scanner stops. FileScanner and FileScannerV2 use the same contract.

### Release note

LIMIT queries stop waiting for additional external splits when their local scanner is finished.

### Check List (For Author)

- Test: Added a BE unit test for local scanner stop while RuntimeState remains healthy. The test was not run locally: build.sh --be stopped during CMake's compiler link probe because this Mac has not accepted the Xcode license. Header hygiene, clang-format 16 validation, and git diff --check passed. Remote buildall is requested below.
- Behavior changed: Yes. A stopped scanner no longer continues retrying pending split fetches.
- Does this need documentation: No.
@924060929

Copy link
Copy Markdown
Contributor Author

run buildall

@924060929

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed all 37 changed files at head 1c7a1ac and traced connector production through FE queues/RPCs to both BE scanners. One new P2 finding: the longer first-split planning wait does not observe cancellation of an already-running producer. No still-applicable existing P0/P1 finding remains.

Critical checkpoint conclusions:

  1. Goal and evidence: individual-split queue capacity, smaller producer batches and connector-sized partition batches implement the stated early-delivery goal. Added unit/regression coverage was inspected; the cancellation gap in the inline finding remains.
  2. Scope and abstraction: changes are focused on split scheduling, its configuration, Hive partition-view TTL inheritance and associated tests/docs. Connector sizing remains behind the SPI.
  3. Concurrency: planner, fair scheduler producers, FE RPC consumers and BE scan workers were traced. Queue monitors protect deque state; backend assignment and capacity listeners use separate locks. Callbacks/connector IO run outside queue monitors; no new lock inversion or partial-offer loss/duplication was established.
  4. Lifecycle and memory: per-backend deque counts and bounded producer residuals limit retained split counts, rather than bytes. BE storage remains allocator-aware under its scan task context. Client connections release per retry; scanner stop is atomic. Pre-first-split query cancellation remains the reported lifecycle defect. No new cross-translation-unit static initialization dependency exists.
  5. Configuration: split_partition_batch_size is positive-checked and forwarded in connector sessions; effective producer size is min(batch size, queue capacity). Settings apply to new query planning without process restart. Queue capacity now measures splits, as documented.
  6. Compatibility: connector API major and recorded plugin surface both advance to 25. No new wire field is required. The existing old-BE/new-FE concern is already covered in a prior thread; the official upgrade flow requires BE before FE, and the new BE accepts the previous FE responses.
  7. Thrift/protobuf IDs: no gensrc changes; field-ID/enum migration checks are not applicable.
  8. Parallel paths: FileScanner and FileScannerV2, local/remote connectors, exception and WAL stubs, cooperative/blocking producers, Hive/MaxCompute partition batching and Iceberg streaming were inspected. Synchronous opt-outs remain intact; remote scanners are not capped by the partition-count estimate.
  9. Conditions and errors: pending is distinct from EOF, producer failure and cancellation; drain and awaited-split branches recheck terminal state. New stop/pending branches explain concrete scenarios. No additional silent-error path was established.
  10. Test coverage: inspected tests cover partial enqueue identity, queue-registration races, completion/error/stop, per-backend requests, delayed initial production/deadlines, TTL aliases and Hive end-to-end scan forms. A running first producer cancelled through StmtExecutor is not covered. The added BE test covers local stop before fetch, not an actual pending-RPC sequence.
  11. Test results: no .out result files changed. Changed expected values and EXPLAIN assertions were inspected; detailed delete-file counts intentionally request synchronous planning. No builds, tests, benchmarks or runtime validation were run for this review.
  12. Observability: existing GetSplitTime and generation profiles expose waits/batches; profile output uses the effective producer size. Errors remain propagated with existing logs; no additional mandatory metric was identified.
  13. Persistence/failover: no EditLog, persisted metadata schema or commit protocol changes; transactional persistence checkpoints are not applicable.
  14. Writes/atomicity: this change schedules reads and adjusts a derived metadata cache. No data-write or crash-recovery transaction path changed; read snapshot/lease preparation remains in the existing path.
  15. FE/BE variable propagation: the new setting is consumed through the connector session SPI, not a new serialized FE/BE variable. Existing scanner call sites pass the local atomic stop signal.
  16. Performance: bulk queue operations amortize locking, bounded offsets avoid reconversion/reassignment, and partial offers use available capacity. No new unbounded growth or verified scanner-concurrency regression was found. The PR's benchmark claims were not independently reproduced.
  17. Additional checks and user focus: no additional user focus was supplied. Cache alias precedence and native-format dispatch were traced; no further verified issue or unresolved code-coverage question remains after the final recheck.

Prior threads were independently revalidated: WAL override, local scanner-stop retries, pending fetch handling, awaited terminal-state recheck and normal slow first-split production are repaired at this head. The new finding concerns cancellation during the extended planning wait and is distinct from those earlier issues. Static-only validation is the review's remaining limitation.

Review converged after 2 round(s).

splitAssignment.init();
// The first split can require a remote read session (for example, MaxCompute). Keep
// the planning wait bounded by the query's effective timeout instead of a fixed 30 seconds.
splitAssignment.init(ConnectContext.get().getExecTimeoutS() * 1000L);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Stop the first-split planning wait when the query is cancelled

When a producer is already inside a slow Hive listing or MaxCompute read-session call, KILL QUERY closes its task group but leaves the running SplitProducer untouched: FairTaskExecutor.Group.close() only cancels running Future tasks, while this producer is a plain Runnable. There is no coordinator yet, and this::stop is registered only for query finish, so needMoreSplit() stays true and init() keeps the planning thread waiting after cancellation. This extends the former 30-second upper bound to the full query timeout (900 seconds by default). Register scan/assignment stop with the executor's cancellation callback, or check cancellation during this wait, and cover cancellation while the first producer is running.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 1ce495e. FileQueryScanNode now registers the current SplitAssignment with StmtExecutor.registerQueryCancellationCallback before starting the first producer. Cancellation stops the assignment, wakes init immediately, and closes producer resources even when the running producer is a plain Runnable in remote IO. After init wakes, the planner throws the executor's retained cancellation reason rather than treating the stopped assignment as an empty scan. A cancellation that precedes registration is handled by the callback handoff and init skips starting more work. SplitAssignmentTest covers stopping after the producer starts but before its first split (23/23 passed); FE Checkstyle passed.

### What problem does this PR solve?

Issue Number: N/A

Related PR: apache#69683

Problem Summary: A query cancelled before its first external split had no coordinator yet. The existing cancellation callback closed the connector task group, but a running split producer is a plain Runnable and SplitAssignment.init could continue waiting for the full query timeout after cancellation. Register the current split assignment with the statement executor's planning-stage cancellation callback. Stopping the assignment wakes the first-split wait and closes producer resources; the planner then propagates the recorded cancellation reason. A cancellation that predates registration stops the assignment immediately, so init does not start more split work.

### Release note

Cancelling an external query while its first split is still being prepared stops the planning wait promptly.

### Check List (For Author)

- Test: run-fe-ut.sh ran SplitAssignmentTest (23 passed), including a stop during the first-split wait. FE Checkstyle and git diff --check passed. The local test script used Homebrew gmake for generated sources and skipped the redundant Maven gensrc goal because the host Xcode license blocks system make.
- Behavior changed: Yes. Query cancellation interrupts the first-split planning wait.
- Does this need documentation: No.
@924060929

Copy link
Copy Markdown
Contributor Author

run buildall

@924060929

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed all 37 changed files at 1ce495e44b5d2fbc18fb0d7a320215e099a59cda. No new actionable findings and no still-applicable existing P0/P1 findings were verified. The prior WAL override P1 (4399108229) is fixed; the awaited-split error, pending-fetch, local-stop, first-split deadline and planning-cancellation threads are also addressed at this head. No duplicate comments are posted.

The review converged in 1 round: both complete reviewers and the separate risk reviewer returned NO_NEW_VALUABLE_FINDINGS. The main agent independently checked their evidence, all initial risk items and the final changed-file set. No unresolved static code question remains. No additional user focus was supplied.

Inspected flow: planner → bounded producer lanes → per-backend split queues → FE fetchSplitBatch → shared BE split connector → FileScanner/FileScannerV2, with query cancellation and local LIMIT traced separately.

Critical checkpoint conclusions:

  1. Goal and proof: the implementation enables smaller asynchronous scans, separates Hive partition request size from the trigger, bounds queues by splits, and treats temporary production gaps separately from EOF/errors. Focused unit and regression cases support those behaviors by inspection; they were not executed here.
  2. Scope and reuse: changes remain focused on scheduling, buffering, defaults and their tests. Partition sizing stays in the connector SPI; TTL inheritance reuses CacheSpec mapping rather than adding connector branches to generic planning.
  3. Concurrency and locks: offsets retain partial-batch ownership without reconversion/reassignment. Queue predicate/wait monitors, listener-registration retry and wakeupRequested handoff cover the reviewed races. Queue and registry locks contain bookkeeping; listing, callbacks and RPCs run outside those FE queue monitors. No new lock cycle was found.
  4. Lifecycle: assignment cancellation is registered before first production, wakes planning before resource cleanup and preserves the executor cancellation reason. Producer completion owns source closure; running external IO finishes cooperatively. BE request/result/client lifetimes remain within the synchronous call. No new static-initialization dependency or reference cycle was found.
  5. Configuration: the new positive split_partition_batch_size defaults to 16, is forwarded and captured for subsequent statements without restart. Effective producer batches are capped by queue capacity. Fetch wait is validated positive and describes a per-RPC window.
  6. Compatibility: the SPI surface and major version 25.0 move together; all in-tree BE virtual overrides/callers match. The existing INCOMPLETE compatibility thread (4396311548) remains a deployment constraint: new FE with old BE is not negotiated, and this master-only PR relies on the author's stated BE-before-FE upgrade order. That known issue is not reposted.
  7. Thrift/protobuf: no definitions or field/enum IDs change; no persisted format change is introduced.
  8. Parallel paths: both scanner versions, local/remote sources, both producer APIs, synchronous fallback, sampling/count gates and connector opt-ins were checked. Hive batches independently; MaxCompute retains the SPI's 1024-partition request default; Iceberg keeps count/v3 exclusions; Paimon remains synchronous. Hybrid scanner selection exclusions were also traced.
  9. Conditional checks: the new stop/pending branches explain the concrete failure scenarios. Positive sizes and nonempty partition gating establish the batching arithmetic's domain; no speculative fallback masking an invariant violation was identified.
  10. Tests: inspected cases cover partial offers, multi-backend identities, capacity handoff, terminal races, delayed initial production, cancellation, pending/EOF/failure, TTL aliases and independent partition batching. The code remains modular for these cases. Runtime integration limits are stated below.
  11. Expected results: no .out fixtures change. Regression edits distinguish approximate streaming EXPLAIN from synchronous complete delete-file counters; the inspected assertions match those paths.
  12. Observability: effective batch size, queue capacity, generated counts, fetch timing and existing errors/profiles remain available. No new critical diagnostic loss was identified.
  13. Persistence and failover: no EditLog, metadata replay, transaction commit or persistent-state path changes; these checkpoints are not applicable to the modified logic.
  14. Writes and core invariants: no data-write, visible-version or delete-bitmap protocol changes. Reviewed queue ownership preserves split identity, bounded buffering and fail-loud producer error propagation; no new crash/cleanup deadlock was verified.
  15. FE/BE value passing: the new sizing knob stays in FE session/connector properties. Pending uses the existing status enum; scanner_stop is an in-process atomic pointer. No additional wire field is needed.
  16. Performance and memory: individual split limits, bounded producer lookahead, retained partial offsets and bulk drain avoid unbounded buffering or repeated conversion. BE pending polls release the client between attempts and check query/local stop. No benchmark result is independently claimed.
  17. Other risks: Hive TTL target-key precedence, classloader pinning, source subset ownership and early-dispatch scanner selection were rechecked without another substantiated issue.

Validation limits: this was a static-only review. No builds, tests, benchmarks or runtime fault injection were run. Direct BE pending-to-success and mid-RPC local-stop coverage is absent from the new test, which checks a pre-stopped scanner; live connector/RPC integration and full executor-to-scan cancellation were not demonstrated here. These limits do not leave an unresolved static finding or an unreviewed changed file.

Review converged after 1 round(s).

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 82.35% (98/119) 🎉
Increment coverage report
Complete coverage report

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 28993 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 1ce495e44b5d2fbc18fb0d7a320215e099a59cda, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17584	5195	5092	5092
q2	2151	341	250	250
q3	10207	1455	839	839
q4	4676	461	333	333
q5	7433	816	538	538
q6	180	183	152	152
q7	760	832	615	615
q8	9261	1389	1109	1109
q9	5645	4214	4222	4214
q10	6814	1295	1065	1065
q11	429	243	238	238
q12	638	398	283	283
q13	18134	3741	3093	3093
q14	273	267	243	243
q15	q16	733	713	694	694
q17	1236	751	584	584
q18	7007	6203	6101	6101
q19	1239	968	605	605
q20	392	349	236	236
q21	5453	2434	2493	2434
q22	377	323	275	275
Total cold run time: 100622 ms
Total hot run time: 28993 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	6057	5924	6146	5924
q2	777	616	629	616
q3	5693	5849	5304	5304
q4	2060	2219	1647	1647
q5	5904	5714	5618	5618
q6	237	187	138	138
q7	2250	1971	1833	1833
q8	3035	2684	2658	2658
q9	7823	7508	7534	7508
q10	3667	3620	3143	3143
q11	600	442	383	383
q12	687	667	505	505
q13	3355	3604	3097	3097
q14	300	289	271	271
q15	q16	661	676	636	636
q17	7741	7181	6859	6859
q18	12998	12256	12875	12256
q19	920	806	804	804
q20	2117	2144	1921	1921
q21	5847	4687	4724	4687
q22	517	443	403	403
Total cold run time: 73246 ms
Total hot run time: 66211 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 151013 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 1ce495e44b5d2fbc18fb0d7a320215e099a59cda, data reload: false

query5	4324	580	448	448
query6	424	206	190	190
query7	4817	457	227	227
query8	317	166	156	156
query9	8790	3200	3202	3200
query10	475	326	264	264
query11	5981	3839	3578	3578
query12	148	94	90	90
query13	1251	453	351	351
query14	6104	3935	3633	3633
query14_1	3459	3424	3443	3424
query15	218	197	184	184
query16	946	420	402	402
query17	878	660	528	528
query18	2434	434	314	314
query19	202	173	145	145
query20	89	87	83	83
query21	211	127	111	111
query22	12958	13099	12836	12836
query23	13510	12867	12356	12356
query23_1	12674	12514	12662	12514
query24	7390	812	470	470
query24_1	475	471	479	471
query25	508	401	338	338
query26	1248	255	139	139
query27	2773	448	274	274
query28	4633	2028	2006	2006
query29	1558	576	435	435
query30	303	220	186	186
query31	1004	931	800	800
query32	154	89	90	89
query33	523	294	230	230
query34	921	846	505	505
query35	730	746	649	649
query36	829	803	712	712
query37	126	98	80	80
query38	1786	1723	1649	1649
query39	799	793	767	767
query39_1	729	720	732	720
query40	219	117	97	97
query41	68	65	63	63
query42	85	88	81	81
query43	348	367	307	307
query44	1301	695	723	695
query45	181	170	164	164
query46	834	968	565	565
query47	2958	2920	2840	2840
query48	297	306	223	223
query49	569	408	297	297
query50	681	273	208	208
query51	10212	10481	10362	10362
query52	77	79	71	71
query53	183	207	150	150
query54	242	197	189	189
query55	72	62	65	62
query56	227	248	204	204
query57	1656	1624	1572	1572
query58	291	263	263	263
query59	2165	2212	1956	1956
query60	289	252	221	221
query61	158	150	142	142
query62	392	338	292	292
query63	191	159	169	159
query64	2736	949	743	743
query65	3328	3256	3281	3256
query66	1770	418	311	311
query67	20336	20106	20001	20001
query68	3268	1008	618	618
query69	425	303	256	256
query70	846	791	772	772
query71	298	237	211	211
query72	2809	2631	2349	2349
query73	536	526	293	293
query74	4679	4551	4379	4379
query75	2345	2284	1907	1907
query76	2389	1012	607	607
query77	342	367	275	275
query78	9741	9606	9117	9117
query79	908	858	526	526
query80	532	408	339	339
query81	530	319	270	270
query82	759	132	104	104
query83	301	198	186	186
query84	312	122	100	100
query85	822	433	378	378
query86	319	244	231	231
query87	2004	1961	1790	1790
query88	3758	2749	2728	2728
query89	333	279	240	240
query90	1878	165	163	163
query91	163	149	124	124
query92	96	90	85	85
query93	1002	1004	580	580
query94	446	308	265	265
query95	588	341	308	308
query96	680	479	236	236
query97	2443	2433	2334	2334
query98	156	150	152	150
query99	771	772	651	651
Total cold run time: 234983 ms
Total hot run time: 151013 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 24.34 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 1ce495e44b5d2fbc18fb0d7a320215e099a59cda, data reload: false

query1	0.01	0.01	0.01
query2	0.10	0.05	0.06
query3	0.26	0.08	0.09
query4	1.62	0.09	0.10
query5	0.23	0.24	0.25
query6	1.17	0.69	0.69
query7	0.04	0.01	0.01
query8	0.06	0.04	0.04
query9	0.40	0.35	0.35
query10	0.61	0.58	0.61
query11	0.20	0.14	0.13
query12	0.18	0.15	0.15
query13	0.48	0.49	0.50
query14	1.02	1.02	1.01
query15	0.65	0.61	0.61
query16	0.35	0.36	0.35
query17	1.17	1.17	1.09
query18	0.20	0.19	0.20
query19	2.13	2.00	1.93
query20	0.02	0.02	0.01
query21	15.50	0.20	0.14
query22	4.81	0.05	0.06
query23	16.28	0.33	0.12
query24	3.06	0.52	0.42
query25	0.10	0.06	0.05
query26	0.92	0.21	0.16
query27	0.05	0.05	0.03
query28	3.16	0.83	0.36
query29	12.50	4.05	3.22
query30	0.28	0.14	0.10
query31	2.78	0.56	0.33
query32	3.22	0.59	0.50
query33	3.26	3.24	3.21
query34	15.60	4.04	3.42
query35	3.36	3.34	3.38
query36	0.57	0.43	0.44
query37	0.09	0.07	0.06
query38	0.05	0.04	0.04
query39	0.04	0.04	0.04
query40	0.16	0.14	0.14
query41	0.08	0.03	0.03
query42	0.04	0.02	0.02
query43	0.04	0.04	0.03
Total cold run time: 96.85 s
Total hot run time: 24.34 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 67.12% (32434/48325)
Line Coverage 51.98% (343344/660569)
Region Coverage 47.43% (279143/588548)
Branch Coverage 49.10% (131655/268126)

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 100% (0/0) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 77.47% (36280/46830)
Line Coverage 62.72% (409876/653540)
Region Coverage 59.16% (346920/586420)
Branch Coverage 60.08% (160692/267474)

@924060929
924060929 merged commit dcee644 into apache:master Oct 29, 2026
39 of 40 checks passed
@924060929
924060929 deleted the codex/kr2-default-split-batch-8 branch October 29, 2026 02:08
OIiveirra added a commit to OIiveirra/doris that referenced this pull request Oct 29, 2026
### What problem does this PR solve?

Issue Number: None

Related PR: apache#69032, apache#69683, apache#69799

Problem Summary: Upstream partition batching and the spatial SPI extension both
used connector API 25.0. Merge official master while retaining both interface
surfaces, advance the spatial extension to 26.0, and update its surface-test pin.
Preserve both spatial constant-folding protection and upstream HLL exclusions.
Apply the two approved HLL constant-result getter calls equivalent to apache#69799;
do not change HLL algorithms or its tests. Spatial functionality and ordinary-key
spatial-value support remain unchanged.

### Release note

None

### Check List (For Author)

- Test: Standard ASAN BE+FE build and Checkstyle; selected FE UT 219/219
  (including SPI 153/153); GIS, Iceberg and VARBINARY native regressions;
  API26 resource and ten connector manifests; format16, hygiene and changed-line
  clang-tidy. BE UT compilation is blocked before execution by unchanged upstream
  HLL test references to the removed ColumnPtrWrapper; no passing BE UT is claimed.
- Behavior changed: No. Preserve both parent features and distinguish the spatial
  SPI major version from upstream partition batching.
- Does this need documentation: No. Internal merge/API reconciliation; public
  spatial contracts in apache/doris-website#4239 remain unchanged.
morningman added a commit that referenced this pull request Nov 2, 2026
…hema (#69488)

### What problem does this PR solve?

Issue Number: None

Related PR: #66538, #57531, #65851

Problem Summary:

**In short.** On an Iceberg table, `DEFAULT(column)` anywhere except
`UPDATE ... SET` and `MERGE ... VALUES` reads the default from the read
schema, which carries no Iceberg write-default. This PR resolves it
against the write schema that the statement pinned for its target, as
branch-4.1 and branch-4.2 do.

**Background.** An Iceberg `write-default` applies to rows written after
it is set. So it lives in the writer schema that a write statement pins
(`IcebergWriteSchemaContext`), not in the columns of the read schema.
#65851 resolves `DEFAULT(column)` against that pinned schema in `UPDATE
... SET`, `MERGE ... UPDATE SET` and `MERGE ... INSERT VALUES`
(`ConnectorWriteSchemaUtils`). Every other `DEFAULT(column)` either
fails at binding or reaches `RewriteDefaultExpression` (#57531), which
reads the default from the bound column. branch-4.1 #66538, also in
branch-4.2, resolves these against the pinned write target too. It
rejects `DEFAULT(column)` on an Iceberg column in a statement that does
not write the table.

**The problem, and what it cost.** Reproduced on a local cluster with a
`file://` format-version 3 table: `CREATE TABLE t (id INT, c INT)`,
`ALTER TABLE t ADD COLUMN d INT DEFAULT 42`, one row `(0, 0)`, so `d =
42`.

| Statement | Master today | After this PR (same as branch-4.2) |
|---|---|---|
| `INSERT INTO t (id, c, d) VALUES (1, 1, DEFAULT(d))` | `Unknown column
'd' in 'table list'` | writes 42 |
| `INSERT INTO t (id, c, d) SELECT 2, 2, DEFAULT(d) FROM t WHERE id = 0`
| writes NULL | writes 42 |
| `INSERT INTO t (id, c, d) SELECT 3, 3, DEFAULT(d)` | `Unknown column
'd'` | writes 42 |
| `UPDATE t SET c = 100 WHERE d = DEFAULT(d)` | updates nothing: `d =
NULL` makes the plan an empty set | updates every row, `d = 42` is
pushed down to the scan |
| `MERGE INTO t USING (SELECT 0 AS id) s ON t.id = s.id AND t.d =
DEFAULT(t.d) WHEN MATCHED THEN UPDATE SET c = 300` | matches nothing |
updates row 0 |
| `SELECT DEFAULT(d) FROM t` | NULL | `DEFAULT(d) must reference a
column of the table that this statement writes` |

The `UPDATE` and `MERGE` cases fail silently: the statement succeeds and
changes nothing.

**How this PR fixes it.**

- fe-core cannot tell from a column whether its connector keeps defaults
in the read schema. Hive does: an HMS default shows up in both schemas.
Iceberg does not. The new connector capability
`SUPPORTS_WRITE_ONLY_DEFAULTS` says which kind a table is. The Iceberg
connector declares it. The Hive connector passes it on to iceberg-on-HMS
tables, like the other per-table capabilities, but only through the
two-argument `getTableSchema`. Since #69299, a statement that pins the
table at its latest snapshot reads the schema from the snapshot
overload, which reflects none of them, so on an iceberg-on-HMS table
such a statement keeps master's results (for example, `UPDATE t SET c =
100 WHERE d = DEFAULT(d)` still changes no row). Reflecting the
sibling's capabilities there changes planning for all of them and is
left to a follow-up PR.
- For a target that declares it, `InsertUtils.normalizePlan` resolves
`DEFAULT(column)` in `INSERT ... VALUES` and in the select lists of
`INSERT ... SELECT`, including the replacements of `SELECT *
REPLACE(...)`, against the pinned write schema. It does this by name,
before the source relations are bound, so the name always refers to a
target column, as in branch-4.2. In MySQL, `DEFAULT(column)` in a
`SELECT` refers to a source column instead. A derived table in `FROM` is
a query of its own and is left alone: `DEFAULT(column)` in it still
names a column of its own `FROM` clause.
- `RewriteDefaultExpression` takes the default for a `DEFAULT(column)`
bound to such a table from the pinned write column with the same field
id. That covers the `WHERE` of `UPDATE` and the `ON` of `MERGE`. A MERGE
resolves it whatever its WHEN branches, also when they all delete, as
branch-4.2 does. If the statement pinned no write schema for that table,
it fails. A `DELETE` pins the writer schema too, for its delete sink,
but it writes no row values, so `RowLevelDmlCommand` marks its target
and `DEFAULT(column)` on it fails with `DEFAULT(d) cannot be used in a
DELETE: the defaults of this table apply only to the rows that a
statement writes`, as in branch-4.2, whose DELETE installs no write
schema context. Master reads NULL there, so `DELETE FROM t WHERE d =
DEFAULT(d)` deletes nothing; resolved to the write-default it would
delete every row with `d = 42`.
- A resolved default is cast to the type of its writer column before the
expression around it is bound, as `RewriteDefaultExpression` already
does for a bound `DEFAULT(column)`. The parsed literal `-1` is a
TINYINT, so without the cast `bit_count(DEFAULT(c))` on an INT column
would count 8 bits instead of 32. The external `UPDATE`, `MERGE` and
changelog paths use the same helper. `RewriteDefaultExpression` rejects
a bound `DEFAULT(column)` whose writer column has another type than the
read column the statement was bound with, which happens only when the
table changed outside Doris after Doris cached it, and asks to refresh
the table: the expressions around it were bound against the read type.
- Hive, Paimon and internal tables do not declare the capability, so
they behave as before.
- The new enum constant changes the connector plugin API surface, so
`connector.plugin.api.version` goes from 26.0 to 27.0, as for the other
recent changes to that surface (#69299, #69588, #69298, #69683 and
#69835 took 22.0 to 26.0).

**Where `DEFAULT(column)` resolves on an Iceberg target (direct Iceberg
catalogs).**

| Statement | Position of `DEFAULT(column)` | Result | branch-4.2 |
|---|---|---|---|
| `INSERT` / `INSERT OVERWRITE` | `VALUES` rows | the target column's
write-default, typed as the column | same |
| | the INSERT's own select lists (with or without `FROM`, set operation
branches, `SELECT * REPLACE`) | the target column's write-default, by
name, before binding | same, except `* REPLACE`, which branch-4.2 binds
to the source |
| | `GROUP BY` / `ROLLUP` outputs, a derived table in `FROM`, `WITH`
definitions, subqueries, `WHERE` / `ON` | bound like any
`DEFAULT(column)` (last row) | same, except derived tables, which
branch-4.2 resolves against the target |
| | a `VALUES` branch of a set operation | fails with an unknown column,
as on master | same |
| | a qualifier other than the target (`DEFAULT(src.c)`,
`DEFAULT(ctl.db.t.c)`) in the positions above | fails: `column in
assignment list is invalid` | same |
| `UPDATE` | `SET` / `WHERE` | write-default | same |
| `MERGE` | `ON` and `WHEN ... AND` conditions, whatever the WHEN
branches, also when they all delete | write-default | same |
| | `UPDATE SET` / `INSERT VALUES` | write-default | same |
| `DELETE` (also `DELETE ... USING`) | anywhere | fails: `cannot be used
in a DELETE` | fails: its DELETE has no write schema context |
| any | a bound `DEFAULT(x.c)` | `x` is the written table: its
write-default by field id; an OLAP or Hive table: that column's default;
another Iceberg table: fails with `must reference a column of the table
that this statement writes` | same |

A bound `DEFAULT(column)` whose writer column has another type than the
read column fails and asks to refresh the table. Where `DEFAULT(column)`
is bound rather than resolved by name (the third row), it keeps its
meaning from before this PR and names a column of its own `FROM` clause,
as on master and branch-4.2: for example in `INSERT INTO t SELECT id,
DEFAULT(d) FROM src GROUP BY id, d` with an OLAP or Hive `src`, it takes
the default of `src.d`.

**Results.**

- Local cluster, with the table above: the table shows what each
statement did before and after. `EXPLAIN UPDATE t SET c = 5 WHERE d =
DEFAULT(d)` goes from an empty set to a scan with `d = 42` pushed down
to Iceberg.
- Unit tests: 6 new tests in `InsertUtilsTest`, 6 in the new
`RewriteDefaultExpressionTest` and 1 in `RowLevelDmlCommandTest`. They
cover VALUES, and INSERT ... SELECT both from a staging relation whose
own column is also `name` and without FROM: each resolves to the pinned
default, and an unknown column fails. `DEFAULT(column)` inside a derived
table, qualified or not and also under a UNION branch, is left to
binding. A `SELECT * REPLACE(DEFAULT(name) AS name)` replacement
resolves like the rest of the select list and keeps the star's qualifier
and `EXCEPT` list. The pinned write column wins over the read column. A
statement that writes nothing fails. A table without the capability is
unchanged. With master's `InsertUtils` and `RewriteDefaultExpression`,
the 5 tests of the fix fail and the 2 tests of the unchanged path pass.
The `SELECT * REPLACE` test fails with this PR's previous `InsertUtils`,
where the replacement stays `DEFAULT(name)`. `IcebergConnectorTest`,
`HiveConnectorMetadataSiblingDelegationTest` and
`ConnectorPluginSurfaceTest` pass. So do the fe-core tests around the
write schema: `ConnectorWriteSchemaUtilsTest`,
`ExternalRowLevelUpdatePlanBuilderTest`,
`ExternalRowLevelMergePlanBuilderTest`,
`ChangelogRowLevelDmlTransformTest` and `PluginDrivenExternalTableTest`.
Two of the tests pin the typing: `bit_count(DEFAULT(bits))` gets the
default as an INT in VALUES and in SELECT, and fails without the cast; a
BIGINT writer column over an INT read column is rejected, directly and
under an IF bound to INT. `DEFAULT(column)` on the target of a DELETE
fails even with a pinned write-default, and only a DELETE marks its
target (an UPDATE does not); skipping the check, or marking UPDATE
instead of DELETE, makes exactly these two tests fail.
`PositionDeleteRowLevelDmlTransformTest`,
`PhysicalPlanTranslatorIcebergRowLevelDmlTest`, `DeleteFromCommandTest`
and `UpdateCommandTest` pass.
- Regression: `test_iceberg_initial_defaults` now writes rows 20 to 22
with `DEFAULT(default_int)` in VALUES and in INSERT ... SELECT with and
without FROM. It then updates them with `WHERE default_int =
DEFAULT(default_int)` and `MERGE ... ON ... = DEFAULT(...)`, for Parquet
and ORC, and checks the rows in the `.out`. A plain `SELECT
DEFAULT(default_int)` must fail, and so must a `DELETE ... WHERE
default_int = DEFAULT(default_int)` on rows 20 to 22, which hold the
write-default. The suite passed locally before the DELETE block was
added, and the whole suite, DELETE block included, has since passed in
two External regression runs on CI. With master's FE it fails at the
first of these statements: `Unknown column 'default_int' in 'table
list'`.
924060929 added a commit to 924060929/incubator-doris that referenced this pull request Nov 2, 2026
### What problem does this PR solve?

Issue Number: None

Related PR: apache#69683

Problem Summary: Enabling batch planning for small external scans leaves Iceberg partition counts at zero and split counts approximate when SQL block rules run before execution. It also removes partition and delete-file details from EXPLAIN. Require the existing synchronous planning path for EXPLAIN and enabled applicable partition_num/tablet_num rules, with one shared eligibility gate for Hive and Iceberg. Keep ordinary unrestricted queries on bounded asynchronous split delivery. Rule applicability and the internal-query bypass remain owned by SqlBlockRuleMgr.

### Release note

Preserve external-table partition and split SQL limits and complete EXPLAIN scan details when batch split planning is enabled.

### Check List (For Author)

- Test: Unit Test
    - Reproduced the two eligibility regressions before the fix; all 196 related FE unit tests pass after the fix.
    - Full FE packaging and Checkstyle pass through build.sh --fe -j4 (UI build disabled).
    - External-service regression remains for remote CI; no BE code changed or BE validation rerun.
- Behavior changed: Yes (use exact synchronous scan planning for EXPLAIN and applicable partition/split limits)
- Does this need documentation: No
924060929 added a commit to 924060929/incubator-doris that referenced this pull request Nov 2, 2026
### What problem does this PR solve?

Issue Number: None

Related PR: apache#69683

Problem Summary: Hudi and MaxCompute bypassed common exact-planning eligibility, MaxCompute used the batch-mode threshold as its task size and queued all partition groups, and non-positive split-fetch waits caused immediate retries. A backend stopping at a local LIMIT could also leave its bounded FE queue blocking publication to the remaining backends. Apply the common eligibility gate, use a dedicated bounded MaxCompute continuation, validate the wait before starting producers, and release each stopped consumer from the scan operator owner through a capability-gated optional request. Preserve ordinary EXPLAIN batch plans, require full metadata for VERBOSE/admission checks, and retain native Hive listing root causes.

### Release note

Fix hangs and excessive scheduling during lazy external-table scans, preserve complete scan-count admission and verbose plan metadata, and retain Hive missing-partition diagnostics.

### Check List (For Author)

- Test: 205 related FE unit tests passed through run-fe-ut.sh; 60 related BE ASAN unit tests passed through run-be-ut.sh. Full FE package/Checkstyle and full BE ASAN package passed through build.sh. BE validation uses a local-only source-specific CMake warning adjustment and a focused native test target; neither is committed. External-service regression cases are updated and await CI. Changed-line clang-tidy is blocked by the existing unmatched NOLINTEND in be/src/core/types.h:578.
    - Unit Test / Regression test updates
- Behavior changed: Yes; bounded split delivery now releases stopped backend consumers, validates wait intervals, and preserves exact planning where required.
- Does this need documentation: No
924060929 added a commit to 924060929/incubator-doris that referenced this pull request Nov 2, 2026
### What problem does this PR solve?

Issue Number: None

Related PR: apache#69683

Problem Summary: Hive split generation now schedules several partitions per task, but recorded the whole task output as the split count of one partition. Extrapolating this across all pruned partitions inflated approximate split/file-size estimates: six partitions with ten splits each reported 360 instead of 60. Count actual output by partition values within each batch and atomically retain the largest per-partition count. Preserve the existing minimum and cover uneven/empty partitions, sampling, unpartitioned scans, and different scheduling batch sizes. Correct the legacy-FE closure comment and verify that its existing timeout error is propagated without retries or an unsupported close request.

### Release note

Correct approximate Hive split counts and derived file-size estimates during batched external scans.

### Check List (For Author)

- Test: 209 related FE unit tests passed through run-fe-ut.sh. The unchanged-production reproduction showed 360 instead of 60 and 116 instead of 100; all four new cases now pass. Full FE packaging and Checkstyle passed through build.sh --fe. 61 related BE ASAN tests passed through run-be-ut.sh, including the new old-FE timeout/no-retry case. BE test validation uses the existing local-only focused CMake target and source-specific compiler-warning adjustment, restored afterwards and excluded from this commit.
    - Unit Test
- Behavior changed: Yes; approximate Hive estimates are independent of scheduling batch size and preserve the per-partition maximum.
- Does this need documentation: No

Changed-line clang-tidy remains blocked by the existing core/types.h:578 unmatched NOLINTEND and the pre-included gtest/internal/gtest-internal.h:56 float.h diagnostic.
924060929 added a commit to 924060929/incubator-doris that referenced this pull request Nov 2, 2026
### What problem does this PR solve?

Issue Number: N/A

Related PR: apache#69683

Problem Summary: The split-consumer close concurrency test initializes the large Env and frontend RPC service mocks inside its 30-second method timeout. CI logs show RPC static initialization still running after that budget, before the producer thread is created. Move these class fixtures to BeforeAll, following existing bounded-concurrency tests, so cold initialization does not consume the queue-race budget. Keep the original 30-second timeout, five-second phase bounds, close-race assertions, RPC idempotence, and executor cleanup unchanged.

### Release note

None

### Check List (For Author)

- Test: Unit Test: controlled 1-second budget fails before the fixture move and passes afterward; 63 related FE tests pass with the original 30-second limit; full FE packaging and Checkstyle via build.sh --fe
- Behavior changed: No
- Does this need documentation: No
924060929 added a commit to 924060929/incubator-doris that referenced this pull request Nov 2, 2026
### What problem does this PR solve?

Issue Number: N/A

Related PR: apache#69683, apache#69991

Problem Summary: Hive lazy partition listing applies TABLESAMPLE independently to every scheduling batch, resetting the ROWS byte target and percentage rounding. A sampled scan now uses the existing complete-metadata path to select files once across all pruned partitions, preserving its seeded table-wide selection. Remote split-source cleanup previously recorded completion before FE acknowledgement, so a temporary RPC failure could prevent subsequent cleanup and strand a bounded producer queue. Serialize close acknowledgements independently of consuming fetches and retry only the idempotent cleanup request through the standard Thrift reconnect path. Mark completion after acknowledgement; exhausted errors still cancel the query so other backends cannot wait indefinitely behind an unclosed queue.

### Release note

Fix Hive TABLESAMPLE over-selection with partition batching and recover split-source cleanup from temporary RPC failures.

### Check List (For Author)

- Test: Unit tests and packaging
    - 236 related FE tests passed; full FE packaging and Checkstyle passed.
    - 63 focused BE ASAN tests passed on the final lock/test-helper implementation.
    - Full BE ASAN packaging (including Java scanning extensions) passed.
    - clang-format 16 and git diff --check passed. Changed-line clang-tidy found no remaining new diagnostics; it remains blocked by the pre-existing core/types.h NOLINTEND and forced gtest float.h header diagnostics.
    - BE tests use a focused native target; the complete BE UT suite and external-service regressions were not run in this cycle. Local CMake build adaptations are excluded from this commit.
- Behavior changed: Yes. Sample files are selected once over all pruned partitions; source closure retries temporary failures and records completion only after acknowledgement. Ordinary consuming fetches retain their existing transport-error behavior.
- Does this need documentation: No
924060929 added a commit to 924060929/incubator-doris that referenced this pull request Nov 3, 2026
… explain

### What problem does this PR solve?

Issue Number: N/A

Related PR: apache#69683, apache#69991

Problem Summary: The Iceberg Variant remote-gather fixture asserts inputSplitNum=2 to prove that its selected snapshot contributes both shredded and unshredded files. With external batching enabled by default, ordinary EXPLAIN intentionally reports a sampled approximate split count, and the external regression fails on approximate inputSplitNum=1 before executing the mixed-file result/profile checks. Select EXPLAIN VERBOSE for this single action through the existing regression DSL so the shared exact-planning guard enumerates both files. Preserve the exact split-count, merge-exchange and projected-path assertions, all subsequent data/profile checks, and default batching for executable queries.

### Release note

None

### Check List (For Author)

- Test: Existing FE unit tests and direct regression-call-chain review
    - The current-head external CI failure and exact revision were captured from build 1089454.
    - Both testVerboseExplainRequiresExactFilePlanning and testOrdinaryExplainKeepsTheRealBatchPlan passed using run-fe-ut.sh (2 tests, no failures/errors/skips).
    - Integrated FE Checkstyle, source hash verification and git diff --check passed.
    - The live external regression was not run locally: the configured Iceberg REST and MinIO endpoints are unavailable. New-head CI must validate the complete suite.
    - No FE/BE repackaging was needed for this regression-only DSL change.
- Behavior changed: No product behavior change. Only the fixture EXPLAIN requests exact planning; executable queries retain their batching settings.
- Does this need documentation: No
yiguolei pushed a commit that referenced this pull request Nov 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants