Repository: incubator-drill Updated Branches: refs/heads/master dcc94a398 -> 810a20409
DRILL-1110: Output precision of functions should always be greater or equal to input precision Project: http://git-wip-us.apache.org/repos/asf/incubator-drill/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-drill/commit/e1cf5c2e Tree: http://git-wip-us.apache.org/repos/asf/incubator-drill/tree/e1cf5c2e Diff: http://git-wip-us.apache.org/repos/asf/incubator-drill/diff/e1cf5c2e Branch: refs/heads/master Commit: e1cf5c2e930e645c7085aae318796bf536ea8c10 Parents: e987e06 Author: Mehant Baid <[email protected]> Authored: Sun Jul 6 09:57:01 2014 -0700 Committer: Jacques Nadeau <[email protected]> Committed: Mon Jul 7 14:50:31 2014 -0700 ---------------------------------------------------------------------- .../DecimalScalePrecisionDivideFunction.java | 5 +- .../util/DecimalScalePrecisionModFunction.java | 43 +++++++++++ .../templates/Decimal/DecimalFunctions.java | 4 +- .../exec/expr/annotations/FunctionTemplate.java | 1 + .../expr/fn/DrillDecimalModScaleFuncHolder.java | 79 ++++++++++++++++++++ .../drill/exec/expr/fn/FunctionConverter.java | 3 + 6 files changed, 132 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/e1cf5c2e/common/src/main/java/org/apache/drill/common/util/DecimalScalePrecisionDivideFunction.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/drill/common/util/DecimalScalePrecisionDivideFunction.java b/common/src/main/java/org/apache/drill/common/util/DecimalScalePrecisionDivideFunction.java index c4b33e4..4d3b939 100644 --- a/common/src/main/java/org/apache/drill/common/util/DecimalScalePrecisionDivideFunction.java +++ b/common/src/main/java/org/apache/drill/common/util/DecimalScalePrecisionDivideFunction.java @@ -45,7 +45,7 @@ public class DecimalScalePrecisionDivideFunction extends DrillBaseComputeScalePr @Override public void computeScalePrecision(int leftPrecision, int leftScale, int rightPrecision, int rightScale) { - // compute the output scale and precision here + // compute the output scale and precision here outputScale = leftScale + rightScale; int leftIntegerDigits = leftPrecision - leftScale; int maxResultIntegerDigits = leftIntegerDigits + rightScale; @@ -53,6 +53,9 @@ public class DecimalScalePrecisionDivideFunction extends DrillBaseComputeScalePr outputPrecision = DecimalUtility.getPrecisionRange(outputScale + maxResultIntegerDigits); + // Output precision should be greater or equal to the input precision + outputPrecision = Math.max(outputPrecision, Math.max(leftPrecision, rightPrecision)); + // Try and increase the scale if we have any room outputScale = (outputPrecision - maxResultIntegerDigits >= 0) ? (outputPrecision - maxResultIntegerDigits) : 0; } http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/e1cf5c2e/common/src/main/java/org/apache/drill/common/util/DecimalScalePrecisionModFunction.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/drill/common/util/DecimalScalePrecisionModFunction.java b/common/src/main/java/org/apache/drill/common/util/DecimalScalePrecisionModFunction.java new file mode 100644 index 0000000..e1e587b --- /dev/null +++ b/common/src/main/java/org/apache/drill/common/util/DecimalScalePrecisionModFunction.java @@ -0,0 +1,43 @@ +/** + * 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. + */ + +package org.apache.drill.common.util; + +public class DecimalScalePrecisionModFunction extends DrillBaseComputeScalePrecision { + + public DecimalScalePrecisionModFunction(int leftPrecision, int leftScale, int rightPrecision, int rightScale) { + super(leftPrecision, leftScale, rightPrecision, rightScale); + } + + @Override + public void computeScalePrecision(int leftPrecision, int leftScale, int rightPrecision, int rightScale) { + + // compute the output scale and precision here + outputScale = Math.max(leftScale, rightScale); + int leftIntegerDigits = leftPrecision - leftScale; + + outputPrecision = DecimalUtility.getPrecisionRange(outputScale + leftIntegerDigits); + + if (outputScale + leftIntegerDigits > outputPrecision) { + outputScale = outputPrecision - leftIntegerDigits; + } + + // Output precision should atleast be greater or equal to the input precision + outputPrecision = Math.max(outputPrecision, Math.max(leftPrecision, rightPrecision)); + } +} http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/e1cf5c2e/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 27279f0..b5a69f1 100644 --- a/exec/java-exec/src/main/codegen/templates/Decimal/DecimalFunctions.java +++ b/exec/java-exec/src/main/codegen/templates/Decimal/DecimalFunctions.java @@ -556,7 +556,7 @@ public class ${type.name}Functions { } } - @FunctionTemplate(name = "mod", scope = FunctionTemplate.FunctionScope.DECIMAL_DIV_SCALE, nulls = NullHandling.NULL_IF_NULL) + @FunctionTemplate(name = "mod", scope = FunctionTemplate.FunctionScope.DECIMAL_MOD_SCALE, nulls = NullHandling.NULL_IF_NULL) public static class ${type.name}ModFunction implements DrillSimpleFunc { @Param ${type.name}Holder left; @@ -1355,7 +1355,7 @@ public class ${type.name}Functions { } } - @FunctionTemplate(name = "mod", scope = FunctionTemplate.FunctionScope.DECIMAL_DIV_SCALE, nulls = NullHandling.NULL_IF_NULL) + @FunctionTemplate(name = "mod", scope = FunctionTemplate.FunctionScope.DECIMAL_MOD_SCALE, nulls = NullHandling.NULL_IF_NULL) public static class ${type.name}ModFunction implements DrillSimpleFunc { @Param ${type.name}Holder left; http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/e1cf5c2e/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 78a22d8..bd4b7f1 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 @@ -63,6 +63,7 @@ public @interface FunctionTemplate { DECIMAL_MUL_SCALE, DECIMAL_CAST, DECIMAL_DIV_SCALE, + DECIMAL_MOD_SCALE, DECIMAL_ADD_SCALE, DECIMAL_SET_SCALE, DECIMAL_ZERO_SCALE, http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/e1cf5c2e/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalModScaleFuncHolder.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalModScaleFuncHolder.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalModScaleFuncHolder.java new file mode 100644 index 0000000..2cf1088 --- /dev/null +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalModScaleFuncHolder.java @@ -0,0 +1,79 @@ +/** + * 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. + */ +package org.apache.drill.exec.expr.fn; + +import java.util.List; +import java.util.Map; + +import org.apache.drill.common.expression.LogicalExpression; +import org.apache.drill.common.types.TypeProtos; +import org.apache.drill.common.types.TypeProtos.MajorType; + +import org.apache.drill.common.util.DecimalScalePrecisionDivideFunction; +import org.apache.drill.common.util.DecimalScalePrecisionModFunction; +import org.apache.drill.common.util.DecimalUtility; +import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionScope; +import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling; + +public class DrillDecimalModScaleFuncHolder extends DrillSimpleFuncHolder{ + + + public DrillDecimalModScaleFuncHolder(FunctionScope scope, NullHandling nullHandling, boolean isBinaryCommutative, boolean isRandom, + String[] registeredNames, ValueReference[] parameters, ValueReference returnValue, WorkspaceReference[] workspaceVars, + Map<String, String> methods, List<String> imports) { + super(scope, nullHandling, isBinaryCommutative, isRandom, registeredNames, parameters, returnValue, workspaceVars, methods, imports); + } + + /* + * This function scope is used by divide functions for decimal data type. + * DecimalScalePrecisionDivideFunction is used to compute the output types' + * scale and precision + */ + @Override + public MajorType getReturnType(List<LogicalExpression> args) { + + TypeProtos.DataMode mode = returnValue.type.getMode(); + + if (nullHandling == NullHandling.NULL_IF_NULL) { + // if any one of the input types is nullable, then return nullable return type + for (LogicalExpression e : args) { + if (e.getMajorType().getMode() == TypeProtos.DataMode.OPTIONAL) { + mode = TypeProtos.DataMode.OPTIONAL; + break; + } + } + } + + + /* Get the result's scale and precision. This is a function scope for Divide function, assert we have + * only two inputs + */ + assert args.size() == 2; + + DecimalScalePrecisionModFunction outputScalePrec = + new DecimalScalePrecisionModFunction(args.get(0).getMajorType().getPrecision(), args.get(0).getMajorType().getScale(), + args.get(1).getMajorType().getPrecision(), args.get(1).getMajorType().getScale()); + return (TypeProtos.MajorType.newBuilder().setMinorType(DecimalUtility.getDecimalDataType(outputScalePrec.getOutputPrecision())) + .setScale(outputScalePrec.getOutputScale()).setPrecision(outputScalePrec.getOutputPrecision()).setMode(mode).build()); + } + + @Override + public boolean checkPrecisionRange() { + return true; + } +} http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/e1cf5c2e/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/FunctionConverter.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/FunctionConverter.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/FunctionConverter.java index 1d7dd0b..64f45c7 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/FunctionConverter.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/FunctionConverter.java @@ -259,6 +259,9 @@ public class FunctionConverter { case DECIMAL_DIV_SCALE: return new DrillDecimalDivScaleFuncHolder(template.scope(), template.nulls(), template.isBinaryCommutative(), template.isRandom(), registeredNames, ps, outputField, works, methods, imports); + case DECIMAL_MOD_SCALE: + return new DrillDecimalModScaleFuncHolder(template.scope(), template.nulls(), template.isBinaryCommutative(), + template.isRandom(), registeredNames, ps, outputField, works, methods, imports); case DECIMAL_SET_SCALE: return new DrillDecimalSetScaleFuncHolder(template.scope(), template.nulls(), template.isBinaryCommutative(), template.isRandom(), registeredNames, ps, outputField, works, methods, imports);
