Skip to content

[fix](nereids) Fix TIMESTAMPTZ string cast in FE folding#63144

Open
zclllyybb wants to merge 1 commit into
apache:masterfrom
zclllyybb:codex-master-ttz-string-fe
Open

[fix](nereids) Fix TIMESTAMPTZ string cast in FE folding#63144
zclllyybb wants to merge 1 commit into
apache:masterfrom
zclllyybb:codex-master-ttz-string-fe

Conversation

@zclllyybb
Copy link
Copy Markdown
Contributor

FE constant folding casts folded TIMESTAMPTZ values through TimestampTzLiteral.checkedCastTo(). TimestampTzLiteral stores the normalized instant as UTC date/time fields, and the old FE cast path only handled TIMESTAMPTZ and DATETIMEV2 targets. For string-like targets this exposed the internal UTC fields instead of formatting the value in the session time zone like runtime evaluation does.

Add explicit CHAR, VARCHAR, and STRING cast handling for TimestampTzLiteral. The new path converts the internal UTC instant to DateUtils.getTimeZone(), preserves the literal scale, and appends the rendered zone offset so folded results match TIMESTAMPTZ string semantics.

Example covered by the test: an internal UTC value of 2023-07-13 19:26:00 in session time zone +12:34 folds to 2023-07-14 08:00:00+12:34, not the raw UTC value.

Add FE unit coverage for FoldConstantRuleOnFE casting TIMESTAMPTZ to STRING and direct VARCHAR/CHAR casts.

@zclllyybb zclllyybb requested review from Mryange and linrrzqqq May 11, 2026 12:07
@zclllyybb
Copy link
Copy Markdown
Contributor Author

/review

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

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 one correctness issue in the new FE TIMESTAMPTZ-to-string folding path. The implementation otherwise stays focused and has targeted unit coverage for offset-based session time zones, but it misses Doris-supported timezone aliases such as CST.

Critical checkpoint conclusions:

  • Goal/test: The PR aims to make FE folding of TIMESTAMPTZ string casts match session-time-zone output; tests cover numeric offset zones and scale preservation, but not alias zones.
  • Scope: The change is small and localized to TimestampTzLiteral casting plus tests.
  • Concurrency/lifecycle/config: No new concurrency, lifecycle, or config concerns.
  • Compatibility/parallel paths: FE folding should match BE/runtime cast semantics; the alias handling gap breaks this for valid session time zones.
  • Testing: Needs an additional alias-zone case, e.g. CST, after fixing timezone resolution.
  • Observability/transactions/data writes: Not applicable.

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

@@ -180,6 +195,29 @@ protected Expression uncheckedCastTo(DataType targetType) throws AnalysisExcepti
throw new AnalysisException(String.format("Cast from %s to %s not supported", this, targetType));
}

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 uses DateUtils.getTimeZone(), which calls ZoneId.of() on the raw session variable without Doris' alias map. SET time_zone = 'CST' is valid in FE (TimeUtils.checkTimeZoneValidAndStandardize accepts it and maps it to Asia/Shanghai, and BE query globals also special-case CST), but this new FE folding path will now throw ZoneRulesException: Unknown time-zone ID: CST when folding CAST(<timestamptz literal> AS STRING/VARCHAR/CHAR). Please resolve the session zone through the same alias-aware path as the rest of FE, for example TimeUtils.getTimeZone().toZoneId() or ZoneId.of(sessionTimeZone, TimeUtils.timeZoneAliasMap), and add a test for CST so FE folding remains consistent with runtime casting.

Comment on lines +182 to +183
} else if (targetType.isVarcharType()) {
return new VarcharLiteral(getStringValueInSessionTimeZone(), ((VarcharType) targetType).getLen());
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.

why do not check length as char ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

uncheckedCastToString#Literal.java also dont check for varchar. only char checks. but I make the code same by directly use uncheckedCastToString#Literal.java and override castValueToString

@zclllyybb zclllyybb force-pushed the codex-master-ttz-string-fe branch from 36ef310 to 804c370 Compare May 19, 2026 15:15
FE constant folding casts folded TIMESTAMPTZ values through TimestampTzLiteral.checkedCastTo(). TimestampTzLiteral stores the normalized instant as UTC date/time fields, and the old FE cast path only handled TIMESTAMPTZ and DATETIMEV2 targets. For string-like targets this exposed the internal UTC fields instead of formatting the value in the session time zone like runtime evaluation does.

Teach TimestampTzLiteral to provide a TIMESTAMPTZ-aware castValueToString(): convert the internal UTC instant to DateUtils.getTimeZone(), preserve the literal scale, and append the rendered zone offset. The actual CHAR/VARCHAR/STRING folding is delegated to Literal.uncheckedCastToString() so the behavior stays consistent with the rest of Nereids: STRING keeps the full value, VARCHAR uses VarcharLiteral length truncation, and CHAR only folds when the target length can hold the rendered value.

The offset suffix is formatted from ZoneOffset.getTotalSeconds() as sign + HH:MM and documented as matching BE TimestampTzValue::to_string() in be/src/core/value/timestamptz_value.cpp. This avoids Java library ids such as Z for UTC, and keeps FE constant folding aligned with BE runtime stringification.

Example covered by the test: an internal UTC value of 2023-07-13 19:26:00 in session time zone +12:34 folds to 2023-07-14 08:00:00+12:34, not the raw UTC value. The same test also checks UTC renders +00:00 rather than Z.

Add FE unit coverage for FoldConstantRuleOnFE casting TIMESTAMPTZ to STRING and direct VARCHAR/CHAR casts.

Verification: mvn test -Dcheckstyle.skip=true -DfailIfNoTests=false -Dmaven.build.cache.enabled=false -Dtest=org.apache.doris.nereids.trees.expressions.literal.TimestampTzLiteralTest -Dfe_ut_parallel=0
@zclllyybb zclllyybb force-pushed the codex-master-ttz-string-fe branch from 804c370 to f032d5c Compare May 19, 2026 16:08
@zclllyybb
Copy link
Copy Markdown
Contributor Author

run buildall

@zclllyybb
Copy link
Copy Markdown
Contributor Author

/review

@hello-stephen
Copy link
Copy Markdown
Contributor

TPC-H: Total hot run time: 31240 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit f032d5cd3e6dda79787f11a7d6512fd854922f36, 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	17643	3890	3780	3780
q2	q3	10752	1345	826	826
q4	4682	474	342	342
q5	7579	2312	2070	2070
q6	245	179	138	138
q7	956	785	642	642
q8	9406	1720	1658	1658
q9	5116	4914	4870	4870
q10	6379	2065	1790	1790
q11	434	284	245	245
q12	625	423	295	295
q13	18108	3335	2831	2831
q14	267	256	232	232
q15	q16	813	771	716	716
q17	967	937	946	937
q18	6858	5803	5556	5556
q19	1324	1312	1073	1073
q20	503	408	260	260
q21	6305	2855	2653	2653
q22	479	382	326	326
Total cold run time: 99441 ms
Total hot run time: 31240 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	4769	4508	4479	4479
q2	q3	4853	5259	4605	4605
q4	2106	2238	1409	1409
q5	4749	4908	4621	4621
q6	230	176	131	131
q7	1834	1721	1516	1516
q8	2359	2069	2072	2069
q9	7762	7588	7233	7233
q10	4436	4377	3972	3972
q11	526	382	348	348
q12	713	705	510	510
q13	3065	3288	2772	2772
q14	265	273	249	249
q15	q16	687	702	612	612
q17	1270	1223	1226	1223
q18	7116	6872	6902	6872
q19	1118	1090	1104	1090
q20	2200	2230	1923	1923
q21	5281	4581	4511	4511
q22	517	461	409	409
Total cold run time: 55856 ms
Total hot run time: 50554 ms

@hello-stephen
Copy link
Copy Markdown
Contributor

TPC-DS: Total hot run time: 169873 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 f032d5cd3e6dda79787f11a7d6512fd854922f36, data reload: false

query5	4344	678	520	520
query6	324	231	206	206
query7	4310	510	311	311
query8	326	233	231	231
query9	8863	4082	4101	4082
query10	461	337	297	297
query11	5769	2370	2228	2228
query12	191	130	130	130
query13	1306	567	418	418
query14	5958	5367	5022	5022
query14_1	4344	4322	4336	4322
query15	210	203	183	183
query16	997	480	435	435
query17	978	725	590	590
query18	2476	482	348	348
query19	215	203	167	167
query20	136	136	130	130
query21	214	147	118	118
query22	13580	13592	13345	13345
query23	17352	16448	16057	16057
query23_1	16294	16160	16254	16160
query24	7376	1785	1331	1331
query24_1	1276	1307	1308	1307
query25	583	494	433	433
query26	1305	350	183	183
query27	2653	585	350	350
query28	4464	1982	2001	1982
query29	1054	630	513	513
query30	307	240	202	202
query31	1143	1062	955	955
query32	97	80	81	80
query33	581	371	319	319
query34	1180	1153	655	655
query35	774	778	696	696
query36	1389	1345	1174	1174
query37	161	112	98	98
query38	3231	3180	3079	3079
query39	947	913	928	913
query39_1	905	882	875	875
query40	233	161	138	138
query41	75	73	70	70
query42	115	114	114	114
query43	331	334	289	289
query44	
query45	220	205	196	196
query46	1077	1212	722	722
query47	2318	2351	2192	2192
query48	431	449	306	306
query49	641	508	412	412
query50	988	356	257	257
query51	4314	4306	4171	4171
query52	110	112	100	100
query53	267	295	213	213
query54	335	301	278	278
query55	100	94	92	92
query56	332	332	332	332
query57	1417	1426	1325	1325
query58	314	289	291	289
query59	1583	1681	1454	1454
query60	380	333	306	306
query61	155	156	150	150
query62	680	613	550	550
query63	243	205	206	205
query64	2434	811	628	628
query65	
query66	1731	470	364	364
query67	30017	29956	29873	29873
query68	
query69	456	355	300	300
query70	1028	1041	979	979
query71	309	280	274	274
query72	3000	2673	2366	2366
query73	833	761	417	417
query74	5087	4906	4783	4783
query75	2680	2597	2275	2275
query76	2283	1158	769	769
query77	408	405	338	338
query78	12224	12293	11751	11751
query79	1438	1054	753	753
query80	638	555	468	468
query81	458	279	244	244
query82	1364	163	125	125
query83	362	275	245	245
query84	306	145	109	109
query85	863	571	452	452
query86	409	366	307	307
query87	3434	3350	3250	3250
query88	3589	2679	2667	2667
query89	434	393	341	341
query90	1968	192	192	192
query91	178	169	139	139
query92	80	82	78	78
query93	1469	1514	852	852
query94	549	352	321	321
query95	694	474	364	364
query96	1051	803	331	331
query97	2752	2703	2570	2570
query98	239	239	231	231
query99	1153	1091	982	982
Total cold run time: 253531 ms
Total hot run time: 169873 ms

@hello-stephen
Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 89.47% (17/19) 🎉
Increment coverage report
Complete coverage report

@hello-stephen
Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

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

@zclllyybb zclllyybb requested a review from morrySnow May 20, 2026 06:51
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.

3 participants