Skip to content

[fix](lakehouse) Fix Iceberg historical reads and nested schema evolution - #66007

Merged
Gabriel39 merged 5 commits into
apache:masterfrom
Gabriel39:agent/fix-lakehouse-historical-schemas
Jul 31, 2026
Merged

[fix](lakehouse) Fix Iceberg historical reads and nested schema evolution#66007
Gabriel39 merged 5 commits into
apache:masterfrom
Gabriel39:agent/fix-lakehouse-historical-schemas

Conversation

@Gabriel39

@Gabriel39 Gabriel39 commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: N/A

Problem Summary:

The connector-plugin refactor on current master already provides the generic relation-local MVCC framework, per-statement connector metadata funnel, snapshot-aware Iceberg/Paimon/Hudi handles, and connector write contexts. The former cross-connector planning and frozen-table implementation from this PR is therefore no longer needed.

The remaining problems on current master are narrower:

  1. Iceberg system-table schema binding, column-handle creation, and scan planning can load different generations of the base table.
  2. Historical Iceberg predicates are converted with the current schema instead of the pinned schema, which can lose pushdown or bind the wrong field id after a rename.
  3. Static metadata tables and ALL_* metadata tables incorrectly receive snapshot/ref selection even though they enumerate metadata history independently or reject pinning APIs.
  4. FE nested-type construction and coercion can lose requiredness or fail to account for NULLs introduced by casts.
  5. BE schema-evolution materialization does not consistently propagate nullable parent masks into Struct/Array/Map descendants.
  6. ORC collection serialization can retain borrowed string storage incorrectly and mishandle non-NULL empty strings.

What is changed?

Iceberg historical reads

  • Reuse one statement-scoped Iceberg base table across system-table schema binding, column handles, and scan planning.
  • Convert historical predicates and pushed-predicate explain output with the pinned schema.
  • Apply snapshot/ref selection only to Iceberg table types that support it, excluding static and ALL_* metadata scans.

Nested schema evolution

  • Preserve nested requiredness and comments in DESCRIBE output.
  • Infer field nullability correctly for struct and named_struct expressions.
  • Include cast-induced nullability when reducing UNION, CASE, comparison, and implicit-coercion struct types.
  • Reject fallible casts into required nested targets while keeping exact identity casts, including DATETIMEV2, non-nullable.
  • Preserve source null maps through BE casts and validate required descendants against enclosing nullable Struct/Array/Map masks.
  • Project collection row masks through offsets before validating Array and Map entries.

ORC safety

  • Compact only collection entries visible through nullable parent masks.
  • Keep borrowed ORC string data alive in Arena storage without recopying already-owned data.
  • Preserve non-NULL empty strings for correct value and statistics semantics.

Tests

  • Add focused FE tests for nested type display, struct construction, cast validation, identity casts, and type coercion.
  • Add Iceberg tests for shared system-table generations, pinned-schema predicate conversion, static metadata tables, and pinned ALL_* snapshot/ref handling.
  • Add BE ASAN coverage for nested rematerialization, parent-mask propagation, collection null maps, and ORC string ownership.
  • Update Iceberg and schema-change regression coverage.

Behavior change

Historical Iceberg reads now remain bound to the selected schema generation. Nested requiredness is preserved through FE planning and BE materialization; physical NULL placeholders are accepted only when an enclosing nullable value hides them.

Release note

Fix Iceberg historical-read metadata consistency and preserve nested field requiredness during external-table schema evolution.

Check List (For Author)

  • Test
    • Regression test
    • Unit Test
    • Manual test
  • Behavior changed:
    • Yes.
  • Does this need documentation?
    • No.

Verification

  • FE focused suite: 74 tests passed; the final CheckCast and TryCast class runs passed 26 and 16 tests respectively with reactor checkstyle.
  • Iceberg focused suite: 3 tests passed; the final IcebergScanPlanProvider class run passed 117 tests with connector reactor build and checkstyle.
  • BE ASAN suite: 16 tests passed.
  • Changed BE files passed clang-format diff validation.
  • Regression golden labels were checked against their current suite definitions.

@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

@Gabriel39
Gabriel39 marked this pull request as ready for review July 24, 2026 09:50
@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@github-actions

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 30th, 2026 7:58 AM.
Workflow run: https://github.com/apache/doris/actions/runs/30082841127

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

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17574	3519	3508	3508
q2	2018	313	185	185
q3	10285	1208	723	723
q4	4713	312	231	231
q5	7871	756	482	482
q6	221	148	114	114
q7	741	690	533	533
q8	10515	1597	1540	1540
q9	4878	3090	3128	3090
q10	6632	1209	980	980
q11	503	322	295	295
q12	693	521	434	434
q13	18028	2441	1919	1919
q14	214	189	174	174
q15	q16	554	513	473	473
q17	1210	924	945	924
q18	5017	3628	3682	3628
q19	2179	1218	1043	1043
q20	790	648	570	570
q21	6045	2625	2265	2265
q22	424	354	294	294
Total cold run time: 101105 ms
Total hot run time: 23405 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	3921	3797	3783	3783
q2	247	262	192	192
q3	2674	2855	2508	2508
q4	1354	1358	1034	1034
q5	2688	2561	2556	2556
q6	223	162	107	107
q7	1357	1212	1121	1121
q8	2004	1745	1726	1726
q9	3747	3738	3700	3700
q10	2472	2441	2194	2194
q11	424	346	321	321
q12	576	547	407	407
q13	2626	2538	2052	2052
q14	234	233	230	230
q15	q16	536	548	488	488
q17	1281	1267	1245	1245
q18	5229	4856	4648	4648
q19	1228	1163	1173	1163
q20	1126	1102	998	998
q21	4417	3735	3793	3735
q22	501	440	406	406
Total cold run time: 38865 ms
Total hot run time: 34614 ms

@github-actions

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 30th, 2026 7:58 AM.
Workflow run: https://github.com/apache/doris/actions/runs/30084537065

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

@hello-stephen

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

query5	4317	543	428	428
query6	470	218	204	204
query7	4931	554	344	344
query8	327	183	172	172
query9	8797	3896	3885	3885
query10	474	315	281	281
query11	5527	1350	1178	1178
query12	158	98	103	98
query13	1261	590	471	471
query14	6074	2826	2696	2696
query14_1	2373	2349	2344	2344
query15	186	161	140	140
query16	1072	537	498	498
query17	918	565	473	473
query18	2401	428	302	302
query19	203	187	145	145
query20	96	92	88	88
query21	228	142	128	128
query22	7498	7584	7348	7348
query23	9709	9502	9176	9176
query23_1	9106	9385	9260	9260
query24	7239	1349	1039	1039
query24_1	1020	1026	1031	1026
query25	491	399	330	330
query26	1309	372	215	215
query27	2597	566	327	327
query28	4443	2176	2145	2145
query29	1060	619	498	498
query30	332	377	210	210
query31	915	715	622	622
query32	124	68	65	65
query33	567	309	254	254
query34	1184	1168	664	664
query35	553	537	481	481
query36	1097	1097	1063	1063
query37	155	101	86	86
query38	1385	1050	1003	1003
query39	642	647	652	647
query39_1	633	628	625	625
query40	259	170	151	151
query41	66	62	64	62
query42	92	90	91	90
query43	291	289	256	256
query44	1350	777	768	768
query45	129	131	118	118
query46	930	1105	664	664
query47	1453	1453	1361	1361
query48	407	399	297	297
query49	589	323	250	250
query50	1077	388	331	331
query51	11736	11201	10900	10900
query52	87	93	75	75
query53	247	268	214	214
query54	286	238	205	205
query55	76	75	67	67
query56	284	302	277	277
query57	957	898	861	861
query58	279	253	231	231
query59	1311	1327	1241	1241
query60	323	260	250	250
query61	149	149	144	144
query62	406	297	279	279
query63	232	192	193	192
query64	2790	877	743	743
query65	2126	2083	2031	2031
query66	1830	403	317	317
query67	16548	16370	16294	16294
query68	3267	1497	957	957
query69	415	309	267	267
query70	1135	1018	1039	1018
query71	370	334	309	309
query72	2904	2548	2268	2268
query73	749	712	425	425
query74	1749	1547	1458	1458
query75	1589	1496	1281	1281
query76	2340	1039	738	738
query77	352	359	279	279
query78	6116	5800	5494	5494
query79	1298	1058	745	745
query80	1278	524	458	458
query81	496	267	226	226
query82	980	140	110	110
query83	370	330	292	292
query84	318	156	133	133
query85	980	606	514	514
query86	425	308	325	308
query87	1145	1116	1034	1034
query88	3789	2931	2914	2914
query89	406	310	273	273
query90	1914	189	182	182
query91	205	196	164	164
query92	63	59	59	59
query93	1622	1462	932	932
query94	740	359	319	319
query95	787	488	524	488
query96	1074	745	373	373
query97	1365	1321	1277	1277
query98	194	172	183	172
query99	602	554	522	522
Total cold run time: 208869 ms
Total hot run time: 118395 ms

@hello-stephen

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

query1	0.01	0.01	0.00
query2	0.08	0.04	0.06
query3	0.25	0.13	0.12
query4	1.60	0.12	0.13
query5	0.19	0.17	0.17
query6	1.20	1.02	0.94
query7	0.04	0.00	0.01
query8	0.06	0.03	0.03
query9	0.32	0.28	0.26
query10	0.44	0.45	0.44
query11	0.17	0.12	0.11
query12	0.16	0.12	0.13
query13	0.39	0.37	0.38
query14	0.60	0.58	0.60
query15	0.49	0.46	0.48
query16	0.26	0.26	0.26
query17	0.95	0.96	0.91
query18	0.24	0.22	0.22
query19	1.46	1.54	1.52
query20	0.02	0.01	0.00
query21	15.44	0.24	0.14
query22	4.74	0.05	0.05
query23	16.15	0.30	0.14
query24	2.92	0.45	0.32
query25	0.11	0.05	0.05
query26	0.72	0.21	0.14
query27	0.04	0.04	0.03
query28	3.62	0.80	0.47
query29	12.52	4.34	3.45
query30	0.25	0.14	0.14
query31	2.77	0.52	0.22
query32	3.28	0.40	0.28
query33	1.71	1.67	1.71
query34	15.38	2.66	2.11
query35	2.15	2.10	2.15
query36	0.48	0.35	0.33
query37	0.07	0.05	0.06
query38	0.04	0.04	0.04
query39	0.04	0.03	0.03
query40	0.14	0.11	0.11
query41	0.08	0.03	0.03
query42	0.04	0.03	0.03
query43	0.05	0.04	0.04
Total cold run time: 91.67 s
Total hot run time: 18.64 s

@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@github-actions

Copy link
Copy Markdown
Contributor

Codex automated review failed and did not complete.

Error: Review context preparation failed before Codex ran; inspect the 'Prepare authoritative PR context and required AGENTS guides' step.
Workflow run: https://github.com/apache/doris/actions/runs/30091856991

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

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17580	3690	3702	3690
q2	2099	295	187	187
q3	10246	1231	787	787
q4	4682	317	230	230
q5	7620	751	503	503
q6	175	144	110	110
q7	721	721	504	504
q8	10084	1625	1599	1599
q9	4990	3173	3176	3173
q10	6767	1195	993	993
q11	518	329	296	296
q12	760	547	429	429
q13	17965	2434	1982	1982
q14	205	197	177	177
q15	q16	563	526	480	480
q17	921	991	1015	991
q18	4879	3733	3666	3666
q19	2606	1209	1064	1064
q20	761	654	522	522
q21	6038	2472	2268	2268
q22	421	348	294	294
Total cold run time: 100601 ms
Total hot run time: 23945 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4196	4052	4079	4052
q2	252	278	189	189
q3	2929	2997	2705	2705
q4	1441	1422	1083	1083
q5	2797	2685	2690	2685
q6	225	147	107	107
q7	1328	1249	1132	1132
q8	2095	1826	1783	1783
q9	3937	3882	3834	3834
q10	2609	2462	2234	2234
q11	515	421	341	341
q12	640	586	469	469
q13	2440	2534	2101	2101
q14	238	230	203	203
q15	q16	532	546	482	482
q17	1334	1300	1259	1259
q18	5387	5057	4906	4906
q19	1221	1173	1199	1173
q20	1231	1173	1005	1005
q21	4575	4052	3908	3908
q22	519	420	399	399
Total cold run time: 40441 ms
Total hot run time: 36050 ms

