Skip to content

[fix](be) Count complex Parquet structs safely#65495

Open
Gabriel39 wants to merge 1 commit into
apache:masterfrom
Gabriel39:codex/fix-parquet-count-complex-struct
Open

[fix](be) Count complex Parquet structs safely#65495
Gabriel39 wants to merge 1 commit into
apache:masterfrom
Gabriel39:codex/fix-parquet-count-complex-struct

Conversation

@Gabriel39

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: N/A

Related PR: N/A

Problem Summary:

Parquet COUNT pushdown uses one representative leaf to count the top-level null state of a complex column. When a STRUCT contains an ARRAY or MAP descendant, the representative levels are repeated. The previous code compared repetition levels with the STRUCT root repetition level, which is zero, skipped every level entry, and triggered a DORIS_CHECK that aborted the BE. It also derived the non-null threshold from the repeated leaf definition level and could count a NULL struct as non-null.

This change identifies top-level rows with repetition level zero and uses the root schema's nullable definition level to determine whether the top-level complex value is non-null. Empty and NULL collections inside a non-null STRUCT remain valid STRUCT rows.

Release note

Fix BE aborts and incorrect COUNT results for Parquet STRUCT columns containing ARRAY or MAP descendants.

Check List (For Author)

  • Test: Unit Test
    • NewParquetReaderTest.CountStructWithRepeatedChildUsesTopLevelRowBoundaries
    • Existing STRUCT, LIST, and MAP COUNT pushdown tests
  • Behavior changed: Yes. COUNT pushdown uses top-level row/null semantics for repeated descendants.
  • Does this need documentation: No

Validation on the designated Linux build host:

  • build-support/check-format.sh
  • Targeted BE unit tests: 4 tests passed
  • run-clang-tidy.sh: test file has no warnings; production analysis reports pre-existing full-file diagnostics and jni-util.h toolchain static assertions unrelated to this change.

### What problem does this PR solve?

Issue Number: N/A

Related PR: N/A

Problem Summary: Parquet COUNT pushdown used a STRUCT root repetition level to identify top-level rows when a representative leaf was repeated. Because the STRUCT repetition level is zero, all level entries were skipped and a correctness check aborted the BE. The non-null threshold also used the repeated leaf definition level and could count NULL structs. Identify top-level rows with repetition level zero and use the root nullable definition level so STRUCT columns containing ARRAY or MAP children are counted correctly.

### Release note

Fix BE aborts and incorrect COUNT results for Parquet STRUCT columns containing repeated children.

### Check List (For Author)

- Test: Unit Test
    - NewParquetReaderTest targeted complex STRUCT and existing complex COUNT tests
- Behavior changed: Yes, COUNT pushdown handles repeated descendants using top-level row semantics.
- 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?

@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39 Gabriel39 marked this pull request as ready for review July 12, 2026 06:02
@Gabriel39 Gabriel39 requested a review from yiguolei as a code owner July 12, 2026 06:02
@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.

I reviewed the two-file Parquet COUNT pushdown change and did not find a blocking issue that needs an inline comment.

Critical checkpoint conclusions:

  • Goal/test: The patch targets COUNT(col) over Parquet STRUCT columns whose representative shape leaf is under a repeated descendant. The implementation now counts top-level rows by rep_level == 0 and uses the root nullable definition level; the added BE unit test covers nullable STRUCT rows with a repeated LIST child in both child orders.
  • Scope: The change is small and limited to the level-counting helper plus a focused test fixture.
  • Parallel paths: COUNT(*) still uses the empty-column row-count path, MIN/MAX is unchanged, and the COUNT(col) request contract still passes a top-level complex column only when exactly one directly mapped complex scan column is projected. I traced the shape-reader path through scalar/list/map/struct nested readers.
  • Concurrency/lifecycle/config/persistence: No new concurrency, lifecycle ownership, config, edit-log, transaction, or persistence behavior is introduced.
  • Compatibility: No Thrift, storage-format, or mixed-version protocol change is introduced.
  • Error handling/data correctness: Existing status/DORIS_CHECK handling remains in place; the new comparison matches the file-reader contract that COUNT(col) should count top-level nullness.
  • Performance/observability: The levels-only path still avoids value materialization for heavy nested leaves; no new observability appears necessary for this narrow fix.
  • Test coverage: The new unit test is deterministic and reaches get_aggregate_result() for the changed path. I could not run BE UTs in this runner because .worktree_initialized, thirdparty/installed, and thirdparty/installed/bin/protoc are absent, so validation here was static plus git diff --check after fetching the exact base commit.

User focus: No additional user-provided focus points were present.

Subagent conclusions: The optimizer-rewrite lane found no semantic-equivalence or reader row-boundary issue. The tests-session-config lane found no test/session/config/style candidate. After the final ledger update, both live subagents reviewed the same no-inline-comments ledger/comment set and replied NO_NEW_VALUABLE_FINDINGS.

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 100.00% (2/2) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 56.90% (23542/41373)
Line Coverage 40.57% (230197/567439)
Region Coverage 36.46% (181863/498738)
Branch Coverage 37.54% (81194/216281)

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17862	4074	4146	4074
q2	2041	316	194	194
q3	10297	1417	801	801
q4	4684	463	333	333
q5	7488	857	567	567
q6	180	164	138	138
q7	772	832	628	628
q8	9345	1417	1484	1417
q9	6007	4380	4342	4342
q10	6741	1793	1519	1519
q11	508	351	308	308
q12	703	541	422	422
q13	18089	3248	2738	2738
q14	270	260	238	238
q15	q16	786	786	719	719
q17	949	963	938	938
q18	6942	5685	5467	5467
q19	1239	1226	1078	1078
q20	779	624	519	519
q21	5814	2543	2558	2543
q22	420	353	297	297
Total cold run time: 101916 ms
Total hot run time: 29280 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4319	4246	4242	4242
q2	285	321	217	217
q3	4516	4927	4413	4413
q4	2041	2123	1356	1356
q5	4414	4302	4314	4302
q6	226	178	126	126
q7	1732	1648	1922	1648
q8	2503	2084	2147	2084
q9	7860	7796	7738	7738
q10	4725	4721	4227	4227
q11	564	437	368	368
q12	756	744	544	544
q13	3384	3602	2949	2949
q14	308	304	283	283
q15	q16	713	754	649	649
q17	1338	1358	1311	1311
q18	8062	7185	7065	7065
q19	1052	1081	1055	1055
q20	2205	2192	1937	1937
q21	5195	4534	4423	4423
q22	518	472	405	405
Total cold run time: 56716 ms
Total hot run time: 51342 ms

@hello-stephen

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

query5	4316	621	496	496
query6	484	224	188	188
query7	4856	550	324	324
query8	336	196	171	171
query9	8792	4089	4057	4057
query10	489	344	278	278
query11	5924	2331	2145	2145
query12	153	103	125	103
query13	1249	601	439	439
query14	6252	5299	4999	4999
query14_1	4380	4383	4351	4351
query15	220	207	176	176
query16	993	462	428	428
query17	922	706	566	566
query18	2423	459	339	339
query19	214	184	141	141
query20	110	109	104	104
query21	229	155	130	130
query22	13665	13618	13418	13418
query23	17412	16521	16149	16149
query23_1	16257	16209	16367	16209
query24	7518	1758	1320	1320
query24_1	1338	1357	1335	1335
query25	567	474	396	396
query26	1352	361	207	207
query27	2591	604	389	389
query28	5010	2021	2049	2021
query29	1101	628	492	492
query30	323	272	223	223
query31	1130	1107	991	991
query32	112	64	70	64
query33	544	331	271	271
query34	1132	1160	672	672
query35	763	788	694	694
query36	1393	1381	1230	1230
query37	157	115	107	107
query38	1877	1724	1677	1677
query39	948	924	890	890
query39_1	902	889	884	884
query40	237	162	145	145
query41	70	73	70	70
query42	97	93	95	93
query43	331	329	289	289
query44	1479	811	780	780
query45	203	188	185	185
query46	1079	1230	776	776
query47	2352	2326	2296	2296
query48	413	387	305	305
query49	599	438	335	335
query50	1039	432	341	341
query51	10803	10802	10782	10782
query52	88	89	82	82
query53	285	294	211	211
query54	298	257	227	227
query55	77	74	70	70
query56	306	332	297	297
query57	1445	1405	1332	1332
query58	285	271	274	271
query59	1589	1623	1496	1496
query60	342	276	290	276
query61	145	151	148	148
query62	693	648	584	584
query63	234	199	208	199
query64	2855	1052	866	866
query65	4861	4800	4776	4776
query66	1832	497	381	381
query67	29434	29383	29341	29341
query68	3070	1585	921	921
query69	396	297	269	269
query70	1111	962	980	962
query71	361	326	303	303
query72	3098	2892	2398	2398
query73	800	831	474	474
query74	5114	4929	4758	4758
query75	2599	2592	2257	2257
query76	2366	1175	793	793
query77	350	380	296	296
query78	12305	12475	11892	11892
query79	1403	1190	735	735
query80	1310	580	449	449
query81	535	325	279	279
query82	593	161	127	127
query83	377	314	307	307
query84	324	154	125	125
query85	952	587	523	523
query86	430	293	294	293
query87	1858	1824	1794	1794
query88	3784	2819	2810	2810
query89	456	404	371	371
query90	1932	205	200	200
query91	199	186	160	160
query92	65	61	58	58
query93	1677	1610	1000	1000
query94	724	370	336	336
query95	792	588	456	456
query96	993	827	357	357
query97	2719	2693	2594	2594
query98	214	203	202	202
query99	1154	1174	1027	1027
Total cold run time: 266389 ms
Total hot run time: 180787 ms

@hello-stephen

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

query1	0.00	0.00	0.00
query2	0.09	0.05	0.05
query3	0.25	0.13	0.13
query4	1.61	0.14	0.14
query5	0.24	0.25	0.22
query6	1.21	1.11	1.12
query7	0.04	0.01	0.00
query8	0.06	0.04	0.04
query9	0.39	0.31	0.33
query10	0.55	0.56	0.57
query11	0.20	0.13	0.13
query12	0.18	0.14	0.14
query13	0.47	0.48	0.48
query14	1.01	1.00	1.00
query15	0.61	0.59	0.61
query16	0.30	0.33	0.31
query17	1.12	1.06	1.13
query18	0.22	0.21	0.20
query19	2.05	1.97	1.94
query20	0.02	0.01	0.01
query21	15.40	0.18	0.13
query22	4.95	0.05	0.05
query23	16.15	0.31	0.12
query24	2.93	0.41	0.32
query25	0.10	0.05	0.06
query26	0.73	0.20	0.14
query27	0.04	0.04	0.04
query28	3.56	0.92	0.54
query29	12.47	4.02	3.21
query30	0.27	0.15	0.16
query31	2.77	0.60	0.32
query32	3.22	0.59	0.47
query33	3.23	3.18	3.18
query34	15.66	4.26	3.53
query35	3.53	3.54	3.54
query36	0.55	0.42	0.43
query37	0.09	0.07	0.06
query38	0.05	0.03	0.03
query39	0.03	0.03	0.04
query40	0.18	0.16	0.15
query41	0.08	0.03	0.03
query42	0.04	0.03	0.03
query43	0.04	0.03	0.03
Total cold run time: 96.69 s
Total hot run time: 24.99 s

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