Skip to content

[improvement](be) Support Arrow loads and schema inference in FileScannerV2 - #69668

Merged
yiguolei merged 4 commits into
apache:masterfrom
Gabriel39:dev/file-scanner-v2-arrow-schema
Oct 28, 2026
Merged

yiguolei merged 4 commits into
apache:masterfrom
Gabriel39:dev/file-scanner-v2-arrow-schema

Conversation

@Gabriel39

@Gabriel39 Gabriel39 commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Arrow Stream Load still selects FileScanner V1, and CSV/TEXT/JSON schema discovery still constructs legacy readers even when the subsequent scan uses V2.

Add a native Arrow IPC FileReader to the V2 load path. It decodes record batches incrementally, supports concatenated streams and compressed IPC, uses tracked allocations, and retains load expressions, defaults, strict-mode checks, and WHERE filtering. Source timestamp units and timezones are preserved for Doris SerDe rounding, including nested values.

Stream Load plans explicitly set enable_file_scanner_v2=true in their query options because these plans construct options independently of query sessions.

Arrow binding preserves positional STRUCT children, DATE64 range validation, and unsigned IPv4 address bits. Before checked recursive casts, ancestor validity masks hide NULL-struct payloads and NULL-list/map ranges are compacted. Ordinary numeric overflow checks remain enabled.

A load-specific schema converter preserves native VARIANT carriers and extensions recursively, including SQL NULLs, and binds AGG_STATE through its actual serialization type. Fixed-length aggregate states use the serialization column's byte width; invalid binary lengths fail before SerDe materialization. Recursive NULL masking skips unchanged children and leaves incompatible container kinds to explicit cast errors.

Nullable fixed-size-list inputs are viewed through 64-bit variable offsets before compaction, so NULL parents drop complete child ranges without synthesizing NULLs in non-nullable STRUCT fields or native VARIANT carriers. DECIMALV2 retains decimal128 wire scales for its existing scale-nine rescaling and truncation rules; other decimal types retain checked conversions.

Keep the existing empty-file schema RPC diagnostics, including empty LZOP data and header-name versus inferred-column-number errors.

Route CSV, TEXT, and JSON schema discovery through V2 readers and the shared schema entry point, alongside the existing native Parquet/ORC readers. Preserve header handling, nullable string inference, JSON root/path options, and independent sampling of HTTP Stream Load data. Also avoid consuming a rooted JSON array's ondemand cursor before jsonpaths materialization.

Release note

Arrow Stream Load and CSV/TEXT/JSON schema discovery now use FileScanner V2 readers.

Check List (For Author)

  • Test

    • Regression test
    • Unit Test
    • Manual test
      • ASAN BE build and 221 focused unit tests passed, including scanner routing, native schema inference, Arrow IPC loading, and existing reader coverage. Focused cases cover positional STRUCT names, DATE64 range checks, unsigned IPv4, NULL container payloads, numeric overflow, native VARIANT storage/extensions, aggregate-state widths, incompatible container input, empty LZOP, NULL fixed-size lists with non-nullable descendants, and DECIMALV2 rescaling with DECIMALV3 rejection controls.
      • Six regression suites passed against a locally built FE/ASAN BE: Arrow Stream Load, V2 HTTP schema discovery, and existing JSON, compressed CSV, CSV-with-names, and CSV-with-names-and-types suites. Results were compared with expected output.
      • clang-format 16, changed-line clang-tidy, and build hygiene checks passed.
      • FE Checkstyle and the FE production build passed after adding the explicit Stream Load query option.
  • Behavior changed:

    • Yes. Arrow loads and text/JSON schema inference use native V2 readers.
  • Does this need documentation?

    • No. Existing load interfaces and options are retained.

Check List (For Reviewer who merge this PR)

  • Confirm the release note
  • Confirm test cases
  • Confirm document
  • Add branch pick label

@Gabriel39
Gabriel39 requested a review from yiguolei as a code owner October 27, 2026 05:48
@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.

Request changes for four Arrow load conversion defects: one P1 silently loses STRUCT child values, and three P2 issues bypass DATE64 range validation, reject valid unsigned IPv4 values, or reject NULL containers because of hidden child payloads. The inline comments give concrete inputs and the affected paths. No additional defect was found in the CSV/TEXT/JSON schema migration or the rooted JSON array cursor fix. There were no existing inline findings to retain and no additional user-provided focus points.

Static review covered all 20 changed files at head 0b7e509, the legacy readers, FE source-slot planning, table/load mapping, pipe producer/consumer lifecycle, source SerDes, sink validation, and the pinned Arrow 24 cast/IPC implementations.

Critical checkpoint conclusions:

  • Goal and evidence: native Arrow load dispatch and native text/JSON schema discovery are wired through the intended paths. Added unit/regression cases support their ordinary behavior, but omit the four conversion cases reported here.
  • Scope and clarity: the reader, routing, schema entry point, RPC simplification, and associated tests form a focused migration; no unrelated source change was identified.
  • Concurrency and locking: scanner state remains local; existing pipe mutex/condition-variable synchronization owns producer/consumer coordination and cancellation. IPC decompression stays on the scanner thread. No new lock order or worker thread was introduced.
  • Lifecycle and static initialization: arrays, batches, IPC reader and input are released before their Arrow memory pool; fallback profiles outlive schema readers and prefetch cleanup. No new cross-translation-unit static initialization dependency was found.
  • Configuration: no new configuration item or dynamic-update obligation.
  • Compatibility: the four findings concern external Arrow input compatibility and conversion semantics. No persisted format or function-symbol change requiring upgrade dispatch was introduced.
  • Thrift/protobuf field IDs: no definitions changed.
  • Parallel paths: legacy/new Arrow conversion, query connector Arrow dispatch, CSV/TEXT/JSON schema and normal scan paths, and shared cloud/non-cloud load plumbing were traced. Query connector dispatch remains separate from the plain load pipe.
  • Conditional checks: schema-only initialization, zero offsets, format dispatch, headers, sampling, and the ondemand cursor change have concrete reasons documented nearby. The generic Arrow binding needs the semantic exceptions identified inline.
  • Test coverage: additions cover stream concatenation/chunks, batch caps, nulls, dictionary/reordered fields, nested arrays, binary strings, compression, timestamp rounding, malformed/missing input, schema options, and load expressions/defaults/WHERE. Missing focused cases include the reported STRUCT/DATE64/IPv4/null-parent failures, live cancellation/backpressure, and multiple record batches within one stream.
  • Expected results: new regression rows are consistent with their fixture inputs and SQL. Their generation and runtime results were not independently verified or regenerated.
  • Observability: Arrow read/materialization timers, traced pipe I/O, scanned-row counters, schema error statuses, and existing scanner/load counters are retained. No new index/cache/virtual-column optimization was added.
  • Persistence and failover: no EditLog, snapshot/version, delete-bitmap, or transaction-persistence logic changed; visibility invariants are unaffected by the routing itself.
  • Data writes and atomicity: these readers feed the existing load transaction/commit path. No new atomicity or crash-cleanup mechanism was introduced, but conversion must be fixed to prevent incorrect data or rejected valid loads before that path.
  • FE/BE variable propagation: existing source tuple, format, attributes, range/load ID, compression, and filesystem metadata carry the change; no new transmitted variable was added.
  • Performance and memory: IPC buffers, normalization and casts use the Doris Arrow pool on the attached scanner task. Reading retains one IPC batch and caps output rows, avoiding the legacy all-batches accumulation; no benchmark was run. Schema discovery parses one sample and uses an independent schema pipe.
  • Other concerns and limits: all candidates and initial risk items have explicit dispositions in the ledger. This was static inspection only: no builds, tests, benchmarks, service execution, source edits, or submodule initialization were performed. Added test coverage does not establish runtime correctness for the reported cases.

Review converged after 2 round(s).

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17632	5220	5069	5069
q2	2136	298	242	242
q3	10280	1372	849	849
q4	4677	463	336	336
q5	7436	794	530	530
q6	184	186	155	155
q7	744	794	601	601
q8	9246	1350	1050	1050
q9	5423	4225	4191	4191
q10	6812	1273	1050	1050
q11	435	260	236	236
q12	630	399	294	294
q13	18079	3590	3044	3044
q14	274	270	249	249
q15	q16	713	715	654	654
q17	1169	735	573	573
q18	7057	6155	6110	6110
q19	1099	951	623	623
q20	382	357	240	240
q21	4936	2137	2299	2137
q22	347	292	256	256
Total cold run time: 99691 ms
Total hot run time: 28489 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	5586	5585	5594	5585
q2	670	595	562	562
q3	5177	5385	4908	4908
q4	2033	2139	1544	1544
q5	5268	5148	5465	5148
q6	252	196	157	157
q7	2321	2068	1857	1857
q8	3024	2730	2701	2701
q9	8042	7988	7948	7948
q10	3700	3895	3262	3262
q11	626	461	416	416
q12	678	728	512	512
q13	3580	3903	3339	3339
q14	334	329	293	293
q15	q16	702	719	659	659
q17	8252	7197	6894	6894
q18	13001	12121	12867	12121
q19	912	803	824	803
q20	2158	2132	1914	1914
q21	5591	4664	4704	4664
q22	495	473	419	419
Total cold run time: 72402 ms
Total hot run time: 65706 ms

…n FE

### What problem does this PR solve?

Keep STRUCT children bound by position when names differ, retain DATE64
validation and unsigned IPv4 storage, and mask logically hidden container
payloads before checked casts. Preserve ordinary numeric overflow checks.
Explicitly enable FileScannerV2 in FE-generated Stream Load query options.

### Release note

Preserve Arrow input conversion semantics in FileScannerV2 and explicitly
select V2 in Stream Load plans.

### Check List (For Author)

- Test: 183 ASAN unit tests, six regression suites, FE/BE production builds,
  FE Checkstyle, clang-format 16, clang-tidy, and build hygiene checks.
- Behavior changed: Correct Arrow edge-case conversion and set the V2 option
  explicitly in Stream Load plans.
- Does this need documentation? No; existing load interfaces are retained.
@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-DS: Total hot run time: 151266 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 0b7e509834b4c8f6d8899c5ec804a46e7619ea08, data reload: false

query5	4315	583	421	421
query6	428	207	195	195
query7	4791	451	218	218
query8	317	163	152	152
query9	8798	3109	3076	3076
query10	471	306	242	242
query11	6004	3896	3602	3602
query12	147	91	87	87
query13	1257	470	336	336
query14	6086	3960	3749	3749
query14_1	3456	3460	3418	3418
query15	209	201	181	181
query16	947	421	403	403
query17	863	669	551	551
query18	2409	410	302	302
query19	192	162	133	133
query20	85	81	82	81
query21	206	121	102	102
query22	13114	13172	12816	12816
query23	13433	13113	12555	12555
query23_1	12593	12453	12369	12369
query24	7344	822	455	455
query24_1	459	466	463	463
query25	523	398	331	331
query26	1270	252	136	136
query27	2758	435	276	276
query28	4617	1925	1914	1914
query29	1520	574	430	430
query30	291	224	184	184
query31	1011	922	816	816
query32	140	91	86	86
query33	506	284	236	236
query34	889	848	496	496
query35	725	743	639	639
query36	813	810	711	711
query37	124	103	77	77
query38	1771	1740	1691	1691
query39	806	805	750	750
query39_1	730	733	746	733
query40	212	117	98	98
query41	66	64	62	62
query42	88	115	78	78
query43	338	376	305	305
query44	1317	687	680	680
query45	205	184	165	165
query46	814	978	569	569
query47	3013	3016	2812	2812
query48	294	300	213	213
query49	564	395	293	293
query50	676	272	207	207
query51	10872	10656	10570	10570
query52	78	77	68	68
query53	183	208	148	148
query54	245	183	169	169
query55	71	69	66	66
query56	238	218	197	197
query57	1617	1645	1584	1584
query58	277	254	256	254
query59	2168	2110	2005	2005
query60	287	248	244	244
query61	152	143	144	143
query62	383	336	289	289
query63	184	159	159	159
query64	2742	942	843	843
query65	3360	3305	3291	3291
query66	1788	429	314	314
query67	20163	20260	20039	20039
query68	2954	1020	631	631
query69	396	285	260	260
query70	853	796	813	796
query71	301	243	225	225
query72	2858	2708	2435	2435
query73	505	526	297	297
query74	4648	4509	4363	4363
query75	2319	2274	1890	1890
query76	2319	1018	594	594
query77	342	377	264	264
query78	9875	9770	9138	9138
query79	975	848	519	519
query80	662	414	357	357
query81	544	318	275	275
query82	571	131	101	101
query83	265	214	195	195
query84	328	126	99	99
query85	868	417	362	362
query86	322	236	231	231
query87	2008	1927	1795	1795
query88	3634	2709	2664	2664
query89	337	277	240	240
query90	1809	174	167	167
query91	160	191	124	124
query92	99	81	87	81
query93	1027	1018	576	576
query94	461	302	261	261
query95	567	390	302	302
query96	677	483	245	245
query97	2427	2444	2310	2310
query98	158	151	149	149
query99	772	753	644	644
Total cold run time: 234582 ms
Total hot run time: 151266 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.

Static review of head 4df2737: one new P2 finding, reported inline. The new reader derives load bindings from an ordinary Arrow output schema, breaking native VARIANT carriers and fixed-size aggregate-state inputs. Both are manifestations of the same input/output contract mismatch and are combined in one comment.

The four existing findings were independently revalidated against this head: STRUCT child identity (4385605392), DATE64 range validation (4385605398), unsigned IPv4 storage (4385605401), and hidden children under NULL containers (4385605407) are addressed by the current branches and focused test cases. No existing P0/P1 finding was confirmed to remain applicable; none is reposted.

Critical checkpoint conclusions:

  1. Goal and proof: Arrow loads and CSV/TEXT/JSON schema discovery reach V2 through the intended reader layers; the specialized input regression prevents full compatibility. Added unit/regression sources cover ordinary loading and schema discovery, but omit the reported carriers.
  2. Scope and reuse: changes are focused and reuse LoadTableReader, MaterializedColumnMapper, schema dispatch, shared parsing, SerDes and profile utilities.
  3. Concurrency and locks: no new threads or lock order; existing load-pipe synchronization remains authoritative. IPC decompression stays on the scanner thread, and schema RPC work retains its attached memory tracker.
  4. Lifecycle/static initialization: arrays, IPC readers and input streams are released before their Arrow pool; schema profiles/state outlive reader cleanup. No new cross-TU initialization dependency was found.
  5. Configuration: no new configuration item; Stream Load explicitly sets the existing scanner query option. Load selection still uses the supported-format switch.
  6. Compatibility: the reported native/serialized input regression needs correction. No new persisted format or function ABI is introduced; existing query connector routing is retained.
  7. Thrift/Protobuf IDs: no definition changes, new IDs or required fields.
  8. Parallel paths: cloud planning inherits the parent planner; query connectors, legacy comparisons, HTTP sampling and each text/JSON schema branch were traced.
  9. Conditional paths: timestamp/date/IP exceptions, positional STRUCT binding, ancestor NULL masks, header probing and zero-slot OpenCSV handling have concrete purposes; no additional conditional defect was substantiated.
  10. Test coverage: sources cover concatenated/empty IPC streams, small batches, compression, dictionaries, nested nulls, timestamps, overflow, load expressions/defaults/WHERE, schema headers/BOM/UTF-8, JSON roots/paths and malformed input. Native VARIANT and fixed-size aggregate-state load cases are missing.
  11. Expected results: modified output rows agree with the supplied fixtures and deterministic ordering. Output generation and execution were not independently verified.
  12. Observability: reader read/materialization timers and common IO/row counters remain available; no additional observability defect was found.
  13. Persistence/failover: no EditLog, metadata replay, visible-version, delete-bitmap or publish protocol change.
  14. Writes/atomicity: decoding still feeds existing load conversion, rejection and sink transaction boundaries; the reported cases fail before successful load completion. No new commit or crash-recovery protocol is introduced.
  15. FE/BE passing: the existing enable_file_scanner_v2 option is explicitly set; no new transmitted variable or schema field requires additional send paths.
  16. Performance/memory: IPC processing retains one record batch rather than all batches in a stream; Arrow buffers use the tracked pool. No additional concrete performance regression was substantiated; throughput and peak memory were not measured.
  17. Other concerns: final review of all changed paths, candidates and risk items found no further verified issue. No extra user focus was supplied.

Review converged in 2 rounds after complete assigned coverage and final validation; no unresolved code candidate or changed-path coverage gap remains. Validation was static only: no builds, tests, ASAN, formatting/static-analysis tools, benchmarks or runtime reproductions were run. Multi-batch single-stream cancellation behavior, external-writer interoperability and measured performance remain execution limits, not validated results.

Review converged after 2 round(s).

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17618	5245	5090	5090
q2	2133	313	252	252
q3	10252	1416	831	831
q4	4677	468	339	339
q5	7426	793	533	533
q6	180	183	156	156
q7	753	784	613	613
q8	9253	1412	1084	1084
q9	5761	4232	4191	4191
q10	6831	1284	1041	1041
q11	441	247	219	219
q12	639	402	287	287
q13	18073	3607	3056	3056
q14	275	272	245	245
q15	q16	735	712	651	651
q17	1202	752	570	570
q18	6974	6183	6120	6120
q19	1114	973	581	581
q20	375	336	221	221
q21	4572	2149	2267	2149
q22	347	295	263	263
Total cold run time: 99631 ms
Total hot run time: 28492 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	5650	5633	5628	5628
q2	694	589	532	532
q3	5243	5396	4962	4962
q4	1996	2191	1580	1580
q5	5298	5191	5580	5191
q6	246	190	152	152
q7	2391	2061	1881	1881
q8	3078	2736	2750	2736
q9	7985	8069	7894	7894
q10	3720	3889	3235	3235
q11	657	470	426	426
q12	711	687	545	545
q13	3627	3944	3401	3401
q14	322	326	288	288
q15	q16	670	734	652	652
q17	8246	7028	6861	6861
q18	13050	12201	12922	12201
q19	978	828	828	828
q20	2160	2139	1926	1926
q21	5601	4809	4814	4809
q22	492	485	403	403
Total cold run time: 72815 ms
Total hot run time: 66131 ms

### What problem does this PR solve?

Native VARIANT carriers were rebound to UTF-8 and serialized fixed-length
AGG_STATE values lacked an Arrow input mapping. Add a dedicated input schema
converter, retain native carriers recursively, and derive fixed-state widths
from the actual serialization column. Mask only child subtrees requiring
conversion and return explicit errors for incompatible input containers.

Restore existing empty-file schema RPC diagnostics for plain and compressed
CSV inputs, including header-name versus inferred-column-number errors.

### Release note

Preserve native VARIANT and aggregate states during Arrow Stream Load and
retain existing empty-file schema discovery errors.

### Check List (For Author)

- Test: 212 ASAN BE unit tests, six regression suites, BE production build,
  clang-format 16, changed-line clang-tidy, and build hygiene checks.
- Behavior changed: Native Arrow values load using their input storage
  contracts; empty compressed files retain existing schema errors.
- Does this need documentation? No; existing load interfaces are retained.
@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-DS: Total hot run time: 150631 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 4df2737ba062913e3c0630f9eec96f031f9c3ebd, data reload: false

query5	4322	583	461	461
query6	415	210	204	204
query7	4815	437	229	229
query8	327	170	146	146
query9	8792	3089	3100	3089
query10	478	307	243	243
query11	6042	3840	3549	3549
query12	142	91	87	87
query13	1246	443	324	324
query14	6109	3949	3615	3615
query14_1	3443	3649	3393	3393
query15	209	197	181	181
query16	951	426	356	356
query17	818	628	511	511
query18	2413	412	295	295
query19	182	153	124	124
query20	84	79	78	78
query21	200	126	104	104
query22	13048	12989	12737	12737
query23	13537	12707	12520	12520
query23_1	12504	12636	12560	12560
query24	7359	808	446	446
query24_1	456	458	455	455
query25	502	392	325	325
query26	1268	256	140	140
query27	2745	432	268	268
query28	4612	1947	1964	1947
query29	1558	584	440	440
query30	301	221	192	192
query31	1016	927	872	872
query32	136	92	90	90
query33	524	291	235	235
query34	873	834	503	503
query35	732	744	635	635
query36	813	803	734	734
query37	119	101	77	77
query38	1768	1724	1672	1672
query39	788	791	734	734
query39_1	739	715	727	715
query40	213	122	93	93
query41	64	61	60	60
query42	85	82	80	80
query43	339	363	305	305
query44	1298	689	717	689
query45	179	171	167	167
query46	834	961	552	552
query47	2764	2891	2633	2633
query48	305	300	221	221
query49	579	392	288	288
query50	671	275	211	211
query51	10530	10550	10682	10550
query52	79	79	68	68
query53	186	204	148	148
query54	232	201	193	193
query55	75	76	64	64
query56	233	208	219	208
query57	1681	1596	1623	1596
query58	285	262	254	254
query59	2153	2182	1967	1967
query60	292	243	227	227
query61	145	144	142	142
query62	381	327	284	284
query63	181	157	163	157
query64	2715	916	740	740
query65	3318	3263	3253	3253
query66	1782	422	308	308
query67	20098	20199	19712	19712
query68	2949	1000	619	619
query69	384	281	250	250
query70	831	794	763	763
query71	286	228	219	219
query72	2640	2572	2431	2431
query73	520	524	296	296
query74	4634	4551	4363	4363
query75	2328	2299	1940	1940
query76	2318	1012	591	591
query77	354	382	289	289
query78	9646	9694	9148	9148
query79	986	836	529	529
query80	676	477	366	366
query81	535	324	275	275
query82	569	134	103	103
query83	273	206	193	193
query84	314	129	106	106
query85	900	485	437	437
query86	318	243	232	232
query87	2006	1943	1796	1796
query88	3638	2709	2679	2679
query89	336	291	243	243
query90	1853	174	222	174
query91	159	147	126	126
query92	100	81	91	81
query93	1045	995	577	577
query94	455	304	266	266
query95	583	351	386	351
query96	655	473	235	235
query97	2467	2427	2335	2335
query98	163	156	157	156
query99	763	758	652	652
Total cold run time: 233573 ms
Total hot run time: 150631 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.

Static review of d7bd729 found two P2 Arrow input-compatibility regressions: NULL fixed-size-list masking synthesizes invalid non-nullable STRUCT descendants, and safe decimal rebinding bypasses the existing DECIMALV2 scale-conversion contract. Both are posted inline.

The five earlier findings were independently revalidated. Their original STRUCT-name, DATE64-range, unsigned-IPv4, hidden-overflow, and native-VARIANT/count-state reproductions are addressed at this head. No existing P0/P1 finding remains applicable; no duplicate comments were added. The new fixed-size-list issue arises in the added masking implementation with valid, in-range source payloads. No additional user review focus was supplied.

End-to-end paths reviewed:

FE typed load slots -> FileScannerV2 -> LoadTableReader -> ArrowStreamReader
  -> encoding normalization/binding/masking -> SerDe -> load expressions/defaults/strict checks -> sink
Schema RPC -> fetch_file_schema -> V2 CSV/TEXT/JSON probe
  -> file or independent schema-sample pipe -> nullable-string schema -> FE planning

Critical checkpoint conclusions:

  • Goal and evidence: Arrow load dispatch and V2 text/JSON schema discovery are implemented; focused unit/regression sources cover the main flows. The two inline cases remain uncovered.
  • Scope and reuse: the change is focused on reader migration, reuses the shared mapper/load materializer and tracked Arrow pool, and keeps physical decoding within the file reader.
  • Concurrency and locking: IPC decompression stays on the existing scanner thread; schema RPCs use the existing heavy-work pool. Existing pipe locks/cancellation remain in place; no new thread or lock order was introduced.
  • Lifecycle and static initialization: IPC batches/readers are released before the owned memory pool; probe readers are destroyed while params/state/profile/statistics remain alive. No new cross-translation-unit static dependency was found.
  • Configuration: no new configuration item; the existing scanner option is explicitly set on stream-load plans. Load scanner selection remains format-driven.
  • Compatibility: original accepted input representations, nested field identity, timestamps, DATE64, IPv4 and specialized serialization were traced. The inline findings identify remaining compatibility changes. No stored format or public protocol definition changes.
  • Thrift/protobuf IDs: no gensrc changes, so branch field-ID comparison is inapplicable.
  • Parallel paths: query Arrow connectors retain their existing dispatch, cloud planning delegates to the changed superclass, and legacy CSV/TEXT/JSON probing was compared with the new probes.
  • Special conditions: schema-only/no-slot inference, header preservation, zero-offset/broker checks, sample-pipe selection, and container-kind guards have concrete purposes. Fixed-size-list masking has the inline defect.
  • Test coverage: inspected routing, chunked/concatenated/compressed IPC, batch boundaries, nulls, nested fields, timestamps, native VARIANT, aggregate states, malformed IPC, schema headers/UTF-8, JSON root/paths, empty LZOP and sample isolation cases. Added tests do not cover the two inline inputs.
  • Expected results: new ordered HTTP-schema rows and Arrow expression/default/filter output match the fixture logic on inspection. Test execution and result-file generation provenance were not independently verified.
  • Observability: Arrow read/materialization timers and existing I/O/row statistics remain available; errors include the relevant column or parsing context. No new per-row logging was introduced.
  • Persistence, visibility and failover: no changed journal, commit/publish protocol, visible-version or delete-bitmap logic. Schema sampling uses an independent pipe and preserves the live load input.
  • Writes, atomicity and crashes: materialization feeds the existing transactional sink; conversion errors propagate through existing Status/exception boundaries. No new partial-commit or ownership leak was identified.
  • FE/BE variables: only an existing query-option field is stamped; existing source tuples, range metadata and load IDs carry the reader contract. No new field requires additional send paths.
  • Performance and memory: record batches replace whole-stream accumulation, major IPC/conversion buffers use the tracked pool, and decompression avoids untracked worker execution. Schema probing remains proportional to the first record/document. No performance benchmark was run.
  • Additional correctness: nullable/container/serialized representations and errors were traced through SerDes and load checks. Common-reader review found no new index, condition-cache, delete-pushdown or virtual-column semantics in these paths.

Coverage is complete for the 22 changed paths and the four recorded risk focuses. This was static inspection only: no build, test, benchmark, cluster execution or source modification was performed. Real remote-filesystem behavior, cancellation timing and rolling-version execution remain unexecuted validation limits; there are no unresolved code candidates.

Review converged after 2 round(s).

### What problem does this PR solve?

Related PR: apache#69668

Problem Summary: Taking nullable indices from a fixed-size list synthesized NULL descendants
under non-nullable STRUCT fields. View NULL fixed lists with 64-bit variable
offsets before compaction so hidden child ranges are dropped as a whole,
while valid child fields and native VARIANT carriers remain unchanged.

Preserve decimal128 wire scales for DECIMALV2 input so its existing SerDe
can truncate extra fractional digits or expand lower scales to nine. Other
decimal types retain safe Arrow scale checks.

### Release note

Restore accepted Arrow loads containing NULL fixed-size lists with
non-nullable descendants and DECIMALV2 values requiring scale conversion.

### Check List (For Author)

- Test: 221 ASAN BE unit tests, six regression suites, production BE build,
  clang-format 16, clang-tidy, and build hygiene checks.
- Behavior changed: Preserve existing input semantics for NULL fixed lists
  and DECIMALV2 rescaling without weakening other numeric conversions.
- Does this need documentation? No; existing load interfaces are retained.
@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: 28789 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit d7bd729aded92c8adf45faa6fd7076d6f2a087cc, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17599	5119	5037	5037
q2	2115	355	264	264
q3	10197	1389	836	836
q4	4681	473	337	337
q5	7436	800	527	527
q6	183	185	149	149
q7	754	795	598	598
q8	9258	1267	1015	1015
q9	5494	4204	4189	4189
q10	6860	1286	1027	1027
q11	450	257	231	231
q12	639	408	281	281
q13	18180	3698	3054	3054
q14	275	269	245	245
q15	q16	748	705	671	671
q17	1225	748	593	593
q18	7047	6212	6122	6122
q19	1121	969	631	631
q20	392	345	232	232
q21	5647	2545	2479	2479
q22	387	314	271	271
Total cold run time: 100688 ms
Total hot run time: 28789 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	5983	5958	6083	5958
q2	738	607	599	599
q3	5681	5718	5327	5327
q4	2003	2167	1568	1568
q5	5848	5810	5679	5679
q6	243	188	153	153
q7	2253	2046	1762	1762
q8	2973	2729	2706	2706
q9	7922	7616	7528	7528
q10	3607	3573	3147	3147
q11	577	406	386	386
q12	659	677	508	508
q13	3332	3593	3008	3008
q14	282	281	262	262
q15	q16	668	687	609	609
q17	7722	7030	6889	6889
q18	12955	12191	12899	12191
q19	909	801	777	777
q20	2143	2152	1932	1932
q21	5640	4594	4674	4594
q22	495	434	411	411
Total cold run time: 72633 ms
Total hot run time: 65994 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.

Static review of all 22 changed files at 213c279 found no new actionable defect. Two complete-scope reviewers and a separate recursive Arrow binding reviewer returned NO_NEW_VALUABLE_FINDINGS. All initial risk items are disposed of; no unresolved code question remains.

The seven existing findings were independently revalidated. P1 comment 4385605392 is fixed: recursive STRUCT binding preserves wire names while binding children by position. The existing P2 instances concerning DATE64 validation, unsigned IPv4, hidden NULL-container payloads, native VARIANT/AGG_STATE storage, fixed-list non-nullable descendants, and DECIMALV2 rescaling also have corresponding fixes and focused tests. None is reposted; no existing P0/P1 finding remains applicable to this head.

