drill-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From prog...@apache.org
Subject [3/3] drill git commit: DRILL-4970: Prevent changing the negative value of input holder for cast functions
Date Tue, 04 Jul 2017 03:00:12 GMT
DRILL-4970: Prevent changing the negative value of input holder for cast functions

closes #863


Project: http://git-wip-us.apache.org/repos/asf/drill/repo
Commit: http://git-wip-us.apache.org/repos/asf/drill/commit/35a1ec66
Tree: http://git-wip-us.apache.org/repos/asf/drill/tree/35a1ec66
Diff: http://git-wip-us.apache.org/repos/asf/drill/diff/35a1ec66

Branch: refs/heads/master
Commit: 35a1ec66726fc5a77ea61cac3b6f3bbc33b8564a
Parents: 0e1e604
Author: Volodymyr Vysotskyi <vvovyk@gmail.com>
Authored: Thu Jun 29 15:28:05 2017 +0000
Committer: Paul Rogers <progers@maprtech.com>
Committed: Mon Jul 3 18:03:35 2017 -0700

----------------------------------------------------------------------
 .../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(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/drill/blob/35a1ec66/exec/java-exec/src/main/codegen/templates/CastFunctions.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/codegen/templates/CastFunctions.java b/exec/java-exec/src/main/codegen/templates/CastFunctions.java
index f68da06..4a1f67f 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 @@ import org.apache.drill.exec.record.RecordBatch;
  */
 
 @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 class Cast${type.from}${type.to} implements DrillSimpleFunc{
 
   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>

http://git-wip-us.apache.org/repos/asf/drill/blob/35a1ec66/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalInt.java
----------------------------------------------------------------------
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 a13f0e7..37f35f3 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 @@ import java.nio.ByteBuffer;
  * 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 class Cast${type.from}${type.to} implements DrillSimpleFunc {
 
     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);
     }
 }
 

http://git-wip-us.apache.org/repos/asf/drill/blob/35a1ec66/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalVarchar.java
----------------------------------------------------------------------
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 239ea28..e4c221e 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 class Cast${type.from}${type.to} implements DrillSimpleFunc {
 
         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 class Cast${type.from}${type.to} implements DrillSimpleFunc {
              *
              * 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;

http://git-wip-us.apache.org/repos/asf/drill/blob/35a1ec66/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestCastFunctions.java
----------------------------------------------------------------------
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 0d50dd3..b3a7fe9 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 class TestCastFunctions extends BaseTestQuery {
         .build()
         .run();
   }
+
+  @Test
+  public void testCastFloatToInt() throws Exception {
+    Map<Float, Integer> 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<Integer> 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<Float, Long> 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<Long> 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<Double, Integer> 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<Double, Long> 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<Integer> 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<Double> 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<String> columnNames = Lists.newArrayList();
+      columnNames.add("float_col");
+      columnNames.add("double_col");
+
+      final List<String> 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<String> 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

http://git-wip-us.apache.org/repos/asf/drill/blob/35a1ec66/exec/java-exec/src/test/resources/decimal/cast_decimal_float.json
----------------------------------------------------------------------
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 0000000..3fc94a0
--- /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

http://git-wip-us.apache.org/repos/asf/drill/blob/35a1ec66/exec/java-exec/src/test/resources/decimal/cast_decimal_int.json
----------------------------------------------------------------------
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 0000000..2cca865
--- /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

http://git-wip-us.apache.org/repos/asf/drill/blob/35a1ec66/exec/java-exec/src/test/resources/decimal/cast_int_decimal.json
----------------------------------------------------------------------
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 0000000..885ff53
--- /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

http://git-wip-us.apache.org/repos/asf/drill/blob/35a1ec66/exec/java-exec/src/test/resources/input_simple_decimal.json
----------------------------------------------------------------------
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 b7c9481..d3687db 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"
 }


Mime
View raw message