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 e0ef58abd133..517a87c22408 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(12, 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(12, 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(12, 4))) from emp; EXPR$0 -1398313.873626374 +1398313.8736 !ok -select var_pop(sal) from emp; +select var_pop(CAST(sal AS DECIMAL(12, 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 @@ -523,78 +523,78 @@ 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; +select empno, stddev_pop(CAST(comm AS DECIMAL(12, 4))) 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.0000 +7521, 100.0000 +7654, 478.4233 +7698, 478.4233 +7844, 522.0153 +7900, 522.0153 !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; +select empno, stddev_samp(CAST(comm AS DECIMAL(12, 4))) 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.4213 +7654, 585.9465 +7698, 585.9465 +7844, 602.7713 +7900, 602.7713 !ok -select empno, stddev(comm) over (order by empno rows unbounded preceding) from emp where deptno = 30 order by 1; +select empno, stddev(CAST(comm AS DECIMAL(12, 4))) 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.4213 +7654, 585.9465 +7698, 585.9465 +7844, 602.7713 +7900, 602.7713 !ok # SUM -select empno, sum(comm) over (order by empno rows unbounded preceding) from emp where deptno = 30 order by 1; +select empno, sum(CAST(comm AS DECIMAL(12, 4))) over (order by empno rows unbounded preceding) from emp where deptno = 30 order by 1; EMPNO, EXPR$1 -7499, 300.00 -7521, 800.00 -7654, 2200.00 -7698, 2200.00 -7844, 2200.00 -7900, 2200.00 +7499, 300.0000 +7521, 800.0000 +7654, 2200.0000 +7698, 2200.0000 +7844, 2200.0000 +7900, 2200.0000 !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(12, 4))) 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 +7654, 228888.8889 +7698, 228888.8889 7844, 272500.0000 7900, 272500.0000 !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(12, 4))) 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 +7654, 343333.3333 +7698, 343333.3333 +7844, 363333.3333 +7900, 363333.3333 !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(12, 4))) 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 +7654, 343333.3333 +7698, 343333.3333 +7844, 363333.3333 +7900, 363333.3333 !ok # 5.2 Ranking functions @@ -2013,7 +2013,7 @@ 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); 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 e49788c5945a..fcdf6ba3705b 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 @@ -442,6 +442,36 @@ private Expression getConvertExpression( return defaultExpression.get(); } + case DECIMAL: { + int precision = targetType.getPrecision(); + int scale = targetType.getScale(); + if (precision != RelDataType.PRECISION_NOT_SPECIFIED + && scale != RelDataType.SCALE_NOT_SPECIFIED) { + 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(); + } case BIGINT: case INTEGER: case TINYINT: diff --git a/core/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java b/core/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java index 8149b22dad5d..04b00774facf 100644 --- a/core/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java +++ b/core/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java @@ -1836,7 +1836,7 @@ public static boolean isValidDecimalValue(@Nullable BigDecimal value, RelDataTyp case DECIMAL: final int intDigits = value.precision() - value.scale(); final int maxIntDigits = toType.getPrecision() - toType.getScale(); - return intDigits <= maxIntDigits; + return (intDigits <= maxIntDigits) && (value.scale() <= toType.getScale()); default: return true; } 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 e0eaa97a3ec9..32e99038d672 100644 --- a/core/src/main/java/org/apache/calcite/util/Bug.java +++ b/core/src/main/java/org/apache/calcite/util/Bug.java @@ -215,6 +215,12 @@ public abstract class Bug { * Fix failing quidem tests for FORMAT in CAST is fixed. */ public static final boolean CALCITE_6375_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 2e72df1be651..903aaf34b590 100644 --- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java +++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java @@ -292,6 +292,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", + Object.class, int.class, int.class), + FP_DECIMAL_CAST(Primitive.class, "fpDecimalCast", + Object.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/rex/RexProgramTest.java b/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java index ba7e4f18bf53..89b6854d9d05 100644 --- a/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java +++ b/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java @@ -3814,7 +3814,8 @@ private SqlSpecialOperatorWithPolicy(String name, SqlKind kind, int prec, boolea RexNode one = literal(1); RexNode b = vDecimalNotNull(2); - RexNode half = literal(new BigDecimal(0.5), b.getType()); + RelDataType decimal = typeFactory.createSqlType(SqlTypeName.DECIMAL, 2, 1); + RexNode half = literal(new BigDecimal("0.5"), decimal); checkSimplify(add(a, zero), "?0.notNullInt1"); checkSimplify(add(zero, a), "?0.notNullInt1"); 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/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/misc.iq b/core/src/test/resources/sql/misc.iq index fd60c24693a5..3ef2cc8e2a30 100644 --- a/core/src/test/resources/sql/misc.iq +++ b/core/src/test/resources/sql/misc.iq @@ -2422,13 +2422,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/winagg.iq b/core/src/test/resources/sql/winagg.iq index ed02f556f40c..a2a66effa757 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 diff --git a/core/src/test/resources/sql/within-distinct.iq b/core/src/test/resources/sql/within-distinct.iq index ea8c5ec554f1..a8109004450a 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 @@ -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) @@ -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 4beddd31ee60..61030d391f35 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,14 @@ 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), CAST(1:DECIMAL(19, 0)):DECIMAL(19, 0)," + + " CAST($3):DECIMAL(19, 0))]], sort0=[1], dir0=[DESC])\n"; CalciteAssert.AssertQuery q = sql(sqlQuery) .explainContains(plan) .queryContains(new DruidChecker(postAggString)); 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 b03f3e19e86a..a318747f46b3 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,13 @@ 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), CAST(1:DECIMAL(19, 0)):DECIMAL(19, 0), " + + "CAST($3):DECIMAL(19, 0))]], sort0=[1], dir0=[DESC])"; CalciteAssert.AssertQuery q = sql(sqlQuery, FOODMART) .explainContains(plan) .queryContains(new DruidChecker(postAggString)); 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 6aa575c795cf..45b568ffa19b 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,10 +384,57 @@ 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); } + static BigDecimal checkOverflow(BigDecimal value, int precision, int scale) { + BigDecimal result = value.setScale(scale, RoundingMode.FLOOR); + result = result.stripTrailingZeros(); + if (result.scale() < scale) { + // stripTrailingZeros also removes zeros if there is no + // decimal point, converting 1000 to 1e+3, using a negative scale. + // Here we undo this change. + result = result.setScale(scale, RoundingMode.FLOOR); + } + int actualPrecision = result.precision(); + if (actualPrecision > precision) { + throw new ArithmeticException("Value " + value + + " cannot be represented as a DECIMAL(" + precision + ", " + scale + ")"); + } + return result; + } + + /** 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 Object value, int precision, int scale) { + if (value == null) { + return null; + } + final BigDecimal decimal = new BigDecimal(((Number) value).longValue()); + return checkOverflow(decimal, precision, scale); + } + + /** Called from BuiltInMethod.FP_DECIMAL_CAST */ + public static @Nullable Object fpDecimalCast( + @Nullable Object value, int precision, int scale) { + if (value == null) { + return null; + } + final BigDecimal decimal = BigDecimal.valueOf(((Number) 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/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java index d0e529944d2b..c6bef6d9d8c0 100644 --- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java +++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java @@ -598,6 +598,13 @@ void testCastBooleanToNumeric(CastType castType, SqlOperatorFixture f) { "Cast function cannot convert value of type BOOLEAN to type DECIMAL\\(19, 0\\)", false); } + /** Test case for + * [CALCITE-6322] Casts to DECIMAL types are ignored. */ + @Test void testDecimalDecimalCast() { + final SqlOperatorFixture f = fixture(); + f.checkScalar("CAST(1.123 AS DECIMAL(4, 0))", "1", "DECIMAL(4, 0) NOT NULL"); + } + @ParameterizedTest @MethodSource("safeParameters") void testCastExactNumericLimits(CastType castType, SqlOperatorFixture f) { @@ -754,6 +761,7 @@ void testCastStringToDecimal(CastType castType, SqlOperatorFixture f) { "-1.2"); f.checkFails("cast(' -1.21e' as decimal(2,1))", INVALID_CHAR_MESSAGE, true); + f.checkFails("cast(''100' as decimal(2, 1))", "Value .* out of range", true); } @ParameterizedTest @@ -8226,7 +8234,7 @@ void checkRegexpExtract(SqlOperatorFixture f0, FunctionAlias functionAlias) { 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))"); @@ -8568,18 +8576,18 @@ void checkRegexpExtract(SqlOperatorFixture f0, FunctionAlias functionAlias) { 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)", @@ -8755,10 +8763,10 @@ void checkRegexpExtract(SqlOperatorFixture f0, FunctionAlias functionAlias) { 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))"); @@ -8768,8 +8776,8 @@ void checkRegexpExtract(SqlOperatorFixture f0, FunctionAlias functionAlias) { 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))"); } @@ -8790,10 +8798,10 @@ void checkRegexpExtract(SqlOperatorFixture f0, FunctionAlias functionAlias) { 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))"); @@ -8803,8 +8811,8 @@ void checkRegexpExtract(SqlOperatorFixture f0, FunctionAlias functionAlias) { 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))"); } @@ -8857,14 +8865,16 @@ void checkRegexpExtract(SqlOperatorFixture f0, FunctionAlias functionAlias) { + "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), " @@ -8936,20 +8946,22 @@ void checkRegexpExtract(SqlOperatorFixture f0, FunctionAlias functionAlias) { 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))"); @@ -9007,14 +9019,16 @@ void checkRegexpExtract(SqlOperatorFixture f0, FunctionAlias functionAlias) { + "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))"); @@ -9117,14 +9131,16 @@ void checkRegexpExtract(SqlOperatorFixture f0, FunctionAlias functionAlias) { + "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), " @@ -11851,8 +11867,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))"); } @@ -14533,14 +14549,13 @@ void checkBitOr(SqlOperatorFixture f0, FunctionAlias functionAlias) { } else { // Value outside legal bound should fail at runtime (not // validate time). - // - // NOTE: Because Java and Fennel calcs give - // different errors, the pattern hedges its bets. - if (Bug.CALCITE_2539_FIXED) { - f.checkFails("CAST(" + literalString + " AS " + type + ")", - "(?s).*(Overflow during calculation or cast\\.|Code=22003).*", - 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); } } }