Skip to content

[fix](function) Handle constant NULL arrays in array pushback - #68380

Open
Mryange wants to merge 1 commit into
apache:masterfrom
Mryange:fix-array-pushback-null-const
Open

Mryange wants to merge 1 commit into
apache:masterfrom
Mryange:fix-array-pushback-null-const

Conversation

@Mryange

@Mryange Mryange commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

array_pushback and its array_append alias could read past the end of the NULL bitmap when the array argument was a constant NULL column evaluated for multiple rows. This caused unstable NULL propagation and could lead to undefined behavior. The implementation now uses the constant-column row index for both the NULL bitmap and array offsets, preserving scalar NULL semantics across all input rows.

Release note

None

Check List (For Author)

  • Test

    • Regression test
    • Unit Test
    • Manual test (add detailed scripts or steps below)
    • 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.
  • 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

### What problem does this PR solve?

Problem Summary: array_pushback and array_append could read past the end of the NULL bitmap when a constant NULL array was evaluated for multiple rows. Use the constant-column row index consistently for NULL bitmap and array offset access.

### Release note

Fix array_pushback and array_append with constant NULL arrays in multi-row execution.

### Check List (For Author)

- Test: BE build, 396 focused array unit tests, and query_p0 array regression test

- Behavior changed: Yes

- Does this need documentation: No
@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?

@Mryange

Mryange commented Sep 22, 2026

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 opinion: approve; I found no blocking correctness issue in the reviewed head.

Checkpoint conclusions:

  • Goal and proof: the PR fixes the mixed constant/vector path where a constant nullable array has one stored NULL-map row but execute_impl processes multiple logical rows. Reusing src_index = index_check_const(i, src_const) for the NULL map and offsets aligns both subcolumns. The added ordered 16-row cases cover array_pushback and its array_append alias.
  • Scope and clarity: the implementation change is minimal and focused; it also removes duplicate const-index calculations. The expected-output change matches the two new queries.
  • Concurrency and lifecycle: this is per-block scalar-function execution with no shared mutable state, threads, locks, static initialization, or special resource lifecycle.
  • Configuration and compatibility: no configuration, protocol, persisted format, function symbol, FE-BE variable, or rolling-upgrade contract changes.
  • Parallel paths and conditions: array_append resolves to the same FE/BE implementation. array_pushfront is already safe because it materializes constant inputs before row-wise access. The top-level NULL branch sets the result NULL/offset and exits before nested-array access; non-constant sources retain row i behavior.
  • Error, memory, and nullable safety: no Status is discarded and no ownership/allocation behavior changes. unpack_if_const exposes the constant's one-row payload, and ColumnArray offsets use the padded container whose row-zero predecessor is intentionally defined as zero.
  • Tests and results: the queries are deterministic via ORDER BY number, exercise more than the one physical constant row, and the recorded sixteen NULL results per name are correct. Per the review-runner constraint, this was static review only: I did not build or run the regression suite, and I did not independently regenerate the .out file.
  • Observability, persistence, and writes: no new logging/metrics are needed; transactions, EditLog/replay, storage visibility, delete bitmaps, and data-write atomicity are not involved.
  • Performance and other risks: the loop keeps the same asymptotic work and slightly reduces repeated branching. No security, build-hygiene, glibc-baseline, or additional correctness concern was found.
  • User focus: no additional review focus was supplied; the full PR and the constant-NULL/alias paths were reviewed.

@Mryange

Mryange commented Sep 22, 2026

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17624	4024	4198	4024
q2	2224	358	310	310
q3	10071	1447	838	838
q4	4681	478	362	362
q5	7464	836	547	547
q6	179	179	140	140
q7	763	816	623	623
q8	9343	1618	1488	1488
q9	5466	4245	4190	4190
q10	6830	1362	1026	1026
q11	443	287	244	244
q12	638	427	314	314
q13	18050	2657	2002	2002
q14	263	266	243	243
q15	q16	739	721	678	678
q17	1818	1230	1040	1040
q18	6529	5611	5523	5523
q19	1178	1204	1087	1087
q20	496	403	261	261
q21	5426	3521	3073	3073
q22	456	375	323	323
Total cold run time: 100681 ms
Total hot run time: 28336 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4757	5014	4708	4708
q2	756	591	550	550
q3	4804	5178	4592	4592
q4	2314	2367	1498	1498
q5	4565	4428	4648	4428
q6	236	183	136	136
q7	1857	1739	1675	1675
q8	2444	2009	1994	1994
q9	7385	7246	7256	7246
q10	3686	3644	3105	3105
q11	535	380	366	366
q12	738	718	511	511
q13	2287	2646	1996	1996
q14	278	280	243	243
q15	q16	668	688	599	599
q17	7319	6753	6666	6666
q18	11963	11142	11748	11142
q19	1124	1008	1011	1008
q20	2230	2211	1917	1917
q21	4979	4127	4499	4127
q22	527	451	415	415
Total cold run time: 65452 ms
Total hot run time: 58922 ms

@hello-stephen

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

query5	4327	623	471	471
query6	424	214	194	194
query7	4807	562	308	308
query8	322	181	165	165
query9	8806	4009	4047	4009
query10	461	301	256	256
query11	5816	3572	3210	3210
query12	154	89	85	85
query13	1263	597	411	411
query14	6546	4584	4269	4269
query14_1	4002	3966	3961	3961
query15	203	213	185	185
query16	986	475	431	431
query17	932	671	536	536
query18	2464	461	345	345
query19	201	183	145	145
query20	83	86	81	81
query21	226	135	116	116
query22	13077	13094	12835	12835
query23	13942	13237	12514	12514
query23_1	12564	12461	12541	12461
query24	7523	1185	662	662
query24_1	692	732	715	715
query25	576	447	386	386
query26	1274	323	174	174
query27	2663	577	363	363
query28	4562	2002	2014	2002
query29	1595	778	535	535
query30	291	216	185	185
query31	890	771	634	634
query32	144	102	99	99
query33	542	302	258	258
query34	1189	1129	617	617
query35	736	751	638	638
query36	815	805	732	732
query37	149	113	94	94
query38	1821	1778	1673	1673
query39	674	692	650	650
query39_1	641	685	677	677
query40	225	129	106	106
query41	76	72	108	72
query42	96	97	96	96
query43	335	345	292	292
query44	1397	711	741	711
query45	181	179	159	159
query46	1055	1204	718	718
query47	1490	1495	1399	1399
query48	413	386	315	315
query49	584	411	285	285
query50	985	350	258	258
query51	10325	10524	10564	10524
query52	92	89	78	78
query53	241	253	174	174
query54	241	223	190	190
query55	83	75	70	70
query56	229	218	234	218
query57	1442	1438	1359	1359
query58	284	262	262	262
query59	1985	2051	1861	1861
query60	288	241	222	222
query61	147	152	141	141
query62	404	325	271	271
query63	218	172	182	172
query64	2826	1010	838	838
query65	3455	3408	3442	3408
query66	1782	427	313	313
query67	19907	20061	19573	19573
query68	3327	1441	969	969
query69	435	307	267	267
query70	905	822	819	819
query71	303	236	210	210
query72	2611	2503	2252	2252
query73	830	777	419	419
query74	4615	4524	4292	4292
query75	2297	2299	1942	1942
query76	2325	1142	735	735
query77	372	402	295	295
query78	9196	9024	8563	8563
query79	1262	1192	743	743
query80	585	452	375	375
query81	543	326	280	280
query82	619	161	134	134
query83	319	237	192	192
query84	314	149	115	115
query85	840	481	392	392
query86	327	236	240	236
query87	1990	1963	1839	1839
query88	3675	2735	2729	2729
query89	370	291	250	250
query90	1908	190	192	190
query91	222	162	131	131
query92	106	95	91	91
query93	1528	1456	835	835
query94	518	347	316	316
query95	672	463	327	327
query96	1046	788	353	353
query97	2502	2425	2333	2333
query98	176	154	149	149
query99	717	728	610	610
Total cold run time: 236298 ms
Total hot run time: 152878 ms

@hello-stephen

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

query1	0.01	0.00	0.01
query2	0.09	0.05	0.05
query3	0.26	0.14	0.14
query4	1.61	0.14	0.14
query5	0.26	0.23	0.22
query6	1.16	0.93	0.93
query7	0.04	0.01	0.00
query8	0.05	0.04	0.04
query9	0.40	0.33	0.35
query10	0.60	0.54	0.56
query11	0.20	0.15	0.14
query12	0.19	0.16	0.15
query13	0.47	0.47	0.47
query14	0.97	0.95	0.95
query15	0.61	0.59	0.58
query16	0.31	0.33	0.32
query17	1.11	1.09	1.10
query18	0.23	0.21	0.22
query19	2.00	1.90	1.94
query20	0.02	0.01	0.01
query21	15.47	0.21	0.13
query22	4.88	0.05	0.06
query23	16.15	0.32	0.12
query24	2.92	0.43	0.34
query25	0.11	0.04	0.04
query26	0.72	0.20	0.15
query27	0.04	0.04	0.03
query28	3.52	0.77	0.36
query29	12.51	4.02	3.22
query30	0.30	0.14	0.15
query31	2.77	0.56	0.32
query32	3.23	0.59	0.49
query33	3.21	3.13	3.26
query34	15.52	3.96	3.28
query35	3.24	3.24	3.27
query36	0.55	0.44	0.42
query37	0.10	0.07	0.06
query38	0.05	0.04	0.04
query39	0.04	0.03	0.03
query40	0.19	0.15	0.15
query41	0.09	0.04	0.03
query42	0.04	0.03	0.03
query43	0.05	0.04	0.04
Total cold run time: 96.29 s
Total hot run time: 24.05 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 63.91% (29742/46540)
Line Coverage 48.59% (310023/638026)
Region Coverage 44.10% (249876/566657)
Branch Coverage 45.68% (116186/254370)

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 100% (0/0) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 76.24% (34357/45066)
Line Coverage 61.16% (385781/630748)
Region Coverage 57.52% (324640/564372)
Branch Coverage 58.36% (148003/253583)

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