Skip to content

[improvement](load) Add LoadTableReader for FileScannerV2 ingestion - #69333

Merged
Gabriel39 merged 3 commits into
apache:masterfrom
Gabriel39:dev/file-scanner-v2-load-master
Oct 26, 2026
Merged

Gabriel39 merged 3 commits into
apache:masterfrom
Gabriel39:dev/file-scanner-v2-load-master

Conversation

@Gabriel39

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Forward-port the complete changes from #69320 to master, including all review fixes through a73b75002fa40f3df7c8189d8fe3560382d2e13a.

Add LoadTableReader so supported traditional file loads use FileScannerV2 with the existing FE/Thrift source and destination tuples. Source defaults, pre-filters, destination conversion, strict/nullability checks, and flexible partial-update bitmaps run in the table-reader finalization hook. CSV/JSON malformed records are rejected with rollback and load counters. JSON pipes consume every message until EOF; empty arrays and invalid configured roots contribute to the load quality gate without losing valid siblings.

Master-specific adaptations:

  • Preserve master's ADBC/Fluss V2 query selection and Lance exclusion.
  • Match master's single-argument TableReader::refresh_conjuncts() and RowDescriptor constructors, and use SlotDescriptor::type().
  • Omit the physical-split override and shared split-cache field, which are absent on master. Loads retain the existing FE split boundaries.

Avro and Arrow IPC loads keep their existing path. No FE or Thrift changes. This port is independent of #69312.

Validation

  • Passed the repository clang-format 16 check, covering all 17 changed C++ source/header files.
  • Passed build-support/check-build-hygiene.sh and git diff --cached --check.
  • Passed focused Clang syntax checks for all 11 changed C++ translation units and table_reader.cpp, using this master's generated headers and UT build configuration. The standalone scanner check suppresses two pre-existing unused-constant warnings from master.
  • Carried over the source PR's BE unit tests, JSON pipe tests, and Stream Load regression fixtures.
  • run-be-ut.sh completed configuration and started the full build. The fresh build requires about 14,750 targets, so it was stopped and replaced with the focused syntax checks above. No master runtime unit-test or cluster-regression pass is claimed; full build and runtime validation remain for CI.

Release note

Route supported traditional file loads through FileScannerV2 with a table reader for load conversion and validation.

### What problem does this PR solve?
Forward-port apache#69320, including all review fixes through a73b750.
Supported traditional loads use a TableReader subclass for source defaults,
pre-filters, destination conversion, rejection accounting and partial updates.
Adapt descriptor and reader APIs to master while preserving its query routing.

### Release note
Route supported traditional file loads through FileScannerV2.

### Check List
- Tests: carried over BE unit and Stream Load regression coverage;
  focused Clang syntax, clang-format 16 and build hygiene checks passed.
- Full runtime testing remains for CI.
- Behavior changed: Yes, supported traditional loads select V2.
- Documentation: updated the FileScannerV2 design document.

Source commits: abdba83, 439f82b, 2f46771, a73b750.
@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

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

No actionable new defect was substantiated in the static review of all 24 changed paths at 6ece82b. Two complete-scope reviewers and a separate risk-focused reviewer returned NO_NEW_VALUABLE_FINDINGS in round 1. The review converged; no unresolved concrete candidate remains. There were no existing inline threads or P0/P1 findings to carry forward. No additional user focus was supplied.

The inspected path is FE source/destination tuple planning -> FileScannerV2 -> LoadTableReader -> TableColumnMapper and physical reader -> source defaults/presence/pre-filters -> destination conversion and validation -> Scanner destination predicates -> existing load sink. The three initial risks—cross-format binding/casts, presence/partial-update semantics, and malformed-record/pipe/counter handling—were checked against actual callers and legacy behavior and dismissed with evidence.

Critical checkpoint conclusions:

  • Goal and evidence: the adapter implements traditional file-load conversion at the table-reader layer. Added BE and Stream Load cases exercise defaults, strict conversion, rejection statistics, missing keys, partial updates, pipe messages, and EOF; these tests were inspected, not executed.
  • Scope and reuse: changes are focused on scanner selection, an ingestion adapter, physical rejection/presence metadata, tests, and documentation; common mapping and reader lifecycle are reused.
  • Concurrency and locks: no new threads, locks, atomics, or lock ordering were introduced. New counters/masks are scanner-local; existing pipe synchronization remains responsible for producer/consumer coordination.
  • Lifecycle and memory: presence masks are consumed before filtering and before reader close; source state is cleared on completion/abort/close. No new ownership cycle or static-initialization dependency was found. Const expressions are materialized before row checks.
  • Configuration: no new configuration item exists. Supported traditional loads intentionally select V2 independently of the query option; query selection retains its existing gates.
  • Compatibility: no persisted/wire representation changes. FE-generated nullable source types and defaults match the adapter; native Parquet/ORC values are mapped into source types before destination expressions. Legacy INT96 timezone behavior is retained when the FE omits the new timestamp contract. WAL recovery continues through its existing query/TVF reader.
  • Thrift/protobuf: no gensrc definitions, field IDs, or enum values changed.
  • Parallel paths: Avro/Arrow ingestion stays on its existing path; query readers retain rejection disabled by default. CSV/JSON and the advertised text/proto/native-format branches were traced.
  • Conditions and errors: rejection branches have concrete malformed-record scenarios; non-recoverable statuses propagate. Rollback restores accepted-row frontiers, and destination filtering follows conversion/error accounting.
  • Test coverage: focused unit/regression cases cover the main adapter and pipe boundaries. New integration fixtures concentrate on CSV/JSON; a full Parquet/ORC writer/encoding matrix, additional sequence/prefilter combinations, and chunked-transfer parse failures remain unexecuted coverage limits.
  • Expected results: fixture-derived row values and loaded/filtered/unselected counts were checked; SELECT results are ordered. No .out files changed. The regression suite uses SQL assertions and final table cleanup, diverging from repository test conventions; this was not treated as a runtime defect.
  • Observability: rejected and unselected totals use separate counters and incremental scanner publication. Existing reader/IO profiles remain; adapter conversion/default/prefilter subphase timing is less detailed than the legacy scanner.
  • Transaction/persistence: no EditLog, transaction, recovery metadata, rowset/version, or publish protocol was modified.
  • Data writes and atomicity: converted rows continue into the existing load sink/transaction path; no new commit boundary was introduced. Crash/failover behavior was not exercised.
  • FE/BE propagation: no new transmitted variable was added; the existing source/destination tuple and expression protocol is reused.
  • Performance: work and presence metadata are bounded by batch rows and projected columns, with expressions prepared once. No measured performance claim is made; benchmarks and final ELF/ABI validation were not run.
  • Other concerns: non-object JSON outer-array recovery and empty arrays with jsonpaths retain legacy behavior; they were recorded as existing edge-case coverage gaps, not new findings.