@hello-stephen

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

query5	4324	575	450	450
query6	462	217	200	200
query7	4962	587	314	314
query8	336	183	173	173
query9	8815	4042	4011	4011
query10	457	340	286	286
query11	5616	1391	1251	1251
query12	161	99	100	99
query13	1265	645	425	425
query14	6076	2953	2843	2843
query14_1	2554	2581	2505	2505
query15	193	163	156	156
query16	1126	565	519	519
query17	1121	625	505	505
query18	2515	462	319	319
query19	223	199	159	159
query20	114	102	93	93
query21	240	150	136	136
query22	8189	8085	7952	7952
query23	10210	9643	9623	9623
query23_1	9875	9712	9701	9701
query24	7290	1415	1016	1016
query24_1	1028	1040	1053	1040
query25	566	440	373	373
query26	1293	352	219	219
query27	2712	599	376	376
query28	4375	2264	2235	2235
query29	1086	605	492	492
query30	349	241	202	202
query31	901	673	589	589
query32	145	72	72	72
query33	538	290	234	234
query34	1190	1092	648	648
query35	541	534	483	483
query36	1098	1062	1035	1035
query37	162	104	96	96
query38	1291	1026	992	992
query39	633	611	619	611
query39_1	637	633	581	581
query40	259	171	149	149
query41	105	63	63	63
query42	96	92	91	91
query43	303	289	256	256
query44	1356	793	792	792
query45	144	136	125	125
query46	997	1178	721	721
query47	1487	1501	1513	1501
query48	414	408	332	332
query49	610	350	257	257
query50	1003	435	340	340
query51	12026	11015	11003	11003
query52	88	89	80	80
query53	261	270	197	197
query54	278	237	218	218
query55	78	72	69	69
query56	287	303	272	272
query57	947	890	838	838
query58	315	256	252	252
query59	1350	1407	1276	1276
query60	306	261	236	236
query61	154	149	143	143
query62	421	308	287	287
query63	243	203	196	196
query64	2764	867	785	785
query65	2165	2137	2146	2137
query66	1823	418	325	325
query67	17254	17728	17540	17540
query68	3345	1459	901	901
query69	420	300	263	263
query70	1129	1103	1084	1084
query71	388	327	338	327
query72	2998	2534	2303	2303
query73	817	708	437	437
query74	1881	1657	1539	1539
query75	1688	1558	1343	1343
query76	2336	1039	728	728
query77	345	356	285	285
query78	6580	6126	5750	5750
query79	3130	1081	709	709
query80	1751	561	472	472
query81	554	251	225	225
query82	786	142	113	113
query83	377	329	305	305
query84	290	166	132	132
query85	1000	605	519	519
query86	454	298	320	298
query87	1210	1170	1096	1096
query88	4079	3131	3132	3131
query89	431	318	296	296
query90	1969	192	191	191
query91	208	197	168	168
query92	65	62	57	57
query93	1829	1441	966	966
query94	783	362	344	344
query95	765	458	535	458
query96	1071	782	369	369
query97	1453	1402	1300	1300
query98	204	184	170	170
query99	632	597	533	533
Total cold run time: 216886 ms
Total hot run time: 123088 ms

@hello-stephen

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

query1	0.01	0.01	0.01
query2	0.10	0.05	0.04
query3	0.28	0.12	0.12
query4	1.61	0.13	0.12
query5	0.19	0.18	0.18
query6	1.18	0.97	0.96
query7	0.04	0.00	0.00
query8	0.06	0.05	0.04
query9	0.33	0.27	0.26
query10	0.44	0.45	0.44
query11	0.18	0.12	0.13
query12	0.17	0.13	0.13
query13	0.39	0.40	0.37
query14	0.61	0.65	0.63
query15	0.49	0.46	0.47
query16	0.24	0.26	0.24
query17	0.95	0.96	0.93
query18	0.25	0.22	0.23
query19	1.54	1.48	1.46
query20	0.01	0.02	0.01
query21	15.42	0.21	0.14
query22	4.95	0.05	0.06
query23	16.12	0.31	0.12
query24	3.06	0.39	0.30
query25	0.11	0.06	0.04
query26	0.74	0.20	0.16
query27	0.05	0.02	0.03
query28	3.46	0.87	0.51
query29	12.52	4.32	3.49
query30	0.26	0.15	0.14
query31	2.76	0.51	0.23
query32	3.26	0.42	0.29
query33	1.71	1.70	1.77
query34	15.31	2.74	2.20
query35	2.18	2.15	2.16
query36	0.49	0.35	0.32
query37	0.08	0.06	0.05
query38	0.05	0.04	0.04
query39	0.04	0.03	0.03
query40	0.14	0.12	0.10
query41	0.09	0.04	0.03
query42	0.04	0.02	0.02
query43	0.04	0.03	0.03
Total cold run time: 91.95 s
Total hot run time: 18.9 s

@github-actions

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 30th, 2026 7:58 AM.
Workflow run: https://github.com/apache/doris/actions/runs/30092764008

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

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 62.18% (97/156) 🎉
Increment coverage report
Complete coverage report

@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17879	3580	3490	3490
q2	2112	308	184	184
q3	10227	1236	740	740
q4	4673	305	230	230
q5	7604	764	484	484
q6	169	147	114	114
q7	702	662	500	500
q8	9353	1507	1646	1507
q9	4237	3113	3087	3087
q10	6734	1172	968	968
q11	506	328	300	300
q12	712	520	432	432
q13	18025	2469	1866	1866
q14	195	189	179	179
q15	q16	562	507	460	460
q17	995	982	948	948
q18	4966	3639	3357	3357
q19	1292	1217	943	943
q20	819	623	510	510
q21	5867	2515	2251	2251
q22	413	355	298	298
Total cold run time: 98042 ms
Total hot run time: 22848 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	3899	3799	3786	3786
q2	248	262	186	186
q3	2629	2791	2593	2593
q4	1351	1316	1042	1042
q5	2629	2553	2515	2515
q6	221	152	102	102
q7	1307	1196	1095	1095
q8	2001	1741	1717	1717
q9	3726	3636	3623	3623
q10	2469	2394	2147	2147
q11	419	339	316	316
q12	573	561	402	402
q13	2246	2339	2266	2266
q14	228	231	218	218
q15	q16	509	520	455	455
q17	1265	1244	1237	1237
q18	5238	4662	4721	4662
q19	1265	1145	1157	1145
q20	1097	1089	940	940
q21	4293	3859	3812	3812
q22	513	454	421	421
Total cold run time: 38126 ms
Total hot run time: 34680 ms

@github-actions

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 30th, 2026 7:58 AM.
Workflow run: https://github.com/apache/doris/actions/runs/30102232994

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

@github-actions

Copy link
Copy Markdown
Contributor

Codex automated review failed and did not complete.

Error: Review context preparation failed before Codex ran; inspect the 'Prepare authoritative PR context and required AGENTS guides' step.
Workflow run: https://github.com/apache/doris/actions/runs/30549730904

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

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17702	4121	4118	4118
q2	2237	343	209	209
q3	10165	1473	830	830
q4	4685	472	340	340
q5	7507	920	557	557
q6	190	178	137	137
q7	774	832	628	628
q8	9407	1582	1530	1530
q9	5587	4337	4366	4337
q10	6768	1721	1466	1466
q11	524	378	330	330
q12	739	577	468	468
q13	18096	3483	2717	2717
q14	270	257	238	238
q15	q16	787	767	695	695
q17	1015	894	1055	894
q18	7153	5778	5628	5628
q19	1354	1260	1146	1146
q20	803	718	580	580
q21	5858	2595	2376	2376
q22	425	358	305	305
Total cold run time: 102046 ms
Total hot run time: 29529 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4432	4439	4490	4439
q2	308	327	213	213
q3	4586	4994	4376	4376
q4	2065	2157	1370	1370
q5	4400	4213	4254	4213
q6	225	177	133	133
q7	1723	2418	1693	1693
q8	2547	2210	2249	2210
q9	7958	8109	7805	7805
q10	4691	4625	4241	4241
q11	556	412	392	392
q12	779	782	554	554
q13	3303	3620	2941	2941
q14	299	306	268	268
q15	q16	701	715	635	635
q17	1373	1353	1365	1353
q18	8028	7527	7274	7274
q19	1164	1066	1092	1066
q20	2209	2204	1934	1934
q21	5220	4587	4386	4386
q22	496	472	412	412
Total cold run time: 57063 ms
Total hot run time: 51908 ms

@hello-stephen

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

query5	4306	613	474	474
query6	484	229	201	201
query7	4960	566	343	343
query8	349	193	170	170
query9	8784	4018	4043	4018
query10	464	367	314	314
query11	5909	2339	2123	2123
query12	155	101	99	99
query13	1249	602	448	448
query14	6224	5198	4841	4841
query14_1	4205	4159	4226	4159
query15	214	206	178	178
query16	1051	474	464	464
query17	1122	711	582	582
query18	2571	475	349	349
query19	224	193	150	150
query20	111	107	104	104
query21	251	160	140	140
query22	13563	13519	13393	13393
query23	17206	16497	16042	16042
query23_1	16200	16200	16154	16154
query24	7463	1769	1305	1305
query24_1	1357	1288	1307	1288
query25	585	458	395	395
query26	1347	371	219	219
query27	2647	603	383	383
query28	4445	2041	2039	2039
query29	1055	658	469	469
query30	351	276	244	244
query31	1114	1082	973	973
query32	110	61	59	59
query33	506	308	240	240
query34	1205	1115	638	638
query35	741	765	657	657
query36	1021	1046	873	873
query37	152	103	93	93
query38	1854	1717	1587	1587
query39	865	872	860	860
query39_1	835	835	840	835
query40	249	174	141	141
query41	64	66	61	61
query42	92	94	100	94
query43	321	334	280	280
query44	1392	779	757	757
query45	190	180	171	171
query46	1081	1157	767	767
query47	2121	2124	2056	2056
query48	395	413	309	309
query49	578	431	306	306
query50	1072	434	346	346
query51	10613	10459	10719	10459
query52	87	87	75	75
query53	260	270	203	203
query54	278	225	217	217
query55	75	70	69	69
query56	309	278	283	278
query57	1304	1282	1220	1220
query58	289	272	289	272
query59	1568	1635	1500	1500
query60	331	276	239	239
query61	149	144	146	144
query62	536	492	425	425
query63	242	200	193	193
query64	2849	1026	838	838
query65	4718	4624	4507	4507
query66	1830	498	378	378
query67	29319	29160	29109	29109
query68	3314	1589	951	951
query69	415	304	269	269
query70	934	807	827	807
query71	373	339	321	321
query72	3027	2473	2381	2381
query73	890	805	418	418
query74	5061	4954	4694	4694
query75	2515	2543	2129	2129
query76	2327	1189	760	760
query77	358	385	275	275
query78	11859	11849	11276	11276
query79	1479	1109	787	787
query80	691	584	490	490
query81	465	343	297	297
query82	561	215	124	124
query83	397	327	303	303
query84	284	157	130	130
query85	966	605	538	538
query86	355	239	233	233
query87	1820	1825	1773	1773
query88	3752	2833	2780	2780
query89	417	364	331	331
query90	1971	203	196	196
query91	206	189	163	163
query92	60	57	56	56
query93	1682	1627	992	992
query94	549	332	304	304
query95	794	497	487	487
query96	1065	812	349	349
query97	2602	2625	2490	2490
query98	213	205	199	199
query99	1092	1102	958	958
Total cold run time: 262439 ms
Total hot run time: 176965 ms

