diff --git a/babel/src/test/resources/sql/big-query.iq b/babel/src/test/resources/sql/big-query.iq index 5ffa0bdf66d1..a158bd16eed0 100755 --- a/babel/src/test/resources/sql/big-query.iq +++ b/babel/src/test/resources/sql/big-query.iq @@ -660,6 +660,7 @@ SELECT SAFE_ADD(CAST(1.7e308 as DOUBLE), CAST(1.7e308 as DOUBLE)) as double_over !ok +!if (fixed.calcite6328) { SELECT SAFE_ADD(9, cast(9.999999999999999999e75 as DECIMAL(38, 19))) as decimal_overflow; +------------------+ | decimal_overflow | @@ -669,6 +670,7 @@ SELECT SAFE_ADD(9, cast(9.999999999999999999e75 as DECIMAL(38, 19))) as decimal_ (1 row) !ok +!} # NaN arguments should return NaN SELECT SAFE_ADD(CAST('NaN' AS DOUBLE), CAST(3 as BIGINT)) as NaN_result; @@ -720,6 +722,7 @@ SELECT SAFE_DIVIDE(CAST(1.7e308 as DOUBLE), !ok +!if (fixed.calcite6328) { SELECT SAFE_DIVIDE(CAST(-3.5e75 AS DECIMAL(76, 0)), CAST(3.5e-75 AS DECIMAL(76, 0))) as decimal_overflow; +------------------+ @@ -730,6 +733,7 @@ SELECT SAFE_DIVIDE(CAST(-3.5e75 AS DECIMAL(76, 0)), (1 row) !ok +!} # NaN arguments should return NaN SELECT SAFE_DIVIDE(CAST('NaN' AS DOUBLE), CAST(3 as BIGINT)) as NaN_result; @@ -801,6 +805,7 @@ SELECT SAFE_MULTIPLY(CAST(1.7e308 as DOUBLE), CAST(3 as BIGINT)) as double_overf !ok +!if (fixed.calcite6328) { SELECT SAFE_MULTIPLY(CAST(-3.5e75 AS DECIMAL(76, 0)), CAST(10 AS BIGINT)) as decimal_overflow; +------------------+ | decimal_overflow | @@ -810,6 +815,7 @@ SELECT SAFE_MULTIPLY(CAST(-3.5e75 AS DECIMAL(76, 0)), CAST(10 AS BIGINT)) as dec (1 row) !ok +!} # NaN arguments should return NaN SELECT SAFE_MULTIPLY(CAST('NaN' AS DOUBLE), CAST(3 as BIGINT)) as NaN_result; @@ -916,6 +922,7 @@ SELECT SAFE_SUBTRACT(CAST(1.7e308 as DOUBLE), CAST(-1.7e308 as DOUBLE)) as doubl !ok +!if (fixed.calcite6328) { SELECT SAFE_SUBTRACT(9, cast(-9.999999999999999999e75 as DECIMAL(38, 19))) as decimal_overflow; +------------------+ | decimal_overflow | @@ -925,6 +932,7 @@ SELECT SAFE_SUBTRACT(9, cast(-9.999999999999999999e75 as DECIMAL(38, 19))) as de (1 row) !ok +!} # NaN arguments should return NaN SELECT SAFE_SUBTRACT(CAST('NaN' AS DOUBLE), CAST(3 as BIGINT)) as NaN_result; diff --git a/babel/src/test/resources/sql/redshift.iq b/babel/src/test/resources/sql/redshift.iq index 6104222746f3..d5d9f255f3a0 100755 --- a/babel/src/test/resources/sql/redshift.iq +++ b/babel/src/test/resources/sql/redshift.iq @@ -184,7 +184,7 @@ select approximate percentile_disc(0.5) within group (order by sal) from emp gro # AVG select avg(sal) from emp; EXPR$0 -2073.214285714286 +2073.21 !ok # COUNT @@ -288,12 +288,12 @@ select percentile_disc(0.6) within group (order by sal) from emp group by deptno # STDDEV_SAMP and STDDEV_POP select stddev_samp(sal) from emp; EXPR$0 -1182.503223516271873450023122131824493408203125 +1182.50 !ok select stddev_pop(sal) from emp; EXPR$0 -1139.488618295281639802851714193820953369140625 +1139.48 !ok # SUM @@ -308,24 +308,24 @@ EXPR$0 !ok # VAR_SAMP and VAR_POP -select var_samp(sal) from emp; +select var_samp(CAST(sal AS DECIMAL(11, 4))) from emp; EXPR$0 -1398313.873626374 +1398313.8736 !ok -select var_samp(distinct sal) from emp; +select var_samp(distinct CAST(sal AS DECIMAL(11, 4))) from emp; EXPR$0 -1512779.356060606 +1512779.3560 !ok -select var_samp(all sal) from emp; +select var_samp(all CAST(sal AS DECIMAL(11, 4))) from emp; EXPR$0 -1398313.873626374 +1398313.8736 !ok -select var_pop(sal) from emp; +select var_pop(CAST(sal AS DECIMAL(11, 4))) from emp; EXPR$0 -1298434.31122449 +1298434.3112 !ok # 4 Bit-Wise Aggregate Functions @@ -378,10 +378,10 @@ select empno, avg(sal) over (order by empno rows unbounded preceding) from emp w EMPNO, EXPR$1 7499, 1600.00 7521, 1425.00 -7654, 1366.666666666667 +7654, 1366.66 7698, 1737.50 7844, 1690.00 -7900, 1566.666666666667 +7900, 1566.66 !ok # COUNT @@ -525,33 +525,33 @@ select deptno, ratio_to_report(sal) over (partition by deptno) from emp; # STDDEV_POP select empno, stddev_pop(comm) over (order by empno rows unbounded preceding) from emp where deptno = 30 order by 1; EMPNO, EXPR$1 -7499, 0 -7521, 100 -7654, 478.42333648024424519462627358734607696533203125 -7698, 478.42333648024424519462627358734607696533203125 -7844, 522.0153254455275373402400873601436614990234375 -7900, 522.0153254455275373402400873601436614990234375 +7499, 0.00 +7521, 100.00 +7654, 478.42 +7698, 478.42 +7844, 522.01 +7900, 522.01 !ok # STDDEV_SAMP (synonym for STDDEV) select empno, stddev_samp(comm) over (order by empno rows unbounded preceding) from emp where deptno = 30 order by 1; EMPNO, EXPR$1 7499, null -7521, 141.421356237309510106570087373256683349609375 -7654, 585.9465277082316561063635163009166717529296875 -7698, 585.9465277082316561063635163009166717529296875 -7844, 602.7713773341707792496890760958194732666015625 -7900, 602.7713773341707792496890760958194732666015625 +7521, 141.42 +7654, 585.94 +7698, 585.94 +7844, 602.77 +7900, 602.77 !ok select empno, stddev(comm) over (order by empno rows unbounded preceding) from emp where deptno = 30 order by 1; EMPNO, EXPR$1 7499, null -7521, 141.421356237309510106570087373256683349609375 -7654, 585.9465277082316561063635163009166717529296875 -7698, 585.9465277082316561063635163009166717529296875 -7844, 602.7713773341707792496890760958194732666015625 -7900, 602.7713773341707792496890760958194732666015625 +7521, 141.42 +7654, 585.94 +7698, 585.94 +7844, 602.77 +7900, 602.77 !ok # SUM @@ -566,35 +566,35 @@ EMPNO, EXPR$1 !ok # VAR_POP -select empno, var_pop(comm) over (order by empno rows unbounded preceding) from emp where deptno = 30 order by 1; +select empno, var_pop(CAST(comm AS DECIMAL(10, 2))) over (order by empno rows unbounded preceding) from emp where deptno = 30 order by 1; EMPNO, EXPR$1 -7499, 0.0000 -7521, 10000.0000 -7654, 228888.888888889 -7698, 228888.888888889 -7844, 272500.0000 -7900, 272500.0000 +7499, 0.00 +7521, 10000.00 +7654, 228888.88 +7698, 228888.88 +7844, 272500.00 +7900, 272500.00 !ok # VAR_SAMP (synonym for VARIANCE) -select empno, var_samp(comm) over (order by empno rows unbounded preceding) from emp where deptno = 30 order by 1; +select empno, var_samp(CAST(comm AS DECIMAL(10, 2))) over (order by empno rows unbounded preceding) from emp where deptno = 30 order by 1; EMPNO, EXPR$1 7499, null -7521, 20000.0000 -7654, 343333.3333333335 -7698, 343333.3333333335 -7844, 363333.3333333333 -7900, 363333.3333333333 +7521, 20000.00 +7654, 343333.33 +7698, 343333.33 +7844, 363333.33 +7900, 363333.33 !ok -select empno, variance(comm) over (order by empno rows unbounded preceding) from emp where deptno = 30 order by 1; +select empno, variance(CAST(comm AS DECIMAL(10, 2))) over (order by empno rows unbounded preceding) from emp where deptno = 30 order by 1; EMPNO, EXPR$1 7499, null -7521, 20000.0000 -7654, 343333.3333333335 -7698, 343333.3333333335 -7844, 363333.3333333333 -7900, 363333.3333333333 +7521, 20000.00 +7654, 343333.33 +7698, 343333.33 +7844, 363333.33 +7900, 363333.33 !ok # 5.2 Ranking functions @@ -2030,12 +2030,12 @@ SELECT "JSON_EXTRACT_PATH_TEXT"('{"f2":{"f3":1},"f4":{"f5":99,"f6":"star"}}', 'f # CAST and CONVERT select cast(stddev_samp(sal) as dec(14, 2)) from emp; EXPR$0 -1182.503223516271873450023122131824493408203125 +1182.50 !ok select 123.456::decimal(8,4); EXPR$0 -123.456 +123.4560 !ok !if (position) { diff --git a/babel/src/test/resources/sql/spark.iq b/babel/src/test/resources/sql/spark.iq index 668d15409e4b..d4d512489bcb 100644 --- a/babel/src/test/resources/sql/spark.iq +++ b/babel/src/test/resources/sql/spark.iq @@ -440,7 +440,7 @@ EXPR$0 SELECT REVERSE(array(CAST(2.1 as decimal(17)), 2.1111111111111119)); EXPR$0 -[2.1111111111111119, 2.1] +[2.11, 2.00] !ok SELECT REVERSE(array(CAST(2.1 as double), 2.1111111111111119)); diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java index 64db857bb503..39014391da81 100644 --- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java +++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java @@ -474,6 +474,27 @@ private Expression getConvertExpression( Expressions.constant(precision), Expressions.constant(scale), Expressions.constant(sourceType.getSqlTypeName().getEndUnit().multiplier)); + } else if (sourceType.getSqlTypeName() == SqlTypeName.DECIMAL) { + // Cast from DECIMAL to DECIMAL, may adjust scale and precision. + return Expressions.call( + BuiltInMethod.DECIMAL_DECIMAL_CAST.method, + operand, + Expressions.constant(precision), + Expressions.constant(scale)); + } else if (SqlTypeName.INT_TYPES.contains(sourceType.getSqlTypeName())) { + // Cast from INTEGER to DECIMAL, check for overflow + return Expressions.call( + BuiltInMethod.INTEGER_DECIMAL_CAST.method, + operand, + Expressions.constant(precision), + Expressions.constant(scale)); + } else if (SqlTypeName.APPROX_TYPES.contains(sourceType.getSqlTypeName())) { + // Cast from FLOAT/DOUBLE to DECIMAL + return Expressions.call( + BuiltInMethod.FP_DECIMAL_CAST.method, + operand, + Expressions.constant(precision), + Expressions.constant(scale)); } } return defaultExpression.get(); diff --git a/core/src/main/java/org/apache/calcite/rex/RexBuilder.java b/core/src/main/java/org/apache/calcite/rex/RexBuilder.java index c3d2c8153ce6..4d40f2be0301 100644 --- a/core/src/main/java/org/apache/calcite/rex/RexBuilder.java +++ b/core/src/main/java/org/apache/calcite/rex/RexBuilder.java @@ -1140,6 +1140,12 @@ protected RexLiteral makeLiteral( } o = ((TimestampWithTimeZoneString) o).round(p); break; + case DECIMAL: + if (o != null && type.getScale() != RelDataType.SCALE_NOT_SPECIFIED) { + assert o instanceof BigDecimal; + o = ((BigDecimal) o).setScale(type.getScale(), RoundingMode.DOWN); + } + break; default: break; } diff --git a/core/src/main/java/org/apache/calcite/util/Bug.java b/core/src/main/java/org/apache/calcite/util/Bug.java index 521da4d29d04..989df00fdc88 100644 --- a/core/src/main/java/org/apache/calcite/util/Bug.java +++ b/core/src/main/java/org/apache/calcite/util/Bug.java @@ -226,6 +226,22 @@ public abstract class Bug { * [CALCITE-6294] Support IN filter in Arrow adapter is fixed. */ public static final boolean CALCITE_6294_FIXED = false; + /** Whether + * + * [CALCITE-6295] Support IS NOT NULL in Arrow adapter is fixed. */ + public static final boolean CALCITE_6295_FIXED = false; + + /** Whether + * + * [CALCITE-6296] Support IS NULL in Arrow adapter is fixed. */ + public static final boolean CALCITE_6296_FIXED = false; + + /* Whether + * [CALCITE-6328] + * The BigQuery functions SAFE_* do not match the BigQuery specification + * is fixed. */ + public static final boolean CALCITE_6328_FIXED = false; + /** * Use this to flag temporary code. */ diff --git a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java index bc5ca1d61ab0..57d1f25a1183 100644 --- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java +++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java @@ -301,6 +301,12 @@ public enum BuiltInMethod { ENUMERABLE_TO_LIST(ExtendedEnumerable.class, "toList"), ENUMERABLE_TO_MAP(ExtendedEnumerable.class, "toMap", Function1.class, Function1.class), AS_LIST(Primitive.class, "asList", Object.class), + DECIMAL_DECIMAL_CAST(Primitive.class, "decimalDecimalCast", + BigDecimal.class, int.class, int.class), + INTEGER_DECIMAL_CAST(Primitive.class, "integerDecimalCast", + Number.class, int.class, int.class), + FP_DECIMAL_CAST(Primitive.class, "fpDecimalCast", + Number.class, int.class, int.class), INTEGER_CAST(Primitive.class, "integerCast", Primitive.class, Object.class), MEMORY_GET0(MemoryFactory.Memory.class, "get"), MEMORY_GET1(MemoryFactory.Memory.class, "get", int.class), diff --git a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java index af3e1bea6ac8..811427d809ab 100644 --- a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java +++ b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java @@ -5393,7 +5393,8 @@ private void checkLiteral2(String expression, String expected) { * is greater than maximum numeric scale. */ @Test void testNumericScaleMod() { final String sql = "SELECT MOD(CAST(2 AS DECIMAL(39, 20)), 2)"; - final String expected = "SELECT MOD(2, 2)\nFROM (VALUES (0)) AS \"t\" (\"ZERO\")"; + final String expected = + "SELECT MOD(2.00000000000000000000, 2)\nFROM (VALUES (0)) AS \"t\" (\"ZERO\")"; sql(sql).withPostgresqlModifiedDecimalTypeSystem() .ok(expected); } diff --git a/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java b/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java index a312e1921134..a0b983fdd701 100644 --- a/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java +++ b/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java @@ -3851,7 +3851,7 @@ private SqlSpecialOperatorWithPolicy(String name, SqlKind kind, int prec, boolea checkSimplify(div(a, one), "?0.notNullInt1"); checkSimplify(div(a, nullInt), "null:INTEGER"); - checkSimplifyUnchanged(add(b, half)); + checkSimplify(add(b, half), "?0.notNullDecimal2"); checkSimplify(add(zero, sub(nullInt, nullInt)), "null:INTEGER"); } @@ -3863,5 +3863,4 @@ private SqlSpecialOperatorWithPolicy(String name, SqlKind kind, int prec, boolea RexNode cast = rexBuilder.makeCast(nullableDateType, dateStr); checkSimplify(cast, "2020-10-30"); } - } diff --git a/core/src/test/java/org/apache/calcite/test/InterpreterTest.java b/core/src/test/java/org/apache/calcite/test/InterpreterTest.java index a98a19625b7f..d241b2a1168b 100644 --- a/core/src/test/java/org/apache/calcite/test/InterpreterTest.java +++ b/core/src/test/java/org/apache/calcite/test/InterpreterTest.java @@ -579,7 +579,7 @@ private static void assertRows(Interpreter interpreter, final String sql = "select x, min(y), max(y), sum(y), avg(y)\n" + "from (values ('a', -1.2), ('a', 2.3), ('a', 15)) as t(x, y)\n" + "group by x"; - sql(sql).returnsRows("[a, -1.2, 15.0, 16.1, 5.366666666666667]"); + sql(sql).returnsRows("[a, -1.2, 15.0, 16.1, 5.3]"); } @Test void testInterpretUnnest() { diff --git a/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java b/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java index c7f0815bfd68..2b7aa4b9b940 100644 --- a/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java +++ b/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java @@ -1110,12 +1110,12 @@ private LockWrapper exclusiveCleanDb(Connection c) throws SQLException { + " JdbcTableModify(table=[[foodmart, expense_fact]], " + "operation=[INSERT], flattened=[false])\n" + " JdbcValues(tuples=[[{ 666, 666, 1997-01-01 00:00:00, 666, " - + "'666', 666, 666 }]])\n\n"; + + "'666', 666, 666.0000 }]])\n\n"; final String jdbcSql = "INSERT INTO \"foodmart\".\"expense_fact\" (\"store_id\", " + "\"account_id\", \"exp_date\", \"time_id\", \"category_id\", \"currency_id\", " + "\"amount\")\n" + "VALUES (666, 666, TIMESTAMP '1997-01-01 00:00:00', 666, '666', " - + "666, 666)"; + + "666, 666.0000)"; final AssertThat that = CalciteAssert.model(FoodmartSchema.FOODMART_MODEL) .enable(CalciteAssert.DB == DatabaseInstance.HSQLDB @@ -1143,14 +1143,14 @@ private LockWrapper exclusiveCleanDb(Connection c) throws SQLException { + " JdbcTableModify(table=[[foodmart, expense_fact]], " + "operation=[INSERT], flattened=[false])\n" + " JdbcValues(tuples=[[" - + "{ 666, 666, 1997-01-01 00:00:00, 666, '666', 666, 666 }, " - + "{ 666, 777, 1997-01-01 00:00:00, 666, '666', 666, 666 }]])\n\n"; + + "{ 666, 666, 1997-01-01 00:00:00, 666, '666', 666, 666.0000 }, " + + "{ 666, 777, 1997-01-01 00:00:00, 666, '666', 666, 666.0000 }]])\n\n"; final String jdbcSql = "INSERT INTO \"foodmart\".\"expense_fact\"" + " (\"store_id\", \"account_id\", \"exp_date\", \"time_id\", " + "\"category_id\", \"currency_id\", \"amount\")\n" + "VALUES " - + "(666, 666, TIMESTAMP '1997-01-01 00:00:00', 666, '666', 666, 666),\n" - + "(666, 777, TIMESTAMP '1997-01-01 00:00:00', 666, '666', 666, 666)"; + + "(666, 666, TIMESTAMP '1997-01-01 00:00:00', 666, '666', 666, 666.0000),\n" + + "(666, 777, TIMESTAMP '1997-01-01 00:00:00', 666, '666', 666, 666.0000)"; final AssertThat that = CalciteAssert.model(FoodmartSchema.FOODMART_MODEL) .enable(CalciteAssert.DB == DatabaseInstance.HSQLDB diff --git a/core/src/test/java/org/apache/calcite/test/JdbcTest.java b/core/src/test/java/org/apache/calcite/test/JdbcTest.java index 736d1b478fa5..3a2352b7a5c8 100644 --- a/core/src/test/java/org/apache/calcite/test/JdbcTest.java +++ b/core/src/test/java/org/apache/calcite/test/JdbcTest.java @@ -8349,7 +8349,7 @@ private void checkGetTimestamp(Connection con) throws SQLException { @Test void testIntAndBigDecimalInArray() { CalciteAssert.that() .query("select array[1, 1.1]") - .returns("EXPR$0=[1, 1.1]\n"); + .returns("EXPR$0=[1.0, 1.1]\n"); } /** Test case for diff --git a/core/src/test/resources/org/apache/calcite/test/TypeCoercionConverterTest.xml b/core/src/test/resources/org/apache/calcite/test/TypeCoercionConverterTest.xml index 2d945b6da38f..c88d38118c0c 100644 --- a/core/src/test/resources/org/apache/calcite/test/TypeCoercionConverterTest.xml +++ b/core/src/test/resources/org/apache/calcite/test/TypeCoercionConverterTest.xml @@ -158,11 +158,11 @@ LogicalTableModify(table=[[CATALOG, SALES, T1]], operation=[INSERT], flattened=[ LogicalUnion(all=[false]) LogicalUnion(all=[false]) LogicalUnion(all=[false]) - LogicalValues(tuples=[[{ 'a', 1, 1.0, 0, 0, 0, 0, 2021-11-28 00:00:00, 2021-11-28, X'0a', false }]]) + LogicalValues(tuples=[[{ 'a', 1, 1, 0, 0, 0, 0, 2021-11-28 00:00:00, 2021-11-28, X'0a', false }]]) LogicalValues(tuples=[[{ 'b', 2, 2, 0, 0, 0, 0, 2021-11-28 00:00:00, 2021-11-28, X'0a', false }]]) - LogicalValues(tuples=[[{ 'c', 3, 3.0, 0, 0, 0, 0, 2021-11-28 00:00:00, 2021-11-28, X'0a', false }]]) - LogicalValues(tuples=[[{ 'd', 4, 4.0, 0, 0, 0, 0, 2021-11-28 00:00:00, 2021-11-28, X'0a', false }]]) - LogicalValues(tuples=[[{ 'e', 5, 5.0, 0, 0, 0, 0, 2021-11-28 00:00:00, 2021-11-28, X'0a', false }]]) + LogicalValues(tuples=[[{ 'c', 3, 3, 0, 0, 0, 0, 2021-11-28 00:00:00, 2021-11-28, X'0a', false }]]) + LogicalValues(tuples=[[{ 'd', 4, 4, 0, 0, 0, 0, 2021-11-28 00:00:00, 2021-11-28, X'0a', false }]]) + LogicalValues(tuples=[[{ 'e', 5, 5, 0, 0, 0, 0, 2021-11-28 00:00:00, 2021-11-28, X'0a', false }]]) ]]> @@ -173,7 +173,7 @@ LogicalTableModify(table=[[CATALOG, SALES, T1]], operation=[INSERT], flattened=[ diff --git a/core/src/test/resources/sql/agg.iq b/core/src/test/resources/sql/agg.iq index 8541f46ba5f4..feeaf9035e66 100644 --- a/core/src/test/resources/sql/agg.iq +++ b/core/src/test/resources/sql/agg.iq @@ -1888,11 +1888,11 @@ from "scott".emp; # Previously threw "java.lang.ArithmeticException: Non-terminating decimal # expansion; no exact representable decimal result" select avg(comm) as a, count(comm) as c from "scott".emp where empno < 7844; -+-------------------+---+ -| A | C | -+-------------------+---+ -| 733.3333333333333 | 3 | -+-------------------+---+ ++--------+---+ +| A | C | ++--------+---+ +| 733.33 | 3 | ++--------+---+ (1 row) !ok @@ -2913,10 +2913,10 @@ EnumerableAggregate(group=[{}], REGR_COUNT(COMM, SAL)=[REGR_COUNT($6, $5)], REGR # [CALCITE-1776, CALCITE-2402] REGR_SXX, REGR_SXY, REGR_SYY SELECT - regr_sxx(COMM, SAL) as "REGR_SXX(COMM, SAL)", - regr_syy(COMM, SAL) as "REGR_SYY(COMM, SAL)", - regr_sxx(SAL, COMM) as "REGR_SXX(SAL, COMM)", - regr_syy(SAL, COMM) as "REGR_SYY(SAL, COMM)" + regr_sxx(CAST(COMM AS DECIMAL(12, 4)), CAST(SAL AS DECIMAL(12, 4))) as "REGR_SXX(COMM, SAL)", + regr_syy(CAST(COMM AS DECIMAL(12, 4)), CAST(SAL AS DECIMAL(12, 4))) as "REGR_SYY(COMM, SAL)", + regr_sxx(CAST(SAL AS DECIMAL(12, 4)), CAST(COMM AS DECIMAL(12, 4))) as "REGR_SXX(SAL, COMM)", + regr_syy(CAST(SAL AS DECIMAL(12, 4)), CAST(COMM AS DECIMAL(12, 4))) as "REGR_SYY(SAL, COMM)" from "scott".emp; +---------------------+---------------------+---------------------+---------------------+ | REGR_SXX(COMM, SAL) | REGR_SYY(COMM, SAL) | REGR_SXX(SAL, COMM) | REGR_SYY(SAL, COMM) | @@ -2929,16 +2929,16 @@ from "scott".emp; # [CALCITE-1776, CALCITE-2402] COVAR_POP, COVAR_SAMP, VAR_SAMP, VAR_POP SELECT - covar_pop(COMM, COMM) as "COVAR_POP(COMM, COMM)", - covar_samp(SAL, SAL) as "COVAR_SAMP(SAL, SAL)", - var_pop(COMM) as "VAR_POP(COMM)", - var_samp(SAL) as "VAR_SAMP(SAL)" + covar_pop(CAST(COMM AS DECIMAL(12, 4)), CAST(COMM AS DECIMAL(12, 4))) as "COVAR_POP(COMM, COMM)", + covar_samp(CAST(SAL AS DECIMAL(12, 4)), CAST(SAL AS DECIMAL(12, 4))) as "COVAR_SAMP(SAL, SAL)", + var_pop(CAST(COMM AS DECIMAL(12, 4))) as "VAR_POP(COMM)", + var_samp(CAST(SAL AS DECIMAL(12, 4))) as "VAR_SAMP(SAL)" from "scott".emp; -+-----------------------+----------------------+---------------+-------------------+ -| COVAR_POP(COMM, COMM) | COVAR_SAMP(SAL, SAL) | VAR_POP(COMM) | VAR_SAMP(SAL) | -+-----------------------+----------------------+---------------+-------------------+ -| 272500.0000 | 1398313.873626374 | 272500.0000 | 1398313.873626374 | -+-----------------------+----------------------+---------------+-------------------+ ++-----------------------+----------------------+---------------+---------------+ +| COVAR_POP(COMM, COMM) | COVAR_SAMP(SAL, SAL) | VAR_POP(COMM) | VAR_SAMP(SAL) | ++-----------------------+----------------------+---------------+---------------+ +| 272500.0000 | 1398313.8736 | 272500.0000 | 1398313.8736 | ++-----------------------+----------------------+---------------+---------------+ (1 row) !ok @@ -2970,23 +2970,23 @@ from "scott".emp group by SAL; # [CALCITE-1776, CALCITE-2402] COVAR_POP, COVAR_SAMP, VAR_SAMP, VAR_POP with group by SELECT MONTH(HIREDATE) as "MONTH", - covar_samp(SAL, COMM) as "COVAR_SAMP(SAL, COMM)", - var_pop(COMM) as "VAR_POP(COMM)", - var_samp(SAL) as "VAR_SAMP(SAL)" + covar_samp(CAST(SAL AS DECIMAL(12, 4)), CAST(COMM AS DECIMAL(12, 4))) as "COVAR_SAMP(SAL, COMM)", + var_pop(CAST(COMM AS DECIMAL(12, 4))) as "VAR_POP(COMM)", + var_samp(CAST(SAL AS DECIMAL(12, 4))) as "VAR_SAMP(SAL)" from "scott".emp group by MONTH(HIREDATE); -+-------+-----------------------+---------------+-------------------+ -| MONTH | COVAR_SAMP(SAL, COMM) | VAR_POP(COMM) | VAR_SAMP(SAL) | -+-------+-----------------------+---------------+-------------------+ -| 1 | | | 1201250.0000 | -| 11 | | | | -| 12 | | | 1510833.333333334 | -| 2 | -35000.0000 | 10000.0000 | 831458.333333335 | -| 4 | | | | -| 5 | | | | -| 6 | | | | -| 9 | -175000.0000 | 490000.0000 | 31250.0000 | -+-------+-----------------------+---------------+-------------------+ ++-------+-----------------------+---------------+---------------+ +| MONTH | COVAR_SAMP(SAL, COMM) | VAR_POP(COMM) | VAR_SAMP(SAL) | ++-------+-----------------------+---------------+---------------+ +| 1 | | | 1201250.0000 | +| 11 | | | | +| 12 | | | 1510833.3333 | +| 2 | -35000.0000 | 10000.0000 | 831458.3333 | +| 4 | | | | +| 5 | | | | +| 6 | | | | +| 9 | -175000.0000 | 490000.0000 | 31250.0000 | ++-------+-----------------------+---------------+---------------+ (8 rows) !ok diff --git a/core/src/test/resources/sql/measure-paper.iq b/core/src/test/resources/sql/measure-paper.iq index f74c920d2b7f..59b03be9e52c 100644 --- a/core/src/test/resources/sql/measure-paper.iq +++ b/core/src/test/resources/sql/measure-paper.iq @@ -56,7 +56,7 @@ GROUP BY "prodName"; +----------+---+--------------------+ | prodName | C | profitMargin | +----------+---+--------------------+ -| Acme | 1 | 0.6 | +| Acme | 1 | 0.60 | | Happy | 3 | 0.4705882352941176 | | Whizz | 1 | 0.6666666666666667 | +----------+---+--------------------+ @@ -79,13 +79,13 @@ CREATE VIEW "SummarizedOrders" AS SELECT "prodName", AVG("profitMargin") AS "m" FROM "SummarizedOrders" GROUP BY "prodName"; -+----------+--------------------+ -| prodName | m | -+----------+--------------------+ -| Acme | 0.6 | -| Happy | 0.5039682539682540 | -| Whizz | 0.6666666666666667 | -+----------+--------------------+ ++----------+-----------------+ +| prodName | m | ++----------+-----------------+ +| Acme | 0.6000000000000 | +| Happy | 0.5039682539682 | +| Whizz | 0.6666666666666 | ++----------+-----------------+ (3 rows) !ok @@ -96,7 +96,7 @@ FROM "SummarizedOrders"; +----------+------------+--------------------+ | prodName | orderDate | profitMargin | +----------+------------+--------------------+ -| Acme | 2023-11-27 | 0.6 | +| Acme | 2023-11-27 | 0.60 | | Happy | 2022-11-27 | 0.75 | | Happy | 2023-11-28 | 0.3333333333333333 | | Happy | 2024-11-28 | 0.4285714285714286 | @@ -115,7 +115,7 @@ GROUP BY "prodName", "custName"; +----------+----------+--------------------+ | prodName | custName | profitMargin | +----------+----------+--------------------+ -| Acme | Bob | 0.6 | +| Acme | Bob | 0.60 | | Happy | Alice | 0.3846153846153846 | | Happy | Bob | 0.75 | | Whizz | Celia | 0.6666666666666667 | @@ -133,7 +133,7 @@ GROUP BY "prodName"; +----------+--------------------+ | prodName | profitMargin | +----------+--------------------+ -| Acme | 0.6 | +| Acme | 0.60 | | Happy | 0.4705882352941176 | | Whizz | 0.6666666666666667 | +----------+--------------------+ @@ -150,7 +150,7 @@ GROUP BY "prodName", "orderDate", "custName"; +----------+------------+----------+--------------------+ | prodName | orderDate | custName | profitMargin | +----------+------------+----------+--------------------+ -| Acme | 2023-11-27 | Bob | 0.6 | +| Acme | 2023-11-27 | Bob | 0.60 | | Happy | 2022-11-27 | Bob | 0.75 | | Happy | 2023-11-28 | Alice | 0.3333333333333333 | | Happy | 2024-11-28 | Alice | 0.4285714285714286 | @@ -227,7 +227,7 @@ GROUP BY "prodName"; +----------+--------------------+-------+ | prodName | profitMargin | count | +----------+--------------------+-------+ -| Acme | 0.6 | 1 | +| Acme | 0.60 | 1 | | Happy | 0.4705882352941176 | 3 | | Whizz | 0.6666666666666667 | 1 | +----------+--------------------+-------+ diff --git a/core/src/test/resources/sql/measure.iq b/core/src/test/resources/sql/measure.iq index 0d5ccf190c33..056537d1f719 100644 --- a/core/src/test/resources/sql/measure.iq +++ b/core/src/test/resources/sql/measure.iq @@ -30,15 +30,15 @@ from emp; select job, avg_sal as a from empm group by job; -+-----------+-------------------+ -| JOB | A | -+-----------+-------------------+ -| ANALYST | 3000.00 | -| CLERK | 1037.50 | -| MANAGER | 2758.333333333333 | -| PRESIDENT | 5000.00 | -| SALESMAN | 1400.00 | -+-----------+-------------------+ ++-----------+---------+ +| JOB | A | ++-----------+---------+ +| ANALYST | 3000.00 | +| CLERK | 1037.50 | +| MANAGER | 2758.33 | +| PRESIDENT | 5000.00 | +| SALESMAN | 1400.00 | ++-----------+---------+ (5 rows) !ok @@ -50,15 +50,15 @@ from ( from "scott".emp ) as empm group by job; -+-----------+-------------------+ -| JOB | A | -+-----------+-------------------+ -| ANALYST | 3000.00 | -| CLERK | 1037.50 | -| MANAGER | 2758.333333333333 | -| PRESIDENT | 5000.00 | -| SALESMAN | 1400.00 | -+-----------+-------------------+ ++-----------+---------+ +| JOB | A | ++-----------+---------+ +| ANALYST | 3000.00 | +| CLERK | 1037.50 | +| MANAGER | 2758.33 | +| PRESIDENT | 5000.00 | +| SALESMAN | 1400.00 | ++-----------+---------+ (5 rows) !ok @@ -71,15 +71,15 @@ with empm as ( select job, avg_sal as a from empm group by job; -+-----------+-------------------+ -| JOB | A | -+-----------+-------------------+ -| ANALYST | 3000.00 | -| CLERK | 1037.50 | -| MANAGER | 2758.333333333333 | -| PRESIDENT | 5000.00 | -| SALESMAN | 1400.00 | -+-----------+-------------------+ ++-----------+---------+ +| JOB | A | ++-----------+---------+ +| ANALYST | 3000.00 | +| CLERK | 1037.50 | +| MANAGER | 2758.33 | +| PRESIDENT | 5000.00 | +| SALESMAN | 1400.00 | ++-----------+---------+ (5 rows) !ok @@ -88,15 +88,15 @@ group by job; select job, aggregate(avg_sal) as a from empm group by job; -+-----------+-------------------+ -| JOB | A | -+-----------+-------------------+ -| ANALYST | 3000.00 | -| CLERK | 1037.50 | -| MANAGER | 2758.333333333333 | -| PRESIDENT | 5000.00 | -| SALESMAN | 1400.00 | -+-----------+-------------------+ ++-----------+---------+ +| JOB | A | ++-----------+---------+ +| ANALYST | 3000.00 | +| CLERK | 1037.50 | +| MANAGER | 2758.33 | +| PRESIDENT | 5000.00 | +| SALESMAN | 1400.00 | ++-----------+---------+ (5 rows) !ok @@ -108,15 +108,15 @@ with empm as ( select job, aggregate(avg_sal) as a from empm group by job; -+-----------+-------------------+ -| JOB | A | -+-----------+-------------------+ -| ANALYST | 3000.00 | -| CLERK | 1037.50 | -| MANAGER | 2758.333333333333 | -| PRESIDENT | 5000.00 | -| SALESMAN | 1400.00 | -+-----------+-------------------+ ++-----------+---------+ +| JOB | A | ++-----------+---------+ +| ANALYST | 3000.00 | +| CLERK | 1037.50 | +| MANAGER | 2758.33 | +| PRESIDENT | 5000.00 | +| SALESMAN | 1400.00 | ++-----------+---------+ (5 rows) !ok @@ -125,11 +125,11 @@ group by job; select avg_sal as a from empm group by (); -+-------------------+ -| A | -+-------------------+ -| 2073.214285714286 | -+-------------------+ ++---------+ +| A | ++---------+ +| 2073.21 | ++---------+ (1 row) !ok @@ -137,11 +137,11 @@ group by (); # Same as previous; 'group by ()' is implicit when we use AGGREGATE. select AGGREGATE(avg_sal) as a from empm; -+-------------------+ -| A | -+-------------------+ -| 2073.214285714286 | -+-------------------+ ++---------+ +| A | ++---------+ +| 2073.21 | ++---------+ (1 row) !ok @@ -149,11 +149,11 @@ from empm; # Similar to previous; 'group by ()' is implicit when we use COUNT. select avg_sal as a, COUNT(*) AS c from empm; -+-------------------+----+ -| A | C | -+-------------------+----+ -| 2073.214285714286 | 14 | -+-------------------+----+ ++---------+----+ +| A | C | ++---------+----+ +| 2073.21 | 14 | ++---------+----+ (1 row) !ok @@ -468,13 +468,13 @@ select deptno, avg(sal) filter (where job in ('ANALYST', 'SALESMAN')) as avg_sal1 from "scott".emp group by deptno; -+--------+---+-------------------+----+----------+ -| DEPTNO | C | AVG_SAL | C1 | AVG_SAL1 | -+--------+---+-------------------+----+----------+ -| 10 | 3 | 2916.666666666667 | 0 | | -| 20 | 5 | 2175.00 | 2 | 3000.00 | -| 30 | 6 | 1566.666666666667 | 4 | 1400.00 | -+--------+---+-------------------+----+----------+ ++--------+---+---------+----+----------+ +| DEPTNO | C | AVG_SAL | C1 | AVG_SAL1 | ++--------+---+---------+----+----------+ +| 10 | 3 | 2916.66 | 0 | | +| 20 | 5 | 2175.00 | 2 | 3000.00 | +| 30 | 6 | 1566.66 | 4 | 1400.00 | ++--------+---+---------+----+----------+ (3 rows) !ok @@ -519,13 +519,13 @@ from ( where job <> 'PRESIDENT') where deptno < 25 group by job; -+---------+---+-------------------+----+----------+ -| JOB | C | AVG_SAL | C2 | AVG_SAL2 | -+---------+---+-------------------+----+----------+ -| ANALYST | 2 | 3000.00 | 2 | 3000.00 | -| CLERK | 4 | 1037.50 | 2 | 950.00 | -| MANAGER | 3 | 2758.333333333333 | 1 | 2975.00 | -+---------+---+-------------------+----+----------+ ++---------+---+---------+----+----------+ +| JOB | C | AVG_SAL | C2 | AVG_SAL2 | ++---------+---+---------+----+----------+ +| ANALYST | 2 | 3000.00 | 2 | 3000.00 | +| CLERK | 4 | 1037.50 | 2 | 950.00 | +| MANAGER | 3 | 2758.33 | 1 | 2975.00 | ++---------+---+---------+----+----------+ (3 rows) !ok diff --git a/core/src/test/resources/sql/misc.iq b/core/src/test/resources/sql/misc.iq index 235581d38863..224d6a1d13e3 100644 --- a/core/src/test/resources/sql/misc.iq +++ b/core/src/test/resources/sql/misc.iq @@ -2439,13 +2439,13 @@ FROM (VALUES (0, 2, 4, 8), (1, 2, 4, 8), (CAST(null as int), CAST(null as int), CAST(null as int), CAST(null as int))) AS T(A,B,C,D); V -13.0 -9.5 -1.75 -1.875 +13.00000000 +9.50000000 +1.75000000 +1.87500000 null -0 -14 +0E-8 +14.00000000 !ok # TIMESTAMP literals without a time part are OK. diff --git a/core/src/test/resources/sql/sub-query.iq b/core/src/test/resources/sql/sub-query.iq index e65eaf0a848d..2201dea8def9 100644 --- a/core/src/test/resources/sql/sub-query.iq +++ b/core/src/test/resources/sql/sub-query.iq @@ -2847,7 +2847,7 @@ EnumerableCalc(expr#0..1=[{inputs}], expr#2=[IS NULL($t1)], DEPTNO=[$t0], $condi EnumerableAggregate(group=[{0}]) EnumerableCalc(expr#0..2=[{inputs}], expr#3=[true], expr#4=[1], expr#5=[>($t2, $t4)], i=[$t3], $condition=[$t5]) EnumerableAggregate(group=[{5, 7}], c=[COUNT()]) - EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t5):DECIMAL(12, 2)], expr#9=[3000:DECIMAL(12, 2)], expr#10=[=($t8, $t9)], expr#11=[IS NOT NULL($t7)], expr#12=[AND($t10, $t11)], proj#0..7=[{exprs}], $condition=[$t12]) + EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t5):DECIMAL(12, 2)], expr#9=[3000.00:DECIMAL(12, 2)], expr#10=[=($t8, $t9)], expr#11=[IS NOT NULL($t7)], expr#12=[AND($t10, $t11)], proj#0..7=[{exprs}], $condition=[$t12]) EnumerableTableScan(table=[[scott, EMP]]) !plan @@ -2873,7 +2873,7 @@ EnumerableCalc(expr#0..1=[{inputs}], expr#2=[IS NULL($t1)], DEPTNO=[$t0], U=[$t2 EnumerableAggregate(group=[{0}]) EnumerableCalc(expr#0..2=[{inputs}], expr#3=[true], expr#4=[1], expr#5=[>($t2, $t4)], i=[$t3], $condition=[$t5]) EnumerableAggregate(group=[{5, 7}], c=[COUNT()]) - EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t5):DECIMAL(12, 2)], expr#9=[3000:DECIMAL(12, 2)], expr#10=[=($t8, $t9)], expr#11=[IS NOT NULL($t7)], expr#12=[AND($t10, $t11)], proj#0..7=[{exprs}], $condition=[$t12]) + EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t5):DECIMAL(12, 2)], expr#9=[3000.00:DECIMAL(12, 2)], expr#10=[=($t8, $t9)], expr#11=[IS NOT NULL($t7)], expr#12=[AND($t10, $t11)], proj#0..7=[{exprs}], $condition=[$t12]) EnumerableTableScan(table=[[scott, EMP]]) !plan @@ -2899,7 +2899,7 @@ EnumerableCalc(expr#0..1=[{inputs}], expr#2=[IS NOT NULL($t1)], DEPTNO=[$t0], U= EnumerableAggregate(group=[{0}]) EnumerableCalc(expr#0..2=[{inputs}], expr#3=[true], expr#4=[1], expr#5=[>($t2, $t4)], i=[$t3], $condition=[$t5]) EnumerableAggregate(group=[{5, 7}], c=[COUNT()]) - EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t5):DECIMAL(12, 2)], expr#9=[3000:DECIMAL(12, 2)], expr#10=[=($t8, $t9)], expr#11=[IS NOT NULL($t7)], expr#12=[AND($t10, $t11)], proj#0..7=[{exprs}], $condition=[$t12]) + EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t5):DECIMAL(12, 2)], expr#9=[3000.00:DECIMAL(12, 2)], expr#10=[=($t8, $t9)], expr#11=[IS NOT NULL($t7)], expr#12=[AND($t10, $t11)], proj#0..7=[{exprs}], $condition=[$t12]) EnumerableTableScan(table=[[scott, EMP]]) !plan @@ -3147,7 +3147,7 @@ select * from "scott".emp where comm in (300, 500, null); !ok -EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t6):DECIMAL(12, 2)], expr#9=[Sarg[300:DECIMAL(12, 2), 500:DECIMAL(12, 2)]:DECIMAL(12, 2)], expr#10=[SEARCH($t8, $t9)], proj#0..7=[{exprs}], $condition=[$t10]) +EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t6):DECIMAL(12, 2)], expr#9=[Sarg[300.00:DECIMAL(12, 2), 500.00:DECIMAL(12, 2)]:DECIMAL(12, 2)], expr#10=[SEARCH($t8, $t9)], proj#0..7=[{exprs}], $condition=[$t10]) EnumerableTableScan(table=[[scott, EMP]]) !plan @@ -3175,7 +3175,7 @@ select *, comm in (300, 500, null) as i from "scott".emp; !ok -EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t6):DECIMAL(12, 2)], expr#9=[Sarg[300:DECIMAL(12, 2), 500:DECIMAL(12, 2)]:DECIMAL(12, 2)], expr#10=[SEARCH($t8, $t9)], expr#11=[null:BOOLEAN], expr#12=[OR($t10, $t11)], proj#0..7=[{exprs}], I=[$t12]) +EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t6):DECIMAL(12, 2)], expr#9=[Sarg[300.00:DECIMAL(12, 2), 500.00:DECIMAL(12, 2)]:DECIMAL(12, 2)], expr#10=[SEARCH($t8, $t9)], expr#11=[null:BOOLEAN], expr#12=[OR($t10, $t11)], proj#0..7=[{exprs}], I=[$t12]) EnumerableTableScan(table=[[scott, EMP]]) !plan @@ -3216,7 +3216,7 @@ select *, comm not in (300, 500, null) as i from "scott".emp; !ok -EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t6):DECIMAL(12, 2)], expr#9=[Sarg[(-∞..300:DECIMAL(12, 2)), (300:DECIMAL(12, 2)..500:DECIMAL(12, 2)), (500:DECIMAL(12, 2)..+∞)]:DECIMAL(12, 2)], expr#10=[SEARCH($t8, $t9)], expr#11=[null:BOOLEAN], expr#12=[AND($t10, $t11)], proj#0..7=[{exprs}], I=[$t12]) +EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t6):DECIMAL(12, 2)], expr#9=[Sarg[(-∞..300.00:DECIMAL(12, 2)), (300.00:DECIMAL(12, 2)..500.00:DECIMAL(12, 2)), (500.00:DECIMAL(12, 2)..+∞)]:DECIMAL(12, 2)], expr#10=[SEARCH($t8, $t9)], expr#11=[null:BOOLEAN], expr#12=[AND($t10, $t11)], proj#0..7=[{exprs}], I=[$t12]) EnumerableTableScan(table=[[scott, EMP]]) !plan @@ -3243,7 +3243,7 @@ select *, (comm <> 300 and comm <> 500 and comm <> null) as i from "scott".emp; (14 rows) !ok -EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t6):DECIMAL(12, 2)], expr#9=[Sarg[(-∞..300:DECIMAL(12, 2)), (300:DECIMAL(12, 2)..500:DECIMAL(12, 2)), (500:DECIMAL(12, 2)..+∞)]:DECIMAL(12, 2)], expr#10=[SEARCH($t8, $t9)], expr#11=[null:BOOLEAN], expr#12=[AND($t10, $t11)], proj#0..7=[{exprs}], I=[$t12]) +EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t6):DECIMAL(12, 2)], expr#9=[Sarg[(-∞..300.00:DECIMAL(12, 2)), (300.00:DECIMAL(12, 2)..500.00:DECIMAL(12, 2)), (500.00:DECIMAL(12, 2)..+∞)]:DECIMAL(12, 2)], expr#10=[SEARCH($t8, $t9)], expr#11=[null:BOOLEAN], expr#12=[AND($t10, $t11)], proj#0..7=[{exprs}], I=[$t12]) EnumerableTableScan(table=[[scott, EMP]]) !plan diff --git a/core/src/test/resources/sql/winagg.iq b/core/src/test/resources/sql/winagg.iq index 963c38eb6746..ddd6dfaae1f5 100644 --- a/core/src/test/resources/sql/winagg.iq +++ b/core/src/test/resources/sql/winagg.iq @@ -80,41 +80,41 @@ from emp; # STDDEV applied to nullable column select empno, - stddev(comm) over (order by empno rows unbounded preceding) as stdev + stddev(CAST(comm AS DECIMAL(12, 4))) over (order by empno rows unbounded preceding) as stdev from emp where deptno = 30 order by 1; -+-------+-------------------------------------------------+ -| EMPNO | STDEV | -+-------+-------------------------------------------------+ -| 7499 | | -| 7521 | 141.421356237309510106570087373256683349609375 | -| 7654 | 585.9465277082316561063635163009166717529296875 | -| 7698 | 585.9465277082316561063635163009166717529296875 | -| 7844 | 602.7713773341707792496890760958194732666015625 | -| 7900 | 602.7713773341707792496890760958194732666015625 | -+-------+-------------------------------------------------+ ++-------+----------+ +| EMPNO | STDEV | ++-------+----------+ +| 7499 | | +| 7521 | 141.4213 | +| 7654 | 585.9465 | +| 7698 | 585.9465 | +| 7844 | 602.7713 | +| 7900 | 602.7713 | ++-------+----------+ (6 rows) !ok # [CALCITE-5931] Allow integers like 1.00 in window frame select empno, - stddev(comm) over (order by empno rows 2 preceding) as stdev_2int, - stddev(comm) over (order by empno rows 2.00 preceding) as stdev_2double + stddev(CAST(comm AS DECIMAL(12, 4))) over (order by empno rows 2 preceding) as stdev_2int, + stddev(CAST(comm AS DECIMAL(12, 4))) over (order by empno rows 2.00 preceding) as stdev_2double from emp where deptno = 30 order by 1; -+-------+-------------------------------------------------+-------------------------------------------------+ -| EMPNO | STDEV_2INT | STDEV_2DOUBLE | -+-------+-------------------------------------------------+-------------------------------------------------+ -| 7499 | | | -| 7521 | 141.421356237309510106570087373256683349609375 | 141.421356237309510106570087373256683349609375 | -| 7654 | 585.9465277082316561063635163009166717529296875 | 585.9465277082316561063635163009166717529296875 | -| 7698 | 636.3961030678927954795653931796550750732421875 | 636.3961030678927954795653931796550750732421875 | -| 7844 | 989.949493661166570745990611612796783447265625 | 989.949493661166570745990611612796783447265625 | -| 7900 | | | -+-------+-------------------------------------------------+-------------------------------------------------+ ++-------+------------+---------------+ +| EMPNO | STDEV_2INT | STDEV_2DOUBLE | ++-------+------------+---------------+ +| 7499 | | | +| 7521 | 141.4213 | 141.4213 | +| 7654 | 585.9465 | 585.9465 | +| 7698 | 636.3961 | 636.3961 | +| 7844 | 989.9494 | 989.9494 | +| 7900 | | | ++-------+------------+---------------+ (6 rows) !ok @@ -883,24 +883,24 @@ select empno, sum(sal) over (order by empno rows between unbounded preceding and unbounded following) as e5 from emp order by 1; -+-------+-------------------------------------------------+----+----------+----------+----------+ -| EMPNO | E1 | E2 | E3 | E4 | E5 | -+-------+-------------------------------------------------+----+----------+----------+----------+ -| 7369 | 585.9465277082316561063635163009166717529296875 | 5 | 29025.00 | 29025.00 | 29025.00 | -| 7499 | 636.3961030678927954795653931796550750732421875 | 6 | 29025.00 | 29025.00 | 29025.00 | -| 7521 | 777.8174593052023055861354805529117584228515625 | 7 | 29025.00 | 29025.00 | 29025.00 | -| 7566 | 585.9465277082316561063635163009166717529296875 | 7 | 28225.00 | 29025.00 | 29025.00 | -| 7654 | 353.5533905932737752664252184331417083740234375 | 7 | 26625.00 | 29025.00 | 29025.00 | -| 7698 | 989.949493661166570745990611612796783447265625 | 7 | 25375.00 | 29025.00 | 29025.00 | -| 7782 | 989.949493661166570745990611612796783447265625 | 7 | 22400.00 | 29025.00 | 29025.00 | -| 7788 | | 7 | 21150.00 | 29025.00 | 29025.00 | -| 7839 | | 7 | 18300.00 | 29025.00 | 29025.00 | -| 7844 | | 6 | 15850.00 | 29025.00 | 29025.00 | -| 7876 | | 5 | 12850.00 | 29025.00 | 29025.00 | -| 7900 | | 4 | 7850.00 | 29025.00 | 29025.00 | -| 7902 | | 3 | 6350.00 | 29025.00 | 29025.00 | -| 7934 | | 2 | 5250.00 | 29025.00 | 29025.00 | -+-------+-------------------------------------------------+----+----------+----------+----------+ ++-------+--------+----+----------+----------+----------+ +| EMPNO | E1 | E2 | E3 | E4 | E5 | ++-------+--------+----+----------+----------+----------+ +| 7369 | 585.94 | 5 | 29025.00 | 29025.00 | 29025.00 | +| 7499 | 636.39 | 6 | 29025.00 | 29025.00 | 29025.00 | +| 7521 | 777.81 | 7 | 29025.00 | 29025.00 | 29025.00 | +| 7566 | 585.94 | 7 | 28225.00 | 29025.00 | 29025.00 | +| 7654 | 353.55 | 7 | 26625.00 | 29025.00 | 29025.00 | +| 7698 | 989.94 | 7 | 25375.00 | 29025.00 | 29025.00 | +| 7782 | 989.94 | 7 | 22400.00 | 29025.00 | 29025.00 | +| 7788 | | 7 | 21150.00 | 29025.00 | 29025.00 | +| 7839 | | 7 | 18300.00 | 29025.00 | 29025.00 | +| 7844 | | 6 | 15850.00 | 29025.00 | 29025.00 | +| 7876 | | 5 | 12850.00 | 29025.00 | 29025.00 | +| 7900 | | 4 | 7850.00 | 29025.00 | 29025.00 | +| 7902 | | 3 | 6350.00 | 29025.00 | 29025.00 | +| 7934 | | 2 | 5250.00 | 29025.00 | 29025.00 | ++-------+--------+----+----------+----------+----------+ (14 rows) !ok diff --git a/core/src/test/resources/sql/within-distinct.iq b/core/src/test/resources/sql/within-distinct.iq index ea8c5ec554f1..63264060be4a 100644 --- a/core/src/test/resources/sql/within-distinct.iq +++ b/core/src/test/resources/sql/within-distinct.iq @@ -304,18 +304,18 @@ ORDER BY 1, 2; !} SELECT deptno, - avg(sal) AS avg_sal, - avg(sal) WITHIN DISTINCT (job) AS avg_job_sal + avg(CAST(sal AS DECIMAL(10, 2))) AS avg_sal, + avg(CAST(sal AS DECIMAL(10, 2))) WITHIN DISTINCT (job) AS avg_job_sal from emp3 group by deptno order by deptno; -+--------+---------+-------------------+ -| DEPTNO | AVG_SAL | AVG_JOB_SAL | -+--------+---------+-------------------+ -| 10 | 2750.00 | 2750.00 | -| 20 | 2010.00 | 2083.333333333333 | -| 30 | 1375.00 | 1500.00 | -+--------+---------+-------------------+ ++--------+---------+-------------+ +| DEPTNO | AVG_SAL | AVG_JOB_SAL | ++--------+---------+-------------+ +| 10 | 2750.00 | 2750.00 | +| 20 | 2010.00 | 2083.33 | +| 30 | 1375.00 | 1500.00 | ++--------+---------+-------------+ (3 rows) !ok @@ -344,17 +344,18 @@ select * from job_salary order by job; # Query on the normalized (emp, job_salary) tables give same result as the query on the # denormalized emp table. Of course. -select e.deptno, avg(j.sal) as avg_sal, avg(j.sal) within distinct (j.job) as avg_job_sal +select e.deptno, avg(CAST(j.sal AS DECIMAL(10, 2))) as avg_sal, + avg(CAST(j.sal AS DECIMAL(10, 2))) within distinct (j.job) as avg_job_sal from emp as e join job_salary as j on e.job = j.job group by deptno order by deptno; -+--------+---------+-------------------+ -| DEPTNO | AVG_SAL | AVG_JOB_SAL | -+--------+---------+-------------------+ -| 10 | 2750.00 | 2750.00 | -| 20 | 2010.00 | 2083.333333333333 | -| 30 | 1375.00 | 1500.00 | -+--------+---------+-------------------+ ++--------+---------+-------------+ +| DEPTNO | AVG_SAL | AVG_JOB_SAL | ++--------+---------+-------------+ +| 10 | 2750.00 | 2750.00 | +| 20 | 2010.00 | 2083.33 | +| 30 | 1375.00 | 1500.00 | ++--------+---------+-------------+ (3 rows) !ok @@ -428,9 +429,9 @@ select * from orders; +----------+-------------+---------+----------+ | ORDER_ID | CUSTOMER_ID | PAYMENT | SHIPPING | +----------+-------------+---------+----------+ -| 1 | 100 | cash | 10 | -| 2 | 100 | visa | 20 | -| 3 | 101 | cash | 12 | +| 1 | 100 | cash | 10.00 | +| 2 | 100 | visa | 20.00 | +| 3 | 101 | cash | 12.00 | +----------+-------------+---------+----------+ (3 rows) @@ -445,12 +446,12 @@ order by order_id, product, units; +-------------+----------+---------+----------+---------+-------+-------+-----+-------+ | CUSTOMER_ID | ORDER_ID | PAYMENT | SHIPPING | PRODUCT | UNITS | NAME | AGE | STATE | +-------------+----------+---------+----------+---------+-------+-------+-----+-------+ -| 100 | 1 | cash | 10 | apple | 3 | Fred | 25 | CA | -| 100 | 1 | cash | 10 | orange | 1 | Fred | 25 | CA | -| 100 | 2 | visa | 20 | banana | 2 | Fred | 25 | CA | -| 100 | 2 | visa | 20 | banana | 6 | Fred | 25 | CA | -| 100 | 2 | visa | 20 | orange | 5 | Fred | 25 | CA | -| 101 | 3 | cash | 12 | mango | 7 | Velma | 17 | NV | +| 100 | 1 | cash | 10.00 | apple | 3 | Fred | 25 | CA | +| 100 | 1 | cash | 10.00 | orange | 1 | Fred | 25 | CA | +| 100 | 2 | visa | 20.00 | banana | 2 | Fred | 25 | CA | +| 100 | 2 | visa | 20.00 | banana | 6 | Fred | 25 | CA | +| 100 | 2 | visa | 20.00 | orange | 5 | Fred | 25 | CA | +| 101 | 3 | cash | 12.00 | mango | 7 | Velma | 17 | NV | +-------------+----------+---------+----------+---------+-------+-------+-----+-------+ (6 rows) @@ -466,7 +467,7 @@ join order_items using (order_id); +-------+--------------+-----------+ | count | sum_shipping | sum_units | +-------+--------------+-----------+ -| 6 | 92 | 24 | +| 6 | 92.00 | 24 | +-------+--------------+-----------+ (1 row) @@ -486,10 +487,10 @@ order by product; +---------+-------+--------------+-----------+ | PRODUCT | count | sum_shipping | sum_units | +---------+-------+--------------+-----------+ -| apple | 1 | 10 | 3 | -| banana | 2 | 40 | 8 | -| mango | 1 | 12 | 7 | -| orange | 2 | 30 | 6 | +| apple | 1 | 10.00 | 3 | +| banana | 2 | 40.00 | 8 | +| mango | 1 | 12.00 | 7 | +| orange | 2 | 30.00 | 6 | +---------+-------+--------------+-----------+ (4 rows) @@ -507,10 +508,10 @@ order by product; +---------+-------+--------------+-----------+ | PRODUCT | count | sum_shipping | sum_units | +---------+-------+--------------+-----------+ -| apple | 1 | 10 | 3 | -| banana | 2 | 20 | 8 | -| mango | 1 | 12 | 7 | -| orange | 2 | 30 | 6 | +| apple | 1 | 10.00 | 3 | +| banana | 2 | 20.00 | 8 | +| mango | 1 | 12.00 | 7 | +| orange | 2 | 30.00 | 6 | +---------+-------+--------------+-----------+ (4 rows) @@ -535,10 +536,10 @@ order by product; +---------+-------+--------------+-----------+ | PRODUCT | count | sum_shipping | sum_units | +---------+-------+--------------+-----------+ -| apple | 1 | 10 | 3 | -| banana | 2 | 20 | 8 | -| mango | 1 | 12 | 7 | -| orange | 2 | 30 | 6 | +| apple | 1 | 10.00 | 3 | +| banana | 2 | 20.00 | 8 | +| mango | 1 | 12.00 | 7 | +| orange | 2 | 30.00 | 6 | +---------+-------+--------------+-----------+ (4 rows) @@ -558,8 +559,8 @@ order by payment; +---------+-------+-------------+--------------+-----------+ | PAYMENT | count | order_count | sum_shipping | sum_units | +---------+-------+-------------+--------------+-----------+ -| cash | 3 | 2 | 32 | 11 | -| visa | 3 | 1 | 60 | 13 | +| cash | 3 | 2 | 32.00 | 11 | +| visa | 3 | 1 | 60.00 | 13 | +---------+-------+-------------+--------------+-----------+ (2 rows) @@ -606,8 +607,8 @@ group by payment; +---------+-------+-------------+--------------+-----------+ | PAYMENT | count | order_count | sum_shipping | sum_units | +---------+-------+-------------+--------------+-----------+ -| cash | 3 | 2 | 22 | 11 | -| visa | 2 | 1 | 20 | 13 | +| cash | 3 | 2 | 22.00 | 11 | +| visa | 2 | 1 | 20.00 | 13 | +---------+-------+-------------+--------------+-----------+ (2 rows) @@ -639,8 +640,8 @@ group by payment; +---------+-------+-------------+--------------+-----------+ | PAYMENT | count | order_count | sum_shipping | sum_units | +---------+-------+-------------+--------------+-----------+ -| cash | 3 | 2 | 22 | 11 | -| visa | 2 | 1 | 20 | 13 | +| cash | 3 | 2 | 22.00 | 11 | +| visa | 2 | 1 | 20.00 | 13 | +---------+-------+-------------+--------------+-----------+ (2 rows) @@ -691,8 +692,8 @@ group by payment; +---------+-------+-------------+--------------+-----------+ | PAYMENT | count | order_count | sum_shipping | sum_units | +---------+-------+-------------+--------------+-----------+ -| cash | 3 | 2 | 22 | 11 | -| visa | 2 | 1 | 20 | 13 | +| cash | 3 | 2 | 22.00 | 11 | +| visa | 2 | 1 | 20.00 | 13 | +---------+-------+-------------+--------------+-----------+ (2 rows) @@ -743,10 +744,10 @@ order by product; +---------+-------+-------------+--------------+-----------+ | PRODUCT | count | order_count | sum_shipping | sum_units | +---------+-------+-------------+--------------+-----------+ -| apple | 1 | 1 | 10 | 3 | -| banana | 2 | 1 | 20 | 8 | -| mango | 1 | 1 | 12 | 7 | -| orange | 2 | 2 | 30 | 6 | +| apple | 1 | 1 | 10.00 | 3 | +| banana | 2 | 1 | 20.00 | 8 | +| mango | 1 | 1 | 12.00 | 7 | +| orange | 2 | 2 | 30.00 | 6 | +---------+-------+-------------+--------------+-----------+ (4 rows) @@ -792,8 +793,8 @@ order by o.payment; +---------+----------------+-------------+------------------+---------+--------------+-----------+ | PAYMENT | customer_count | order_count | order_item_count | sum_age | sum_shipping | sum_units | +---------+----------------+-------------+------------------+---------+--------------+-----------+ -| cash | 2 | 2 | 3 | 67 | 32 | 11 | -| visa | 1 | 1 | 3 | 75 | 60 | 13 | +| cash | 2 | 2 | 3 | 67 | 32.00 | 11 | +| visa | 1 | 1 | 3 | 75 | 60.00 | 13 | +---------+----------------+-------------+------------------+---------+--------------+-----------+ (2 rows) diff --git a/druid/src/test/java/org/apache/calcite/test/DruidAdapter2IT.java b/druid/src/test/java/org/apache/calcite/test/DruidAdapter2IT.java index 7bf53579dbca..8c522b06a0bf 100644 --- a/druid/src/test/java/org/apache/calcite/test/DruidAdapter2IT.java +++ b/druid/src/test/java/org/apache/calcite/test/DruidAdapter2IT.java @@ -1909,10 +1909,10 @@ private void checkGroupBySingleSortLimit(boolean approx) { + "end as b from \"foodmart\" group by \"store_state\" order by a desc"; final String postAggString = "'postAggregations':[{'type':'expression','name':'A'," + "'expression':'(\\'$f1\\' / \\'$f2\\')'},{'type':'expression','name':'B'," - + "'expression':'case_searched((\\'$f3\\' == 0),1.0,CAST(\\'$f3\\'"; + + "'expression':'case_searched((\\'$f3\\' == 0),1,CAST(\\'$f3\\'"; final String plan = "PLAN=" + "EnumerableInterpreter\n" - + " DruidQuery(table=[[foodmart, foodmart]], intervals=[[1900-01-09T00:00:00.000Z/2992-01-10T00:00:00.000Z]], projects=[[$63, $90, $91, $89]], groups=[{0}], aggs=[[SUM($1), SUM($2), SUM($3)]], post_projects=[[$0, /($1, $2), CASE(=($3, 0), 1.0:DECIMAL(19, 0), CAST($3):DECIMAL(19, 0))]], sort0=[1], dir0=[DESC])\n"; + + " DruidQuery(table=[[foodmart, foodmart]], intervals=[[1900-01-09T00:00:00.000Z/2992-01-10T00:00:00.000Z]], projects=[[$63, $90, $91, $89]], groups=[{0}], aggs=[[SUM($1), SUM($2), SUM($3)]], post_projects=[[$0, /($1, $2), CASE(=($3, 0), 1:DECIMAL(19, 0), CAST($3):DECIMAL(19, 0))]], sort0=[1], dir0=[DESC])\n"; CalciteAssert.AssertQuery q = sql(sqlQuery) .explainContains(plan) .queryContains(new DruidChecker(postAggString)); @@ -3285,8 +3285,8 @@ private void testCountWithApproxDistinct(boolean approx, String sql, sql(sql).runs().queryContains( new DruidChecker( false, - "\"filter\":{\"type\":\"bound\",\"dimension\":\"product_id\",\"lower\":\"16.0\"," - + "\"lowerStrict\":false,\"upper\":\"16.0\"," + "\"filter\":{\"type\":\"bound\",\"dimension\":\"product_id\"," + + "\"lower\":\"16.000000000\",\"lowerStrict\":false,\"upper\":\"16.000000000\"," + "\"upperStrict\":false,\"ordering\":\"numeric\"}")); } diff --git a/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java b/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java index b3d62632c075..200c93efe598 100644 --- a/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java +++ b/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java @@ -2215,12 +2215,12 @@ private void checkGroupBySingleSortLimit(boolean approx) { + "from \"foodmart\" group by \"store_state\" order by a desc"; final String postAggString = "'postAggregations':[{'type':'expression','name':'A'," + "'expression':'(\\'$f1\\' / \\'$f2\\')'},{'type':'expression','name':'B'," - + "'expression':'case_searched((\\'$f3\\' == 0),1.0,CAST(\\'$f3\\'"; + + "'expression':'case_searched((\\'$f3\\' == 0),1,CAST(\\'$f3\\'"; final String plan = "DruidQuery(table=[[foodmart, foodmart]], intervals=[[1900-01-09T00:00:00.000Z/" + "2992-01-10T00:00:00.000Z]], projects=[[$63, $90, $91, $89]], groups=[{0}], " + "aggs=[[SUM($1), SUM($2), SUM($3)]], post_projects=[[$0, /($1, $2), " - + "CASE(=($3, 0), 1.0:DECIMAL(19, 0), CAST($3):DECIMAL(19, 0))]], sort0=[1], dir0=[DESC])"; + + "CASE(=($3, 0), 1:DECIMAL(19, 0), CAST($3):DECIMAL(19, 0))]], sort0=[1], dir0=[DESC])"; CalciteAssert.AssertQuery q = sql(sqlQuery, FOODMART) .explainContains(plan) .queryContains(new DruidChecker(postAggString)); @@ -3942,8 +3942,8 @@ private void testCountWithApproxDistinct(boolean approx, String sql, String expe sql(sql, FOODMART).runs().queryContains( new DruidChecker( false, - "\"filter\":{\"type\":\"bound\",\"dimension\":\"product_id\",\"lower\":\"16.0\"," - + "\"lowerStrict\":false,\"upper\":\"16.0\"," + "\"filter\":{\"type\":\"bound\",\"dimension\":\"product_id\"," + + "\"lower\":\"16.000000000\",\"lowerStrict\":false,\"upper\":\"16.000000000\"," + "\"upperStrict\":false,\"ordering\":\"numeric\"}")); } diff --git a/innodb/src/test/java/org/apache/calcite/adapter/innodb/InnodbAdapterTest.java b/innodb/src/test/java/org/apache/calcite/adapter/innodb/InnodbAdapterTest.java index f3a889c1229e..61de692755b2 100644 --- a/innodb/src/test/java/org/apache/calcite/adapter/innodb/InnodbAdapterTest.java +++ b/innodb/src/test/java/org/apache/calcite/adapter/innodb/InnodbAdapterTest.java @@ -913,7 +913,7 @@ public class InnodbAdapterTest { sql("SELECT * FROM \"EMP\" WHERE DEPTNO = 30 AND SAL = 1250 AND COMM = 500.00") .explainContains("PLAN=InnodbToEnumerableConverter\n" + " InnodbFilter(condition=[(SK_POINT_QUERY, index=DEPTNO_SAL_COMM_KEY, " - + "DEPTNO=30,SAL=1250,COMM=500.00)])\n" + + "DEPTNO=30,SAL=1250.00,COMM=500.00)])\n" + " InnodbTableScan(table=[[test, EMP]])\n") .returns(some(7521)); } @@ -923,7 +923,7 @@ public class InnodbAdapterTest { .explainContains("PLAN=InnodbToEnumerableConverter\n" + " InnodbProject(EMPNO=[$0], ENAME=[$1])\n" + " InnodbFilter(condition=[(SK_POINT_QUERY, index=DEPTNO_SAL_COMM_KEY, " - + "DEPTNO=30,SAL=1250,COMM=500.00)])\n" + + "DEPTNO=30,SAL=1250.00,COMM=500.00)])\n" + " InnodbTableScan(table=[[test, EMP]])") .returns("EMPNO=7521; ENAME=WARD\n"); } diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/Primitive.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/Primitive.java index 94578647e303..71e7d5aae18d 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/Primitive.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/Primitive.java @@ -384,6 +384,7 @@ static void checkRoundedRange(Number value, double min, double max) { } } + /** Called from BuiltInMethod.INTEGER_CAST */ public static @Nullable Object integerCast(Primitive primitive, final Object value) { return requireNonNull(primitive, "primitive").numberValue((Number) value); } @@ -447,6 +448,35 @@ static BigDecimal checkOverflow(BigDecimal value, int precision, int scale) { return checkOverflow(result, precision, scale); } + /** Called from BuiltInMethod.DECIMAL_DECIMAL_CAST */ + public static @Nullable Object decimalDecimalCast( + @Nullable BigDecimal value, int precision, int scale) { + if (value == null) { + return null; + } + return checkOverflow(value, precision, scale); + } + + /** Called from BuiltInMethod.INTEGER_DECIMAL_CAST */ + public static @Nullable Object integerDecimalCast( + @Nullable Number value, int precision, int scale) { + if (value == null) { + return null; + } + final BigDecimal decimal = new BigDecimal(value.longValue()); + return checkOverflow(decimal, precision, scale); + } + + /** Called from BuiltInMethod.FP_DECIMAL_CAST */ + public static @Nullable Object fpDecimalCast( + @Nullable Number value, int precision, int scale) { + if (value == null) { + return null; + } + final BigDecimal decimal = BigDecimal.valueOf(value.doubleValue()); + return checkOverflow(decimal, precision, scale); + } + /** * Converts a number into a value of the type specified by this primitive * using the SQL CAST rules. If the value conversion causes loss of significant digits, diff --git a/site/_docs/history.md b/site/_docs/history.md index d2ae580fdbe5..b9440ae2c525 100644 --- a/site/_docs/history.md +++ b/site/_docs/history.md @@ -43,6 +43,11 @@ z. #### Breaking Changes {: #breaking-1-38-0} +In previous versions of Calcite the casts to DECIMAL types were +treated as no-ops [CALCITE-6322]. Fixing this bug causes all +calculations that use DECIMAL values to produce slightly different +results. + Compatibility: This release is tested on Linux, macOS, Microsoft Windows; using JDK/OpenJDK versions 8 to 19; Guava versions 21.0 to 32.1.3-jre; diff --git a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java index 72b3559336fd..12d396128998 100644 --- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java +++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java @@ -352,11 +352,6 @@ static void forEach(Consumer consumer) { Pattern.compile("(?s).*could not calculate results for the following " + "row.*PC=5 Code=2201F.*"); - /** - * Whether DECIMAL type is implemented. - */ - public static final boolean DECIMAL = false; - /** Function object that returns a string with 2 copies of each character. * For example, {@code DOUBLER.apply("xy")} returns {@code "xxyy"}. */ private static final UnaryOperator DOUBLER = @@ -743,6 +738,29 @@ void testCastToExactNumeric(CastType castType, SqlOperatorFixture f) { "654342432412312"); } + /** Test cases for + * [CALCITE-6322] Casts to DECIMAL types are ignored. */ + @Test public void testIssue6322() { + SqlOperatorFixture f = fixture(); + f.checkScalar("CAST(1.123 AS DECIMAL(4, 0))", "1", "DECIMAL(4, 0) NOT NULL"); + f.checkScalar("CAST(100 AS DECIMAL(3, 0))", "100", "DECIMAL(3, 0) NOT NULL"); + f.checkScalar("CAST(-100 AS DECIMAL(3, 0))", "-100", "DECIMAL(3, 0) NOT NULL"); + f.checkScalar("CAST(100 AS DECIMAL(5, 2))", "100.00", "DECIMAL(5, 2) NOT NULL"); + f.checkScalar("CAST(-100 AS DECIMAL(5, 2))", "-100.00", "DECIMAL(5, 2) NOT NULL"); + f.checkFails("CAST(1000 AS DECIMAL(2, 0))", + "Value 1000 cannot be represented as a DECIMAL\\(2, 0\\)", true); + f.checkFails("CAST(-1000 AS DECIMAL(2, 0))", + "Value -1000 cannot be represented as a DECIMAL\\(2, 0\\)", true); + f.checkScalar("CAST(100.5e0 AS DECIMAL(4, 1))", "100.5", "DECIMAL(4, 1) NOT NULL"); + f.checkScalar("CAST(-100.5e0 AS DECIMAL(4, 1))", "-100.5", "DECIMAL(4, 1) NOT NULL"); + f.checkScalar("CAST(100.55e0 AS DECIMAL(4, 1))", "100.5", "DECIMAL(4, 1) NOT NULL"); + f.checkScalar("CAST(-100.55e0 AS DECIMAL(4, 1))", "-100.5", "DECIMAL(4, 1) NOT NULL"); + f.checkFails("CAST(100.5e0 AS DECIMAL(4, 2))", + "Value 100.5 cannot be represented as a DECIMAL\\(4, 2\\)", true); + f.checkFails("CAST(-100.5e0 AS DECIMAL(4, 2))", + "Value -100.5 cannot be represented as a DECIMAL\\(4, 2\\)", true); + } + /** * Test case for * Constant expression with nested casts causes a compiler crash. */ @@ -939,23 +957,18 @@ void testCastToInterval(CastType castType, SqlOperatorFixture f) { "cast(5 as interval year)", "+5", "INTERVAL YEAR NOT NULL"); - if (DECIMAL) { - // Due to DECIMAL rounding bugs, currently returns "+5" - f.checkScalar( - "cast(5.7 as interval day)", - "+6", - "INTERVAL DAY NOT NULL"); - f.checkScalar( - "cast(-5.7 as interval day)", - "-6", - "INTERVAL DAY NOT NULL"); - } else { - // An easier case - f.checkScalar( - "cast(6.2 as interval day)", - "+6", - "INTERVAL DAY NOT NULL"); - } + f.checkScalar( + "cast(5.7 as interval day)", + "+6", + "INTERVAL DAY NOT NULL"); + f.checkScalar( + "cast(-5.7 as interval day)", + "-6", + "INTERVAL DAY NOT NULL"); + f.checkScalar( + "cast(6.2 as interval day)", + "+6", + "INTERVAL DAY NOT NULL"); f.checkScalar( "cast(3456 as interval month(4))", "+3456", @@ -1159,9 +1172,7 @@ void testCastNull(CastType castType, SqlOperatorFixture f) { // null f.checkNull("cast(null as integer)"); - if (DECIMAL) { - f.checkNull("cast(null as decimal(4,3))"); - } + f.checkNull("cast(null as decimal(4,3))"); f.checkNull("cast(null as double)"); f.checkNull("cast(null as varchar(10))"); f.checkNull("cast(null as char(10))"); @@ -1759,14 +1770,12 @@ void testCastToBoolean(CastType castType, SqlOperatorFixture f) { f.checkString("case 1 when 1 then cast('a' as varchar(1)) " + "when 2 then cast('bcd' as varchar(3)) end", "a", "VARCHAR(3)"); - if (DECIMAL) { - f.checkScalarExact("case 2 when 1 then 11.2 " - + "when 2 then 4.543 else null end", - "DECIMAL(5, 3)", "4.543"); - f.checkScalarExact("case 1 when 1 then 11.2 " - + "when 2 then 4.543 else null end", - "DECIMAL(5, 3)", "11.200"); - } + f.checkScalarExact("case 2 when 1 then 11.2 " + + "when 2 then 4.543 else null end", + "DECIMAL(5, 3)", "4.543"); + f.checkScalarExact("case 1 when 1 then 11.2 " + + "when 2 then 4.543 else null end", + "DECIMAL(5, 3)", "11.200"); f.checkScalarExact("case 'a' when 'a' then 1 end", 1); f.checkScalarApprox("case 1 when 1 then 11.2e0 " + "when 2 then cast(4 as bigint) else 3 end", @@ -2593,9 +2602,6 @@ void checkModOperator(SqlOperatorFixture f) { f.checkScalarExact("12%-7", 5); f.checkScalarExact("cast(12 as tinyint) % cast(-7 as tinyint)", "TINYINT NOT NULL", "5"); - if (!DECIMAL) { - return; - } f.checkScalarExact("cast(9 as decimal(2, 0)) % 7", "INTEGER NOT NULL", "2"); f.checkScalarExact("7 % cast(9 as decimal(2, 0))", @@ -2612,9 +2618,6 @@ void checkModPrecedence(SqlOperatorFixture f) { void checkModOperatorNull(SqlOperatorFixture f) { f.checkNull("cast(null as integer) % 2"); f.checkNull("4 % cast(null as tinyint)"); - if (!DECIMAL) { - return; - } f.checkNull("4 % cast(null as decimal(12,0))"); } @@ -2642,15 +2645,12 @@ void checkModOperatorDivByZero(SqlOperatorFixture f) { f.checkScalarApprox(" 6.0 / cast(10.0 as real) ", "DOUBLE NOT NULL", isExactly("0.6")); f.checkScalarExact("10.0 / 5.0", "DECIMAL(9, 6) NOT NULL", "2"); - if (DECIMAL) { - f.checkScalarExact("1.0 / 3.0", "DECIMAL(8, 6) NOT NULL", "0.333333"); - f.checkScalarExact("100.1 / 0.0001", "DECIMAL(14, 7) NOT NULL", - "1001000.0000000"); - f.checkScalarExact("100.1 / 0.00000001", "DECIMAL(19, 8) NOT NULL", - "10010000000.00000000"); - } + f.checkScalarExact("1.0 / 3.0", "DECIMAL(8, 6) NOT NULL", "0.3333333333333333"); + f.checkScalarExact("100.1 / 0.0001", "DECIMAL(14, 7) NOT NULL", + "1.001E+6"); + f.checkScalarExact("100.1 / 0.00000001", "DECIMAL(19, 8) NOT NULL", + "1.001E+10"); f.checkNull("1e1 / cast(null as float)"); - f.checkScalarExact("100.1 / 0.00000000000000001", "DECIMAL(19, 0) NOT NULL", "1.001E+19"); } @@ -3116,9 +3116,6 @@ static void checkOverlaps(OverlapChecker c) { } @Test void testLessThanOperatorInterval() { - if (!DECIMAL) { - return; - } final SqlOperatorFixture f = fixture(); f.checkBoolean("interval '2' day < interval '1' day", false); f.checkBoolean("interval '2' day < interval '5' day", true); @@ -7169,9 +7166,6 @@ void checkRegexpExtract(SqlOperatorFixture f0, FunctionAlias functionAlias) { f.checkScalarExact("mod(cast(12 as tinyint), cast(-7 as tinyint))", "TINYINT NOT NULL", "5"); - if (!DECIMAL) { - return; - } f.checkScalarExact("mod(cast(9 as decimal(2, 0)), 7)", "INTEGER NOT NULL", "2"); f.checkScalarExact("mod(7, cast(9 as decimal(2, 0)))", @@ -7185,16 +7179,13 @@ void checkRegexpExtract(SqlOperatorFixture f0, FunctionAlias functionAlias) { final SqlOperatorFixture f = fixture(); f.checkNull("mod(cast(null as integer),2)"); f.checkNull("mod(4,cast(null as tinyint))"); - if (!DECIMAL) { - return; - } f.checkNull("mod(4,cast(null as decimal(12,0)))"); } @Test void testModFuncDivByZero() { // The extra CASE expression is to fool Janino. It does constant // reduction and will throw the divide by zero exception while - // compiling the expression. The test frame work would then issue + // compiling the expression. The test framework would then issue // unexpected exception occurred during "validation". You cannot // submit as non-runtime because the janino exception does not have // error position information and the framework is unhappy with that. @@ -7904,7 +7895,7 @@ void checkArrayReverseFunc(SqlOperatorFixture f0, SqlFunction function, f.checkScalar(fn + "(array[null, 1, cast(2 as decimal)])", "[2, 1, null]", "DECIMAL(19, 0) ARRAY NOT NULL"); f.checkScalar(fn + "(array[CAST(2.1 as decimal(17)), 2.1111111111111119])", - "[2.1111111111111119, 2.1]", "DECIMAL(19, 2) NOT NULL ARRAY NOT NULL"); + "[2.11, 2.00]", "DECIMAL(19, 2) NOT NULL ARRAY NOT NULL"); f.checkScalar(fn + "(array[CAST(2.1 as double), 2.1111111111111119])", "[2.111111111111112, 2.1]", "DOUBLE NOT NULL ARRAY NOT NULL"); f.checkScalar(fn + "(array[null])", "[null]", "NULL ARRAY NOT NULL"); @@ -9034,7 +9025,7 @@ void checkArrayReverseFunc(SqlOperatorFixture f0, SqlFunction function, f.checkType("atanh('abc')", "DOUBLE NOT NULL"); f.checkScalarApprox("atanh(0.76159416)", "DOUBLE NOT NULL", isWithin(1d, 0.0001d)); - f.checkScalarApprox("atanh(cast(-0.1 as decimal))", "DOUBLE NOT NULL", + f.checkScalarApprox("atanh(cast(-0.1 as decimal(2,1)))", "DOUBLE NOT NULL", isWithin(-0.1003d, 0.0001d)); f.checkNull("atanh(cast(null as integer))"); f.checkNull("atanh(cast(null as double))"); @@ -9112,7 +9103,7 @@ void checkArrayReverseFunc(SqlOperatorFixture f0, SqlFunction function, isWithin(0.5d, 0.01d)); f.checkScalarApprox("cosd(-60)", "DOUBLE NOT NULL", isWithin(0.5d, 0.01d)); - f.checkScalarApprox("cosd(cast(60 as decimal(1, 0)))", "DOUBLE NOT NULL", + f.checkScalarApprox("cosd(cast(60 as decimal(2, 0)))", "DOUBLE NOT NULL", isWithin(0.5d, 0.01d)); f.checkScalarExact("cosd(cast('NaN' as double))", "DOUBLE NOT NULL", "NaN"); @@ -9404,18 +9395,18 @@ void checkArrayReverseFunc(SqlOperatorFixture f0, SqlFunction function, false); f.checkType("round('abc', 'def')", "DECIMAL(19, 9) NOT NULL"); f.checkScalar("round(42, -1)", 40, "INTEGER NOT NULL"); - f.checkScalar("round(cast(42.346 as decimal(2, 3)), 2)", - BigDecimal.valueOf(4235, 2), "DECIMAL(2, 3) NOT NULL"); - f.checkScalar("round(cast(-42.346 as decimal(2, 3)), 2)", - BigDecimal.valueOf(-4235, 2), "DECIMAL(2, 3) NOT NULL"); + f.checkScalar("round(cast(42.346 as decimal(5, 3)), 2)", + BigDecimal.valueOf(4235, 2), "DECIMAL(5, 3) NOT NULL"); + f.checkScalar("round(cast(-42.346 as decimal(5, 3)), 2)", + BigDecimal.valueOf(-4235, 2), "DECIMAL(5, 3) NOT NULL"); f.checkNull("round(cast(null as integer), 1)"); f.checkNull("round(cast(null as double), 1)"); f.checkNull("round(43.21, cast(null as integer))"); f.checkNull("round(cast(null as double))"); f.checkScalar("round(42)", 42, "INTEGER NOT NULL"); - f.checkScalar("round(cast(42.346 as decimal(2, 3)))", - BigDecimal.valueOf(42, 0), "DECIMAL(2, 3) NOT NULL"); + f.checkScalar("round(cast(42.346 as decimal(5, 3)))", + BigDecimal.valueOf(42, 0), "DECIMAL(5, 3) NOT NULL"); f.checkScalar("round(42.324)", BigDecimal.valueOf(42, 0), "DECIMAL(5, 3) NOT NULL"); f.checkScalar("round(42.724)", @@ -9533,7 +9524,7 @@ void checkArrayReverseFunc(SqlOperatorFixture f0, SqlFunction function, isWithin(0.5d, 0.01d)); f.checkScalarApprox("sind(-30)", "DOUBLE NOT NULL", isWithin(-0.5d, 0.01d)); - f.checkScalarApprox("sind(cast(30 as decimal(1, 0)))", "DOUBLE NOT NULL", + f.checkScalarApprox("sind(cast(30 as decimal(2, 0)))", "DOUBLE NOT NULL", isWithin(0.5d, 0.01d)); f.checkScalarExact("sin(cast('NaN' as double))", "DOUBLE NOT NULL", "NaN"); @@ -9603,7 +9594,7 @@ void checkArrayReverseFunc(SqlOperatorFixture f0, SqlFunction function, isWithin(1.73d, 1.74d)); f.checkScalarApprox("cosd(-60)", "DOUBLE NOT NULL", isWithin(1.73d, 1.74d)); - f.checkScalarApprox("tand(cast(60 as decimal(1, 0)))", "DOUBLE NOT NULL", + f.checkScalarApprox("tand(cast(60 as decimal(3, 0)))", "DOUBLE NOT NULL", isWithin(1.73d, 1.74d)); f.checkScalarExact("tand(cast('NaN' as double))", "DOUBLE NOT NULL", "NaN"); @@ -9648,10 +9639,10 @@ void checkArrayReverseFunc(SqlOperatorFixture f0, SqlFunction function, false); f.checkType("trunc('abc', 'def')", "DECIMAL(19, 9) NOT NULL"); f.checkScalar("trunc(42, -1)", 40.0, "DOUBLE NOT NULL"); - f.checkScalar("trunc(cast(42.345 as decimal(2, 3)), 2)", - BigDecimal.valueOf(4234, 2), "DECIMAL(2, 3) NOT NULL"); - f.checkScalar("trunc(cast(-42.345 as decimal(2, 3)), 2)", - BigDecimal.valueOf(-4234, 2), "DECIMAL(2, 3) NOT NULL"); + f.checkScalar("trunc(cast(42.345 as decimal(5, 3)), 2)", + BigDecimal.valueOf(4234, 2), "DECIMAL(5, 3) NOT NULL"); + f.checkScalar("trunc(cast(-42.345 as decimal(5, 3)), 2)", + BigDecimal.valueOf(-4234, 2), "DECIMAL(5, 3) NOT NULL"); f.checkNull("trunc(cast(null as integer), 1)"); f.checkNull("trunc(cast(null as double), 1)"); f.checkNull("trunc(43.21, cast(null as integer))"); @@ -9661,8 +9652,8 @@ void checkArrayReverseFunc(SqlOperatorFixture f0, SqlFunction function, BigDecimal.valueOf(42, 0), "DECIMAL(5, 3) NOT NULL"); f.checkScalar("trunc(cast(42.324 as float))", 42F, "FLOAT NOT NULL"); - f.checkScalar("trunc(cast(42.345 as decimal(2, 3)))", - BigDecimal.valueOf(42, 0), "DECIMAL(2, 3) NOT NULL"); + f.checkScalar("trunc(cast(42.345 as decimal(5, 3)))", + BigDecimal.valueOf(42, 0), "DECIMAL(5, 3) NOT NULL"); f.checkNull("trunc(cast(null as integer))"); f.checkNull("trunc(cast(null as double))"); } @@ -9683,10 +9674,10 @@ void checkArrayReverseFunc(SqlOperatorFixture f0, SqlFunction function, false); f.checkType("truncate('abc', 'def')", "DECIMAL(19, 9) NOT NULL"); f.checkScalar("truncate(42, -1)", 40, "INTEGER NOT NULL"); - f.checkScalar("truncate(cast(42.345 as decimal(2, 3)), 2)", - BigDecimal.valueOf(4234, 2), "DECIMAL(2, 3) NOT NULL"); - f.checkScalar("truncate(cast(-42.345 as decimal(2, 3)), 2)", - BigDecimal.valueOf(-4234, 2), "DECIMAL(2, 3) NOT NULL"); + f.checkScalar("truncate(cast(42.345 as decimal(5, 3)), 2)", + BigDecimal.valueOf(4234, 2), "DECIMAL(5, 3) NOT NULL"); + f.checkScalar("truncate(cast(-42.345 as decimal(5, 3)), 2)", + BigDecimal.valueOf(-4234, 2), "DECIMAL(5, 3) NOT NULL"); f.checkNull("truncate(cast(null as integer), 1)"); f.checkNull("truncate(cast(null as double), 1)"); f.checkNull("truncate(43.21, cast(null as integer))"); @@ -9696,8 +9687,8 @@ void checkArrayReverseFunc(SqlOperatorFixture f0, SqlFunction function, BigDecimal.valueOf(42, 0), "DECIMAL(5, 3) NOT NULL"); f.checkScalar("truncate(cast(42.324 as float))", 42F, "FLOAT NOT NULL"); - f.checkScalar("truncate(cast(42.345 as decimal(2, 3)))", - BigDecimal.valueOf(42, 0), "DECIMAL(2, 3) NOT NULL"); + f.checkScalar("truncate(cast(42.345 as decimal(5, 3)))", + BigDecimal.valueOf(42, 0), "DECIMAL(5, 3) NOT NULL"); f.checkNull("truncate(cast(null as integer))"); f.checkNull("truncate(cast(null as double))"); } @@ -9750,14 +9741,16 @@ void checkArrayReverseFunc(SqlOperatorFixture f0, SqlFunction function, + "cast(9223372036854775807 as bigint))"); f.checkNull("safe_add(cast(-20 as bigint), " + "cast(-9223372036854775807 as bigint))"); - f.checkNull("safe_add(9, cast(9.999999999999999999e75 as DECIMAL(38, 19)))"); - f.checkNull("safe_add(-9, cast(-9.999999999999999999e75 as DECIMAL(38, 19)))"); - f.checkNull("safe_add(cast(9.999999999999999999e75 as DECIMAL(38, 19)), 9)"); - f.checkNull("safe_add(cast(-9.999999999999999999e75 as DECIMAL(38, 19)), -9)"); - f.checkNull("safe_add(cast(9.9e75 as DECIMAL(76, 0)), " - + "cast(9.9e75 as DECIMAL(76, 0)))"); - f.checkNull("safe_add(cast(-9.9e75 as DECIMAL(76, 0)), " - + "cast(-9.9e75 as DECIMAL(76, 0)))"); + if (Bug.CALCITE_6328_FIXED) { + f.checkNull("safe_add(9, cast(9.999999999999999999e75 as DECIMAL(38, 19)))"); + f.checkNull("safe_add(-9, cast(-9.999999999999999999e75 as DECIMAL(38, 19)))"); + f.checkNull("safe_add(cast(9.999999999999999999e75 as DECIMAL(38, 19)), 9)"); + f.checkNull("safe_add(cast(-9.999999999999999999e75 as DECIMAL(38, 19)), -9)"); + f.checkNull("safe_add(cast(9.9e75 as DECIMAL(76, 0)), " + + "cast(9.9e75 as DECIMAL(76, 0)))"); + f.checkNull("safe_add(cast(-9.9e75 as DECIMAL(76, 0)), " + + "cast(-9.9e75 as DECIMAL(76, 0)))"); + } f.checkNull("safe_add(cast(1.7976931348623157e308 as double), " + "cast(9.9e7 as decimal(76, 0)))"); f.checkNull("safe_add(cast(-1.7976931348623157e308 as double), " @@ -9829,20 +9822,22 @@ void checkArrayReverseFunc(SqlOperatorFixture f0, SqlFunction function, f.checkNull("safe_divide(cast(0 as double), cast(0 as bigint))"); f.checkNull("safe_divide(cast(0 as double), cast(0 as double))"); f.checkNull("safe_divide(cast(0 as double), cast(0 as decimal(1, 0)))"); - f.checkNull("safe_divide(cast(1.5 as decimal(2, 1)), cast(0 as bigint))"); - f.checkNull("safe_divide(cast(1.5 as decimal(2, 1)), cast(0 as double))"); - f.checkNull("safe_divide(cast(1.5 as decimal(2, 1)), cast(0 as decimal(1, 0)))"); - // Overflow test for each pairing - f.checkNull("safe_divide(cast(10 as bigint), cast(3.5e-75 as DECIMAL(76, 0)))"); - f.checkNull("safe_divide(cast(10 as bigint), cast(-3.5e75 as DECIMAL(76, 0)))"); - f.checkNull("safe_divide(cast(3.5e75 as DECIMAL(76, 0)), " - + "cast(1.5 as DECIMAL(2, 1)))"); - f.checkNull("safe_divide(cast(-3.5e75 as DECIMAL(76, 0)), " - + "cast(1.5 as DECIMAL(2, 1)))"); + if (Bug.CALCITE_6328_FIXED) { + f.checkNull("safe_divide(cast(1.5 as decimal(2, 1)), cast(0 as bigint))"); + f.checkNull("safe_divide(cast(1.5 as decimal(2, 1)), cast(0 as double))"); + f.checkNull("safe_divide(cast(1.5 as decimal(2, 1)), cast(0 as decimal(1, 0)))"); + // Overflow test for each pairing + f.checkNull("safe_divide(cast(10 as bigint), cast(3.5e-75 as DECIMAL(76, 0)))"); + f.checkNull("safe_divide(cast(10 as bigint), cast(-3.5e75 as DECIMAL(76, 0)))"); + f.checkNull("safe_divide(cast(3.5e75 as DECIMAL(76, 0)), " + + "cast(1.5 as DECIMAL(2, 1)))"); + f.checkNull("safe_divide(cast(-3.5e75 as DECIMAL(76, 0)), " + + "cast(1.5 as DECIMAL(2, 1)))"); + f.checkNull("safe_divide(cast(5e20 as decimal(1, 0)), cast(1.7e-309 as double))"); + f.checkNull("safe_divide(cast(5e20 as decimal(1, 0)), cast(-1.7e-309 as double))"); + } f.checkNull("safe_divide(cast(1.7e308 as double), cast(0.5 as decimal(3, 2)))"); f.checkNull("safe_divide(cast(-1.7e308 as double), cast(0.5 as decimal(2, 1)))"); - f.checkNull("safe_divide(cast(5e20 as decimal(1, 0)), cast(1.7e-309 as double))"); - f.checkNull("safe_divide(cast(5e20 as decimal(1, 0)), cast(-1.7e-309 as double))"); f.checkNull("safe_divide(cast(3 as bigint), cast(1.7e-309 as double))"); f.checkNull("safe_divide(cast(3 as bigint), cast(-1.7e-309 as double))"); f.checkNull("safe_divide(cast(3 as double), cast(1.7e-309 as double))"); @@ -9900,14 +9895,16 @@ void checkArrayReverseFunc(SqlOperatorFixture f0, SqlFunction function, + "cast(9223372036854775807 as bigint))"); f.checkNull("safe_multiply(cast(20 as bigint), " + "cast(-9223372036854775807 as bigint))"); - f.checkNull("safe_multiply(cast(10 as bigint), cast(3.5e75 as DECIMAL(76, 0)))"); - f.checkNull("safe_multiply(cast(10 as bigint), cast(-3.5e75 as DECIMAL(76, 0)))"); - f.checkNull("safe_multiply(cast(3.5e75 as DECIMAL(76, 0)), cast(10 as bigint))"); - f.checkNull("safe_multiply(cast(-3.5e75 as DECIMAL(76, 0)), cast(10 as bigint))"); - f.checkNull("safe_multiply(cast(3.5e75 as DECIMAL(76, 0)), " - + "cast(1.5 as DECIMAL(2, 1)))"); - f.checkNull("safe_multiply(cast(-3.5e75 as DECIMAL(76, 0)), " - + "cast(1.5 as DECIMAL(2, 1)))"); + if (Bug.CALCITE_6328_FIXED) { + f.checkNull("safe_multiply(cast(10 as bigint), cast(3.5e75 as DECIMAL(76, 0)))"); + f.checkNull("safe_multiply(cast(10 as bigint), cast(-3.5e75 as DECIMAL(76, 0)))"); + f.checkNull("safe_multiply(cast(3.5e75 as DECIMAL(76, 0)), cast(10 as bigint))"); + f.checkNull("safe_multiply(cast(-3.5e75 as DECIMAL(76, 0)), cast(10 as bigint))"); + f.checkNull("safe_multiply(cast(3.5e75 as DECIMAL(76, 0)), " + + "cast(1.5 as DECIMAL(2, 1)))"); + f.checkNull("safe_multiply(cast(-3.5e75 as DECIMAL(76, 0)), " + + "cast(1.5 as DECIMAL(2, 1)))"); + } f.checkNull("safe_multiply(cast(1.7e308 as double), cast(1.23 as decimal(3, 2)))"); f.checkNull("safe_multiply(cast(-1.7e308 as double), cast(1.2 as decimal(2, 1)))"); f.checkNull("safe_multiply(cast(1.2 as decimal(2, 1)), cast(1.7e308 as double))"); @@ -10010,14 +10007,16 @@ void checkArrayReverseFunc(SqlOperatorFixture f0, SqlFunction function, + "cast(-9223372036854775807 as bigint))"); f.checkNull("safe_subtract(cast(-20 as bigint), " + "cast(9223372036854775807 as bigint))"); - f.checkNull("safe_subtract(9, cast(-9.999999999999999999e75 as DECIMAL(38, 19)))"); - f.checkNull("safe_subtract(-9, cast(9.999999999999999999e75 as DECIMAL(38, 19)))"); - f.checkNull("safe_subtract(cast(-9.999999999999999999e75 as DECIMAL(38, 19)), 9)"); - f.checkNull("safe_subtract(cast(9.999999999999999999e75 as DECIMAL(38, 19)), -9)"); - f.checkNull("safe_subtract(cast(-9.9e75 as DECIMAL(76, 0)), " - + "cast(9.9e75 as DECIMAL(76, 0)))"); - f.checkNull("safe_subtract(cast(9.9e75 as DECIMAL(76, 0)), " - + "cast(-9.9e75 as DECIMAL(76, 0)))"); + if (Bug.CALCITE_6328_FIXED) { + f.checkNull("safe_subtract(9, cast(-9.999999999999999999e75 as DECIMAL(38, 19)))"); + f.checkNull("safe_subtract(-9, cast(9.999999999999999999e75 as DECIMAL(38, 19)))"); + f.checkNull("safe_subtract(cast(-9.999999999999999999e75 as DECIMAL(38, 19)), 9)"); + f.checkNull("safe_subtract(cast(9.999999999999999999e75 as DECIMAL(38, 19)), -9)"); + f.checkNull("safe_subtract(cast(-9.9e75 as DECIMAL(76, 0)), " + + "cast(9.9e75 as DECIMAL(76, 0)))"); + f.checkNull("safe_subtract(cast(9.9e75 as DECIMAL(76, 0)), " + + "cast(-9.9e75 as DECIMAL(76, 0)))"); + } f.checkNull("safe_subtract(cast(1.7976931348623157e308 as double), " + "cast(-9.9e7 as decimal(76, 0)))"); f.checkNull("safe_subtract(cast(-1.7976931348623157e308 as double), " @@ -11380,7 +11379,7 @@ void assertSubFunReturns(boolean binary, String s, int start, f12.checkScalar("nvl2('a', 3, 2)", "3", "INTEGER NOT NULL"); f12.checkScalar("NVL2(NULL, 3.0, 4.0)", "4.0", "DECIMAL(2, 1) NOT NULL"); f12.checkScalar("NVL2('abc', 3.0, 4.0)", "3.0", "DECIMAL(2, 1) NOT NULL"); - f12.checkScalar("NVL2(1, 3.0, 2.111)", "3.0", "DECIMAL(4, 3) NOT NULL"); + f12.checkScalar("NVL2(1, 3.0, 2.111)", "3.000", "DECIMAL(4, 3) NOT NULL"); f12.checkScalar("NVL2(NULL, 3.0, 2.111)", "2.111", "DECIMAL(4, 3) NOT NULL"); f12.checkScalar("NVL2(3.111, 3.1415926, 2.111)", "3.1415926", "DECIMAL(8, 7) NOT NULL"); @@ -12854,8 +12853,8 @@ private static void checkArrayConcatAggFuncFails(SqlOperatorFixture t) { f.checkScalarExact("ceil(cast(3 as integer))", "DOUBLE NOT NULL", "3.0"); f.checkScalarExact("ceil(cast(3 as bigint))", "DOUBLE NOT NULL", "3.0"); f.checkScalarExact("ceil(cast(3.5 as double))", "DOUBLE NOT NULL", "4.0"); - f.checkScalarExact("ceil(cast(3.45 as decimal))", - "DECIMAL(19, 0) NOT NULL", "4"); + f.checkScalarExact("ceil(cast(3.45 as decimal(19, 1)))", + "DECIMAL(19, 1) NOT NULL", "4"); f.checkScalarExact("ceil(cast(3.45 as float))", "FLOAT NOT NULL", "4.0"); f.checkNull("ceil(cast(null as tinyint))"); } @@ -15598,9 +15597,13 @@ void checkBitOr(SqlOperatorFixture f0, FunctionAlias functionAlias) { } else { // Value outside legal bound should fail at runtime (not // validate time). - f.checkFails("CAST(" + literalString + " AS " + type + ")", - OUT_OF_RANGE_MESSAGE, - true); + String expected; + if (type.getSqlTypeName() == SqlTypeName.DECIMAL) { + expected = "Value .* cannot be represented as .*"; + } else { + expected = "Value .* out of range"; + } + f.checkFails("CAST(" + literalString + " AS " + type + ")", expected, true); } } }