Validation was static only, as required by this invocation. No builds, runtime tests, source edits, or performance measurements were performed. Convergence describes completion of this review process, not a runtime-validation result.

Review converged after 1 round(s).

Apply the regression assertion fixes from apache#69320 to its master port.
Update UTF-8, physical field-count and JSON no-match diagnostics while
preserving status, rejected-row and exact JSON source-record checks.

Validation: all four affected Groovy assertion replays, all three suite
syntax checks, repository clang-format 16 check, and diff checks passed.
Full cluster regression execution remains for CI.

(cherry picked from commit 7e29433)
@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@Gabriel39

Copy link
Copy Markdown
Contributor Author

Applied the same regression assertion fixes as #69320 to this master port.

The source PR failures covered are:

  • test_csv_with_none_utf8_data: expect the V2 UTF-8 data-quality diagnostic; retain status and rejected-row checks.
  • test_stream_load_error_url: verify the V2 diagnostic reports the exact expected and actual field counts (3 and 9).
  • test_json_load: expect V2's distinct diagnostics for unmatched JSON paths and unmatched object aliases; retain exact source-record checks. The second check was previously hidden by the first failure.

Validation: the four affected Groovy assertions fail before the update and pass afterward in local assertion replays. The three reported cases use their recorded CI responses; the subsequent alias case uses the diagnostic from the reader's no-match branch. All three Groovy files pass syntax checks on master, and the repository clang-format 16 check passes. Full cluster regressions have not been rerun locally; CI has been requested again.

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

No new actionable findings were verified for head ebd0f5f7820ebaf65f7abe35e251d134c661473b. Reviewed all 27 changed paths and the complete supplied diff. The main review and all three independent reviewers completed their rechecks with NO_NEW_VALUABLE_FINDINGS; the review converged in 1 round. There were no existing inline threads or additional user focus points.

The reviewed flow is FE source/default/expression planning → FileScannerV2 selection and split progression → physical decoding and column mapping → source materialization and missing-field handling → source pre-filters → destination conversion/strict/nullability checks → Scanner destination predicates → existing load quality/transaction handling.

Critical checkpoint conclusions:

  1. Goal and evidence: the adapter places ingestion conversion and validation in LoadTableReader while retaining the existing source/destination tuple protocol. Added unit and regression cases cover the principal contracts by inspection; runtime success is not established by this review.
  2. Scope and abstraction: dispatch, physical malformed-record rejection/presence, the finalization hook and load counters form a focused change. File identities are translated through the mapper.
  3. Concurrency and locks: new reader, presence and counter state is scanner-local. Pipe concurrency uses the existing locks and conditions; no new thread or lock-order change was identified.
  4. Lifecycle: source blocks, expressions and descriptors have query/reader ownership; presence metadata is consumed before physical-reader close. Empty converted batches, split transitions, abort and retryable close were checked. No new static-initialization dependency was identified.
  5. Configuration: no new configuration item. Supported traditional loads deliberately select by format; query selection retains its existing gates.
  6. Compatibility: current FE supplies both default channels, source metadata and expressions. Source casts, native-reader timestamp options and file/name identities were traced against the legacy path. No new stored representation or system dependency was identified.
  7. Thrift/protobuf: no definition, field-ID or enum changes.
  8. Parallel paths: query versus traditional/TVF load, Avro/Arrow fallback, Parquet/ORC, CSV/TEXT/PROTO, WAL recovery, JSON file/line/message/chunked modes, ordinary versus flexible updates were examined.
  9. Special conditions: field-count, encoding, missing-key/auto-increment, omitted-value/explicit-NULL and sequence-map checks have concrete triggering cases. No new incorrect condition was verified.
  10. Test coverage: inspected strict/non-strict, defaults, pre-filter ordering, malformed-record rollback, partial-update marks, EOF/batch/split and stream-message cases. The broader validation limits are listed below.
  11. Test results: fixture row/count expectations and changed diagnostics were checked statically; no .out files changed. No execution result is claimed.
  12. Observability: rejected and unselected rows remain separate, with incremental scanner reporting and existing error logging/profile hierarchy.
  13. Persistence and transactions: no journal, transaction or persistence protocol changed; existing load-quality acceptance remains downstream. Current WAL replay continues through its TVF query path.
  14. Writes and atomicity: physical rejection rolls back partial cells/presence before continuation; conversion removes invalid whole rows before downstream loading. No new write-atomicity defect was verified.
  15. FE/BE variables: no new transmitted variable; existing tuples/defaults/strict/sequence metadata supply the adapter. New presence and counters are local.
  16. Performance and memory: buffers and existing physical-reader fast paths remain in use; added presence/filter work is batch-related. No demonstrated pathological regression was found, and no performance or memory benchmark result is claimed.
  17. Final recheck: all initial risks and candidate-like concerns have evidence-based dispositions; no unresolved new defect or unreviewed changed path remains.

