Skip to content

[fix](be) Align cast input nullability for Iceberg struct evolution#65370

Open
Gabriel39 wants to merge 1 commit into
apache:masterfrom
Gabriel39:codex/fix-iceberg-struct-evolution-cast
Open

[fix](be) Align cast input nullability for Iceberg struct evolution#65370
Gabriel39 wants to merge 1 commit into
apache:masterfrom
Gabriel39:codex/fix-iceberg-struct-evolution-cast

Conversation

@Gabriel39

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: None

Related PR: None

Problem Summary: Reading Iceberg struct fields after Spark schema evolution can materialize a column whose root nullability does not match the declared file type used to prepare the cast expression. The cast wrapper unwraps nullable inputs based on the declared input type, so a nullable declared type with a non-nullable actual column can hit an invalid unwrap path and crash BE instead of returning the cast result. This change aligns the declared cast input root nullability with the actual column shape before executing the cast. It also adds a focused BE unit test and an Iceberg regression case that creates a Spark Iceberg struct, evolves col.a from INT to BIGINT, refreshes the Doris catalog, and queries col.a/col.b/col.c with nested pruning enabled.

Release note

None

Check List (For Author)

  • Test: Manual test
    • Ran git diff --check for modified files
    • Ran targeted clang-format v16 wrapper for modified BE C++ files
    • Attempted BE unit test: ./run-be-ut.sh --run --filter=TableReaderTest.ComplexRematerializeCastsNonNullableScalarChildWithNullableFileType:TableReaderTest.ComplexRematerializeCastsScalarChildToTableType, blocked because local thirdparty/installed is incomplete (missing bin/protoc and Snappy)
    • Attempted regression test: ./run-regression-test.sh --run -d external_table_p0/iceberg -s test_iceberg_struct_schema_evolution, blocked because local thirdparty/installed is incomplete (missing bin/thrift)
  • Behavior changed: No
  • Does this need documentation: No

What problem does this PR solve?

Issue Number: close #xxx

Related PR: #xxx

Problem Summary:

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?

Issue Number: None

Related PR: None

Problem Summary: Reading Iceberg struct fields after Spark schema evolution can materialize a column whose root nullability does not match the declared file type used to prepare the cast expression. The cast wrapper unwraps nullable inputs based on the declared input type, so a nullable declared type with a non-nullable actual column can hit an invalid unwrap path and crash BE instead of returning the cast result. This change aligns the declared cast input root nullability with the actual column shape before executing the cast. It also adds a focused BE unit test and an Iceberg regression case that creates a Spark Iceberg struct, evolves col.a from INT to BIGINT, refreshes the Doris catalog, and queries col.a/col.b/col.c with nested pruning enabled.

### Release note

None

### Check List (For Author)

- Test: Manual test
    - Ran git diff --check for modified files
    - Ran targeted clang-format v16 wrapper for modified BE C++ files
    - Attempted BE unit test: ./run-be-ut.sh --run --filter=TableReaderTest.ComplexRematerializeCastsNonNullableScalarChildWithNullableFileType:TableReaderTest.ComplexRematerializeCastsScalarChildToTableType, blocked because local thirdparty/installed is incomplete (missing bin/protoc and Snappy)
    - Attempted regression test: ./run-regression-test.sh --run -d external_table_p0/iceberg -s test_iceberg_struct_schema_evolution, blocked because local thirdparty/installed is incomplete (missing bin/thrift)
- Behavior changed: No
- Does this need documentation: No
@Gabriel39 Gabriel39 requested a review from yiguolei as a code owner July 8, 2026 09:18
@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 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Codex automated review failed and did not complete.

Error: You've hit your usage limit. Visit https://chatgpt.com/codex/settings/usage to purchase more credits or try again at Jul 10th, 2026 6:44 AM.
Workflow run: https://github.com/apache/doris/actions/runs/28931752009

Please inspect the workflow logs and rerun the review after the underlying issue is resolved.

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@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.54% (23210/41051)
Line Coverage 40.10% (225217/561690)
Region Coverage 36.04% (177832/493462)
Branch Coverage 37.10% (79065/213109)

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17765	4173	4261	4173
q2	2020	335	204	204
q3	10270	1445	876	876
q4	4680	466	340	340
q5	7593	870	585	585
q6	190	182	140	140
q7	803	832	615	615
q8	9323	1582	1573	1573
q9	5717	4445	4392	4392
q10	6745	1802	1530	1530
q11	498	358	322	322
q12	725	554	450	450
q13	18176	3320	2729	2729
q14	269	265	261	261
q15	q16	793	775	710	710
q17	1012	927	1011	927
q18	7226	5748	5502	5502
q19	1138	1278	1117	1117
q20	745	659	526	526
q21	5651	2666	2486	2486
q22	436	363	295	295
Total cold run time: 101775 ms
Total hot run time: 29753 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4514	4425	4347	4347
q2	305	328	216	216
q3	4636	4939	4367	4367
q4	2075	2166	1374	1374
q5	4492	4347	4364	4347
q6	225	173	132	132
q7	1743	2381	1678	1678
q8	2652	2334	2367	2334
q9	8049	8168	8006	8006
q10	4751	4755	4296	4296
q11	568	447	387	387
q12	766	797	544	544
q13	3308	3555	2941	2941
q14	312	322	299	299
q15	q16	726	745	630	630
q17	1343	1346	1340	1340
q18	8344	7561	7321	7321
q19	1143	1134	1096	1096
q20	2215	2221	1934	1934
q21	5295	4594	4514	4514
q22	539	489	418	418
Total cold run time: 58001 ms
Total hot run time: 52521 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.

I found one test coverage issue that should be fixed before merging.

Critical checkpoint conclusions:

  • Goal and correctness: the BE change is focused on aligning declared cast input nullability with the actual column shape, and the main TableReader path matches the cast wrapper behavior that unwraps nullable inputs according to the declared type.
  • Scope: the implementation is small and localized to _cast_column_to_type; I did not find an unrelated code-path expansion.
  • Concurrency, lifecycle, configuration, persistence, and protocol compatibility: not materially changed by this PR.
  • Parallel paths: the existing nullable-actual/non-nullable-declared case is still handled, and the new opposite case is now handled before the cast expression executes. I did not find optimizer/rewrite or aggregate pushdown semantic regressions.
  • Tests: the new BE unit test checks the direct crash path, but the new Iceberg regression query is not an expected-output assertion, so it can miss wrong values after nested pruning/casting.
  • Performance and observability: no additional issue found for this narrow cast-path fix.

User focus: no additional user-provided review focus was supplied.

Subagent conclusions:

  • optimizer-rewrite: no candidates; convergence round 1 returned NO_NEW_VALUABLE_FINDINGS.
  • tests-session-config: proposed TSC-1, accepted as MAIN-1 and submitted inline; convergence round 1 returned NO_NEW_VALUABLE_FINDINGS.

Validation: git diff --check passed for the changed files. I could not run the targeted BE UT or external regression in this runner because thirdparty/installed is absent, including bin/protoc and bin/thrift.

@hello-stephen

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

query5	4343	626	478	478
query6	457	224	202	202
query7	4867	588	344	344
query8	338	191	168	168
query9	8773	4029	4035	4029
query10	459	358	309	309
query11	5869	2368	2191	2191
query12	159	105	105	105
query13	1279	633	437	437
query14	6261	5306	4969	4969
query14_1	4305	4284	4274	4274
query15	211	203	181	181
query16	1008	517	470	470
query17	943	764	604	604
query18	2455	481	353	353
query19	214	190	154	154
query20	120	109	119	109
query21	232	160	133	133
query22	13681	13725	13445	13445
query23	17504	16599	16156	16156
query23_1	16310	16246	16351	16246
query24	7651	1789	1312	1312
query24_1	1269	1308	1307	1307
query25	582	466	390	390
query26	1330	358	213	213
query27	2631	595	357	357
query28	4488	2037	2038	2037
query29	1090	626	508	508
query30	343	261	227	227
query31	1113	1094	993	993
query32	108	68	64	64
query33	542	331	259	259
query34	1174	1160	692	692
query35	791	777	688	688
query36	1452	1446	1273	1273
query37	160	118	134	118
query38	1881	1691	1655	1655
query39	924	916	890	890
query39_1	873	872	894	872
query40	242	163	135	135
query41	65	62	62	62
query42	95	95	95	95
query43	320	328	277	277
query44	1406	777	770	770
query45	199	190	182	182
query46	1082	1249	729	729
query47	2374	2414	2265	2265
query48	393	437	302	302
query49	574	419	320	320
query50	1087	450	338	338
query51	10841	10687	10729	10687
query52	86	86	74	74
query53	257	283	202	202
query54	275	228	212	212
query55	75	74	66	66
query56	284	278	291	278
query57	1448	1406	1325	1325
query58	276	245	249	245
query59	1571	1617	1439	1439
query60	293	270	256	256
query61	159	152	157	152
query62	695	647	586	586
query63	239	208	205	205
query64	2817	1076	891	891
query65	4883	4792	4761	4761
query66	1807	529	396	396
query67	29521	29404	29306	29306
query68	3175	1511	1030	1030
query69	406	313	262	262
query70	1111	1010	977	977
query71	347	336	307	307
query72	3079	2761	2471	2471
query73	807	806	438	438
query74	5128	4935	4772	4772
query75	2628	2581	2235	2235
query76	2326	1178	785	785
query77	366	372	286	286
query78	12099	12280	11774	11774
query79	1273	1190	738	738
query80	638	553	466	466
query81	465	321	291	291
query82	589	168	126	126
query83	403	315	293	293
query84	330	159	127	127
query85	909	602	511	511
query86	369	299	269	269
query87	1817	1820	1763	1763
query88	3759	2810	2800	2800
query89	451	404	353	353
query90	1997	199	198	198
query91	202	186	160	160
query92	70	64	57	57
query93	1576	1548	1096	1096
query94	548	362	329	329
query95	770	497	494	494
query96	1036	801	336	336
query97	2706	2669	2555	2555
query98	214	210	206	206
query99	1154	1171	1051	1051
Total cold run time: 264764 ms
Total hot run time: 180622 ms

@hello-stephen

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

query1	0.01	0.00	0.01
query2	0.09	0.05	0.05
query3	0.25	0.14	0.14
query4	1.60	0.14	0.14
query5	0.24	0.23	0.22
query6	1.23	1.05	1.05
query7	0.04	0.01	0.00
query8	0.06	0.04	0.04
query9	0.39	0.32	0.31
query10	0.57	0.53	0.53
query11	0.19	0.14	0.13
query12	0.19	0.15	0.15
query13	0.47	0.48	0.49
query14	1.01	1.02	0.99
query15	0.62	0.59	0.58
query16	0.34	0.32	0.33
query17	1.15	1.14	1.08
query18	0.22	0.20	0.22
query19	2.10	1.94	1.98
query20	0.01	0.01	0.02
query21	15.44	0.21	0.14
query22	4.90	0.05	0.06
query23	16.16	0.32	0.12
query24	2.90	0.44	0.33
query25	0.11	0.05	0.04
query26	0.74	0.21	0.16
query27	0.04	0.04	0.03
query28	3.57	0.93	0.58
query29	12.51	4.07	3.28
query30	0.29	0.16	0.15
query31	2.76	0.61	0.31
query32	3.22	0.59	0.49
query33	3.17	3.20	3.24
query34	15.51	4.24	3.55
query35	3.51	3.52	3.45
query36	0.55	0.44	0.43
query37	0.09	0.06	0.07
query38	0.05	0.05	0.04
query39	0.04	0.03	0.04
query40	0.19	0.16	0.15
query41	0.09	0.03	0.03
query42	0.04	0.03	0.03
query43	0.04	0.04	0.04
Total cold run time: 96.7 s
Total hot run time: 25.05 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 100.00% (2/2) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 72.99% (29248/40071)
Line Coverage 56.65% (316396/558473)
Region Coverage 53.17% (263486/495548)
Branch Coverage 54.20% (115630/213344)

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