Skip to content

[fix](fe) Preserve coalesce nullability after conditional rewrite#62094

Closed
starocean999 wants to merge 2 commits intoapache:masterfrom
starocean999:master_0403
Closed

[fix](fe) Preserve coalesce nullability after conditional rewrite#62094
starocean999 wants to merge 2 commits intoapache:masterfrom
starocean999:master_0403

Conversation

@starocean999
Copy link
Copy Markdown
Contributor

Problem Summary:

This PR fixes an incorrect nullability regression in Nereids when simplifying conditional functions such as coalesce and nvl.

Root cause:

  • SimplifyConditionalFunction rewrites expressions like coalesce(non_nullable_expr, ...) to the first guaranteed non-null child.
  • When the rewritten result needs type alignment, ensureSameResultType may wrap that child with a Cast.
  • Some casts are conservatively treated as nullable, even when the original coalesce result is guaranteed to be non-null.
  • As a result, the planner could lose the original non-nullability of coalesce, and downstream plan output metadata became inconsistent.

Fix:

  • Keep the fix inside SimplifyConditionalFunction instead of relying on a later nullable-adjustment pass.
  • After rewriting coalesce or nvl, if the original expression is non-nullable but the rewritten expression becomes nullable because of type coercion, wrap the rewritten result with NonNullable(...).
  • This preserves the original semantics of conditional functions while keeping the rewrite localized to the rule that introduced the issue.

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

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

@starocean999
Copy link
Copy Markdown
Contributor Author

run buildall

@starocean999
Copy link
Copy Markdown
Contributor Author

/review

Copy link
Copy Markdown
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found 1 issue that should be addressed before merge.

Critical checkpoint conclusions:

  • Goal and correctness: Partially met. The PR fixes the nullability loss in SimplifyConditionalFunction, but the same regression remains reachable through another rewrite path (FoldConstantRuleOnFE.visitNvl).
  • Scope: The code change is small and focused.
  • Concurrency: Not applicable; this change is in FE expression rewriting only.
  • Lifecycle/static init: No issue found.
  • Config changes: None.
  • Compatibility: No FE/BE protocol or storage compatibility issue found.
  • Parallel code paths: Not fully covered. ifnull/nvl is simplified both here and in FE constant folding, and only one path was updated.
  • Special conditional checks: The new NonNullable(...) guard is reasonable for this rule.
  • Test coverage: Improved for the simplifier path and regression SQL, but still missing coverage for the FE constant-folding path.
  • Observability: No additional observability needed.
  • Transaction/persistence/data write/FE-BE variable passing: Not applicable.
  • Performance: No material issue found.
  • Other issues: The remaining FoldConstantRuleOnFE.visitNvl gap can still produce incorrect nullable metadata after type coercion.

Because of that missed parallel path, I do not consider the fix complete yet.