Validation limits: static analysis only, with no builds, tests or source edits. Added tests do not establish a full Parquet/ORC traditional-load differential matrix, compressed/TEXT/PROTO load integration coverage, or FE-to-BE flexible sequence/auto-increment integration. Empty outer arrays with jsonpaths and scalar outer-array rollback retain legacy behavior; the new simple-array rejection tests do not establish a universal array-error policy. These are explicit testing/existing-behavior limits, not verified new inline findings.

Review converged after 1 round(s).

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17639	5212	5091	5091
q2	2263	328	267	267
q3	10113	1393	828	828
q4	4683	467	340	340
q5	7445	813	537	537
q6	189	185	158	158
q7	773	795	614	614
q8	9250	1349	1132	1132
q9	5537	4247	4247	4247
q10	6839	1298	1035	1035
q11	436	252	231	231
q12	649	408	303	303
q13	18088	3695	3004	3004
q14	287	277	252	252
q15	q16	741	728	658	658
q17	1231	767	584	584
q18	7097	6201	6137	6137
q19	1266	953	626	626
q20	397	346	222	222
q21	5665	2470	2612	2470
q22	445	344	293	293
Total cold run time: 101033 ms
Total hot run time: 29029 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	6034	5954	6145	5954
q2	762	623	617	617
q3	5682	5788	5362	5362
q4	2077	2175	1601	1601
q5	5744	5894	5647	5647
q6	235	188	149	149
q7	2187	1982	1831	1831
q8	3083	2701	2716	2701
q9	7851	7890	7579	7579
q10	3632	3588	3137	3137
q11	597	417	389	389
q12	688	668	506	506
q13	3293	3637	3048	3048
q14	285	288	272	272
q15	q16	660	694	635	635
q17	7771	7158	7038	7038
q18	12964	12199	12880	12199
q19	935	827	876	827
q20	2171	2138	1926	1926
q21	5914	4841	5049	4841
q22	492	466	412	412
Total cold run time: 73057 ms
Total hot run time: 66671 ms

@hello-stephen

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

query5	4302	574	444	444
query6	433	198	195	195
query7	4815	459	230	230
query8	326	168	150	150
query9	8765	3124	3148	3124
query10	491	298	288	288
query11	5994	3886	3588	3588
query12	156	92	85	85
query13	1265	440	326	326
query14	6078	3977	3686	3686
query14_1	3443	3413	3454	3413
query15	205	194	178	178
query16	957	429	402	402
query17	879	652	527	527
query18	2458	419	294	294
query19	187	154	134	134
query20	82	81	77	77
query21	217	126	105	105
query22	12969	12943	12850	12850
query23	13492	12847	12298	12298
query23_1	12497	12568	12400	12400
query24	7377	830	458	458
query24_1	465	466	473	466
query25	521	395	337	337
query26	1247	248	134	134
query27	2794	434	272	272
query28	4648	1960	1951	1951
query29	1545	581	436	436
query30	304	225	181	181
query31	1009	918	811	811
query32	172	95	102	95
query33	529	292	230	230
query34	902	832	508	508
query35	730	740	631	631
query36	827	832	727	727
query37	125	96	78	78
query38	1779	1742	1683	1683
query39	803	788	741	741
query39_1	722	727	739	727
query40	244	111	97	97
query41	100	61	60	60
query42	83	84	83	83
query43	345	359	309	309
query44	1311	677	694	677
query45	176	176	156	156
query46	845	954	564	564
query47	2801	2945	2681	2681
query48	285	302	215	215
query49	580	392	299	299
query50	661	274	203	203
query51	10358	10106	10119	10106
query52	83	81	66	66
query53	180	209	152	152
query54	268	186	181	181
query55	65	64	71	64
query56	260	218	203	203
query57	1645	1632	1589	1589
query58	324	258	251	251
query59	2052	2184	1974	1974
query60	291	239	219	219
query61	137	142	135	135
query62	385	329	286	286
query63	186	154	161	154
query64	2692	912	824	824
query65	3335	3263	3273	3263
query66	1788	432	334	334
query67	20019	20252	19949	19949
query68	2989	1010	619	619
query69	390	302	261	261
query70	850	782	806	782
query71	310	239	223	223
query72	2822	2790	2445	2445
query73	552	532	299	299
query74	4639	4518	4373	4373
query75	2367	2376	1940	1940
query76	2328	1007	601	601
query77	335	379	274	274
query78	9878	9700	9176	9176
query79	1008	835	520	520
query80	1242	413	334	334
query81	607	317	269	269
query82	1004	144	107	107
query83	301	197	175	175
query84	312	122	106	106
query85	940	414	372	372
query86	482	237	235	235
query87	2010	1955	1836	1836
query88	3827	2690	2671	2671
query89	405	283	235	235
query90	1920	172	170	170
query91	154	150	119	119
query92	96	85	86	85
query93	1157	1013	576	576
query94	742	305	260	260
query95	583	388	308	308
query96	662	499	239	239
query97	2495	2411	2320	2320
query98	163	150	148	148
query99	762	750	656	656
Total cold run time: 236143 ms
Total hot run time: 150480 ms

