This is an automated email from the ASF dual-hosted git repository. volodymyr pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/drill.git
The following commit(s) were added to refs/heads/master by this push: new fa0d78d DRILL-6710: Disallow negative scale for decimal data type fa0d78d is described below commit fa0d78d16eaf35d30d95613913a5613b2a82280d Author: Volodymyr Vysotskyi <vvo...@gmail.com> AuthorDate: Mon Aug 27 23:16:35 2018 -0700 DRILL-6710: Disallow negative scale for decimal data type --- .../native/client/src/protobuf/UserBitShared.pb.cc | 15 +- .../native/client/src/protobuf/UserBitShared.pb.h | 2 +- .../Decimal/DecimalAggrTypeFunctions1.java | 5 +- .../Decimal/DecimalAggrTypeFunctions3.java | 1 + .../templates/Decimal/DecimalFunctions.java | 6 +- .../expr/fn/output/DecimalReturnTypeInference.java | 2 +- .../decimal/DecimalScalePrecisionAddFunction.java | 2 +- .../DecimalScalePrecisionDivideFunction.java | 1 + .../decimal/DecimalScalePrecisionModFunction.java | 4 +- .../decimal/DecimalScalePrecisionMulFunction.java | 3 +- .../decimal/DrillBaseComputeScalePrecision.java | 13 +- .../java/org/apache/drill/TestFunctionsQuery.java | 277 +++++++++++---------- .../exec/fn/impl/TestVarDecimalFunctions.java | 56 ++++- 13 files changed, 234 insertions(+), 153 deletions(-) diff --git a/contrib/native/client/src/protobuf/UserBitShared.pb.cc b/contrib/native/client/src/protobuf/UserBitShared.pb.cc index 574406d..d0e4aa5 100644 --- a/contrib/native/client/src/protobuf/UserBitShared.pb.cc +++ b/contrib/native/client/src/protobuf/UserBitShared.pb.cc @@ -750,7 +750,7 @@ void protobuf_AddDesc_UserBitShared_2eproto() { "TATEMENT\020\005*\207\001\n\rFragmentState\022\013\n\007SENDING\020" "\000\022\027\n\023AWAITING_ALLOCATION\020\001\022\013\n\007RUNNING\020\002\022" "\014\n\010FINISHED\020\003\022\r\n\tCANCELLED\020\004\022\n\n\006FAILED\020\005" - "\022\032\n\026CANCELLATION_REQUESTED\020\006*\343\010\n\020CoreOpe" + "\022\032\n\026CANCELLATION_REQUESTED\020\006*\367\010\n\020CoreOpe" "ratorType\022\021\n\rSINGLE_SENDER\020\000\022\024\n\020BROADCAS" "T_SENDER\020\001\022\n\n\006FILTER\020\002\022\022\n\016HASH_AGGREGATE" "\020\003\022\r\n\tHASH_JOIN\020\004\022\016\n\nMERGE_JOIN\020\005\022\031\n\025HAS" @@ -778,12 +778,12 @@ void protobuf_AddDesc_UserBitShared_2eproto() { "ER\0200\022\026\n\022OPEN_TSDB_SUB_SCAN\0201\022\017\n\013JSON_WRI" "TER\0202\022\026\n\022HTPPD_LOG_SUB_SCAN\0203\022\022\n\016IMAGE_S" "UB_SCAN\0204\022\025\n\021SEQUENCE_SUB_SCAN\0205\022\023\n\017PART" - "ITION_LIMIT\0206\022\023\n\017PCAPNG_SUB_SCAN\0207*g\n\nSa" - "ITION_LIMIT\0206\022\022\n\016RUNTIME_FILTER\0207*g\n\nSas" - "slStatus\022\020\n\014SASL_UNKNOWN\020\000\022\016\n\nSASL_START" - "\020\001\022\024\n\020SASL_IN_PROGRESS\020\002\022\020\n\014SASL_SUCCESS" - "\020\003\022\017\n\013SASL_FAILED\020\004B.\n\033org.apache.drill." - "exec.protoB\rUserBitSharedH\001", 5427); + "ITION_LIMIT\0206\022\023\n\017PCAPNG_SUB_SCAN\0207\022\022\n\016RU" + "NTIME_FILTER\0208*g\n\nSaslStatus\022\020\n\014SASL_UNK" + "NOWN\020\000\022\016\n\nSASL_START\020\001\022\024\n\020SASL_IN_PROGRE" + "SS\020\002\022\020\n\014SASL_SUCCESS\020\003\022\017\n\013SASL_FAILED\020\004B" + ".\n\033org.apache.drill.exec.protoB\rUserBitS" + "haredH\001", 5447); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "UserBitShared.proto", &protobuf_RegisterTypes); UserCredentials::default_instance_ = new UserCredentials(); @@ -960,6 +960,7 @@ bool CoreOperatorType_IsValid(int value) { case 53: case 54: case 55: + case 56: return true; default: return false; diff --git a/contrib/native/client/src/protobuf/UserBitShared.pb.h b/contrib/native/client/src/protobuf/UserBitShared.pb.h index 07ec0af..8494857 100644 --- a/contrib/native/client/src/protobuf/UserBitShared.pb.h +++ b/contrib/native/client/src/protobuf/UserBitShared.pb.h @@ -260,7 +260,7 @@ enum CoreOperatorType { SEQUENCE_SUB_SCAN = 53, PARTITION_LIMIT = 54, PCAPNG_SUB_SCAN = 55, - RUNTIME_FILTER = 56 + RUNTIME_FILTER = 56 }; bool CoreOperatorType_IsValid(int value); const CoreOperatorType CoreOperatorType_MIN = SINGLE_SENDER; diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions1.java b/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions1.java index 7f4ca15..083a3cd 100644 --- a/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions1.java +++ b/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions1.java @@ -92,6 +92,8 @@ public class Decimal${aggrtype.className}Functions { if (outputScale.value == Integer.MIN_VALUE) { outputScale.value = in.scale; } + org.apache.drill.exec.util.DecimalUtility.checkValueOverflow((java.math.BigDecimal) value.obj, + org.apache.drill.exec.planner.types.DrillRelDataTypeSystem.DRILL_REL_DATATYPE_SYSTEM.getMaxNumericPrecision(), outputScale.value); <#if type.inputType?starts_with("Nullable")> } // end of sout block </#if> @@ -102,8 +104,7 @@ public class Decimal${aggrtype.className}Functions { if (nonNullCount.value > 0) { out.isSet = 1; out.start = 0; - out.scale = Math.min(outputScale.value, - org.apache.drill.exec.planner.types.DrillRelDataTypeSystem.DRILL_REL_DATATYPE_SYSTEM.getMaxNumericScale()); + out.scale = outputScale.value; out.precision = org.apache.drill.exec.planner.types.DrillRelDataTypeSystem.DRILL_REL_DATATYPE_SYSTEM.getMaxNumericPrecision(); value.obj = ((java.math.BigDecimal) value.obj).setScale(out.scale, java.math.BigDecimal.ROUND_HALF_UP); diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions3.java b/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions3.java index 3058381..211bab9 100644 --- a/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions3.java +++ b/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions3.java @@ -155,6 +155,7 @@ public class Decimal${aggrtype.className}Functions { result = result.setScale(out.scale, java.math.RoundingMode.HALF_UP); out.start = 0; out.precision = org.apache.drill.exec.planner.types.DrillRelDataTypeSystem.DRILL_REL_DATATYPE_SYSTEM.getMaxNumericPrecision(); + org.apache.drill.exec.util.DecimalUtility.checkValueOverflow(result, out.precision, out.scale); byte[] bytes = result.unscaledValue().toByteArray(); int len = bytes.length; out.buffer = buffer.reallocIfNeeded(len); diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/DecimalFunctions.java b/exec/java-exec/src/main/codegen/templates/Decimal/DecimalFunctions.java index da18cb1..9b055f1 100644 --- a/exec/java-exec/src/main/codegen/templates/Decimal/DecimalFunctions.java +++ b/exec/java-exec/src/main/codegen/templates/Decimal/DecimalFunctions.java @@ -183,6 +183,8 @@ public class ${type.name}Functions { new java.math.MathContext(result.precision, java.math.RoundingMode.HALF_UP)) .setScale(result.scale, java.math.BigDecimal.ROUND_HALF_UP); + org.apache.drill.exec.util.DecimalUtility.checkValueOverflow(opResult, result.precision, result.scale); + byte[] bytes = opResult.unscaledValue().toByteArray(); int len = bytes.length; result.buffer = buffer.reallocIfNeeded(len); @@ -285,7 +287,7 @@ public class ${type.name}Functions { public void eval() { result.start = 0; - result.scale = right.value; + result.scale = Math.max(right.value, 0); result.precision = left.precision; java.math.BigDecimal opResult = org.apache.drill.exec.util.DecimalUtility @@ -313,7 +315,7 @@ public class ${type.name}Functions { } public void eval() { - result.scale = right.value; + result.scale = Math.max(right.value, 0); result.precision = left.precision; result.start = 0; java.math.BigDecimal bd = diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/output/DecimalReturnTypeInference.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/output/DecimalReturnTypeInference.java index 442514f..b30703d 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/output/DecimalReturnTypeInference.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/output/DecimalReturnTypeInference.java @@ -277,7 +277,7 @@ public class DecimalReturnTypeInference { return TypeProtos.MajorType.newBuilder() .setMinorType(attributes.getReturnValue().getType().getMinorType()) - .setScale(scale) + .setScale(Math.max(scale, 0)) .setPrecision(precision) .setMode(mode) .build(); diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionAddFunction.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionAddFunction.java index 138f97f..db00c51 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionAddFunction.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionAddFunction.java @@ -31,6 +31,6 @@ public class DecimalScalePrecisionAddFunction extends DrillBaseComputeScalePreci outputPrecision = (outputScale + maxResultIntegerDigits); - checkPrecisionRange(); + adjustScaleAndPrecision(); } } diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionDivideFunction.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionDivideFunction.java index eb79d44..af04f2b 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionDivideFunction.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionDivideFunction.java @@ -34,5 +34,6 @@ public class DecimalScalePrecisionDivideFunction extends DrillBaseComputeScalePr outputScale = Math.min(outputScale, MAX_NUMERIC_PRECISION - maxResultIntegerDigits); outputScale = Math.min(outputScale, DRILL_REL_DATATYPE_SYSTEM.getMaxNumericScale()); outputPrecision = maxResultIntegerDigits + outputScale; + adjustScaleAndPrecision(); } } diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionModFunction.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionModFunction.java index 6901580..9508f3d 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionModFunction.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionModFunction.java @@ -38,7 +38,7 @@ public class DecimalScalePrecisionModFunction extends DrillBaseComputeScalePreci outputScale = outputPrecision - leftIntegerDigits; } - // Output precision should atleast be greater or equal to the input precision - outputPrecision = Math.max(outputPrecision, Math.max(leftPrecision, rightPrecision)); + // Output precision should at least be greater or equal to the input precision + outputPrecision = Math.min(outputPrecision, Math.max(leftPrecision, rightPrecision)); } } diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionMulFunction.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionMulFunction.java index 2a8b22b..6cc5537 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionMulFunction.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionMulFunction.java @@ -32,10 +32,9 @@ public class DecimalScalePrecisionMulFunction extends DrillBaseComputeScalePreci public void computeScalePrecision(int leftPrecision, int leftScale, int rightPrecision, int rightScale) { // compute the output scale and precision here outputScale = leftScale + rightScale; - outputPrecision = leftPrecision + rightPrecision; - checkPrecisionRange(); + adjustScaleAndPrecision(); } } diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DrillBaseComputeScalePrecision.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DrillBaseComputeScalePrecision.java index 1c3c186..af671e0 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DrillBaseComputeScalePrecision.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DrillBaseComputeScalePrecision.java @@ -17,9 +17,14 @@ */ package org.apache.drill.exec.planner.types.decimal; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import static org.apache.drill.exec.planner.types.DrillRelDataTypeSystem.DRILL_REL_DATATYPE_SYSTEM; public abstract class DrillBaseComputeScalePrecision { + private static final Logger logger = LoggerFactory.getLogger(DrillBaseComputeScalePrecision.class); + protected final static int MAX_NUMERIC_PRECISION = DRILL_REL_DATATYPE_SYSTEM.getMaxNumericPrecision(); protected int outputScale = 0; @@ -43,10 +48,16 @@ public abstract class DrillBaseComputeScalePrecision { * Cuts down the fractional part if the current precision * exceeds the maximum precision range. */ - protected void checkPrecisionRange() { + protected void adjustScaleAndPrecision() { if (outputPrecision > MAX_NUMERIC_PRECISION) { outputScale = outputScale - (outputPrecision - MAX_NUMERIC_PRECISION); outputPrecision = MAX_NUMERIC_PRECISION; } + if (outputScale < 0) { + logger.warn("Resulting precision: {} may overflow max allowed precision: {}.\n" + + "Forced setting max allowed precision and 0 scale.", + MAX_NUMERIC_PRECISION - outputScale, MAX_NUMERIC_PRECISION); + outputScale = 0; + } } } diff --git a/exec/java-exec/src/test/java/org/apache/drill/TestFunctionsQuery.java b/exec/java-exec/src/test/java/org/apache/drill/TestFunctionsQuery.java index 390a6bf..719df6f 100644 --- a/exec/java-exec/src/test/java/org/apache/drill/TestFunctionsQuery.java +++ b/exec/java-exec/src/test/java/org/apache/drill/TestFunctionsQuery.java @@ -26,13 +26,17 @@ import java.time.LocalDateTime; import java.time.ZoneOffset; import org.apache.drill.categories.SqlFunctionTest; +import org.apache.drill.common.exceptions.UserRemoteException; import org.apache.drill.exec.planner.physical.PlannerSettings; import org.apache.drill.test.BaseTestQuery; +import org.hamcrest.CoreMatchers; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; +import org.junit.rules.ExpectedException; @Category(SqlFunctionTest.class) public class TestFunctionsQuery extends BaseTestQuery { @@ -48,6 +52,9 @@ public class TestFunctionsQuery extends BaseTestQuery { resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY); } + @Rule + public ExpectedException expectedException = ExpectedException.none(); + @Test public void testAbsDecimalFunction() throws Exception{ String query = "SELECT " + @@ -58,16 +65,18 @@ public class TestFunctionsQuery extends BaseTestQuery { "abs(cast('12345678912345678912.4567' as decimal(28, 5))) DEC28_ABS_1, " + "abs(cast('-12345678912345678912.4567' as decimal(28, 5))) DEC28_ABS_2, " + "abs(cast('1234567891234567891234567891234567891.4' as decimal(38, 1))) DEC38_ABS_1, " + - "abs(cast('-1234567891234567891234567891234567891.4' as decimal(38, 1))) DEC38_ABS_2 " + - "FROM cp.`tpch/region.parquet` limit 1"; + "abs(cast('-1234567891234567891234567891234567891.4' as decimal(38, 1))) DEC38_ABS_2"; testBuilder() .sqlQuery(query) .unOrdered() - .baselineColumns("DEC9_ABS_1", "DEC9_ABS_2", "DEC18_ABS_1", "DEC18_ABS_2", "DEC28_ABS_1", "DEC28_ABS_2", "DEC38_ABS_1", "DEC38_ABS_2") - .baselineValues(new BigDecimal("1234.45670"), new BigDecimal("1234.45670"), new BigDecimal("99999912399.45670"), new BigDecimal("99999912399.45670"), - new BigDecimal("12345678912345678912.45670"), new BigDecimal("12345678912345678912.45670"), new BigDecimal("1234567891234567891234567891234567891.4"), - new BigDecimal("1234567891234567891234567891234567891.4")) + .baselineColumns("DEC9_ABS_1", "DEC9_ABS_2", "DEC18_ABS_1", "DEC18_ABS_2", "DEC28_ABS_1", "DEC28_ABS_2", + "DEC38_ABS_1", "DEC38_ABS_2") + .baselineValues(new BigDecimal("1234.45670"), new BigDecimal("1234.45670"), + new BigDecimal("99999912399.45670"), new BigDecimal("99999912399.45670"), + new BigDecimal("12345678912345678912.45670"), new BigDecimal("12345678912345678912.45670"), + new BigDecimal("1234567891234567891234567891234567891.4"), + new BigDecimal("1234567891234567891234567891234567891.4")) .go(); } @@ -92,20 +101,23 @@ public class TestFunctionsQuery extends BaseTestQuery { "ceil(cast('999999999999999999999999999999999999.4' as decimal(38, 1))) DEC38_2, " + "ceil(cast('1234567891234567891234567891234567891.0' as decimal(38, 1))) DEC38_3, " + "ceil(cast('-1234567891234567891234567891234567891.4' as decimal(38, 1))) DEC38_4, " + - "ceil(cast('-1234567891234567891234567891234567891.0' as decimal(38, 1))) DEC38_5 " + - "FROM cp.`tpch/region.parquet` limit 1"; + "ceil(cast('-1234567891234567891234567891234567891.0' as decimal(38, 1))) DEC38_5"; testBuilder() .sqlQuery(query) .unOrdered() .baselineColumns("DEC9_1", "DEC9_2", "DEC9_3", "DEC9_4", "DEC18_1", "DEC18_2", "DEC18_3", "DEC18_4", "DEC28_1", "DEC28_2", "DEC28_3", "DEC28_4", "DEC28_5", "DEC38_1", "DEC38_2", "DEC38_3", "DEC38_4", "DEC38_5") - .baselineValues(new BigDecimal("1235"), new BigDecimal("1234"), new BigDecimal("-1234"), new BigDecimal("-1234"), - new BigDecimal("99999912400"), new BigDecimal("99999912399"), new BigDecimal("-99999912399"), new BigDecimal("-99999912399"), - new BigDecimal("12345678912345678913"), new BigDecimal("1000000000000000000"), new BigDecimal("12345678912345678912"), new BigDecimal("-12345678912345678912"), - new BigDecimal("-12345678912345678912"), new BigDecimal("1234567891234567891234567891234567892"), new BigDecimal("1000000000000000000000000000000000000"), - new BigDecimal("1234567891234567891234567891234567891"), new BigDecimal("-1234567891234567891234567891234567891"), - new BigDecimal("-1234567891234567891234567891234567891")) + .baselineValues(new BigDecimal("1235"), new BigDecimal("1234"), new BigDecimal("-1234"), + new BigDecimal("-1234"), new BigDecimal("99999912400"), new BigDecimal("99999912399"), + new BigDecimal("-99999912399"), new BigDecimal("-99999912399"), + new BigDecimal("12345678912345678913"), new BigDecimal("1000000000000000000"), + new BigDecimal("12345678912345678912"), new BigDecimal("-12345678912345678912"), + new BigDecimal("-12345678912345678912"), new BigDecimal("1234567891234567891234567891234567892"), + new BigDecimal("1000000000000000000000000000000000000"), + new BigDecimal("1234567891234567891234567891234567891"), + new BigDecimal("-1234567891234567891234567891234567891"), + new BigDecimal("-1234567891234567891234567891234567891")) .go(); } @@ -129,20 +141,23 @@ public class TestFunctionsQuery extends BaseTestQuery { "floor(cast('999999999999999999999999999999999999.4' as decimal(38, 1))) DEC38_2, " + "floor(cast('1234567891234567891234567891234567891.0' as decimal(38, 1))) DEC38_3, " + "floor(cast('-1234567891234567891234567891234567891.4' as decimal(38, 1))) DEC38_4, " + - "floor(cast('-999999999999999999999999999999999999.4' as decimal(38, 1))) DEC38_5 " + - "FROM cp.`tpch/region.parquet` limit 1"; + "floor(cast('-999999999999999999999999999999999999.4' as decimal(38, 1))) DEC38_5"; testBuilder() .sqlQuery(query) .unOrdered() .baselineColumns("DEC9_1", "DEC9_2", "DEC9_3", "DEC9_4", "DEC18_1", "DEC18_2", "DEC18_3", "DEC18_4", "DEC28_1", "DEC28_2", "DEC28_3", "DEC28_4", "DEC28_5", "DEC38_1", "DEC38_2", "DEC38_3", "DEC38_4", "DEC38_5") - .baselineValues(new BigDecimal("1234"), new BigDecimal("1234"), new BigDecimal("-1235"), new BigDecimal("-1234"), - new BigDecimal("99999912399"), new BigDecimal("99999912399"), new BigDecimal("-99999912400"), new BigDecimal("-99999912399"), - new BigDecimal("12345678912345678912"), new BigDecimal("999999999999999999"), new BigDecimal("12345678912345678912"), - new BigDecimal("-12345678912345678913"), new BigDecimal("-12345678912345678912"), new BigDecimal("1234567891234567891234567891234567891"), - new BigDecimal("999999999999999999999999999999999999"), new BigDecimal("1234567891234567891234567891234567891"), - new BigDecimal("-1234567891234567891234567891234567892"), new BigDecimal("-1000000000000000000000000000000000000")) + .baselineValues(new BigDecimal("1234"), new BigDecimal("1234"), new BigDecimal("-1235"), + new BigDecimal("-1234"), new BigDecimal("99999912399"), new BigDecimal("99999912399"), + new BigDecimal("-99999912400"), new BigDecimal("-99999912399"), + new BigDecimal("12345678912345678912"), new BigDecimal("999999999999999999"), + new BigDecimal("12345678912345678912"), new BigDecimal("-12345678912345678913"), + new BigDecimal("-12345678912345678912"), new BigDecimal("1234567891234567891234567891234567891"), + new BigDecimal("999999999999999999999999999999999999"), + new BigDecimal("1234567891234567891234567891234567891"), + new BigDecimal("-1234567891234567891234567891234567892"), + new BigDecimal("-1000000000000000000000000000000000000")) .go(); } @@ -166,21 +181,23 @@ public class TestFunctionsQuery extends BaseTestQuery { "trunc(cast('999999999999999999999999999999999999.4' as decimal(38, 1))) DEC38_2, " + "trunc(cast('1234567891234567891234567891234567891.0' as decimal(38, 1))) DEC38_3, " + "trunc(cast('-1234567891234567891234567891234567891.4' as decimal(38, 1))) DEC38_4, " + - "trunc(cast('-999999999999999999999999999999999999.4' as decimal(38, 1))) DEC38_5 " + - "FROM cp.`tpch/region.parquet` limit 1"; + "trunc(cast('-999999999999999999999999999999999999.4' as decimal(38, 1))) DEC38_5"; testBuilder() .sqlQuery(query) .unOrdered() .baselineColumns("DEC9_1", "DEC9_2", "DEC9_3", "DEC9_4", "DEC18_1", "DEC18_2", "DEC18_3", "DEC18_4", "DEC28_1", "DEC28_2", "DEC28_3", "DEC28_4", "DEC28_5", "DEC38_1", "DEC38_2", "DEC38_3", "DEC38_4", "DEC38_5") - .baselineValues(new BigDecimal("1234"), new BigDecimal("1234"), new BigDecimal("-1234"), new BigDecimal("0"), - new BigDecimal("99999912399"), new BigDecimal("99999912399"), new BigDecimal("-99999912399"), - new BigDecimal("-99999912399"), new BigDecimal("12345678912345678912"), new BigDecimal("999999999999999999"), - new BigDecimal("12345678912345678912"), new BigDecimal("-12345678912345678912"), new BigDecimal("-12345678912345678912"), - new BigDecimal("1234567891234567891234567891234567891"), new BigDecimal("999999999999999999999999999999999999"), - new BigDecimal("1234567891234567891234567891234567891"), new BigDecimal("-1234567891234567891234567891234567891"), - new BigDecimal("-999999999999999999999999999999999999")) + .baselineValues(new BigDecimal("1234"), new BigDecimal("1234"), new BigDecimal("-1234"), + new BigDecimal("0"), new BigDecimal("99999912399"), new BigDecimal("99999912399"), + new BigDecimal("-99999912399"), new BigDecimal("-99999912399"), + new BigDecimal("12345678912345678912"), new BigDecimal("999999999999999999"), + new BigDecimal("12345678912345678912"), new BigDecimal("-12345678912345678912"), + new BigDecimal("-12345678912345678912"), new BigDecimal("1234567891234567891234567891234567891"), + new BigDecimal("999999999999999999999999999999999999"), + new BigDecimal("1234567891234567891234567891234567891"), + new BigDecimal("-1234567891234567891234567891234567891"), + new BigDecimal("-999999999999999999999999999999999999")) .go(); } @@ -204,20 +221,22 @@ public class TestFunctionsQuery extends BaseTestQuery { "trunc(cast('999999999.4' as decimal(38, 1)), 8) DEC38_2, " + "trunc(cast('999999999.1234' as decimal(38, 4)), 12) DEC38_3, " + "trunc(cast('-123456789123456789.4' as decimal(38, 1)), 10) DEC38_4, " + - "trunc(cast('-999999999999999999999999999999999999.4' as decimal(38, 1)), 1) DEC38_5 " + - "FROM cp.`tpch/region.parquet` limit 1"; + "trunc(cast('-999999999999999999999999999999999999.4' as decimal(38, 1)), 1) DEC38_5"; testBuilder() .sqlQuery(query) .unOrdered() .baselineColumns("DEC9_1", "DEC9_2", "DEC9_3", "DEC9_4", "DEC18_1", "DEC18_2", "DEC18_3", "DEC18_4", "DEC28_1", "DEC28_2", "DEC28_3", "DEC28_4", "DEC28_5", "DEC38_1", "DEC38_2", "DEC38_3", "DEC38_4", "DEC38_5") - .baselineValues(new BigDecimal("1234.45"), new BigDecimal("1234.4500"), new BigDecimal("-1234"), new BigDecimal("0.11"), - new BigDecimal("99999912399.45"), new BigDecimal("99999912399.00"), new BigDecimal("-99999912399.450000"), - new BigDecimal("-99999912399.0000"), new BigDecimal("12345678912345678912.4"), new BigDecimal("999999999999999999.456000"), - new BigDecimal("12345678912345678912.00"), new BigDecimal("-12345678912345678912"), new BigDecimal("-12345678912345678912.0"), - new BigDecimal("999999999.1234567"), new BigDecimal("999999999.40000000"), new BigDecimal("999999999.123400000000"), - new BigDecimal("-123456789123456789.4000000000"), new BigDecimal("-999999999999999999999999999999999999.4")) + .baselineValues(new BigDecimal("1234.45"), new BigDecimal("1234.4500"), new BigDecimal("-1234"), + new BigDecimal("0.11"), new BigDecimal("99999912399.45"), new BigDecimal("99999912399.00"), + new BigDecimal("-99999912399.450000"), new BigDecimal("-99999912399.0000"), + new BigDecimal("12345678912345678912.4"), new BigDecimal("999999999999999999.456000"), + new BigDecimal("12345678912345678912.00"), new BigDecimal("-12345678912345678912"), + new BigDecimal("-12345678912345678912.0"), new BigDecimal("999999999.1234567"), + new BigDecimal("999999999.40000000"), new BigDecimal("999999999.123400000000"), + new BigDecimal("-123456789123456789.4000000000"), + new BigDecimal("-999999999999999999999999999999999999.4")) .go(); } @@ -242,20 +261,23 @@ public class TestFunctionsQuery extends BaseTestQuery { "round(cast('999999999999999999999999999999999999.5' as decimal(38, 1))) DEC38_3, " + "round(cast('1234567891234567891234567891234567891.2' as decimal(38, 1))) DEC38_4, " + "round(cast('-1234567891234567891234567891234567891.4' as decimal(38, 1))) DEC38_5, " + - "round(cast('-999999999999999999999999999999999999.9' as decimal(38, 1))) DEC38_6 " + - "FROM cp.`tpch/region.parquet` limit 1"; + "round(cast('-999999999999999999999999999999999999.9' as decimal(38, 1))) DEC38_6"; testBuilder() .sqlQuery(query) .unOrdered() .baselineColumns("DEC9_1", "DEC9_2", "DEC9_3", "DEC9_4", "DEC18_1", "DEC18_2", "DEC18_3", "DEC18_4", "DEC28_1", "DEC28_2", "DEC28_3", "DEC28_4", "DEC28_5", "DEC38_1", "DEC38_2", "DEC38_3", "DEC38_4", "DEC38_5", "DEC38_6") - .baselineValues(new BigDecimal("1235"), new BigDecimal("1234"), new BigDecimal("-1235"), new BigDecimal("-1234"), - new BigDecimal("99999912400"), new BigDecimal("99999912399"), new BigDecimal("-99999912400"), new BigDecimal("-99999912399"), - new BigDecimal("12345678912345678913"), new BigDecimal("1000000000000000000"), new BigDecimal("12345678912345678912"), - new BigDecimal("-12345678912345678913"), new BigDecimal("-12345678912345678912"), new BigDecimal("1000000000000000000000000000"), - new BigDecimal("100000000"), new BigDecimal("1000000000000000000000000000000000000"), new BigDecimal("1234567891234567891234567891234567891"), - new BigDecimal("-1234567891234567891234567891234567891"), new BigDecimal("-1000000000000000000000000000000000000")) + .baselineValues(new BigDecimal("1235"), new BigDecimal("1234"), new BigDecimal("-1235"), + new BigDecimal("-1234"), new BigDecimal("99999912400"), new BigDecimal("99999912399"), + new BigDecimal("-99999912400"), new BigDecimal("-99999912399"), + new BigDecimal("12345678912345678913"), new BigDecimal("1000000000000000000"), + new BigDecimal("12345678912345678912"), new BigDecimal("-12345678912345678913"), + new BigDecimal("-12345678912345678912"), new BigDecimal("1000000000000000000000000000"), + new BigDecimal("100000000"), new BigDecimal("1000000000000000000000000000000000000"), + new BigDecimal("1234567891234567891234567891234567891"), + new BigDecimal("-1234567891234567891234567891234567891"), + new BigDecimal("-1000000000000000000000000000000000000")) .go(); } @@ -283,20 +305,24 @@ public class TestFunctionsQuery extends BaseTestQuery { "round(cast('999999999.9999999995678' as decimal(38, 18)), 11) DEC38_4, " + "round(cast('999999999.9999999995678' as decimal(38, 18)), 21) DEC38_5, " + "round(cast('-1234567891234567891234567891234567891.4' as decimal(38, 1)), 1) DEC38_6, " + - "round(cast('-999999999999999999999999999999999999.9' as decimal(38, 1)), 0) DEC38_7 " + - "FROM cp.`tpch/region.parquet` limit 1"; + "round(cast('-999999999999999999999999999999999999.9' as decimal(38, 1)), 0) DEC38_7"; testBuilder() .sqlQuery(query) .unOrdered() - .baselineColumns("DEC9_1", "DEC9_2", "DEC9_3", "DEC9_4", "DEC9_5", "DEC18_1", "DEC18_2", "DEC18_3", "DEC18_4", "DEC28_1", - "DEC28_2", "DEC28_3", "DEC28_4", "DEC28_5", "DEC38_1", "DEC38_2", "DEC38_3", "DEC38_4", "DEC38_5", "DEC38_6", "DEC38_7") - .baselineValues(new BigDecimal("1234.557"), new BigDecimal("1234.10"), new BigDecimal("-1234.5567"), new BigDecimal("-1234.123"), - new BigDecimal("-1234.1200"), new BigDecimal("99999912399.957"), new BigDecimal("99999912399.00"), new BigDecimal("-99999912399.56"), - new BigDecimal("-99999912399"), new BigDecimal("12345678912345678912.56"), new BigDecimal("999999999999999999.6"), - new BigDecimal("12345678912345678912.00000000"), new BigDecimal("-12345678912345678912.557"), new BigDecimal("-12345678912345678912"), - new BigDecimal("999999999999999999999999999.5"), new BigDecimal("99999999.512345679"), new BigDecimal("1000000000.000000000"), - new BigDecimal("999999999.99999999957"), new BigDecimal("999999999.999999999567800000000"), new BigDecimal("-1234567891234567891234567891234567891.4"), - new BigDecimal("-1000000000000000000000000000000000000")) + .baselineColumns("DEC9_1", "DEC9_2", "DEC9_3", "DEC9_4", "DEC9_5", "DEC18_1", "DEC18_2", "DEC18_3", "DEC18_4", + "DEC28_1", "DEC28_2", "DEC28_3", "DEC28_4", "DEC28_5", "DEC38_1", "DEC38_2", "DEC38_3", "DEC38_4", "DEC38_5", + "DEC38_6", "DEC38_7") + .baselineValues(new BigDecimal("1234.557"), new BigDecimal("1234.10"), new BigDecimal("-1234.5567"), + new BigDecimal("-1234.123"), new BigDecimal("-1234.1200"), new BigDecimal("99999912399.957"), + new BigDecimal("99999912399.00"), new BigDecimal("-99999912399.56"), + new BigDecimal("-99999912399"), new BigDecimal("12345678912345678912.56"), + new BigDecimal("999999999999999999.6"), new BigDecimal("12345678912345678912.00000000"), + new BigDecimal("-12345678912345678912.557"), new BigDecimal("-12345678912345678912"), + new BigDecimal("999999999999999999999999999.5"), new BigDecimal("99999999.512345679"), + new BigDecimal("1000000000.000000000"), new BigDecimal("999999999.99999999957"), + new BigDecimal("999999999.999999999567800000000"), + new BigDecimal("-1234567891234567891234567891234567891.4"), + new BigDecimal("-1000000000000000000000000000000000000")) .go(); } @@ -305,8 +331,7 @@ public class TestFunctionsQuery extends BaseTestQuery { public void testCastDecimalDivide() throws Exception { String query = "select (cast('9' as decimal(9, 1)) / cast('2' as decimal(4, 1))) as DEC9_DIV, " + "cast('999999999' as decimal(9,0)) / cast('0.000000000000000000000000001' as decimal(28,28)) as DEC38_DIV, " + - "cast('123456789.123456789' as decimal(18, 9)) * cast('123456789.123456789' as decimal(18, 9)) as DEC18_MUL " + - "from cp.`employee.json` where employee_id = 1"; + "cast('123456789.123456789' as decimal(18, 9)) * cast('123456789.123456789' as decimal(18, 9)) as DEC18_MUL"; testBuilder() .sqlQuery(query) @@ -327,44 +352,40 @@ public class TestFunctionsQuery extends BaseTestQuery { @Test public void testLiteralCastToFLOATYieldsFLOAT() throws Exception { testBuilder() - .sqlQuery( "SELECT CAST( 1.5 AS FLOAT ) AS ShouldBeFLOAT " - + "FROM cp.`employee.json` LIMIT 1" ) + .sqlQuery( "SELECT CAST( 1.5 AS FLOAT ) AS ShouldBeFLOAT") .unOrdered() .baselineColumns("ShouldBeFLOAT") - .baselineValues(Float.valueOf(1.5f)) + .baselineValues(1.5f) .go(); } @Test public void testLiteralCastToDOUBLEYieldsDOUBLE() throws Exception { testBuilder() - .sqlQuery( "SELECT CAST( 1.25 AS DOUBLE PRECISION ) AS ShouldBeDOUBLE " - + "FROM cp.`employee.json` LIMIT 1" ) + .sqlQuery( "SELECT CAST( 1.25 AS DOUBLE PRECISION ) AS ShouldBeDOUBLE") .unOrdered() .baselineColumns("ShouldBeDOUBLE") - .baselineValues(Double.valueOf(1.25)) + .baselineValues(1.25) .go(); } @Test public void testLiteralCastToBIGINTYieldsBIGINT() throws Exception { testBuilder() - .sqlQuery( "SELECT CAST( 64 AS BIGINT ) AS ShouldBeBIGINT " - + "FROM cp.`employee.json` LIMIT 1" ) + .sqlQuery( "SELECT CAST( 64 AS BIGINT ) AS ShouldBeBIGINT") .unOrdered() .baselineColumns("ShouldBeBIGINT") - .baselineValues(Long.valueOf(64)) + .baselineValues(64L) .go(); } @Test public void testLiteralCastToINTEGERYieldsINTEGER() throws Exception { testBuilder() - .sqlQuery( "SELECT CAST( 32 AS INTEGER ) AS ShouldBeINTEGER " - + "FROM cp.`employee.json` LIMIT 1" ) + .sqlQuery( "SELECT CAST( 32 AS INTEGER ) AS ShouldBeINTEGER") .unOrdered() .baselineColumns("ShouldBeINTEGER") - .baselineValues(Integer.valueOf(32)) + .baselineValues(32) .go(); } @@ -372,11 +393,10 @@ public class TestFunctionsQuery extends BaseTestQuery { @Test public void testLiteralCastToSMALLINTYieldsSMALLINT() throws Exception { testBuilder() - .sqlQuery( "SELECT CAST( 16 AS SMALLINT ) AS ShouldBeSMALLINT " - + "FROM cp.`employee.json` LIMIT 1" ) + .sqlQuery( "SELECT CAST( 16 AS SMALLINT ) AS ShouldBeSMALLINT") .unOrdered() .baselineColumns("ShouldBeSMALLINT") - .baselineValues(Short.valueOf((short) 16)) + .baselineValues((short) 16) .go(); } @@ -384,14 +404,21 @@ public class TestFunctionsQuery extends BaseTestQuery { @Test public void testLiteralCastToTINYINTYieldsTINYINT() throws Exception { testBuilder() - .sqlQuery( "SELECT CAST( 8 AS TINYINT ) AS ShouldBeTINYINT " - + "FROM cp.`employee.json` LIMIT 1" ) + .sqlQuery( "SELECT CAST( 8 AS TINYINT ) AS ShouldBeTINYINT") .unOrdered() .baselineColumns("ShouldBeTINYINT") - .baselineValues(Byte.valueOf((byte) 8)) + .baselineValues((byte) 8) .go(); } + @Test + public void testDecimalMultiplicationOverflowNegativeScale() throws Exception { + String query = "select cast('1000000000000000001.000000000000000000' as decimal(38, 18)) * " + + "cast('99999999999999999999.999999999999999999' as decimal(38, 18)) as DEC38_1"; + expectedException.expect(UserRemoteException.class); + expectedException.expectMessage(CoreMatchers.containsString("VALIDATION ERROR: Value 100000000000000000100000000000000000000 overflows specified precision 38 with scale 0.")); + test(query); + } @Test public void testDecimalMultiplicationOverflowHandling() throws Exception { @@ -404,7 +431,7 @@ public class TestFunctionsQuery extends BaseTestQuery { .sqlQuery(query) .unOrdered() .baselineColumns("DEC38_1", "DEC38_2", "DEC38_3") - .baselineValues(new BigDecimal("1000000000000000000000000000.00000"), new BigDecimal("1.0000000000000000E+18"), new BigDecimal("1000000000.000000000000000000")) + .baselineValues(new BigDecimal("1000000000000000000000000000.00000"), new BigDecimal("1000000000000000000"), new BigDecimal("1000000000.000000000000000000")) .go(); } @@ -414,15 +441,16 @@ public class TestFunctionsQuery extends BaseTestQuery { "cast('999999999999999999.9999999999999999994' as decimal(38, 18)) as DEC38_2, " + "cast('999999999999999999.1234567895' as decimal(38, 9)) as DEC38_3, " + "cast('99999.12345' as decimal(18, 4)) as DEC18_1, " + - "cast('99999.99995' as decimal(18, 4)) as DEC18_2 " + - "from cp.`employee.json` where employee_id = 1"; + "cast('99999.99995' as decimal(18, 4)) as DEC18_2"; testBuilder() .sqlQuery(query) .unOrdered() .baselineColumns("DEC38_1", "DEC38_2", "DEC38_3", "DEC18_1", "DEC18_2") - .baselineValues(new BigDecimal("1000000000000000000.000000000000000000"), new BigDecimal("999999999999999999.999999999999999999"), - new BigDecimal("999999999999999999.123456790"), new BigDecimal("99999.1235"), new BigDecimal("100000.0000")) + .baselineValues(new BigDecimal("1000000000000000000.000000000000000000"), + new BigDecimal("999999999999999999.999999999999999999"), + new BigDecimal("999999999999999999.123456790"), new BigDecimal("99999.1235"), + new BigDecimal("100000.0000")) .go(); } @@ -434,14 +462,15 @@ public class TestFunctionsQuery extends BaseTestQuery { "cast((cast('99999999.6789' as decimal(38, 4))) as decimal(9, 0)) as DEC38_DEC19_1, " + "cast((cast('-999999999999999.6789' as decimal(38, 4))) as decimal(18, 2)) as DEC38_DEC18_1, " + "cast((cast('-999999999999999.6789' as decimal(38, 4))) as decimal(18, 0)) as DEC38_DEC18_2, " + - "cast((cast('100000000999999999.6789' as decimal(38, 4))) as decimal(28, 0)) as DEC38_DEC28_1 " + - "from cp.`employee.json` where employee_id = 1"; + "cast((cast('100000000999999999.6789' as decimal(38, 4))) as decimal(28, 0)) as DEC38_DEC28_1"; testBuilder() .sqlQuery(query) .unOrdered() - .baselineColumns("DEC18_DEC9_1", "DEC18_DEC9_2", "DEC18_DEC9_3", "DEC38_DEC19_1", "DEC38_DEC18_1", "DEC38_DEC18_2", "DEC38_DEC28_1") - .baselineValues(new BigDecimal("12345.6789"), new BigDecimal("12345.68"), new BigDecimal("-12346"), new BigDecimal("100000000"), - new BigDecimal("-999999999999999.68"), new BigDecimal("-1000000000000000"), new BigDecimal("100000001000000000")) + .baselineColumns("DEC18_DEC9_1", "DEC18_DEC9_2", "DEC18_DEC9_3", "DEC38_DEC19_1", "DEC38_DEC18_1", + "DEC38_DEC18_2", "DEC38_DEC28_1") + .baselineValues(new BigDecimal("12345.6789"), new BigDecimal("12345.68"), new BigDecimal("-12346"), + new BigDecimal("100000000"), new BigDecimal("-999999999999999.68"), + new BigDecimal("-1000000000000000"), new BigDecimal("100000001000000000")) .go(); } @@ -458,15 +487,15 @@ public class TestFunctionsQuery extends BaseTestQuery { "trunc(cast('1234' as double), -4) as T_7,\n" + "trunc(cast('-1234' as double), -4) as T_8,\n" + "trunc(cast('8124674407369523212' as double), 0) as T_9,\n" + - "trunc(cast('81246744073695.395' as double), 1) as T_10\n" + - "FROM cp.`tpch/region.parquet` limit 1"; + "trunc(cast('81246744073695.395' as double), 1) as T_10\n"; testBuilder() .sqlQuery(query) .unOrdered() .baselineColumns("T_1", "T_2", "T_3", "T_4", "T_5", "T_6", "T_7", "T_8", "T_9", "T_10") - .baselineValues(Double.valueOf("1234.45"), Double.valueOf("-1234.45"), Double.valueOf("1200.0"), Double.valueOf("-1200.0"), Double.valueOf("1234.0"), - Double.valueOf("-1234.0"), Double.valueOf("0.0"), Double.valueOf("0.0"), Double.valueOf("8.1246744073695232E18"), Double.valueOf("8.12467440736953E13")) + .baselineValues(Double.valueOf("1234.45"), Double.valueOf("-1234.45"), Double.valueOf("1200.0"), + Double.valueOf("-1200.0"), Double.valueOf("1234.0"), Double.valueOf("-1234.0"), Double.valueOf("0.0"), + Double.valueOf("0.0"), Double.valueOf("8.1246744073695232E18"), Double.valueOf("8.12467440736953E13")) .go(); } @@ -483,15 +512,14 @@ public class TestFunctionsQuery extends BaseTestQuery { "round(cast('1234' as double), -4) as T_7,\n" + "round(cast('-1234' as double), -4) as T_8,\n" + "round(cast('8124674407369523212' as double), -4) as T_9,\n" + - "round(cast('81246744073695.395' as double), 1) as T_10\n" + - "FROM cp.`tpch/region.parquet` limit 1"; - + "round(cast('81246744073695.395' as double), 1) as T_10\n"; testBuilder() .sqlQuery(query) .unOrdered() .baselineColumns("T_1", "T_2", "T_3", "T_4", "T_5", "T_6", "T_7", "T_8", "T_9", "T_10") - .baselineValues(Double.valueOf("1234.46"), Double.valueOf("-1234.46"), Double.valueOf("1200.0"), Double.valueOf("-1200.0"), Double.valueOf("1234.0"), - Double.valueOf("-1234.0"), Double.valueOf("0.0"), Double.valueOf("0.0"), Double.valueOf("8.1246744073695201E18"), Double.valueOf("8.12467440736954E13")) + .baselineValues(Double.valueOf("1234.46"), Double.valueOf("-1234.46"), Double.valueOf("1200.0"), + Double.valueOf("-1200.0"), Double.valueOf("1234.0"), Double.valueOf("-1234.0"), Double.valueOf("0.0"), + Double.valueOf("0.0"), Double.valueOf("8.1246744073695201E18"), Double.valueOf("8.12467440736954E13")) .go(); } @@ -505,8 +533,8 @@ public class TestFunctionsQuery extends BaseTestQuery { "round(cast('23.45' as float)) round_float_1,\n" + "round(cast('23.55' as float)) round_float_2,\n" + "round(cast('8124674407369.2345' as double)) round_double_1,\n" + - "round(cast('8124674407369.589' as double)) round_double_2\n" + - "from cp.`tpch/region.parquet` limit 1"; + "round(cast('8124674407369.589' as double)) round_double_2\n"; + testBuilder() .sqlQuery(query) .unOrdered() @@ -523,14 +551,14 @@ public class TestFunctionsQuery extends BaseTestQuery { "to_char(cast('1234.5567' as decimal(9, 5)), '#,###.##') as DEC9_1, " + "to_char(cast('99999912399.9567' as decimal(18, 5)), '#.#####') DEC18_1, " + "to_char(cast('12345678912345678912.5567' as decimal(28, 5)), '#,###.#####') DEC28_1, " + - "to_char(cast('999999999999999999999999999.5' as decimal(38, 1)), '#.#') DEC38_1 " + - "FROM cp.`tpch/region.parquet` limit 1"; + "to_char(cast('999999999999999999999999999.5' as decimal(38, 1)), '#.#') DEC38_1"; testBuilder() .sqlQuery(query) .unOrdered() .baselineColumns("FLOAT8_1", "FLOAT8_2", "DEC9_1", "DEC18_1", "DEC28_1", "DEC38_1") - .baselineValues("1,234.56", "$1,234.50", "1,234.56", "99999912399.9567", "12,345,678,912,345,678,912.5567", "999999999999999999999999999.5") + .baselineValues("1,234.56", "$1,234.50", "1,234.56", "99999912399.9567", "12,345,678,912,345,678,912.5567", + "999999999999999999999999999.5") .go(); } @@ -551,8 +579,7 @@ public class TestFunctionsQuery extends BaseTestQuery { @Test public void testTimeStampConstant() throws Exception { String query = "SELECT " + - "timestamp '2008-2-23 12:23:23' as TS " + - "FROM cp.`tpch/region.parquet` limit 1"; + "timestamp '2008-2-23 12:23:23' as TS"; LocalDateTime date = LocalDateTime.parse("2008-02-23 12:23:23.0", formatTimeStamp); testBuilder() @@ -568,8 +595,7 @@ public class TestFunctionsQuery extends BaseTestQuery { String query = "SELECT " + "CAST(NULL AS TIME) AS t, " + "CAST(NULL AS TIMESTAMP) AS ts, " + - "CAST(NULL AS DATE) AS d " + - "FROM cp.`region.json` LIMIT 1"; + "CAST(NULL AS DATE) AS d"; testBuilder() .sqlQuery(query) .unOrdered() @@ -623,8 +649,8 @@ public class TestFunctionsQuery extends BaseTestQuery { @Test public void testSignFunction() throws Exception { - String query = "select sign(cast('1.23' as float)) as SIGN_FLOAT, sign(-1234.4567) as SIGN_DOUBLE, sign(23) as SIGN_INT " + - "from cp.`employee.json` where employee_id < 2"; + String query = "select sign(cast('1.23' as float)) as SIGN_FLOAT, sign(-1234.4567) as SIGN_DOUBLE, " + + "sign(23) as SIGN_INT"; testBuilder() .sqlQuery(query) .unOrdered() @@ -636,9 +662,9 @@ public class TestFunctionsQuery extends BaseTestQuery { @Test public void testPadFunctions() throws Exception { - String query = "select rpad(first_name, 10) as RPAD_DEF, rpad(first_name, 10, '*') as RPAD_STAR, lpad(first_name, 10) as LPAD_DEF, lpad(first_name, 10, '*') as LPAD_STAR, " + - "lpad(first_name, 2) as LPAD_TRUNC, rpad(first_name, 2) as RPAD_TRUNC " + - "from cp.`employee.json` where employee_id = 1"; + String query = "select rpad(first_name, 10) as RPAD_DEF, rpad(first_name, 10, '*') as RPAD_STAR, " + + "lpad(first_name, 10) as LPAD_DEF, lpad(first_name, 10, '*') as LPAD_STAR, lpad(first_name, 2) as LPAD_TRUNC, " + + "rpad(first_name, 2) as RPAD_TRUNC from cp.`employee.json` where employee_id = 1"; testBuilder() .sqlQuery(query) @@ -651,9 +677,9 @@ public class TestFunctionsQuery extends BaseTestQuery { @Test public void testExtractSecond() throws Exception { - String query = "select extract(second from date '2008-2-23') as DATE_EXT, extract(second from timestamp '2008-2-23 10:00:20.123') as TS_EXT, " + - "extract(second from time '10:20:30.303') as TM_EXT " + - "from cp.`employee.json` where employee_id = 1"; + String query = "select extract(second from date '2008-2-23') as DATE_EXT, " + + "extract(second from timestamp '2008-2-23 10:00:20.123') as TS_EXT, " + + "extract(second from time '10:20:30.303') as TM_EXT"; testBuilder() .sqlQuery(query) @@ -665,8 +691,7 @@ public class TestFunctionsQuery extends BaseTestQuery { @Test public void testCastDecimalDouble() throws Exception { - String query = "select cast((cast('1.0001' as decimal(18, 9))) as double) DECIMAL_DOUBLE_CAST " + - "from cp.`employee.json` where employee_id = 1"; + String query = "select cast((cast('1.0001' as decimal(18, 9))) as double) DECIMAL_DOUBLE_CAST"; testBuilder() .sqlQuery(query) @@ -678,8 +703,7 @@ public class TestFunctionsQuery extends BaseTestQuery { @Test public void testExtractSecondFromInterval() throws Exception { - String query = "select extract (second from interval '1 2:30:45.100' day to second) as EXT_INTDAY " + - "from cp.`employee.json` where employee_id = 1"; + String query = "select extract (second from interval '1 2:30:45.100' day to second) as EXT_INTDAY"; testBuilder() .sqlQuery(query) @@ -693,8 +717,7 @@ public class TestFunctionsQuery extends BaseTestQuery { public void testFunctionCaseInsensitiveNames() throws Exception { String query = "SELECT to_date('2003/07/09', 'yyyy/MM/dd') as col1, " + "TO_DATE('2003/07/09', 'yyyy/MM/dd') as col2, " + - "To_DaTe('2003/07/09', 'yyyy/MM/dd') as col3 " + - "from cp.`employee.json` LIMIT 1"; + "To_DaTe('2003/07/09', 'yyyy/MM/dd') as col3"; LocalDate date = LocalDate.parse("2003-07-09"); @@ -708,8 +731,8 @@ public class TestFunctionsQuery extends BaseTestQuery { @Test public void testDecimal18Decimal38Comparison() throws Exception { - String query = "select cast('-999999999.999999999' as decimal(18, 9)) = cast('-999999999.999999999' as decimal(38, 18)) as CMP " + - "from cp.`employee.json` where employee_id = 1"; + String query = "select cast('-999999999.999999999' as decimal(18, 9)) = cast('-999999999.999999999' as " + + "decimal(38, 18)) as CMP"; testBuilder() .sqlQuery(query) @@ -721,8 +744,7 @@ public class TestFunctionsQuery extends BaseTestQuery { @Test public void testOptiqDecimalCapping() throws Exception { - String query = "select cast('12345.678900000' as decimal(18, 9))=cast('12345.678900000' as decimal(38, 9)) as CMP " + - "from cp.`employee.json` where employee_id = 1"; + String query = "select cast('12345.678900000' as decimal(18, 9))=cast('12345.678900000' as decimal(38, 9)) as CMP"; testBuilder() .sqlQuery(query) @@ -734,8 +756,7 @@ public class TestFunctionsQuery extends BaseTestQuery { @Test public void testNegative() throws Exception { - String query = "select negative(cast(2 as bigint)) as NEG\n" + - "from cp.`employee.json` where employee_id = 1"; + String query = "select negative(cast(2 as bigint)) as NEG\n"; testBuilder() .sqlQuery(query) @@ -760,8 +781,8 @@ public class TestFunctionsQuery extends BaseTestQuery { @Test public void testToTimeStamp() throws Exception { - String query = "select to_timestamp(cast('800120400.12312' as decimal(38, 5))) as DEC38_TS, to_timestamp(200120400) as INT_TS\n" + - "from cp.`employee.json` where employee_id < 2"; + String query = "select to_timestamp(cast('800120400.12312' as decimal(38, 5))) as DEC38_TS, " + + "to_timestamp(200120400) as INT_TS\n"; LocalDateTime result1 = Instant.ofEpochMilli(800120400123L).atZone(ZoneOffset.systemDefault()).toLocalDateTime(); LocalDateTime result2 = Instant.ofEpochMilli(200120400000L).atZone(ZoneOffset.systemDefault()).toLocalDateTime(); diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestVarDecimalFunctions.java b/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestVarDecimalFunctions.java index 4087e67..68a1fb6 100644 --- a/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestVarDecimalFunctions.java +++ b/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestVarDecimalFunctions.java @@ -18,12 +18,16 @@ package org.apache.drill.exec.fn.impl; import org.apache.drill.categories.SqlFunctionTest; +import org.apache.drill.common.exceptions.UserRemoteException; import org.apache.drill.exec.planner.physical.PlannerSettings; import org.apache.drill.test.BaseTestQuery; +import org.hamcrest.CoreMatchers; import org.junit.AfterClass; import org.junit.BeforeClass; +import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; +import org.junit.rules.ExpectedException; import java.math.BigDecimal; import java.math.MathContext; @@ -42,6 +46,9 @@ public class TestVarDecimalFunctions extends BaseTestQuery { resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY); } + @Rule + public ExpectedException expectedException = ExpectedException.none(); + // Tests for math functions @Test @@ -59,9 +66,9 @@ public class TestVarDecimalFunctions extends BaseTestQuery { "cast('15.02' as DECIMAL(4, 2)) - cast('12.93' as DECIMAL(4, 2)) as s4,\n" + "cast('11.02' as DECIMAL(4, 2)) - cast('12.93' as DECIMAL(4, 2)) as s5,\n" + "cast('0' as DECIMAL(36, 2)) - cast('12.93' as DECIMAL(36, 2)) as s6,\n" + - // check trimming (negative scale) - "cast('99999999999999999999999999992345678912' as DECIMAL(38, 0))\n" + - "+ cast('32345678912345678912345678912345678912' as DECIMAL(38, 0)) as s7"; + // check trimming (digits after decimal point will be trimmed from result) + "cast('9999999999999999999999999999234567891.1' as DECIMAL(38, 1))\n" + + "+ cast('3234567891234567891234567891234567891.1' as DECIMAL(38, 1)) as s7"; testBuilder() .sqlQuery(query) .ordered() @@ -73,11 +80,24 @@ public class TestVarDecimalFunctions extends BaseTestQuery { new BigDecimal("1358024680358024680358024680358024.679"), new BigDecimal("1234567891234567891234567891234567.890"), new BigDecimal("2.09"), new BigDecimal("-1.91"), new BigDecimal("-12.93"), - new BigDecimal("1.3234567891234567891234567890469135782E+38")) + new BigDecimal("13234567891234567891234567890469135782")) .go(); } @Test + public void testDecimalAddOverflow() throws Exception { + String query = + "select\n" + + "cast('99999999999999999999999999992345678912' as DECIMAL(38, 0))\n" + + "+ cast('32345678912345678912345678912345678912' as DECIMAL(38, 0)) as s7"; + expectedException.expect(UserRemoteException.class); + expectedException.expectMessage( + CoreMatchers.containsString("VALIDATION ERROR: Value 132345678912345678912345678904691357820 " + + "overflows specified precision 38 with scale 0.")); + test(query); + } + + @Test public void testDecimalMultiply() throws Exception { String query = "select\n" + @@ -102,12 +122,24 @@ public class TestVarDecimalFunctions extends BaseTestQuery { } @Test + public void testDecimalMultiplyOverflow() throws Exception { + String query = "select\n" + + "cast('999999999999999999999999999.92345678912' as DECIMAL(38, 11))\n" + + " * cast('323456789123.45678912345678912345678912' as DECIMAL(38, 26)) as s1"; + expectedException.expect(UserRemoteException.class); + expectedException.expectMessage( + CoreMatchers.containsString("VALIDATION ERROR: Value 323456789123456789123456789098698367900 " + + "overflows specified precision 38 with scale 0.")); + test(query); + } + + @Test public void testDecimalDivide() throws Exception { String query = "select\n" + // checks trimming of scale "cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37))\n" + - "/ cast('0.00000000000000000000000000000000000001' as DECIMAL(38, 38)) as s1,\n" + + "/ cast('0.0000000000000000000000000000000000001' as DECIMAL(38, 37)) as s1,\n" + // sanitary checks "cast('1234567.89' as DECIMAL(9, 2))\n" + "/ cast('-1.789' as DECIMAL(4, 3)) as s2,\n" + @@ -118,13 +150,25 @@ public class TestVarDecimalFunctions extends BaseTestQuery { .sqlQuery(query) .ordered() .baselineColumns("s1", "s2", "s3", "s4", "s5") - .baselineValues(new BigDecimal("199999999999999999999999999992345678910"), + .baselineValues(new BigDecimal("19999999999999999999999999999234567891"), new BigDecimal("-690088.2560089"), new BigDecimal("1.0000000"), new BigDecimal("12.9312345678900"), new BigDecimal("0.000000")) .go(); } @Test + public void testDecimalDivideOverflow() throws Exception { + String query = "select\n" + + "cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37))\n" + + " / cast('0.00000000000000000000000000000000000001' as DECIMAL(38, 38)) as s1"; + expectedException.expect(UserRemoteException.class); + expectedException.expectMessage( + CoreMatchers.containsString("VALIDATION ERROR: Value 199999999999999999999999999992345678910 " + + "overflows specified precision 38 with scale 0")); + test(query); + } + + @Test public void testDecimalMod() throws Exception { String query = "select\n" +