Critical checkpoint conclusions:

  1. Goal: Arrow stream loads and CSV/TEXT/JSON schema discovery use the intended V2 paths. Added unit and regression source covers those paths; execution was not independently verified.
  2. Scope and reuse: reader changes stay within routing, physical decoding/schema discovery and load options. Existing mapping and LoadTableReader conversion/default/filter accounting are reused.
  3. Concurrency and locks: existing pipe producer/consumer synchronization and cancellation wakeups are retained. No new thread or lock order is introduced; IPC decompression runs on the attached scanner thread.
  4. Lifecycle: the Arrow pool outlives its buffers; close releases Arrow owners first. Schema readers are destroyed before their temporary RuntimeState, scan parameters and profile. No new static initialization dependency was found.
  5. Configuration: no new configuration is defined. The FE sets the existing V2 option explicitly on independently constructed load options.
  6. Compatibility: no persisted storage format or function ABI changes. Reviewed recursive type binding, source timestamp units/timezones, positional children, specialized storage and NULL handling against downstream SerDes.
  7. Thrift/protobuf IDs: no definitions are changed, so a cross-branch field-ID audit is inapplicable.
  8. Parallel paths: connector Arrow query dispatch and capability guards remain intact; ordinary Arrow loads use the load adapter. Parquet/ORC schema paths remain available.
  9. Special conditions: comments explain the concrete binding exceptions, NULL-range compaction, slotless OpenCSV probing and retained empty/header diagnostics. Invalid conversions return errors.
  10. Tests: inspected chunked/compressed/concatenated IPC, batch boundaries, dictionaries, nested/specialized values, overflow, malformed/missing/empty input, schema headers/encoding/root/path options and independent HTTP sampling. Regression coverage includes expressions, defaults, strict mode and WHERE accounting.
  11. Expected results: changed output rows agree with the input and SQL, including id=2, EV=3.5, doubled=4 and tag=loaded. Generation provenance and passing test runs were not independently established.
  12. Observability: read/materialization timers, traced I/O and scan-row statistics use the existing profile hierarchy. No additional logging/metric defect was substantiated.
  13. Transactions and persistence: EditLog, publish, failover, visible versions and delete-bitmap handling are outside the changed path.
  14. Writes and atomicity: destination sink/commit behavior is unchanged; decoder and conversion failures propagate through Status or the scanner exception boundary.
  15. FE-to-BE values: existing source/destination slots, expressions, load IDs and schema RPC fields are reused. No new transmitted variable or omitted send path was identified.
  16. Performance and memory: IPC retains one record batch, reuses its conversions across bounded output slices and uses the tracked Arrow pool. No substantiated performance regression was found; no benchmark was run.
  17. Other concerns and focus: no additional user focus was supplied. The final sweep found no further issue in the complete changed-file scope.

Validation limits: this invocation performed static source/test inspection only. It did not build Doris, run tests, execute ASAN, benchmark, regenerate outputs or perform live interoperability validation.

Review converged after 1 round(s).

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17603	5082	5068	5068
q2	2123	314	286	286
q3	10208	1477	838	838
q4	4676	461	340	340
q5	7444	797	532	532
q6	180	187	158	158
q7	771	796	599	599
q8	9267	1312	1054	1054
q9	5474	4217	4197	4197
q10	6842	1282	1025	1025
q11	431	251	231	231
q12	641	401	281	281
q13	18112	3719	3035	3035
q14	279	262	248	248
q15	q16	724	715	666	666
q17	1202	747	585	585
q18	7149	6165	6125	6125
q19	1110	970	595	595
q20	375	342	237	237
q21	4872	2115	2274	2115
q22	351	299	253	253
Total cold run time: 99834 ms
Total hot run time: 28468 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	5594	5614	5591	5591
q2	677	611	514	514
q3	5232	5436	4955	4955
q4	2012	2142	1540	1540
q5	5310	5176	5696	5176
q6	316	203	157	157
q7	2361	2130	1926	1926
q8	3183	2931	2689	2689
q9	8126	8094	8135	8094
q10	3712	3635	3234	3234
q11	628	439	407	407
q12	713	696	537	537
q13	3644	3890	3204	3204
q14	323	314	292	292
q15	q16	718	716	688	688
q17	8340	7554	6862	6862
q18	12975	12244	12897	12244
q19	895	780	770	770
q20	2154	2127	1962	1962
q21	5648	4585	4707	4585
q22	493	448	411	411
Total cold run time: 73054 ms
Total hot run time: 65838 ms

@hello-stephen

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

query5	4304	559	468	468
query6	440	211	192	192
query7	4803	445	229	229
query8	323	167	157	157
query9	8765	3125	3147	3125
query10	475	315	248	248
query11	6031	3866	3557	3557
query12	147	90	90	90
query13	1263	446	338	338
query14	6155	3918	3630	3630
query14_1	3450	3381	3423	3381
query15	207	195	173	173
query16	926	451	397	397
query17	830	693	517	517
query18	2412	418	303	303
query19	192	166	127	127
query20	88	84	83	83
query21	210	124	104	104
query22	12914	13056	12833	12833
query23	13506	12765	12533	12533
query23_1	12660	12616	12577	12577
query24	7339	799	461	461
query24_1	466	481	461	461
query25	509	406	343	343
query26	1249	261	138	138
query27	2785	443	268	268
query28	4610	1942	1942	1942
query29	1569	592	430	430
query30	296	223	187	187
query31	1007	935	827	827
query32	162	98	95	95
query33	526	317	254	254
query34	894	842	505	505
query35	734	753	669	669
query36	846	852	748	748
query37	125	108	87	87
query38	1788	1767	1650	1650
query39	794	784	739	739
query39_1	740	723	743	723
query40	230	135	99	99
query41	72	70	71	70
query42	93	87	84	84
query43	350	364	321	321
query44	1289	703	718	703
query45	181	185	162	162
query46	818	970	592	592
query47	2945	2879	2657	2657
query48	297	310	227	227
query49	581	407	300	300
query50	695	275	217	217
query51	10644	10626	10385	10385
query52	84	82	73	73
query53	194	216	157	157
query54	246	225	193	193
query55	76	69	69	69
query56	249	232	220	220
query57	1674	1627	1557	1557
query58	305	286	271	271
query59	2183	2189	2044	2044
query60	310	258	244	244
query61	170	171	177	171
query62	386	355	287	287
query63	189	163	165	163
query64	2901	1022	799	799
query65	3328	3282	3258	3258
query66	1790	415	305	305
query67	19969	20071	20092	20071
query68	3228	997	634	634
query69	386	285	246	246
query70	915	773	745	745
query71	297	222	208	208
query72	2817	2617	2367	2367
query73	529	515	293	293
query74	4637	4541	4380	4380
query75	2365	2308	1926	1926
query76	2398	1035	595	595
query77	352	384	281	281
query78	9950	9690	9196	9196
query79	978	836	520	520
query80	1219	441	363	363
query81	596	320	280	280
query82	738	133	104	104
query83	308	195	182	182
query84	324	120	102	102
query85	861	426	380	380
query86	398	247	235	235
query87	2012	1933	1799	1799
query88	3718	2682	2650	2650
query89	328	284	243	243
query90	1928	177	167	167
query91	168	163	143	143
query92	98	94	95	94
query93	1063	991	582	582
query94	627	323	272	272
query95	581	345	375	345
query96	658	483	241	241
query97	2466	2437	2306	2306
query98	166	151	148	148
query99	775	761	653	653
Total cold run time: 236379 ms
Total hot run time: 151324 ms

@hello-stephen

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

query1	0.00	0.00	0.00
query2	0.09	0.05	0.05
query3	0.26	0.08	0.08
query4	1.61	0.10	0.10
query5	0.23	0.25	0.24
query6	1.18	0.68	0.68
query7	0.04	0.01	0.01
query8	0.05	0.04	0.04
query9	0.39	0.36	0.34
query10	0.57	0.55	0.57
query11	0.21	0.14	0.15
query12	0.18	0.16	0.15
query13	0.49	0.49	0.50
query14	1.04	1.03	1.01
query15	0.63	0.61	0.60
query16	0.35	0.36	0.34
query17	1.19	1.15	1.14
query18	0.20	0.20	0.20
query19	2.11	2.02	2.00
query20	0.03	0.02	0.02
query21	15.48	0.20	0.14
query22	4.88	0.06	0.05
query23	16.30	0.32	0.13
query24	3.08	0.59	0.39
query25	0.11	0.06	0.05
query26	1.39	0.21	0.17
query27	0.05	0.04	0.04
query28	3.66	0.78	0.38
query29	12.49	4.19	3.25
query30	0.29	0.13	0.10
query31	2.77	0.56	0.32
query32	3.23	0.60	0.51
query33	3.13	3.28	3.23
query34	15.26	4.03	3.44
query35	3.36	3.33	3.37
query36	0.54	0.48	0.45
query37	0.10	0.06	0.07
query38	0.05	0.04	0.03
query39	0.03	0.04	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.03
Total cold run time: 97.39 s
Total hot run time: 24.51 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 0.00% (0/7) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 67.05% (32338/48228)
Line Coverage 51.90% (342330/659651)
Region Coverage 47.32% (278134/587802)
Branch Coverage 49.01% (131186/267670)

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 100.00% (7/7) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 77.44% (36190/46732)
Line Coverage 62.66% (408936/652616)
Region Coverage 59.09% (346099/585674)
Branch Coverage 60.01% (160231/267018)

@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 0.16% (1/621) 🎉
Increment coverage report
Complete coverage report

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 100.00% (7/7) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 77.44% (36190/46732)
Line Coverage 62.66% (408936/652616)
Region Coverage 59.09% (346099/585674)
Branch Coverage 60.01% (160231/267018)

@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 0.16% (1/621) 🎉
Increment coverage report
Complete coverage report

