You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@drill.apache.org by ja...@apache.org on 2014/05/10 02:34:58 UTC
[3/5] git commit: DRILL-619: Implement Decimal functions abs ceil
floor round truncate divide modulo Fix resolver type precedence Fix bug in
multiplication of large decimals Add tests
DRILL-619: Implement Decimal functions abs ceil floor round truncate divide modulo Fix resolver type precedence Fix bug in multiplication of large decimals Add tests
Added following misc functions
concat
length
to_char
to_number
Aggregate functions for 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/88e31534
Tree: http://git-wip-us.apache.org/repos/asf/incubator-drill/tree/88e31534
Diff: http://git-wip-us.apache.org/repos/asf/incubator-drill/diff/88e31534
Branch: refs/heads/master
Commit: 88e3153425bbc99f6766d192c7c8c8d6e2f7b398
Parents: 05e67e7
Author: Mehant Baid <me...@gmail.com>
Authored: Tue Apr 29 19:39:22 2014 -0700
Committer: Jacques Nadeau <ja...@apache.org>
Committed: Fri May 9 17:16:38 2014 -0700
----------------------------------------------------------------------
.../drill/common/util/DecimalUtility.java | 199 ++++
exec/java-exec/src/main/codegen/config.fmpp | 4 +-
exec/java-exec/src/main/codegen/data/Casts.tdd | 4 +
.../src/main/codegen/data/DecimalAggrTypes1.tdd | 65 ++
.../src/main/codegen/data/NumericTypes.tdd | 20 +
.../templates/DateIntervalAggrFunctions1.java | 4 +-
.../templates/Decimal/CastDecimalFloat.java | 4 +
.../templates/Decimal/DecimalFunctions.java | 1034 ++++++++++++++----
.../templates/DecimalAggrTypeFunctions1.java | 200 ++++
.../codegen/templates/FixedValueVectors.java | 2 +-
.../templates/NumericToCharFunctions.java | 83 ++
.../exec/expr/annotations/FunctionTemplate.java | 12 +-
.../exec/expr/fn/DrillDecimalAggFuncHolder.java | 46 +
.../expr/fn/DrillDecimalDivScaleFuncHolder.java | 64 ++
.../expr/fn/DrillDecimalSetScaleFuncHolder.java | 69 ++
.../fn/DrillDecimalZeroScaleFuncHolder.java | 60 +
.../drill/exec/expr/fn/FunctionConverter.java | 12 +
.../drill/exec/expr/fn/impl/MathFunctions.java | 40 +-
.../exec/expr/fn/impl/StringFunctions.java | 101 +-
.../drill/exec/planner/logical/DrillOptiq.java | 42 +-
.../exec/resolver/ResolverTypePrecedence.java | 10 +-
.../jdbc/test/TestAggregateFunctionsQuery.java | 98 ++
.../jdbc/test/TestDateAggregateFunction.java | 75 --
.../drill/jdbc/test/TestFunctionsQuery.java | 404 +++++++
24 files changed, 2338 insertions(+), 314 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/88e31534/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 8255784..dbfd6ac 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
@@ -31,6 +31,7 @@ public class DecimalUtility {
public final static int MAX_DIGITS = 9;
public final static int DIGITS_BASE = 1000000000;
+ public final static int DIGITS_MAX = 999999999;
public final static int integerSize = (Integer.SIZE/8);
public final static String[] decimalToString = {"",
@@ -287,5 +288,203 @@ public class DecimalUtility {
return (input.unscaledValue().longValue());
}
+
+ public static int compareDenseBytes(ByteBuf left, int leftStart, boolean leftSign, ByteBuf right, int rightStart, boolean rightSign, int width) {
+
+ int invert = 1;
+
+ /* If signs are different then simply look at the
+ * sign of the two inputs and determine which is greater
+ */
+ if (leftSign != rightSign) {
+
+ return((leftSign == true) ? -1 : 1);
+ } else if(leftSign == true) {
+ /* Both inputs are negative, at the end we will
+ * have to invert the comparison
+ */
+ invert = -1;
+ }
+
+ int cmp = 0;
+
+ for (int i = 0; i < width; i++) {
+ byte leftByte = left.getByte(leftStart + i);
+ byte rightByte = right.getByte(rightStart + i);
+ // Unsigned byte comparison
+ if ((leftByte & 0xFF) > (rightByte & 0xFF)) {
+ cmp = 1;
+ break;
+ } else if ((leftByte & 0xFF) < (rightByte & 0xFF)) {
+ cmp = -1;
+ break;
+ }
+ }
+ cmp *= invert; // invert the comparison if both were negative values
+
+ return cmp;
+ }
+
+ public static int getIntegerFromSparseBuffer(ByteBuf buffer, int start, int index) {
+ int value = buffer.getInt(start + (index * 4));
+
+ if (index == 0) {
+ /* the first byte contains sign bit, return value without it */
+ value = (value & 0x7FFFFFFF);
+ }
+ return value;
+ }
+
+ public static void setInteger(ByteBuf buffer, int start, int index, int value) {
+ buffer.setInt(start + (index * 4), value);
+ }
+
+ public static int compareSparseBytes(ByteBuf left, int leftStart, boolean leftSign, int leftScale, int leftPrecision, ByteBuf right, int rightStart, boolean rightSign, int rightPrecision, int rightScale, int width, int nDecimalDigits, boolean absCompare) {
+
+ int invert = 1;
+
+ if (absCompare == false) {
+ if (leftSign != rightSign) {
+ return (leftSign == true) ? -1 : 1;
+ }
+
+ // Both values are negative invert the outcome of the comparison
+ if (leftSign == true) {
+ invert = -1;
+ }
+ }
+
+ int cmp = compareSparseBytesInner(left, leftStart, leftSign, leftScale, leftPrecision, right, rightStart, rightSign, rightPrecision, rightScale, width, nDecimalDigits);
+ return cmp * invert;
+ }
+ public static int compareSparseBytesInner(ByteBuf left, int leftStart, boolean leftSign, int leftScale, int leftPrecision, ByteBuf right, int rightStart, boolean rightSign, int rightPrecision, int rightScale, int width, int nDecimalDigits) {
+ /* compute the number of integer digits in each decimal */
+ int leftInt = leftPrecision - leftScale;
+ int rightInt = rightPrecision - rightScale;
+
+ /* compute the number of indexes required for storing integer digits */
+ int leftIntRoundedUp = org.apache.drill.common.util.DecimalUtility.roundUp(leftInt);
+ int rightIntRoundedUp = org.apache.drill.common.util.DecimalUtility.roundUp(rightInt);
+
+ /* compute number of indexes required for storing scale */
+ int leftScaleRoundedUp = org.apache.drill.common.util.DecimalUtility.roundUp(leftScale);
+ int rightScaleRoundedUp = org.apache.drill.common.util.DecimalUtility.roundUp(rightScale);
+
+ /* compute index of the most significant integer digits */
+ int leftIndex1 = nDecimalDigits - leftScaleRoundedUp - leftIntRoundedUp;
+ int rightIndex1 = nDecimalDigits - rightScaleRoundedUp - rightIntRoundedUp;
+
+ int leftStopIndex = nDecimalDigits - leftScaleRoundedUp;
+ int rightStopIndex = nDecimalDigits - rightScaleRoundedUp;
+
+ /* Discard the zeroes in the integer part */
+ while (leftIndex1 < leftStopIndex) {
+ if (getIntegerFromSparseBuffer(left, leftStart, leftIndex1) != 0) {
+ break;
+ }
+
+ /* Digit in this location is zero, decrement the actual number
+ * of integer digits
+ */
+ leftIntRoundedUp--;
+ leftIndex1++;
+ }
+
+ /* If we reached the stop index then the number of integers is zero */
+ if (leftIndex1 == leftStopIndex) {
+ leftIntRoundedUp = 0;
+ }
+
+ while (rightIndex1 < rightStopIndex) {
+ if (getIntegerFromSparseBuffer(right, rightStart, rightIndex1) != 0) {
+ break;
+ }
+
+ /* Digit in this location is zero, decrement the actual number
+ * of integer digits
+ */
+ rightIntRoundedUp--;
+ rightIndex1++;
+ }
+
+ if (rightIndex1 == rightStopIndex) {
+ rightIntRoundedUp = 0;
+ }
+
+ /* We have the accurate number of non-zero integer digits,
+ * if the number of integer digits are different then we can determine
+ * which decimal is larger and needn't go down to comparing individual values
+ */
+ if (leftIntRoundedUp > rightIntRoundedUp) {
+ return 1;
+ }
+ else if (rightIntRoundedUp > leftIntRoundedUp) {
+ return -1;
+ }
+
+ /* The number of integer digits are the same, set the each index
+ * to the first non-zero integer and compare each digit
+ */
+ leftIndex1 = nDecimalDigits - leftScaleRoundedUp - leftIntRoundedUp;
+ rightIndex1 = nDecimalDigits - rightScaleRoundedUp - rightIntRoundedUp;
+
+ while (leftIndex1 < leftStopIndex && rightIndex1 < rightStopIndex) {
+ if (getIntegerFromSparseBuffer(left, leftStart, leftIndex1) > getIntegerFromSparseBuffer(right, rightStart, rightIndex1)) {
+ return 1;
+ }
+ else if (getIntegerFromSparseBuffer(right, rightStart, rightIndex1) > getIntegerFromSparseBuffer(left, leftStart, leftIndex1)) {
+ return -1;
+ }
+
+ leftIndex1++;
+ rightIndex1++;
+ }
+
+ /* The integer part of both the decimal's are equal, now compare
+ * each individual fractional part. Set the index to be at the
+ * beginning of the fractional part
+ */
+ leftIndex1 = leftStopIndex;
+ rightIndex1 = rightStopIndex;
+
+ /* Stop indexes will be the end of the array */
+ leftStopIndex = nDecimalDigits;
+ rightStopIndex = nDecimalDigits;
+
+ /* compare the two fractional parts of the decimal */
+ while (leftIndex1 < leftStopIndex && rightIndex1 < rightStopIndex) {
+ if (getIntegerFromSparseBuffer(left, leftStart, leftIndex1) > getIntegerFromSparseBuffer(right, rightStart, rightIndex1)) {
+ return 1;
+ }
+ else if (getIntegerFromSparseBuffer(right, rightStart, rightIndex1) > getIntegerFromSparseBuffer(left, leftStart, leftIndex1)) {
+ return -1;
+ }
+
+ leftIndex1++;
+ rightIndex1++;
+ }
+
+ /* Till now the fractional part of the decimals are equal, check
+ * if one of the decimal has fractional part that is remaining
+ * and is non-zero
+ */
+ while (leftIndex1 < leftStopIndex) {
+ if (getIntegerFromSparseBuffer(left, leftStart, leftIndex1) != 0) {
+ return 1;
+ }
+ leftIndex1++;
+ }
+
+ while(rightIndex1 < rightStopIndex) {
+ if (getIntegerFromSparseBuffer(right, rightStart, rightIndex1) != 0) {
+ return -1;
+ }
+ rightIndex1++;
+ }
+
+ /* Both decimal values are equal */
+ return 0;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/88e31534/exec/java-exec/src/main/codegen/config.fmpp
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/codegen/config.fmpp b/exec/java-exec/src/main/codegen/config.fmpp
index 909d611..5c0d03b 100644
--- a/exec/java-exec/src/main/codegen/config.fmpp
+++ b/exec/java-exec/src/main/codegen/config.fmpp
@@ -22,6 +22,7 @@ data: {
mathFunc:tdd(../data/MathFunc.tdd),
drillOI:tdd(../data/HiveTypes.tdd),
aggrtypes1: tdd(../data/AggrTypes1.tdd),
+ decimalaggrtypes1: tdd(../data/DecimalAggrTypes1.tdd),
aggrtypes2: tdd(../data/AggrTypes2.tdd),
aggrtypes3: tdd(../data/AggrTypes3.tdd),
date: tdd(../data/DateTypes.tdd),
@@ -30,7 +31,8 @@ data: {
decimal: tdd(../data/DecimalTypes.tdd),
dateIntervalFunc: tdd(../data/DateIntervalFunc.tdd),
intervalNumericTypes: tdd(../data/IntervalNumericTypes.tdd),
- extract: tdd(../data/ExtractTypes.tdd)
+ extract: tdd(../data/ExtractTypes.tdd),
+ numericTypes: tdd(../data/NumericTypes.tdd)
}
freemarkerLinks: {
includes: includes/
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/88e31534/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 397dcdb..0dc0090 100644
--- a/exec/java-exec/src/main/codegen/data/Casts.tdd
+++ b/exec/java-exec/src/main/codegen/data/Casts.tdd
@@ -126,7 +126,9 @@
{from: "Decimal9", to: "Float4", major: "DecimalSimpleFloat", javatype: "float"},
{from: "Decimal18", to: "Float4", major: "DecimalSimpleFloat", javatype: "float"},
{from: "Decimal28Sparse", to: "Float4", major: "DecimalComplexFloat", javatype: "float"},
+ {from: "Decimal28Dense", to: "Float4", major: "DecimalComplexFloat", javatype: "float"},
{from: "Decimal38Sparse", to: "Float4", major: "DecimalComplexFloat", javatype: "float"},
+ {from: "Decimal38Dense", to: "Float4", major: "DecimalComplexFloat", javatype: "float"},
{from: "Float4", to: "Decimal9", major: "FloatDecimalSimple", javatype: "int"},
{from: "Float4", to: "Decimal18", major: "FloatDecimalSimple", javatype: "long"},
@@ -141,7 +143,9 @@
{from: "Decimal9", to: "Float8", major: "DecimalSimpleDouble", javatype: "double"},
{from: "Decimal18", to: "Float8", major: "DecimalSimpleDouble", javatype: "double"},
{from: "Decimal28Sparse", to: "Float8", major: "DecimalComplexDouble", javatype: "double"},
+ {from: "Decimal28Dense", to: "Float8", major: "DecimalComplexDouble", javatype: "double"},
{from: "Decimal38Sparse", to: "Float8", major: "DecimalComplexDouble", javatype: "double"},
+ {from: "Decimal38Dense", to: "Float8", major: "DecimalComplexDouble", javatype: "double"},
{from: "VarChar", to: "Decimal9", major: "VarCharDecimalSimple"},
{from: "VarChar", to: "Decimal18", major: "VarCharDecimalSimple"},
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/88e31534/exec/java-exec/src/main/codegen/data/DecimalAggrTypes1.tdd
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/codegen/data/DecimalAggrTypes1.tdd b/exec/java-exec/src/main/codegen/data/DecimalAggrTypes1.tdd
new file mode 100644
index 0000000..558f95b
--- /dev/null
+++ b/exec/java-exec/src/main/codegen/data/DecimalAggrTypes1.tdd
@@ -0,0 +1,65 @@
+# 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
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http:# www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+{
+ aggrtypes: [
+ {className: "Max", funcName: "max", types: [
+ {inputType: "Decimal9", outputType: "Decimal9", runningType: "Decimal9", initValue: "Integer.MIN_VALUE"},
+ {inputType: "NullableDecimal9", outputType: "Decimal9", runningType: "Decimal9", initValue: "Integer.MIN_VALUE"},
+ {inputType: "Decimal18", outputType: "Decimal18", runningType: "Decimal18", initValue: "Long.MIN_VALUE"},
+ {inputType: "NullableDecimal18", outputType: "Decimal18", runningType: "Decimal18", initValue: "Long.MIN_VALUE"},
+ {inputType: "Decimal28Dense", outputType: "Decimal28Dense", runningType: "Decimal28Dense"},
+ {inputType: "NullableDecimal28Dense", outputType: "Decimal28Dense", runningType: "Decimal28Dense"},
+ {inputType: "Decimal38Dense", outputType: "Decimal38Dense", runningType: "Decimal38Dense"},
+ {inputType: "NullableDecimal38Dense", outputType: "Decimal38Dense", runningType: "Decimal38Dense"},
+ {inputType: "Decimal28Sparse", outputType: "Decimal28Sparse", runningType: "Decimal28Sparse"},
+ {inputType: "NullableDecimal28Sparse", outputType: "Decimal28Sparse", runningType: "Decimal28Sparse"},
+ {inputType: "Decimal38Sparse", outputType: "Decimal38Sparse", runningType: "Decimal38Sparse"},
+ {inputType: "NullableDecimal38Sparse", outputType: "Decimal38Sparse", runningType: "Decimal38Sparse"}
+ ]
+ },
+ {className: "Min", funcName: "min", types: [
+ {inputType: "Decimal9", outputType: "Decimal9", runningType: "Decimal9", initValue: "Integer.MAX_VALUE"},
+ {inputType: "NullableDecimal9", outputType: "Decimal9", runningType: "Decimal9", initValue: "Integer.MAX_VALUE"},
+ {inputType: "Decimal18", outputType: "Decimal18", runningType: "Decimal18", initValue: "Integer.MAX_VALUE"},
+ {inputType: "NullableDecimal18", outputType: "Decimal18", runningType: "Decimal18", initValue: "Integer.MAX_VALUE"},
+ {inputType: "Decimal28Dense", outputType: "Decimal28Dense", runningType: "Decimal28Dense"},
+ {inputType: "NullableDecimal28Dense", outputType: "Decimal28Dense", runningType: "Decimal28Dense"},
+ {inputType: "Decimal38Dense", outputType: "Decimal38Dense", runningType: "Decimal38Dense"},
+ {inputType: "NullableDecimal38Dense", outputType: "Decimal38Dense", runningType: "Decimal38Dense"},
+ {inputType: "Decimal28Sparse", outputType: "Decimal28Sparse", runningType: "Decimal28Sparse"},
+ {inputType: "NullableDecimal28Sparse", outputType: "Decimal28Sparse", runningType: "Decimal28Sparse"},
+ {inputType: "Decimal38Sparse", outputType: "Decimal38Sparse", runningType: "Decimal38Sparse"},
+ {inputType: "NullableDecimal38Sparse", outputType: "Decimal38Sparse", runningType: "Decimal38Sparse"}
+ ]
+ },
+ {className: "Count", funcName: "count", types: [
+ {inputType: "Decimal9", outputType: "BigInt", runningType: "BigInt", major: "Numeric"},
+ {inputType: "NullableDecimal9", outputType: "BigInt", runningType: "BigInt", major: "Numeric"},
+ {inputType: "Decimal18", outputType: "BigInt", runningType: "BigInt", major: "Numeric"},
+ {inputType: "NullableDecimal18", outputType: "BigInt", runningType: "BigInt", major: "Numeric"},
+ {inputType: "Decimal28Sparse", outputType: "BigInt", runningType: "BigInt", major: "Numeric"},
+ {inputType: "NullableDecimal28Sparse", outputType: "BigInt", runningType: "BigInt", major: "Numeric"},
+ {inputType: "Decimal38Sparse", outputType: "BigInt", runningType: "BigInt", major: "Numeric"},
+ {inputType: "NullableDecimal38Sparse", outputType: "BigInt", runningType: "BigInt", major: "Numeric"},
+ {inputType: "Decimal28Dense", outputType: "BigInt", runningType: "BigInt", major: "Numeric"},
+ {inputType: "NullableDecimal28Dense", outputType: "BigInt", runningType: "BigInt", major: "Numeric"},
+ {inputType: "Decimal38Dense", outputType: "BigInt", runningType: "BigInt", major: "Numeric"},
+ {inputType: "NullableDecimal38Dense", outputType: "BigInt", runningType: "BigInt", major: "Numeric"}
+ ]
+ }
+ ]
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/88e31534/exec/java-exec/src/main/codegen/data/NumericTypes.tdd
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/codegen/data/NumericTypes.tdd b/exec/java-exec/src/main/codegen/data/NumericTypes.tdd
new file mode 100644
index 0000000..f37a3dd
--- /dev/null
+++ b/exec/java-exec/src/main/codegen/data/NumericTypes.tdd
@@ -0,0 +1,20 @@
+# 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
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http:# www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+{
+ numeric: ["Int", "BigInt", "TinyInt", "SmallInt", "UInt1", "UInt2", "UInt4", "UInt8", "Float4", "Float8",
+ "Decimal9", "Decimal18", "Decimal28Dense", "Decimal28Sparse", "Decimal38Dense", "Decimal38Sparse"]
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/88e31534/exec/java-exec/src/main/codegen/templates/DateIntervalAggrFunctions1.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/codegen/templates/DateIntervalAggrFunctions1.java b/exec/java-exec/src/main/codegen/templates/DateIntervalAggrFunctions1.java
index eee349d..701e992 100644
--- a/exec/java-exec/src/main/codegen/templates/DateIntervalAggrFunctions1.java
+++ b/exec/java-exec/src/main/codegen/templates/DateIntervalAggrFunctions1.java
@@ -45,7 +45,6 @@ import org.apache.drill.exec.record.RecordBatch;
@SuppressWarnings("unused")
public class ${aggrtype.className}DateTypeFunctions {
- static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(${aggrtype.className}Functions.class);
<#list aggrtype.types as type>
<#if type.major == "Date">
@@ -96,11 +95,12 @@ public static class ${type.inputType}${aggrtype.className} implements DrillAggFu
value.value = Math.min(value.value, inMS);
<#elseif type.outputType == "IntervalDay">
- org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(org.apache.drill.exec.expr.fn.impl.MathFunctions.class);
long inMS = (long) in.days * (org.apache.drill.exec.expr.fn.impl.DateUtility.daysToStandardMillis) +
in.milliSeconds;
value.value = Math.min(value.value, inMS);
+
+
<#else>
value.value = Math.min(value.value, in.value);
</#if>
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/88e31534/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalFloat.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalFloat.java b/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalFloat.java
index 82f9a43..9e2e48d 100644
--- a/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalFloat.java
+++ b/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalFloat.java
@@ -87,7 +87,11 @@ public class Cast${type.from}${type.to} implements DrillSimpleFunc {
public void eval() {
+ <#if type.from == "Decimal28Dense" || type.from == "Decimal38Dense">
+ java.math.BigDecimal bigDecimal = org.apache.drill.common.util.DecimalUtility.getBigDecimalFromDense(in.buffer, in.start, in.nDecimalDigits, in.scale, in.maxPrecision, in.WIDTH);
+ <#else>
java.math.BigDecimal bigDecimal = org.apache.drill.common.util.DecimalUtility.getBigDecimalFromByteBuf(in.buffer, in.start, in.nDecimalDigits, in.scale, true);
+ </#if>
out.value = bigDecimal.${type.javatype}Value();
}
}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/88e31534/exec/java-exec/src/main/codegen/templates/Decimal/DecimalFunctions.java
----------------------------------------------------------------------
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 4603853..60b22fb 100644
--- a/exec/java-exec/src/main/codegen/templates/Decimal/DecimalFunctions.java
+++ b/exec/java-exec/src/main/codegen/templates/Decimal/DecimalFunctions.java
@@ -20,198 +20,15 @@ import org.apache.drill.exec.expr.annotations.Workspace;
<@pp.dropOutputFile />
-<#macro denseCompareBlock left right output>
-
- int invert = 1;
-
- outside: {
-
- /* If signs are different then simply look at the
- * sign of the two inputs and determine which is greater
- */
- if (left.sign != right.sign) {
-
- ${output} = (left.sign == true) ? -1 : 1;
- break outside;
- } else if(left.sign == true) {
- /* Both inputs are negative, at the end we will
- * have to invert the comparison
- */
- invert = -1;
- }
-
- ${output} = 0;
- for (int i = 0; i < left.WIDTH; i++) {
- byte leftByte = left.buffer.getByte(left.start + i);
- byte rightByte = right.buffer.getByte(right.start + i);
-
- // Unsigned byte comparison
- if ((leftByte & 0xFF) > (rightByte & 0xFF)) {
- ${output} = 1;
- break;
- } else if ((leftByte & 0xFF) < (rightByte & 0xFF)) {
- ${output} = -1;
- break;
- }
- }
- ${output} *= invert; // invert the comparison if both were negative values
- }
-</#macro>
-
<#macro compareBlock holderType left right absCompare output>
outside:{
+ ${output} = org.apache.drill.common.util.DecimalUtility.compareSparseBytes(left.buffer, left.start, left.sign,
+ left.scale, left.precision, right.buffer,
+ right.start, right.sign, right.precision,
+ right.scale, left.WIDTH, left.nDecimalDigits, ${absCompare});
- <#if absCompare == "false">
- if (left.sign != right.sign) {
- /* signs are different, we can simply look at the sign
- * and determine which decimal is greater
- */
- ${output} = left.sign == true ? -1 : 1;
- break outside;
- } else if (left.sign == true) {
- /* Because both decimals are negative, we swap them
- * and go ahead with the regular comparison
- */
- left.swap(right);
- }
- </#if>
- /* compute the number of integer digits in each decimal */
- int leftInt = left.precision - left.scale;
- int rightInt = right.precision - right.scale;
-
- /* compute the number of indexes required for storing integer digits */
- int leftIntRoundedUp = org.apache.drill.common.util.DecimalUtility.roundUp(leftInt);
- int rightIntRoundedUp = org.apache.drill.common.util.DecimalUtility.roundUp(rightInt);
-
- /* compute number of indexes required for storing scale */
- int leftScaleRoundedUp = org.apache.drill.common.util.DecimalUtility.roundUp(left.scale);
- int rightScaleRoundedUp = org.apache.drill.common.util.DecimalUtility.roundUp(right.scale);
-
- /* compute index of the most significant integer digits */
- int leftIndex1 = left.nDecimalDigits - leftScaleRoundedUp - leftIntRoundedUp;
- int rightIndex1 = right.nDecimalDigits - rightScaleRoundedUp - rightIntRoundedUp;
-
- int leftStopIndex = left.nDecimalDigits - leftScaleRoundedUp;
- int rightStopIndex = right.nDecimalDigits - rightScaleRoundedUp;
-
- /* Discard the zeroes in the integer part */
- while (leftIndex1 < leftStopIndex) {
- if (left.getInteger(leftIndex1) != 0) {
- break;
- }
-
- /* Digit in this location is zero, decrement the actual number
- * of integer digits
- */
- leftIntRoundedUp--;
- leftIndex1++;
- }
-
- /* If we reached the stop index then the number of integers is zero */
- if (leftIndex1 == leftStopIndex) {
- leftIntRoundedUp = 0;
- }
-
- while (rightIndex1 < rightStopIndex) {
- if (right.getInteger(rightIndex1) != 0) {
- break;
- }
-
- /* Digit in this location is zero, decrement the actual number
- * of integer digits
- */
- rightIntRoundedUp--;
- rightIndex1++;
- }
-
- if (rightIndex1 == rightStopIndex) {
- rightIntRoundedUp = 0;
- }
-
- /* We have the accurate number of non-zero integer digits,
- * if the number of integer digits are different then we can determine
- * which decimal is larger and needn't go down to comparing individual values
- */
- if (leftIntRoundedUp > rightIntRoundedUp) {
- ${output }= 1;
- break outside;
- }
- else if (rightIntRoundedUp > leftIntRoundedUp) {
- ${output} = -1;
- break outside;
- }
-
- /* The number of integer digits are the same, set the each index
- * to the first non-zero integer and compare each digit
- */
- leftIndex1 = left.nDecimalDigits - leftScaleRoundedUp - leftIntRoundedUp;
- rightIndex1 = right.nDecimalDigits - rightScaleRoundedUp - rightIntRoundedUp;
-
- while (leftIndex1 < leftStopIndex && rightIndex1 < rightStopIndex) {
- if (left.getInteger(leftIndex1) > right.getInteger(rightIndex1)) {
- ${output} = 1;
- break outside;
- }
- else if (right.getInteger(rightIndex1) > left.getInteger(leftIndex1)) {
- ${output} = -1;
- break outside;
- }
-
- leftIndex1++;
- rightIndex1++;
- }
-
- /* The integer part of both the decimal's are equal, now compare
- * each individual fractional part. Set the index to be at the
- * beginning of the fractional part
- */
- leftIndex1 = leftStopIndex;
- rightIndex1 = rightStopIndex;
-
- /* Stop indexes will be the end of the array */
- leftStopIndex = left.nDecimalDigits;
- rightStopIndex = right.nDecimalDigits;
-
- /* compare the two fractional parts of the decimal */
- while (leftIndex1 < leftStopIndex && rightIndex1 < rightStopIndex) {
- if (left.getInteger(leftIndex1) > right.getInteger(rightIndex1)) {
- ${output} = 1;
- break outside;
- }
- else if (right.getInteger(rightIndex1) > left.getInteger(leftIndex1)) {
- ${output} = -1;
- break outside;
- }
-
- leftIndex1++;
- rightIndex1++;
- }
-
- /* Till now the fractional part of the decimals are equal, check
- * if one of the decimal has fractional part that is remaining
- * and is non-zero
- */
- while (leftIndex1 < leftStopIndex) {
- if (left.getInteger(leftIndex1) != 0) {
- ${output} = 1;
- break outside;
- }
- leftIndex1++;
- }
-
- while(rightIndex1 < rightStopIndex) {
- if (right.getInteger(rightIndex1) != 0) {
- ${output} = -1;
- break outside;
- }
- rightIndex1++;
- }
-
- /* Both decimal values are equal */
- ${output} = 0;
-
- }
+ }
</#macro>
<#macro subtractBlock holderType left right result>
@@ -369,7 +186,7 @@ import org.apache.drill.exec.expr.annotations.Workspace;
leftIndex--;
rightIndex--;
- if (sum > org.apache.drill.common.util.DecimalUtility.DIGITS_BASE) {
+ if (sum >= org.apache.drill.common.util.DecimalUtility.DIGITS_BASE) {
result.setInteger(resultIndex, (sum - org.apache.drill.common.util.DecimalUtility.DIGITS_BASE));
sum = 1;
} else {
@@ -383,7 +200,7 @@ import org.apache.drill.exec.expr.annotations.Workspace;
sum += left.getInteger(leftIndex);
leftIndex--;
- if (sum > org.apache.drill.common.util.DecimalUtility.DIGITS_BASE) {
+ if (sum >= org.apache.drill.common.util.DecimalUtility.DIGITS_BASE) {
result.setInteger(resultIndex, (sum - org.apache.drill.common.util.DecimalUtility.DIGITS_BASE));
sum = 1;
} else {
@@ -396,7 +213,7 @@ import org.apache.drill.exec.expr.annotations.Workspace;
sum += right.getInteger(rightIndex);
rightIndex--;
- if (sum > org.apache.drill.common.util.DecimalUtility.DIGITS_BASE) {
+ if (sum >= org.apache.drill.common.util.DecimalUtility.DIGITS_BASE) {
result.setInteger(resultIndex, (sum - org.apache.drill.common.util.DecimalUtility.DIGITS_BASE));
sum = 1;
} else {
@@ -521,7 +338,6 @@ public class ${type.name}Functions {
}
public void eval() {
-
result.buffer = buffer;
result.start = 0;
@@ -564,12 +380,14 @@ public class ${type.name}Functions {
@Param ${type.name}Holder left;
@Param ${type.name}Holder right;
@Workspace ByteBuf buffer;
+ @Workspace int[] tempResult;
@Output ${type.name}Holder result;
public void setup(RecordBatch incoming) {
int size = (${type.storage} * (org.apache.drill.common.util.DecimalUtility.integerSize));
buffer = io.netty.buffer.Unpooled.wrappedBuffer(new byte[size]);
buffer = new io.netty.buffer.SwappedByteBuf(buffer);
+ tempResult = new int[${type.storage} * ${type.storage}];
}
public void eval() {
@@ -577,12 +395,12 @@ public class ${type.name}Functions {
result.buffer = buffer;
result.start = 0;
- // Re initialize the buffer everytime
- for (int i = 0; i < ${type.storage}; i++) {
- result.setInteger(i, 0);
+ // Re initialize the temporary array
+ for (int i = 0; i < ${type.storage} * ${type.storage}; i++) {
+ tempResult[i] = 0;
}
- /* Remove the leading zeroes from the integer part of the input */
+ // Remove the leading zeroes from the integer part of the input
int leftIndex = 0;
int leftStopIndex = left.nDecimalDigits - org.apache.drill.common.util.DecimalUtility.roundUp(left.scale);
@@ -616,26 +434,25 @@ public class ${type.name}Functions {
int leftSize = left.nDecimalDigits - 1;
int rightSize = right.nDecimalDigits - 1;
- //int resultIndex = resultSize - 1;
- int resultIndex = result.nDecimalDigits - 1;
+ int resultIndex = tempResult.length - 1;
+ int currentIndex = 0;
for (int i = leftSize; i >= leftIndex; i--) {
- int currentIndex = resultIndex;
+ currentIndex = resultIndex;
int carry = 0;
for (int j = rightSize; j >= rightIndex; j--) {
long mulResult = (long) right.getInteger(j) * (long) left.getInteger(i);
- //long tempSum = mulResultDigits[currentIndex] + mulResult + carry;
- long tempSum = result.getInteger(currentIndex) + mulResult + carry;
+ long tempSum = tempResult[currentIndex] + mulResult + carry;
if (tempSum >= org.apache.drill.common.util.DecimalUtility.DIGITS_BASE) {
- result.setInteger(currentIndex, (int) (tempSum % org.apache.drill.common.util.DecimalUtility.DIGITS_BASE));
+ tempResult[currentIndex] = (int) (tempSum % org.apache.drill.common.util.DecimalUtility.DIGITS_BASE);
carry = (int) (tempSum / org.apache.drill.common.util.DecimalUtility.DIGITS_BASE);
} else {
- result.setInteger(currentIndex, (int) tempSum);
+ tempResult[currentIndex] = (int) tempSum;
carry = 0;
}
@@ -643,11 +460,21 @@ public class ${type.name}Functions {
}
/* propogate the carry */
if (carry > 0)
- result.setInteger(currentIndex, (result.getInteger(currentIndex) + carry));
+ tempResult[currentIndex] += carry;
resultIndex--;
}
+ int outputIndex = result.nDecimalDigits - 1;
+
+ for (int i = (currentIndex + resultIntegerSize + resultScaleSize - 1); i >= currentIndex; i--) {
+ result.setInteger(outputIndex--, tempResult[i]);
+ }
+
+ // Set the remaining digits to be zero
+ while(outputIndex >= 0) {
+ result.setInteger(outputIndex--, 0);
+ }
// Set the scale and precision
result.scale = left.scale + right.scale;
@@ -657,6 +484,536 @@ public class ${type.name}Functions {
}
}
+ @FunctionTemplate(name = "divide", scope = FunctionTemplate.FunctionScope.DECIMAL_DIV_SCALE, nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}DivideFunction implements DrillSimpleFunc {
+
+ @Param ${type.name}Holder left;
+ @Param ${type.name}Holder right;
+ @Output ${type.name}Holder result;
+ @Workspace ByteBuf buffer;
+
+ public void setup(RecordBatch incoming) {
+ int size = (${type.storage} * (org.apache.drill.common.util.DecimalUtility.integerSize));
+ buffer = io.netty.buffer.Unpooled.wrappedBuffer(new byte[size]);
+ buffer = new io.netty.buffer.SwappedByteBuf(buffer);
+ }
+
+ public void eval() {
+
+ result.scale = left.scale;
+ result.precision = left.precision;
+ result.buffer = buffer;
+ result.start = 0;
+
+ java.math.BigDecimal numerator = org.apache.drill.common.util.DecimalUtility.getBigDecimalFromByteBuf(left.buffer, left.start, left.nDecimalDigits, left.scale, true);
+ java.math.BigDecimal denominator = org.apache.drill.common.util.DecimalUtility.getBigDecimalFromByteBuf(right.buffer, right.start, right.nDecimalDigits, right.scale, true);
+
+ java.math.BigDecimal output = numerator.divide(denominator, (int) result.scale, java.math.BigDecimal.ROUND_DOWN);
+
+ // Initialize the result buffer
+ for (int i = 0; i < ${type.storage}; i++) {
+ result.setInteger(i, 0);
+ }
+
+ org.apache.drill.common.util.DecimalUtility.getSparseFromBigDecimal(output, result.buffer, result.start, result.scale, result.precision, result.nDecimalDigits);
+ }
+ }
+
+ @FunctionTemplate(name = "mod", scope = FunctionTemplate.FunctionScope.DECIMAL_DIV_SCALE, nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}ModFunction implements DrillSimpleFunc {
+
+ @Param ${type.name}Holder left;
+ @Param ${type.name}Holder right;
+ @Output ${type.name}Holder result;
+ @Workspace ByteBuf buffer;
+
+ public void setup(RecordBatch incoming) {
+ int size = (${type.storage} * (org.apache.drill.common.util.DecimalUtility.integerSize));
+ buffer = io.netty.buffer.Unpooled.wrappedBuffer(new byte[size]);
+ buffer = new io.netty.buffer.SwappedByteBuf(buffer);
+ }
+
+ public void eval() {
+
+ result.scale = left.scale;
+ result.precision = left.precision;
+ result.buffer = buffer;
+ result.start = 0;
+
+ java.math.BigDecimal numerator = org.apache.drill.common.util.DecimalUtility.getBigDecimalFromByteBuf(left.buffer, left.start, left.nDecimalDigits, left.scale, true);
+ java.math.BigDecimal denominator = org.apache.drill.common.util.DecimalUtility.getBigDecimalFromByteBuf(right.buffer, right.start, right.nDecimalDigits, right.scale, true);
+
+ java.math.BigDecimal output = numerator.remainder(denominator);
+ output.setScale(left.scale, java.math.BigDecimal.ROUND_DOWN);
+
+ // Initialize the result buffer
+ for (int i = 0; i < ${type.storage}; i++) {
+ result.setInteger(i, 0);
+ }
+
+ org.apache.drill.common.util.DecimalUtility.getSparseFromBigDecimal(output, result.buffer, result.start, result.scale, result.precision, result.nDecimalDigits);
+ }
+ }
+
+ @FunctionTemplate(name = "abs", scope = FunctionTemplate.FunctionScope.DECIMAL_MAX_SCALE, nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}AbsFunction implements DrillSimpleFunc {
+
+ @Param ${type.name}Holder in;
+ @Output ${type.name}Holder out;
+ public void setup(RecordBatch incoming) {
+
+ }
+
+ public void eval() {
+ out.scale = in.scale;
+ out.precision = in.precision;
+ out.buffer = in.buffer;
+ out.start = in.start;
+
+ // set the output buffer with the positive sign
+ out.buffer.setInt(out.start, (out.buffer.getInt(out.start) & 0x7fffffff));
+ }
+ }
+
+ @FunctionTemplate(name = "sign", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}SignFunction implements DrillSimpleFunc {
+
+ @Param ${type.name}Holder in;
+ @Output IntHolder out;
+
+ public void setup(RecordBatch incoming) {}
+
+ public void eval() {
+
+ boolean zeroValue = true;
+
+ if (in.sign == true) {
+ out.value = -1;
+ } else {
+ for (int i = 0; i < ${type.storage}; i++) {
+ if (in.getInteger(i) != 0) {
+ zeroValue = false;
+ break;
+ }
+ }
+ out.value = (zeroValue == true) ? 0 : 1;
+ }
+ }
+ }
+
+ @FunctionTemplate(names = {"ceil", "ceiling"}, scope = FunctionTemplate.FunctionScope.DECIMAL_ZERO_SCALE, nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}CeilFunction implements DrillSimpleFunc {
+
+ @Param ${type.name}Holder in;
+ @Output ${type.name}Holder out;
+ public void setup(RecordBatch incoming) {
+
+ }
+
+ public void eval() {
+ out.scale = 0;
+ out.precision = in.precision;
+ out.buffer = in.buffer;
+ out.start = in.start;
+ out.sign = in.sign;
+
+ // Indicates whether we need to add 1 to the integer part, while performing ceil
+ int carry = 0;
+
+ int scaleStartIndex = ${type.storage} - org.apache.drill.common.util.DecimalUtility.roundUp(in.scale);
+ int srcIntIndex = scaleStartIndex - 1;
+
+ if (out.sign == false) {
+ // For negative values ceil we don't need to increment the integer part
+ while (scaleStartIndex < ${type.storage}) {
+ if (out.getInteger(scaleStartIndex) != 0) {
+ carry = 1;
+ break;
+ }
+ scaleStartIndex++;
+ }
+ }
+
+ // Truncate the fractional part, move the integer part
+ int destIndex = ${type.storage} - 1;
+ while (srcIntIndex >= 0) {
+ out.setInteger(destIndex--, out.getInteger(srcIntIndex--));
+ }
+
+ // Set the remaining portion of the decimal to be zeroes
+ while (destIndex >= 0) {
+ out.setInteger(destIndex--, 0);
+ }
+
+ // Add the carry
+ if (carry != 0) {
+ destIndex = ${type.storage} - 1;
+
+ while (destIndex >= 0) {
+ int intValue = out.getInteger(destIndex);
+ intValue += carry;
+
+ if (intValue >= org.apache.drill.common.util.DecimalUtility.DIGITS_BASE) {
+ out.setInteger(destIndex--, intValue % org.apache.drill.common.util.DecimalUtility.DIGITS_BASE);
+ carry = intValue / org.apache.drill.common.util.DecimalUtility.DIGITS_BASE;
+ } else {
+ out.setInteger(destIndex--, intValue);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ @FunctionTemplate(name = "floor", scope = FunctionTemplate.FunctionScope.DECIMAL_ZERO_SCALE, nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}FloorFunction implements DrillSimpleFunc {
+
+ @Param ${type.name}Holder in;
+ @Output ${type.name}Holder out;
+ public void setup(RecordBatch incoming) {
+
+ }
+
+ public void eval() {
+ out.scale = 0;
+ out.precision = in.precision;
+ out.buffer = in.buffer;
+ out.start = in.start;
+ out.sign = in.sign;
+
+ // Indicates whether we need to decrement 1 from the integer part, while performing floor, done for -ve values
+ int carry = 0;
+
+ int scaleStartIndex = ${type.storage} - org.apache.drill.common.util.DecimalUtility.roundUp(in.scale);
+ int srcIntIndex = scaleStartIndex - 1;
+
+ if (out.sign == true) {
+ // For negative values ceil we don't need to increment the integer part
+ while (scaleStartIndex < ${type.storage}) {
+ if (out.getInteger(scaleStartIndex) != 0) {
+ carry = 1;
+ break;
+ }
+ scaleStartIndex++;
+ }
+ }
+
+ // Truncate the fractional part, move the integer part
+ int destIndex = ${type.storage} - 1;
+ while (srcIntIndex >= 0) {
+ out.setInteger(destIndex--, out.getInteger(srcIntIndex--));
+ }
+
+ // Set the remaining portion of the decimal to be zeroes
+ while (destIndex >= 0) {
+ out.setInteger(destIndex--, 0);
+ }
+
+ // Add the carry
+ if (carry != 0) {
+ destIndex = ${type.storage} - 1;
+
+ while (destIndex >= 0) {
+ int intValue = out.getInteger(destIndex);
+ intValue += carry;
+
+ if (intValue >= org.apache.drill.common.util.DecimalUtility.DIGITS_BASE) {
+ out.setInteger(destIndex--, intValue % org.apache.drill.common.util.DecimalUtility.DIGITS_BASE);
+ carry = intValue / org.apache.drill.common.util.DecimalUtility.DIGITS_BASE;
+ } else {
+ out.setInteger(destIndex--, intValue);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ @FunctionTemplate(names = {"trunc", "truncate"}, scope = FunctionTemplate.FunctionScope.DECIMAL_ZERO_SCALE, nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}TruncateFunction implements DrillSimpleFunc {
+
+ @Param ${type.name}Holder in;
+ @Output ${type.name}Holder out;
+ public void setup(RecordBatch incoming) {
+
+ }
+
+ public void eval() {
+ out.scale = 0;
+ out.precision = in.precision;
+ out.buffer = in.buffer;
+ out.start = in.start;
+ out.sign = in.sign;
+
+ // Integer part's src index
+ int srcIntIndex = ${type.storage} - org.apache.drill.common.util.DecimalUtility.roundUp(in.scale) - 1;
+
+ // Truncate the fractional part, move the integer part
+ int destIndex = ${type.storage} - 1;
+ while (srcIntIndex >= 0) {
+ out.setInteger(destIndex--, out.getInteger(srcIntIndex--));
+ }
+
+ // Set the remaining portion of the decimal to be zeroes
+ while (destIndex >= 0) {
+ out.setInteger(destIndex--, 0);
+ }
+ }
+ }
+
+ @FunctionTemplate(names = {"trunc", "truncate"}, scope = FunctionTemplate.FunctionScope.DECIMAL_SET_SCALE, nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}TruncateScaleFunction implements DrillSimpleFunc {
+
+ @Param ${type.name}Holder left;
+ @Param IntHolder right;
+ @Output ${type.name}Holder result;
+ public void setup(RecordBatch incoming) {
+
+ }
+
+ public void eval() {
+ result.scale = right.value;
+ result.precision = left.precision;
+ result.buffer = left.buffer;
+ result.start = left.start;
+ result.sign = left.sign;
+
+ int newScaleRoundedUp = org.apache.drill.common.util.DecimalUtility.roundUp(right.value);
+ int origScaleRoundedUp = org.apache.drill.common.util.DecimalUtility.roundUp(left.scale);
+
+ if (right.value < left.scale) {
+ // Get the source index beyond which we will truncate
+ int srcIntIndex = ${type.storage} - origScaleRoundedUp - 1;
+ int srcIndex = srcIntIndex + newScaleRoundedUp;
+
+ // Truncate the remaining fractional part, move the integer part
+ int destIndex = ${type.storage} - 1;
+ if (srcIndex != destIndex) {
+ while (srcIndex >= 0) {
+ result.setInteger(destIndex--, result.getInteger(srcIndex--));
+ }
+
+ // Set the remaining portion of the decimal to be zeroes
+ while (destIndex >= 0) {
+ result.setInteger(destIndex--, 0);
+ }
+ }
+
+ // We truncated the decimal digit. Now we need to truncate within the base 1 billion fractional digit
+ int truncateFactor = org.apache.drill.common.util.DecimalUtility.MAX_DIGITS - (right.value % org.apache.drill.common.util.DecimalUtility.MAX_DIGITS);
+ if (truncateFactor != org.apache.drill.common.util.DecimalUtility.MAX_DIGITS) {
+ truncateFactor = (int) Math.pow(10, truncateFactor);
+ int fractionalDigits = result.getInteger(${type.storage} - 1);
+ fractionalDigits /= truncateFactor;
+ result.setInteger(${type.storage} - 1, fractionalDigits * truncateFactor);
+ }
+ } else if (right.value > left.scale) {
+ // Add fractional digits to the decimal
+
+ // Check if we need to shift the decimal digits to the left
+ if (newScaleRoundedUp > origScaleRoundedUp) {
+ int srcIndex = 0;
+ int destIndex = newScaleRoundedUp - origScaleRoundedUp;
+
+ // Check while extending scale, we are not overwriting integer part
+ while (srcIndex < destIndex) {
+ if (result.getInteger(srcIndex++) != 0) {
+ throw new org.apache.drill.common.exceptions.DrillRuntimeException("Truncate resulting in loss of integer part, reduce scale specified");
+ }
+ }
+
+ srcIndex = 0;
+ while (destIndex < ${type.storage}) {
+ result.setInteger(srcIndex++, result.getInteger(destIndex++));
+ }
+
+ // Clear the remaining part
+ while (srcIndex < ${type.storage}) {
+ result.setInteger(srcIndex++, 0);
+ }
+ }
+ }
+ }
+ }
+
+ @FunctionTemplate(name = "round", scope = FunctionTemplate.FunctionScope.DECIMAL_ZERO_SCALE, nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}RoundFunction implements DrillSimpleFunc {
+
+ @Param ${type.name}Holder in;
+ @Output ${type.name}Holder out;
+ public void setup(RecordBatch incoming) {
+
+ }
+
+ public void eval() {
+ out.scale = 0;
+ out.precision = in.precision;
+ out.buffer = in.buffer;
+ out.start = in.start;
+ out.sign = in.sign;
+
+ boolean roundUp = false;
+
+ // Get the first fractional digit to see if want to round up or not
+ int scaleIndex = ${type.storage} - org.apache.drill.common.util.DecimalUtility.roundUp(in.scale);
+ if (scaleIndex < ${type.storage}) {
+ int fractionalPart = out.getInteger(scaleIndex);
+ int digit = fractionalPart / (org.apache.drill.common.util.DecimalUtility.DIGITS_BASE / 10);
+
+ if (digit > 4) {
+ roundUp = true;
+ }
+ }
+
+ // Integer part's src index
+ int srcIntIndex = scaleIndex - 1;
+
+ // Truncate the fractional part, move the integer part
+ int destIndex = ${type.storage} - 1;
+ while (srcIntIndex >= 0) {
+ out.setInteger(destIndex--, out.getInteger(srcIntIndex--));
+ }
+
+ // Set the remaining portion of the decimal to be zeroes
+ while (destIndex >= 0) {
+ out.setInteger(destIndex--, 0);
+ }
+
+ // Perform the roundup
+ srcIntIndex = ${type.storage} - 1;
+ if (roundUp == true) {
+ while (srcIntIndex >= 0) {
+ int value = out.getInteger(srcIntIndex) + 1;
+ if (value >= org.apache.drill.common.util.DecimalUtility.DIGITS_BASE) {
+ out.setInteger(srcIntIndex--, value % org.apache.drill.common.util.DecimalUtility.DIGITS_BASE);
+ value = value / org.apache.drill.common.util.DecimalUtility.DIGITS_BASE;
+ } else {
+ out.setInteger(srcIntIndex--, value);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ @FunctionTemplate(name = "round", scope = FunctionTemplate.FunctionScope.DECIMAL_SET_SCALE, nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}RoundScaleFunction implements DrillSimpleFunc {
+
+ @Param ${type.name}Holder left;
+ @Param IntHolder right;
+ @Output ${type.name}Holder result;
+ public void setup(RecordBatch incoming) {
+
+ }
+
+ public void eval() {
+ result.scale = right.value;
+ result.precision = left.precision;
+ result.buffer = left.buffer;
+ result.start = left.start;
+ result.sign = left.sign;
+
+ int newScaleRoundedUp = org.apache.drill.common.util.DecimalUtility.roundUp(right.value);
+ int origScaleRoundedUp = org.apache.drill.common.util.DecimalUtility.roundUp(left.scale);
+
+ if (right.value < left.scale) {
+
+ boolean roundUp = false;
+
+ //Extract the first digit to be truncated to check if we need to round up
+ int truncatedScaleIndex = right.value + 1;
+ if (truncatedScaleIndex <= left.scale) {
+ int extractDigitIndex = ${type.storage} - origScaleRoundedUp -1;
+ extractDigitIndex += org.apache.drill.common.util.DecimalUtility.roundUp(truncatedScaleIndex);
+ int extractDigit = result.getInteger(extractDigitIndex);
+ int temp = org.apache.drill.common.util.DecimalUtility.MAX_DIGITS - (truncatedScaleIndex % org.apache.drill.common.util.DecimalUtility.MAX_DIGITS);
+ if (temp != 0) {
+ extractDigit = extractDigit / (int) (Math.pow(10, temp));
+ }
+ if ((extractDigit % 10) > 4) {
+ roundUp = true;
+ }
+ }
+
+ // Get the source index beyond which we will truncate
+ int srcIntIndex = ${type.storage} - origScaleRoundedUp - 1;
+ int srcIndex = srcIntIndex + newScaleRoundedUp;
+
+ // Truncate the remaining fractional part, move the integer part
+ int destIndex = ${type.storage} - 1;
+ if (srcIndex != destIndex) {
+ while (srcIndex >= 0) {
+ result.setInteger(destIndex--, result.getInteger(srcIndex--));
+ }
+
+ // Set the remaining portion of the decimal to be zeroes
+ while (destIndex >= 0) {
+ result.setInteger(destIndex--, 0);
+ }
+ srcIndex = ${type.storage} - 1;
+ }
+
+ // We truncated the decimal digit. Now we need to truncate within the base 1 billion fractional digit
+ int truncateFactor = org.apache.drill.common.util.DecimalUtility.MAX_DIGITS - (right.value % org.apache.drill.common.util.DecimalUtility.MAX_DIGITS);
+ if (truncateFactor != org.apache.drill.common.util.DecimalUtility.MAX_DIGITS) {
+ truncateFactor = (int) Math.pow(10, truncateFactor);
+ int fractionalDigits = result.getInteger(${type.storage} - 1);
+ fractionalDigits /= truncateFactor;
+ result.setInteger(${type.storage} - 1, fractionalDigits * truncateFactor);
+ }
+
+ // Finally round up the digit if needed
+ if (roundUp == true) {
+ srcIndex = ${type.storage} - 1;
+ int carry;
+ if (truncateFactor != org.apache.drill.common.util.DecimalUtility.MAX_DIGITS) {
+ carry = truncateFactor;
+ } else {
+ carry = 1;
+ }
+
+ while (srcIndex >= 0) {
+ int value = result.getInteger(srcIndex);
+ value += carry;
+
+ if (value >= org.apache.drill.common.util.DecimalUtility.DIGITS_BASE) {
+ result.setInteger(srcIndex--, value % org.apache.drill.common.util.DecimalUtility.DIGITS_BASE);
+ carry = value / org.apache.drill.common.util.DecimalUtility.DIGITS_BASE;
+ } else {
+ result.setInteger(srcIndex--, value);
+ carry = 0;
+ break;
+ }
+ }
+ }
+ } else if (right.value > left.scale) {
+ // Add fractional digits to the decimal
+
+ // Check if we need to shift the decimal digits to the left
+ if (newScaleRoundedUp > origScaleRoundedUp) {
+ int srcIndex = 0;
+ int destIndex = newScaleRoundedUp - origScaleRoundedUp;
+
+ // Check while extending scale, we are not overwriting integer part
+ while (srcIndex < destIndex) {
+ if (result.getInteger(srcIndex++) != 0) {
+ throw new org.apache.drill.common.exceptions.DrillRuntimeException("Truncate resulting in loss of integer part, reduce scale specified");
+ }
+ }
+
+ srcIndex = 0;
+ while (destIndex < ${type.storage}) {
+ result.setInteger(srcIndex++, result.getInteger(destIndex++));
+ }
+
+ // Clear the remaining part
+ while (srcIndex < ${type.storage}) {
+ result.setInteger(srcIndex++, 0);
+ }
+ }
+ }
+ }
+ }
@FunctionTemplate(name = "compare_to", scope = FunctionTemplate.FunctionScope.DECIMAL_MAX_SCALE, nulls = NullHandling.NULL_IF_NULL)
public static class ${type.name}CompareTo implements DrillSimpleFunc {
@@ -793,9 +1150,7 @@ public class ${type.name}Functions {
public void setup(RecordBatch incoming) {}
public void eval() {
- int cmp;
- <@denseCompareBlock left="left" right="right" output="cmp"/>
- out.value = cmp;
+ out.value = org.apache.drill.common.util.DecimalUtility.compareDenseBytes(left.buffer, left.start, left.sign, right.buffer, right.start, right.sign, left.WIDTH);
}
}
@@ -808,8 +1163,7 @@ public class ${type.name}Functions {
public void setup(RecordBatch incoming) {}
public void eval() {
- int cmp;
- <@denseCompareBlock left="left" right="right" output="cmp"/>
+ int cmp = org.apache.drill.common.util.DecimalUtility.compareDenseBytes(left.buffer, left.start, left.sign, right.buffer, right.start, right.sign, left.WIDTH);
out.value = cmp == -1 ? 1 : 0;
}
}
@@ -823,8 +1177,7 @@ public class ${type.name}Functions {
public void setup(RecordBatch incoming) {}
public void eval() {
- int cmp;
- <@denseCompareBlock left="left" right="right" output="cmp"/>
+ int cmp = org.apache.drill.common.util.DecimalUtility.compareDenseBytes(left.buffer, left.start, left.sign, right.buffer, right.start, right.sign, left.WIDTH);
out.value = cmp < 1 ? 1 : 0;
}
}
@@ -838,8 +1191,7 @@ public class ${type.name}Functions {
public void setup(RecordBatch incoming) {}
public void eval() {
- int cmp;
- <@denseCompareBlock left="left" right="right" output="cmp"/>
+ int cmp = org.apache.drill.common.util.DecimalUtility.compareDenseBytes(left.buffer, left.start, left.sign, right.buffer, right.start, right.sign, left.WIDTH);
out.value = cmp == 1 ? 1 : 0;
}
}
@@ -853,8 +1205,7 @@ public class ${type.name}Functions {
public void setup(RecordBatch incoming) {}
public void eval() {
- int cmp;
- <@denseCompareBlock left="left" right="right" output="cmp"/>
+ int cmp = org.apache.drill.common.util.DecimalUtility.compareDenseBytes(left.buffer, left.start, left.sign, right.buffer, right.start, right.sign, left.WIDTH);
out.value = cmp > -1 ? 1 : 0;
}
}
@@ -868,8 +1219,7 @@ public class ${type.name}Functions {
public void setup(RecordBatch incoming) {}
public void eval() {
- int cmp;
- <@denseCompareBlock left="left" right="right" output="cmp"/>
+ int cmp = org.apache.drill.common.util.DecimalUtility.compareDenseBytes(left.buffer, left.start, left.sign, right.buffer, right.start, right.sign, left.WIDTH);
out.value = cmp == 0 ? 1 : 0;
}
}
@@ -885,8 +1235,7 @@ public class ${type.name}Functions {
public void eval() {
- int cmp;
- <@denseCompareBlock left="left" right="right" output="cmp"/>
+ int cmp = org.apache.drill.common.util.DecimalUtility.compareDenseBytes(left.buffer, left.start, left.sign, right.buffer, right.start, right.sign, left.WIDTH);
out.value = cmp != 0 ? 1 : 0;
}
}
@@ -904,6 +1253,7 @@ import org.apache.drill.exec.expr.annotations.FunctionTemplate;
import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling;
import org.apache.drill.exec.expr.annotations.Output;
import org.apache.drill.exec.expr.annotations.Param;
+import org.apache.drill.exec.expr.annotations.Workspace;
import org.apache.drill.exec.expr.holders.*;
import org.apache.drill.exec.record.RecordBatch;
import io.netty.buffer.ByteBuf;
@@ -966,6 +1316,252 @@ public class ${type.name}Functions {
}
}
+ @FunctionTemplate(name = "abs", scope = FunctionTemplate.FunctionScope.DECIMAL_MAX_SCALE, nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}AbsFunction implements DrillSimpleFunc {
+
+ @Param ${type.name}Holder in;
+ @Output ${type.name}Holder out;
+
+ public void setup(RecordBatch incoming) {}
+
+ public void eval() {
+ out.precision = out.maxPrecision;
+ out.scale = in.scale;
+
+ out.value = in.value;
+
+ if (out.value < 0){
+ out.value *= -1;
+ }
+ }
+ }
+
+ @FunctionTemplate(name = "divide", scope = FunctionTemplate.FunctionScope.DECIMAL_DIV_SCALE, nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}DivideFunction implements DrillSimpleFunc {
+
+ @Param ${type.name}Holder left;
+ @Param ${type.name}Holder right;
+ @Output ${type.name}Holder result;
+
+ public void setup(RecordBatch incoming) {}
+
+ public void eval() {
+
+ result.scale = left.scale;
+
+ java.math.BigDecimal numerator = new java.math.BigDecimal(java.math.BigInteger.valueOf(left.value), left.scale);
+ java.math.BigDecimal denominator = new java.math.BigDecimal(java.math.BigInteger.valueOf(right.value), right.scale);
+
+ java.math.BigDecimal output = numerator.divide(denominator, (int) result.scale, java.math.BigDecimal.ROUND_DOWN);
+
+ result.value = output.unscaledValue().${type.storage}Value();
+ }
+ }
+
+ @FunctionTemplate(name = "mod", scope = FunctionTemplate.FunctionScope.DECIMAL_DIV_SCALE, nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}ModFunction implements DrillSimpleFunc {
+
+ @Param ${type.name}Holder left;
+ @Param ${type.name}Holder right;
+ @Output ${type.name}Holder result;
+
+ public void setup(RecordBatch incoming) {}
+
+ public void eval() {
+
+ java.math.BigDecimal numerator = new java.math.BigDecimal(java.math.BigInteger.valueOf(left.value), left.scale);
+ java.math.BigDecimal denominator = new java.math.BigDecimal(java.math.BigInteger.valueOf(right.value), right.scale);
+
+ java.math.BigDecimal output = numerator.remainder(denominator);
+ output.setScale(left.scale, java.math.BigDecimal.ROUND_DOWN);
+
+ result.value = output.unscaledValue().${type.storage}Value();
+ result.precision = result.maxPrecision;
+ result.scale = left.scale;
+ }
+ }
+
+ @FunctionTemplate(name = "sign", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}SignFunction implements DrillSimpleFunc {
+
+ @Param ${type.name}Holder in;
+ @Output IntHolder out;
+
+ public void setup(RecordBatch incoming) {}
+
+ public void eval() {
+
+ out.value = (in.value < 0) ? -1 : ((in.value > 0) ? 1 : 0);
+ }
+ }
+
+ @FunctionTemplate(names = {"trunc", "truncate"}, scope = FunctionTemplate.FunctionScope.DECIMAL_ZERO_SCALE, nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}TruncFunction implements DrillSimpleFunc {
+
+ @Param ${type.name}Holder in;
+ @Output ${type.name}Holder out;
+
+ public void setup(RecordBatch incoming) {}
+
+ public void eval() {
+
+ out.value =(${type.storage}) (in.value / (Math.pow(10, in.scale)));
+ out.precision = out.maxPrecision;
+ out.scale = 0;
+ }
+ }
+
+ @FunctionTemplate(names = {"trunc", "truncate"}, scope = FunctionTemplate.FunctionScope.DECIMAL_SET_SCALE, nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}TruncateScaleFunction implements DrillSimpleFunc {
+
+ @Param ${type.name}Holder left;
+ @Param IntHolder right;
+ @Output ${type.name}Holder out;
+
+ public void setup(RecordBatch incoming) {}
+
+ public void eval() {
+
+ out.value = (${type.storage}) (left.value / ( Math.pow(10, (left.scale - right.value))));
+ out.precision = out.maxPrecision;
+ out.scale = right.value;
+ }
+ }
+
+ @FunctionTemplate(names = {"ceil", "ceiling"}, scope = FunctionTemplate.FunctionScope.DECIMAL_ZERO_SCALE, nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}CeilFunction implements DrillSimpleFunc {
+
+ @Param ${type.name}Holder in;
+ @Output ${type.name}Holder out;
+
+ public void setup(RecordBatch incoming) {
+
+ }
+
+ public void eval() {
+ ${type.storage} scaleFactor = (${type.storage}) (Math.pow(10, in.scale));
+
+ // Get the integer part
+ ${type.storage} integerPart = in.value / scaleFactor;
+
+ // Get the fractional part, if its non-zero increment the integer part
+ ${type.storage} fractionalPart = (${type.storage}) (in.value % scaleFactor);
+ if (fractionalPart != 0 && in.value >= 0) {
+ integerPart++;
+ }
+
+ out.scale = 0;
+ out.value = integerPart;
+ }
+ }
+
+ @FunctionTemplate(name = "floor", scope = FunctionTemplate.FunctionScope.DECIMAL_ZERO_SCALE, nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}FloorFunction implements DrillSimpleFunc {
+
+ @Param ${type.name}Holder in;
+ @Output ${type.name}Holder out;
+
+ public void setup(RecordBatch incoming) {
+ }
+
+ public void eval() {
+
+ ${type.storage} scaleFactor = (${type.storage}) (Math.pow(10, in.scale));
+ out.scale = 0;
+ out.value = (in.value / scaleFactor);
+
+ // For negative values we have to decrement by 1
+ if (in.value < 0) {
+ ${type.storage} fractionalPart = (${type.storage}) (in.value % scaleFactor);
+ if (fractionalPart != 0) {
+ out.value--;
+ }
+ }
+ }
+ }
+
+ @FunctionTemplate(name = "round", scope = FunctionTemplate.FunctionScope.DECIMAL_ZERO_SCALE, nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}RoundFunction implements DrillSimpleFunc {
+
+ @Param ${type.name}Holder in;
+ @Output ${type.name}Holder out;
+
+ public void setup(RecordBatch incoming) {
+ }
+
+ public void eval() {
+
+ ${type.storage} scaleFactor = (${type.storage}) (Math.pow(10, in.scale));
+ ${type.storage} extractDigit = scaleFactor / 10;
+
+ out.scale = 0;
+ // Assign the integer part to the output
+ out.value = in.value / scaleFactor;
+
+ // Get the fractional part
+ ${type.storage} fractionalPart = in.value % scaleFactor;
+ // Get the first digit to check for rounding
+ int digit = Math.abs((int) (fractionalPart / extractDigit));
+
+ if (digit > 4) {
+ if (in.value > 0) {
+ out.value++;
+ } else if (in.value < 0) {
+ out.value--;
+ }
+ }
+ }
+ }
+
+ @FunctionTemplate(name = "round", scope = FunctionTemplate.FunctionScope.DECIMAL_SET_SCALE, nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}RoundScaleFunction implements DrillSimpleFunc {
+
+ @Param ${type.name}Holder left;
+ @Param IntHolder right;
+ @Output ${type.name}Holder out;
+
+
+ public void setup(RecordBatch incoming) {
+ }
+
+ public void eval() {
+
+ ${type.storage} scaleFactor = (${type.storage}) (Math.pow(10, left.scale));
+ ${type.storage} newScaleFactor = (${type.storage}) (Math.pow(10, right.value));
+ ${type.storage} truncScaleFactor = (${type.storage}) (Math.pow(10, left.scale - right.value));
+
+ // If rounding scale is >= current scale
+ if (right.value >= left.scale) {
+ out.value = (${type.storage}) (left.value * (int) Math.pow(10, (right.value - left.scale)));
+ }
+ else {
+ out.scale = right.value;
+ // Assign the integer part to the output
+ out.value = left.value / scaleFactor;
+
+ // Get the fractional part
+ ${type.storage} fractionalPart = left.value % scaleFactor;
+
+ // From the entire fractional part extract the digits upto which rounding is needed
+ ${type.storage} newFractionalPart = fractionalPart / truncScaleFactor;
+ ${type.storage} truncatedFraction = fractionalPart % truncScaleFactor;
+
+
+ // Get the truncated fractional part and extract the first digit to see if we need to add 1
+ int digit = Math.abs((int) (truncatedFraction / (truncScaleFactor / 10)));
+
+ if (digit > 4) {
+ if (left.value > 0) {
+ newFractionalPart++;
+ } else if (left.value < 0) {
+ newFractionalPart--;
+ }
+ }
+
+ out.value = (out.value * newScaleFactor) + newFractionalPart;
+ }
+ }
+ }
@FunctionTemplate(name = "compare_to", scope = FunctionTemplate.FunctionScope.DECIMAL_MAX_SCALE, nulls = NullHandling.NULL_IF_NULL)
public static class ${type.name}CompareTo implements DrillSimpleFunc {
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/88e31534/exec/java-exec/src/main/codegen/templates/DecimalAggrTypeFunctions1.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/codegen/templates/DecimalAggrTypeFunctions1.java b/exec/java-exec/src/main/codegen/templates/DecimalAggrTypeFunctions1.java
new file mode 100644
index 0000000..b899986
--- /dev/null
+++ b/exec/java-exec/src/main/codegen/templates/DecimalAggrTypeFunctions1.java
@@ -0,0 +1,200 @@
+/**
+ * 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
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+<@pp.dropOutputFile />
+
+
+
+<#list decimalaggrtypes1.aggrtypes as aggrtype>
+<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gaggr/Decimal${aggrtype.className}Functions.java" />
+
+<#include "/@includes/license.ftl" />
+
+<#-- A utility class that is used to generate java code for aggr functions for decimal data type that maintain a single -->
+<#-- running counter to hold the result. This includes: MIN, MAX, COUNT. -->
+
+/*
+ * This class is automatically generated from AggrTypeFunctions1.tdd using FreeMarker.
+ */
+
+package org.apache.drill.exec.expr.fn.impl.gaggr;
+
+import org.apache.drill.exec.expr.DrillAggFunc;
+import org.apache.drill.exec.expr.annotations.FunctionTemplate;
+import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionScope;
+import org.apache.drill.exec.expr.annotations.Output;
+import org.apache.drill.exec.expr.annotations.Param;
+import org.apache.drill.exec.expr.annotations.Workspace;
+import org.apache.drill.exec.expr.holders.*;
+import org.apache.drill.exec.record.RecordBatch;
+import io.netty.buffer.ByteBuf;
+
+@SuppressWarnings("unused")
+
+public class Decimal${aggrtype.className}Functions {
+ static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(${aggrtype.className}Functions.class);
+
+<#list aggrtype.types as type>
+
+@FunctionTemplate(name = "${aggrtype.funcName}", scope = FunctionTemplate.FunctionScope.DECIMAL_AGGREGATE)
+public static class ${type.inputType}${aggrtype.className} implements DrillAggFunc{
+
+ @Param ${type.inputType}Holder in;
+ @Workspace ${type.runningType}Holder value;
+ @Workspace ByteBuf buffer;
+ @Output ${type.outputType}Holder out;
+
+ public void setup(RecordBatch b) {
+ value = new ${type.runningType}Holder();
+ <#if aggrtype.funcName == "count">
+ value.value = 0;
+ <#elseif aggrtype.funcName == "max" || aggrtype.funcName == "min">
+ <#if type.outputType.endsWith("Dense") || type.outputType.endsWith("Sparse")>
+ buffer = io.netty.buffer.Unpooled.wrappedBuffer(new byte[value.WIDTH]);
+ buffer = new io.netty.buffer.SwappedByteBuf(buffer);
+ value.buffer = buffer;
+ value.start = 0;
+ for (int i = 0; i < value.nDecimalDigits; i++) {
+ value.setInteger(i, 0xFFFFFFFF);
+ }
+ <#if aggrtype.funcName == "min">
+ // Set sign to be positive so initial value is maximum
+ value.sign = false;
+ <#elseif aggrtype.funcName == "max">
+ value.sign = true;
+ </#if>
+ <#elseif type.outputType == "Decimal9" || type.outputType == "Decimal18">
+ value.value = ${type.initValue};
+ </#if>
+ </#if>
+
+ }
+
+ @Override
+ public void add() {
+ <#if type.inputType?starts_with("Nullable")>
+ sout: {
+ if (in.isSet == 0) {
+ // processing nullable input and the value is null, so don't do anything...
+ break sout;
+ }
+ </#if>
+ <#if aggrtype.funcName == "count">
+ value.value++;
+ <#elseif aggrtype.funcName == "max">
+ <#if type.outputType.endsWith("Dense")>
+ int cmp = org.apache.drill.common.util.DecimalUtility.compareDenseBytes(in.buffer, in.start, in.sign, value.buffer, value.start, value.sign, in.WIDTH);
+ if (cmp == 1) {
+ in.buffer.getBytes(in.start, value.buffer, 0, value.WIDTH);
+ value.sign = in.sign;
+ value.scale = in.scale;
+ value.precision = in.precision;
+ }
+ <#elseif type.outputType.endsWith("Sparse")>
+ int cmp = org.apache.drill.common.util.DecimalUtility.compareSparseBytes(in.buffer, in.start, in.sign,
+ in.scale, in.precision, value.buffer,
+ value.start, value.sign, value.precision,
+ value.scale, in.WIDTH, in.nDecimalDigits, false);
+ if (cmp == 1) {
+ in.buffer.getBytes(in.start, value.buffer, 0, value.WIDTH);
+ value.sign = in.sign;
+ value.scale = in.scale;
+ value.precision = in.precision;
+ }
+ <#elseif type.outputType == "Decimal9" || type.outputType == "Decimal18">
+ value.value = Math.max(value.value, in.value);
+ </#if>
+ <#elseif aggrtype.funcName == "min">
+ <#if type.outputType.endsWith("Dense")>
+ int cmp = org.apache.drill.common.util.DecimalUtility.compareDenseBytes(in.buffer, in.start, in.sign, value.buffer, value.start, value.sign, in.WIDTH);
+ if (cmp == -1) {
+ in.buffer.getBytes(in.start, value.buffer, 0, value.WIDTH);
+ value.sign = in.sign;
+ value.scale = in.scale;
+ value.precision = in.precision;
+ }
+ <#elseif type.outputType.endsWith("Sparse")>
+ int cmp = org.apache.drill.common.util.DecimalUtility.compareSparseBytes(in.buffer, in.start, in.sign,
+ in.scale, in.precision, value.buffer,
+ value.start, value.sign, value.precision,
+ value.scale, in.WIDTH, in.nDecimalDigits, false);
+ if (cmp == -1) {
+ in.buffer.getBytes(in.start, value.buffer, 0, value.WIDTH);
+ value.sign = in.sign;
+ value.scale = in.scale;
+ value.precision = in.precision;
+ }
+ <#elseif type.outputType == "Decimal9" || type.outputType == "Decimal18">
+ value.value = Math.min(value.value, in.value);
+ </#if>
+ </#if>
+ <#if type.inputType?starts_with("Nullable")>
+ } // end of sout block
+ </#if>
+ }
+
+ @Override
+ public void output() {
+ <#if aggrtype.funcName == "count">
+ out.value = value.value;
+ <#else>
+ <#if type.outputType.endsWith("Dense") || type.outputType.endsWith("Sparse")>
+ out.buffer = value.buffer;
+ out.start = value.start;
+ out.sign = value.sign;
+ <#elseif type.outputType == "Decimal9" || type.outputType == "Decimal18">
+ out.value = value.value;
+ </#if>
+ out.scale = value.scale;
+ out.precision = value.precision;
+ </#if>
+ }
+
+ @Override
+ public void reset() {
+
+ <#if aggrtype.funcName == "count">
+ value.value = 0;
+ <#elseif aggrtype.funcName == "max" || aggrtype.funcName == "min">
+ <#if type.outputType.endsWith("Dense") || type.outputType.endsWith("Sparse")>
+ buffer = io.netty.buffer.Unpooled.wrappedBuffer(new byte[value.WIDTH]);
+ buffer = new io.netty.buffer.SwappedByteBuf(buffer);
+ value.buffer = buffer;
+ value.start = 0;
+ for (int i = 0; i < value.nDecimalDigits; i++) {
+ value.setInteger(i, 0xFFFFFFFF);
+ }
+ <#if aggrtype.funcName == "min">
+ // Set sign to be positive so initial value is maximum
+ value.sign = false;
+ <#elseif aggrtype.funcName == "max">
+ value.sign = true;
+ </#if>
+ <#elseif type.outputType == "Decimal9" || type.outputType == "Decimal18">
+ value.value = ${type.initValue};
+ </#if>
+ </#if>
+
+ }
+
+ }
+
+
+</#list>
+}
+</#list>
+
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/88e31534/exec/java-exec/src/main/codegen/templates/FixedValueVectors.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/codegen/templates/FixedValueVectors.java b/exec/java-exec/src/main/codegen/templates/FixedValueVectors.java
index 781b5a1..f9916c9 100644
--- a/exec/java-exec/src/main/codegen/templates/FixedValueVectors.java
+++ b/exec/java-exec/src/main/codegen/templates/FixedValueVectors.java
@@ -662,7 +662,7 @@ public final class ${minor.class}Vector extends BaseDataValueVector implements F
public void set(int index, <#if (type.width >= 4)>${minor.javaType!type.javaType}<#else>int</#if> value) {
data.set${(minor.javaType!type.javaType)?cap_first}(index * ${type.width}, value);
}
-
+
public boolean setSafe(int index, <#if (type.width >= 4)>${minor.javaType!type.javaType}<#else>int</#if> value) {
if(index >= getValueCapacity()) {
allocationMonitor--;
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/88e31534/exec/java-exec/src/main/codegen/templates/NumericToCharFunctions.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/codegen/templates/NumericToCharFunctions.java b/exec/java-exec/src/main/codegen/templates/NumericToCharFunctions.java
new file mode 100644
index 0000000..6615e33
--- /dev/null
+++ b/exec/java-exec/src/main/codegen/templates/NumericToCharFunctions.java
@@ -0,0 +1,83 @@
+/**
+ * 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
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.drill.exec.expr.annotations.Workspace;
+
+<@pp.dropOutputFile />
+
+<#list numericTypes.numeric as type>
+
+<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/G${type}ToChar.java" />
+
+<#include "/@includes/license.ftl" />
+
+package org.apache.drill.exec.expr.fn.impl;
+
+import org.apache.drill.exec.expr.DrillSimpleFunc;
+import org.apache.drill.exec.expr.annotations.FunctionTemplate;
+import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling;
+import org.apache.drill.exec.expr.annotations.Output;
+import org.apache.drill.exec.expr.annotations.Workspace;
+import org.apache.drill.exec.expr.annotations.Param;
+import org.apache.drill.exec.expr.holders.*;
+import org.apache.drill.exec.record.RecordBatch;
+
+import io.netty.buffer.ByteBuf;
+import java.text.NumberFormat;
+import java.text.DecimalFormat;
+
+@SuppressWarnings("unused")
+@FunctionTemplate(name = "to_char", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL)
+public class G${type}ToChar implements DrillSimpleFunc {
+
+ @Param ${type}Holder left;
+ @Param VarCharHolder right;
+ @Workspace ByteBuf buffer;
+ @Workspace java.text.NumberFormat outputFormat;
+ @Output VarCharHolder out;
+
+ public void setup(RecordBatch b) {
+ buffer = io.netty.buffer.Unpooled.wrappedBuffer(new byte[100]);
+ byte[] buf = new byte[right.end - right.start];
+ right.buffer.getBytes(right.start, buf, 0, right.end - right.start);
+ String inputFormat = new String(buf);
+ outputFormat = new java.text.DecimalFormat(inputFormat);
+ }
+
+ public void eval() {
+
+ <#if type == "Decimal9" || type == "Decimal18">
+ java.math.BigDecimal bigDecimal = new java.math.BigDecimal(java.math.BigInteger.valueOf(left.value), left.scale);
+ String str = outputFormat.format(bigDecimal);
+ <#elseif type == "Decimal28Sparse" || type == "Decimal38Sparse">
+ java.math.BigDecimal bigDecimal = org.apache.drill.common.util.DecimalUtility.getBigDecimalFromByteBuf(left.buffer, left.start, left.nDecimalDigits, left.scale, true);
+ String str = outputFormat.format(bigDecimal);
+ <#elseif type == "Decimal28Dense" || type == "Decimal38Dense">
+ java.math.BigDecimal bigDecimal = org.apache.drill.common.util.DecimalUtility.getBigDecimalFromDense(left.buffer, left.start, left.nDecimalDigits, left.scale, left.maxPrecision, left.WIDTH);
+ String str = outputFormat.format(bigDecimal);
+ <#else>
+ String str = outputFormat.format(left.value);
+ </#if>
+ out.buffer = buffer;
+ out.start = 0;
+ out.end = Math.min(100, str.length()); // truncate if target type has length smaller than that of input's string
+ out.buffer.setBytes(0, str.substring(0,out.end).getBytes());
+
+ }
+}
+</#list>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/88e31534/exec/java-exec/src/main/java/org/apache/drill/exec/expr/annotations/FunctionTemplate.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/annotations/FunctionTemplate.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/annotations/FunctionTemplate.java
index 53c9952..9d7091d 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/annotations/FunctionTemplate.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/annotations/FunctionTemplate.java
@@ -51,6 +51,16 @@ public @interface FunctionTemplate {
}
public static enum FunctionScope{
- SIMPLE, POINT_AGGREGATE, HOLISTIC_AGGREGATE, RANGE_AGGREGATE, DECIMAL_MAX_SCALE, DECIMAL_SUM_SCALE, DECIMAL_CAST;
+ SIMPLE,
+ POINT_AGGREGATE,
+ DECIMAL_AGGREGATE,
+ HOLISTIC_AGGREGATE,
+ RANGE_AGGREGATE,
+ DECIMAL_MAX_SCALE,
+ DECIMAL_SUM_SCALE,
+ DECIMAL_CAST,
+ DECIMAL_DIV_SCALE,
+ DECIMAL_SET_SCALE,
+ DECIMAL_ZERO_SCALE;
}
}