You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@calcite.apache.org by "Julian Hyde (Jira)" <ji...@apache.org> on 2023/04/19 18:30:00 UTC

[jira] [Commented] (CALCITE-5651) Type system decimal scale in inferred types may exceed allowed scale

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

Julian Hyde commented on CALCITE-5651:
--------------------------------------

Some DBs may not allow it, but it is reasonable to allow scale larger than precision. A value of type {{NUMBER(3, 10)}} can store values such as '0.000 000 000 1' and '0.000 000 099 9' exactly.

It is also reasonable to allow negative scales. If you want to store the number of atoms to 3 significant figures, you could use a type {{{}NUMBER(3, -23){}}}, bearing in mind that Avogadro's number is 6e23.

> Type system decimal scale in inferred types may exceed allowed scale
> --------------------------------------------------------------------
>
>                 Key: CALCITE-5651
>                 URL: https://issues.apache.org/jira/browse/CALCITE-5651
>             Project: Calcite
>          Issue Type: Bug
>          Components: core
>    Affects Versions: 1.34.0
>            Reporter: Mihai Budiu
>            Priority: Major
>              Labels: pull-request-available
>          Time Spent: 1h 50m
>  Remaining Estimate: 0h
>
> If one uses a type system with a scale which is < precision/2 the calcite compiler may crash with an assertion failure. This can happen in the RelDataTypeSystem.deriveDecimalPlusType method, where this assertion fails:
> assert scale <= getMaxNumericScale();
> The root cause is the function SqlTypeUtil.getMaxPrecisionScaleDecimal, which does the following:
> int scale = maxPrecision / 2;
> This was introduced in Calcite 1.27.
> I think the a better version should be
> int scale = Math.min(maxPrecision/2, factory.getTypeSystem().getMaxNumericScale());
> To reproduce this bug I had to do a bit of juggling. First I had to fix the bug reported in CALCITE-5650. Then I added the following two functions in RelToSqlConverterTest.java:
> {code}
> @Test void testNumericScale() {
>     String q = "WITH v(x) AS (VALUES('4.2')) " +
>         " SELECT x1 + x2 FROM v AS v1(x1), v AS V2(x2)";
>     sql(q)
>         .withPostgresqlModifiedDecimalTypeSystem()
>         .ok("");
>   }
> {code}
> and in the static class Sql I added this method:
> {code}
>     Sql withPostgresqlModifiedDecimalTypeSystem() {
>       final PostgresqlSqlDialect postgresqlSqlDialect =
>           new PostgresqlSqlDialect(PostgresqlSqlDialect.DEFAULT_CONTEXT
>               .withDataTypeSystem(new RelDataTypeSystemImpl() {
>                 @Override
>                 public int getMaxNumericScale() {
>                   return 10;
>                 }
>                 @Override
>                 public int getMaxNumericPrecision() {
>                   return 39;
>                 }
>               }));
>       return dialect(postgresqlSqlDialect);
>     }
> {code}
> This is the exception stack trace:
> {noformat}
> java.lang.AssertionError
>     at org.apache.calcite.rel.type.RelDataTypeSystem.deriveDecimalPlusType(RelDataTypeSystem.java:167)
>     at org.apache.calcite.sql.type.ReturnTypes.lambda$static$8(ReturnTypes.java:653)
>     at org.apache.calcite.sql.type.SqlTypeTransformCascade.inferReturnType(SqlTypeTransformCascade.java:58)
>     at org.apache.calcite.sql.type.SqlReturnTypeInferenceChain.inferReturnType(SqlReturnTypeInferenceChain.java:55)
>     at org.apache.calcite.sql.SqlOperator.inferReturnType(SqlOperator.java:537)
>     at org.apache.calcite.sql.SqlOperator.validateOperands(SqlOperator.java:504)
>     at org.apache.calcite.sql.SqlOperator.deriveType(SqlOperator.java:605)
>     at org.apache.calcite.sql.SqlBinaryOperator.deriveType(SqlBinaryOperator.java:178)
>     at org.apache.calcite.sql.validate.SqlValidatorImpl$DeriveTypeVisitor.visit(SqlValidatorImpl.java:6521)
>     at org.apache.calcite.sql.validate.SqlValidatorImpl$DeriveTypeVisitor.visit(SqlValidatorImpl.java:6508)
>     at org.apache.calcite.sql.SqlCall.accept(SqlCall.java:161)
>     at org.apache.calcite.sql.validate.SqlValidatorImpl.deriveTypeImpl(SqlValidatorImpl.java:1897)
>     at org.apache.calcite.sql.validate.SqlValidatorImpl.deriveType(SqlValidatorImpl.java:1882)
>     at org.apache.calcite.sql.validate.SqlValidatorImpl.expandSelectItem(SqlValidatorImpl.java:489)
>     at org.apache.calcite.sql.validate.SqlValidatorImpl.validateSelectList(SqlValidatorImpl.java:4608)
>     at org.apache.calcite.sql.validate.SqlValidatorImpl.validateSelect(SqlValidatorImpl.java:3780)
>     at org.apache.calcite.sql.validate.SelectNamespace.validateImpl(SelectNamespace.java:61)
>     at org.apache.calcite.sql.validate.AbstractNamespace.validate(AbstractNamespace.java:88)
>     at org.apache.calcite.sql.validate.SqlValidatorImpl.validateNamespace(SqlValidatorImpl.java:1135)
>     at org.apache.calcite.sql.validate.SqlValidatorImpl.validateQuery(SqlValidatorImpl.java:1106)
>     at org.apache.calcite.sql.validate.WithNamespace.validateImpl(WithNamespace.java:59)
>     at org.apache.calcite.sql.validate.AbstractNamespace.validate(AbstractNamespace.java:88)
>     at org.apache.calcite.sql.validate.SqlValidatorImpl.validateNamespace(SqlValidatorImpl.java:1135)
>     at org.apache.calcite.sql.validate.SqlValidatorImpl.validateWith(SqlValidatorImpl.java:4240)
>     at org.apache.calcite.sql.SqlWith.validate(SqlWith.java:74)
>     at org.apache.calcite.sql.validate.SqlValidatorImpl.validateScopedExpression(SqlValidatorImpl.java:1081)
>     at org.apache.calcite.sql.validate.SqlValidatorImpl.validate(SqlValidatorImpl.java:787)
>     at org.apache.calcite.prepare.PlannerImpl.validate(PlannerImpl.java:226)
>     at org.apache.calcite.rel.rel2sql.RelToSqlConverterTest$Sql.exec(RelToSqlConverterTest.java:7076)
>     at org.apache.calcite.rel.rel2sql.RelToSqlConverterTest$Sql.ok(RelToSqlConverterTest.java:7043)
>     at org.apache.calcite.rel.rel2sql.RelToSqlConverterTest.testNumericScale(RelToSqlConverterTest.java:1027)
>     at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>     at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
>     at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>     at java.base/java.lang.reflect.Method.invoke(Method.java:566)
>     at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
>     at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
>     at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
>     at org.junit.jupiter.engine.extension.SameThreadTimeoutInvocation.proceed(SameThreadTimeoutInvocation.java:45)
>     at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
>     at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
>     at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
>     at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
>     at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
>     at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
>     at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
>     at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
>     at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
>     at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
>     at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
>     at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
>     at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
>     at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
>     at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
>     at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
>     at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
>     at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
>     at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
>     at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
>     at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
>     at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
>     at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
>     at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
>     at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:185)
>     at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService.invokeAll(ForkJoinPoolHierarchicalTestExecutorService.java:129)
>     at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
>     at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
>     at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
>     at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
>     at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
>     at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
>     at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
>     at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
>     at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:185)
>     at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService.invokeAll(ForkJoinPoolHierarchicalTestExecutorService.java:129)
>     at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
>     at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
>     at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
>     at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
>     at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
>     at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
>     at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
>     at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
>     at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:185)
>     at java.base/java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:189)
>     at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
>     at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
>     at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
>     at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
>     at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
> {noformat}



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