@hello-stephen

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

query1	0.01	0.01	0.01
query2	0.09	0.05	0.05
query3	0.25	0.14	0.13
query4	1.60	0.13	0.14
query5	0.24	0.22	0.23
query6	1.16	0.83	0.81
query7	0.04	0.01	0.00
query8	0.06	0.04	0.04
query9	0.38	0.36	0.31
query10	0.56	0.54	0.55
query11	0.20	0.14	0.14
query12	0.18	0.14	0.14
query13	0.47	0.48	0.49
query14	1.00	1.01	1.01
query15	0.62	0.60	0.61
query16	0.32	0.33	0.32
query17	1.08	1.16	1.10
query18	0.23	0.21	0.21
query19	2.10	1.91	1.96
query20	0.01	0.01	0.02
query21	15.44	0.24	0.13
query22	4.90	0.05	0.05
query23	16.14	0.30	0.12
query24	3.04	0.43	0.33
query25	0.12	0.05	0.04
query26	0.73	0.21	0.14
query27	0.05	0.04	0.03
query28	3.46	0.91	0.54
query29	12.50	4.08	3.29
query30	0.28	0.15	0.14
query31	2.77	0.59	0.31
query32	3.24	0.59	0.49
query33	3.16	3.27	3.26
query34	15.50	4.24	3.48
query35	3.54	3.54	3.49
query36	0.54	0.42	0.44
query37	0.09	0.07	0.06
query38	0.05	0.03	0.03
query39	0.03	0.03	0.03
query40	0.19	0.16	0.16
query41	0.08	0.03	0.03
query42	0.04	0.03	0.03
query43	0.04	0.04	0.03
Total cold run time: 96.53 s
Total hot run time: 24.79 s

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

Reviewed all 40 changed files at a9d44b45502c8e6f557468583f841169a381a6e9 against the authoritative bundle and the existing review threads. I found two new issues; the other residual concerns are already covered by existing threads.

Critical-checkpoint conclusions:

  • Goal and tests: The patch substantially improves historical Iceberg reads, nested schema evolution, ORC masking/lifetimes, and Struct nullability, with broad unit/regression coverage. The empty-read MERGE conflict edge and quoted nested comments remain untested and incorrect.
  • Scope and clarity: Changes are generally focused, but the read/write table split introduces a sentinel boundary that needs an explicit state contract.
  • Concurrency: Statement-local maps use the existing scope and transaction begin lock correctly. The material race is a concurrent first Iceberg append between empty target binding and the first writable-table load.
  • Lifecycle: Frozen read tables and statement scopes have bounded statement lifetimes; no new ownership cycle or static-initialization issue was found.
  • Configuration: No new configuration item is introduced. Existing strict-cast and DESCRIBE-comment settings are read through their established session paths.
  • Compatibility: FE/BE Struct nullability remains rolling-compatible through the function-builder complex-type compatibility path; no storage-format or protocol incompatibility was found.
  • Parallel paths: Data/system tables, branch/tag/snapshot reads, INSERT/DELETE/UPDATE/MERGE/REWRITE, new/legacy coercion reducers, and Struct/named_struct FE/BE paths were traced. Remaining generation/mask defects outside these two findings duplicate existing threads.
  • Conditional logic: Snapshot-selection exclusions and nullable-mask conditions are documented and match the supported paths; the -1 empty/no-pin conflation is the missing distinction.
  • Test coverage: Existing tests cover current-version coercion, frozen BaseTable reads, system-table selection, ORC lifetime/masks, and changed regression matrices. They lack the two barrier/escaping cases reported inline.
  • Test results: No build or test was run because the authoritative review prompt prohibits builds and test execution; this review is static.
  • Observability: No additional logging or metrics are required for these deterministic planning/formatting paths.
  • Transactions and persistence: No Doris EditLog change is involved. Iceberg RowDelta conflict validation is affected by F1; other transaction concerns are covered by existing review threads.
  • Data writes: F1 can violate serializable MERGE semantics by missing a concurrent first append; no additional crash/leak issue was found.
  • Variable propagation: The existing snapshot/schema handle fields reach scan and write paths for nonempty snapshots, but the empty sentinel loses its state before the write context.
  • Performance: The clear-mask fast path and Arena ownership check avoid the suspected large allocation/double-copy costs; no distinct hot-path regression remained.
  • Other issues: F2 makes nested-comment DESCRIBE type strings malformed for valid quoted/backslash comments.

Additional user focus: none was provided.