@hello-stephen

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

query1	0.01	0.01	0.01
query2	0.10	0.04	0.05
query3	0.27	0.09	0.09
query4	1.60	0.10	0.10
query5	0.24	0.24	0.23
query6	1.16	0.68	0.67
query7	0.04	0.00	0.00
query8	0.05	0.03	0.03
query9	0.41	0.35	0.33
query10	0.58	0.60	0.59
query11	0.20	0.14	0.15
query12	0.18	0.15	0.14
query13	0.48	0.50	0.49
query14	1.00	0.99	1.01
query15	0.64	0.63	0.63
query16	0.34	0.33	0.35
query17	1.16	1.13	1.15
query18	0.20	0.19	0.20
query19	2.15	1.96	2.03
query20	0.02	0.01	0.01
query21	15.50	0.19	0.13
query22	4.89	0.05	0.06
query23	16.34	0.33	0.13
query24	3.08	0.60	0.40
query25	0.11	0.08	0.04
query26	1.06	0.20	0.14
query27	0.06	0.06	0.05
query28	3.05	0.74	0.37
query29	12.50	4.20	3.36
query30	0.28	0.13	0.10
query31	2.78	0.56	0.32
query32	3.22	0.60	0.51
query33	3.22	3.26	3.17
query34	15.33	3.96	3.35
query35	3.36	3.36	3.34
query36	0.54	0.46	0.41
query37	0.10	0.06	0.06
query38	0.06	0.04	0.04
query39	0.04	0.03	0.03
query40	0.18	0.14	0.14
query41	0.09	0.03	0.02
query42	0.06	0.03	0.03
query43	0.04	0.04	0.03
Total cold run time: 96.72 s
Total hot run time: 24.32 s

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17595	5173	5068	5068
q2	2124	329	257	257
q3	10214	1389	811	811
q4	4680	459	333	333
q5	7423	798	533	533
q6	183	186	153	153
q7	763	803	609	609
q8	9247	1347	1053	1053
q9	5511	4187	4161	4161
q10	6837	1285	1038	1038
q11	421	252	234	234
q12	639	396	272	272
q13	18120	3618	3026	3026
q14	276	270	240	240
q15	q16	738	722	670	670
q17	1246	746	589	589
q18	7058	6190	6128	6128
q19	1253	945	576	576
q20	385	350	222	222
q21	5046	2130	2265	2130
q22	351	295	247	247
Total cold run time: 100110 ms
Total hot run time: 28350 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	5609	5570	5585	5570
q2	688	594	553	553
q3	5250	5414	4963	4963
q4	2011	2135	1563	1563
q5	5310	5175	5674	5175
q6	248	201	150	150
q7	2403	2127	1894	1894
q8	3222	2860	2734	2734
q9	8130	8210	7962	7962
q10	3756	3666	3257	3257
q11	609	433	451	433
q12	681	712	517	517
q13	3342	3768	3388	3388
q14	337	326	315	315
q15	q16	685	705	641	641
q17	8244	7422	7371	7371
q18	13023	12214	12959	12214
q19	938	846	799	799
q20	2140	2159	1903	1903
q21	5616	4719	4683	4683
q22	506	448	410	410
Total cold run time: 72748 ms
Total hot run time: 66495 ms

@hello-stephen

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

query5	4309	597	443	443
query6	429	201	187	187
query7	4811	446	235	235
query8	318	171	154	154
query9	8754	3104	3099	3099
query10	458	309	255	255
query11	5965	3857	3593	3593
query12	150	95	86	86
query13	1246	447	309	309
query14	6065	3899	3666	3666
query14_1	3434	3345	3357	3345
query15	211	197	190	190
query16	930	413	412	412
query17	839	636	514	514
query18	2404	424	303	303
query19	199	156	131	131
query20	82	80	80	80
query21	210	125	104	104
query22	12957	13024	12785	12785
query23	13316	12897	12400	12400
query23_1	12539	12442	12510	12442
query24	7351	829	459	459
query24_1	468	473	467	467
query25	508	394	351	351
query26	1255	255	140	140
query27	2778	441	271	271
query28	4619	1964	1960	1960
query29	1538	586	450	450
query30	301	231	184	184
query31	1026	949	818	818
query32	147	97	92	92
query33	523	307	270	270
query34	889	849	492	492
query35	737	766	638	638
query36	864	865	737	737
query37	123	94	86	86
query38	1758	1747	1685	1685
query39	788	796	738	738
query39_1	736	727	735	727
query40	221	123	96	96
query41	73	69	69	69
query42	87	84	83	83
query43	347	365	324	324
query44	1306	696	693	693
query45	178	178	174	174
query46	827	976	602	602
query47	2772	2616	2763	2616
query48	289	308	224	224
query49	597	409	306	306
query50	680	274	201	201
query51	10405	10391	10255	10255
query52	80	81	72	72
query53	188	214	151	151
query54	242	222	201	201
query55	83	73	65	65
query56	245	229	219	219
query57	1698	1614	1569	1569
query58	297	270	259	259
query59	2209	2224	1981	1981
query60	317	258	233	233
query61	171	167	160	160
query62	389	334	290	290
query63	188	165	161	161
query64	2840	978	790	790
query65	3310	3253	3244	3244
query66	1761	427	307	307
query67	20270	20095	19927	19927
query68	3008	992	611	611
query69	379	288	249	249
query70	870	768	723	723
query71	288	223	209	209
query72	2671	2659	2324	2324
query73	516	521	291	291
query74	4610	4504	4368	4368
query75	2320	2278	1929	1929
query76	2314	998	579	579
query77	336	377	282	282
query78	9720	9735	9256	9256
query79	958	896	517	517
query80	762	419	365	365
query81	548	322	266	266
query82	581	142	109	109
query83	278	195	181	181
query84	308	130	103	103
query85	944	425	370	370
query86	360	235	230	230
query87	2000	1980	1806	1806
query88	3654	2703	2675	2675
query89	329	288	245	245
query90	1701	166	158	158
query91	163	154	128	128
query92	98	108	96	96
query93	1002	1017	577	577
query94	495	333	263	263
query95	580	340	365	340
query96	668	481	235	235
query97	2449	2439	2303	2303
query98	163	155	149	149
query99	776	764	650	650
Total cold run time: 233674 ms
Total hot run time: 150501 ms

@hello-stephen

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

query1	0.01	0.01	0.01
query2	0.09	0.05	0.05
query3	0.26	0.08	0.08
query4	1.61	0.10	0.10
query5	0.27	0.25	0.24
query6	1.17	0.69	0.69
query7	0.04	0.01	0.01
query8	0.05	0.04	0.03
query9	0.40	0.33	0.33
query10	0.61	0.56	0.60
query11	0.20	0.14	0.14
query12	0.18	0.16	0.15
query13	0.48	0.49	0.50
query14	1.05	1.02	1.02
query15	0.63	0.61	0.62
query16	0.34	0.35	0.33
query17	1.14	1.15	1.16
query18	0.20	0.18	0.18
query19	2.12	1.92	1.99
query20	0.02	0.02	0.01
query21	15.49	0.20	0.13
query22	4.88	0.05	0.05
query23	16.27	0.32	0.12
query24	3.13	0.67	0.40
query25	0.10	0.05	0.04
query26	1.60	0.23	0.16
query27	0.05	0.04	0.03
query28	2.58	0.74	0.37
query29	12.54	4.16	3.27
query30	0.27	0.13	0.09
query31	2.76	0.56	0.31
query32	3.22	0.60	0.51
query33	3.16	3.22	3.18
query34	15.40	4.03	3.41
query35	3.31	3.31	3.39
query36	0.56	0.47	0.42
query37	0.09	0.07	0.06
query38	0.05	0.04	0.03
query39	0.03	0.03	0.03
query40	0.17	0.15	0.14
query41	0.09	0.03	0.03
query42	0.04	0.03	0.03
query43	0.04	0.03	0.04
Total cold run time: 96.7 s
Total hot run time: 24.25 s

ADBC and Fluss do not support ordinary file loads. Reject their table
markers before checking the physical format, since the default Parquet
format otherwise admits them to LoadTableReader.

Add shared selector coverage for an omitted option and default format,
both option values and explicit physical formats. Query selection stays
on the existing connector-specific path.

Validation: the new regression fails before the fix; 31 targeted tests
pass in the branch-4.2 ASAN/UBSAN harness afterward, including the two CI
failure assertions. Master operator and relevant test translation units
pass syntax checks. clang-format 16, build hygiene and diff checks pass.
Full BE UT execution remains for CI.
@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@Gabriel39

Copy link
Copy Markdown
Contributor Author

Fixed the two BE UT failures reported by build 1074847. The load selector previously accepted the default Parquet format before considering the ADBC/Fluss table marker. These connectors support queries only, so the load gate now rejects their markers before the physical-format switch. Query routing is unchanged.

Added a shared regression covering both connectors with the default format/omitted option, both option values, and explicit physical formats. The same change is applied to #69320 and #69333.

Validation:

  • The new regression fails before the fix and passes afterward.
  • All 31 targeted tests pass in the branch-4.2 ASAN/UBSAN harness, linking rebuilt changed units against existing project libraries. This includes the assertions from both reported CI failures and the existing load conversion/JSON pipe tests.
  • Master's operator, shared regression, and the original ADBC/Fluss test translation units pass syntax checks using its own UT build configuration.
  • clang-format 16 checks pass on both branches; master's build-hygiene and diff checks pass.

The complete master BE UT suite was not run locally; CI has been requested again.

@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 #69333 at 2fae0d9. One P2 data-correctness/compatibility finding is reported inline: the newly mandatory V2 Parquet load path changes a supported non-NULL year-zero local timestamp to NULL. No P0/P1 finding or existing blocking inline thread was identified.

The main reviewer and two complete-scope reviewers covered all 27 changed paths; a separate reviewer investigated conversion provenance, presence/default/partial-update semantics, and EOF/counters/cleanup. The source/destination load protocol was traced from FE planning through scanner selection, table/column mapping, physical reads, source finalization, destination validation and the existing sink.

