Skip to content

[feature](arrow) Port Flight metadata, native Variant and VARBINARY fixes to master - #68883

Open
Gabriel39 wants to merge 2 commits into
apache:masterfrom
Gabriel39:dev/flight-type-fixes-master
Open

Gabriel39 wants to merge 2 commits into
apache:masterfrom
Gabriel39:dev/flight-type-fixes-master

Conversation

@Gabriel39

@Gabriel39 Gabriel39 commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Forward-port the requested changes whose missing behavior is still present on master: complete the missing Variant writer hooks from #68381, then retain the ports of #68614, #68667 and #68859 in branch-4.1 merge order.

Source PR Evidence on master before this change Action
#68381 Master already contains the main converter refactor through #68396, but lacks the Variant-specific Paimon/Iceberg SerDe overrides. Native Flight dispatch intercepts Paimon binary structs. Complete the missing hooks and preserve Paimon value,metadata versus Flight metadata,value storage contracts, including nested columns.
#68614 Arrow ARRAY/MAP/STRUCT child fields lose Doris logical type markers; JSON/VARIANT markers are absent. Preserve recursive logical metadata and use protocol-specific schema converters.
#68667 Flight maps Variant V2 to UTF8 instead of native binary values. Return arrow.parquet.variant with struct<metadata: binary not null, value: binary not null> storage; preserve SQL NULL, physical scalar types and row-local dictionaries.
#68852 The obsolete external-table queries are already removed. All 276 active query tags match the 276 expected output blocks in execution order. Excluded; no expected-output changes.
#68856 The preload module is already removed. The Hudi plugin resolves Parquet readers and format structures consistently to 1.18.0. Excluded; no dependency changes.
#68859 Block metadata omits VARBINARY length, and deserialization constructs DataTypeVarbinary() with an unspecified length. Preserve declared lengths, including nested and nullable columns, using optional protobuf field 13.

Adapt the ports to master's existing architecture: retain native UUID and nanosecond/timestamp mappings, reuse the shared FE Arrow mapper, and wrap extension storage correctly for nested Variant arrays. Master already uses Variant V2, so the removed legacy Variant switch and SerDe are not restored. This does not add the branch-4.1-only Iceberg table Variant feature or prepared-statement schema machinery. ADBC recognizes the native Variant extension, validates and decodes its bytes, and retains Variant sub-column access; the scanner permits that carrier only for ADBC among Arrow readers.

The Flight integration tests and Python samples cover native Variant and recursive metadata. GetTables and ADBC expectations follow the native schema. The Iceberg static-null partition unit-test fixture uses master's existing Thrift field ID 19; production Thrift definitions are unchanged. The Flink regression explicitly casts Variant to STRING for a connector that declares that column as STRING.

Release note

Preserve nested logical type metadata in Arrow Flight SQL results, return Variant V2 as native Arrow Variant binary, preserve native Variant values and sub-column access through ADBC, and retain declared VARBINARY lengths across block serialization. Clients requiring Variant JSON text should explicitly cast it to STRING.

Validation

  • FE targeted unit tests: 25 passed for the follow-up (ADBC mapping, native Variant and Flight schemas); the initial port also passed 64 targeted tests including UUID and recursive mappings.
  • FE Checkstyle: passed.
  • BE targeted ASAN unit tests: 408 passed, covering Arrow, Variant, ADBC, FileScannerV2, UUID, VARBINARY and the static-null Iceberg fixture.
  • Changed-line clang-tidy, clang-format 16 and build hygiene checks: passed.
  • Groovy regression scripts compiled; Python samples passed syntax checks.
  • Checked modified Thrift/protobuf field IDs against master and branch-3.1, branch-4.0, branch-4.1 and branch-4.2.
  • Confirmed the ES baseline query/output alignment and Hudi Parquet dependency tree before excluding those ports.
  • Built FE and ASAN BE with the repository build script. On a local cluster, test_adbc_type_semantic, test_get_tables_schema and test_flight_native_variant passed (3 suites, 0 failures, 0 skips). The ADBC .out was generated by the regression framework and then checked by a normal rerun.
  • Full Paimon and Flink integration suites require the external test environment and were not run locally. Paimon writer and nested-container paths passed BE tests.
  • Four muted P0 failures also recur on unrelated PR builds: two optimizer plan-shape mismatches and two object-store upload timeouts. They are not included as fixed by this port.

Check List (For Author)

  • Test
    • Unit tests
    • Regression tests added/updated
  • Behavior changed:
    • Yes, native Variant Flight output and preserved type metadata.
  • Does this need documentation?
    • Yes, Python Flight sample documentation updated.

…ixes to master

### What problem does this PR solve?

Forward-port only the requested changes whose missing behavior is still present on master, in branch-4.1 merge order: apache#68614, then apache#68667, followed by apache#68859.

| Source PR | Evidence on master before this change | Action |
| --- | --- | --- |
| apache#68614 | Arrow ARRAY/MAP/STRUCT child fields lose Doris logical type markers; JSON/VARIANT markers are absent. | Preserve recursive logical metadata and use protocol-specific schema converters. |
| apache#68667 | Flight maps Variant V2 to UTF8 instead of native binary values. | Return `arrow.parquet.variant` with `struct<metadata: binary not null, value: binary not null>` storage; preserve SQL NULL, physical scalar types and row-local dictionaries. |
| apache#68852 | The obsolete external-table queries are already removed. All 276 active query tags match the 276 expected output blocks in execution order. | Excluded; no expected-output changes. |
| apache#68856 | The preload module is already removed. The Hudi plugin resolves Parquet readers and format structures consistently to 1.18.0. | Excluded; no dependency changes. |
| apache#68859 | Block metadata omits VARBINARY length, and deserialization constructs `DataTypeVarbinary()` with an unspecified length. | Preserve declared lengths, including nested and nullable columns, using optional protobuf field 13. |

Adapt the ports to master's existing architecture: retain native UUID and nanosecond/timestamp mappings, reuse the shared FE Arrow mapper, and wrap extension storage correctly for nested Variant arrays. Master already uses Variant V2, so the removed legacy Variant switch and SerDe are not restored. Branch-4.1-only Iceberg Variant writing and prepared-statement schema machinery are outside this port.

The Flight integration tests and Python samples cover native Variant and recursive metadata. The Flink regression explicitly casts Variant to STRING for a connector that declares that column as STRING.

### Release note

Preserve nested logical type metadata in Arrow Flight SQL results, return Variant V2 as native Arrow Variant binary, and retain declared VARBINARY lengths across block serialization. Clients requiring Variant JSON text should explicitly cast it to STRING.

### Validation

- FE targeted unit tests: 64 passed, including nested metadata, native Variant, UUID preservation and shared Arrow mappings.
- FE Checkstyle: passed.
- BE targeted ASAN unit tests: 326 passed, covering Arrow, Variant, UUID and VARBINARY.
- Changed-line clang-tidy, clang-format 16 and build hygiene checks: passed.
- Groovy regression scripts compiled; Python samples passed syntax checks.
- Checked modified Thrift/protobuf field IDs against master and branch-3.1, branch-4.0, branch-4.1 and branch-4.2.
- Confirmed the ES baseline query/output alignment and Hudi Parquet dependency tree before excluding those ports.
- Live cluster, ADBC and Flink integration tests were not run locally.

### Check List (For Author)

- Test
  - [x] Unit tests
  - [x] Regression tests added/updated
- Behavior changed:
  - [x] Yes, native Variant Flight output and preserved type metadata.
- Does this need documentation?
  - [x] Yes, Python Flight sample documentation updated.

Adapted from commits:
- e233c4a (apache#68614)
- b8c03bf (apache#68667)
- b35abbd (apache#68859)
@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.

Complete static review of PR #68883 at head 91810cb36b7678adbb8f5fc2979827ff26841196. I found two P1 compatibility regressions, one P2 Flight error-status defect, and one P3 regression-test cleanup issue. The two P1s should be fixed before merging. There were no existing inline blockers to carry forward. Three review rounds converged with no unresolved candidate. No additional user focus was provided.

Critical checkpoints:

  • Goal and proof: Native Variant V2 Arrow Flight output, nested logical metadata, and Varbinary width transport are implemented and covered by new BE/FE and regression cases, but the Paimon writer and external scanner regressions prevent the change from meeting its compatibility goal. The unchanged value-first Variant SerDe tests would fail under the new dispatch. Builds and tests were prohibited for this review, so these are static conclusions, not runtime results.
  • Scope and clarity: The converter refactor reaches Flight, table-format, Python, and scanner consumers. Most production callers retain their protocol-specific schema; the memory scratch sink is a concrete unintended expansion (P1).
  • Concurrency: Result schema converters are initialized before sink local-state use; the reviewed changes add no shared mutable request state or new lock order. No separate race or deadlock was substantiated.
  • Lifecycle and ownership: Local and remote Flight readers obtain their schema from the result buffer, and the remote reader registers the Variant extension before decoding IPC. No new ownership cycle, static-initialization dependency, or missing release path was substantiated.
  • Configuration: No new runtime configuration item is introduced. The new optional sink capability bit is set by FE Flight result sinks and read by BE; external scanner traffic has no corresponding negotiation (P1).
  • Compatibility and wire definitions: Proto field 13 and Thrift field 4 are optional, retain their meaning on release branches where present, and have safe old-wire defaults. Native Variant changes the external scanner's established UTF8 representation without opt-in (P1). Old-BE UTF8 Variant is intentionally rejected by new FE, but its intended UNIMPLEMENTED status becomes INTERNAL (P2). The documented metadata difference between old-BE DoGet and enriched FlightInfo yielded no separate demonstrated client failure.
  • Parallel paths: Legacy and Nereids planners both propagate the Flight sink bit; parallel and per-instance result sinks, nested SerDes, Paimon/Iceberg/Parquet writers, Python UDFs, and the separate memory scratch scanner were traced. Paimon's value-first Variant struct is lost by the new generic dispatch (P1).
  • Conditions and errors: The new unconditional STRUCT branch makes the existing value-first branch unreachable (P1). The FE schema-fetch catch chain changes the intentional Flight status (P2). Other inspected Status returns and conditional bindings had no distinct substantiated issue.
  • Test coverage and results: New tests cover root and nested Variant, nulls, dictionary compaction, metadata policy, timestamps, and Varbinary width. They miss the scanner's existing Variant wire contract, and the new regression suite deletes its table after failures contrary to repository test standards (P3). No builds, tests, or result regeneration were run because the review contract forbids execution.
  • Observability: Existing sink statuses, reader errors, and profiles cover the new data paths; no separate logging or metric gap was substantiated. P2 obscures the actionable client error category.
  • Persistence and transactions: No EditLog, transaction, rowset, or persistent storage format is changed. The Paimon failure concerns Arrow output before downstream write completion; no additional atomicity or crash-recovery defect was substantiated.
  • FE/BE state transfer: The Flight metadata bit and Varbinary length are transmitted at their intended Thrift/protobuf boundaries; no other missing send path was substantiated.
  • Performance and remaining issues: Per-row Variant dictionary compaction adds work but bounds emitted metadata and showed no separate correctness or material performance regression in static review. Final changed-file, inline-thread, and candidate sweeps found no further actionable point.

options.timezone = &ctz;
const size_t first = checked_row(start);
const size_t last = checked_row(end);
if (array_builder->type()->id() == arrow::Type::STRUCT) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[P1] Preserve the value-first Variant struct writer. This branch captures every struct builder, but write_parquet_variant_arrow rejects the existing struct<value: binary, metadata: binary> layout before the following write_binary_variant_arrow branch can run. Paimon's Variant writer uses that value-first schema and delegates here, so Paimon Variant writes now fail; the unchanged binary-struct SerDe tests would fail too. Dispatch by the validated child field order to keep both representations reachable.

}
DorisArrowBlockConvertor converter(block, state->timezone(), _timezone_obj,
/*datetime_naive=*/true);
ArrowFlightArrowBlockConvertor converter(block, state->timezone(), _timezone_obj);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[P1] Keep the external scanner's Variant wire type compatible. TableQueryPlanAction installs this memory scratch sink for open_scanner, and get_next sends its RecordBatch directly to scanner clients. Switching to the Flight converter changes a selected Variant V2 column from UTF8 to an extension-backed STRUCT without any scanner capability flag; the in-tree DorisReaderExample accepts VARCHAR but rejects STRUCT. Keep this sink on the ordinary converter unless the separate scanner protocol negotiates native Variant.

if (type.isVariantType()) {
if (field.getMetadata() == null
|| !"arrow.parquet.variant".equals(field.getMetadata().get("ARROW:extension:name"))) {
throw CallStatus.UNIMPLEMENTED.withDescription(

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 the unsupported Variant status at the Flight boundary. An older BE can return a UTF8 schema for a planned Variant, causing this branch to throw UNIMPLEMENTED. fetchArrowFlightSchema wraps that exception, then executeQueryStatement passes it to queryFailure, which returns INTERNAL to the client. Pass the capability error through the fetch and producer boundaries so clients receive the actionable UNIMPLEMENTED status.

try {
allocator.close()
} finally {
jdbc_sql("DROP TABLE IF EXISTS ${table}")

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.

[P3] Leave the table available for regression debugging. This finally drop removes flight_native_variant_input even when an assertion fails. The suite already drops it before creation, and the repository testing standard requires retaining test tables afterward. Keep the client and allocator cleanup, but remove this final table drop.

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17597	5631	5527	5527
q2	2114	328	269	269
q3	10204	1399	847	847
q4	4679	481	355	355
q5	7439	803	541	541
q6	190	194	159	159
q7	765	801	614	614
q8	9838	1372	1087	1087
q9	5803	4489	4444	4444
q10	6872	1297	1030	1030
q11	457	266	238	238
q12	693	398	282	282
q13	18179	3070	2385	2385
q14	276	268	239	239
q15	q16	742	726	693	693
q17	1209	760	573	573
q18	7059	6240	6188	6188
q19	1110	964	597	597
q20	388	340	223	223
q21	5270	2481	2553	2481
q22	396	321	282	282
Total cold run time: 101280 ms
Total hot run time: 29054 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	6530	6660	6518	6518
q2	725	598	559	559
q3	5664	5686	5495	5495
q4	2047	2148	1583	1583
q5	5792	5741	5637	5637
q6	252	184	151	151
q7	2378	2124	1811	1811
q8	3147	2836	2778	2778
q9	8253	7840	7831	7831
q10	3666	3604	3247	3247
q11	596	402	374	374
q12	669	698	502	502
q13	2729	3064	2374	2374
q14	278	291	261	261
q15	q16	660	684	620	620
q17	7852	6994	6849	6849
q18	13129	12250	13113	12250
q19	917	792	782	782
q20	2200	2175	1957	1957
q21	5794	4680	4789	4680
q22	493	462	418	418
Total cold run time: 73771 ms
Total hot run time: 66677 ms

@hello-stephen

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

query5	4308	575	440	440
query6	416	203	206	203
query7	4810	465	227	227
query8	321	195	166	166
query9	8762	3937	3938	3937
query10	459	310	254	254
query11	6020	3439	3203	3203
query12	143	90	83	83
query13	1230	432	301	301
query14	6511	4796	4451	4451
query14_1	4263	4261	4229	4229
query15	210	196	188	188
query16	961	449	455	449
query17	870	667	549	549
query18	2468	414	296	296
query19	186	159	133	133
query20	79	77	78	77
query21	209	133	108	108
query22	13050	13011	12968	12968
query23	13269	12467	12144	12144
query23_1	12167	12296	12124	12124
query24	7088	824	455	455
query24_1	453	466	453	453
query25	509	388	332	332
query26	1250	251	132	132
query27	2787	434	261	261
query28	4632	1899	1890	1890
query29	1535	568	422	422
query30	296	213	192	192
query31	888	761	641	641
query32	140	91	105	91
query33	492	293	235	235
query34	953	872	489	489
query35	748	764	632	632
query36	833	809	770	770
query37	128	96	90	90
query38	1810	1730	1721	1721
query39	710	716	718	716
query39_1	662	670	652	652
query40	214	127	100	100
query41	80	77	62	62
query42	87	80	84	80
query43	371	369	325	325
query44	1312	686	687	686
query45	188	183	163	163
query46	848	961	556	556
query47	2931	2916	2895	2895
query48	304	310	224	224
query49	576	399	298	298
query50	687	280	212	212
query51	10227	10125	10166	10125
query52	83	89	77	77
query53	192	207	154	154
query54	250	199	218	199
query55	68	69	61	61
query56	221	228	203	203
query57	1613	1597	1570	1570
query58	283	257	253	253
query59	2379	2395	2135	2135
query60	271	237	224	224
query61	148	151	147	147
query62	389	346	282	282
query63	199	156	164	156
query64	2744	901	761	761
query65	3442	3382	3359	3359
query66	1776	422	298	298
query67	20102	20159	19955	19955
query68	2982	985	591	591
query69	391	281	241	241
query70	934	863	828	828
query71	290	271	209	209
query72	2772	2577	2277	2277
query73	568	521	295	295
query74	4586	4474	4294	4294
query75	2358	2305	1936	1936
query76	2293	1019	589	589
query77	357	406	290	290
query78	9011	9024	8434	8434
query79	884	832	501	501
query80	498	429	351	351
query81	517	317	267	267
query82	211	130	107	107
query83	193	196	187	187
query84	292	121	109	109
query85	778	432	378	378
query86	280	239	227	227
query87	1981	2026	1820	1820
query88	3563	2662	2653	2653
query89	322	291	253	253
query90	2110	180	180	180
query91	156	147	125	125
query92	96	86	88	86
query93	968	989	552	552
query94	450	317	278	278
query95	614	356	330	330
query96	689	534	229	229
query97	2447	2422	2358	2358
query98	160	148	140	140
query99	776	772	668	668
Total cold run time: 232715 ms
Total hot run time: 151413 ms

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 88.71% (55/62) 🎉
Increment coverage report
Complete coverage report

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	16544	5676	5553	5553
q2	2118	311	279	279
q3	9853	1384	831	831
q4	4563	465	344	344
q5	7296	793	536	536
q6	192	190	160	160
q7	763	788	603	603
q8	9381	1307	1048	1048
q9	5818	4412	4410	4410
q10	6799	1282	1038	1038
q11	443	260	229	229
q12	630	404	283	283
q13	17880	3065	2395	2395
q14	275	279	247	247
q15	q16	722	718	661	661
q17	1165	735	567	567
q18	7135	6192	6178	6178
q19	1111	969	616	616
q20	391	339	226	226
q21	4669	2220	2380	2220
q22	373	312	276	276
Total cold run time: 98121 ms
Total hot run time: 28700 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	6174	6113	6137	6113
q2	677	576	554	554
q3	5203	5414	4947	4947
q4	1988	2105	1555	1555
q5	5332	5170	5680	5170
q6	277	204	160	160
q7	2299	1994	1850	1850
q8	3111	2803	2722	2722
q9	8275	8202	8140	8140
q10	3733	3668	3672	3668
q11	659	449	423	423
q12	714	720	546	546
q13	2862	3280	2554	2554
q14	351	353	284	284
q15	q16	759	724	635	635
q17	8353	7560	7473	7473
q18	13178	12420	13056	12420
q19	958	776	774	774
q20	2184	2168	1937	1937
q21	5797	4673	4830	4673
q22	508	478	403	403
Total cold run time: 73392 ms
Total hot run time: 67001 ms

@hello-stephen

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

query5	4326	603	458	458
query6	437	233	205	205
query7	4807	448	229	229
query8	322	184	172	172
query9	8754	4058	4054	4054
query10	501	322	270	270
query11	5983	3416	3197	3197
query12	148	93	87	87
query13	1268	448	314	314
query14	6548	4793	4504	4504
query14_1	4265	4296	4255	4255
query15	211	203	185	185
query16	973	458	459	458
query17	860	669	545	545
query18	2428	436	308	308
query19	199	169	136	136
query20	81	80	80	80
query21	207	135	113	113
query22	12981	13119	12901	12901
query23	13111	12364	12054	12054
query23_1	12227	12103	12242	12103
query24	6875	823	462	462
query24_1	488	472	486	472
query25	532	426	367	367
query26	1257	256	138	138
query27	2771	435	268	268
query28	4486	1923	1945	1923
query29	1534	602	452	452
query30	296	205	182	182
query31	917	768	651	651
query32	145	91	87	87
query33	516	317	241	241
query34	883	852	498	498
query35	753	759	634	634
query36	806	807	728	728
query37	125	100	92	92
query38	1811	1796	1683	1683
query39	723	725	704	704
query39_1	669	644	680	644
query40	260	131	105	105
query41	80	69	64	64
query42	83	90	84	84
query43	364	378	337	337
query44	1293	685	704	685
query45	185	178	158	158
query46	840	956	584	584
query47	2871	2962	2918	2918
query48	298	301	211	211
query49	559	388	287	287
query50	672	268	214	214
query51	10478	10222	10348	10222
query52	77	79	67	67
query53	189	209	150	150
query54	248	198	181	181
query55	70	70	62	62
query56	231	220	215	215
query57	1604	1573	1542	1542
query58	280	254	253	253
query59	2362	2377	2104	2104
query60	278	236	218	218
query61	185	148	177	148
query62	389	342	282	282
query63	192	165	164	164
query64	2630	924	765	765
query65	3414	3352	3386	3352
query66	1769	412	293	293
query67	20157	20095	19898	19898
query68	2903	985	597	597
query69	381	285	238	238
query70	896	836	810	810
query71	302	237	206	206
query72	2692	2608	2224	2224
query73	516	523	289	289
query74	4577	4450	4259	4259
query75	2337	2274	1940	1940
query76	2052	1022	595	595
query77	382	394	299	299
query78	9127	9037	8480	8480
query79	985	858	518	518
query80	793	433	356	356
query81	573	321	273	273
query82	550	140	110	110
query83	296	189	177	177
query84	308	123	103	103
query85	859	433	371	371
query86	379	242	231	231
query87	2046	1988	1810	1810
query88	3581	2686	2677	2677
query89	340	292	260	260
query90	1852	184	169	169
query91	163	147	121	121
query92	114	79	83	79
query93	979	966	551	551
query94	507	299	275	275
query95	580	423	330	330
query96	666	512	229	229
query97	2434	2410	2298	2298
query98	162	152	141	141
query99	782	788	643	643
Total cold run time: 233020 ms
Total hot run time: 151428 ms

@hello-stephen

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

query1	0.01	0.01	0.01
query2	0.15	0.09	0.08
query3	0.40	0.20	0.19
query4	1.62	0.19	0.20
query5	0.31	0.30	0.29
query6	1.16	0.66	0.66
query7	0.04	0.01	0.01
query8	0.09	0.07	0.08
query9	0.50	0.39	0.39
query10	0.60	0.60	0.61
query11	0.34	0.18	0.19
query12	0.33	0.19	0.19
query13	0.52	0.50	0.52
query14	0.91	0.89	0.89
query15	0.68	0.59	0.59
query16	0.37	0.37	0.36
query17	1.02	1.04	1.02
query18	0.31	0.28	0.28
query19	2.00	1.80	1.89
query20	0.02	0.01	0.02
query21	15.48	0.35	0.31
query22	4.81	0.13	0.12
query23	15.87	0.49	0.29
query24	2.15	0.55	0.39
query25	0.16	0.10	0.12
query26	0.74	0.27	0.21
query27	0.10	0.10	0.10
query28	3.52	0.86	0.42
query29	12.53	4.31	3.30
query30	0.38	0.23	0.22
query31	2.76	0.62	0.36
query32	3.24	0.64	0.51
query33	2.96	2.96	3.03
query34	15.84	4.16	3.43
query35	3.40	3.40	3.38
query36	0.59	0.50	0.48
query37	0.13	0.10	0.10
query38	0.07	0.07	0.07
query39	0.06	0.05	0.06
query40	0.19	0.18	0.16
query41	0.10	0.05	0.06
query42	0.06	0.05	0.05
query43	0.06	0.05	0.06
Total cold run time: 96.58 s
Total hot run time: 25.42 s

@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 80.65% (50/62) 🎉
Increment coverage report
Complete coverage report

Adapt the missing Variant hooks from apache#68381 to master, isolate Paimon binary storage from Flight, and decode native Variant through ADBC. Align GetTables and ADBC regressions and correct the Iceberg test wire fixture.
@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.

Review result

Complete static review of PR #68883 at 163e10248fe5f3cd255dfb909840beedcabd9101 (base a01cc89378f027b875a3f7e93b94ff04314e857f). Request changes: one new P1 finding is inline, and the already-reported P1 scanner issue remains applicable. The review covered the complete authoritative diff, related call paths, existing threads, and two convergence rounds. No additional user focus was supplied.

Existing threads: P1 4237385156 still applies because the memory-scratch scanner uses the Flight Variant converter without scanner negotiation. P1 4237385154 is resolved on this head: Paimon now calls its value-first Variant writer, including nested dispatch. P2 4237385157 still describes the new-FE/old-BE Flight status wrapping, and P3 4237385161 still describes the regression suite's final table drop; both are duplicate fences and are not reposted. The new inline P1 concerns the distinct old-FE/new-BE result-sink path.

Critical checkpoints

  • Goal and proof: Native Arrow Variant transport and Doris type metadata are wired through Flight, ADBC, readers, and writers. The added unit and regression cases exercise native, nested, nullable, sliced, malformed, and empty results statically. The old-FE/new-BE result-sink compatibility gap means the goal is incomplete for rolling upgrades. No test was executed in this review.
  • Scope and clarity: The changed paths are centered on Arrow schema/Variant transport, protocol fields, associated type handling, and focused tests/samples. I found no separate scope or abstraction issue worth an inline comment.
  • Concurrency: Result buffers and their schema policy are scoped to a query; local and remote readers consume the stored schema. I found no new shared mutable state, lock-order change, or independently substantiated race.
  • Lifecycle and ownership: Arrow buffers, extension restoration, sliced arrays, nullable values, and temporary Variant builders were traced through creation, conversion, and release. Malformed input returns an error before insertion; no distinct leak or dangling ownership path was substantiated.
  • Configuration: There is no new dynamic configuration item. The optional FE-to-BE Flight flag selects schema metadata policy; its absent case does not preserve the previous Variant physical type, as the inline P1 explains.
  • Compatibility and wire definitions: PColumnMeta.varbinary_length id 13 and TResultSink.enable_arrow_type_metadata id 4 are optional and absent or same-meaning on origin branches 3.1, 4.0, 4.1, and 4.2. An absent Varbinary length remains -1. The remaining rolling-upgrade defects are the new inline P1 and the existing scanner/status threads.
  • Parallel paths: I checked both FE result-sink construction paths, ordinary and parallel BE result buffers, local and remote DoGet, schema RPC, GetTables, ADBC FileScannerV2, and Paimon/Iceberg/Parquet conversions. The Paimon writer thread is fixed; the scanner thread remains applicable.
  • Conditional checks and errors: Native Variant shape/payload validation and unsupported-type errors have concrete failure paths. The existing P2 thread covers the Flight boundary's loss of an actionable UNIMPLEMENTED status.
  • Tests and results: BE/FE unit tests, Flight/ADBC/Flink regressions, golden output, and sample clients were inspected. They cover the main new data shapes but the legacy-schema BE test codifies the old-FE/new-BE physical change; it does not prove compatibility. The existing P3 thread covers test cleanup. This review was static only: no build, test, or CI result is claimed.
  • Observability: Existing status and logging paths appear sufficient for the new conversion paths apart from the already-reported Flight status wrapping. I found no additional metric or logging defect.
  • Transactions and persistence: No transaction, EditLog, visible-version, or persisted catalog-state path changes here.
  • Data writes: Paimon and Iceberg Arrow writer dispatch and fixed-width handling were traced. No new transaction atomicity or crash-recovery defect was substantiated; Paimon's prior value-first issue is resolved.
  • FE/BE variables: Both FE Flight result-sink constructors set the optional flag, and BE reads it. Old FE plans omit it; the inline P1 is the resulting capability-handling defect.
  • Performance and other issues: Schema recursion is proportional to schema shape; row conversion and Variant compaction paths revealed no separate substantiated CPU, memory, or correctness issue after the final sweep.

Existing P0/P1 findings confirmed for this head: #68883 (comment)

Status ArrowFlightSchemaConvertor::convert_to_arrow_type(
const DataTypePtr& type, std::shared_ptr<arrow::DataType>* result) const {
// Flight always uses native Variant, including recursively converted children.
if (type->get_primitive_type() == TYPE_VARIANT) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[P1] Preserve UTF8 Variant for an FE without the Flight capability. An old FE omits enable_arrow_type_metadata, so ResultSinkOperatorX selects LegacyArrowFlightSchemaConvertor, but it inherits this native Variant mapping. The new BE consequently advertises and sends arrow.parquet.variant/STRUCT through both Flight readers, while the old FE GetTables still describes Variant as UTF8 and pre-upgrade clients expect JSON text. During an old-FE/new-BE rolling upgrade, discovery and query schemas disagree and the result wire type changes. Gate native Variant output on an explicit FE capability and keep the UTF8 path for older plans. This is separate from the existing memory-scratch scanner thread.

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	16816	5575	5536	5536
q2	2106	296	238	238
q3	10028	1392	828	828
q4	4663	474	346	346
q5	7526	796	532	532
q6	190	183	158	158
q7	762	797	604	604
q8	9349	1313	1057	1057
q9	5749	4438	4423	4423
q10	6825	1284	1025	1025
q11	427	252	243	243
q12	630	396	285	285
q13	18097	3102	2380	2380
q14	283	284	250	250
q15	q16	749	729	670	670
q17	1181	739	573	573
q18	7022	6247	6184	6184
q19	1098	952	595	595
q20	389	344	230	230
q21	5157	2608	2591	2591
q22	409	345	297	297
Total cold run time: 99456 ms
Total hot run time: 29045 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	6476	6467	6508	6467
q2	717	597	582	582
q3	5617	5719	5270	5270
q4	2297	2184	1563	1563
q5	5710	5760	5728	5728
q6	262	199	152	152
q7	2266	1977	1863	1863
q8	3127	2808	2789	2789
q9	8254	7978	7751	7751
q10	3658	3576	3243	3243
q11	610	407	399	399
q12	673	700	511	511
q13	2733	3066	2365	2365
q14	290	286	259	259
q15	q16	673	695	616	616
q17	7806	7003	6944	6944
q18	13137	12265	13080	12265
q19	922	776	780	776
q20	2205	2163	1930	1930
q21	5786	4682	4811	4682
q22	493	442	432	432
Total cold run time: 73712 ms
Total hot run time: 66587 ms

@hello-stephen

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

query5	4387	601	446	446
query6	423	223	230	223
query7	4827	438	220	220
query8	317	184	161	161
query9	8760	3967	4005	3967
query10	471	309	255	255
query11	5854	3423	3205	3205
query12	149	91	85	85
query13	1267	453	353	353
query14	6536	4813	4494	4494
query14_1	4214	4231	4211	4211
query15	211	206	181	181
query16	949	461	443	443
query17	858	657	545	545
query18	2421	426	301	301
query19	206	164	135	135
query20	84	78	77	77
query21	209	138	113	113
query22	13027	13125	12877	12877
query23	13194	12499	12087	12087
query23_1	12180	12275	12270	12270
query24	6984	843	464	464
query24_1	472	473	502	473
query25	542	422	366	366
query26	1252	253	140	140
query27	2780	435	268	268
query28	4514	1933	1905	1905
query29	1531	612	448	448
query30	289	223	185	185
query31	895	773	652	652
query32	137	93	92	92
query33	501	301	243	243
query34	890	850	500	500
query35	760	762	650	650
query36	827	807	735	735
query37	129	103	93	93
query38	1784	1758	1694	1694
query39	696	719	680	680
query39_1	680	663	670	663
query40	222	125	98	98
query41	71	70	69	69
query42	85	81	80	80
query43	363	376	338	338
query44	1342	696	706	696
query45	181	184	167	167
query46	859	958	574	574
query47	3025	3026	2928	2928
query48	294	301	214	214
query49	555	394	291	291
query50	677	273	205	205
query51	10456	10227	10280	10227
query52	85	83	68	68
query53	184	207	151	151
query54	234	203	172	172
query55	74	69	63	63
query56	240	220	197	197
query57	1590	1582	1566	1566
query58	274	262	239	239
query59	2352	2393	2111	2111
query60	274	233	221	221
query61	142	137	150	137
query62	385	334	286	286
query63	190	162	162	162
query64	2686	957	773	773
query65	3426	3376	3347	3347
query66	1773	418	301	301
query67	20290	20163	19854	19854
query68	2987	995	596	596
query69	379	274	248	248
query70	931	846	842	842
query71	314	225	203	203
query72	2794	2819	2318	2318
query73	519	523	296	296
query74	4610	4444	4339	4339
query75	2332	2284	1936	1936
query76	2175	1012	626	626
query77	348	385	290	290
query78	9216	8925	8458	8458
query79	954	847	514	514
query80	706	427	330	330
query81	553	317	266	266
query82	545	136	106	106
query83	302	193	175	175
query84	325	120	95	95
query85	827	424	357	357
query86	370	240	228	228
query87	2028	1951	1846	1846
query88	3598	2687	2667	2667
query89	336	291	267	267
query90	1752	179	174	174
query91	161	150	122	122
query92	92	84	90	84
query93	986	990	554	554
query94	490	286	266	266
query95	585	413	320	320
query96	659	516	237	237
query97	2446	2416	2296	2296
query98	174	149	145	145
query99	780	768	659	659
Total cold run time: 233553 ms
Total hot run time: 151648 ms

@hello-stephen

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

query1	0.00	0.00	0.01
query2	0.14	0.08	0.08
query3	0.38	0.21	0.18
query4	1.61	0.21	0.21
query5	0.30	0.30	0.30
query6	1.17	0.66	0.66
query7	0.04	0.01	0.00
query8	0.09	0.07	0.07
query9	0.49	0.38	0.38
query10	0.57	0.56	0.57
query11	0.33	0.20	0.18
query12	0.33	0.18	0.18
query13	0.51	0.53	0.53
query14	0.90	0.87	0.89
query15	0.68	0.59	0.59
query16	0.36	0.36	0.36
query17	1.04	1.03	1.03
query18	0.31	0.29	0.28
query19	2.00	1.86	1.82
query20	0.02	0.02	0.02
query21	15.39	0.34	0.30
query22	4.80	0.13	0.13
query23	15.84	0.48	0.29
query24	2.43	0.55	0.40
query25	0.15	0.11	0.11
query26	0.78	0.28	0.21
query27	0.10	0.09	0.10
query28	3.42	0.83	0.41
query29	12.45	4.30	3.35
query30	0.39	0.24	0.22
query31	2.76	0.62	0.36
query32	3.22	0.64	0.51
query33	3.01	2.95	3.04
query34	15.82	4.08	3.45
query35	3.40	3.38	3.39
query36	0.60	0.51	0.49
query37	0.13	0.10	0.09
query38	0.07	0.06	0.07
query39	0.06	0.06	0.06
query40	0.20	0.16	0.16
query41	0.10	0.06	0.05
query42	0.06	0.06	0.06
query43	0.08	0.06	0.06
Total cold run time: 96.53 s
Total hot run time: 25.49 s

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 88.71% (55/62) 🎉
Increment coverage report
Complete coverage report

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 96.52% (194/201) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 76.81% (35335/46004)
Line Coverage 62.05% (399814/644386)
Region Coverage 58.43% (337284/577278)
Branch Coverage 59.36% (155359/261742)

@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 80.65% (50/62) 🎉
Increment coverage report
Complete coverage report

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.

3 participants