DRILL-1085: Round up while casting to int/bigint from float/double/decimal
Project: http://git-wip-us.apache.org/repos/asf/incubator-drill/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-drill/commit/22709c21
Tree: http://git-wip-us.apache.org/repos/asf/incubator-drill/tree/22709c21
Diff: http://git-wip-us.apache.org/repos/asf/incubator-drill/diff/22709c21
Branch: refs/heads/master
Commit: 22709c2185778a61b10ab96fe8b04b170dc25c68
Parents: de8f359
Author: Mehant Baid <mehantr@gmail.com>
Authored: Wed Jul 2 02:29:54 2014 -0700
Committer: Jacques Nadeau <jacques@apache.org>
Committed: Thu Jul 3 08:59:48 2014 -0700
----------------------------------------------------------------------
.../drill/common/util/DecimalUtility.java | 25 ++++++++++++++++++++
exec/java-exec/src/main/codegen/data/Casts.tdd | 8 +++----
.../main/codegen/templates/CastFunctions.java | 15 +++++++++++-
.../templates/Decimal/CastDecimalInt.java | 10 +++++++-
.../drill/exec/planner/logical/DrillOptiq.java | 4 ++--
5 files changed, 54 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/22709c21/common/src/main/java/org/apache/drill/common/util/DecimalUtility.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/drill/common/util/DecimalUtility.java b/common/src/main/java/org/apache/drill/common/util/DecimalUtility.java
index 0ac870a..4f9f096 100644
--- a/common/src/main/java/org/apache/drill/common/util/DecimalUtility.java
+++ b/common/src/main/java/org/apache/drill/common/util/DecimalUtility.java
@@ -684,5 +684,30 @@ public class DecimalUtility {
public static int getPrecisionRange(int precision) {
return getMaxPrecision(getDecimalDataType(precision));
}
+
+ public static int getFirstFractionalDigit(int decimal, int scale) {
+ if (scale == 0) {
+ return 0;
+ }
+ int temp = (int) adjustScaleDivide(decimal, scale - 1);
+ return Math.abs(temp % 10);
+ }
+
+ public static int getFirstFractionalDigit(long decimal, int scale) {
+ if (scale == 0) {
+ return 0;
+ }
+ long temp = adjustScaleDivide(decimal, scale - 1);
+ return (int) (Math.abs(temp % 10));
+ }
+
+ public static int getFirstFractionalDigit(ByteBuf data, int scale, int start, int nDecimalDigits)
{
+ if (scale == 0) {
+ return 0;
+ }
+
+ int index = nDecimalDigits - roundUp(scale);
+ return (int) (adjustScaleDivide(data.getInt(start + (index * integerSize)), MAX_DIGITS
- 1));
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/22709c21/exec/java-exec/src/main/codegen/data/Casts.tdd
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/codegen/data/Casts.tdd b/exec/java-exec/src/main/codegen/data/Casts.tdd
index ba8b6d6..2869bd0 100644
--- a/exec/java-exec/src/main/codegen/data/Casts.tdd
+++ b/exec/java-exec/src/main/codegen/data/Casts.tdd
@@ -24,10 +24,10 @@
{from: "BigInt", to: "Float8", major: "Fixed" },
{to: "Int", from: "BigInt", explicit: "int", major: "Fixed"},
{to: "Float4", from: "Float8" , explicit: "float", major: "Fixed"},
- {to: "Int", from: "Float4" , explicit: "int", major: "Fixed"},
- {to: "BigInt", from: "Float4" , explicit: "long", major: "Fixed"},
- {to: "Int", from: "Float8" , explicit: "int", major: "Fixed"},
- {to: "BigInt", from: "Float8" , explicit: "long", major: "Fixed"},
+ {to: "Int", from: "Float4" , explicit: "int", native: "float", major: "Fixed"},
+ {to: "BigInt", from: "Float4" , explicit: "long", native: "float", major: "Fixed"},
+ {to: "Int", from: "Float8" , explicit: "int", native: "double", major: "Fixed"},
+ {to: "BigInt", from: "Float8" , explicit: "long", native: "double", major: "Fixed"},
{from: "TinyInt", to: "Bit", major: "Fixed"},
{from: "Bit", to: "TinyInt", explicit: "byte", major: "Fixed"},
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/22709c21/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 af32a27..4c750dd 100644
--- a/exec/java-exec/src/main/codegen/templates/CastFunctions.java
+++ b/exec/java-exec/src/main/codegen/templates/CastFunctions.java
@@ -46,7 +46,20 @@ public class Cast${type.from}${type.to} implements DrillSimpleFunc{
public void setup(RecordBatch incoming) {}
public void eval() {
- <#if type.explicit??>
+ <#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;
+ }
+ <#elseif type.explicit??>
out.value = (${type.explicit}) in.value;
<#else>
out.value = in.value;
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/22709c21/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 cf7a634..57c38a1 100644
--- a/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalInt.java
+++ b/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalInt.java
@@ -52,8 +52,12 @@ public class Cast${type.from}${type.to} implements DrillSimpleFunc {
public void eval() {
+ int carry = (org.apache.drill.common.util.DecimalUtility.getFirstFractionalDigit(in.value,
in.scale) > 4) ? 1 : 0;
// Assign the integer part of the decimal to the output holder
- out.value = (${type.javatype}) (org.apache.drill.common.util.DecimalUtility.adjustScaleDivide(in.value,
(int) in.scale));
+ out.value = java.lang.Math.abs((${type.javatype}) (org.apache.drill.common.util.DecimalUtility.adjustScaleDivide(in.value,
(int) in.scale))) + carry;
+ if (in.value < 0) {
+ out.value *= -1;
+ }
}
}
@@ -88,6 +92,8 @@ public class Cast${type.from}${type.to} implements DrillSimpleFunc {
public void eval() {
+ int carry = (org.apache.drill.common.util.DecimalUtility.getFirstFractionalDigit(in.buffer,
in.scale, in.start, in.nDecimalDigits) > 4) ? 1 : 0;
+
// Get the index, where the integer part of the decimal ends
int integerEndIndex = in.nDecimalDigits - org.apache.drill.common.util.DecimalUtility.roundUp(in.scale);
@@ -96,6 +102,8 @@ public class Cast${type.from}${type.to} implements DrillSimpleFunc {
out.value = (${type.javatype}) ((out.value * org.apache.drill.common.util.DecimalUtility.DIGITS_BASE)
+ in.getInteger(i));
}
+ out.value += carry;
+
if (in.getSign() == true) {
out.value *= -1;
}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/22709c21/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java
b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java
index 428ff6b..deb3049 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java
@@ -382,7 +382,7 @@ public class DrillOptiq {
if (isLiteralNull(literal)) {
return createNullExpr(MinorType.BIGINT);
}
- long l = ((BigDecimal) literal.getValue()).longValue();
+ long l = (((BigDecimal) literal.getValue()).setScale(0, BigDecimal.ROUND_HALF_UP)).longValue();
return ValueExpressions.getBigInt(l);
case BOOLEAN:
if (isLiteralNull(literal)) {
@@ -410,7 +410,7 @@ public class DrillOptiq {
if (isLiteralNull(literal)) {
return createNullExpr(MinorType.INT);
}
- int a = ((BigDecimal) literal.getValue()).intValue();
+ int a = (((BigDecimal) literal.getValue()).setScale(0, BigDecimal.ROUND_HALF_UP)).intValue();
return ValueExpressions.getInt(a);
case DECIMAL:
|