From d363c1d884dc2f382b4e930d7fe0fc5f31d4dc7b Mon Sep 17 00:00:00 2001 From: Volodymyr Vysotskyi Date: Thu, 29 Jun 2017 15:28:05 +0000 Subject: [PATCH] DRILL-4970: Prevent changing the negative value of input holder for cast functions --- .../main/codegen/templates/CastFunctions.java | 19 +- .../templates/Decimal/CastDecimalInt.java | 14 +- .../templates/Decimal/CastDecimalVarchar.java | 11 +- .../drill/exec/fn/impl/TestCastFunctions.java | 439 +++++++++++++++++- .../resources/decimal/cast_decimal_float.json | 45 ++ .../resources/decimal/cast_decimal_int.json | 45 ++ .../resources/decimal/cast_int_decimal.json | 45 ++ .../test/resources/input_simple_decimal.json | 24 +- 8 files changed, 612 insertions(+), 30 deletions(-) create mode 100644 exec/java-exec/src/test/resources/decimal/cast_decimal_float.json create mode 100644 exec/java-exec/src/test/resources/decimal/cast_decimal_int.json create mode 100644 exec/java-exec/src/test/resources/decimal/cast_int_decimal.json diff --git a/exec/java-exec/src/main/codegen/templates/CastFunctions.java b/exec/java-exec/src/main/codegen/templates/CastFunctions.java index f68da0658c3..4a1f67f325e 100644 --- a/exec/java-exec/src/main/codegen/templates/CastFunctions.java +++ b/exec/java-exec/src/main/codegen/templates/CastFunctions.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -43,8 +43,10 @@ */ @SuppressWarnings("unused") -@FunctionTemplate(name = "cast${type.to?upper_case}", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls=NullHandling.NULL_IF_NULL) -public class Cast${type.from}${type.to} implements DrillSimpleFunc{ +@FunctionTemplate(name = "cast${type.to?upper_case}", + scope = FunctionTemplate.FunctionScope.SIMPLE, + nulls = NullHandling.NULL_IF_NULL) +public class Cast${type.from}${type.to} implements DrillSimpleFunc { @Param ${type.from}Holder in; @Output ${type.to}Holder out; @@ -53,18 +55,13 @@ public void setup() {} public void eval() { <#if (type.from.startsWith("Float") && type.to.endsWith("Int"))> - boolean sign = (in.value < 0); - in.value = java.lang.Math.abs(in.value); ${type.native} fractional = in.value % 1; int digit = ((int) (fractional * 10)); int carry = 0; - if (digit > 4) { - carry = 1; - } - out.value = ((${type.explicit}) in.value) + carry; - if (sign == true) { - out.value *= -1; + if (java.lang.Math.abs(digit) > 4) { + carry = (int) java.lang.Math.signum(digit); } + out.value = (${type.explicit}) (in.value + carry); <#elseif type.explicit??> out.value = (${type.explicit}) in.value; <#else> diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalInt.java b/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalInt.java index a13f0e7a5c6..37f35f38150 100644 --- a/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalInt.java +++ b/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalInt.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -46,7 +46,9 @@ * This class is generated using freemarker and the ${.template_name} template. */ @SuppressWarnings("unused") -@FunctionTemplate(name = "cast${type.to?upper_case}", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls=NullHandling.NULL_IF_NULL) +@FunctionTemplate(name = "cast${type.to?upper_case}", + scope = FunctionTemplate.FunctionScope.SIMPLE, + nulls = NullHandling.NULL_IF_NULL) public class Cast${type.from}${type.to} implements DrillSimpleFunc { @Param ${type.from}Holder in; @@ -57,12 +59,10 @@ public void setup() { public void eval() { - int carry = (org.apache.drill.exec.util.DecimalUtility.getFirstFractionalDigit(in.value, in.scale) > 4) ? 1 : 0; + int carry = (org.apache.drill.exec.util.DecimalUtility.getFirstFractionalDigit(in.value, in.scale) > 4) + ? (int) java.lang.Math.signum(in.value) : 0; // Assign the integer part of the decimal to the output holder - out.value = java.lang.Math.abs((${type.javatype}) (org.apache.drill.exec.util.DecimalUtility.adjustScaleDivide(in.value, (int) in.scale))) + carry; - if (in.value < 0) { - out.value *= -1; - } + out.value = (${type.javatype}) (org.apache.drill.exec.util.DecimalUtility.adjustScaleDivide(in.value, (int) in.scale) + carry); } } diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalVarchar.java b/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalVarchar.java index 239ea282da6..e4c221ee8ef 100644 --- a/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalVarchar.java +++ b/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalVarchar.java @@ -70,22 +70,23 @@ public void eval() { StringBuilder str = new StringBuilder(); - if (in.value < 0) { + ${type.javatype} value = in.value; + if (value < 0) { // Negative value, add '-' to the string str.append("-"); // Negate the number - in.value *= -1; + value *= -1; } ${type.javatype} separator = (${type.javatype}) org.apache.drill.exec.util.DecimalUtility.getPowerOfTen((int) in.scale); - str.append(in.value / separator); + str.append(value / separator); if (in.scale > 0) { str.append("."); - String fractionalPart = String.valueOf(in.value % separator); + String fractionalPart = String.valueOf(value % separator); /* Since we are taking modulus to find fractional part, * we will miss printing the leading zeroes in the fractional part @@ -101,7 +102,7 @@ public void eval() { * * We missed the initial zeroes in the fractional part. Below logic accounts for this case */ - str.append(org.apache.drill.exec.util.DecimalUtility.toStringWithZeroes((in.value % separator), in.scale)); + str.append(org.apache.drill.exec.util.DecimalUtility.toStringWithZeroes((value % separator), in.scale)); } out.buffer = buffer; diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestCastFunctions.java b/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestCastFunctions.java index 0d50dd3428c..b3a7fe91dd7 100644 --- a/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestCastFunctions.java +++ b/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestCastFunctions.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -17,11 +17,17 @@ */ package org.apache.drill.exec.fn.impl; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import org.apache.drill.BaseTestQuery; import org.apache.drill.common.util.FileUtils; import org.joda.time.DateTime; import org.junit.Test; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + public class TestCastFunctions extends BaseTestQuery { @Test @@ -78,4 +84,435 @@ public void testToDateForTimeStamp() throws Exception { .build() .run(); } + + @Test + public void testCastFloatToInt() throws Exception { + Map values = Maps.newHashMap(); + + values.put(0F, 0); + values.put(0.4F, 0); + values.put(-0.4F, 0); + values.put(0.5F, 1); + values.put(-0.5F, -1); + values.put(16777215F, 16777215); + values.put(1677721F + 0.4F, 1677721); + values.put(1677721F + 0.5F, 1677722); + values.put(-16777216F, -16777216); + values.put(-1677721 - 0.4F, -1677721); + values.put(-1677721 - 0.5F, -1677722); + values.put(Float.MAX_VALUE, Integer.MAX_VALUE); + values.put(-Float.MAX_VALUE, Integer.MIN_VALUE); + values.put(Float.MIN_VALUE, 0); + + for (float value : values.keySet()) { + try { + test("create table dfs_test.tmp.table_with_float as\n" + + "(select cast(%1$s as float) c1 from (values(1)))", value); + + testBuilder() + .sqlQuery("select cast(c1 as int) col1 from dfs_test.tmp.table_with_float") + .unOrdered() + .baselineColumns("col1") + .baselineValues(values.get(value)) + .build() + .run(); + } finally { + test("drop table if exists dfs_test.tmp.table_with_float"); + } + } + } + + @Test + public void testCastIntToFloatAndDouble() throws Exception { + List values = Lists.newArrayList(); + + values.add(0); + values.add(1); + values.add(-1); + values.add(16777215); + values.add(-16777216); + values.add(Integer.MAX_VALUE); + values.add(Integer.MIN_VALUE); + + for (int value : values) { + try { + test("create table dfs_test.tmp.table_with_int as\n" + + "(select cast(%1$s as int) c1 from (values(1)))", value); + + testBuilder() + .sqlQuery("select cast(c1 as float) col1,\n" + + "cast(c1 as double) col2\n" + + "from dfs_test.tmp.table_with_int") + .unOrdered() + .baselineColumns("col1", "col2") + .baselineValues((float) value, (double) value) + .build() + .run(); + } finally { + test("drop table if exists dfs_test.tmp.table_with_int"); + } + } + } + + @Test + public void testCastFloatToBigInt() throws Exception { + Map values = Maps.newHashMap(); + + values.put(0F, 0L); + values.put(0.4F, 0L); + values.put(-0.4F, 0L); + values.put(0.5F, 1L); + values.put(-0.5F, -1L); + values.put(16777215F, 16777215L); + values.put(1677721F + 0.4F, 1677721L); + values.put(1677721F + 0.5F, 1677722L); + values.put(-16777216F, -16777216L); + values.put(-1677721 - 0.4F, -1677721L); + values.put(-1677721 - 0.5F, -1677722L); + values.put(Float.MAX_VALUE, Long.MAX_VALUE); + values.put(Long.MIN_VALUE * 2F, Long.MIN_VALUE); + values.put(Float.MIN_VALUE, 0L); + + for (float value : values.keySet()) { + try { + test("create table dfs_test.tmp.table_with_float as\n" + + "(select cast(%1$s as float) c1 from (values(1)))", value); + + testBuilder() + .sqlQuery("select cast(c1 as bigInt) col1 from dfs_test.tmp.table_with_float") + .unOrdered() + .baselineColumns("col1") + .baselineValues(values.get(value)) + .build() + .run(); + } finally { + test("drop table if exists dfs_test.tmp.table_with_float"); + } + } + } + + @Test + public void testCastBigIntToFloatAndDouble() throws Exception { + List values = Lists.newArrayList(); + + values.add(0L); + values.add(1L); + values.add(-1L); + values.add(16777215L); + values.add(-16777216L); + values.add(9007199254740991L); + values.add(-9007199254740992L); + values.add(Long.MAX_VALUE); + values.add(Long.MIN_VALUE); + + for (long value : values) { + try { + test("create table dfs_test.tmp.table_with_bigint as\n" + + "(select cast(%1$s as bigInt) c1 from (values(1)))", value); + + testBuilder() + .sqlQuery("select cast(c1 as float) col1,\n" + + "cast(c1 as double) col2\n" + + "from dfs_test.tmp.table_with_bigint") + .unOrdered() + .baselineColumns("col1", "col2") + .baselineValues((float) value, (double) value) + .build() + .run(); + } finally { + test("drop table if exists dfs_test.tmp.table_with_bigint"); + } + } + } + + @Test + public void testCastDoubleToInt() throws Exception { + Map values = Maps.newHashMap(); + + values.put(0D, 0); + values.put(0.4, 0); + values.put(-0.4, 0); + values.put(0.5, 1); + values.put(-0.5, -1); + values.put((double) Integer.MAX_VALUE, Integer.MAX_VALUE); + values.put(Integer.MAX_VALUE + 0.4, Integer.MAX_VALUE); + values.put(Integer.MAX_VALUE + 0.5, Integer.MAX_VALUE); + values.put((double) Integer.MIN_VALUE, Integer.MIN_VALUE); + values.put(Integer.MIN_VALUE - 0.4, Integer.MIN_VALUE); + values.put(Integer.MIN_VALUE - 0.5, Integer.MIN_VALUE); + values.put(Double.MAX_VALUE, Integer.MAX_VALUE); + values.put(-Double.MAX_VALUE, Integer.MIN_VALUE); + values.put(Double.MIN_VALUE, 0); + + for (double value : values.keySet()) { + try { + test("create table dfs_test.tmp.table_with_double as\n" + + "(select cast(%1$s as double) c1 from (values(1)))", value); + + testBuilder() + .sqlQuery("select cast(c1 as int) col1 from dfs_test.tmp.table_with_double") + .unOrdered() + .baselineColumns("col1") + .baselineValues(values.get(value)) + .build() + .run(); + } finally { + test("drop table if exists dfs_test.tmp.table_with_double"); + } + } + } + + @Test + public void testCastDoubleToBigInt() throws Exception { + Map values = Maps.newHashMap(); + + values.put(0D, 0L); + values.put(0.4, 0L); + values.put(-0.4, 0L); + values.put(0.5, 1L); + values.put(-0.5, -1L); + values.put((double) Integer.MAX_VALUE, (long) Integer.MAX_VALUE); + values.put((double) 9007199254740991L, 9007199254740991L); + values.put(900719925474098L + 0.4, 900719925474098L); + values.put(900719925474098L + 0.5, 900719925474099L); + values.put((double) -9007199254740991L, -9007199254740991L); + values.put(-900719925474098L - 0.4, -900719925474098L); + values.put(-900719925474098L - 0.5, -900719925474099L); + values.put(Double.MAX_VALUE, Long.MAX_VALUE); + values.put(-Double.MAX_VALUE, Long.MIN_VALUE); + values.put(Double.MIN_VALUE, 0L); + for (double value : values.keySet()) { + try { + test("create table dfs_test.tmp.table_with_double as\n" + + "(select cast(%1$s as double) c1 from (values(1)))", value); + + testBuilder() + .sqlQuery("select cast(c1 as bigInt) col1 from dfs_test.tmp.table_with_double") + .unOrdered() + .baselineColumns("col1") + .baselineValues(values.get(value)) + .build() + .run(); + } finally { + test("drop table if exists dfs_test.tmp.table_with_double"); + } + } + } + + @Test + public void testCastIntAndBigInt() throws Exception { + List values = Lists.newArrayList(); + + values.add(0); + values.add(1); + values.add(-1); + values.add(Integer.MAX_VALUE); + values.add(Integer.MIN_VALUE); + values.add(16777215); + + for (int value : values) { + try { + test("create table dfs_test.tmp.table_with_int as\n" + + "(select cast(%1$s as int) c1, cast(%1$s as bigInt) c2 from (values(1)))", value); + + testBuilder() + .sqlQuery("select cast(c1 as bigint) col1,\n" + + "cast(c1 as int) col2\n" + + "from dfs_test.tmp.table_with_int") + .unOrdered() + .baselineColumns("col1", "col2") + .baselineValues((long) value, value) + .build() + .run(); + } finally { + test("drop table if exists dfs_test.tmp.table_with_int"); + } + } + } + + @Test + public void testCastFloatAndDouble() throws Exception { + List values = Lists.newArrayList(); + + values.add(0d); + values.add(0.4); + values.add(-0.4); + values.add(0.5); + values.add(-0.5); + values.add(16777215d); + values.add(-16777216d); + values.add((double) Float.MAX_VALUE); + values.add(Double.MAX_VALUE); + values.add((double) Float.MIN_VALUE); + values.add(Double.MIN_VALUE); + + for (double value : values) { + try { + test("create table dfs_test.tmp.table_with_float as\n" + + "(select cast(%1$s as float) c1,\n" + + "cast(%1$s as double) c2\n" + + "from (values(1)))", value); + + testBuilder() + .sqlQuery("select cast(c1 as double) col1,\n" + + "cast(c2 as float) col2\n" + + "from dfs_test.tmp.table_with_float") + .unOrdered() + .baselineColumns("col1", "col2") + .baselineValues((double) ((float) (value)), (float) value) + .build() + .run(); + } finally { + test("drop table if exists dfs_test.tmp.table_with_float"); + } + } + } + + @Test + public void testCastIntAndBigIntToDecimal() throws Exception { + try { + test("alter session set planner.enable_decimal_data_type = true"); + + testBuilder() + .physicalPlanFromFile("decimal/cast_int_decimal.json") + .unOrdered() + .baselineColumns("DEC9_INT", "DEC38_INT", "DEC9_BIGINT", "DEC38_BIGINT") + .baselineValues(new BigDecimal(0), new BigDecimal(0), new BigDecimal(0), new BigDecimal(0)) + .baselineValues(new BigDecimal(1), new BigDecimal(1), new BigDecimal(1), new BigDecimal(1)) + .baselineValues(new BigDecimal(-1), new BigDecimal(-1), new BigDecimal(-1), new BigDecimal(-1)) + + .baselineValues(new BigDecimal(Integer.MAX_VALUE), + new BigDecimal(Integer.MAX_VALUE), + new BigDecimal((int) Long.MAX_VALUE), + new BigDecimal(Long.MAX_VALUE)) + + .baselineValues(new BigDecimal(Integer.MIN_VALUE), + new BigDecimal(Integer.MIN_VALUE), + new BigDecimal((int) Long.MIN_VALUE), + new BigDecimal(Long.MIN_VALUE)) + + .baselineValues(new BigDecimal(123456789), + new BigDecimal(123456789), + new BigDecimal(123456789), + new BigDecimal(123456789)) + .build() + .run(); + } finally { + test("drop table if exists dfs_test.tmp.table_with_int"); + test("alter session reset planner.enable_decimal_data_type"); + } + } + + @Test + public void testCastDecimalToIntAndBigInt() throws Exception { + try { + test("alter session set planner.enable_decimal_data_type = true"); + + testBuilder() + .physicalPlanFromFile("decimal/cast_decimal_int.json") + .unOrdered() + .baselineColumns("DEC9_INT", "DEC38_INT", "DEC9_BIGINT", "DEC38_BIGINT") + .baselineValues(0, 0, 0L, 0L) + .baselineValues(1, 1, 1L, 1L) + .baselineValues(-1, -1, -1L, -1L) + .baselineValues(Integer.MAX_VALUE, (int) Long.MAX_VALUE, (long) Integer.MAX_VALUE, Long.MAX_VALUE) + .baselineValues(Integer.MIN_VALUE, (int) Long.MIN_VALUE, (long) Integer.MIN_VALUE, Long.MIN_VALUE) + .baselineValues(123456789, 123456789, 123456789L, 123456789L) + .build() + .run(); + } finally { + test("drop table if exists dfs_test.tmp.table_with_int"); + test("alter session reset planner.enable_decimal_data_type"); + } + } + + @Test + public void testCastDecimalToFloatAndDouble() throws Exception { + try { + test("alter session set planner.enable_decimal_data_type = true"); + + testBuilder() + .physicalPlanFromFile("decimal/cast_decimal_float.json") + .ordered() + .baselineColumns("DEC9_FLOAT", "DEC38_FLOAT", "DEC9_DOUBLE", "DEC38_DOUBLE") + .baselineValues(99f, 123456789f, 99d, 123456789d) + .baselineValues(11.1235f, 11.1235f, 11.1235, 11.1235) + .baselineValues(0.1000f, 0.1000f, 0.1000, 0.1000) + .baselineValues(-0.12f, -0.1004f, -0.12, -0.1004) + .baselineValues(-123.1234f, -987654321.1234567891f, -123.1234, -987654321.1235) + .baselineValues(-1.0001f, -2.0301f, -1.0001, -2.0301) + .build() + .run(); + } finally { + test("drop table if exists dfs_test.tmp.table_with_int"); + test("alter session reset planner.enable_decimal_data_type"); + } + } + + @Test // DRILL-4970 + public void testCastNegativeFloatToInt() throws Exception { + try { + test("create table dfs_test.tmp.table_with_float as\n" + + "(select cast(-255.0 as double) as double_col,\n" + + "cast(-255.0 as float) as float_col\n" + + "from (values(1)))"); + + final List columnNames = Lists.newArrayList(); + columnNames.add("float_col"); + columnNames.add("double_col"); + + final List castTypes = Lists.newArrayList(); + castTypes.add("int"); + castTypes.add("bigInt"); + + final String query = "select count(*) as c from dfs_test.tmp.table_with_float\n" + + "where (cast(%1$s as %2$s) >= -255 and (%1$s <= -5)) or (%1$s <= -256)"; + + for (String columnName : columnNames) { + for (String castType : castTypes) { + testBuilder() + .sqlQuery(query, columnName, castType) + .unOrdered() + .baselineColumns("c") + .baselineValues(1L) + .build() + .run(); + } + } + } finally { + test("drop table if exists dfs_test.tmp.table_with_float"); + } + } + + @Test // DRILL-4970 + public void testCastNegativeDecimalToVarChar() throws Exception { + try { + test("alter session set planner.enable_decimal_data_type = true"); + + test("create table dfs_test.tmp.table_with_decimal as" + + "(select cast(cast(manager_id as double) * (-1) as decimal(9, 0)) as decimal9_col,\n" + + "cast(cast(manager_id as double) * (-1) as decimal(18, 0)) as decimal18_col\n" + + "from cp.`parquet/fixedlenDecimal.parquet` limit 1)"); + + final List columnNames = Lists.newArrayList(); + columnNames.add("decimal9_col"); + columnNames.add("decimal18_col"); + + final String query = "select count(*) as c from dfs_test.tmp.table_with_decimal\n" + + "where (cast(%1$s as varchar) = '-124' and (%1$s <= -5)) or (%1$s <= -256)"; + + for (String colName : columnNames) { + testBuilder() + .sqlQuery(query, colName) + .unOrdered() + .baselineColumns("c") + .baselineValues(1L) + .build() + .run(); + } + } finally { + test("drop table if exists dfs_test.tmp.table_with_decimal"); + test("alter session reset planner.enable_decimal_data_type"); + } + } } \ No newline at end of file diff --git a/exec/java-exec/src/test/resources/decimal/cast_decimal_float.json b/exec/java-exec/src/test/resources/decimal/cast_decimal_float.json new file mode 100644 index 00000000000..3fc94a0d266 --- /dev/null +++ b/exec/java-exec/src/test/resources/decimal/cast_decimal_float.json @@ -0,0 +1,45 @@ +{ + "head" : { + "version" : 1, + "generator" : { + "type" : "org.apache.drill.exec.planner.logical.DrillImplementor", + "info" : "" + }, + "type" : "APACHE_DRILL_PHYSICAL", + "resultMode" : "EXEC" + }, + graph:[ + { + @id:1, + pop:"fs-scan", + format: {type: "json"}, + storage:{type: "file", connection: "classpath:///"}, + files:["/input_simple_decimal.json"] + }, { + "pop" : "project", + "@id" : 2, + "exprs" : [ + { "ref" : "DEC9_COL", "expr": "(cast(DEC9 as decimal9(9, 4)))" }, + { "ref" : "DEC38_COL", "expr": "(cast(DEC18 as decimal38sparse(38, 4)))" } + ], + + "child" : 1 + }, + { + "pop" : "project", + "@id" : 4, + "exprs" : [ + {"ref": "DEC9_FLOAT", "expr" : "cast(DEC9_COL as float4)"}, + {"ref": "DEC38_FLOAT", "expr" : "cast(DEC38_COL as float4)"}, + {"ref": "DEC9_DOUBLE", "expr" : "cast(DEC9_COL as float8)"}, + {"ref": "DEC38_DOUBLE", "expr" : "cast(DEC38_COL as float8)"} + ], + + "child" : 2 + }, + { + "pop" : "screen", + "@id" : 5, + "child" : 4 + } ] +} \ No newline at end of file diff --git a/exec/java-exec/src/test/resources/decimal/cast_decimal_int.json b/exec/java-exec/src/test/resources/decimal/cast_decimal_int.json new file mode 100644 index 00000000000..2cca86541c5 --- /dev/null +++ b/exec/java-exec/src/test/resources/decimal/cast_decimal_int.json @@ -0,0 +1,45 @@ +{ + "head" : { + "version" : 1, + "generator" : { + "type" : "org.apache.drill.exec.planner.logical.DrillImplementor", + "info" : "" + }, + "type" : "APACHE_DRILL_PHYSICAL", + "resultMode" : "EXEC" + }, + graph:[ + { + @id:1, + pop:"fs-scan", + format: {type: "json"}, + storage:{type: "file", connection: "classpath:///"}, + files:["/input_simple_decimal.json"] + }, { + "pop" : "project", + "@id" : 2, + "exprs" : [ + { "ref" : "DEC9_COL", "expr": "(cast(cast(INT_COL as int) as decimal9(9, 0)))" }, + { "ref" : "DEC38_COL", "expr": "(cast(BIGINT_COL as decimal38sparse(38, 0)))" } + ], + + "child" : 1 + }, + { + "pop" : "project", + "@id" : 4, + "exprs" : [ + {"ref": "DEC9_INT", "expr" : "cast(DEC9_COL as int)"}, + {"ref": "DEC38_INT", "expr" : "cast(DEC38_COL as int)"}, + {"ref": "DEC9_BIGINT", "expr" : "cast(DEC9_COL as bigint)"}, + {"ref": "DEC38_BIGINT", "expr" : "cast(DEC38_COL as bigint)"} + ], + + "child" : 2 + }, + { + "pop" : "screen", + "@id" : 5, + "child" : 4 + } ] +} \ No newline at end of file diff --git a/exec/java-exec/src/test/resources/decimal/cast_int_decimal.json b/exec/java-exec/src/test/resources/decimal/cast_int_decimal.json new file mode 100644 index 00000000000..885ff534b0a --- /dev/null +++ b/exec/java-exec/src/test/resources/decimal/cast_int_decimal.json @@ -0,0 +1,45 @@ +{ + "head" : { + "version" : 1, + "generator" : { + "type" : "org.apache.drill.exec.planner.logical.DrillImplementor", + "info" : "" + }, + "type" : "APACHE_DRILL_PHYSICAL", + "resultMode" : "EXEC" + }, + graph:[ + { + @id:1, + pop:"fs-scan", + format: {type: "json"}, + storage:{type: "file", connection: "classpath:///"}, + files:["/input_simple_decimal.json"] + }, { + "pop" : "project", + "@id" : 2, + "exprs" : [ + { "ref" : "INT_COL", "expr": "(cast(INT_COL as int))" }, + { "ref" : "BIGINT_COL", "expr": "(cast(BIGINT_COL as bigint))" } + ], + + "child" : 1 + }, + { + "pop" : "project", + "@id" : 4, + "exprs" : [ + {"ref": "DEC9_INT", "expr" : "cast(INT_COL as decimal9(9, 0))"}, + {"ref": "DEC38_INT", "expr" : "cast(INT_COL as decimal38sparse(38, 0))"}, + {"ref": "DEC9_BIGINT", "expr" : "cast(BIGINT_COL as decimal9(9, 0))"}, + {"ref": "DEC38_BIGINT", "expr" : "cast(BIGINT_COL as decimal38sparse(38, 0))"} + ], + + "child" : 2 + }, + { + "pop" : "screen", + "@id" : 5, + "child" : 4 + } ] +} \ No newline at end of file diff --git a/exec/java-exec/src/test/resources/input_simple_decimal.json b/exec/java-exec/src/test/resources/input_simple_decimal.json index b7c9481f73f..d3687dbfd0c 100644 --- a/exec/java-exec/src/test/resources/input_simple_decimal.json +++ b/exec/java-exec/src/test/resources/input_simple_decimal.json @@ -1,24 +1,36 @@ { "DEC9": "99", -"DEC18": "123456789" +"DEC18": "123456789", +"INT_COL": "0", +"BIGINT_COL": "0" } { "DEC9": "11.1234567890123456", -"DEC18": "11.123456789" +"DEC18": "11.123456789", +"INT_COL": "1", +"BIGINT_COL": "1" } { "DEC9": "0.100000000001", -"DEC18":"0.100000000001" +"DEC18":"0.100000000001", +"INT_COL": "-1", +"BIGINT_COL": "-1" } { "DEC9": "-0.12", -"DEC18":"-0.1004" +"DEC18":"-0.1004", +"INT_COL": "2147483647", +"BIGINT_COL": "9223372036854775807" } { "DEC9": "-123.1234", -"DEC18": "-987654321.1234567891" +"DEC18": "-987654321.1234567891", +"INT_COL": "-2147483648", +"BIGINT_COL": "-9223372036854775808" } { "DEC9": "-1.0001", -"DEC18":"-2.0301" +"DEC18":"-2.0301", +"INT_COL": "123456789", +"BIGINT_COL": "123456789" }