Table loaded = IcebergStatementScope.sharedTable(session, db, tableName,
// Reuse the write planner's mutable table, never the frozen read view: newTransaction
// refreshes operations to establish a fresh OCC base and must not mutate bound read metadata.
Table loaded = IcebergStatementScope.sharedWritableTable(session, db, tableName,

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 an explicitly empty read as the RowDelta base

An empty latest snapshot is -1, but applySnapshot leaves that handle unpinned and buildWriteContext passes -1. With this new independent writable-table load, a MERGE whose target was bound to empty T0 can load a concurrent first append S1 here; applyBeginGuards then records S1 as baseSnapshotId. The commit calls validateFromSnapshot(S1), so serializable validateNoConflictingDataFiles ignores the matching file added in S1 and the MERGE can insert a duplicate. Iceberg's BaseRowDelta uses an unset starting snapshot to check all versions, so this edge must preserve "explicitly empty" separately from "no pin" (or otherwise validate from T0). Please add an empty-bind / concurrent-first-append MERGE barrier test.

}
// Nested docs are part of DESCRIBE output only when comments were explicitly requested.
if (showNestedComment && field.isCommentSpecified()) {
desc.append(String.format(" comment '%s'", field.getComment()));

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] Quote nested comments in DESCRIBE type strings

With show_column_comment_in_describe=true, a valid nested comment such as owner's \path is rendered as comment 'owner's \path'. That is not a valid round-trippable SQL literal, and backslashes may also be reinterpreted. The parallel Nereids StructField.toSql() uses SqlLiteralUtils.quoteStringLiteral for this syntax. Please use equivalent SQL-literal quoting here and add coverage for quotes and backslashes.

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 65.79% (25/38) 🎉
Increment coverage report
Complete coverage report

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 93.73% (314/335) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 75.75% (31995/42235)
Line Coverage 60.42% (356885/590631)
Region Coverage 57.00% (299365/525178)
Branch Coverage 58.47% (134995/230883)

@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 55.26% (21/38) 🎉
Increment coverage report
Complete coverage report

### What problem does this PR solve?

Issue Number: N/A

Problem Summary:

Historical Iceberg source snapshots could leak their schema pin into connector sink binding in the same INSERT statement. This made valid writes against the latest target schema fail when a column had been renamed. Iceberg STRUCT conversion also defaulted every nested field to nullable and dropped field documentation, causing system-table schemas such as entries to disagree with Iceberg metadata.

Bind connector write targets with an explicit latest-schema lookup while retaining source snapshot pins, and carry nested field requiredness and documentation through the neutral connector type mapping.

### Release note

Fix connector writes that read historical Iceberg snapshots and preserve nested Iceberg field requiredness.

### Check List (For Author)

- Test
    - [x] Regression test
    - [x] Unit Test
- Behavior changed:
    - [x] Yes. Connector sinks bind the latest target schema and Iceberg nested fields retain requiredness.
- Does this need documentation?
    - [x] No.
@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

Copy link
Copy Markdown
Contributor Author

/review

Gabriel39 added a commit that referenced this pull request Jul 31, 2026
…sistency fixes (#66246)

### What problem does this PR solve?

This backports the following lakehouse fixes to `branch-4.1`:

- #66112: enforce external write correctness for Iceberg operations.
- #66223: preserve pruned Paimon struct field reads.
- #66007: preserve metadata generations and nested schema semantics
across Iceberg, Paimon, Hudi, ORC, and complex-type materialization.

The #66007 changes were adapted to the `branch-4.1` APIs while
preserving the source PR's behavior. A minimal nullable-cast helper
required by the backport was included instead of pulling the unrelated
master refactor that originally introduced it.

### Check List

- FE focused unit tests: 202 successful test executions across the
initial suite and the Paimon follow-up run.
- FE Maven reactor: `BUILD SUCCESS`.
- BE affected production and test translation units: compiled
successfully with ASAN settings.
- BE #66007 ORC and complex-rematerialization tests: 18 tests passed on
the exact #66007 head.
- `git diff --check`: passed.
@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17858	4126	4308	4126
q2	2464	330	196	196
q3	10323	1437	828	828
q4	4686	469	335	335
q5	7771	851	544	544
q6	185	176	140	140
q7	762	838	605	605
q8	9500	1521	1711	1521
q9	7033	4293	4327	4293
q10	7441	1716	1471	1471
q11	604	358	325	325
q12	775	578	462	462
q13	18168	3399	2717	2717
q14	268	267	245	245
q15	q16	779	765	709	709
q17	1040	1010	1053	1010
q18	6995	5653	5501	5501
q19	1183	1191	1085	1085
q20	824	706	586	586
q21	5902	2642	2487	2487
q22	432	361	307	307
Total cold run time: 104993 ms
Total hot run time: 29493 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4538	4387	4441	4387
q2	298	325	214	214
q3	4579	5022	4427	4427
q4	2078	2148	1353	1353
q5	4540	4274	4817	4274
q6	263	200	153	153
q7	2024	1806	1629	1629
q8	2484	2274	2252	2252
q9	7875	7753	7723	7723
q10	4640	4680	4270	4270
q11	631	474	398	398
q12	764	778	523	523
q13	3297	3624	2973	2973
q14	301	309	279	279
q15	q16	713	741	658	658
q17	1369	1377	1372	1372
q18	8112	7316	6771	6771
q19	1128	1092	1109	1092
q20	2227	2204	1951	1951
q21	5267	4588	4347	4347
q22	516	466	400	400
Total cold run time: 57644 ms
Total hot run time: 51446 ms

@hello-stephen

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

query5	4330	627	493	493
query6	473	228	216	216
query7	5022	587	347	347
query8	333	190	171	171
query9	8760	4112	4124	4112
query10	483	373	303	303
query11	5928	2339	2117	2117
query12	157	106	100	100
query13	1272	617	436	436
query14	6263	5237	4886	4886
query14_1	4267	4309	4243	4243
query15	224	209	181	181
query16	1007	483	483	483
query17	1150	739	595	595
query18	2442	477	361	361
query19	218	190	152	152
query20	113	108	108	108
query21	233	162	152	152
query22	13604	13687	13556	13556
query23	17193	16375	16106	16106
query23_1	16205	16217	16235	16217
query24	8142	1766	1291	1291
query24_1	1321	1359	1309	1309
query25	561	466	392	392
query26	1333	365	215	215
query27	2577	632	394	394
query28	4465	2088	2042	2042
query29	1079	644	499	499
query30	358	275	228	228
query31	1117	1095	991	991
query32	141	58	59	58
query33	518	295	249	249
query34	1151	1193	652	652
query35	763	780	663	663
query36	1042	1010	876	876
query37	152	104	89	89
query38	1876	1700	1667	1667
query39	870	869	856	856
query39_1	857	832	836	832
query40	256	161	136	136
query41	67	64	62	62
query42	92	91	90	90
query43	327	332	286	286
query44	1463	791	767	767
query45	195	180	174	174
query46	1070	1223	708	708
query47	2101	2103	1923	1923
query48	417	437	316	316
query49	574	418	302	302
query50	1061	446	342	342
query51	10565	10661	10779	10661
query52	83	87	76	76
query53	256	316	201	201
query54	286	244	223	223
query55	74	72	69	69
query56	324	304	282	282
query57	1323	1290	1191	1191
query58	285	251	252	251
query59	1591	1681	1419	1419
query60	312	279	253	253
query61	153	150	146	146
query62	550	493	426	426
query63	246	208	203	203
query64	2835	1022	817	817
query65	4746	4624	4640	4624
query66	1806	493	380	380
query67	29256	29274	29005	29005
query68	3271	1573	992	992
query69	414	318	279	279
query70	942	846	835	835
query71	390	332	314	314
query72	3199	2695	2293	2293
query73	821	762	418	418
query74	5072	4921	4795	4795
query75	2554	2512	2169	2169
query76	2331	1201	769	769
query77	376	393	303	303
query78	11956	11962	11367	11367
query79	1453	1203	769	769
query80	1281	569	475	475
query81	554	341	289	289
query82	583	154	120	120
query83	381	328	305	305
query84	284	173	145	145
query85	970	612	532	532
query86	414	248	235	235
query87	1839	1819	1740	1740
query88	3801	2847	2781	2781
query89	441	373	335	335
query90	1898	199	200	199
query91	201	191	163	163
query92	60	62	57	57
query93	1644	1562	947	947
query94	732	350	317	317
query95	798	602	501	501
query96	1069	811	335	335
query97	2602	2623	2497	2497
query98	212	214	198	198
query99	1097	1127	967	967
Total cold run time: 264391 ms
Total hot run time: 178284 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 312272e732dd0e7ace0111060b0611577749eca5, data reload: false

query1	0.01	0.03	0.01
query2	0.09	0.05	0.05
query3	0.25	0.15	0.15
query4	1.60	0.15	0.15
query5	0.25	0.23	0.23
query6	1.17	0.84	0.82
query7	0.04	0.01	0.00
query8	0.05	0.03	0.03
query9	0.38	0.32	0.31
query10	0.56	0.56	0.55
query11	0.19	0.14	0.13
query12	0.17	0.14	0.14
query13	0.47	0.48	0.47
query14	1.01	1.02	1.02
query15	0.61	0.59	0.61
query16	0.34	0.33	0.32
query17	1.16	1.17	1.14
query18	0.23	0.22	0.21
query19	2.08	1.98	1.96
query20	0.02	0.02	0.01
query21	15.43	0.20	0.13
query22	4.91	0.06	0.06
query23	16.16	0.31	0.12
query24	2.92	0.42	0.32
query25	0.11	0.06	0.04
query26	0.74	0.21	0.16
query27	0.03	0.04	0.04
query28	3.53	0.91	0.55
query29	12.46	4.13	3.27
query30	0.27	0.17	0.17
query31	2.77	0.58	0.31
query32	3.22	0.59	0.49
query33	3.19	3.23	3.19
query34	15.71	4.19	3.51
query35	3.53	3.55	3.55
query36	0.55	0.45	0.43
query37	0.10	0.06	0.07
query38	0.05	0.04	0.03
query39	0.04	0.03	0.03
query40	0.18	0.16	0.15
query41	0.09	0.03	0.03
query42	0.03	0.03	0.03
query43	0.04	0.04	0.03
Total cold run time: 96.74 s
Total hot run time: 24.99 s

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

Requesting changes for two distinct issues identified in the current head; details are inline.

Critical checkpoint conclusions:

  • Goal and proof: The change substantially addresses historical Iceberg generation/schema selection, nested requiredness propagation, and ORC masked-collection payload lifetime, with focused unit/regression coverage in the diff. It is not complete because trivial collection children and strict pre-cast Struct children still fail reachable cases.
  • Scope and focus: The 44-file change is broad but coherent around those contracts. No additional user-provided review focus was supplied, so the whole PR was reviewed.
  • Concurrency: Iceberg statement-scope reads, mutable write helpers, transaction refresh, sink binding, and optimistic commit ordering were traced. The remaining T0/T1 write-generation interval and empty-snapshot RowDelta base are already represented by existing live threads; no additional distinct concurrency finding is duplicated here.
  • Lifecycle and memory: ORC row batches, compacted temporary columns, borrowed versus Arena-owned strings, empty/absent positions, and Writer::add lifetime were checked. The current Arena lifetime and packed-coordinate paths are sound after excluding existing live ORC findings; no static-initialization or ownership-cycle issue was found.
  • Configuration: No new configuration item is added.
  • Compatibility: The FE/BE Struct child-nullability difference is tolerated by the nested return-type compatibility helper, and FunctionStruct materializes the FE-supplied layout, so both rolling directions were verified safe; no new incompatibility remains.
  • Parallel paths and conditions: Non-trivial ARRAY/MAP rematerializers now project ancestor masks, but the trivial-child alignment path still drops them (MAIN-2). Strict-aware common-type and outer-Struct checks were updated, but a pre-cast child remains mode-blind nullable (MAIN-3). Other adjacent paths were either sound or already covered by live threads.
  • Tests and result files: The diff adds substantial FE/BE and Iceberg regression coverage, and changed result files were checked against their query shapes. Missing coverage corresponds directly to the two inline findings. Per the review task, this was a static review: no build or test command was run; the worktree initialization marker and thirdparty/installed are also absent.
  • Observability: No new logs or metrics are required for these local conversion/materialization paths; existing errors propagate with actionable messages. No silent Status discard was found.
  • Transactions, persistence, and writes: Iceberg INSERT/OVERWRITE/DELETE/UPDATE/MERGE/REWRITE planning and transaction boundaries were reviewed. No Doris EditLog or new persistent state is introduced. Existing live threads already cover the outstanding Iceberg generation and empty-base write correctness concerns.
  • FE/BE propagation: No new session variable or thrift field is introduced. The changed Struct function result layouts remain executable across mixed versions through the existing compatibility and FE-layout materialization paths.
  • Performance and remaining risks: Clear-mask allocation, collection compaction, COW detachment, and duplicate Arena-copy paths were checked; no new non-duplicate performance issue remains. The final missed-risk sweep found no additional actionable issue beyond MAIN-2 and MAIN-3 and the already-open live threads.

}
RETURN_IF_ERROR(_align_column_nullability(column, mapping.table_type));
RETURN_IF_ERROR(
_align_column_nullability(column, mapping.table_type, nullable_parent_null_map));

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] Project inherited masks for trivial collection children

This inherited mask is still lost when mapping.is_trivial and the mapped child is an ARRAY or MAP. For example, a nullable Struct can be rematerialized because one sibling changed while an identical collection sibling remains trivial; this call passes the Struct row mask into _align_column_nullability, whose ARRAY/MAP branches recurse into entries without projecting that row-coordinate mask through the offsets. A NULL Struct row with a populated physical collection can then expose a required descendant's hidden NULL placeholder and fail with Default expression produced NULL for non-nullable table column. Please project the inherited mask at the ARRAY/MAP branches too, and add a mapper-driven test with a non-trivial Struct parent and a trivial collection child.

// the field nullable here would reject safe casts into required target fields.
structFields.add(new StructField(nameLiteral.getStringValue(),
children.get(i + 1).getDataType(), true, ""));
children.get(i + 1).getDataType(), children.get(i + 1).nullable(), ""));

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] Keep strict pre-cast Struct children required

This now copies the child expression's nullability, but Cast.nullable() is still mode-blind. With enable_strict_cast=true, named_struct('metric', CAST(required_string AS INT)) therefore declares metric nullable because STRING-to-INT can return NULL in loose mode, even though strict execution aborts bad rows and returns a required INT for successful rows. A subsequent strict cast or INSERT into STRUCT<metric:INT NOT NULL> is rejected by CheckCast's declared-source-nullable guard before its new strict exemption is reached. Please make scalar-Cast/Struct-child nullability strict-aware (while keeping TryCast nullable), and cover pre-cast children in both struct and named_struct.

@github-actions

Copy link
Copy Markdown
Contributor

PR approved by at least one committer and no changes requested.

@github-actions github-actions Bot added the approved Indicates a PR has been approved by one committer. label Jul 31, 2026
@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 92.54% (310/335) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 75.68% (31963/42235)
Line Coverage 60.29% (356084/590631)
Region Coverage 56.81% (298378/525178)
Branch Coverage 58.30% (134612/230883)

@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 43.40% (23/53) 🎉
Increment coverage report
Complete coverage report

@924060929 924060929 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.

FE review at head 312272e732dd0e7ace0111060b0611577749eca5.

The overall direction is sound: statement-frozen Iceberg read metadata is now separated from mutable write operations, historical predicates use the pinned schema, unsupported metadata-table snapshot selection is fenced, and most Struct requiredness/coercion paths are covered.

I found one additional planning-cost issue inline. I did not duplicate these three existing actionable threads, which still apply to the current head:

  • Empty-table MERGE loses the distinction between an explicitly empty read and no read pin: #66007 (comment)
  • Nested DESCRIBE comments are not SQL-literal quoted: #66007 (comment)
  • Strict pre-cast Struct children remain incorrectly nullable: #66007 (comment)

The earlier unresolved FE threads about nested NOT NULL display, non-strict fallible required-field casts, legacy CASE/set-operation nullability, frozen read generations, and strict common Struct types are fixed by later commits and their added tests.

}

private static Column connectorSinkTargetColumn(PluginDrivenExternalTable table, String name) {
return sinkTargetFullSchema(table).stream()

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] Resolve the latest target schema only once per sink bind

connectorSinkTargetColumn calls sinkTargetFullSchema(table) for every user column and every static-partition name, then linearly scans the returned list. An explicit list of M columns over an N-column table therefore becomes O(M×N), replacing the previous map lookup.

The more expensive case is row-level DML: PluginDrivenExternalTable.getFullSchema(Optional.empty()) passes through appendSyntheticWriteColumns; while the hidden-column gate is open, that calls fetchSyntheticWriteColumns, resolves the connector handle again, and the Iceberg getTableHandle implementation executes catalogOps.tableExists. A wide DML statement can consequently repeat a remote catalog existence probe per target column.

Please load the latest target schema once at the start of sink binding, build one case-insensitive name map, and pass that schema/map through canonicalization, explicit-column selection, and static-partition materialization. An invocation-count test should verify that one bind calls getFullSchema(Optional.empty()) only once regardless of the number of target columns.

@Gabriel39
Gabriel39 merged commit 8429776 into apache:master Jul 31, 2026
35 checks passed
hubgeter added a commit to hubgeter/doris that referenced this pull request Jul 31, 2026
### What problem does this PR solve?

Issue Number: None

Related PR: apache#65851, apache#66007

Problem Summary: Master introduced frozen historical reads, current-schema branch writes, nullable parent-mask propagation, and ORC ownership fixes while this PR adds Iceberg V3 initial and write defaults. Resolve the overlapping FE and BE paths semantically: keep historical reads separate from mutable writer metadata, pin the current table writer schema while targeting a branch lineage, compose parent masks with recursive default materialization, and retain both test suites.

### Release note

Branch-targeted Iceberg writes use the table current schema while committing to the selected branch lineage.

### Check List (For Author)

- Test: Unit Test
    - 262 focused Iceberg connector tests passed
    - 34 focused FE sink and row-level DML tests passed
    - C++ format and connector import-boundary checks passed
- Behavior changed: Yes (branch writes use the table-global current schema, matching current master)
- Does this need documentation: Yes (updated docs/iceberg-v3-default-values-design.md)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by one committer. dev/4.1.4-merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants