[
https://issues.apache.org/jira/browse/CALCITE-7529?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18081313#comment-18081313
]
Mihai Budiu commented on CALCITE-7529:
--------------------------------------
Can you explain what the strategy is? There are many kinds of constant
expressions involving TIMESTAMPs that this does not seem to handle, like
comparing timestamps, subtracting timestamps, calling functions on TIMESTAMPs.
> RexExecutor constant reduction loses sub-millisecond precision for
> TIME/TIMESTAMP literals
> ------------------------------------------------------------------------------------------
>
> Key: CALCITE-7529
> URL: https://issues.apache.org/jira/browse/CALCITE-7529
> Project: Calcite
> Issue Type: Bug
> Components: core
> Reporter: zzwqqq
> Priority: Major
> Labels: pull-request-available
>
> When a custom RelDataTypeSystem allows datetime precision greater than
> Calcite's default maximum precision, RexExecutor constant reduction can lose
> sub-millisecond precision for TIME and TIMESTAMP values.
> Calcite's default RelDataTypeSystem limits TIME/TIMESTAMP precision to 3, but
> users can override RelDataTypeSystem#getMaxPrecision. With such a type
> system, RexBuilder can be configured to create TIME(6) and TIMESTAMP(6)
> literals backed by TimeString/TimestampString.
> However, RexExecutorImpl reduces constant expressions through generated Java
> code, where TIME and TIMESTAMP values are represented using millisecond-based
> runtime values. When RexExecutable.reduce rebuilds a RexLiteral from those
> values, digits beyond milliseconds are lost.
> Minimal reproduction:
> {code:java}
> @Test void testReduceTimeCastWithMicros() {
> final RelDataTypeFactory typeFactory =
> new JavaTypeFactoryImpl(
> new RelDataTypeSystemImpl() {
> @Override public int getMaxPrecision(SqlTypeName typeName) {
> switch (typeName) {
> case TIME:
> case TIMESTAMP:
> return 6;
> default:
> return super.getMaxPrecision(typeName);
> }
> }
> });
> final RexBuilder rexBuilder = new RexBuilder(typeFactory);
> final RexExecutorImpl executor =
> new RexExecutorImpl(
> DataContexts.of(
> ImmutableMap.of(
> DataContext.Variable.TIME_ZONE.camelName,
> TimeZone.getTimeZone("GMT"),
> DataContext.Variable.LOCALE.camelName, Locale.US)));
> final RexNode cast =
> rexBuilder.makeCast(
> typeFactory.createSqlType(SqlTypeName.TIME, 6),
> rexBuilder.makeLiteral("12:34:56.123456"));
> final List<RexNode> reducedValues = new ArrayList<>();
> executor.reduce(rexBuilder, ImmutableList.of(cast), reducedValues);
> assertThat(
> ((RexLiteral)
> reducedValues.get(0)).getValueAs(TimeString.class).toString(6),
> equalTo("12:34:56.123456"));
> }
> {code}
> Expected:
> {code}
> 12:34:56.123456
> {code}
> Actual before the fix:
> {code}
> 12:34:56.123000
> {code}
> The same issue can occur for TIMESTAMP(6). It can also affect already-created
> high precision TimeString/TimestampString RexLiterals if they are passed
> through RexExecutorImpl.reduce.
> A possible fix is to preserve high-precision temporal literal casts as Rex
> literals when they can be represented directly by TimeString/TimestampString,
> and to let RexExecutorImpl return existing RexLiteral values without
> compiling and executing them again.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)