Applicable critical checkpoints:

  1. Goal and functional evidence: LoadTableReader places ingestion conversion at the table layer and retains destination filtering in Scanner. Added tests exercise the intended flow, but the inline Parquet compatibility defect prevents full preservation of load behavior.
  2. Scope and clarity: changes are focused on dispatch, the adapter/finalization contract, physical rejection/presence metadata, counters, documentation and tests.
  3. Concurrency and locks: new mutable reader/IOContext state is scanner-local; existing synchronized pipes handle concurrent producers. No new thread, lock order or deadlock path was found.
  4. Lifecycle/static initialization: missing masks are consumed before reader close; EOF with rows, fully rejected batches, split transitions, abort and close were traced. No new owner cycle or cross-TU initialization dependency was found.
  5. Configuration: no configuration item was added. The dispatch intentionally ignores the query V2 option for supported loads; load strict_mode and query enable_strict_cast are separate, relevant to the finding.
  6. Compatibility/internal interfaces: finalization's changed schema/row-count contract was checked across callers. The Parquet input compatibility issue is inline; no wire or persisted format changed.
  7. Thrift/protobuf IDs: no generated protocol definition changed; branch field-ID comparison is not applicable.
  8. Parallel paths: CSV, JSON object/path/root/array, TEXT/PROTO, Parquet/ORC and WAL selection were traced; Avro/Arrow keep their existing load path and normal WAL TVF replay stays separate.
  9. Special conditions: wrong field counts, UTF8 rejection, optional defaults, explicit NULL, flexible keys/auto-increment/sequence, query-only connectors and EOF conditions were checked against upstream producers and legacy behavior. Inherited JSON edge behavior was not reposted as a new defect.
  10. Test coverage: selector, adapter, malformed-record/default/bitmap and pipe tests plus regression fixtures were inspected. There is no added end-to-end binary-format load matrix or complete Scanner-to-load-counter runtime test.
  11. Test results: new expected rows/counts and changed diagnostics are statically consistent with the code. No new .out file was added. No runtime pass is claimed.
  12. Observability: rejected/unselected counters retain separate channels into load statistics and the profile hierarchy remains. The finding exposes a conversion failure that escapes rejected-row accounting.
  13. Transactions/persistence/failover: no EditLog, durable registration, commit, replay, visible-version or MoW publication protocol is changed.
  14. Data writes/atomicity/crashes: the reader feeds existing transactional sinks; no new commit/rollback or crash-recovery path was introduced. The inline finding can change the value delivered to that sink.
  15. FE-BE variables: existing tuples/required slots/defaults/expressions are reused; current FE writes both default representations and preserves slot order. No new transmitted variable was added.
  16. Performance/memory: batch masks, validity filters, source/default materialization and buffer ownership were inspected; no additional substantiated performance or memory defect was found. No benchmark claim is made.
  17. Other issues and focus: no further distinct verified defect or unresolved candidate remains. There was no additional user-provided focus; every initial risk has an explicit ledger disposition.

Validation and coverage limits: this invocation was static-only by contract; no builds, tests, cluster runs or source edits were performed. Added tests do not establish runtime correctness for the full Parquet/ORC/PROTO/TEXT/compressed/quoted/nonzero-split/cancellation matrix. These runtime limits remain even after static reviewer convergence. Review uses three bounded rounds; the trusted helper records the convergence and delivery result.

Review converged after 3 round(s).

// Load planners omit query session options. Thrift's default makes an omitted V2
// option indistinguishable from false, so ingestion selects by format instead.
switch (scan_params.format_type) {
case TFileFormatType::FORMAT_PARQUET:

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] Preserve year-zero timestamps when enabling V2 Parquet loads

Selecting V2 for every Parquet load turns supported year-zero local timestamps into NULL. For example, an optional INT64 TIMESTAMP(MICROS, isAdjustedToUTC=false) value -62167219200000000 loaded into a nullable STRING column previously produced 0000-01-01 00:00:00.000000 through V1's Int64ToTimestamp and CAST. V2's parquet_timestamp_micros rejects values before 0001, and its non-strict native decoder marks this non-NULL physical value as NULL. LoadTableReader::_convert then sees an already-NULL source, so strict_mode=true still accepts/stores NULL without counting a rejected row; a required destination instead rejects the formerly valid row. Preserve the prior load behavior for Doris' supported year-zero values before routing these loads unconditionally.

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17584	5218	5118	5118
q2	2091	299	257	257
q3	10265	1410	844	844
q4	4685	463	340	340
q5	7459	813	540	540
q6	184	183	159	159
q7	767	801	618	618
q8	9271	1378	1100	1100
q9	5627	4257	4228	4228
q10	6842	1284	1032	1032
q11	423	253	233	233
q12	636	401	292	292
q13	18081	3631	3034	3034
q14	281	272	249	249
q15	q16	746	719	662	662
q17	1219	774	579	579
q18	7019	6209	6127	6127
q19	1273	954	610	610
q20	383	336	235	235
q21	5595	2560	2487	2487
q22	382	328	276	276
Total cold run time: 100813 ms
Total hot run time: 29020 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	6002	5923	6096	5923
q2	772	644	596	596
q3	5564	5869	5400	5400
q4	2059	2181	1598	1598
q5	5671	5863	5665	5665
q6	238	191	147	147
q7	2268	2052	1861	1861
q8	3025	2622	2651	2622
q9	7877	7954	7633	7633
q10	3647	3604	3141	3141
q11	594	410	378	378
q12	667	671	513	513
q13	3373	3657	3044	3044
q14	286	290	269	269
q15	q16	679	685	611	611
q17	7772	7137	6878	6878
q18	12973	12214	12882	12214
q19	908	814	778	778
q20	2144	2161	1938	1938
q21	5885	4827	4950	4827
q22	513	446	406	406
Total cold run time: 72917 ms
Total hot run time: 66442 ms

@hello-stephen

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

query5	4309	595	444	444
query6	432	209	188	188
query7	4801	447	221	221
query8	323	165	152	152
query9	8801	3094	3095	3094
query10	479	322	257	257
query11	5993	3879	3584	3584
query12	150	98	92	92
query13	1259	482	357	357
query14	6112	3897	3651	3651
query14_1	3389	3400	3388	3388
query15	213	201	185	185
query16	957	443	414	414
query17	850	668	534	534
query18	2422	422	315	315
query19	204	168	143	143
query20	87	85	88	85
query21	216	127	106	106
query22	13001	12881	12884	12881
query23	13554	12860	12382	12382
query23_1	12563	12598	12670	12598
query24	7377	806	465	465
query24_1	477	462	469	462
query25	534	422	377	377
query26	1270	264	140	140
query27	2762	440	270	270
query28	4626	1936	1924	1924
query29	1565	619	453	453
query30	299	234	195	195
query31	1013	929	824	824
query32	138	92	94	92
query33	526	309	245	245
query34	911	837	496	496
query35	745	755	650	650
query36	838	814	731	731
query37	132	99	88	88
query38	1768	1730	1699	1699
query39	786	812	751	751
query39_1	733	732	750	732
query40	224	117	99	99
query41	87	69	70	69
query42	89	84	81	81
query43	349	376	311	311
query44	1302	676	687	676
query45	179	183	168	168
query46	854	965	566	566
query47	3025	2962	2755	2755
query48	288	305	215	215
query49	577	401	296	296
query50	667	264	205	205
query51	10529	10407	10470	10407
query52	78	76	72	72
query53	182	202	145	145
query54	233	204	192	192
query55	73	71	63	63
query56	219	209	215	209
query57	1661	1626	1575	1575
query58	277	244	257	244
query59	2105	2161	1959	1959
query60	292	243	229	229
query61	144	174	146	146
query62	380	338	283	283
query63	187	160	171	160
query64	2735	945	773	773
query65	3313	3252	3254	3252
query66	1772	411	295	295
query67	20163	20065	19857	19857
query68	2950	1009	610	610
query69	389	303	250	250
query70	832	780	775	775
query71	299	246	216	216
query72	2715	2622	2362	2362
query73	509	515	294	294
query74	4608	4508	4364	4364
query75	2336	2277	1926	1926
query76	2309	990	577	577
query77	348	376	263	263
query78	9695	9719	9227	9227
query79	993	889	514	514
query80	842	426	344	344
query81	575	311	274	274
query82	567	129	102	102
query83	280	197	180	180
query84	316	124	101	101
query85	1013	429	377	377
query86	363	248	197	197
query87	2027	1963	1785	1785
query88	3645	2664	2645	2645
query89	326	278	241	241
query90	1711	168	163	163
query91	162	152	126	126
query92	97	83	79	79
query93	990	999	567	567
query94	507	294	269	269
query95	573	380	296	296
query96	669	479	232	232
query97	2444	2496	2315	2315
query98	178	151	147	147
query99	773	762	660	660
Total cold run time: 234253 ms
Total hot run time: 150829 ms

@hello-stephen

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

query1	0.00	0.00	0.01
query2	0.09	0.05	0.05
query3	0.27	0.09	0.08
query4	1.61	0.10	0.10
query5	0.23	0.24	0.25
query6	1.17	0.70	0.68
query7	0.04	0.01	0.01
query8	0.06	0.03	0.04
query9	0.40	0.36	0.36
query10	0.57	0.57	0.55
query11	0.20	0.15	0.15
query12	0.18	0.15	0.15
query13	0.49	0.50	0.49
query14	1.03	1.02	1.02
query15	0.63	0.62	0.63
query16	0.31	0.34	0.35
query17	1.12	1.17	1.14
query18	0.20	0.19	0.21
query19	2.11	2.00	1.97
query20	0.02	0.02	0.01
query21	15.50	0.19	0.14
query22	4.99	0.06	0.06
query23	16.26	0.31	0.12
query24	2.93	0.52	0.40
query25	0.10	0.07	0.04
query26	1.47	0.23	0.15
query27	0.05	0.03	0.04
query28	3.12	0.68	0.35
query29	12.51	4.13	3.26
query30	0.28	0.14	0.11
query31	2.77	0.55	0.33
query32	3.23	0.60	0.50
query33	3.15	3.28	3.18
query34	15.34	4.02	3.39
query35	3.33	3.31	3.33
query36	0.54	0.47	0.43
query37	0.09	0.07	0.06
query38	0.04	0.04	0.03
query39	0.04	0.03	0.03
query40	0.18	0.15	0.13
query41	0.08	0.04	0.03
query42	0.03	0.02	0.03
query43	0.04	0.04	0.03
Total cold run time: 96.8 s
Total hot run time: 24.31 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 84.62% (11/13) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 66.49% (31897/47971)
Line Coverage 51.28% (336288/655749)
Region Coverage 46.67% (272056/582940)
Branch Coverage 48.40% (128393/265251)

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 100.00% (13/13) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 77.26% (35910/46480)
Line Coverage 62.43% (404987/648721)
Region Coverage 58.97% (342525/580820)
Branch Coverage 59.85% (158352/264594)

@Gabriel39
Gabriel39 merged commit 9af1840 into apache:master Oct 26, 2026
37 checks passed
morningman added a commit to morningman/doris that referenced this pull request Oct 26, 2026
…e Lance reader

### What problem does this PR solve?

Issue Number: None

Related PR: apache#69581

Problem Summary:

BE configure runs `build-support/check-build-hygiene.sh`. Its reverse reach
budget caps how many TUs may transitively include `util/rle_encoding.h` at the
baseline 823 (master 9a48f81, 2026-08-18) plus 10%, that is 906. Master
9af1840 is at 903 (apache#69333 added the load table reader and its tests), and
the Lance reader adds the same four TUs that the `util/threadpool.h`
rebaseline in this PR counts (`format_v2/table/lance_reader.cpp`,
`format_v2/lance/lance_runtime_filter_helper.cpp` and their unit tests), so
configure on master plus this PR fails with "util/rle_encoding.h now reaches
907 TUs (baseline 823 +10% = 906)". Before apache#69333 the PR stayed under the
limit, which is why the earlier rebaseline only had to cover
`util/threadpool.h`.

The four TUs add no new edge. `exprs/vexpr_context.h` includes
`storage/segment/column_reader.h`, which includes
`storage/segment/parsed_page.h` -> `util/rle_encoding.h`, the path the other
format_v2 readers already take. As for `util/threadpool.h`, this rebaselines
`util/rle_encoding.h` to the measured 907 (limit 998) and records the reason
next to the entry; cutting the `vexpr_context.h` -> `column_reader.h` edge
stays the separate build cleanup and would lower both.

### Release note

None

### Check List (For Author)

- Test: No need to test: build configuration only.
  `bash build-support/check-build-hygiene.sh` passes on master 9af1840
  plus this PR.
- Behavior changed: No
- Does this need documentation: No

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
sollhui added a commit that referenced this pull request Oct 29, 2026
#69716)

### What problem does this PR solve?

Issue Number: None

Related PR: #69333

Problem Summary:

After CSV ingestion switched to FileScannerV2, `DelimitedTextReader`
opened remote files directly through `FileFactory`, bypassing the
sequential prefetch used by the original CSV reader. S3 reads therefore
block the scanner instead of overlapping remote I/O with CSV parsing.

Restore `DelegateReader::create_file_reader(SEQUENTIAL)` in the shared
CSV/Text reader, passing the shared IOContext and adjusted split range.
Unknown-size first splits use an end sentinel bounded by the physical
file size. Tracing remains outside the prefetch layer, and shared
stream-load pipes retain their existing ownership and cancellation
behavior.

To safely integrate asynchronous reads with V2 scanner statistics:
- Each prefetch buffer owns its cache statistics and an IOContext
snapshot. The consumer merges completed statistics exactly once before
consuming, reusing or closing the buffer. Workers never update the
scanner's cache-statistics object.
- Close drains active reads even after a foreground timeout, keeping
borrowed scanner state alive until I/O completes. Queued tasks observe
CLOSED and skip reading. Cleanup can consequently take longer than
`buffered_reader_read_timeout_ms` while an underlying request is
outstanding.
- The ring modulus uses allocated capacity: a 6 MiB setting allocates
one 4 MiB buffer and wraps at 4 MiB. Settings below 4 MiB use one
buffer; the 16 MiB default is unchanged.
- CSV/Text filesystem readers close before collecting prefetch profile
counters. Repeated close does not publish counters twice.

### Performance

For the TPC-H dataset load benchmark, elapsed time decreased from
**2617.33 s** to **1696.06 s**, saving **921.27 s**. This is a **35.2%
reduction in load time**, or approximately **1.54x speedup**, for the
measured workload.

| Dataset | Before | After | Load time reduction | Speedup |
| --- | ---: | ---: | ---: | ---: |
| TPC-H | 2617.33 s | 1696.06 s | 35.2% | 1.54x |

### Release note

Restore asynchronous S3 prefetch for FileScannerV2 CSV and text reads,
with safe cache-statistics aggregation and cleanup, consistent ring
capacity and populated prefetch profiles.

### Check List (For Author)

- Test:
- Added S3 mock coverage for whole-file, mid-row split and unknown-size
reads; checks row values, outer tracing, background S3 reads, prefetch
profile publication and repeated close.
- Added buffered-reader tests for four concurrent workers with isolated
cache statistics, partial consumption, slot reuse, unconsumed-buffer
collection, successful reads finishing after foreground timeout,
explicit close/destruction, and exact bytes across 0/1/6/10/16 MiB ring
settings from zero/nonzero offsets. Added a shared stream-pipe ownership
test.
- Passed Clang 16 syntax checking of the complete
`buffered_reader_test.cpp` translation unit against repository and
installed third-party headers with `-Werror -Wunused-member-function`.
- Passed repository clang-format 16 formatting/check scripts,
`build-support/check-build-hygiene.sh`, and `git diff --check`.
- Full BE build and runtime tests are **not verified locally**:
`./run-be-ut.sh --run --filter='BufferedReaderTest.*:CsvV2ReaderTest.*'
-j 8` stops at JDK initialization (`Failed setting boot class path`).
Separate production/CSV syntax attempts encounter installed C++ library
and stale generated-header incompatibilities. No compilation database is
available for clang-tidy. Runtime and sanitizer validation remain
pending CI.
- The S3 mock test disables file cache; the concurrent statistics test
exercises the actual prefetch implementation with a mock reader updating
`FileCacheStatistics`. No cached-S3 end-to-end runtime result is
claimed.
- TPC-H load benchmark: elapsed time decreased from 2617.33 s to 1696.06
s (35.2% less load time; approximately 1.54x speedup).

- Behavior changed:
- [x] Yes. Eligible S3 CSV/Text readers use sequential prefetch. Shared
prefetch readers isolate cache counters, drain outstanding reads during
cleanup and normalize ring capacity. CSV/Text publishes prefetch
profiles on close.

- Does this need documentation?
    - [x] No.

### Check List (For Reviewer who merge this PR)

- [ ] Confirm the release note
- [ ] Confirm test cases
- [ ] Confirm document
- [ ] Add branch pick label
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants