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 <meha...@gmail.com> Authored: Wed Jul 2 02:29:54 2014 -0700 Committer: Jacques Nadeau <jacq...@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: