Skip to content

[test](expr opt) Cover narrow decimal cast nullability - #67893

Open
morrySnow wants to merge 1 commit into
apache:masterfrom
morrySnow:test/narrow-decimal-cast-nullability
Open

[test](expr opt) Cover narrow decimal cast nullability#67893
morrySnow wants to merge 1 commit into
apache:masterfrom
morrySnow:test/narrow-decimal-cast-nullability

Conversation

@morrySnow

Copy link
Copy Markdown
Contributor

Problem

Narrow numeric casts can return NULL for out-of-range values even when the source slot is NOT NULL. A range simplification that uses only the source-slot nullability can incorrectly replace a nullable comparison with a non-null Boolean constant. Existing coverage did not permanently exercise the INT-to-DECIMALV3(2, 0) path end to end.

Root cause

The production fix already preserves a cast that may introduce NULL as the nullability witness for range-derived constants. The remaining gap was test coverage: the focused unit test used BIGINT-to-TINYINT, and there was no permanent SQL regression proving that positive and negative decimal overflow stay NULL in both projections and filters.

Reproduction

Use a NOT NULL INT column containing -100, -99, 0, 99, and 100. Cast it to DECIMALV3(2, 0) and compare it with 99 or -99. The values outside the decimal range cast to NULL, so every comparison on those rows must remain NULL and WHERE must filter those rows out. The same semantics apply to TryCast.

Fix

  • Add exact rewrite assertions for Cast and TryCast from a non-null INT to DECIMALV3(2, 0), covering both true-or-null and false-or-null results at the upper and lower bounds.
  • Add a safe TinyInt-to-DECIMALV3(3, 0) widening control to ensure non-null Boolean simplification remains enabled when the conversion is total.
  • Add a permanent regression suite covering projection results, WHERE behavior, positive and negative overflow, and enabled-versus-disabled rule results.
  • Assert the optimized project retains the complete Cast/TryCast expression inside the null-aware form.

Tests

  • ./run-fe-ut.sh --run org.apache.doris.nereids.rules.expression.rules.SimplifyComparisonPredicateTest — 14 tests, 0 failures, 0 errors, 0 skipped.
  • DISABLE_BUILD_UI=ON ./build.sh --fe — full FE reactor build passed; checkstyle reported 0 violations.
  • Generated the new expected output with -forceGenOut against the rebuilt sandbox — 1 suite passed.
  • Ran the new regression normally against the rebuilt sandbox — 1 suite passed, 0 failed/fatal/skipped.

### What problem does this PR solve?

Issue Number: None

Related PR: None

Problem Summary: Narrow numeric casts can introduce NULL even when their input slot is declared NOT NULL. Range-based comparison simplification must therefore preserve the cast as the nullability witness. For example, casting a non-null INT value of 100 or -100 to DECIMALV3(2, 0) yields NULL, so comparisons against the decimal bounds also yield NULL. Existing tests covered a BIGINT-to-TINYINT conversion but did not permanently cover the INT-to-narrow-DECIMAL path or its end-to-end projection and filter behavior. Add exact Cast and TryCast rewrite assertions, a safe decimal widening control, and a regression matrix with rule-disabled results as the oracle.

### Release note

None

### Check List (For Author)

- Test: Unit Test, Regression test, and Manual test
    - Extended the comparison simplification unit test with narrow and widening DecimalV3 conversions.
    - Added projection, filter, plan-shape, overflow, and rule-disabled regression coverage for Cast and TryCast.
    - Ran the focused FE unit test, full FE build with checkstyle, and the generated-output and normal regression runs on a rebuilt local deployment.
- Behavior changed: No. This change adds permanent coverage for existing correct behavior and does not modify production code.
- Does this need documentation: No
@morrySnow
morrySnow requested a review from yujun777 as a code owner September 11, 2026 20:27
@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?

@morrySnow

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17550	3120	3126	3120
q2	2063	259	224	224
q3	10274	961	508	508
q4	4670	249	204	204
q5	7669	559	382	382
q6	137	117	94	94
q7	547	527	379	379
q8	9220	921	925	921
q9	3420	2371	2363	2363
q10	6538	847	724	724
q11	402	196	170	170
q12	640	260	201	201
q13	18094	1528	1147	1147
q14	153	152	139	139
q15	q16	431	391	367	367
q17	1397	882	785	785
q18	3026	2269	2261	2261
q19	1271	884	765	765
q20	366	280	196	196
q21	5571	1735	1839	1735
q22	334	272	227	227
Total cold run time: 93773 ms
Total hot run time: 16912 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	3440	3401	3387	3387
q2	493	400	372	372
q3	2188	2289	2154	2154
q4	1182	1160	895	895
q5	2172	2095	2080	2080
q6	162	120	88	88
q7	1026	915	847	847
q8	1573	1394	1389	1389
q9	3082	3063	3040	3040
q10	1932	1763	1619	1619
q11	351	268	250	250
q12	454	430	343	343
q13	1478	1535	1142	1142
q14	170	173	151	151
q15	q16	392	399	358	358
q17	3568	3352	3106	3106
q18	4792	4394	4735	4394
q19	840	771	918	771
q20	1006	1007	826	826
q21	3810	3074	3250	3074
q22	391	339	311	311
Total cold run time: 34502 ms
Total hot run time: 30597 ms

@hello-stephen

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

query5	4254	398	341	341
query6	385	144	133	133
query7	4938	412	219	219
query8	292	131	121	121
query9	8703	2868	2851	2851
query10	396	213	184	184
query11	5390	1023	918	918
query12	120	66	71	66
query13	1210	452	320	320
query14	6077	2223	2111	2111
query14_1	1981	1949	1940	1940
query15	170	124	114	114
query16	918	371	348	348
query17	810	459	362	362
query18	2326	330	232	232
query19	176	137	113	113
query20	71	72	71	71
query21	204	103	88	88
query22	5452	5466	5310	5310
query23	6960	6293	5826	5826
query23_1	6071	6100	6067	6067
query24	7358	1111	774	774
query24_1	774	762	779	762
query25	428	302	257	257
query26	1248	221	138	138
query27	2795	419	262	262
query28	4667	1495	1486	1486
query29	990	420	323	323
query30	263	153	132	132
query31	850	393	324	324
query32	134	66	72	66
query33	466	211	161	161
query34	980	858	474	474
query35	382	398	333	333
query36	571	549	528	528
query37	121	79	67	67
query38	999	839	803	803
query39	492	494	481	481
query39_1	470	485	459	459
query40	208	89	75	75
query41	54	52	51	51
query42	77	66	72	66
query43	238	241	213	213
query44	973	529	533	529
query45	111	107	100	100
query46	792	829	542	542
query47	756	756	698	698
query48	281	298	213	213
query49	538	232	181	181
query50	786	261	193	193
query51	7957	8111	8028	8028
query52	68	67	64	64
query53	192	198	142	142
query54	234	159	160	159
query55	70	58	57	57
query56	189	176	155	155
query57	728	710	629	629
query58	201	165	154	154
query59	1221	1204	1082	1082
query60	229	181	181	181
query61	113	108	129	108
query62	365	201	168	168
query63	165	137	134	134
query64	2684	676	569	569
query65	1612	1583	1612	1583
query66	1921	261	215	215
query67	10127	9516	9588	9516
query68	2761	1152	711	711
query69	355	220	194	194
query70	673	605	638	605
query71	252	171	173	171
query72	2366	1695	1468	1468
query73	658	583	351	351
query74	1558	1222	1148	1148
query75	1174	1107	947	947
query76	2304	715	500	500
query77	245	252	205	205
query78	4035	3738	3217	3217
query79	2812	809	585	585
query80	1571	314	263	263
query81	489	154	137	137
query82	909	137	96	96
query83	275	204	187	187
query84	299	109	89	89
query85	788	331	278	278
query86	389	176	164	164
query87	1022	977	904	904
query88	2765	2119	2075	2075
query89	289	195	176	176
query90	1938	128	128	128
query91	127	121	95	95
query92	70	68	66	66
query93	1671	1045	694	694
query94	618	242	226	226
query95	554	317	220	220
query96	838	606	253	253
query97	1032	1057	994	994
query98	168	138	136	136
query99	415	341	309	309
Total cold run time: 178627 ms
Total hot run time: 81146 ms

@hello-stephen

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

query1	0.01	0.01	0.01
query2	0.08	0.04	0.04
query3	0.25	0.11	0.10
query4	1.60	0.09	0.10
query5	0.18	0.15	0.16
query6	1.29	0.69	0.67
query7	0.03	0.00	0.01
query8	0.05	0.03	0.03
query9	0.28	0.20	0.22
query10	0.34	0.35	0.37
query11	0.16	0.11	0.12
query12	0.16	0.12	0.12
query13	0.32	0.29	0.31
query14	0.44	0.45	0.43
query15	0.36	0.35	0.36
query16	0.24	0.22	0.24
query17	0.70	0.68	0.71
query18	0.19	0.17	0.18
query19	1.25	1.14	1.12
query20	0.02	0.00	0.01
query21	15.47	0.17	0.12
query22	5.09	0.05	0.04
query23	16.18	0.25	0.10
query24	3.03	0.31	0.25
query25	0.10	0.05	0.04
query26	0.77	0.17	0.13
query27	0.03	0.03	0.02
query28	3.68	0.57	0.28
query29	12.42	3.16	2.57
query30	0.26	0.11	0.12
query31	2.75	0.37	0.17
query32	3.54	0.33	0.23
query33	1.36	1.49	1.64
query34	15.34	2.21	1.78
query35	1.75	1.70	1.73
query36	0.46	0.30	0.28
query37	0.06	0.03	0.03
query38	0.04	0.03	0.03
query39	0.03	0.03	0.02
query40	0.11	0.08	0.07
query41	0.07	0.02	0.03
query42	0.03	0.03	0.03
query43	0.04	0.03	0.03
Total cold run time: 90.56 s
Total hot run time: 14.67 s

@morrySnow morrySnow changed the title [test](nereids) Cover narrow decimal cast nullability [test](expr opt) Cover narrow decimal cast nullability Sep 12, 2026
hello-stephen pushed a commit that referenced this pull request Sep 12, 2026
…67897)

Since today every `Doris_DorisCloudRegression_VaultP0` run dies in the
`run` step before executing a single test, e.g.
#67883 (TeamCity build 39010) and
#67881 / #67882 / #67885 / #67886 / #67892 / #67893:

```
doris-external--minio Pulling
doris-external--minio Error
Error response from daemon: pull access denied for minio/minio, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
ERROR: start minio docker twice failed
```

MinIO stopped publishing container images in October 2025 (the project
is a source-only distribution now, see minio/minio#21647) and the
`minio/minio` and `minio/mc` repositories have since been removed from
Docker Hub altogether
(`https://hub.docker.com/v2/repositories/minio/minio/` answers 404, same
for `minio/mc`). The few VaultP0 runs that still pass do so only on
agents that have the image cached locally (their logs have no `Pulling`
line). The iceberg, hudi and polaris third-party fixtures,
`test_file_cache_warmup_read_metrics_docker` (which runs a `docker run
minio/minio` itself), the all-in-one `cloud.yml` and the datalake
samples reference the same images and are one cache eviction away from
the same failure.

`quay.io/minio/minio` and `quay.io/minio/mc` still serve every tag we
use -- `RELEASE.2024-11-07T00-52-20Z`, `RELEASE.2025-01-20T14-49-07Z`,
mc `RELEASE.2025-01-17T23-25-50Z`, the two 2022 tags of the samples and
`latest` -- and MinIO keeps pushing hotfix tags there (latest one dated
2026-04). `docker manifest inspect` resolves all of them (amd64 / arm64
/ ppc64le). So every reference gets the `quay.io/` prefix and the tags
stay exactly as they were: same builds, different registry. The CI
agents already pull from quay.io for the OceanBase fixture.

A longer-term option is to mirror these three tags into the project's
own `doristhirdpartydocker` namespace, which already hosts hive /
zookeeper / kafka / trinodb; that needs someone with push access to that
Docker Hub organization and can follow separately.
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