Skip to content

[fix](be) Export byte-backed aggregate states as Parquet binary - #66305

Draft
zclllyybb wants to merge 1 commit into
apache:masterfrom
zclllyybb:agent/fix-agg-state-parquet-binary
Draft

[fix](be) Export byte-backed aggregate states as Parquet binary#66305
zclllyybb wants to merge 1 commit into
apache:masterfrom
zclllyybb:agent/fix-agg-state-parquet-binary

Conversation

@zclllyybb

@zclllyybb zclllyybb commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: DORIS-27625

Related PR: #50769

Problem Summary:

Parquet OUTFILE derived Arrow schemas from the physical serialized type of aggregate-state columns. String-backed states were labeled as UTF-8, while fixed-length states could not be mapped to Arrow. The import path also interpreted exported byte-backed state payloads as text and did not validate fixed-length payload widths.

Aggregate states do not all have the same physical representation. String and FixedLengthObject states are raw bytes, while Array, Map, Bitmap, and other complex states use their native columns and SerDes. Mapping every AggState to Arrow Binary mismatched complex SerDes with BinaryBuilder and caused a BE SIGABRT in the existing array_agg OUTFILE regression.

This PR exports only byte-backed aggregate states as Arrow Binary, preserves native Arrow types for complex states, restores raw payloads into byte-backed state columns, and rejects malformed fixed-size payloads.

Release note

Parquet OUTFILE now exports byte-backed aggregate-state columns as binary and supports round-trip import of fixed-length states. Complex aggregate states retain their native Parquet representation.

Check List (For Author)

  • Test

    • Regression test
    • Unit Test
    • Manual test (local ASAN cluster, including the array_agg coredump suite)
    • No need to test or manual test. Explain why:
      • This is a refactor/code format and no logic has been changed.
      • Previous test can cover this change.
      • No code files have been changed.
      • Other reason
  • Behavior changed:

    • No.
    • Yes. Byte-backed aggregate-state columns in Parquet OUTFILE use binary encoding, complex states retain native encoding, and fixed-length states are imported as raw bytes with width validation.
  • Does this need documentation?

    • No.
    • Yes.

Check List (For Reviewer who merge this PR)

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

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

@zclllyybb

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 completed for head 284c90e. Requesting changes for one performance regression.

Checkpoint conclusions:

  • Goal and correctness proof: Aggregate states are emitted as opaque Parquet binary, valid fixed and variable state bytes round-trip, and malformed fixed widths fail before unsafe insertion or partial output.

  • Scope, focus, and performance: The change is focused, but the early CAST dispatch bypasses the existing identity fast path and copies all String-backed variable states; see the inline finding.

  • Nullable, constant, and error handling: Standard wrappers preserve source null maps and materialize constants; fixed-width errors propagate explicitly without publishing partial output.

  • Concurrency, lifecycle, configuration, persistence, FE/BE propagation, transactions, and observability: No new shared state, lifecycle, configuration, durable Doris format, distributed variable, transaction behavior, or separate observability requirement is introduced.

  • Compatibility and parallel paths: The external Parquet representation intentionally changes to opaque binary as documented; both Parquet reader mappings reach the checked CAST, and FileScannerV2 cannot bypass load conversion. The direct FORMAT_ARROW validation weakness is pre-existing and not changed by this PR.

  • Tests and results: Unit coverage checks Arrow type selection, exact fixed-state bytes, and malformed width; the ordered regression checks fixed, variable, nullable-declared, and non-nullable-declared semantic round trips. Per the review bundle, no local build or test was run; existing style and macOS BE-UT checks are green.

No additional review focus was supplied, so the full PR was reviewed.

// NOLINTNEXTLINE(readability-function-size)
WrapperType prepare_impl(FunctionContext* context, const DataTypePtr& origin_from_type,
const DataTypePtr& origin_to_type) {
if (check_and_get_data_type<DataTypeAggState>(origin_to_type.get()) != nullptr &&

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 identity fast path for String-backed states

This branch runs before the serialized-type equality check below, so a String source cast to a variable AggState whose serialized column is already ColumnString (for example HLL or group_concat) now allocates a new column and copies every state payload row-by-row. Raw Parquet BYTE_ARRAY maps to DataTypeString by default, so the normal OUTFILE-to-stream-load path regresses from O(1) column reuse to O(total state bytes). Let the existing serialized-type equality/identity check run before this specialization; fixed-state and VARBINARY sources would still take the checked byte-copy path.

@zclllyybb

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17755	4155	4115	4115
q2	2088	347	206	206
q3	10259	1485	845	845
q4	4677	476	333	333
q5	7529	875	559	559
q6	179	171	138	138
q7	754	804	593	593
q8	9669	1667	1606	1606
q9	5653	4459	4471	4459
q10	6771	1778	1537	1537
q11	529	360	339	339
q12	754	598	486	486
q13	18132	3353	2774	2774
q14	268	268	251	251
q15	q16	784	783	710	710
q17	1030	1073	1014	1014
q18	7007	5662	5584	5584
q19	1314	1253	1132	1132
q20	825	690	607	607
q21	6271	2912	2557	2557
q22	449	379	314	314
Total cold run time: 102697 ms
Total hot run time: 30159 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	5312	4944	4943	4943
q2	305	337	216	216
q3	4971	5376	4683	4683
q4	2034	2133	1354	1354
q5	4978	4564	4725	4564
q6	260	191	133	133
q7	1852	1738	1565	1565
q8	2381	2147	2183	2147
q9	7568	7155	7167	7155
q10	4618	4581	4152	4152
q11	521	377	350	350
q12	721	732	524	524
q13	2960	3355	2749	2749
q14	275	270	247	247
q15	q16	681	687	619	619
q17	1272	1255	1255	1255
q18	7100	6824	6812	6812
q19	1133	1072	1116	1072
q20	2208	2203	1947	1947
q21	5249	4527	4451	4451
q22	513	482	407	407
Total cold run time: 56912 ms
Total hot run time: 51345 ms

@hello-stephen

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

query5	4317	645	465	465
query6	467	222	206	206
query7	4882	636	336	336
query8	330	189	170	170
query9	8762	4141	4116	4116
query10	454	354	291	291
query11	5914	2317	2122	2122
query12	158	103	101	101
query13	1278	632	438	438
query14	6222	5193	4892	4892
query14_1	4259	4288	4234	4234
query15	219	205	180	180
query16	1045	480	482	480
query17	972	759	591	591
query18	2442	488	352	352
query19	212	196	154	154
query20	113	111	107	107
query21	234	166	145	145
query22	13506	13560	13358	13358
query23	17485	16564	16093	16093
query23_1	16257	16338	16270	16270
query24	7701	1798	1270	1270
query24_1	1323	1271	1286	1271
query25	532	442	351	351
query26	1323	384	220	220
query27	2578	583	390	390
query28	4480	2004	2044	2004
query29	1070	626	472	472
query30	345	267	226	226
query31	1120	1087	973	973
query32	112	63	60	60
query33	514	320	242	242
query34	1180	1158	683	683
query35	772	783	674	674
query36	1040	1023	886	886
query37	153	105	93	93
query38	1880	1692	1659	1659
query39	872	882	854	854
query39_1	828	835	840	835
query40	245	162	137	137
query41	67	64	62	62
query42	93	92	93	92
query43	338	340	286	286
query44	1465	804	758	758
query45	194	181	176	176
query46	1030	1268	715	715
query47	2118	2106	2009	2009
query48	380	441	306	306
query49	580	421	308	308
query50	1124	421	337	337
query51	10583	10466	10838	10466
query52	85	88	75	75
query53	268	277	204	204
query54	297	229	213	213
query55	75	72	67	67
query56	314	307	304	304
query57	1297	1300	1202	1202
query58	296	259	267	259
query59	1552	1670	1427	1427
query60	303	288	258	258
query61	155	146	148	146
query62	539	497	431	431
query63	241	214	201	201
query64	2832	1050	910	910
query65	4691	4638	4619	4619
query66	1868	533	405	405
query67	29279	29221	29115	29115
query68	3299	1476	991	991
query69	405	311	275	275
query70	923	840	800	800
query71	373	340	339	339
query72	3209	2878	2373	2373
query73	844	804	427	427
query74	5061	4927	4694	4694
query75	2529	2505	2130	2130
query76	2359	1174	783	783
query77	361	394	281	281
query78	11819	11730	11276	11276
query79	1385	1152	793	793
query80	1288	542	475	475
query81	545	331	288	288
query82	609	160	120	120
query83	380	326	307	307
query84	327	161	134	134
query85	977	593	540	540
query86	416	252	244	244
query87	1832	1816	1758	1758
query88	3792	2814	2799	2799
query89	434	370	337	337
query90	1908	210	205	205
query91	203	207	165	165
query92	62	61	56	56
query93	1707	1583	963	963
query94	712	374	311	311
query95	792	602	486	486
query96	1026	815	359	359
query97	2598	2642	2472	2472
query98	213	216	202	202
query99	1088	1110	987	987
Total cold run time: 263537 ms
Total hot run time: 177703 ms

@hello-stephen

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

query1	0.01	0.00	0.00
query2	0.10	0.05	0.05
query3	0.26	0.14	0.14
query4	1.60	0.13	0.13
query5	0.24	0.22	0.22
query6	1.16	0.83	0.82
query7	0.04	0.01	0.00
query8	0.05	0.04	0.04
query9	0.39	0.31	0.31
query10	0.55	0.54	0.55
query11	0.19	0.13	0.14
query12	0.19	0.14	0.13
query13	0.46	0.46	0.47
query14	1.02	1.01	1.01
query15	0.61	0.59	0.61
query16	0.31	0.34	0.33
query17	1.09	1.09	1.15
query18	0.23	0.20	0.21
query19	2.02	2.03	2.01
query20	0.02	0.01	0.01
query21	15.43	0.19	0.13
query22	4.94	0.05	0.05
query23	16.16	0.30	0.12
query24	2.99	0.43	0.34
query25	0.10	0.05	0.05
query26	0.72	0.22	0.15
query27	0.04	0.05	0.03
query28	3.51	0.94	0.53
query29	12.67	4.12	3.30
query30	0.26	0.15	0.16
query31	2.77	0.59	0.31
query32	3.22	0.59	0.48
query33	3.14	3.20	3.15
query34	15.64	4.26	3.50
query35	3.51	3.52	3.55
query36	0.54	0.45	0.42
query37	0.10	0.06	0.07
query38	0.04	0.04	0.03
query39	0.03	0.03	0.03
query40	0.17	0.17	0.15
query41	0.08	0.03	0.04
query42	0.04	0.03	0.03
query43	0.05	0.04	0.03
Total cold run time: 96.69 s
Total hot run time: 24.8 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 90.91% (30/33) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 59.06% (25576/43302)
Line Coverage 43.15% (256455/594371)
Region Coverage 38.84% (203205/523140)
Branch Coverage 40.17% (92650/230631)

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 90.91% (30/33) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 66.99% (28292/42231)
Line Coverage 51.42% (303550/590383)
Region Coverage 48.09% (252391/524881)
Branch Coverage 49.51% (114207/230663)

Parquet OUTFILE previously derived Arrow schemas from an aggregate state serialized type. String-backed states were labeled as UTF-8, while fixed-length states could not be mapped to Arrow. The first fix overcorrected this by mapping every AggState to Binary. DataTypeAggState delegates its column and SerDe to the physical serialized type, so complex states such as array_agg still use ArraySerDe. Pairing that SerDe with BinaryBuilder caused the P0/Cloud P0 SIGABRT.

Classify an AggState as raw bytes only when its physical serialized type is String or FixedLengthObject. Export those states as Arrow Binary and keep Array, Map, Bitmap, and other complex states on their native Arrow/SerDe path. On import, preserve serialized-type identity before the raw-byte cast, limit that cast to byte-backed states, and validate fixed-width payloads through nullable wrappers.

Add unit coverage for raw-byte schema mapping, real Array AggState record-batch conversion, cast identity, valid fixed-size payloads, and malformed widths. Keep regression coverage for string/fixed states and validate the existing array and bitmap sibling suites on an ASAN local cluster.

Verification:

- GLIBC_COMPATIBILITY=OFF CMAKE_BUILD_DIR=/mnt/disk6/common/doris-27625-zhaochangle/ut_build_ASAN ./run-be-ut.sh -j 90 --run --filter=Params/DataTypeAggStateTest.* (30/30 passed)

- GLIBC_COMPATIBILITY=OFF ./build.sh --be --fe --be-extension-ignore avro-scanner -j 90

- ./run-regression-test.sh --run -d query_p0/outfile/agg_state_array -s test_outfile_agg_state_array

- ./run-regression-test.sh --run -d query_p0/outfile/agg_state -s test_outfile_agg_state

- ./run-regression-test.sh --run -d query_p0/outfile/agg_state_bitmap -s test_outfile_agg_state_bitmap

- build-support/check-format.sh with clang-format 16

- git diff --check
@zclllyybb
zclllyybb force-pushed the agent/fix-agg-state-parquet-binary branch from 284c90e to e3fcf58 Compare July 31, 2026 07:32
@zclllyybb zclllyybb changed the title [fix](be) Export aggregate states as Parquet binary [fix](be) Export byte-backed aggregate states as Parquet binary Jul 31, 2026
@zclllyybb

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17686	4025	3961	3961
q2	2069	330	201	201
q3	10211	1404	850	850
q4	4687	478	339	339
q5	7544	830	549	549
q6	185	170	140	140
q7	735	809	606	606
q8	9977	1612	1529	1529
q9	5867	4076	4058	4058
q10	6815	1632	1372	1372
q11	517	345	321	321
q12	751	580	467	467
q13	18153	3274	2762	2762
q14	263	263	256	256
q15	q16	734	729	655	655
q17	925	1079	955	955
q18	6809	5737	5540	5540
q19	1190	1270	1033	1033
q20	794	683	566	566
q21	6116	2729	2626	2626
q22	462	379	319	319
Total cold run time: 102490 ms
Total hot run time: 29105 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4931	4712	4746	4712
q2	306	360	295	295
q3	4938	5150	4764	4764
q4	2238	2305	1414	1414
q5	4633	4671	4478	4478
q6	231	175	127	127
q7	1873	1735	1508	1508
q8	2389	1935	1939	1935
q9	6798	6696	6828	6696
q10	4229	4229	3823	3823
q11	512	375	341	341
q12	693	713	500	500
q13	3040	3361	2824	2824
q14	280	285	253	253
q15	q16	664	685	611	611
q17	1249	1221	1225	1221
q18	7387	6781	6742	6742
q19	1085	1087	1085	1085
q20	2230	2201	1950	1950
q21	5321	4637	4440	4440
q22	507	477	406	406
Total cold run time: 55534 ms
Total hot run time: 50125 ms

@hello-stephen

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

query5	4314	616	464	464
query6	472	214	197	197
query7	4861	576	354	354
query8	351	180	165	165
query9	8749	4011	4054	4011
query10	486	342	306	306
query11	5845	2214	2023	2023
query12	150	97	98	97
query13	1272	599	416	416
query14	6066	4649	4457	4457
query14_1	3823	3791	3828	3791
query15	204	200	173	173
query16	1040	483	456	456
query17	1115	668	545	545
query18	2457	458	331	331
query19	223	196	141	141
query20	104	99	102	99
query21	234	160	134	134
query22	13095	12949	12771	12771
query23	17302	16395	16095	16095
query23_1	16081	16102	16125	16102
query24	7629	1694	1236	1236
query24_1	1249	1242	1213	1213
query25	549	426	350	350
query26	1315	365	204	204
query27	2584	571	374	374
query28	4478	2000	2026	2000
query29	1098	627	474	474
query30	349	267	220	220
query31	1096	1091	950	950
query32	103	59	59	59
query33	543	310	244	244
query34	1179	1128	645	645
query35	728	746	647	647
query36	783	780	715	715
query37	155	107	89	89
query38	1861	1661	1613	1613
query39	840	821	803	803
query39_1	790	782	789	782
query40	246	160	146	146
query41	81	82	67	67
query42	104	94	93	93
query43	317	319	269	269
query44	1410	777	753	753
query45	178	174	171	171
query46	1058	1156	696	696
query47	1536	1530	1416	1416
query48	427	402	298	298
query49	590	394	324	324
query50	1069	434	358	358
query51	10429	10479	10161	10161
query52	92	86	76	76
query53	251	272	204	204
query54	289	231	235	231
query55	83	69	67	67
query56	293	282	290	282
query57	1031	988	927	927
query58	291	255	257	255
query59	1506	1562	1384	1384
query60	316	269	259	259
query61	151	152	153	152
query62	410	320	262	262
query63	237	189	194	189
query64	2880	1182	970	970
query65	3948	3830	3828	3828
query66	1867	478	367	367
query67	28158	28184	28015	28015
query68	3206	1585	1000	1000
query69	402	294	263	263
query70	900	789	792	789
query71	386	329	321	321
query72	2968	2627	2315	2315
query73	807	741	441	441
query74	4592	4510	4308	4308
query75	2390	2325	2004	2004
query76	2365	1135	763	763
query77	336	374	268	268
query78	11070	11031	10549	10549
query79	1397	1145	728	728
query80	658	532	459	459
query81	459	341	282	282
query82	556	149	118	118
query83	412	315	303	303
query84	280	164	133	133
query85	954	614	514	514
query86	330	226	221	221
query87	1806	1790	1723	1723
query88	3709	2825	2752	2752
query89	400	318	292	292
query90	1877	201	194	194
query91	201	187	167	167
query92	63	60	53	53
query93	1504	1686	962	962
query94	539	366	298	298
query95	794	582	496	496
query96	1067	810	381	381
query97	2481	2455	2328	2328
query98	218	194	194	194
query99	726	721	619	619
Total cold run time: 254890 ms
Total hot run time: 168859 ms

@hello-stephen

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

query1	0.01	0.01	0.00
query2	0.11	0.05	0.05
query3	0.28	0.13	0.13
query4	1.61	0.14	0.15
query5	0.24	0.22	0.22
query6	1.16	0.82	0.79
query7	0.04	0.02	0.00
query8	0.05	0.03	0.03
query9	0.37	0.31	0.32
query10	0.54	0.54	0.54
query11	0.19	0.13	0.14
query12	0.18	0.14	0.14
query13	0.46	0.45	0.46
query14	1.00	0.98	0.99
query15	0.62	0.57	0.60
query16	0.32	0.32	0.31
query17	1.08	1.09	1.07
query18	0.21	0.19	0.20
query19	2.03	1.95	1.94
query20	0.01	0.01	0.02
query21	15.46	0.23	0.13
query22	4.79	0.05	0.05
query23	16.13	0.31	0.12
query24	3.00	0.43	0.32
query25	0.12	0.05	0.03
query26	0.75	0.20	0.16
query27	0.04	0.04	0.04
query28	3.43	0.80	0.38
query29	12.49	4.05	3.15
query30	0.28	0.16	0.17
query31	2.76	0.54	0.32
query32	3.23	0.58	0.51
query33	3.15	3.22	3.30
query34	15.60	3.90	3.30
query35	3.21	3.21	3.26
query36	0.57	0.45	0.43
query37	0.08	0.06	0.06
query38	0.04	0.04	0.03
query39	0.04	0.02	0.03
query40	0.17	0.15	0.15
query41	0.08	0.04	0.03
query42	0.04	0.03	0.03
query43	0.04	0.04	0.03
Total cold run time: 96.01 s
Total hot run time: 23.88 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 89.36% (42/47) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 75.79% (32025/42253)
Line Coverage 60.41% (356910/590845)
Region Coverage 56.97% (299414/525530)
Branch Coverage 58.47% (135099/231070)

@zclllyybb

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 summary

This change correctly maps byte-backed AggState payloads to Arrow Binary and keeps complex states on their native builders, but internally nullable fixed-state round trips still fail in both directions. Requesting changes for the two data-correctness defects below; the existing String identity-copy thread is resolved at the current head.

Checkpoint conclusions:

  • Goal and tests: The non-null fixed and representative complex paths are covered, but max_state(NULL) is omitted and fails both export and load as described inline.
  • Scope and conditions: The implementation is focused and the raw-byte predicate is narrow; shared Flight and Python consumers were inspected and their Binary builder/SerDe types agree.
  • Concurrency, lifecycle, configuration, persistence, transactions, and FE-BE variables: No new mechanism in these categories is introduced. OUTFILE and stream-load transaction boundaries are unchanged.
  • Compatibility and parallel paths: Parquet export/import and the shared Arrow schema consumers were traced. The Utf8-to-Binary schema change correctly describes opaque bytes; no separate incompatibility was demonstrated.
  • Error handling and observability: Status propagation and malformed-width context are adequate; this local conversion path does not need new metrics or logs. Null-source handling remains incorrect as described inline.
  • Memory and performance: Destination ownership, reservation, COW behavior, and allocator use are sound. Serialized-type identity precedes the copy path, resolving the prior performance comment.
  • Data correctness and BE nullable handling: Two P1 defects remain: serialized nullability is absent from the Arrow field and the load cast loses the nullable source map.
  • Test results: The deterministic expected output is consistent with the added non-null data. No builds or tests were run in this review because the authoritative task requires static review only; current PR checks are green.
  • Other applicable checkpoints: No additional valuable finding survived the full upstream/downstream review.

Status convert_to_arrow_type(const DataTypePtr& origin_type,
std::shared_ptr<arrow::DataType>* result,
const std::string& timezone) {
if (is_raw_byte_agg_state(origin_type)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[P1] Preserve serialized AggState nullability in the Arrow field

A legal agg_state<max(int null)> stores max_state(NULL) as an internally nullable FixedLengthObject, even though the outer AggState is deliberately non-nullable. This branch emits that state through a Binary builder, but the Parquet schema still takes field nullability from root()->is_nullable() (false), making the byte column required and leaving no definition level for the internal null. Please derive Arrow field nullability from the AggState's serialized type and cover a max_state(NULL) Parquet round trip.

}

const auto value = source.get_data_at(row);
if (fixed_result != nullptr && value.size != fixed_result->item_size()) {

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] Propagate nullable binary sources before checking state width

FileScanner makes the Parquet byte column Nullable, but the target AggState's outer type is non-nullable, so prepare_remove_nullable() does not pass this source null map here. For a null row, ColumnNullable::get_data_at() therefore returns a zero-byte value and this check rejects it as malformed before the internally nullable fixed-state destination can preserve the null. Please unwrap/propagate source nulls for byte-to-AggState casts (while still rejecting nulls for a non-nullable serialized target) and add a nullable fixed-state load case.

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.

2 participants