Nvl nvl = ctx.expr;
if (nvl.child(0) instanceof NullLiteral) {
return TypeCoercionUtils.ensureSameResultType(nvl, nvl.child(1), ctx.rewriteContext);
return keepConditionalNullability(
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 fixes the SimplifyConditionalFunction path, but ifnull/nvl can still lose non-nullability through FoldConstantRuleOnFE.visitNvl(). That method still rewrites nvl(nonNullableExpr, nullLiteral) / nvl(nullLiteral, nonNullableExpr) via TypeCoercionUtils.ensureSameResultType(...) and, for cases like datetime(0) -> datetime(6), it returns a nullable Cast. Since FE constant folding is invoked directly in other planner flows (FoldConstantRuleOnFE.evaluate(...), InsertIntoValuesAnalyzer, etc.), the regression is still reachable even after this change. Please apply the same nullability preservation there and add a fold-constant test for that path.

@doris-robot
Copy link
Copy Markdown

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

------ Round 1 ----------------------------------
orders	Doris	NULL	NULL	0	0	0	NULL	0	NULL	NULL	2023-12-26 18:27:23	2023-12-26 18:42:55	NULL	utf-8	NULL	NULL	
============================================
q1	17590	3763	3708	3708
q2	q3	10688	853	610	610
q4	4691	464	355	355
q5	7458	1333	1145	1145
q6	182	168	143	143
q7	938	953	779	779
q8	9318	1386	1344	1344
q9	5515	5246	5167	5167
q10	6253	2016	1775	1775
q11	465	276	291	276
q12	636	402	277	277
q13	18046	2767	2153	2153
q14	287	285	258	258
q15	q16	878	850	773	773
q17	1068	1048	902	902
q18	6402	5693	5494	5494
q19	1161	1203	1047	1047
q20	567	417	291	291
q21	4914	2508	2049	2049
q22	559	442	354	354
Total cold run time: 97616 ms
Total hot run time: 28900 ms

----- Round 2, with runtime_filter_mode=off -----
orders	Doris	NULL	NULL	150000000	42	6422171781	NULL	22778155	NULL	NULL	2023-12-26 18:27:23	2023-12-26 18:42:55	NULL	utf-8	NULL	NULL	
============================================
q1	4489	4418	4618	4418
q2	q3	4624	4701	4167	4167
q4	2010	2100	1325	1325
q5	5022	5198	5349	5198
q6	192	166	149	149
q7	2034	1714	1624	1624
q8	3305	3062	3093	3062
q9	8248	8190	8412	8190
q10	4429	4415	4235	4235
q11	589	428	402	402
q12	669	705	487	487
q13	2639	3005	2383	2383
q14	303	331	278	278
q15	q16	825	780	699	699
q17	1249	1253	1209	1209
q18	7859	7099	7059	7059
q19	1120	1139	1137	1137
q20	2189	2191	1976	1976
q21	6253	5302	4825	4825
q22	562	511	438	438
Total cold run time: 58610 ms
Total hot run time: 53261 ms

@doris-robot
Copy link
Copy Markdown

TPC-DS: Total hot run time: 178724 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 27116af062c50570927f0b20d8e61a6262044843, data reload: false

query5	4365	674	529	529
query6	336	230	199	199
query7	4321	572	332	332
query8	335	239	218	218
query9	8738	3838	3842	3838
query10	451	357	307	307
query11	6652	5435	5139	5139
query12	186	139	129	129
query13	1278	621	446	446
query14	5729	5176	4808	4808
query14_1	4106	4120	4100	4100
query15	217	203	189	189
query16	1005	447	437	437
query17	1145	781	661	661
query18	2477	513	394	394
query19	224	214	183	183
query20	141	133	130	130
query21	232	145	126	126
query22	13873	14730	14664	14664
query23	18177	17094	16670	16670
query23_1	16858	16783	16797	16783
query24	7571	1709	1339	1339
query24_1	1354	1336	1337	1336
query25	576	478	441	441
query26	1253	319	168	168
query27	2680	666	359	359
query28	4462	1886	1885	1885
query29	949	641	601	601
query30	300	231	194	194
query31	1100	1051	944	944
query32	86	70	69	69
query33	537	348	284	284
query34	1231	1155	659	659
query35	748	769	655	655
query36	1249	1190	1075	1075
query37	156	102	82	82
query38	3088	3010	2989	2989
query39	910	888	857	857
query39_1	829	844	837	837
query40	229	144	127	127
query41	64	60	59	59
query42	113	108	104	104
query43	308	311	273	273
query44	
query45	212	192	187	187
query46	1140	1248	754	754
query47	2336	2314	2265	2265
query48	425	410	306	306
query49	634	543	434	434
query50	781	286	217	217
query51	4303	4272	4219	4219
query52	109	107	96	96
query53	248	273	194	194
query54	314	283	262	262
query55	100	91	88	88
query56	307	347	311	311
query57	1762	1682	1632	1632
query58	300	282	266	266
query59	2886	2990	2751	2751
query60	338	329	333	329
query61	159	157	156	156
query62	682	623	567	567
query63	245	199	191	191
query64	5295	1309	999	999
query65	
query66	1461	469	360	360
query67	24149	24156	24163	24156
query68	
query69	459	334	299	299
query70	972	993	990	990
query71	311	283	269	269
query72	2946	2720	2527	2527
query73	809	749	480	480
query74	9831	9757	9530	9530
query75	2767	2625	2327	2327
query76	2296	1149	788	788
query77	411	421	349	349
query78	11365	11333	10779	10779
query79	1349	1081	789	789
query80	658	626	558	558
query81	469	289	249	249
query82	246	168	129	129
query83	388	304	272	272
query84	267	153	123	123
query85	949	510	447	447
query86	372	310	338	310
query87	3265	3179	3079	3079
query88	3605	2731	2708	2708
query89	418	388	346	346
query90	2043	180	177	177
query91	178	172	144	144
query92	73	77	72	72
query93	945	982	564	564
query94	533	351	287	287
query95	646	372	349	349
query96	1035	809	363	363
query97	2731	2684	2591	2591
query98	249	229	229	229
query99	1082	1063	973	973
Total cold run time: 255822 ms
Total hot run time: 178724 ms

@starocean999
Copy link
Copy Markdown
Contributor Author

run buildall

@doris-robot
Copy link
Copy Markdown

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

------ Round 1 ----------------------------------
orders	Doris	NULL	NULL	0	0	0	NULL	0	NULL	NULL	2023-12-26 18:27:23	2023-12-26 18:42:55	NULL	utf-8	NULL	NULL	
============================================
q1	17670	3734	3688	3688
q2	q3	10712	870	632	632
q4	4679	464	357	357
q5	7471	1343	1137	1137
q6	183	168	138	138
q7	916	937	750	750
q8	9299	1472	1260	1260
q9	5594	5317	5264	5264
q10	6284	2008	1734	1734
q11	484	271	273	271
q12	643	410	282	282
q13	18035	2801	2147	2147
q14	278	278	259	259
q15	q16	897	858	784	784
q17	1067	1105	828	828
q18	6459	5680	5472	5472
q19	1160	1198	1058	1058
q20	583	418	289	289
q21	4867	2483	2018	2018
q22	499	407	370	370
Total cold run time: 97780 ms
Total hot run time: 28738 ms

----- Round 2, with runtime_filter_mode=off -----
orders	Doris	NULL	NULL	150000000	42	6422171781	NULL	22778155	NULL	NULL	2023-12-26 18:27:23	2023-12-26 18:42:55	NULL	utf-8	NULL	NULL	
============================================
q1	4505	4490	4376	4376
q2	q3	4600	4767	4205	4205
q4	2093	2210	1364	1364
q5	4903	5005	5161	5005
q6	200	163	137	137
q7	2017	1785	1596	1596
q8	3259	3032	3054	3032
q9	8298	8301	8450	8301
q10	4464	4647	4219	4219
q11	607	405	403	403
q12	648	718	495	495
q13	2744	3096	2378	2378
q14	312	308	276	276
q15	q16	762	791	687	687
q17	1258	1266	1200	1200
q18	7842	6861	6910	6861
q19	1129	1104	1157	1104
q20	2373	2324	2088	2088
q21	6104	5369	4640	4640
q22	538	487	425	425
Total cold run time: 58656 ms
Total hot run time: 52792 ms

@doris-robot
Copy link
Copy Markdown

TPC-DS: Total hot run time: 178539 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 6d19b5f6502d84280c718d123fc7febb161c6df9, data reload: false

query5	4331	679	522	522
query6	333	228	223	223
query7	4247	571	331	331
query8	332	257	235	235
query9	8760	3922	3906	3906
query10	461	377	321	321
query11	6665	5484	5140	5140
query12	194	133	131	131
query13	1319	621	454	454
query14	5681	5198	4796	4796
query14_1	4160	4160	4134	4134
query15	217	205	184	184
query16	1022	459	448	448
query17	1156	799	661	661
query18	2724	510	391	391
query19	238	216	173	173
query20	139	131	136	131
query21	229	147	126	126
query22	14016	14915	14302	14302
query23	17987	17166	16554	16554
query23_1	16744	16672	17059	16672
query24	7990	1879	1414	1414
query24_1	1399	1361	1374	1361
query25	671	496	438	438
query26	1284	313	180	180
query27	3180	624	363	363
query28	4567	1953	1930	1930
query29	1109	731	559	559
query30	307	239	197	197
query31	1114	1072	970	970
query32	88	75	71	71
query33	535	373	291	291
query34	1230	1178	704	704
query35	767	807	666	666
query36	1252	1279	1219	1219
query37	162	105	89	89
query38	3131	3090	3006	3006
query39	935	907	854	854
query39_1	849	838	874	838
query40	239	160	135	135
query41	63	58	59	58
query42	108	105	107	105
query43	304	315	278	278
query44	
query45	205	197	185	185
query46	1095	1225	776	776
query47	2333	2370	2224	2224
query48	424	436	304	304
query49	639	543	469	469
query50	771	315	216	216
query51	4338	4304	4211	4211
query52	112	112	98	98
query53	246	271	202	202
query54	324	278	260	260
query55	106	92	91	91
query56	301	314	329	314
query57	1644	1703	1521	1521
query58	299	269	281	269
query59	2885	2950	2691	2691
query60	359	355	316	316
query61	162	158	158	158
query62	688	623	571	571
query63	240	201	198	198
query64	5331	1344	998	998
query65	
query66	1427	477	383	383
query67	24487	24358	24207	24207
query68	
query69	459	349	307	307
query70	961	1033	963	963
query71	310	289	279	279
query72	2921	2710	2456	2456
query73	777	762	466	466
query74	9899	9754	9592	9592
query75	2735	2599	2316	2316
query76	2296	1130	770	770
query77	402	409	356	356
query78	11392	11404	10729	10729
query79	1499	1081	810	810
query80	980	564	519	519
query81	502	277	245	245
query82	1381	154	124	124
query83	344	293	261	261
query84	265	143	123	123
query85	916	513	455	455
query86	432	353	305	305
query87	3303	3207	3079	3079
query88	3591	2700	2728	2700
query89	443	385	351	351
query90	1918	177	178	177
query91	184	170	139	139
query92	77	75	74	74
query93	970	971	560	560
query94	617	349	307	307
query95	652	367	418	367
query96	1024	770	345	345
query97	2678	2663	2544	2544
query98	242	251	232	232
query99	1067	1073	984	984
Total cold run time: 259021 ms
Total hot run time: 178539 ms

@hello-stephen
Copy link
Copy Markdown
Contributor

FE UT Coverage Report

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

@starocean999 starocean999 marked this pull request as ready for review April 8, 2026 01:40
@morrySnow morrySnow marked this pull request as draft April 8, 2026 03:26
@morrySnow morrySnow closed this Apr 8, 2026
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.

4 participants