FAQ
Author: ehans
Date: Thu Jan 30 18:12:44 2014
New Revision: 1562910

URL: http://svn.apache.org/r1562910
Log:
HIVE-6139: implement vectorized decimal division and modulo (Eric Hanson, reviewed by Jitendra Pandey)

Added:
     hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnDivideColumnDecimal.txt
     hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnDivideScalarDecimal.txt
     hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ScalarDivideColumnDecimal.txt
Removed:
     hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/DecimalColAddDecimalColumn.java
Modified:
     hive/trunk/ant/src/org/apache/hadoop/hive/ant/GenVectorCode.java
     hive/trunk/common/src/java/org/apache/hadoop/hive/common/type/Decimal128.java
     hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnArithmeticScalarDecimal.txt
     hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/FilterDecimalColumnCompareColumn.txt
     hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/DecimalUtil.java
     hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/NullUtil.java
     hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/exec/vector/expressions/TestVectorArithmeticExpressions.java

Modified: hive/trunk/ant/src/org/apache/hadoop/hive/ant/GenVectorCode.java
URL: http://svn.apache.org/viewvc/hive/trunk/ant/src/org/apache/hadoop/hive/ant/GenVectorCode.java?rev=1562910&r1=1562909&r2=1562910&view=diff
==============================================================================
--- hive/trunk/ant/src/org/apache/hadoop/hive/ant/GenVectorCode.java (original)
+++ hive/trunk/ant/src/org/apache/hadoop/hive/ant/GenVectorCode.java Thu Jan 30 18:12:44 2014
@@ -119,6 +119,15 @@ public class GenVectorCode extends Task
        {"ColumnArithmeticColumnDecimal", "Subtract"},
        {"ColumnArithmeticColumnDecimal", "Multiply"},

+ {"ColumnDivideScalarDecimal", "Divide"},
+ {"ColumnDivideScalarDecimal", "Modulo"},
+
+ {"ScalarDivideColumnDecimal", "Divide"},
+ {"ScalarDivideColumnDecimal", "Modulo"},
+
+ {"ColumnDivideColumnDecimal", "Divide"},
+ {"ColumnDivideColumnDecimal", "Modulo"},
+
        {"ColumnCompareScalar", "Equal", "long", "double", "=="},
        {"ColumnCompareScalar", "Equal", "double", "double", "=="},
        {"ColumnCompareScalar", "NotEqual", "long", "double", "!="},
@@ -578,6 +587,12 @@ public class GenVectorCode extends Task
          generateScalarArithmeticColumnDecimal(tdesc);
        } else if (tdesc[0].equals("ColumnArithmeticColumnDecimal")) {
          generateColumnArithmeticColumnDecimal(tdesc);
+ } else if (tdesc[0].equals("ColumnDivideScalarDecimal")) {
+ generateColumnDivideScalarDecimal(tdesc);
+ } else if (tdesc[0].equals("ScalarDivideColumnDecimal")) {
+ generateScalarDivideColumnDecimal(tdesc);
+ } else if (tdesc[0].equals("ColumnDivideColumnDecimal")) {
+ generateColumnDivideColumnDecimal(tdesc);
        } else if (tdesc[0].equals("ColumnCompareScalar")) {
          generateColumnCompareScalar(tdesc);
        } else if (tdesc[0].equals("ScalarCompareColumn")) {
@@ -1203,6 +1218,48 @@ public class GenVectorCode extends Task
         className, templateString);
    }

+ private void generateColumnDivideScalarDecimal(String[] tdesc) throws IOException {
+ String operatorName = tdesc[1];
+ String className = "DecimalCol" + getInitialCapWord(operatorName) + "DecimalScalar";
+
+ // Read the template into a string;
+ File templateFile = new File(joinPath(this.expressionTemplateDirectory, tdesc[0] + ".txt"));
+ String templateString = readFile(templateFile);
+ templateString = templateString.replaceAll("<ClassName>", className);
+ templateString = templateString.replaceAll("<Operator>", operatorName.toLowerCase());
+
+ writeFile(templateFile.lastModified(), expressionOutputDirectory, expressionClassesDirectory,
+ className, templateString);
+ }
+
+ private void generateScalarDivideColumnDecimal(String[] tdesc) throws IOException {
+ String operatorName = tdesc[1];
+ String className = "DecimalScalar" + getInitialCapWord(operatorName) + "DecimalColumn";
+
+ // Read the template into a string;
+ File templateFile = new File(joinPath(this.expressionTemplateDirectory, tdesc[0] + ".txt"));
+ String templateString = readFile(templateFile);
+ templateString = templateString.replaceAll("<ClassName>", className);
+ templateString = templateString.replaceAll("<Operator>", operatorName.toLowerCase());
+
+ writeFile(templateFile.lastModified(), expressionOutputDirectory, expressionClassesDirectory,
+ className, templateString);
+ }
+
+ private void generateColumnDivideColumnDecimal(String[] tdesc) throws IOException {
+ String operatorName = tdesc[1];
+ String className = "DecimalCol" + getInitialCapWord(operatorName) + "DecimalColumn";
+
+ // Read the template into a string;
+ File templateFile = new File(joinPath(this.expressionTemplateDirectory, tdesc[0] + ".txt"));
+ String templateString = readFile(templateFile);
+ templateString = templateString.replaceAll("<ClassName>", className);
+ templateString = templateString.replaceAll("<Operator>", operatorName.toLowerCase());
+
+ writeFile(templateFile.lastModified(), expressionOutputDirectory, expressionClassesDirectory,
+ className, templateString);
+ }
+
    private void generateScalarArithmeticColumn(String[] tdesc) throws IOException {
      String operatorName = tdesc[1];
      String operandType1 = tdesc[2];
@@ -1294,6 +1351,14 @@ public class GenVectorCode extends Task
      }
    }

+ /**
+ * Return the argument with the first letter capitalized
+ */
+ private static String getInitialCapWord(String word) {
+ String firstLetterAsCap = word.substring(0, 1).toUpperCase();
+ return firstLetterAsCap + word.substring(1);
+ }
+
    private String getArithmeticReturnType(String operandType1,
        String operandType2) {
      if (operandType1.equals("double") ||

Modified: hive/trunk/common/src/java/org/apache/hadoop/hive/common/type/Decimal128.java
URL: http://svn.apache.org/viewvc/hive/trunk/common/src/java/org/apache/hadoop/hive/common/type/Decimal128.java?rev=1562910&r1=1562909&r2=1562910&view=diff
==============================================================================
--- hive/trunk/common/src/java/org/apache/hadoop/hive/common/type/Decimal128.java (original)
+++ hive/trunk/common/src/java/org/apache/hadoop/hive/common/type/Decimal128.java Thu Jan 30 18:12:44 2014
@@ -1190,10 +1190,54 @@ public final class Decimal128 extends Nu
      HiveDecimal rightHD = HiveDecimal.create(right.toBigDecimal());
      HiveDecimal thisHD = HiveDecimal.create(this.toBigDecimal());
      HiveDecimal result = thisHD.divide(rightHD);
+
+ /* If the result is null, throw an exception. This can be caught
+ * by calling code in the vectorized code path and made to yield
+ * a SQL NULL value.
+ */
+ if (result == null) {
+ throw new ArithmeticException("null divide result");
+ }
      this.update(result.bigDecimalValue().toPlainString(), newScale);
      this.unscaledValue.throwIfExceedsTenToThirtyEight();
    }

+ /**
+ * Performs decimal modulo
+ * <p>
+ * The definition of modulo (x % p) is:
+ * x - IntegerPart(x / p, resultScale) * p
+ * </p>
+ *
+ * @left
+ * is x
+ * @right
+ * is p
+ * @result
+ * receives the result
+ * @scratch
+ * scratch space to avoid need to create a new object
+ * @scale
+ * scale of result
+ */
+ public static void modulo(Decimal128 left, Decimal128 right, Decimal128 result,
+ short scale) {
+
+ // set result to x / p (the quotient)
+ Decimal128.divide(left, right, result, scale);
+
+ // take integer part of it
+ result.zeroFractionPart();
+
+ // multiply by p
+ result.multiplyDestructive(right, scale);
+
+ // negate it
+ result.negateDestructive();
+
+ // add x to it
+ result.addDestructive(left, scale);
+ }

    /**
     * Makes this {@code Decimal128} a positive number. Unlike
@@ -1665,4 +1709,35 @@ public final class Decimal128 extends Nu
        this.signum = 1;
      }
    }
+
+ /**
+ * Zero the fractional part of value.
+ *
+ * Argument scratch is needed to hold unused remainder output, to avoid need to
+ * create a new object.
+ */
+ public void zeroFractionPart() {
+ short placesToRemove = this.getScale();
+
+ // If there's no fraction part, return immediately to avoid the cost of a divide.
+ if (placesToRemove == 0) {
+ return;
+ }
+
+ /* Divide by a power of 10 equal to 10**scale to logically shift the digits
+ * places right by "scale" positions to eliminate them.
+ */
+ UnsignedInt128 powerTenDivisor = SqlMathUtil.POWER_TENS_INT128[placesToRemove];
+
+ /* A scratch variable is created here. This could be optimized in the future
+ * by perhaps using thread-local storage to allocate this scratch field.
+ */
+ UnsignedInt128 scratch = new UnsignedInt128();
+ this.getUnscaledValue().divideDestructive(powerTenDivisor, scratch);
+
+ /* Multiply by the same power of ten to shift the decimal point back to
+ * the original place. Places to the right of the decimal will be zero.
+ */
+ this.getUnscaledValue().scaleUpTenDestructive(placesToRemove);
+ }
  }

Modified: hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnArithmeticScalarDecimal.txt
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnArithmeticScalarDecimal.txt?rev=1562910&r1=1562909&r2=1562910&view=diff
==============================================================================
--- hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnArithmeticScalarDecimal.txt (original)
+++ hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnArithmeticScalarDecimal.txt Thu Jan 30 18:12:44 2014
@@ -117,7 +117,10 @@ public class <ClassName> extends VectorE
        }
      }

- NullUtil.setNullDataEntriesDecimal(outputColVector, batch.selectedInUse, sel, n);
+ /*
+ * Null data entries are not set to a special non-zero value because all null math operations
+ * are checked, meaning that a zero-divide always results in a null result.
+ */
    }

    @Override

Added: hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnDivideColumnDecimal.txt
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnDivideColumnDecimal.txt?rev=1562910&view=auto
==============================================================================
--- hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnDivideColumnDecimal.txt (added)
+++ hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnDivideColumnDecimal.txt Thu Jan 30 18:12:44 2014
@@ -0,0 +1,177 @@
+/**
+ * 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.hadoop.hive.ql.exec.vector.expressions.gen;
+
+import org.apache.hadoop.hive.ql.exec.vector.expressions.VectorExpression;
+import org.apache.hadoop.hive.ql.exec.vector.DecimalColumnVector;
+import org.apache.hadoop.hive.ql.exec.vector.VectorizedRowBatch;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.NullUtil;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.DecimalUtil;
+import org.apache.hadoop.hive.ql.exec.vector.VectorExpressionDescriptor;
+import org.apache.hadoop.hive.common.type.Decimal128;
+
+/**
+ * Generated from template ColumnArithmeticColumnDecimal.txt, which covers binary arithmetic
+ * expressions between a column and a scalar.
+ */
+public class <ClassName> extends VectorExpression {
+
+ private static final long serialVersionUID = 1L;
+
+ private int colNum1;
+ private int colNum2;
+ private int outputColumn;
+
+ public <ClassName>(int colNum1, int colNum2, int outputColumn) {
+ this.colNum1 = colNum1;
+ this.colNum2 = colNum2;
+ this.outputColumn = outputColumn;
+ }
+
+ public <ClassName>() {
+ }
+
+ @Override
+ public void evaluate(VectorizedRowBatch batch) {
+
+ if (childExpressions != null) {
+ super.evaluateChildren(batch);
+ }
+
+ DecimalColumnVector inputColVector1 = (DecimalColumnVector) batch.cols[colNum1];
+ DecimalColumnVector inputColVector2 = (DecimalColumnVector) batch.cols[colNum2];
+ DecimalColumnVector outputColVector = (DecimalColumnVector) batch.cols[outputColumn];
+ int[] sel = batch.selected;
+ int n = batch.size;
+ Decimal128[] vector1 = inputColVector1.vector;
+ Decimal128[] vector2 = inputColVector2.vector;
+
+ // return immediately if batch is empty
+ if (n == 0) {
+ return;
+ }
+
+ outputColVector.isRepeating =
+ inputColVector1.isRepeating && inputColVector2.isRepeating
+ || inputColVector1.isRepeating && !inputColVector1.noNulls && inputColVector1.isNull[0]
+ || inputColVector2.isRepeating && !inputColVector2.noNulls && inputColVector2.isNull[0];
+
+ if (inputColVector1.noNulls && inputColVector2.noNulls) {
+
+ /* Initialize output vector NULL values to false. This is necessary
+ * since the decimal operation may produce a NULL result even for
+ * a non-null input vector value, and convert the output vector
+ * to have noNulls = false;
+ */
+ NullUtil.initOutputNullsToFalse(outputColVector,
+ inputColVector1.isRepeating && inputColVector2.isRepeating,
+ batch.selectedInUse, sel, n);
+ }
+
+ // Handle nulls first
+ NullUtil.propagateNullsColCol(
+ inputColVector1, inputColVector2, outputColVector, sel, n, batch.selectedInUse);
+
+ /* Disregard nulls for processing. In other words,
+ * the arithmetic operation is performed even if one or
+ * more inputs are null. This is to improve speed by avoiding
+ * conditional checks in the inner loop.
+ */
+ if (inputColVector1.isRepeating && inputColVector2.isRepeating) {
+ DecimalUtil.<Operator>Checked(0, vector1[0], vector2[0], outputColVector);
+ } else if (inputColVector1.isRepeating) {
+ if (batch.selectedInUse) {
+ for(int j = 0; j != n; j++) {
+ int i = sel[j];
+ DecimalUtil.<Operator>Checked(i, vector1[0], vector2[i], outputColVector);
+ }
+ } else {
+ for(int i = 0; i != n; i++) {
+ DecimalUtil.<Operator>Checked(i, vector1[0], vector2[i], outputColVector);
+ }
+ }
+ } else if (inputColVector2.isRepeating) {
+ if (batch.selectedInUse) {
+ for(int j = 0; j != n; j++) {
+ int i = sel[j];
+ DecimalUtil.<Operator>Checked(i, vector1[i], vector2[0], outputColVector);
+ }
+ } else {
+ for(int i = 0; i != n; i++) {
+ DecimalUtil.<Operator>Checked(i, vector1[i], vector2[0], outputColVector);
+ }
+ }
+ } else {
+ if (batch.selectedInUse) {
+ for(int j = 0; j != n; j++) {
+ int i = sel[j];
+ DecimalUtil.<Operator>Checked(i, vector1[i], vector2[i], outputColVector);
+ }
+ } else {
+ for(int i = 0; i != n; i++) {
+ DecimalUtil.<Operator>Checked(i, vector1[i], vector2[i], outputColVector);
+ }
+ }
+ }
+ }
+
+ @Override
+ public int getOutputColumn() {
+ return outputColumn;
+ }
+
+ @Override
+ public String getOutputType() {
+ return "decimal";
+ }
+
+ public int getColNum1() {
+ return colNum1;
+ }
+
+ public void setColNum1(int colNum1) {
+ this.colNum1 = colNum1;
+ }
+
+ public int getColNum2() {
+ return colNum2;
+ }
+
+ public void setColNum2(int colNum2) {
+ this.colNum2 = colNum2;
+ }
+
+ public void setOutputColumn(int outputColumn) {
+ this.outputColumn = outputColumn;
+ }
+
+ @Override
+ public VectorExpressionDescriptor.Descriptor getDescriptor() {
+ return (new VectorExpressionDescriptor.Builder())
+ .setMode(
+ VectorExpressionDescriptor.Mode.PROJECTION)
+ .setNumArguments(2)
+ .setArgumentTypes(
+ VectorExpressionDescriptor.ArgumentType.getType("decimal"),
+ VectorExpressionDescriptor.ArgumentType.getType("decimal"))
+ .setInputExpressionTypes(
+ VectorExpressionDescriptor.InputExpressionType.COLUMN,
+ VectorExpressionDescriptor.InputExpressionType.COLUMN).build();
+ }
+}

Added: hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnDivideScalarDecimal.txt
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnDivideScalarDecimal.txt?rev=1562910&view=auto
==============================================================================
--- hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnDivideScalarDecimal.txt (added)
+++ hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnDivideScalarDecimal.txt Thu Jan 30 18:12:44 2014
@@ -0,0 +1,181 @@
+/**
+ * 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.hadoop.hive.ql.exec.vector.expressions.gen;
+
+import org.apache.hadoop.hive.ql.exec.vector.expressions.VectorExpression;
+import org.apache.hadoop.hive.ql.exec.vector.DecimalColumnVector;
+import org.apache.hadoop.hive.ql.exec.vector.VectorizedRowBatch;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.NullUtil;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.DecimalUtil;
+import org.apache.hadoop.hive.ql.exec.vector.VectorExpressionDescriptor;
+import org.apache.hadoop.hive.common.type.Decimal128;
+
+/**
+ * Generated from template ColumnDivideScalarDecimal.txt, which covers binary arithmetic
+ * expressions between a column and a scalar.
+ */
+public class <ClassName> extends VectorExpression {
+
+ private static final long serialVersionUID = 1L;
+
+ private int colNum;
+ private Decimal128 value;
+ private int outputColumn;
+ private transient Decimal128 zero; // to hold constant 0 for later use
+
+ public <ClassName>(int colNum, Decimal128 value, int outputColumn) {
+ this.colNum = colNum;
+ this.value = value;
+ this.outputColumn = outputColumn;
+ }
+
+ public <ClassName>() {
+ }
+
+ @Override
+ public void evaluate(VectorizedRowBatch batch) {
+
+ if (childExpressions != null) {
+ super.evaluateChildren(batch);
+ }
+
+ DecimalColumnVector inputColVector = (DecimalColumnVector) batch.cols[colNum];
+ DecimalColumnVector outputColVector = (DecimalColumnVector) batch.cols[outputColumn];
+ int[] sel = batch.selected;
+ boolean[] inputIsNull = inputColVector.isNull;
+ boolean[] outputIsNull = outputColVector.isNull;
+ outputColVector.noNulls = inputColVector.noNulls;
+ outputColVector.isRepeating = inputColVector.isRepeating;
+ int n = batch.size;
+ Decimal128[] vector = inputColVector.vector;
+ Decimal128[] outputVector = outputColVector.vector;
+
+ // Initialize local variable to use as 0 value on first use.
+ if (zero == null) {
+ this.zero = new Decimal128(0, inputColVector.scale);
+ }
+
+ // return immediately if batch is empty
+ if (n == 0) {
+ return;
+ }
+
+ if (inputColVector.noNulls) {
+
+ /* Initialize output vector NULL values to false. This is necessary
+ * since the decimal operation may produce a NULL result even for
+ * a non-null input vector value, and convert the output vector
+ * to have noNulls = false;
+ */
+ NullUtil.initOutputNullsToFalse(outputColVector, inputColVector.isRepeating,
+ batch.selectedInUse, sel, n);
+ }
+
+
+ if (value.compareTo(zero) == 0) {
+
+ // Denominator is zero, convert the batch to nulls
+ outputColVector.noNulls = false;
+ outputColVector.isRepeating = true;
+ outputIsNull[0] = true;
+ } else if (inputColVector.isRepeating) {
+ DecimalUtil.<Operator>Checked(0, vector[0], value, outputColVector);
+
+ // Even if there are no nulls, we always copy over entry 0. Simplifies code.
+ outputIsNull[0] = inputIsNull[0];
+ } else if (inputColVector.noNulls) {
+ if (batch.selectedInUse) {
+ for(int j = 0; j != n; j++) {
+ int i = sel[j];
+ DecimalUtil.<Operator>Checked(i, vector[i], value, outputColVector);
+ }
+ } else {
+ for(int i = 0; i != n; i++) {
+ DecimalUtil.<Operator>Checked(i, vector[i], value, outputColVector);
+ }
+ }
+ } else /* there are nulls */ {
+ if (batch.selectedInUse) {
+ for(int j = 0; j != n; j++) {
+ int i = sel[j];
+
+ // copy isNull entry first because operation may overwrite it
+ outputIsNull[i] = inputIsNull[i];
+ DecimalUtil.<Operator>Checked(i, vector[i], value, outputColVector);
+ }
+ } else {
+
+ // copy isNull entries first because operation may overwrite them
+ System.arraycopy(inputIsNull, 0, outputIsNull, 0, n);
+ for(int i = 0; i != n; i++) {
+ DecimalUtil.<Operator>Checked(i, vector[i], value, outputColVector);
+ }
+ }
+ }
+
+ /*
+ * Null data entries are not set to a special non-zero value because all null math operations
+ * are checked, meaning that a zero-divide always results in a null result.
+ */
+ }
+
+ @Override
+ public int getOutputColumn() {
+ return outputColumn;
+ }
+
+ @Override
+ public String getOutputType() {
+ return "decimal";
+ }
+
+ public int getColNum() {
+ return colNum;
+ }
+
+ public void setColNum(int colNum) {
+ this.colNum = colNum;
+ }
+
+ public Decimal128 getValue() {
+ return value;
+ }
+
+ public void setValue(Decimal128 value) {
+ this.value = value;
+ }
+
+ public void setOutputColumn(int outputColumn) {
+ this.outputColumn = outputColumn;
+ }
+
+ @Override
+ public VectorExpressionDescriptor.Descriptor getDescriptor() {
+ return (new VectorExpressionDescriptor.Builder())
+ .setMode(
+ VectorExpressionDescriptor.Mode.PROJECTION)
+ .setNumArguments(2)
+ .setArgumentTypes(
+ VectorExpressionDescriptor.ArgumentType.getType("decimal"),
+ VectorExpressionDescriptor.ArgumentType.getType("decimal"))
+ .setInputExpressionTypes(
+ VectorExpressionDescriptor.InputExpressionType.COLUMN,
+ VectorExpressionDescriptor.InputExpressionType.SCALAR).build();
+ }
+}

Modified: hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/FilterDecimalColumnCompareColumn.txt
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/FilterDecimalColumnCompareColumn.txt?rev=1562910&r1=1562909&r2=1562910&view=diff
==============================================================================
--- hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/FilterDecimalColumnCompareColumn.txt (original)
+++ hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/FilterDecimalColumnCompareColumn.txt Thu Jan 30 18:12:44 2014
@@ -15,7 +15,7 @@
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
-
+
  package org.apache.hadoop.hive.ql.exec.vector.expressions.gen;

  import org.apache.hadoop.hive.ql.exec.vector.expressions.VectorExpression;
@@ -64,17 +64,17 @@ public class <ClassName> extends VectorE
      if (n == 0) {
        return;
      }
-
+
      // handle case where neither input has nulls
      if (inputColVector1.noNulls && inputColVector2.noNulls) {
        if (inputColVector1.isRepeating && inputColVector2.isRepeating) {
-
+
          /* Either all must remain selected or all will be eliminated.
           * Repeating property will not change.
           */
          if (!(vector1[0].compareTo(vector2[0]) <OperatorSymbol> 0)) {
            batch.size = 0;
- }
+ }
        } else if (inputColVector1.isRepeating) {
          if (batch.selectedInUse) {
            int newSize = 0;
@@ -140,16 +140,16 @@ public class <ClassName> extends VectorE
            batch.selectedInUse = true;
          }
        }
-
+
      // handle case where only input 2 has nulls
- } else if (inputColVector1.noNulls) {
+ } else if (inputColVector1.noNulls) {
        if (inputColVector1.isRepeating && inputColVector2.isRepeating) {
          if (nullPos2[0] ||
              !(vector1[0].compareTo(vector2[0]) <OperatorSymbol> 0)) {
            batch.size = 0;
          }
        } else if (inputColVector1.isRepeating) {
-
+
           // no need to check for nulls in input 1
           if (batch.selectedInUse) {
            int newSize = 0;
@@ -178,7 +178,7 @@ public class <ClassName> extends VectorE
          }
        } else if (inputColVector2.isRepeating) {
          if (nullPos2[0]) {
-
+
            // no values will qualify because every comparison will be with NULL
            batch.size = 0;
            return;
@@ -229,9 +229,9 @@ public class <ClassName> extends VectorE
              batch.size = newSize;
              batch.selectedInUse = true;
            }
- }
+ }
        }
-
+
      // handle case where only input 1 has nulls
      } else if (inputColVector2.noNulls) {
        if (inputColVector1.isRepeating && inputColVector2.isRepeating) {
@@ -242,7 +242,7 @@ public class <ClassName> extends VectorE
          }
        } else if (inputColVector1.isRepeating) {
          if (nullPos1[0]) {
-
+
            // if repeating value is null then every comparison will fail so nothing qualifies
            batch.size = 0;
            return;
@@ -319,9 +319,9 @@ public class <ClassName> extends VectorE
              batch.size = newSize;
              batch.selectedInUse = true;
            }
- }
+ }
        }
-
+
      // handle case where both inputs have nulls
      } else {
        if (inputColVector1.isRepeating && inputColVector2.isRepeating) {
@@ -414,7 +414,7 @@ public class <ClassName> extends VectorE
              batch.size = newSize;
              batch.selectedInUse = true;
            }
- }
+ }
        }
      }
    }

Added: hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ScalarDivideColumnDecimal.txt
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ScalarDivideColumnDecimal.txt?rev=1562910&view=auto
==============================================================================
--- hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ScalarDivideColumnDecimal.txt (added)
+++ hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ScalarDivideColumnDecimal.txt Thu Jan 30 18:12:44 2014
@@ -0,0 +1,168 @@
+/**
+ * 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.hadoop.hive.ql.exec.vector.expressions.gen;
+
+import org.apache.hadoop.hive.ql.exec.vector.expressions.VectorExpression;
+import org.apache.hadoop.hive.ql.exec.vector.DecimalColumnVector;
+import org.apache.hadoop.hive.ql.exec.vector.VectorizedRowBatch;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.NullUtil;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.DecimalUtil;
+import org.apache.hadoop.hive.ql.exec.vector.VectorExpressionDescriptor;
+import org.apache.hadoop.hive.common.type.Decimal128;
+
+/**
+ * Generated from template ScalarDivideColumnDecimal.txt, which covers binary arithmetic
+ * expressions between a scalar and a column.
+ */
+public class <ClassName> extends VectorExpression {
+
+ private static final long serialVersionUID = 1L;
+
+ private int colNum;
+ private Decimal128 value;
+ private int outputColumn;
+
+ public <ClassName>(Decimal128 value, int colNum, int outputColumn) {
+ this.colNum = colNum;
+ this.value = value;
+ this.outputColumn = outputColumn;
+ }
+
+ public <ClassName>() {
+ }
+
+ @Override
+ public void evaluate(VectorizedRowBatch batch) {
+
+ if (childExpressions != null) {
+ super.evaluateChildren(batch);
+ }
+
+ DecimalColumnVector inputColVector = (DecimalColumnVector) batch.cols[colNum];
+ DecimalColumnVector outputColVector = (DecimalColumnVector) batch.cols[outputColumn];
+ int[] sel = batch.selected;
+ boolean[] inputIsNull = inputColVector.isNull;
+ boolean[] outputIsNull = outputColVector.isNull;
+ outputColVector.noNulls = inputColVector.noNulls;
+ outputColVector.isRepeating = inputColVector.isRepeating;
+ int n = batch.size;
+ Decimal128[] vector = inputColVector.vector;
+ Decimal128[] outputVector = outputColVector.vector;
+
+ // return immediately if batch is empty
+ if (n == 0) {
+ return;
+ }
+
+ if (inputColVector.noNulls) {
+
+ /* Initialize output vector NULL values to false. This is necessary
+ * since the decimal operation may produce a NULL result even for
+ * a non-null input vector value, and convert the output vector
+ * to have noNulls = false;
+ */
+ NullUtil.initOutputNullsToFalse(outputColVector, inputColVector.isRepeating,
+ batch.selectedInUse, sel, n);
+ }
+
+ if (inputColVector.isRepeating) {
+ DecimalUtil.<Operator>Checked(0, value, vector[0], outputColVector);
+
+ // Even if there are no nulls, we always copy over entry 0. Simplifies code.
+ outputIsNull[0] = inputIsNull[0];
+ } else if (inputColVector.noNulls) {
+ if (batch.selectedInUse) {
+ for(int j = 0; j != n; j++) {
+ int i = sel[j];
+ DecimalUtil.<Operator>Checked(i, value, vector[i], outputColVector);
+ }
+ } else {
+ for(int i = 0; i != n; i++) {
+ DecimalUtil.<Operator>Checked(i, value, vector[i], outputColVector);
+ }
+ }
+ } else /* there are nulls */ {
+ if (batch.selectedInUse) {
+ for(int j = 0; j != n; j++) {
+ int i = sel[j];
+
+ // copy isNull entry first because the operation may overwrite it
+ outputIsNull[i] = inputIsNull[i];
+ DecimalUtil.<Operator>Checked(i, value, vector[i], outputColVector);
+ }
+ } else {
+
+ // copy isNull entries first because the operation may overwrite them
+ System.arraycopy(inputIsNull, 0, outputIsNull, 0, n);
+ for(int i = 0; i != n; i++) {
+ DecimalUtil.<Operator>Checked(i, value, vector[i], outputColVector);
+ }
+ }
+ }
+
+ /*
+ * Null data entries are not set to a special non-zero value because all null math operations
+ * are checked, meaning that a zero-divide always results in a null result anyway.
+ */
+ }
+
+ @Override
+ public int getOutputColumn() {
+ return outputColumn;
+ }
+
+ @Override
+ public String getOutputType() {
+ return "decimal";
+ }
+
+ public int getColNum() {
+ return colNum;
+ }
+
+ public void setColNum(int colNum) {
+ this.colNum = colNum;
+ }
+
+ public Decimal128 getValue() {
+ return value;
+ }
+
+ public void setValue(Decimal128 value) {
+ this.value = value;
+ }
+
+ public void setOutputColumn(int outputColumn) {
+ this.outputColumn = outputColumn;
+ }
+
+ @Override
+ public VectorExpressionDescriptor.Descriptor getDescriptor() {
+ return (new VectorExpressionDescriptor.Builder())
+ .setMode(
+ VectorExpressionDescriptor.Mode.PROJECTION)
+ .setNumArguments(2)
+ .setArgumentTypes(
+ VectorExpressionDescriptor.ArgumentType.getType("decimal"),
+ VectorExpressionDescriptor.ArgumentType.getType("decimal"))
+ .setInputExpressionTypes(
+ VectorExpressionDescriptor.InputExpressionType.SCALAR,
+ VectorExpressionDescriptor.InputExpressionType.COLUMN).build();
+ }
+}

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/DecimalUtil.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/DecimalUtil.java?rev=1562910&r1=1562909&r2=1562910&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/DecimalUtil.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/DecimalUtil.java Thu Jan 30 18:12:44 2014
@@ -19,6 +19,8 @@
  package org.apache.hadoop.hive.ql.exec.vector.expressions;

  import org.apache.hadoop.hive.common.type.Decimal128;
+import org.apache.hadoop.hive.common.type.SqlMathUtil;
+import org.apache.hadoop.hive.common.type.UnsignedInt128;
  import org.apache.hadoop.hive.ql.exec.vector.DecimalColumnVector;

  /**
@@ -73,4 +75,16 @@ public class DecimalUtil {
        outputColVector.isNull[i] = true;
      }
    }
+
+ // Modulo operator with overflow/zero-divide check.
+ public static void moduloChecked(int i, Decimal128 left, Decimal128 right,
+ DecimalColumnVector outputColVector) {
+ try {
+ Decimal128.modulo(left, right, outputColVector.vector[i], outputColVector.scale);
+ outputColVector.vector[i].checkPrecisionOverflow(outputColVector.precision);
+ } catch (ArithmeticException e) { // catch on error
+ outputColVector.noNulls = false;
+ outputColVector.isNull[i] = true;
+ }
+ }
  }

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/NullUtil.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/NullUtil.java?rev=1562910&r1=1562909&r2=1562910&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/NullUtil.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/NullUtil.java Thu Jan 30 18:12:44 2014
@@ -19,8 +19,6 @@
  package org.apache.hadoop.hive.ql.exec.vector.expressions;

  import java.util.Arrays;
-
-import org.apache.hadoop.hive.common.type.Decimal128;
  import org.apache.hadoop.hive.ql.exec.vector.DecimalColumnVector;
  import org.apache.hadoop.hive.ql.exec.vector.LongColumnVector;
  import org.apache.hadoop.hive.ql.exec.vector.DoubleColumnVector;

Modified: hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/exec/vector/expressions/TestVectorArithmeticExpressions.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/exec/vector/expressions/TestVectorArithmeticExpressions.java?rev=1562910&r1=1562909&r2=1562910&view=diff
==============================================================================
--- hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/exec/vector/expressions/TestVectorArithmeticExpressions.java (original)
+++ hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/exec/vector/expressions/TestVectorArithmeticExpressions.java Thu Jan 30 18:12:44 2014
@@ -29,6 +29,17 @@ import org.apache.hadoop.hive.ql.exec.ve
  import org.apache.hadoop.hive.ql.exec.vector.LongColumnVector;
  import org.apache.hadoop.hive.ql.exec.vector.TestVectorizedRowBatch;
  import org.apache.hadoop.hive.ql.exec.vector.VectorizedRowBatch;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.DecimalColDivideDecimalScalar;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.DecimalScalarDivideDecimalColumn;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.DecimalScalarModuloDecimalColumn;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.DecimalColAddDecimalColumn;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.DecimalColDivideDecimalColumn;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.DecimalColModuloDecimalColumn;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.DecimalColModuloDecimalScalar;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.DecimalColMultiplyDecimalScalar;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.DecimalColSubtractDecimalScalar;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.DecimalColMultiplyDecimalColumn;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.DecimalColSubtractDecimalColumn;
  import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.LongColAddLongColumn;
  import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.LongColAddLongScalar;
  import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.DecimalColSubtractDecimalColumn;
@@ -331,44 +342,6 @@ public class TestVectorArithmeticExpress

      // verify proper null output data value
      assertTrue(r.vector[0].equals(new Decimal128("0.01", (short) 2)));
- }
-
- // Test decimal column-column addition
- @Test
- public void testDecimalColumnAddDecimalColumn() {
- VectorizedRowBatch b = getVectorizedRowBatch3DecimalCols();
- VectorExpression expr = new DecimalColAddDecimalColumn(0, 1, 2);
- DecimalColumnVector r = (DecimalColumnVector) b.cols[2];
-
- // test without nulls
- expr.evaluate(b);
- assertTrue(r.vector[0].equals(new Decimal128("2.20", (short) 2)));
- assertTrue(r.vector[1].equals(new Decimal128("-2.30", (short) 2)));
- assertTrue(r.vector[2].equals(new Decimal128("1.00", (short) 2)));
-
- // test nulls propagation
- b = getVectorizedRowBatch3DecimalCols();
- DecimalColumnVector c0 = (DecimalColumnVector) b.cols[0];
- c0.noNulls = false;
- c0.isNull[0] = true;
- r = (DecimalColumnVector) b.cols[2];
- expr.evaluate(b);
- assertTrue(!r.noNulls && r.isNull[0]);
-
- // Verify null output data entry is not 0, but rather the value specified by design,
- // which is the minimum non-0 value, 0.01 in this case.
- assertTrue(r.vector[0].equals(new Decimal128("0.01", (short) 2)));
-
- // test that overflow produces NULL
- b = getVectorizedRowBatch3DecimalCols();
- c0 = (DecimalColumnVector) b.cols[0];
- c0.vector[0].update("9999999999999999.99", (short) 2); // set to max possible value
- r = (DecimalColumnVector) b.cols[2];
- expr.evaluate(b); // will cause overflow for result at position 0, must yield NULL
- assertTrue(!r.noNulls && r.isNull[0]);
-
- // verify proper null output data value
- assertTrue(r.vector[0].equals(new Decimal128("0.01", (short) 2)));

      // test left input repeating
      b = getVectorizedRowBatch3DecimalCols();
@@ -399,7 +372,7 @@ public class TestVectorArithmeticExpress

    // Spot check decimal column-column subtract
    @Test
- public void testDecimalColumnSubtractDecimalColumn() {
+ public void testDecimalColSubtractDecimalColumn() {
      VectorizedRowBatch b = getVectorizedRowBatch3DecimalCols();
      VectorExpression expr = new DecimalColSubtractDecimalColumn(0, 1, 2);
      DecimalColumnVector r = (DecimalColumnVector) b.cols[2];
@@ -421,7 +394,7 @@ public class TestVectorArithmeticExpress

    // Spot check decimal column-column multiply
    @Test
- public void testDecimalColumnMultiplyDecimalColumn() {
+ public void testDecimalColMultiplyDecimalColumn() {
      VectorizedRowBatch b = getVectorizedRowBatch3DecimalCols();
      VectorExpression expr = new DecimalColMultiplyDecimalColumn(0, 1, 2);
      DecimalColumnVector r = (DecimalColumnVector) b.cols[2];
@@ -500,6 +473,269 @@ public class TestVectorArithmeticExpress
      assertTrue(r.isNull[0]);
    }

+ /* Test decimal column to decimal scalar division. This is used to cover all the
+ * cases used in the source code template ColumnDivideScalarDecimal.txt.
+ * The template is used for division and modulo.
+ */
+ @Test
+ public void testDecimalColDivideDecimalScalar() {
+ VectorizedRowBatch b = getVectorizedRowBatch3DecimalCols();
+ Decimal128 d = new Decimal128("2.00", (short) 2);
+ VectorExpression expr = new DecimalColDivideDecimalScalar(0, d, 2);
+
+
+ // test without nulls
+ expr.evaluate(b);
+ DecimalColumnVector r = (DecimalColumnVector) b.cols[2];
+ assertTrue(r.vector[0].equals(new Decimal128("0.60", (short) 2)));
+ assertTrue(r.vector[1].equals(new Decimal128("-1.65", (short) 2)));
+ assertTrue(r.vector[2].equals(new Decimal128("0", (short) 2)));
+
+ // test null propagation
+ b = getVectorizedRowBatch3DecimalCols();
+ DecimalColumnVector in = (DecimalColumnVector) b.cols[0];
+ r = (DecimalColumnVector) b.cols[2];
+ in.noNulls = false;
+ in.isNull[0] = true;
+ expr.evaluate(b);
+ assertTrue(!r.noNulls);
+ assertTrue(r.isNull[0]);
+
+ // test repeating case, no nulls
+ b = getVectorizedRowBatch3DecimalCols();
+ in = (DecimalColumnVector) b.cols[0];
+ in.isRepeating = true;
+ expr.evaluate(b);
+ r = (DecimalColumnVector) b.cols[2];
+ assertTrue(r.isRepeating);
+ assertTrue(r.vector[0].equals(new Decimal128("0.60", (short) 2)));
+
+ // test repeating case for null value
+ b = getVectorizedRowBatch3DecimalCols();
+ in = (DecimalColumnVector) b.cols[0];
+ in.isRepeating = true;
+ in.isNull[0] = true;
+ in.noNulls = false;
+ expr.evaluate(b);
+ r = (DecimalColumnVector) b.cols[2];
+ assertTrue(r.isRepeating);
+ assertTrue(!r.noNulls);
+ assertTrue(r.isNull[0]);
+
+ // test that zero-divide produces null for all output values
+ b = getVectorizedRowBatch3DecimalCols();
+ in = (DecimalColumnVector) b.cols[0];
+ expr = new DecimalColDivideDecimalScalar(0, new Decimal128("0", (short) 2), 2);
+ expr.evaluate(b);
+ r = (DecimalColumnVector) b.cols[2];
+ assertFalse(r.noNulls);
+ assertTrue(r.isNull[0]);
+ assertTrue(r.isRepeating);
+ }
+
+ /* Test decimal scalar divided column. This tests the primary logic
+ * for template ScalarDivideColumnDecimal.txt.
+ */
+ @Test
+ public void testDecimalScalarDivideDecimalColumn() {
+ VectorizedRowBatch b = getVectorizedRowBatch3DecimalCols();
+ Decimal128 d = new Decimal128("3.96", (short) 2); // 1.20 * 3.30
+ VectorExpression expr = new DecimalScalarDivideDecimalColumn(d, 0, 2);
+
+ // test without nulls
+ expr.evaluate(b);
+ DecimalColumnVector r = (DecimalColumnVector) b.cols[2];
+ assertTrue(r.vector[0].equals(new Decimal128("3.30", (short) 2)));
+ assertTrue(r.vector[1].equals(new Decimal128("-1.20", (short) 2)));
+ assertFalse(r.noNulls); // entry 2 is null due to zero-divide
+ assertTrue(r.isNull[2]);
+
+ // test null propagation
+ b = getVectorizedRowBatch3DecimalCols();
+ DecimalColumnVector in = (DecimalColumnVector) b.cols[0];
+ r = (DecimalColumnVector) b.cols[2];
+ in.noNulls = false;
+ in.isNull[0] = true;
+ expr.evaluate(b);
+ assertTrue(!r.noNulls);
+ assertTrue(r.isNull[0]);
+
+ // test repeating case, no nulls
+ b = getVectorizedRowBatch3DecimalCols();
+ in = (DecimalColumnVector) b.cols[0];
+ in.isRepeating = true;
+ expr.evaluate(b);
+ r = (DecimalColumnVector) b.cols[2];
+ assertTrue(r.isRepeating);
+ assertTrue(r.vector[0].equals(new Decimal128("3.30", (short) 2)));
+
+ // test repeating case for null value
+ b = getVectorizedRowBatch3DecimalCols();
+ in = (DecimalColumnVector) b.cols[0];
+ in.isRepeating = true;
+ in.isNull[0] = true;
+ in.noNulls = false;
+ expr.evaluate(b);
+ r = (DecimalColumnVector) b.cols[2];
+ assertTrue(r.isRepeating);
+ assertTrue(!r.noNulls);
+ assertTrue(r.isNull[0]);
+ }
+
+ // Spot check Decimal Col-Scalar Modulo
+ @Test
+ public void testDecimalColModuloDecimalScalar() {
+ VectorizedRowBatch b = getVectorizedRowBatch3DecimalCols();
+ Decimal128 d = new Decimal128("2.00", (short) 2);
+ VectorExpression expr = new DecimalColModuloDecimalScalar(0, d, 2);
+
+ // test without nulls
+ expr.evaluate(b);
+ DecimalColumnVector r = (DecimalColumnVector) b.cols[2];
+ assertTrue(r.vector[0].equals(new Decimal128("1.20", (short) 2)));
+ assertTrue(r.vector[1].equals(new Decimal128("-1.30", (short) 2)));
+ assertTrue(r.vector[2].equals(new Decimal128("0", (short) 2)));
+
+ // try again with some different data values and divisor
+ DecimalColumnVector in = (DecimalColumnVector) b.cols[0];
+ in.vector[0].update("15.40", (short) 2);
+ in.vector[1].update("-17.20", (short) 2);
+ in.vector[2].update("70.00", (short) 2);
+ d.update("4.75", (short) 2);
+
+ expr.evaluate(b);
+ assertTrue(r.vector[0].equals(new Decimal128("1.15", (short) 2)));
+ assertTrue(r.vector[1].equals(new Decimal128("-2.95", (short) 2)));
+ assertTrue(r.vector[2].equals(new Decimal128("3.50", (short) 2)));
+
+ // try a zero-divide to show a repeating NULL is produced
+ d.update("0", (short) 2);
+ expr.evaluate(b);
+ assertFalse(r.noNulls);
+ assertTrue(r.isNull[0]);
+ assertTrue(r.isRepeating);
+ }
+
+ // Spot check decimal scalar-column modulo
+ @Test
+ public void testDecimalScalarModuloDecimalColumn() {
+ VectorizedRowBatch b = getVectorizedRowBatch3DecimalCols();
+ Decimal128 d = new Decimal128("2.00", (short) 2);
+ VectorExpression expr = new DecimalScalarModuloDecimalColumn(d, 0, 2);
+
+ // test without nulls
+ expr.evaluate(b);
+ DecimalColumnVector r = (DecimalColumnVector) b.cols[2];
+ assertTrue(r.vector[0].equals(new Decimal128("0.80", (short) 2)));
+ assertTrue(r.vector[1].equals(new Decimal128("2.00", (short) 2)));
+ assertFalse(r.noNulls); // entry 2 will be null due to zero-divide
+ assertTrue(r.isNull[2]);
+
+ // try again with some different data values
+ DecimalColumnVector in = (DecimalColumnVector) b.cols[0];
+ in.vector[0].update("0.50", (short) 2);
+ in.vector[1].update("0.80", (short) 2);
+ in.vector[2].update("0.70", (short) 2);
+
+ expr.evaluate(b);
+ assertTrue(r.vector[0].equals(new Decimal128("0.00", (short) 2)));
+ assertTrue(r.vector[1].equals(new Decimal128("0.40", (short) 2)));
+ assertTrue(r.vector[2].equals(new Decimal128("0.60", (short) 2)));
+ }
+
+ @Test
+ public void testDecimalColDivideDecimalColumn() {
+ VectorizedRowBatch b = getVectorizedRowBatch3DecimalCols();
+ DecimalColumnVector in1 = (DecimalColumnVector) b.cols[1];
+ for (int i = 0; i < 3; i++) {
+ in1.vector[i] = new Decimal128("0.50", (short) 2);
+ }
+ VectorExpression expr = new DecimalColDivideDecimalColumn(0, 1, 2);
+ expr.evaluate(b);
+ DecimalColumnVector r = (DecimalColumnVector) b.cols[2];
+
+ // all divides are by 0.50 so the result column is 2 times col 0.
+ assertTrue(r.vector[0].equals(new Decimal128("2.40", (short) 2)));
+ assertTrue(r.vector[1].equals(new Decimal128("-6.60", (short) 2)));
+ assertTrue(r.vector[2].equals(new Decimal128("0", (short) 2)));
+
+ // test null on left
+ b.cols[0].noNulls = false;
+ b.cols[0].isNull[0] = true;
+ expr.evaluate(b);
+ assertFalse(r.noNulls);
+ assertTrue(r.isNull[0]);
+
+ // test null on right
+ b = getVectorizedRowBatch3DecimalCols();
+ b.cols[1].noNulls = false;
+ b.cols[1].isNull[0] = true;
+ r = (DecimalColumnVector) b.cols[2];
+ expr.evaluate(b);
+ assertFalse(r.noNulls);
+ assertTrue(r.isNull[0]);
+
+ // test null on both sides
+ b = getVectorizedRowBatch3DecimalCols();
+ b.cols[0].noNulls = false;
+ b.cols[0].isNull[0] = true;
+ b.cols[1].noNulls = false;
+ b.cols[1].isNull[0] = true;
+ expr.evaluate(b);
+ assertFalse(r.noNulls);
+ assertTrue(r.isNull[0]);
+ assertFalse(r.isNull[1]);
+ assertFalse(r.isNull[2]);
+
+ // test repeating on left
+ b = getVectorizedRowBatch3DecimalCols();
+ b.cols[0].isRepeating = true;
+ expr.evaluate(b);
+ r = (DecimalColumnVector) b.cols[2];
+ assertTrue(r.vector[2].equals(new Decimal128("1.20", (short) 2)));
+
+ // test repeating on right
+ b = getVectorizedRowBatch3DecimalCols();
+ b.cols[1].isRepeating = true;
+ expr.evaluate(b);
+ r = (DecimalColumnVector) b.cols[2];
+ assertTrue(r.vector[2].equals(new Decimal128("0", (short) 2)));
+
+ // test both repeating
+ b = getVectorizedRowBatch3DecimalCols();
+ b.cols[0].isRepeating = true;
+ b.cols[1].isRepeating = true;
+ expr.evaluate(b);
+ r = (DecimalColumnVector) b.cols[2];
+ assertTrue(r.isRepeating);
+ assertTrue(r.vector[0].equals(new Decimal128("1.20", (short) 2)));
+
+ // test zero-divide to show it results in NULL
+ b = getVectorizedRowBatch3DecimalCols();
+ ((DecimalColumnVector) b.cols[1]).vector[0].update(0);
+ expr.evaluate(b);
+ r = (DecimalColumnVector) b.cols[2];
+ assertFalse(r.noNulls);
+ assertTrue(r.isNull[0]);
+ }
+
+ // Spot check decimal column modulo decimal column
+ @Test
+ public void testDecimalColModuloDecimalColumn() {
+ VectorizedRowBatch b = getVectorizedRowBatch3DecimalCols();
+ DecimalColumnVector in1 = (DecimalColumnVector) b.cols[1];
+ for (int i = 0; i < 3; i++) {
+ in1.vector[i] = new Decimal128("0.50", (short) 2);
+ }
+ VectorExpression expr = new DecimalColModuloDecimalColumn(0, 1, 2);
+ expr.evaluate(b);
+ DecimalColumnVector r = (DecimalColumnVector) b.cols[2];
+
+ assertTrue(r.vector[0].equals(new Decimal128("0.20", (short) 2)));
+ assertTrue(r.vector[1].equals(new Decimal128("-0.30", (short) 2)));
+ assertTrue(r.vector[2].equals(new Decimal128("0", (short) 2)));
+ }
+
    /* Spot check correctness of decimal column subtract decimal scalar. The case for
     * addition checks all the cases for the template, so don't do that redundantly here.
     */

Search Discussions

Related Discussions

Discussion Navigation
viewthread | post
posts ‹ prev | 1 of 1 | next ›
Discussion Overview
groupcommits @
categorieshive, hadoop
postedJan 30, '14 at 6:13p
activeJan 30, '14 at 6:13p
posts1
users1
websitehive.apache.org

1 user in discussion

Ehans: 1 post

People

Translate

site design / logo © 2021 Grokbase