[ 
https://issues.apache.org/jira/browse/CALCITE-7529?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18083004#comment-18083004
 ] 

zzwqqq commented on CALCITE-7529:
---------------------------------

OK, I have updated the issue and PR titles/descriptions to match the 
cast/literal-cast scope. Please take a look.

> Casts between literals and TIME/TIMESTAMP can lose precision beyond 
> milliseconds
> --------------------------------------------------------------------------------
>
>                 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.
> Note: After discussion, this issue is narrowed to casts involving temporal 
> literals. Broader TIME/TIMESTAMP constant-expression handling likely requires 
> an evaluator-level change and may be covered by other issues.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to