hive-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From eh...@apache.org
Subject svn commit: r1562910 - in /hive/trunk: ant/src/org/apache/hadoop/hive/ant/ common/src/java/org/apache/hadoop/hive/common/type/ ql/src/gen/vectorization/ExpressionTemplates/ ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/ ql/src/test/org/...
Date Thu, 30 Jan 2014 18:12:44 GMT
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.
    */



Mime
View raw message