@yiguolei
yiguolei merged commit 7865646 into apache:master Oct 28, 2026
47 checks passed
Gabriel39 added a commit to Gabriel39/incubator-doris that referenced this pull request Oct 29, 2026
File scans still maintain the legacy scanner, its readers and a second capability/routing matrix. Route all file scans, file loads and external row-ID fetches through `FileScannerV2`, and remove the unused V1 implementation and tests.

- Keep `enable_file_scanner_v2` as a deprecated compatibility variable. Its stored value no longer affects planning or scanning; FE sends `true` in the existing Thrift field for older backends.
- Remove scanner-level capability checks. Factories and concrete readers return errors for unsupported operations, including native Hudi delta-log reads, query-only connector loads and Remote Doris Variant reads.
- Move standalone Iceberg position-delete reads to V2 `TableReader`, and historical Push ingestion to `LoadTableReader`. Preserve Push conversion expressions across ranges and compatibility with requests that omit the file-column count.
- Retain shared writer, metadata, JDBC/JNI and Elasticsearch HTTP components that surviving readers still use. Remove V1-only schema, partition, count and decoder infrastructure.
- Update connector planning, nullable COUNT pushdown, documentation and compatibility regression expectations.

Related PR: apache#69668

File scans always use FileScannerV2. `enable_file_scanner_v2` is deprecated and has no effect. Unsupported reader operations return an error instead of selecting the legacy scanner.

- Test
    - [x] Unit Test
    - [x] Regression test
    - [x] Manual test

Validation:
- Production BE and FE build, including connector plugin packages.
- 523 focused FE tests and FE Checkstyle.
- 593 distinct BE tests; the Remote Doris Flight suite was rerun successfully with localhost excluded from the development proxy.
- clang-format 16, clang-tidy on changed lines, build hygiene and its full self-test suite.
- Final Push fixture rerun passed after the test-data helper cleanup.
- Six standalone regression suites passed: Arrow Stream Load, HTTP CSV/JSON/compression/header formats and schema inference.
- Manual SQL verified that setting the old option to false remains accepted and SHOW VARIABLES marks it deprecated.

External Paimon regression expectations are updated for the no-op option and will be exercised by the external CI environment.

The exhaustive CSV/JSON split tests retain their existing boundary assertions after dropping the V1 parameterization. Four narrow cognitive-complexity suppressions preserve these existing GTest-expanded cross-product tests; new tests are decomposed instead.

- Behavior changed:
    - [x] Yes. The scanner option is now a deprecated no-op; unsupported operations fail in their reader.
- Does this need documentation?
    - [x] Yes. The scanner design and review guide are updated in this PR.

- [ ] Confirm the release note
- [ ] Confirm test cases
- [ ] Confirm document
- [ ] Add branch pick label
Gabriel39 added a commit to Gabriel39/incubator-doris that referenced this pull request Oct 29, 2026
Apply the outstanding changes in master merge order:
apache#69545 7d16729
apache#69551 7224a2d
apache#69612 61d1aef
apache#69615 8d2bd1e
apache#69650 3dc7341
apache#69651 c00ecb1
apache#69646 e493c61
apache#69668 7865646

apache#69614 already exists on branch-4.2 through apache#69644.
Adapt datasource APIs and tests to the release branch, retaining its
existing scanner dispatch and statement-bound metadata contracts.
yiguolei pushed a commit that referenced this pull request Oct 30, 2026
### What problem does this PR solve?

Backport the requested external-data and FileScannerV2 changes to
`branch-4.2` in their actual master merge order:

| Order | Master PR | Change | Backport |
| --- | --- | --- | --- |
| 1 | #69545 | Preserve Paimon schema options after field renames |
Included |
| 2 | #69551 | Expand Iceberg capability, transaction and snapshot tests
| Included with 4.2 API adaptations |
| 3 | #69614 | Elasticsearch HTTP scans in FileScannerV2 | Already
present through #69644 (`2104b7509cda`); not applied twice |
| 4 | #69612 | Check catalog visibility before SHOW DATABASES accesses
metadata | Included |
| 5 | #69615 | Publish Iceberg Parquet split offsets | Included |
| 6 | #69650 | Preserve ES compound residuals and expand scanner
coverage | Included |
| 7 | #69651 | Accept Elasticsearch 9.x during node discovery | Included
|
| 8 | #69646 | Prioritize Parquet V2 row groups using TopN bounds |
Included |
| 9 | #69668 | Arrow loads and schema inference in FileScannerV2 |
Included |

The eight outstanding changes are combined in one commit. This branch
retains the 4.2 FE datasource APIs instead of importing master's
connector-module refactor.

### Backport adaptations

- Port Paimon schema restoration, catalog-option provenance, fallback
handling and tests to the existing table-copy/serialization lifecycle.
Keep statement-bound fields when reader options are applied after a
schema-only rename.
- Exercise Iceberg's existing metadata and transaction entry points with
real in-memory tables and retained-generation fixtures. Preserve the
nine disabled known-bug reproductions; omit two connector-only lifecycle
tests. Expiration checks verify live data-file sets and exact
delete-file counters; 4.2's separate manifest-name/data-counter issue
remains unchanged. The delete/history SQL suite checks visible rows and
eager/late-materialization parity because 4.2 does not expose master's
`_file`/`_pos` columns. The inventory labels upstream-only evidence
explicitly.
- Port ES residual tracking to the legacy planner and add compound
OR/NOT, docvalue eligibility and Thrift-context tests there. Use Java
8-compatible HTTP APIs for opt-in ES 9 tests and the branch's supported
node-address fixtures.
- Keep the existing full-schema Iceberg metadata-table scan, which
already supplies the file-size dependency for split offsets. Adapt the
external write suite to verify offsets without requiring master-only
distribution plans or golden output.
- Use the existing Parquet statistics interface and physical
row-location representation. Keep the TopN scheduling and pruning
invariants.
- Include the shared Arrow array normalizer required by the new reader,
taken from the same master revision. Preserve 4.2 Lance/Avro dispatch;
omit the schema-inference test for the unavailable Hive OpenCSV parser.

### Validation

- FE production and test sources compile with the branch's Java 8
target. Across the targeted runs and focused reruns, 20 test classes
report 181 discovered, 171 passed, zero failures/errors, and 10 skipped:
nine intentionally disabled known-bug reproductions plus the opt-in live
ES 9 class.
- FE Checkstyle: passed with zero violations.
- Clang compiler syntax checks: all 23 affected C++ translation units
passed against the current sources and freshly generated Thrift, using
cached third-party/generated build dependencies. Focused BE runtime
validation is listed below.
- clang-format 16: all 30 affected C++ source/header files passed.
- Groovy 4.0.19 syntax and AST conversion: all seven changed suites
passed. All 105 local inventory links resolve.
- Complete staged-diff self-review, whitespace/conflict checks, and
sensitive-information checks passed.

A full BE rebuild and SQL/external-service regressions were not run
locally. Live ES 9 tests require their opt-in endpoint. CI is requested
for the combined backport.

### Release note

Fix Paimon reads after field renames, external-catalog SHOW DATABASES
authorization, and ES compound residual filtering. Support ES 9.x node
discovery, publish Iceberg Parquet split offsets, improve Parquet V2
TopN row-group scheduling, and use FileScannerV2 for Arrow loads and
text/JSON schema inference.

### Check List (For Author)

- Test
    - [x] Unit Test
- [x] Regression test additions and syntax checks; SQL execution pending
CI
- Behavior changed:
    - [x] Yes. Backport the changes listed above.
- Does this need documentation?
- [x] No. Existing interfaces and settings are retained; the test
coverage inventory is included.

### Follow-up fixes

- Set the Thrift `enable_file_scanner_v2` default to `true`, matching
the session default. Preserve explicit `false` for legacy query scans
and extend the existing load-selection test.
- Keep the selected Paimon snapshot and schema together during relation
projection. Historical sequence/aggregation options must not be combined
with the latest field names. Read-only principals can resolve historical
selectors without INSERT permission.
- Read legacy append schemas with missing or empty bucket keys without
bucket pruning, preserving every historical file. The regression covers
both unaware and multiple fixed buckets.

Follow-up validation: 169 targeted Paimon FE tests passed with zero
failures/errors/skips. FE production compilation and Checkstyle passed.
Both changed C++ test translation units passed compiler syntax checks
and clang-format 16. Regenerated Java/C++ defaults are enabled; a Java
8-targeted protocol check verifies constructor/clear defaults, an
omitted wire field, and an explicit-false round trip. Complete BE CI and
live external SQL suites remain pending.

The two new reproductions first failed with the same missing-bucket-key
and renamed-sequence-field errors as CI. A separate read-only-principal
reproduction also failed before the permission correction. Complete
external regression execution remains pending CI.

### BE unit-test compatibility

- Complete the native Arrow Variant input dependency for `branch-4.2`:
accept binary storage and the Parquet Variant extension, validate
metadata and payloads before appending, and retain owned data after
Arrow buffers are released. Allow that ingestion path through the load
reader while preserving query-format restrictions and source-default
validation.
- Preserve Variant V2 markers in the Arrow test fixtures, including
nested types. Verify timestamp input against this branch's SerDe for
positive, negative, and second-boundary values. Match the existing DATE
range diagnostic in the TopN pruning test.
- Add tests for sliced and empty reads, invalid ranges and carriers,
malformed metadata/payloads, NULL children, atomic failure, buffer
ownership, and the query capability boundary.

Validation: all 13 previously failing BE tests passed. The expanded run
passed all 309 tests across nine suites, including Arrow/JSON loads,
load validation, Iceberg, table mapping, and Variant input/output. The
focused executable rebuilds the affected readers and SerDe against
cached 4.2 build dependencies; this is not a complete BE rebuild. All
seven changed C++ translation units passed compiler checks with current
headers/generated Thrift, and all 33 affected C/C++ files passed
clang-format 16. The complete staged diff, whitespace, and
sensitive-information checks passed. Full CI is requested with `run
buildall` and `/review`.
Gabriel39 added a commit to Gabriel39/incubator-doris that referenced this pull request Oct 31, 2026
File scans still maintain the legacy scanner, its readers and a second capability/routing matrix. Route all file scans, file loads and external row-ID fetches through `FileScannerV2`, and remove the unused V1 implementation and tests.

