Skip to content

[fix](file) Resolve remaining FileScannerV2 audit issues#65931

Merged
Gabriel39 merged 4 commits into
apache:masterfrom
Gabriel39:ai/doris-27038-complete-v2-fixes
Jul 23, 2026
Merged

[fix](file) Resolve remaining FileScannerV2 audit issues#65931
Gabriel39 merged 4 commits into
apache:masterfrom
Gabriel39:ai/doris-27038-complete-v2-fixes

Conversation

@Gabriel39

@Gabriel39 Gabriel39 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

This follow-up audits the 10 unresolved review threads on #65674 and every child of DORIS-27038.

  • Three unresolved threads were already fixed on master.
  • This PR fixes the remaining seven review findings.

What is changed?

  • Harden Parquet delta geometry, page allocation validation, schema ambiguity handling, dictionary reuse, decompression scratch lifetime, and one-child MAP_KEY_VALUE SET parsing.
  • Validate delete expression result ownership before erasing temporary columns.
  • Scope Iceberg row-lineage virtual columns to Iceberg readers.
  • Propagate Remote Doris Flight timeout and cancellation.
  • Reject NULL JDBC special-type casts for non-nullable targets.
  • Aggregate hybrid Paimon/Hudi condition-cache hit counters.
  • Remove redundant JSON-line copies and Hive key allocations.

The scanner V1 path under be/src/format is intentionally untouched.

Verification

  • BE ASAN unit tests: 172 tests from 12 related suites passed.
  • clang-format 16 dry-run passed for every changed C++ file.
  • git diff --check passed.
  • Confirmed no diff under be/src/format.

@Gabriel39
Gabriel39 requested a review from yiguolei as a code owner July 22, 2026 23:53
@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?

@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17586	4070	4125	4070
q2	2037	317	202	202
q3	10259	1437	816	816
q4	4683	472	340	340
q5	7489	859	571	571
q6	186	174	140	140
q7	775	843	619	619
q8	9665	1451	1478	1451
q9	6114	4337	4334	4334
q10	6823	1736	1469	1469
q11	506	354	318	318
q12	761	578	474	474
q13	18069	3280	2729	2729
q14	257	267	239	239
q15	q16	782	778	704	704
q17	985	925	877	877
q18	6776	5892	5559	5559
q19	1182	1291	1114	1114
q20	813	687	637	637
q21	5716	2653	2361	2361
q22	426	362	301	301
Total cold run time: 101890 ms
Total hot run time: 29325 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4387	4334	4288	4288
q2	305	316	208	208
q3	4560	4958	4395	4395
q4	2055	2146	1359	1359
q5	4413	4300	4276	4276
q6	228	176	133	133
q7	1741	1719	1858	1719
q8	2522	2223	2191	2191
q9	7827	7766	7778	7766
q10	4698	4630	4153	4153
q11	596	434	394	394
q12	742	761	553	553
q13	3398	3516	2921	2921
q14	287	321	288	288
q15	q16	720	719	646	646
q17	1391	1347	1346	1346
q18	8090	7289	7296	7289
q19	1100	1088	1035	1035
q20	2213	2200	1944	1944
q21	5191	4554	4464	4464
q22	514	457	413	413
Total cold run time: 56978 ms
Total hot run time: 51781 ms

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

Automated code review: request changes.

I found seven patch-scoped issues in the FileScannerV2 audit changes: five P1 correctness/resource-safety problems and two P2 lifecycle/performance problems.

Checkpoint conclusions:

  • Goal and scope: the patch remains focused on be/src/format_v2; unchanged V1 paths were explicitly excluded by the PR and were not reported.
  • Correctness and compatibility: the new STRUCT collision check rejects already-resolved field-ID/partial projections. Legacy LIST/MAP parsing, row-lineage opt-in, JDBC casts, JSON buffer ownership, delete-expression ownership, dictionary identity, and hybrid counters otherwise traced cleanly.
  • Concurrency and lifecycle: Flight stream destruction order is safe, but cancellation is armed after DoGet, normal scanner stop cannot interrupt an in-flight Next, the watcher lacks query thread context, and its polling sleep delays every synchronous split close.
  • Memory and error handling: optional Data Page V2 and nonempty fixed-width dictionaries still allocate attacker-declared decompression extents before validating known sizes; retained decompression capacity cannot age out under the production read cadence.
  • Performance and observability: counter propagation and JSON lookup changes are sound; the decompression retention and Flight close-delay findings remain.
  • Tests: the added tests do not exercise blocked Flight setup/read, the production watcher close path, compressed optional V2 pages, compressed nonempty dictionaries, or real batch/page scratch cadence.
  • Configuration, persistence, transactions, and data writes: no applicable changes found.

Validation was static only, as required by the review task; no build or tests were run. The checkout also lacks thirdparty/installed. The PR's reported test results were not independently rerun. No additional user focus was supplied.

std::map<std::string, const ParquetColumnSchema*> file_children;
for (const auto& child : file_schema.children) {
file_children.emplace(to_lower(child->name), child.get());
const auto [_, inserted] = file_children.emplace(to_lower(child->name), child.get());

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.

[P1] Preserve resolved field identity before rejecting case folds

This rejects every case-folded collision in the physical STRUCT before looking at the already-pruned projected_type. For an Iceberg schema s<Value(id=1), value(id=2), other(id=3)>, a field-ID projection of only s.other is fully resolved by TableColumnMapper/projected_type(), yet this loop still returns CORRUPTION because the unrelated siblings collide. It also prevents selecting either case-distinct child by its field ID. Please use the resolved local/field identity (or exact writer-name match) first and report ambiguity only when a requested child actually needs a case-insensitive fallback; add a partial-projection test.

// cannot outlive the query execution timeout indefinitely.
options.timeout = std::chrono::seconds(_timeout_seconds);
options.stop_token = _stop_source.token();
RETURN_DORIS_STATUS_IF_ERROR(_flight_client->DoGet(options, ticket).Value(&_stream));

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.

[P1] Arm cancellation for in-flight setup and normal scanner stop

The only code that signals _stop_source is created after synchronous DoGet() returns, so query cancellation while the server withholds initial stream data cannot interrupt setup and waits for the full Flight deadline. After open, the watcher polls only RuntimeState::is_cancelled(); reaching LIMIT instead calls FileScannerV2::try_stop() and sets only IOContext::should_stop, so a scanner already blocked in Next() is likewise not cancelled. The added fake test sets should_stop before entering Next() and misses both paths. Please arm a thread-safe cancellation bridge before DoGet() and have both query cancellation and scanner stop cancel the in-flight call; cover blocked setup and blocked read.

options.timeout = std::chrono::seconds(_timeout_seconds);
options.stop_token = _stop_source.token();
RETURN_DORIS_STATUS_IF_ERROR(_flight_client->DoGet(options, ticket).Value(&_stream));
_cancellation_watcher = std::jthread([this](std::stop_token stop_token) {

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] Attach the cancellation thread to the query context

This query-owned std::jthread does not inherit the scanner worker's thread-local context, and the lambda enters without SCOPED_ATTACH_TASK (or even SCOPED_INIT_THREAD_CONTEXT). That violates the BE runtime thread-entry contract and leaves cancellation work outside the query's resource/memory accounting; any Doris thread-local use on this path can also fail for an unattached thread. Attach the watcher to the retained RuntimeState/ResourceContext at lambda entry, or run it on an existing query-attached executor.

Status validate_fixed_width_page_size(const tparquet::PageHeader& header, int32_t type_length,
level_t max_rep_level, level_t max_def_level,
bool schema_is_required) {
if (type_length <= 0 || max_rep_level != 0 || max_def_level != 0 || !schema_is_required) {

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.

[P1] Validate optional V2 fixed-width extents before allocation

This early return skips every optional fixed-width page (max_def_level != 0), but Data Page V2 already provides num_values, num_nulls, and exact level byte lengths. A compressed optional INT32 page with one value can therefore declare uncompressed_page_size = INT32_MAX; PageReader bounds only the tiny compressed payload, then load_page_data() calls _reserve_decompress_buf() with nearly 2 GiB before decompression can reject it. Extend the pre-allocation check for V2 PLAIN/BYTE_STREAM_SPLIT using the non-null count and level extents, and test the real compressed optional-V2 load path.

// Only the current encoding is active. Old decoder instances retain reusable capacity but
// must not make the high-water policy treat their last batch as current working memory.
return (_page_decoder == nullptr ? 0 : _page_decoder->active_scratch_bytes()) +
const size_t active_decompress_bytes = _page_uses_decompress_buf ? _decompress_buf_size : 0;

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.

[P1] Let retained decompression capacity age at a safe page boundary

This reports the full allocation as active whenever any compressed page uses it. After a 64 MiB outlier, every later 4 KiB compressed page therefore still looks 64 MiB active, so release_batch_scratch() resets the three-idle counter at each periodic probe. The production loop normally loads the next page before that probe, while the test calls release directly in the artificial gap after next_page(); read_with_plain_filter() never runs the probe at all. Track the current payload separately, carry a pending release to a safe page boundary, and test a large page followed by small compressed pages with boundaries misaligned to the 16-batch cadence plus the direct PLAIN-filter path.

Status validate_dictionary_page_size(const tparquet::PageHeader& header) {
DORIS_CHECK(header.__isset.dictionary_page_header);
const int32_t num_values = header.dictionary_page_header.num_values;
if (UNLIKELY(num_values < 0 || (num_values == 0 && header.uncompressed_page_size != 0))) {

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.

[P1] Validate nonempty fixed-width dictionaries before allocation

This accepts every positive num_values. With a compressed fixed-width dictionary, a one-entry INT32 page can advertise uncompressed_page_size = INT32_MAX while keeping its compressed payload tiny; PageReader bounds only the compressed bytes, and _decode_dict_page() allocates nearly 2 GiB before decompression and set_dict() finally enforce the known four-byte extent. Pass the physical width into this pre-allocation check and validate the checked count/width product for fixed-width PLAIN dictionaries, with a compressed ColumnChunkReader regression rather than only the empty helper test.

_stream->Cancel();
return;
}
std::this_thread::sleep_for(std::chrono::milliseconds(25));

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] Wake the watcher promptly during stream close

request_stop() does not interrupt sleep_for, so a normally completed Flight stream can block in join() for the remainder of this 25 ms polling interval before cleanup proceeds. TableReader::get_block() synchronously closes the current reader at every split EOF, so workloads with many small or fast Remote Doris tickets accumulate roughly 12.5 ms average (25 ms worst-case) avoidable latency per split. Use a stop-token-aware timed wait or notify a condition variable before joining, and add a prompt-close test for the production watcher.

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 176524 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 447d7bcde05039aad38f1fdc1442fcb25a395955, data reload: false

query5	4333	642	487	487
query6	480	218	210	210
query7	5007	571	339	339
query8	338	195	176	176
query9	8772	4142	4035	4035
query10	455	344	295	295
query11	5960	2304	2137	2137
query12	153	104	108	104
query13	1262	643	427	427
query14	6259	5271	4906	4906
query14_1	4248	4248	4249	4248
query15	213	202	208	202
query16	968	462	440	440
query17	1024	693	557	557
query18	2414	453	339	339
query19	204	192	142	142
query20	112	107	109	107
query21	234	158	140	140
query22	13629	13683	13299	13299
query23	17329	16434	16109	16109
query23_1	16197	16204	16127	16127
query24	7428	1660	1277	1277
query24_1	1294	1301	1297	1297
query25	545	431	363	363
query26	1325	350	218	218
query27	2601	589	359	359
query28	4513	1984	2001	1984
query29	1069	588	476	476
query30	348	265	221	221
query31	1111	1081	976	976
query32	104	61	60	60
query33	546	325	262	262
query34	1170	1142	658	658
query35	765	818	675	675
query36	1213	1199	1082	1082
query37	157	111	100	100
query38	1885	1692	1673	1673
query39	870	877	848	848
query39_1	836	837	834	834
query40	252	167	148	148
query41	100	63	62	62
query42	93	90	91	90
query43	317	326	277	277
query44	1395	769	757	757
query45	191	182	178	178
query46	1061	1151	724	724
query47	2108	2099	1993	1993
query48	408	420	292	292
query49	582	436	305	305
query50	1018	425	327	327
query51	10782	10568	10473	10473
query52	85	87	75	75
query53	271	267	196	196
query54	294	229	214	214
query55	75	70	66	66
query56	321	307	296	296
query57	1295	1302	1187	1187
query58	264	271	236	236
query59	1530	1611	1398	1398
query60	308	272	266	266
query61	148	152	151	151
query62	544	506	439	439
query63	239	200	198	198
query64	2844	1086	850	850
query65	4716	4584	4618	4584
query66	1823	535	445	445
query67	29337	29154	29064	29064
query68	3031	1586	1025	1025
query69	407	308	255	255
query70	1049	989	983	983
query71	372	347	305	305
query72	2969	2653	2327	2327
query73	843	788	405	405
query74	5093	4911	4695	4695
query75	2540	2499	2141	2141
query76	2356	1168	772	772
query77	342	370	282	282
query78	11876	11810	11274	11274
query79	1196	1179	748	748
query80	616	583	465	465
query81	457	329	293	293
query82	233	154	124	124
query83	329	316	292	292
query84	291	162	131	131
query85	906	622	514	514
query86	345	290	258	258
query87	1821	1825	1761	1761
query88	3694	2772	2731	2731
query89	414	372	324	324
query90	2160	201	192	192
query91	205	191	167	167
query92	65	59	58	58
query93	1548	1495	979	979
query94	534	357	310	310
query95	780	608	484	484
query96	992	815	368	368
query97	2638	2633	2482	2482
query98	213	207	204	204
query99	1103	1120	967	967
Total cold run time: 261494 ms
Total hot run time: 176524 ms

@hello-stephen

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

query1	0.00	0.00	0.00
query2	0.08	0.05	0.05
query3	0.26	0.14	0.14
query4	1.61	0.15	0.14
query5	0.24	0.23	0.22
query6	1.21	1.06	1.07
query7	0.04	0.01	0.01
query8	0.06	0.04	0.04
query9	0.38	0.31	0.32
query10	0.54	0.56	0.58
query11	0.20	0.14	0.14
query12	0.18	0.14	0.14
query13	0.47	0.48	0.48
query14	1.02	1.01	0.99
query15	0.61	0.58	0.59
query16	0.32	0.34	0.32
query17	1.10	1.12	1.09
query18	0.23	0.20	0.21
query19	2.04	1.92	1.91
query20	0.02	0.01	0.01
query21	15.43	0.25	0.13
query22	4.91	0.05	0.05
query23	16.13	0.31	0.13
query24	2.89	0.42	0.32
query25	0.11	0.05	0.05
query26	0.74	0.21	0.16
query27	0.03	0.03	0.04
query28	3.43	0.91	0.54
query29	12.48	4.05	3.29
query30	0.27	0.15	0.16
query31	2.76	0.58	0.31
query32	3.22	0.58	0.48
query33	3.24	3.22	3.18
query34	15.62	4.21	3.53
query35	3.45	3.50	3.53
query36	0.57	0.44	0.44
query37	0.09	0.07	0.06
query38	0.05	0.04	0.03
query39	0.03	0.03	0.02
query40	0.18	0.17	0.14
query41	0.09	0.03	0.03
query42	0.04	0.03	0.03
query43	0.04	0.03	0.03
Total cold run time: 96.41 s
Total hot run time: 25.02 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 80.17% (190/237) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 57.90% (24467/42258)
Line Coverage 41.90% (243459/581095)
Region Coverage 37.80% (193368/511606)
Branch Coverage 38.89% (87018/223756)

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 92.31% (204/221) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 75.17% (30977/41210)
Line Coverage 59.57% (343923/577320)
Region Coverage 56.31% (289124/513429)
Branch Coverage 57.63% (129009/223856)

@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

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.

Automated follow-up code review: request changes.

I found two additional patch-scoped issues on the current head: one P1 compatibility regression in legacy LIST/MAP schema parsing and one P2 query task-context violation in the newly introduced DoGet worker. I did not duplicate residual problems already covered by the existing Flight-cancellation and Parquet-allocation threads.

Checkpoint conclusions:

  • Goal and scope: this 37-file follow-up remains focused on FileScannerV2 and format-v2 audit fixes. The current implementations for exact-name field identity, Iceberg-only row-lineage opt-in, delete-result ownership, watcher synchronization, supported fixed-width extent checks, scratch release, JSON/JDBC behavior, dictionary identity, delta geometry, and hybrid counters otherwise traced coherently.
  • Correctness and compatibility: the new SET-wrapper exception misinterprets the Parquet-compatible legacy MAP_KEY_VALUE representation when it is a direct LIST element, changing an array-of-map schema into an incompatible wrapper shape or mapping failure.
  • Concurrency and lifecycle: watcher publication, cancellation, locking, and close ordering traced cleanly, but the new query-owned DoGet worker uses a generic non-task thread context and may remain detached beyond query teardown. The still-uncancelled in-flight DoGet RPC is already covered by the existing review thread and was not duplicated.
  • Memory and malformed input: the repaired supported page layouts and scratch/cache lifetimes traced cleanly. Remaining repeated-page, invalid-width, BOOLEAN-dictionary, and cadence variants are at allocation sites already covered by existing review threads, so no duplicate comments were added.
  • Performance and observability: JSON lookup, condition-cache aggregation, and scanner delta reporting traced cleanly; no additional issue found.
  • Tests: the new tests do not cover the legacy uncontained MAP_KEY_VALUE LIST shape or enforce task attachment for the new worker. Other residual test gaps are already requested by existing threads.
  • Configuration, persistence, transactions, and data writes: no applicable changes found.

Validation was static only, as required by the review task; no build or tests were run. This checkout lacks .worktree_initialized and thirdparty/installed, and the PR's reported test results were not independently rerun. No additional user focus was supplied.

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

Correcting the two inline anchors from review 4760641735; the findings and requested-changes state are unchanged.

const bool nested_collection_annotation =
is_list_node(second_level) ||
(is_map_node(second_level) &&
(!second_level.__isset.converted_type ||

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.

[P1] Preserve legacy MAP_KEY_VALUE elements nested in LIST

This exclusion treats every repeated MAP_KEY_VALUE node inside a LIST as the one-key SET-wrapper case. However, Parquet's compatibility contract says a MAP_KEY_VALUE group that is not contained by a MAP group must be interpreted as a map. For a valid legacy shape such as LIST -> repeated element (MAP_KEY_VALUE) -> repeated map -> key/value, the previous branch called parse_map_field(..., true) and produced ARRAY<MAP<...>>; this branch now falls through to parse_struct_field() and exposes a different nested shape (or fails table mapping). Please distinguish the direct one-key wrapper of an enclosing SET from a legacy MAP_KEY_VALUE list element, and add coverage for the latter.

[this](std::stop_token stop_token) { _watch_cancellation(stop_token); });

std::thread do_get_thread([pending, options, ticket] {
SCOPED_INIT_THREAD_CONTEXT();

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] Attach the new DoGet worker to the query task

The watcher now follows the task-thread contract, but this newly introduced worker uses SCOPED_INIT_THREAD_CONTEXT() even though it performs the query's DoGet and owns its client/stream cleanup. On cancellation it is detached and can remain alive until the full Flight deadline, after the reader and query have gone away, so its work runs in the orphan context rather than the query's resource context. This is a distinct new thread from the watcher covered by the earlier review. Prefer removing the worker by using Flight's call-establishment stop token; if it remains, capture a shared ResourceContext, attach it at entry, and ensure its Flight objects are destroyed before that attachment ends.

@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

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.

Automated final follow-up code review: request changes.

I found six additional patch-scoped issues on the current head: three P1 resource/concurrency defects and three P2 performance/test defects.

Checkpoint conclusions:

  • Goal and scope: this 35-file follow-up remains focused on FileScannerV2/format-v2 audit repairs. It fixes several earlier findings, but the remaining allocation, cancellation, and dictionary-retention paths mean the stated hardening goal is not yet complete.
  • Correctness and compatibility: the revised LIST/MAP/SET compatibility, exact-first field identity, delete-expression ownership, Iceberg-only row-lineage synthesis, JDBC nullability, and JSON borrowed-buffer behavior trace coherently. No new storage-format or result-correctness regression was found beyond the reported resource/performance paths.
  • Concurrency and lifecycle: the new Flight watcher reads a plain stop flag concurrently with the operator-thread write, so LIMIT cancellation has a C++ data race. Pending-open locking, task attachment, stream ownership, and close ordering otherwise traced soundly; previously reported detached-open and polling-close concerns were not duplicated.
  • Memory and malformed input: repeated V2 plus variable-width/V1 data pages, and variable-width dictionaries, can still allocate an attacker-declared near-2-GiB decompression extent before Snappy validates the true output. Scratch release and ordinary dictionary generation lifetimes otherwise remain safe.
  • Performance and observability: STRUCT child resolution is now quadratic per selected Row Group for wide nested schemas, and TIMESTAMPTZ pointer identity rematerializes the typed dictionary every filter batch. Hudi/Paimon condition-cache totals and scanner delta publication remain monotonic and exact.
  • Tests: the new blocking Flight tests can stall for the 3600-second default deadline when a fatal assertion exits before server release. The tests also miss the reported repeated/variable-width allocation paths, wide repeated-Row-Group mapping, and multi-batch TIMESTAMPTZ production mapping.
  • Configuration, persistence, transactions, data writes, and FE-BE protocol: no applicable changes found.
  • User focus: no additional user-provided focus was supplied.

Validation was static only, as required by the review task; no build or tests were run. The checkout lacks .worktree_initialized, thirdparty/installed, and thirdparty/installed/bin/protoc, and the PR's reported test results were not independently rerun.

Status validate_fixed_width_page_size(const tparquet::PageHeader& header, int32_t type_length,
level_t max_rep_level, level_t max_def_level,
bool schema_is_required) {
if (type_length <= 0 || max_rep_level != 0) {

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.

[P1] Close the remaining compressed data-page preallocation paths

This still returns before validation for repeated V2 leaves, although V2 provides num_values - num_nulls and exact repetition/definition byte lengths. The type_length <= 0 and V1 optional fallbacks likewise reach _reserve_decompress_buf(uncompressed_size) before Snappy reads the frame's true decoded length. A tiny compressed ARRAY<INT32> V2 page or one-value BYTE_ARRAY/optional V1 page can therefore advertise INT32_MAX and make Doris reserve nearly 2 GiB before rejecting it. The existing thread covered flat optional V2; these are distinct remaining layouts. Apply the exact V2 formula regardless of repetition, preflight codec output before reserving for layouts without a statically known extent, and add compressed regressions for both paths.

return Status::Corruption("Parquet dictionary has {} values and {} uncompressed bytes",
num_values, header.uncompressed_page_size);
}
if (type_length > 0) {

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.

[P1] Validate variable-width dictionary output before allocating it

BYTE_ARRAY keeps type_length == -1, so this helper accepts any positive uncompressed_page_size; _decode_dict_page() then allocates that advertised size before reading either the cached or file payload. A one-entry Snappy dictionary that really expands to a short length-prefixed value can therefore advertise INT32_MAX and force a near-2-GiB allocation before GetUncompressedLength exposes the mismatch. This is distinct from the existing fixed-width dictionary thread. Preflight the compressed frame's decoded length before allocation (and require it to match the page header), with a compressed BYTE_ARRAY regression.

private:
bool _is_cancelled() const {
return (_runtime_state != nullptr && _runtime_state->is_cancelled()) ||
(_io_ctx != nullptr && _io_ctx->should_stop);

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.

[P1] Synchronize the scanner-stop signal read by this watcher

ScannerContext::stop_scanners() can call FileScannerV2::try_stop() on the operator thread, which writes IOContext::should_stop, while this new std::jthread reads the same field here. should_stop is a plain bool and no common lock protects it, so the LIMIT cancellation path has a C++ data race; the watcher may miss the stop and leave Next() blocked until the Flight deadline. The new blocked-Next test performs the same unsynchronized write. This is distinct from the earlier missing-propagation thread: make the lifecycle signal atomic/acquire-release or use a dedicated synchronized stop token, and exercise that production mechanism in the test.

const auto child_it = file_children.find(to_lower(table_name));
if (child_it == file_children.end()) {
const ParquetColumnSchema* file_child = nullptr;
for (const auto& child : file_schema.children) {

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] Keep STRUCT child resolution indexed

This exact-name scan restarts from the first physical child for every projected field, so a full N-field STRUCT now performs roughly N(N+1)/2 comparisons; fallback scans again and recomputes lowercase strings inside the loop. NativeColumnReader::create() rebuilds this mapping for predicate/output readers in every selected Row Group, making wide nested schemas pay the quadratic cost repeatedly. This is distinct from the existing case-collision correctness thread. Build exact-name and normalized unique/ambiguous indices once per physical STRUCT, then preserve the current exact-first semantics through indexed lookups.

std::async(std::launch::async, [&] { return reader->open(std::move(request)); });
ASSERT_TRUE(server.wait_until_entered(std::chrono::seconds(2)));
state->cancel(Status::Cancelled("cancel blocked Flight DoGet"));
ASSERT_EQ(open_result.wait_for(std::chrono::milliseconds(750)), std::future_status::ready);

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] Release the server before a fatal async assertion can return

If this 750 ms assertion fails, GoogleTest returns from the test and destroys open_result before server (reverse declaration order). A std::future from std::async(std::launch::async, ...) waits for its unfinished task, while the server destructor that would release the blocked DoGet cannot run; the only remaining bound is the default 3600-second query/Flight deadline. The fatal assertions at lines 626 and 698 have the same cleanup ordering. Install a scope guard that releases the server before the future is destroyed, or explicitly release/join before reporting each failure.


const DataTypePtr serde_type = is_dict_filter ? file_type : materialization_type;
if (_serde_type != serde_type.get() || _dictionary_index_only != is_dict_filter) {
const bool serde_type_changed = _serde_type != serde_type.get();

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] Compare logical SerDe types before dropping the retained dictionary

With TIMESTAMPTZ mapping enabled, native schema parsing already creates a DataTypeTimeStampTz; build_parquet_column_schema() shares that pointer, but apply_timestamp_tz_mapping() replaces it with a newly allocated, semantically equal type. The pruning probe publishes the projected pointer, then every dictionary-ID batch selects the native field pointer here and resets _materialization_state; matched-value materialization switches back and rebuilds the full typed dictionary, repeating each batch. The direct test passes one shared type pointer and misses this production path. Compare semantic type/scale (or avoid remapping an already equal type) and add a multi-batch TIMESTAMPTZ dictionary-filter regression.

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17815	4393	4409	4393
q2	2072	333	207	207
q3	10313	1528	835	835
q4	4761	487	352	352
q5	8080	897	588	588
q6	307	186	144	144
q7	853	853	621	621
q8	10645	1719	1578	1578
q9	5850	4440	4423	4423
q10	6878	1756	1462	1462
q11	526	358	317	317
q12	758	594	468	468
q13	18110	3482	2741	2741
q14	272	265	244	244
q15	q16	796	794	715	715
q17	978	1048	927	927
q18	7150	5874	5620	5620
q19	1214	1308	1170	1170
q20	813	677	557	557
q21	5638	2616	2420	2420
q22	453	363	304	304
Total cold run time: 104282 ms
Total hot run time: 30086 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4631	4552	4528	4528
q2	305	333	225	225
q3	4616	4991	4453	4453
q4	2127	2194	1413	1413
q5	4513	4348	4405	4348
q6	237	179	132	132
q7	1794	1669	1568	1568
q8	2421	2118	2025	2025
q9	7326	7319	7309	7309
q10	4646	4615	4190	4190
q11	579	443	397	397
q12	758	770	545	545
q13	3055	3437	2867	2867
q14	297	305	258	258
q15	q16	698	723	642	642
q17	1325	1313	1282	1282
q18	7393	7009	6833	6833
q19	1116	1102	1099	1099
q20	2243	2233	1972	1972
q21	5426	4850	4623	4623
q22	547	477	435	435
Total cold run time: 56053 ms
Total hot run time: 51144 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 178453 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 dcc08bf8bc12b5617fb72be01ce1b0ceafac9632, data reload: false

query5	4309	652	506	506
query6	471	241	238	238
query7	2843	601	345	345
query8	214	189	173	173
query9	4551	4102	4099	4099
query10	398	362	320	320
query11	2517	2379	2131	2131
query12	159	107	102	102
query13	1779	601	431	431
query14	6327	5233	4900	4900
query14_1	4285	4300	4286	4286
query15	225	203	179	179
query16	1034	515	460	460
query17	1155	737	600	600
query18	2445	477	353	353
query19	214	201	161	161
query20	118	109	109	109
query21	240	167	143	143
query22	13600	13631	13420	13420
query23	17522	16523	16177	16177
query23_1	16184	16367	16254	16254
query24	10116	1788	1309	1309
query24_1	1295	1310	1299	1299
query25	577	455	385	385
query26	1479	381	218	218
query27	2559	623	373	373
query28	4545	2013	1973	1973
query29	1088	630	500	500
query30	462	284	234	234
query31	1163	1094	985	985
query32	117	66	67	66
query33	687	333	258	258
query34	1204	1089	664	664
query35	882	786	668	668
query36	1247	1175	1055	1055
query37	153	107	92	92
query38	1865	1718	1648	1648
query39	875	859	857	857
query39_1	845	834	871	834
query40	256	166	137	137
query41	63	63	62	62
query42	95	92	94	92
query43	327	327	288	288
query44	1447	764	759	759
query45	200	185	183	183
query46	1068	1174	719	719
query47	2132	2143	2044	2044
query48	440	415	290	290
query49	574	415	302	302
query50	1060	423	340	340
query51	10651	10694	10561	10561
query52	89	95	73	73
query53	270	272	200	200
query54	323	234	230	230
query55	141	73	66	66
query56	283	297	289	289
query57	1325	1295	1184	1184
query58	302	286	257	257
query59	1585	1678	1507	1507
query60	302	272	242	242
query61	143	152	140	140
query62	545	498	428	428
query63	246	209	203	203
query64	2840	1048	921	921
query65	4750	4695	4647	4647
query66	1798	502	376	376
query67	29451	29333	29238	29238
query68	3560	1489	1027	1027
query69	427	321	276	276
query70	1076	967	994	967
query71	396	328	331	328
query72	3074	2719	2379	2379
query73	854	755	413	413
query74	5120	4947	4715	4715
query75	2545	2488	2144	2144
query76	2778	1171	741	741
query77	360	377	284	284
query78	12086	11817	11354	11354
query79	1391	1136	737	737
query80	686	548	457	457
query81	450	327	281	281
query82	506	162	119	119
query83	374	331	302	302
query84	296	162	132	132
query85	950	617	512	512
query86	356	284	288	284
query87	1841	1824	1771	1771
query88	3681	2778	2761	2761
query89	434	376	333	333
query90	1663	203	198	198
query91	202	200	167	167
query92	77	64	55	55
query93	1606	1524	1007	1007
query94	605	371	336	336
query95	798	601	471	471
query96	1083	800	362	362
query97	2660	2652	2495	2495
query98	221	217	204	204
query99	1101	1114	980	980
Total cold run time: 254429 ms
Total hot run time: 178453 ms

@hello-stephen

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

query1	0.01	0.00	0.01
query2	0.10	0.05	0.05
query3	0.26	0.13	0.14
query4	1.62	0.14	0.15
query5	0.26	0.25	0.23
query6	1.26	1.09	1.05
query7	0.04	0.02	0.01
query8	0.06	0.04	0.03
query9	0.42	0.32	0.32
query10	0.60	0.60	0.57
query11	0.21	0.13	0.13
query12	0.18	0.15	0.15
query13	0.48	0.48	0.47
query14	1.03	1.01	1.00
query15	0.64	0.61	0.59
query16	0.32	0.35	0.34
query17	1.09	1.08	1.13
query18	0.24	0.22	0.22
query19	2.09	1.95	2.01
query20	0.01	0.01	0.02
query21	15.45	0.22	0.13
query22	4.91	0.05	0.06
query23	16.16	0.32	0.12
query24	3.15	0.43	0.33
query25	0.11	0.04	0.06
query26	0.74	0.20	0.15
query27	0.06	0.03	0.04
query28	3.55	0.90	0.54
query29	12.51	4.14	3.31
query30	0.27	0.15	0.16
query31	2.79	0.61	0.31
query32	3.22	0.60	0.49
query33	3.21	3.21	3.21
query34	15.64	4.20	3.48
query35	3.57	3.52	3.55
query36	0.56	0.44	0.42
query37	0.09	0.07	0.07
query38	0.06	0.05	0.04
query39	0.04	0.03	0.02
query40	0.19	0.17	0.16
query41	0.08	0.03	0.03
query42	0.04	0.03	0.03
query43	0.05	0.04	0.03
Total cold run time: 97.37 s
Total hot run time: 25.13 s

@Gabriel39
Gabriel39 force-pushed the ai/doris-27038-complete-v2-fixes branch from dcc08bf to 665cd8b Compare July 23, 2026 06:08
@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17936	4442	4141	4141
q2	2078	342	199	199
q3	10236	1487	859	859
q4	4684	468	341	341
q5	7506	856	563	563
q6	177	167	132	132
q7	769	817	614	614
q8	9347	1581	1582	1581
q9	5619	4372	4337	4337
q10	6771	1729	1494	1494
q11	499	354	323	323
q12	714	574	456	456
q13	18136	3372	2778	2778
q14	265	269	247	247
q15	q16	795	783	713	713
q17	998	907	883	883
q18	7142	5733	5598	5598
q19	1196	1264	1061	1061
q20	799	684	603	603
q21	5581	2577	2458	2458
q22	445	360	296	296
Total cold run time: 101693 ms
Total hot run time: 29677 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4456	4485	4383	4383
q2	294	318	216	216
q3	4603	4983	4417	4417
q4	2070	2132	1376	1376
q5	4429	4344	4279	4279
q6	223	179	129	129
q7	1743	2016	1812	1812
q8	2593	2263	2225	2225
q9	7977	8155	7742	7742
q10	4675	4616	4261	4261
q11	590	444	391	391
q12	764	781	564	564
q13	3306	3645	2945	2945
q14	310	300	277	277
q15	q16	695	759	645	645
q17	1358	1356	1428	1356
q18	8013	7405	7181	7181
q19	1179	1133	1081	1081
q20	2216	2202	1942	1942
q21	5212	4559	4372	4372
q22	509	479	407	407
Total cold run time: 57215 ms
Total hot run time: 52001 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 177539 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 665cd8b1a7297ccc0826cd0dec4ac314b3151fc1, data reload: false

query5	4382	644	476	476
query6	489	246	217	217
query7	4873	611	336	336
query8	339	188	175	175
query9	8795	4098	4104	4098
query10	521	362	299	299
query11	5774	2340	2117	2117
query12	160	102	102	102
query13	1255	596	434	434
query14	6245	5205	4904	4904
query14_1	4251	4312	4242	4242
query15	216	206	190	190
query16	1017	480	480	480
query17	949	722	585	585
query18	2462	480	355	355
query19	207	194	155	155
query20	111	112	107	107
query21	227	161	137	137
query22	13596	13437	13339	13339
query23	17311	16537	16111	16111
query23_1	16305	16259	16188	16188
query24	7521	1767	1289	1289
query24_1	1310	1286	1301	1286
query25	576	476	407	407
query26	1339	358	222	222
query27	2580	573	386	386
query28	4500	1994	1996	1994
query29	1073	638	493	493
query30	347	266	227	227
query31	1116	1115	983	983
query32	100	65	61	61
query33	532	333	257	257
query34	1190	1134	646	646
query35	752	801	685	685
query36	1202	1154	1067	1067
query37	155	147	93	93
query38	1861	1698	1653	1653
query39	872	861	841	841
query39_1	838	842	840	840
query40	243	164	142	142
query41	68	66	65	65
query42	94	92	90	90
query43	324	326	286	286
query44	1446	767	756	756
query45	195	180	173	173
query46	1094	1168	741	741
query47	2080	2077	1940	1940
query48	405	439	279	279
query49	583	416	302	302
query50	1101	440	333	333
query51	10755	10438	10509	10438
query52	91	85	74	74
query53	274	280	203	203
query54	271	246	219	219
query55	74	72	73	72
query56	305	303	280	280
query57	1309	1253	1198	1198
query58	287	259	282	259
query59	1566	1661	1439	1439
query60	318	277	254	254
query61	152	144	148	144
query62	540	496	428	428
query63	230	202	202	202
query64	2783	1016	903	903
query65	4745	4484	4626	4484
query66	1817	509	395	395
query67	29644	29217	29076	29076
query68	3015	1510	1013	1013
query69	410	308	267	267
query70	1028	956	975	956
query71	388	343	303	303
query72	3044	2713	2478	2478
query73	795	799	418	418
query74	5046	4893	4760	4760
query75	2512	2575	2118	2118
query76	2335	1181	784	784
query77	353	365	286	286
query78	11808	11896	11332	11332
query79	1412	1192	737	737
query80	1277	561	475	475
query81	545	330	285	285
query82	622	158	118	118
query83	372	337	291	291
query84	319	160	132	132
query85	979	624	524	524
query86	426	299	281	281
query87	1830	1823	1728	1728
query88	3728	2770	2742	2742
query89	434	385	321	321
query90	1947	204	197	197
query91	216	191	163	163
query92	62	58	58	58
query93	1647	1522	1003	1003
query94	733	351	306	306
query95	774	607	486	486
query96	998	828	332	332
query97	2621	2651	2477	2477
query98	217	207	198	198
query99	1097	1116	989	989
Total cold run time: 263290 ms
Total hot run time: 177539 ms

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

Automated follow-up review of 665cd8b1a7297ccc0826cd0dec4ac314b3151fc1.

Outcome: no new non-duplicate inline finding. This is a summary-only review, not an approval: the current head still leaves concerns already raised in existing discussions, and reposting those concerns would create duplicate threads.

Existing discussions that remain applicable:

  • Compressed Parquet allocation hardening is still codec-incomplete: validate_compressed_page_size() preflights only Snappy, while variable-width/optional V1 and dictionary paths for other codecs can still reserve the header-declared extent. This is already covered by r3635726309 and r3635726313.
  • Cancelled Flight DoGet setup is detached until its deadline instead of being cancelled at call establishment, even though the Arrow 17 Flight guidance documents FlightCallOptions::stop_token for that purpose. This remains within r3634830173. The scanner-stop flag read by the watcher is also still an unsynchronized plain bool, as reported in r3635726314.
  • The watcher still uses a non-stop-aware 25 ms sleep (r3634830183), the new STRUCT resolution remains quadratic for wide schemas (r3635726315), fatal assertions can still strand the async Remote Doris tests (r3635726322), and TIMESTAMPTZ dictionary materialization still keys retained state by pointer identity (r3635726324.

Critical checkpoint conclusions:

  • Goal and proof: the patch implements most of the stated FileScannerV2 audit follow-ups and adds focused BE unit tests for the changed branches, but the goal is not fully complete while the existing issues above remain. I reviewed the tests statically; I did not execute them.
  • Scope and focus: the 35 changed BE source/test files remain centered on mapper/reader correctness, native Parquet hardening, Remote Doris cancellation, and focused coverage. No unrelated product change was found.
  • Concurrency and thread safety: only Remote Doris introduces new concurrency. PendingOpen state, Flight stream publication/cancellation, query resource retention, and watcher teardown are otherwise synchronized. The plain-bool scanner-stop race and uncancelled setup RPC remain in the existing threads above; no distinct lock-order or deadlock issue was found.
  • Lifecycle and memory safety: cached/cold Page V1/V2, dictionary/data pages, direct/ordinary reads, and retained decompression scratch were traced. The pending scratch release occurs only after the old page is exhausted. Detached Flight resource ownership is retained correctly, but the existing cancellation and async-test cleanup issues remain. No new use-after-free or ownership defect was found.
  • Configuration: no configuration item or dynamic-reload contract is added.
  • Compatibility: no storage, wire, FE-BE, function-symbol, or rolling-upgrade contract changes. The revised legacy LIST/MAP/MAP_KEY_VALUE handling matches the Parquet compatibility rules, and exact field identity now wins before unique case-insensitive fallback.
  • Parallel paths: compact/selection delete filtering, ORC/materialized delete execution, cache hit/miss, Page V1/V2, dictionary/plain, direct/selected/ordinary reads, and Iceberg/Hudi/Paimon/JSON/JDBC paths were checked. Production delete predicates always append a fresh result column, so the unchanged parallel erases do not expose a separate reachable input-column deletion bug.
  • Special conditions and nullable handling: BOM/empty/EOF line handling, Hive case folding, split reuse, invalid JDBC CAST-to-NULL, empty dictionaries, repeated/optional layouts, malformed level extents, and exact/case-colliding names were checked. No new issue was substantiated.
  • Test coverage and results: the changed unit tests target the intended mapper, JSON, JDBC, hybrid-reader, Parquet, and Remote Doris cases. Known codec, production TIMESTAMPTZ, wide-STRUCT, and async cleanup gaps are already in the linked threads. Per the governing review contract, no local build or test was run; .worktree_initialized, thirdparty/installed, and thirdparty/installed/bin/protoc are absent.
  • Observability: existing/new reader timers and cumulative condition-cache counters cover the changed paths; no additional metric or tracing gap was found.
  • Persistence, transactions, and data writes: not applicable; this patch changes read paths and tests only.
  • FE-BE variables: none added or changed.
  • Performance: JSON removes a line-sized copy, hybrid batch-size propagation is correct, and Parquet checks are page-level. The remaining wide-STRUCT quadratic lookup and TIMESTAMPTZ rematerialization are already reported.
  • Other issues: after the full changed-file sweep and the normal plus risk-focused review passes, no additional non-duplicate finding remained.
  • User focus: no additional user-provided review focus was supplied.

@hello-stephen

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

query1	0.01	0.00	0.01
query2	0.09	0.05	0.05
query3	0.28	0.13	0.13
query4	1.61	0.13	0.12
query5	0.25	0.23	0.23
query6	1.27	1.09	1.09
query7	0.03	0.01	0.00
query8	0.06	0.04	0.04
query9	0.41	0.31	0.32
query10	0.55	0.58	0.58
query11	0.20	0.14	0.14
query12	0.17	0.13	0.15
query13	0.49	0.48	0.47
query14	1.01	1.00	1.02
query15	0.60	0.60	0.59
query16	0.32	0.33	0.32
query17	1.11	1.11	1.12
query18	0.23	0.23	0.21
query19	2.09	1.98	2.00
query20	0.01	0.01	0.01
query21	15.42	0.23	0.13
query22	4.86	0.06	0.05
query23	16.16	0.31	0.13
query24	2.93	0.41	0.33
query25	0.10	0.05	0.05
query26	0.74	0.21	0.16
query27	0.05	0.04	0.04
query28	3.50	0.95	0.53
query29	12.55	4.14	3.30
query30	0.27	0.15	0.16
query31	2.76	0.59	0.31
query32	3.22	0.60	0.49
query33	3.20	3.16	3.19
query34	15.67	4.20	3.50
query35	3.52	3.48	3.55
query36	0.55	0.43	0.43
query37	0.10	0.07	0.07
query38	0.06	0.04	0.04
query39	0.04	0.03	0.03
query40	0.19	0.17	0.14
query41	0.08	0.03	0.02
query42	0.04	0.03	0.03
query43	0.04	0.04	0.03
Total cold run time: 96.84 s
Total hot run time: 25.11 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 88.62% (405/457) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 58.01% (24525/42274)
Line Coverage 42.03% (244373/581466)
Region Coverage 37.92% (194085/511819)
Branch Coverage 39.04% (87414/223905)

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 89.80% (396/441) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 75.22% (31007/41223)
Line Coverage 59.66% (344627/577655)
Region Coverage 56.22% (288738/513625)
Branch Coverage 57.58% (128977/223997)

@Gabriel39
Gabriel39 force-pushed the ai/doris-27038-complete-v2-fixes branch from 665cd8b to f9e7a47 Compare July 23, 2026 09:17
@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@github-actions

Copy link
Copy Markdown
Contributor

Codex automated review failed and did not complete.

Error: You've hit your usage limit. Visit https://chatgpt.com/codex/settings/usage to purchase more credits or try again at Jul 28th, 2026 5:08 PM.
Workflow run: https://github.com/apache/doris/actions/runs/29994753549

Please inspect the workflow logs and rerun the review after the underlying issue is resolved.

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17639	4089	4071	4071
q2	2069	341	203	203
q3	10219	1456	829	829
q4	4686	477	340	340
q5	7504	857	561	561
q6	184	168	136	136
q7	766	808	618	618
q8	9367	1637	1600	1600
q9	5592	4387	4349	4349
q10	6773	1742	1495	1495
q11	501	349	329	329
q12	737	574	455	455
q13	18109	3491	2760	2760
q14	273	266	248	248
q15	q16	793	770	720	720
q17	951	1031	1060	1031
q18	7168	5808	5496	5496
q19	1317	1318	1102	1102
q20	831	691	570	570
q21	5848	2589	2410	2410
q22	427	355	296	296
Total cold run time: 101754 ms
Total hot run time: 29619 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4426	4336	4331	4331
q2	287	322	210	210
q3	4567	4957	4425	4425
q4	2037	2157	1362	1362
q5	4423	4251	4298	4251
q6	230	175	124	124
q7	1739	1994	1854	1854
q8	2582	2220	2155	2155
q9	8113	8131	7798	7798
q10	4733	4643	4251	4251
q11	582	406	386	386
q12	769	766	547	547
q13	3309	3683	2949	2949
q14	303	310	271	271
q15	q16	732	721	636	636
q17	1349	1344	1356	1344
q18	7973	7170	7124	7124
q19	1175	1161	1150	1150
q20	2225	2217	1915	1915
q21	5302	4563	4452	4452
q22	518	448	408	408
Total cold run time: 57374 ms
Total hot run time: 51943 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 178264 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 f9e7a4798588b98505218c20c39a33dcb75fe92b, data reload: false

query5	4312	635	468	468
query6	467	220	204	204
query7	4939	560	347	347
query8	336	183	164	164
query9	8769	4042	4082	4042
query10	458	355	292	292
query11	5916	2351	2152	2152
query12	158	106	105	105
query13	1289	605	424	424
query14	6252	5217	4882	4882
query14_1	4257	4252	4243	4243
query15	228	209	181	181
query16	1000	490	477	477
query17	998	745	596	596
query18	2436	474	357	357
query19	214	196	154	154
query20	110	109	110	109
query21	234	165	141	141
query22	13573	13534	13264	13264
query23	17229	16478	16043	16043
query23_1	16307	16094	16228	16094
query24	7451	1783	1307	1307
query24_1	1295	1291	1301	1291
query25	567	466	395	395
query26	1342	376	216	216
query27	2569	600	378	378
query28	4439	1977	1971	1971
query29	1083	628	483	483
query30	350	270	233	233
query31	1120	1099	982	982
query32	115	65	63	63
query33	547	320	253	253
query34	1181	1146	627	627
query35	770	794	668	668
query36	1197	1188	1036	1036
query37	154	110	98	98
query38	1886	1721	1660	1660
query39	895	861	887	861
query39_1	859	837	823	823
query40	246	171	145	145
query41	65	63	63	63
query42	94	94	92	92
query43	328	324	282	282
query44	1421	759	763	759
query45	198	198	176	176
query46	1078	1201	757	757
query47	2119	2095	1982	1982
query48	416	415	294	294
query49	586	424	299	299
query50	1075	448	343	343
query51	10918	10514	10738	10514
query52	87	88	74	74
query53	266	297	212	212
query54	285	244	213	213
query55	72	77	67	67
query56	313	288	282	282
query57	1320	1286	1173	1173
query58	294	244	260	244
query59	1594	1666	1497	1497
query60	309	276	257	257
query61	158	147	152	147
query62	551	491	422	422
query63	240	203	213	203
query64	2898	1124	867	867
query65	4709	4619	4634	4619
query66	1879	512	390	390
query67	29283	29234	29095	29095
query68	3189	1630	1023	1023
query69	391	304	263	263
query70	1063	971	967	967
query71	410	323	328	323
query72	3111	2732	2395	2395
query73	825	807	417	417
query74	5095	4932	4731	4731
query75	2546	2504	2136	2136
query76	2321	1154	760	760
query77	357	381	286	286
query78	11880	11931	11455	11455
query79	1407	1103	762	762
query80	1323	544	476	476
query81	556	331	301	301
query82	654	159	122	122
query83	403	330	305	305
query84	328	159	134	134
query85	995	623	524	524
query86	424	307	269	269
query87	1832	1829	1761	1761
query88	3728	2803	2776	2776
query89	446	367	346	346
query90	1938	211	203	203
query91	205	187	160	160
query92	64	72	57	57
query93	1680	1520	1017	1017
query94	718	348	328	328
query95	829	600	462	462
query96	1081	809	338	338
query97	2626	2603	2516	2516
query98	214	205	219	205
query99	1077	1127	971	971
Total cold run time: 264109 ms
Total hot run time: 178264 ms

@hello-stephen

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

query1	0.01	0.00	0.01
query2	0.10	0.05	0.05
query3	0.26	0.13	0.13
query4	1.61	0.14	0.14
query5	0.24	0.22	0.23
query6	1.30	1.06	1.09
query7	0.06	0.01	0.00
query8	0.05	0.04	0.04
query9	0.38	0.32	0.31
query10	0.55	0.55	0.56
query11	0.19	0.13	0.14
query12	0.18	0.14	0.14
query13	0.48	0.48	0.49
query14	1.03	1.01	1.01
query15	0.64	0.60	0.61
query16	0.32	0.33	0.32
query17	1.13	1.08	1.10
query18	0.23	0.22	0.21
query19	2.06	1.96	1.95
query20	0.02	0.02	0.01
query21	15.43	0.21	0.15
query22	4.82	0.05	0.05
query23	16.12	0.31	0.13
query24	2.94	0.42	0.36
query25	0.13	0.05	0.04
query26	0.74	0.20	0.16
query27	0.05	0.04	0.04
query28	3.52	0.92	0.52
query29	12.50	4.23	3.34
query30	0.28	0.16	0.15
query31	2.76	0.61	0.32
query32	3.22	0.60	0.49
query33	3.15	3.18	3.32
query34	15.60	4.31	3.55
query35	3.57	3.54	3.56
query36	0.56	0.45	0.44
query37	0.08	0.06	0.06
query38	0.05	0.04	0.03
query39	0.04	0.03	0.03
query40	0.18	0.16	0.15
query41	0.09	0.04	0.03
query42	0.04	0.02	0.03
query43	0.04	0.04	0.04
Total cold run time: 96.75 s
Total hot run time: 25.25 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 88.62% (405/457) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 58.04% (24555/42308)
Line Coverage 42.08% (244858/581876)
Region Coverage 38.01% (194707/512233)
Branch Coverage 39.08% (87601/224132)

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot added the approved Indicates a PR has been approved by one committer. label Jul 23, 2026
@github-actions

Copy link
Copy Markdown
Contributor

PR approved by at least one committer and no changes requested.

@github-actions

Copy link
Copy Markdown
Contributor

Codex automated review failed and did not complete.

Error: You've hit your usage limit. Visit https://chatgpt.com/codex/settings/usage to purchase more credits or try again at Jul 28th, 2026 5:08 PM.
Workflow run: https://github.com/apache/doris/actions/runs/30005243594

Please inspect the workflow logs and rerun the review after the underlying issue is resolved.

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 89.12% (393/441) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 75.35% (31085/41252)
Line Coverage 59.82% (345759/578044)
Region Coverage 56.65% (291185/514033)
Branch Coverage 57.93% (129898/224224)

@Gabriel39
Gabriel39 merged commit b80247f into apache:master Jul 23, 2026
30 checks passed
Gabriel39 added a commit to Gabriel39/incubator-doris that referenced this pull request Jul 23, 2026
### What problem does this PR solve?

This follow-up audits the 10 unresolved review threads on
apache#65674 and every child of
DORIS-27038.

- Three unresolved threads were already fixed on master.
- This PR fixes the remaining seven review findings.

### What is changed?

- Harden Parquet delta geometry, page allocation validation, schema
ambiguity handling, dictionary reuse, decompression scratch lifetime,
and one-child MAP_KEY_VALUE SET parsing.
- Validate delete expression result ownership before erasing temporary
columns.
- Scope Iceberg row-lineage virtual columns to Iceberg readers.
- Propagate Remote Doris Flight timeout and cancellation.
- Reject NULL JDBC special-type casts for non-nullable targets.
- Aggregate hybrid Paimon/Hudi condition-cache hit counters.
- Remove redundant JSON-line copies and Hive key allocations.

The scanner V1 path under `be/src/format` is intentionally untouched.

### Verification

- BE ASAN unit tests: 172 tests from 12 related suites passed.
- clang-format 16 dry-run passed for every changed C++ file.
- `git diff --check` passed.
- Confirmed no diff under `be/src/format`.

---------

Signed-off-by: Gabriel <liwenqiang@selectdb.com>
yiguolei pushed a commit that referenced this pull request Jul 24, 2026
## Summary

Backport the requested Apache Doris PRs to `branch-4.1` in their master
merge order:

1. #63648
2. #64033
3. #64263
4. #64315
5. #63825
6. #65332
7. #65354
8. #65094
9. #65401
10. #65502
11. #65135
12. #65742
13. #65709
14. #65548
15. #65676
16. #65770
17. #65759
18. #65782
19. #65784
20. #65674
21. #65921
22. #65934
23. #65925
24. #65931

#64263, #65354, #65094, #65502, and #65770 are already effectively
present on current `branch-4.1`, so this branch does not duplicate those
commits. The remaining requested changes are represented by ordered
backport commits followed by branch-4.1 compatibility fixes.

## Compatibility notes

- Rebased onto the latest `upstream/branch-4.1` and retained both sides
of the Iceberg scan conflict resolution.
- Keep `be/src/format_v2` and `be/test/format_v2` exactly aligned with
current `upstream/master`, as requested.
- Apply branch-4.1 compatibility adaptations outside the format_v2
paths.
- Preserve the selected PR behavior while avoiding dependencies on
unrelated master-only changes.
- #65921 supplies the Parquet benchmark scenario header required by
`parquet_benchmark_scenarios_test.cpp`, fixing the BE UT compile
failure.
- Adapt branch-4.1 `VRuntimeFilterWrapper` at the master TableReader
boundary so FileScannerV2 residual predicates keep globally rewritten
slot indexes.
- Keep non-transactional JDBC V2 connections usable by avoiding the
unsupported auto-commit transition before Hikari invalidates the proxy.

## FE UT fix

- Widen the auto-profile test timing margins to prevent CI scheduling
delays from selecting the wrong threshold branch.
- Keep the table-filter correctness assertions and use broader
performance guardrails suitable for shared FE UT workers.

## Verification

- Full local FE+BE build: `Successfully build Doris`.
- ASAN BE UT build completed successfully; `test/doris_be_test` linked
with exit code 0.
- Related BE tests: 382/382 passed across 32 suites, including
FileScannerV2, runtime filters, Parquet, Iceberg readers, and format_v2
coverage.
- JDBC scanner UT: 3/3 passed; Maven reactor `BUILD SUCCESS`; Checkstyle
reports 0 violations.
- ClickHouse JDBC V2 regression: 1 suite, 0 failed suites, 0 fatal
scripts.
- Iceberg branch/tag regression (`iceberg_branch_complex_queries`): 1
suite, 0 failed suites, 0 fatal scripts.
- Repository clang-format 16 check: passed for 4,191 files.
- `git diff --check`: passed.
- `be/src/format_v2` and `be/test/format_v2` have zero diff from current
`upstream/master`.

---------

Signed-off-by: Gabriel <liwenqiang@selectdb.com>
Co-authored-by: daidai <changyuwei@selectdb.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by one committer. dev/4.1.4-merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants