Skip to content

[fix](iceberg) Support nested decimal precision promotion#65122

Open
Gabriel39 wants to merge 1 commit into
apache:masterfrom
Gabriel39:fix-doris-26324-master
Open

[fix](iceberg) Support nested decimal precision promotion#65122
Gabriel39 wants to merge 1 commit into
apache:masterfrom
Gabriel39:fix-doris-26324-master

Conversation

@Gabriel39

@Gabriel39 Gabriel39 commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Proposed changes

Fix Iceberg complex column schema evolution validation for nested decimal precision widening.

Doris validates complex column modifications before committing Iceberg schema updates. The previous nested primitive promotion rules covered varchar length growth, exact matches, integer widening, and FLOAT -> DOUBLE, but missed Iceberg's valid decimal promotion rule:

decimal(P, S) -> decimal(P', S), where P' >= P and S is unchanged

This patch keeps the internal table complex type schema-change path on the existing strict nested promotion rules:

  • integer widening
  • FLOAT -> DOUBLE

Iceberg complex column schema evolution uses a separate validation entry point that additionally accepts decimal precision widening when both sides are decimal, scale is unchanged, and destination precision is not smaller. This keeps internal table nested decimal schema-change behavior unchanged.

Why

The internal table schema change matrix is broader than Iceberg schema evolution semantics. It allows conversions such as decimal bucket changes, date/string conversions, and other casts that are not safe metadata-only promotions for Iceberg nested schema evolution.

Tests

mvn test -pl fe-core -am \
  -Dcheckstyle.skip=true \
  -DfailIfNoTests=false \
  -Dmaven.build.cache.enabled=false \
  -Dtest=ColumnTest,IcebergMetadataOpsValidationTest

Related issue

DORIS-26324

@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 Gabriel39 force-pushed the fix-doris-26324-master branch 3 times, most recently from d5a3595 to 6a18fcb Compare July 1, 2026 13:05
@Gabriel39 Gabriel39 marked this pull request as ready for review July 1, 2026 13:06
@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@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: request changes.

Critical checkpoint conclusions:

  • Goal/test coverage: The PR adds tests for the new strict nested decimal promotion helper and Iceberg validation path, but the internal OLAP light schema-change path is not covered for decimal primitive-family boundary changes.
  • Scope/focus: The implementation is localized, but sharing the helper with internal complex schema change makes Iceberg metadata-safe decimal widening affect OLAP table schema change behavior.
  • Concurrency/lifecycle/config: No new threads, lifecycle ownership, or dynamic config items are introduced.
  • Compatibility/parallel paths: The Iceberg path is metadata-oriented, but the parallel internal OLAP complex-type path can apply accepted changes as light schema change without rewriting stored values.
  • Tests/results: I could not run the Maven tests because thirdparty/installed and thirdparty/installed/bin/protoc are missing in this runner; per fe/AGENTS.md I stopped before build/test execution.
  • User focus: No additional user-provided focus points were present.

Subagent conclusions:

  • optimizer-rewrite: NO_NEW_VALUABLE_FINDINGS in the final convergence round; no subagent candidates became comments.
  • tests-session-config: NO_NEW_VALUABLE_FINDINGS in the final convergence round; no subagent candidates became comments.
  • Main accepted MAIN-1 as the only inline comment after duplicate checks; no existing inline threads were present.

@Gabriel39 Gabriel39 force-pushed the fix-doris-26324-master branch from 6a18fcb to 6fa8099 Compare July 1, 2026 13:36
Doris validates Iceberg complex column modifications before committing the Iceberg schema update. The previous nested primitive promotion rules covered varchar length growth, exact matches, integer widening, and float to double, but missed Iceberg decimal precision widening.

Split the validation paths so internal table complex type schema change keeps the existing nested promotion semantics, while Iceberg complex column schema evolution can additionally allow decimal precision widening with unchanged scale.

Keep the shared strict nested primitive promotion utility limited to integer widening and float to double. Add an Iceberg-specific nested decimal promotion helper for decimal(P, S) -> decimal(P', S), where P' >= P and S is unchanged. Scale changes remain rejected because they would reinterpret historical decimal values.

Add ColumnTest coverage to verify internal table nested decimal precision widening is still rejected and Iceberg decimal promotion rules are isolated. Add IcebergMetadataOpsValidationTest coverage for array, map value, and struct nested decimal promotion plus narrowing and scale-change rejection through the Iceberg ALTER validation path.

Tests: mvn test -pl fe-core -am -Dcheckstyle.skip=true -DfailIfNoTests=false -Dmaven.build.cache.enabled=false -Dtest=ColumnTest,IcebergMetadataOpsValidationTest
@Gabriel39 Gabriel39 force-pushed the fix-doris-26324-master branch from 6fa8099 to 751470a Compare July 1, 2026 14:03
@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@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: request changes.

Critical checkpoint conclusions:

  • Goal/test coverage: The implementation splits internal complex-type schema-change validation from the Iceberg validation path and keeps internal nested decimal precision promotion rejected, but the new Iceberg tests only cover the struct-field shape while production also supports array-element and map-value updates through separate code paths.
  • Scope/focus: The code changes are localized to ColumnType, IcebergMetadataOps, and focused FE tests.
  • Concurrency/lifecycle/config: No new threads, locks, lifecycle ownership, or dynamic config items are introduced.
  • Compatibility/parallel paths: Internal OLAP callers still use the strict helper; Iceberg modify-column validation uses the decimal-enabled helper. Map-key type changes remain rejected by applyMapChange before commit.
  • Tests/results: Static review only. git diff --check passed for the four live PR files after fetching the base SHA. I did not run FE tests because .worktree_initialized is absent and thirdparty/installed/bin/protoc is missing, which is a stop condition under fe/AGENTS.md.
  • User focus: No additional user-provided review focus was present.

Subagent conclusions:

  • optimizer-rewrite: No candidates became comments; convergence round 1 returned NO_NEW_VALUABLE_FINDINGS.
  • tests-session-config: TSC-1 was accepted as MAIN-1 and submitted as the inline comment; convergence round 1 returned NO_NEW_VALUABLE_FINDINGS after the main ledger update.
  • Existing review thread 3506222061 was treated as already-known duplicate context and was not resubmitted.

}

@Test
public void testValidateForModifyComplexColumnAllowsNestedDecimalPrecisionPromotion() throws Throwable {

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.

This still only exercises the new decimal promotion through a struct field. The production path this PR enables is recursive for all complex shapes, and after validation IcebergMetadataOps takes different update paths for arrays and maps: array elements go through applyListChange(... updateColumn(elementPath, ...)), while map values go through applyMapChange(... updateColumn(valuePath, ...)). A struct-only reflection test would not catch a bad element/value path or an UpdateSchema incompatibility in those two supported shapes. Please add Iceberg modify validation coverage for at least array<decimal(5,3)> -> array<decimal(10,3)> and map<int,decimal(5,3)> -> map<int,decimal(10,3)> (ideally through the full modify/apply path, not only the shared helper).

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17673	4031	4027	4027
q2	2185	328	197	197
q3	10295	1381	832	832
q4	4702	470	340	340
q5	7545	854	562	562
q6	178	168	132	132
q7	770	833	613	613
q8	9393	1621	1624	1621
q9	5730	4411	4435	4411
q10	6788	1797	1557	1557
q11	506	340	314	314
q12	731	550	433	433
q13	18119	3428	2758	2758
q14	266	259	254	254
q15	q16	795	787	715	715
q17	1037	1023	1061	1023
q18	7583	5735	5569	5569
q19	1321	1223	970	970
q20	800	645	547	547
q21	6044	2758	2577	2577
q22	446	357	300	300
Total cold run time: 102907 ms
Total hot run time: 29752 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4380	4294	4328	4294
q2	292	311	206	206
q3	4548	5028	4434	4434
q4	2073	2140	1360	1360
q5	4429	4393	4355	4355
q6	240	176	132	132
q7	2003	2017	1643	1643
q8	2509	2223	2200	2200
q9	8126	8040	7950	7950
q10	4779	4791	4290	4290
q11	576	416	370	370
q12	755	759	539	539
q13	3298	3548	2853	2853
q14	287	303	279	279
q15	q16	700	737	660	660
q17	1346	1322	1486	1322
q18	8026	7239	7150	7150
q19	1163	1120	1119	1119
q20	2229	2215	1921	1921
q21	5244	4529	4428	4428
q22	509	440	387	387
Total cold run time: 57512 ms
Total hot run time: 51892 ms

@hello-stephen

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

query5	4307	633	493	493
query6	489	220	203	203
query7	4851	600	342	342
query8	341	195	172	172
query9	8745	4101	4114	4101
query10	473	356	293	293
query11	5903	2344	2133	2133
query12	158	105	101	101
query13	1276	585	432	432
query14	6761	5371	4979	4979
query14_1	4273	4322	4290	4290
query15	218	197	179	179
query16	1055	476	459	459
query17	1216	692	569	569
query18	2790	472	338	338
query19	222	183	146	146
query20	115	106	102	102
query21	252	170	137	137
query22	13807	13689	13395	13395
query23	17612	16555	16196	16196
query23_1	16397	16209	16190	16190
query24	7516	1757	1306	1306
query24_1	1304	1331	1341	1331
query25	579	437	405	405
query26	1323	349	213	213
query27	2538	614	378	378
query28	4397	2044	2044	2044
query29	1181	631	511	511
query30	344	265	233	233
query31	1142	1100	982	982
query32	106	64	63	63
query33	541	319	258	258
query34	1235	1136	662	662
query35	781	779	675	675
query36	1421	1393	1273	1273
query37	193	113	108	108
query38	1928	1697	1684	1684
query39	943	916	912	912
query39_1	863	889	882	882
query40	277	173	148	148
query41	80	69	71	69
query42	96	94	96	94
query43	367	322	284	284
query44	1451	782	789	782
query45	203	190	176	176
query46	1062	1226	746	746
query47	2380	2376	2258	2258
query48	411	429	303	303
query49	595	437	316	316
query50	1137	443	333	333
query51	4437	4374	4343	4343
query52	86	85	75	75
query53	265	285	205	205
query54	273	244	224	224
query55	75	75	66	66
query56	308	280	292	280
query57	1465	1399	1329	1329
query58	321	268	254	254
query59	1564	1626	1417	1417
query60	320	270	249	249
query61	153	149	151	149
query62	703	655	591	591
query63	248	213	218	213
query64	2496	761	619	619
query65	4854	4824	4760	4760
query66	1784	507	385	385
query67	29542	29629	29439	29439
query68	3229	1537	978	978
query69	434	305	276	276
query70	1069	955	962	955
query71	362	333	292	292
query72	2954	2608	2331	2331
query73	858	779	401	401
query74	5144	4954	4765	4765
query75	2616	2562	2209	2209
query76	2352	1231	780	780
query77	355	375	288	288
query78	12425	12461	11874	11874
query79	1202	1108	719	719
query80	613	540	453	453
query81	466	328	281	281
query82	230	154	123	123
query83	319	322	295	295
query84	300	158	129	129
query85	1040	600	526	526
query86	351	305	279	279
query87	1824	1828	1757	1757
query88	3731	2821	2810	2810
query89	436	410	357	357
query90	2183	204	202	202
query91	201	193	162	162
query92	66	59	56	56
query93	1515	1539	993	993
query94	571	357	321	321
query95	822	592	453	453
query96	1120	790	379	379
query97	2676	2728	2535	2535
query98	218	208	198	198
query99	1171	1178	1034	1034
Total cold run time: 259923 ms
Total hot run time: 173954 ms

@hello-stephen

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

query1	0.01	0.01	0.00
query2	0.10	0.05	0.05
query3	0.26	0.17	0.14
query4	1.62	0.14	0.13
query5	0.24	0.22	0.22
query6	1.26	1.04	1.08
query7	0.04	0.01	0.01
query8	0.06	0.04	0.04
query9	0.41	0.30	0.30
query10	0.58	0.57	0.57
query11	0.20	0.15	0.14
query12	0.18	0.15	0.15
query13	0.47	0.46	0.46
query14	1.05	1.01	1.00
query15	0.61	0.59	0.59
query16	0.31	0.33	0.32
query17	1.11	1.10	1.06
query18	0.23	0.22	0.21
query19	2.03	1.97	2.02
query20	0.02	0.02	0.01
query21	15.46	0.19	0.14
query22	4.89	0.06	0.05
query23	16.09	0.32	0.12
query24	3.05	0.42	0.34
query25	0.14	0.07	0.04
query26	0.77	0.20	0.14
query27	0.05	0.04	0.03
query28	3.50	0.90	0.56
query29	12.60	4.28	3.45
query30	0.31	0.16	0.15
query31	2.77	0.61	0.31
query32	3.23	0.61	0.51
query33	3.13	3.22	3.26
query34	15.60	4.20	3.51
query35	3.51	3.48	3.57
query36	0.60	0.44	0.43
query37	0.10	0.06	0.07
query38	0.06	0.04	0.03
query39	0.04	0.03	0.02
query40	0.18	0.16	0.14
query41	0.09	0.03	0.03
query42	0.04	0.03	0.03
query43	0.04	0.03	0.04
Total cold run time: 97.04 s
Total hot run time: 25.23 s

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 100.00% (1/1) 🎉
Increment coverage report
Complete coverage report

@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 0.00% (0/1) 🎉
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.

2 participants