- Keep `enable_file_scanner_v2` as a deprecated compatibility variable. Its stored value no longer affects planning or scanning; FE sends `true` in the existing Thrift field for older backends.
- Remove scanner-level capability checks. Factories and concrete readers return errors for unsupported operations, including native Hudi delta-log reads, query-only connector loads and Remote Doris Variant reads.
- Move standalone Iceberg position-delete reads to V2 `TableReader`, and historical Push ingestion to `LoadTableReader`. Preserve Push conversion expressions across ranges and compatibility with requests that omit the file-column count.
- Retain shared writer, metadata, JDBC/JNI and Elasticsearch HTTP components that surviving readers still use. Remove V1-only schema, partition, count and decoder infrastructure.
- Update connector planning, nullable COUNT pushdown, documentation and compatibility regression expectations.

Related PR: apache#69668

File scans always use FileScannerV2. `enable_file_scanner_v2` is deprecated and has no effect. Unsupported reader operations return an error instead of selecting the legacy scanner.

- Test
    - [x] Unit Test
    - [x] Regression test
    - [x] Manual test

Validation:
- Production BE and FE build, including connector plugin packages.
- 523 focused FE tests and FE Checkstyle.
- 593 distinct BE tests; the Remote Doris Flight suite was rerun successfully with localhost excluded from the development proxy.
- clang-format 16, clang-tidy on changed lines, build hygiene and its full self-test suite.
- Final Push fixture rerun passed after the test-data helper cleanup.
- Six standalone regression suites passed: Arrow Stream Load, HTTP CSV/JSON/compression/header formats and schema inference.
- Manual SQL verified that setting the old option to false remains accepted and SHOW VARIABLES marks it deprecated.

External Paimon regression expectations are updated for the no-op option and will be exercised by the external CI environment.

The exhaustive CSV/JSON split tests retain their existing boundary assertions after dropping the V1 parameterization. Four narrow cognitive-complexity suppressions preserve these existing GTest-expanded cross-product tests; new tests are decomposed instead.

- Behavior changed:
    - [x] Yes. The scanner option is now a deprecated no-op; unsupported operations fail in their reader.
- Does this need documentation?
    - [x] Yes. The scanner design and review guide are updated in this PR.

- [ ] Confirm the release note
- [ ] Confirm test cases
- [ ] Confirm document
- [ ] Add branch pick label
Gabriel39 added a commit that referenced this pull request Nov 2, 2026
…ion (#69723)

### What problem does this PR solve?

File scans maintained both the legacy scanner/readers and the V2 reader
stack. Route query scans, schema inference, file loads and external
row-ID fetches through FileScannerV2, migrate standalone Push and
Iceberg delete-file consumers, and remove the retired implementation and
tests.

- Keep enable_file_scanner_v2 as a deprecated no-op, with the existing
optional Thrift field emitted/defaulted to true.
- Preserve ORC session/adaptive batch caps, stripe dictionary rejection,
lazy predicate-column reuse and sequential CSV/TEXT/JSON S3 prefetch.
- Filter matching ORC dictionary IDs before string expansion in lazy,
eager and predicate-only scans. Retain residual predicates, NULL
semantics, pruning fences, physical column identity and physical row
positions.
- Restore ORC serialized-tail caching using the existing V1
FileMetaCache key policy, including its file-size fallback when mtime is
absent. Keep V2 payload types separate. ORC footer counters have
format-qualified names and publish once across repeated close; native
Parquet cache identity remains unchanged.
- Bound standalone position-delete reads to the native Parquet batch
limit. Broker source projections follow validated src_slot_ids order,
and malformed ORC dictionary offsets return CORRUPTION.
- Retain eight active V2 position-delete system-table regressions and
the operator shared-cache/shard-limit tests in maintained suites.
- Preserve all six Hive nested STRUCT/ARRAY/MAP access-path scenarios in
V2 across ORC/Parquet and name/position mapping, including separate
predicate-column IDs and complete-versus-projected row comparisons.
- Preserve active-file error context and the upstream Arrow column/type
context without changing original validation status codes.

Related PR: #69668

The supported rolling-upgrade direction remains BE first, then FE.
Old-FE/new-BE requests without semantic COUNT arguments retain their
ordinary-read fallback. New-FE/old-BE nullable COUNT is outside that
documented upgrade direction; the deprecated scanner option does not
provide a legacy routing gate.

The branch resolves the modify/delete conflict with master at
339e087. The old Arrow reader stays deleted, and its upstream
error-context fix is preserved in the V2 reader.

### Release note

File scans always use FileScannerV2. enable_file_scanner_v2 is
deprecated and has no effect. Unsupported operations fail in their
reader.

### Validation

- 565 selected BE ASAN tests passed on the rebased code: 190 ORC, 75
Parquet, 118 Iceberg reader, 21 delete-file helper, 28 scanner, 43 CSV,
43 Arrow load, 18 load-reader, 11 JSON load, 11 position-delete
system-table, 4 metadata-cache and 3 JSON-prefetch tests.
- The Hive follow-up passed 182 related BE ASAN tests, including 24
nested-path matrix cases. Selected values, parent null maps and
ARRAY/MAP offsets match full scans; KEYS-only MAP expectations retain
the existing V2 value-column fallback.
- The new 102401-row position-delete case failed before the batch-cap
fix and now checks every visited position.
- The selective dictionary case reproduced about 256 MiB of
rejected-string expansion before the fix. It now bounds materialized
strings and checks returned values and physical condition-cache granules
with lazy materialization enabled, disabled, and no follower column.
- Warm ORC footer opens perform zero physical pread calls. Versioned
keys, the legacy versionless file-size fallback, disabled caching and
repeated close are covered. Both ORC/Parquet profile initialization
orders retain independent footer counters.
- Arrow Date64 validation retains INVALID_ARGUMENT and reports the input
column and types.
- The cache/profile follow-up passed 311 related BE ASAN tests (278
reader/cache/profile and 33 scanner/operator/push tests). Two valid
operator cache tests were preserved from the retired fixture.
- FE core and all five affected connector modules pass Checkstyle.
clang-format 16 passes on all 60 affected surviving C/C++ files. Build
hygiene and changed-line clang-tidy pass.

External-service regression suites and full CI are not fresh results
from this update. No end-to-end performance benchmark is claimed. CHAR
dictionary pruning remains outside the restored STRING/VARCHAR path.

### Check List (For Author)

- [x] Unit Test
- [ ] External-service regression test on the updated head
- [x] Documentation synchronized

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

- [ ] Confirm release note
- [ ] Confirm tests and documentation
- [ ] Add branch pick label
yiguolei pushed a commit that referenced this pull request Nov 6, 2026
### What problem does this PR solve?

Issue Number: None

Related PR: #65730 #66608 #66805 #66841 #66999 #67005 #67011 #67110
#67268 #67289 #67325 #67650 #67921 #68028 #68335 #68375 #68615 #68690
#68813 #68815 #68707 #68649

Problem Summary:

**In short.** This ports the Lance BE read path of branch-4.1 /
branch-4.2 to master, in its branch-4.2 form as of `cabcf45c1af`, plus
the BE side of three 4.x changes merged after that snapshot: the search
filter `prefilter` flag and profile layout (#68813), distance bounds for
`vector_search` (#68815), and the split-level index rule of #68707 that
#68815 relies on. It gathers the BE parts of the PRs listed above.
Master links `liblance_c` but has no Lance reader, so every
`FORMAT_LANCE` scan fails today. With this PR the BE reads Lance
datasets through FileScannerV2: plain scans, vector search and full-text
search, predicate and runtime-filter pushdown, the schema fetch of a
local Lance TVF, and the second phase of TopN lazy materialization. The
PR is BE only. The FE connector plugin and the regression suites come in
separate PRs, so until then nothing on master plans a Lance scan, and
the BE unit tests carry the proof.

Original authors: @zhangstar333 @Gabriel39 @wangzhaobo957-cloud @Jay-ju
@FANNG1

**Background.** Lance shipped in 4.1.4: the Lance catalog, `local()` /
`s3()` with `format=lance`, and the `vector_search` / `full_text_search`
TVFs. On master the FE side is being rebuilt as a connector plugin
(`fe-connector-lance`), and the BE needs the reader from 4.x. The thrift
ids are the branch-4.1 / 4.2 ones, including `TExternalSearchRequest.5`
(`prefilter`) and `TVectorSearchParams.6/7` (distance bounds) added
after the snapshot, so a BE built from master also reads the Lance scan
ranges and search requests that a 4.x FE sends during a rolling upgrade.
The one exception is `TVectorSearchOptions` 6, branch-4.2's
`approx_mode` (#69852, merged into branch-4.2 after the snapshot and not
ported): it is reserved in a comment, and a master BE ignores it, so
during a rolling upgrade a 4.2 FE that asks for `fast` or `accurate`
gets Lance's default (`normal`).

**The problem, and what it cost.**

| | master today | with this PR |
|---|---|---|
| A `FORMAT_LANCE` scan | FileScannerV2 has no Lance reader, so the scan
fails with "FileScannerV2 does not support file format" | read by
`LanceTableReader` in FileScannerV2 |
| `fetch_table_schema` for a local Lance TVF | not handled | returns the
Arrow schema mapped to Doris types; Null leaves keep `NULL_TYPE` |
| The row location of a Lance row in TopN lazy materialization |
`GlobalRowLoacationV2` only has a 32-bit row id, but a Lance row id is a
64-bit id within the snapshot | a version 1 layout carries the 64-bit
row id; phase two reads the rows with the dataset's `take_rows` |

**How this PR fixes it.**

- Reader: `be/src/format_v2/lance/*` and
`be/src/format_v2/table/lance_reader.*`, as on branch-4.2 except one
local renamed for master's `-Wshadow`. The unit tests construct
`RuntimeState(TQueryOptions(), globals)`, because master removed the
globals-only constructor.
- FileScannerV2: the reader dispatch and `_to_file_format` handle
`FORMAT_LANCE` / `"lance"`; `FileFormat::LANCE` is added to its two
exhaustive switches. Since #69723 every file scan uses FileScannerV2, so
nothing else routes Lance scans (on branch-4.2 a Lance query fails with
NotSupported when `enable_file_scanner_v2` is off).
- Row locations: `ROW_VERSION {FILE_LOCAL_ROW_ID = 0,
LANCE_DATASET_ROW_ID = 1}` and a union layout for
`GlobalRowLoacationV2`. Version 0 keeps its byte layout, which static
asserts pin. `PRequestBlockDesc.row_id` becomes `uint64` (a proto2
varint, so the wire format is compatible). The materialization operator
decodes row locations by version, rejects an unknown version or a wrong
size, and stamps `row_location_version`. `RowIdStorageReader` validates
the counts and the version, range-checks internal row ids against
`uint32`, and groups Lance rows by plan node, snapshot version and
dataset URI, so each dataset is read with one `take_rows`. Master's
segment batching, scan-slot dedup and fetch concurrency stay as they
are.
- Thrift (`PlanNodes.thrift`): the external search request body
(`TVectorElementType`, `TVectorMetric`, `TSearchVector`,
`TVectorSearchParams` 1-7, `TFtsCoverageMode`, `TFtsQueryType`,
`TFtsMatchOperator`, `TFullTextSearchParams`, `TSearchFilterFormat`,
`TSearchFilter`, `TVectorSearchOptions`, `TExternalSearchQuery`),
`TExternalSearchRequest` 2-5 and `TLanceFileDesc` 4-6, all with the
branch-4.1 / 4.2 ids. The enums spell out their 4.x values. No id is
reused. On master, #70075 reserved `TExternalSearchRequest` 2-5 in
comments and added 6 (`paimon_options`); this PR replaces those comments
with the fields and leaves 6 as it is. `TVectorSearchOptions` 6 is
reserved in a comment for branch-4.2's `approx_mode` (#69852).
- After the snapshot (one commit each):
- #68813: `prefilter` decides whether the TVF search filter runs before
(true) or after (unset / false) candidate selection, for vector and
full-text search. The profile groups the Lance counters under
`LanceTiming`, `LanceIO`, `LanceIndex`, `LanceVectorIndex`,
`LanceScalarIndex`, `LanceExecutionPlan`, `LanceScan`, `LanceSearchPlan`
and `LanceDataCache`, uses the 4.x counter names, and registers every
scan metric before the statistics callback is installed, so the
callback, which Lance invokes from its execution streams, never adds
counters. #68813's FE tweak that hides `TUnit.NONE` labels in
`AggCounter` belongs to the FE port.
- #68707 (part): a vector split searches exactly the index segments FE
planned for it, and a split without segments is searched flat whatever
`use_index` says; a split with segments under `use_index = false` is
rejected. 4.x FEs plan segments only when `use_index` allows them.
- #68815: `distance_lower_bound` (inclusive) and `distance_upper_bound`
(exclusive) are validated (finite FLOAT values, lower < upper at FLOAT
precision, single-vector only) and installed with
`lance_scanner_set_distance_range()`, which master's pinned lance-c
provides.
- Review fixes:
- A nested array goes to the Doris SerDes without a copy only when it
and every descendant start at offset 0 and reference exactly their child
ranges. Lance's legacy (v1) decoder can return a struct or list that is
tight at its own level over a Boolean child with a bit offset (a batch
that starts mid-byte in the bitmap), and the SerDes reject that under
Arrow input validation.
- A zero-field `STRUCT<>`, which Lance decodes, is reported as an
unsupported column at any nesting level, like the other unsupported
Lance types. It used to be typed as a STRUCT that `ColumnStruct` cannot
hold (its row count comes from its first child).
- A Lance Decimal256 field with precision <= 38 is narrowed to
Decimal128 by a safe Arrow cast before decoding. Doris types it
DECIMAL32/64/128I by precision, and those SerDes read only Decimal128
arrays; the BE used to crash on the first value, also for nested leaves.
Only values a reader can see are cast: before a nested leaf is narrowed,
every child slot that no visible row references (under a NULL list,
fixed-size-list, map or struct row, or outside a sliced parent) is
marked NULL, so a hidden value does not fail the cast and a visible
value outside the declared precision still does; map keys, which cannot
be NULL, stay checked.
- FLOAT / DOUBLE `>=` runtime filters stay residual-only. Lance compares
floats by totalOrder, so a pushed `x >= c` dropped negative-NaN rows
that Doris keeps.
- Runtime filters that mention INT64_MIN stay residual-only. The pinned
Lance SQL parser reads `-9223372036854775808` as the negation of a
magnitude that it parses as i64 first; the overflow turns the literal
into a Float64, which the planner cannot coerce to Int64 or Decimal, so
a pushed IN, `>=` or `<=` filter on an INT64 or scale-zero decimal
column failed planning and the query failed. Every other i64 is still
pushed.
- The shared Arrow DATE32 decoding
(`DataTypeDateV2SerDe::read_column_from_arrow`) rejects days outside
0000-01-01..9999-12-31 instead of returning a non-null `0000-00-00`,
skips null slots and adds the epoch in 64 bits: the DATE32 range part of
branch-4.1 / 4.2 #68649. It also changes ADBC, Arrow stream load and
paimon-rust reads.
- Child values hidden by a NULL list, fixed-size-list, map or struct row
are not decoded: the array, map and struct SerDes give the element SerDe
a validity bitmap that also clears those slots
(`mask_arrow_children_hidden_by_null_parents()`). Arrow leaves them
unspecified, and Lance's v2.1 miniblock encoding keeps them, so a hidden
10000-01-01 under a NULL fixed-size list used to fail the DATE32 range
check above. Visible values are unchanged; this applies to ADBC, Arrow
stream load and paimon-rust as well. The masks come from ExecEnv's
tracked Arrow pool. A nested Lance array that is compacted before
decoding is masked the same way, at every level, before its
`ValidateFull()`, so a hidden invalid UTF-8 string, out-of-precision
decimal, Date64 or time no longer fails the batch while a visible one
still does. Since #69697 the same masks keep hidden DATETIMEV2 /
TIMESTAMPTZ values out of its range checks. A mask costs at most one
pass per batch: a NULL row that owns no child slots, or only NULL ones,
allocates nothing, and Arrow stream load masks each retained IPC batch
once (`mask_arrow_descendants_not_visible()`) before it hands row ranges
to the SerDes, so its per-block reads allocate nothing. The one
per-block mask left is for map keys under a NULL map row that still owns
entries, since a MapArray cannot hold NULL keys; Arrow's map builder
writes NULL map rows without entries.
- Core: `to_protobuf` keeps `NULL_TYPE` for a NULL literal type, so a
Null leaf in ARRAY / MAP / STRUCT no longer comes back as BOOLEAN. The
nullable serde reads an Arrow Null array as NULLs without touching
buffers that the array does not have.
- Configs, caches and metrics, with the 4.x names and defaults:

  | Config | Default |
  |---|---|
  | `lance_index_cache_size_bytes` | 10 GiB |
  | `lance_metadata_cache_size_bytes` | 1 GiB |
  | `enable_lance_data_cache` | true |
  | `lance_data_cache_path` | `${DORIS_HOME}/lance_data_cache` |
  | `lance_data_cache_disk_capacity_bytes` | 100 GiB |
  | `lance_data_cache_read_block_size_bytes` | 1 MiB |
  | `lance_io_buffer_size_bytes` (mutable) | 2 GiB |
  | `lance_batch_readahead` (mutable) | 5 |
  | `lance_fragment_readahead` (mutable) | 5 |

The BE-wide Lance session (index cache, metadata cache and the optional
Foyer disk cache) is created by the first Lance scan, so a BE that never
reads Lance creates no cache directory. The first six configs take
effect after a restart. A negative cache size (and, while the data cache
is enabled, a negative disk capacity or read block size) fails the first
Lance scan with a message that names the setting, as does any data-cache
value lance-c rejects; the rest of the BE keeps serving. Ten
`lance_session_*` metrics report the two in-memory caches. With the
defaults, the disk tier keeps 51,200 sparse 2 MiB block files open from
the first Lance scan on (100 GiB in blocks of twice the read block
size), the same as on branch-4.1 / 4.2. Size
`lance_data_cache_disk_capacity_bytes` and
`lance_data_cache_read_block_size_bytes` against the BE's open-file
limit, or set `enable_lance_data_cache = false`.

The index and metadata caches live in lance-c memory: they are not
charged to a MemTracker or registered with CacheManager, so memory GC,
the cache capacity adjustment under memory pressure and
`/api/clear_cache/all` do not shrink them, and `enable_lance_data_cache
= false` does not turn them off. lance-c has no call to clear, evict or
resize them, so size them with the two configs. The disk tier keys
blocks by Lance's store prefix (`scheme$bucket` for S3, GCS and OSS,
without the endpoint) and the object path
(`thirdparty/patches/lance-c-foyer.patch`). Several endpoints that serve
the same bucket name and data-file path with different bytes (data files
registered under chosen names or replaced in place; Lance's writers use
random file names) share entries, also across a BE restart; such a
deployment should set `enable_lance_data_cache = false`. Both are as on
branch-4.1 / 4.2 and tracked as follow-ups.

A Lance scan's native working set, that is the I/O buffered up to
`lance_io_buffer_size_bytes` per scanner, the decode readahead and the
operators of a search plan such as the top-k of a flat vector search, is
allocated inside lance-c and is charged to neither the query nor its
workload group. It counts toward the BE process memory only, so memory
GC, which ranks queries by tracked memory, does not attribute it to the
Lance query. lance-c accepts no memory budget, so on BEs with little
memory headroom size `lance_io_buffer_size_bytes`,
`lance_batch_readahead` and `lance_fragment_readahead` for the number of
concurrent Lance scanners. As on branch-4.1 / 4.2; tracked as a
follow-up.
- Build: macOS links `-framework IOKit`. This is the first time objects
of `liblance_c.a` are pulled into `doris_be`, so the binary and the link
time grow. With this PR `util/rle_encoding.h` reaches 231 TUs and
`util/threadpool.h` 589, the same as master `315c2e00331` alone (limits
275 and 660 since #69717), and `gen_cpp/internal_service.pb.h` 562
(master alone 559, limit 660); the reach budgets are unchanged.

Not included: the Lance index metadata scanner (`LANCE_INDEX_ENTRIES`);
the FE side, including the rolling-upgrade guard that keeps Lance lazy
materialization off while an old BE could decode a version 1 row
location as version 0; the regression suites; the rest of #68707
(searching historical versions, tags and branches, rejecting fragment
ids missing from the snapshot, naming the snapshot in errors and the
profile). The `InitReaderAvgTime` / `GetBlockAvgTime` profile fix that
#67005 carried goes in a separate PR.

**Results.**

| | master | with this PR |
|---|---|---|
| A `FORMAT_LANCE` query | fails before reading anything | read by
`LanceTableReader` in FileScannerV2 |
| A Lance row in the second phase of TopN lazy materialization | cannot
be represented | a version 1 row location, read back with `take_rows` |
| A row location of an unknown version or size in phase two | decoded as
version 0 | rejected with an error |
| An Arrow DATE32 day outside 0000-01-01..9999-12-31 (ADBC, Arrow stream
load, paimon-rust, Lance) | read as a non-null `0000-00-00` | the read
fails with `InvalidArgument` |

BE unit tests (ASAN, macOS arm64, against master's pinned lance-c), on
the head rebased onto master `378404eeb12`: 1029 cases in 54 suites run,
1027 pass and 2 Parquet microbenchmarks skip by design. They cover the
Lance suites (107: `LanceTableReader*` 83, `LanceNestedNullTest` 10,
`LanceRuntimeFilterHelperTest` 10, `LanceSessionManagerTest` 4); the
row-location protocol (`MaterializationSharedStateTest`,
`RowIdStorageReaderTest`, and the new `RowIdFetchRequestValidationTest`:
count mismatch, unknown version, a Lance version on an internal mapping,
an internal row id of 2^32); `FileScannerV2Test` (28); the ORC and
Parquet reader suites (`NewOrcReaderTest`, `NewParquetReaderTest`,
`ParquetScanTest` and the other `Parquet*` suites), whose row ids now go
through `file_local`; and the Arrow / protobuf / DATE serde suites with
the new `ArrowParentNullsTest`, plus the Iceberg and Parquet reader
suites that decode Arrow dates. Reverting any of the review fixes, the
#68813 flag, the #68707 split rule or the #68815 bounds makes its new
tests fail. The sixth review round adds 13 cases (`ArrowParentNullsTest`
10, `LanceTableReaderTypeTest` 3) and extends one; with them the Arrow
SerDe, Lance, ADBC and `IcebergV2ReaderTest` suites run 317 cases: 310
pass and the 7 ADBC SQLite cases skip without a local SQLite driver. The
ninth review round adds
`LanceRuntimeFilterHelperTest.KeepsInt64MinFiltersResidualOnly` and
`LanceTableReaderFilterTest.KeepsInt64MinRuntimeFiltersOutOfLanceScanner`:
both pass with the 106 Lance cases (`Lance*`) on the branch rebased onto
`339e087b11f`, and restoring `parse_int64()` in either check makes
exactly these two fail. On the head rebased onto master `315c2e00331`,
with the per-block mask fix (`42cf4e3e5d1`), 328 cases in 24 suites
pass: the Arrow SerDe and validation suites, `ArrowParentNullsTest`
(15), `LoadArrowPipeTest` (47), the DATETIMEV2 / TIMESTAMPTZ SerDe
suites, `ArrowColumnToDorisColumnTest`, `ArrowBlockConvertorTest`,
`AdbcReaderTest`, `RemoteDorisV2ReaderTest`, `PaimonRustTableReaderTest`
and the Lance suites. Allocating at the first NULL row of each call
again fails the new `ArrowParentNullsTest` case and the four new
`LoadArrowPipeTest` block cases, dropping the per-batch mask fails the
LIST and STRUCT block cases, and returning the child unmasked fails the
new timestamp case, four `ArrowParentNullsTest` cases and
`LanceTableReaderTypeTest.IgnoresDate32PayloadHiddenByNullParents`.

### Release note

Add nine `lance_*` BE configs and `lance_session_*` BE metrics. They
take effect once the FE can plan Lance scans. Reading an Arrow DATE32
value outside 0000-01-01..9999-12-31 through ADBC, Arrow stream load or
paimon-rust now fails instead of returning 0000-00-00.

### Check List (For Author)

- Test <!-- At least one of them must be included. -->
    - [ ] Regression test
    - [x] Unit Test
- `run-be-ut.sh --run --filter=...` with the suites listed under
Results: 420 of 420 pass on macOS arm64 (ASAN) on the content before the
rebases, and the Lance and Arrow SerDe suites pass again with the
nested-offset, zero-field struct, hidden-child, hidden-Decimal256 and
compaction-mask fixes (the ADBC SQLite cases skip without a local SQLite
driver). Rebased onto master `43f9ceb48d7`: #69668 conflicted in the
scanner selection and in `fetch_table_schema`, which now hands every
file format to `format::fetch_file_schema()`, so the Lance branch runs
ahead of that call; #69646 added a TopN row-group test that reads the
version 0 row location fields, which now go through `file_local` (the
earlier rebase onto `5caaeb3e3d4` resolved #69614 and #69601 in the
scanner selection, the `FileFormat` enum, its test and the reach budget
table). The 95 TUs that this PR changes or that master changed since
`5caaeb3e3d4` were syntax-checked against the rebased tree with the UT
build flags, and CI runs the suites again. Rebased again onto master
`8d88f1cc6f7`: the only conflict was the budget table, where #65858
moved the `util/rle_encoding.h` baseline to 828, and the 163 TUs that
this PR changes or that master changed since `43f9ceb48d7` pass the same
syntax check. Rebased again onto master `339e087b11f`: the only conflict
was the budget table again, where #67292 moved the `util/rle_encoding.h`
baseline to 834; #69872 added Arrow type checks ahead of the NULL-parent
masking in the map and struct readers and merged cleanly. Of the 114
sources that this PR changes or that master changed since `8d88f1cc6f7`,
111 pass the same syntax check. The other three are master's: two new
#67292 files under `storage/segment` fail the same way on master alone,
since they compile only inside their unity batch, and this PR adds no
source to that target; the #69818 benchmark is not in the UT build and
includes only `util/simd` headers that this PR does not touch. Reverting
any of the review fixes, the #68813 flag, the #68707 split rule or the
#68815 bounds makes its new tests fail. Rebased again onto master
`378404eeb12`, which removed the legacy file scanner (#69723): the
conflicts were in the scanner-selection code and tests that #69723
deleted, so this PR's Lance lines there went with them (including its
`LanceQueriesAlwaysUseScannerV2` test), in the profile keys of
`materialization_opertor.cpp`, and in the row fetch of
`rowid_fetcher.cpp`, whose non-Lance path is now only
`FileScannerV2::read_by_rows`; the deleted V1 ORC / Parquet row id tests
took this PR's `file_local` rename with them, and the
`util/rle_encoding.h` budget commit is dropped because master is no
longer near that limit. Of the 100 sources that this PR changes or that
master changed since `339e087b11f`, 99 pass the same syntax check; the
other, `format_v2/orc/orc_reader.cpp`, fails the same way on master
alone. On the rebased head the suites listed under Results run 1029
cases: 1027 pass and 2 microbenchmarks skip. The test-utility fix that
`DataTypeDateTimeV2SerDeTest` needed on macOS (#69695) is now on master.
Rebased again onto master `315c2e00331`: the only conflict was
`TExternalSearchRequest` in `PlanNodes.thrift`, where #70075 had
reserved fields 2-5 in comments; the two commits that add the fields
replace those comments, and field 6 stays #70075's `paimon_options`.
#69717 cut transitive includes from shared headers: of the 160 sources
that this PR changes or that master changed since `378404eeb12`, 156
pass the same syntax check; the two `jemalloc_hook` tests have no
compile command on macOS, `runtime/memory/jemalloc_hook.cpp` uses glibc
aliases that macOS cannot build (#69819), and
`format_v2/table_reader.cpp` alone fails the same way on master alone
while its unity batch compiles. The full `doris_be_test` builds and
links on the rebased head; `ArrowParentNulls*` and `Lance*` (121 cases)
pass before the mask fix, and the 328 cases above with it.
- `build-support/check-build-hygiene.sh` (on this branch rebased onto
master `315c2e00331`), clang-format 16 and
`build-support/run-clang-tidy.sh` on the changed files: all pass; on the
changed lines clang-tidy (llvm 22) reports only
`readability-inconsistent-ifelse-braces` on the `DORIS_CHECK` lines of
the masking functions, the macro's expansion that master's existing
`DORIS_CHECK`s report too.
    - [ ] Manual test (add detailed scripts or steps below)
    - [ ] No need to test or manual test. Explain why:
- Behavior changed:
    - [ ] No.
- [x] Yes. `PRequestBlockDesc.row_id` is `uint64`; phase two of TopN
lazy materialization rejects row locations of an unknown version or
size; `FORMAT_LANCE` scans run on FileScannerV2; an Arrow DATE32 day
outside the Doris DATE range fails the read instead of becoming
`0000-00-00`.
- Does this need documentation?
    - [x] No. Lance is documented with the FE connector.
- [ ] Yes. <!-- Add document PR link here. eg:
apache/doris-website#1214 -->

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

- [ ] Confirm the release note
- [ ] Confirm test cases
- [ ] Confirm document
- [ ] Add branch pick label <!-- Add branch pick label that this PR
should merge into -->

---------

Co-authored-by: zhangstar333 <[email protected]>
Co-authored-by: Gabriel <[email protected]>
Co-authored-by: zhaobo wang <[email protected]>
Co-authored-by: jay <[email protected]>
Co-authored-by: FANNG <[email protected]>
Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
Co-authored-by: zy-kkk <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants