hive-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From eh...@apache.org
Subject svn commit: r1558956 - in /hive/trunk: ant/src/org/apache/hadoop/hive/ant/ ql/src/gen/vectorization/ExpressionTemplates/ ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/ ql/src/test/org/apache/hadoop/hive/ql/exec/vector/expressions/
Date Thu, 16 Jan 2014 23:09:57 GMT
Author: ehans
Date: Thu Jan 16 23:09:57 2014
New Revision: 1558956

URL: http://svn.apache.org/r1558956
Log:
HIVE-6124: Support basic Decimal arithmetic in vector mode (+, -, *) (Eric Hanson)

Added:
    hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnArithmeticColumnDecimal.txt
    hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnArithmeticScalarDecimal.txt
    hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ScalarArithmeticColumnDecimal.txt
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/DecimalUtil.java
Modified:
    hive/trunk/ant/src/org/apache/hadoop/hive/ant/GenVectorCode.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=1558956&r1=1558955&r2=1558956&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 16 23:09:57 2014
@@ -107,6 +107,18 @@ public class GenVectorCode extends Task 
       {"ColumnDivideColumn", "Modulo", "double", "long", "%"},
       {"ColumnDivideColumn", "Modulo", "double", "double", "%"},
 
+      {"ColumnArithmeticScalarDecimal", "Add"},
+      {"ColumnArithmeticScalarDecimal", "Subtract"},
+      {"ColumnArithmeticScalarDecimal", "Multiply"},
+
+      {"ScalarArithmeticColumnDecimal", "Add"},
+      {"ScalarArithmeticColumnDecimal", "Subtract"},
+      {"ScalarArithmeticColumnDecimal", "Multiply"},
+
+      {"ColumnArithmeticColumnDecimal", "Add"},
+      {"ColumnArithmeticColumnDecimal", "Subtract"},
+      {"ColumnArithmeticColumnDecimal", "Multiply"},
+
       {"ColumnCompareScalar", "Equal", "long", "double", "=="},
       {"ColumnCompareScalar", "Equal", "double", "double", "=="},
       {"ColumnCompareScalar", "NotEqual", "long", "double", "!="},
@@ -560,6 +572,12 @@ public class GenVectorCode extends Task 
     for (String [] tdesc : templateExpansions) {
       if (tdesc[0].equals("ColumnArithmeticScalar") || tdesc[0].equals("ColumnDivideScalar"))
{
         generateColumnArithmeticScalar(tdesc);
+      } else if (tdesc[0].equals("ColumnArithmeticScalarDecimal")) {
+        generateColumnArithmeticScalarDecimal(tdesc);
+      } else if (tdesc[0].equals("ScalarArithmeticColumnDecimal")) {
+        generateScalarArithmeticColumnDecimal(tdesc);
+      } else if (tdesc[0].equals("ColumnArithmeticColumnDecimal")) {
+        generateColumnArithmeticColumnDecimal(tdesc);
       } else if (tdesc[0].equals("ColumnCompareScalar")) {
         generateColumnCompareScalar(tdesc);
       } else if (tdesc[0].equals("ScalarCompareColumn")) {
@@ -1143,6 +1161,48 @@ public class GenVectorCode extends Task 
     generateColumnBinaryOperatorScalar(tdesc, returnType, className);
   }
 
+  private void generateColumnArithmeticScalarDecimal(String[] tdesc) throws IOException {
+    String operatorName = tdesc[1];
+    String className = "DecimalCol" + 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 generateScalarArithmeticColumnDecimal(String[] tdesc) throws IOException {
+    String operatorName = tdesc[1];
+    String className = "DecimalScalar" + 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 generateColumnArithmeticColumnDecimal(String[] tdesc) throws IOException {
+    String operatorName = tdesc[1];
+    String className = "DecimalCol" + 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];

Added: hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnArithmeticColumnDecimal.txt
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnArithmeticColumnDecimal.txt?rev=1558956&view=auto
==============================================================================
--- hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnArithmeticColumnDecimal.txt
(added)
+++ hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnArithmeticColumnDecimal.txt
Thu Jan 16 23:09:57 2014
@@ -0,0 +1,185 @@
+/**
+ * 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);
+        }
+      }
+    }
+
+    /* For the case when the output can have null values, follow
+     * the convention that the data values must be set to a specific non-zero
+     * value. This is to prevent possible later zero-divide errors
+     * in complex arithmetic expressions like col2 / (col1 - 1)
+     * in the case when some col1 entries are null.
+     */
+    NullUtil.setNullDataEntriesDecimal(outputColVector, batch.selectedInUse, sel, n);
+  }
+
+  @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/ColumnArithmeticScalarDecimal.txt
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnArithmeticScalarDecimal.txt?rev=1558956&view=auto
==============================================================================
--- hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnArithmeticScalarDecimal.txt
(added)
+++ hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ColumnArithmeticScalarDecimal.txt
Thu Jan 16 23:09:57 2014
@@ -0,0 +1,166 @@
+/**
+ * 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 ColumnArithmeticScalarDecimal.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;
+
+  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;
+    
+    // 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) {
+      if (!inputColVector.noNulls) {
+        outputIsNull[0] = inputIsNull[0];
+      } 
+      
+      // The following may override a "false" null setting if an error or overflow occurs.
+      DecimalUtil.<Operator>Checked(0, vector[0], value, outputColVector);
+    } 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];
+          outputIsNull[i] = inputIsNull[i];
+
+          // The following may override a "false" null setting if an error or overflow occurs.
+          DecimalUtil.<Operator>Checked(i, vector[i], value, outputColVector);
+        }
+      } else {
+        System.arraycopy(inputIsNull, 0, outputIsNull, 0, n);
+        for(int i = 0; i != n; i++) {
+
+          // The following may override a "false" null setting if an error or overflow occurs.
+          DecimalUtil.<Operator>Checked(i, vector[i], value, outputColVector);
+        }
+      }
+    }
+    
+    NullUtil.setNullDataEntriesDecimal(outputColVector, batch.selectedInUse, sel, n);
+  }
+
+  @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();
+  }
+}

Added: hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ScalarArithmeticColumnDecimal.txt
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ScalarArithmeticColumnDecimal.txt?rev=1558956&view=auto
==============================================================================
--- hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ScalarArithmeticColumnDecimal.txt
(added)
+++ hive/trunk/ql/src/gen/vectorization/ExpressionTemplates/ScalarArithmeticColumnDecimal.txt
Thu Jan 16 23:09:57 2014
@@ -0,0 +1,166 @@
+/**
+ * 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 ScalarArithmeticColumnDecimal.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;
+    
+    // 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) {
+      if (!inputColVector.noNulls) {
+        outputIsNull[0] = inputIsNull[0];
+      } 
+      
+      // The following may override a "false" null setting if an error or overflow occurs.
+      DecimalUtil.<Operator>Checked(0, value, vector[0], outputColVector);
+    } 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];
+          outputIsNull[i] = inputIsNull[i];
+
+          // The following may override a "false" null setting if an error or overflow occurs.
+          DecimalUtil.<Operator>Checked(i, value, vector[i], outputColVector);
+        }
+      } else {
+        System.arraycopy(inputIsNull, 0, outputIsNull, 0, n);
+        for(int i = 0; i != n; i++) {
+
+          // The following may override a "false" null setting if an error or overflow occurs.
+          DecimalUtil.<Operator>Checked(i, value, vector[i], outputColVector);
+        }
+      }
+    }
+    
+    NullUtil.setNullDataEntriesDecimal(outputColVector, batch.selectedInUse, sel, n);
+  }
+
+  @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();
+  }
+}

Added: 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=1558956&view=auto
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/DecimalUtil.java
(added)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/DecimalUtil.java
Thu Jan 16 23:09:57 2014
@@ -0,0 +1,92 @@
+/**
+ * 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;
+
+import org.apache.hadoop.hive.common.type.Decimal128;
+import org.apache.hadoop.hive.ql.exec.vector.DecimalColumnVector;
+
+/**
+ * Utility functions for vector operations on decimal values.
+ */
+public class DecimalUtil {
+
+  // Addition with overflow check. Overflow produces NULL output.
+  public static void addChecked(int i, Decimal128 left, Decimal128 right,
+      DecimalColumnVector outputColVector) {
+    try {
+      Decimal128.add(left, right, outputColVector.vector[i], outputColVector.scale);
+      outputColVector.vector[i].checkPrecisionOverflow(outputColVector.precision);
+    } catch (ArithmeticException e) {  // catch on overflow
+      outputColVector.noNulls = false;
+      outputColVector.isNull[i] = true;
+    }
+  }
+
+  // Subtraction with overflow check. Overflow produces NULL output.
+  public static void subtractChecked(int i, Decimal128 left, Decimal128 right,
+      DecimalColumnVector outputColVector) {
+    try {
+      Decimal128.subtract(left, right, outputColVector.vector[i], outputColVector.scale);
+      outputColVector.vector[i].checkPrecisionOverflow(outputColVector.precision);
+    } catch (ArithmeticException e) {  // catch on overflow
+      outputColVector.noNulls = false;
+      outputColVector.isNull[i] = true;
+    }
+  }
+
+  // Multiplication with overflow check. Overflow produces NULL output.
+  public static void multiplyChecked(int i, Decimal128 left, Decimal128 right,
+      DecimalColumnVector outputColVector) {
+    try {
+      Decimal128.multiply(left, right, outputColVector.vector[i], outputColVector.scale);
+      outputColVector.vector[i].checkPrecisionOverflow(outputColVector.precision);
+    } catch (ArithmeticException e) {  // catch on overflow
+      outputColVector.noNulls = false;
+      outputColVector.isNull[i] = true;
+    }
+  }
+
+  // Division with overflow/zero-divide check. Error produces NULL output.
+  // Remainder argument is necessary to match up with the Decimal128.divide() interface.
+  // It will be discarded so just pass in a dummy argument.
+  public static void divideChecked(int i, Decimal128 left, Decimal128 right,
+      DecimalColumnVector outputColVector, Decimal128 remainder) {
+    try {
+      Decimal128.divide(left, right, outputColVector.vector[i], remainder, outputColVector.scale);
+      outputColVector.vector[i].checkPrecisionOverflow(outputColVector.precision);
+    } catch (ArithmeticException e) {  // catch on error
+      outputColVector.noNulls = false;
+      outputColVector.isNull[i] = true;
+    }
+  }
+
+  // Modulo operator with overflow/zero-divide check.
+  // Quotient argument is necessary to match up with Decimal128.divide() interface.
+  // It will be discarded so just pass in a dummy argument.
+  public static void moduloChecked(int i, Decimal128 left, Decimal128 right,
+      DecimalColumnVector outputColVector, Decimal128 quotient) {
+    try {
+      Decimal128.divide(left, right, quotient, 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=1558956&r1=1558955&r2=1558956&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 16 23:09:57 2014
@@ -18,13 +18,14 @@
 
 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;
 import org.apache.hadoop.hive.ql.exec.vector.ColumnVector;
 
-
 /**
  * Utility functions to handle null propagation.
  */
@@ -317,4 +318,22 @@ public class NullUtil {
       }
     }
   }
+
+  // Initialize any entries that could be used in an output vector to have false for null
value.
+  public static void initOutputNullsToFalse(ColumnVector v, boolean isRepeating, boolean
selectedInUse,
+      int[] sel, int n) {
+    if (v.isRepeating) {
+      v.isNull[0] = false;
+      return;
+    }
+
+    if (selectedInUse) {
+      for (int j = 0; j != n; j++) {
+        int i = sel[j];
+        v.isNull[i] = false;
+      }
+    } else {
+      Arrays.fill(v.isNull, 0, n, false);
+    }
+  }
 }

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=1558956&r1=1558955&r2=1558956&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 16 23:09:57 2014
@@ -31,6 +31,15 @@ import org.apache.hadoop.hive.ql.exec.ve
 import org.apache.hadoop.hive.ql.exec.vector.VectorizedRowBatch;
 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;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.DecimalColAddDecimalColumn;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.DecimalColMultiplyDecimalColumn;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.DecimalColAddDecimalScalar;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.DecimalColSubtractDecimalScalar;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.DecimalColMultiplyDecimalScalar;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.DecimalScalarAddDecimalColumn;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.DecimalScalarSubtractDecimalColumn;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.DecimalScalarMultiplyDecimalColumn;
 import org.apache.hadoop.hive.ql.exec.vector.util.VectorizedRowGroupGenUtil;
 import org.junit.Test;
 
@@ -324,6 +333,336 @@ public class TestVectorArithmeticExpress
     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();
+    c0 = (DecimalColumnVector) b.cols[0];
+    c0.isRepeating = true;
+    r = (DecimalColumnVector) b.cols[2];
+    expr.evaluate(b);
+    assertTrue(r.vector[0].equals(new Decimal128("2.20", (short) 2)));
+    assertTrue(r.vector[1].equals(new Decimal128("2.20", (short) 2)));
+    assertTrue(r.vector[2].equals(new Decimal128("2.20", (short) 2)));
+
+    // test both inputs repeating
+    DecimalColumnVector c1 = (DecimalColumnVector) b.cols[1];
+    c1.isRepeating = true;
+    expr.evaluate(b);
+    assertTrue(r.isRepeating);
+    assertTrue(r.vector[0].equals(new Decimal128("2.20", (short) 2)));
+
+    // test right input repeating
+    b = getVectorizedRowBatch3DecimalCols();
+    c1 = (DecimalColumnVector) b.cols[1];
+    c1.isRepeating = true;
+    c1.vector[0].update("2", (short) 2);
+    r = (DecimalColumnVector) b.cols[2];
+    expr.evaluate(b);
+    assertTrue(r.vector[2].equals(new Decimal128("2", (short) 2)));
+  }
+
+  // Spot check decimal column-column subtract
+  @Test
+  public void testDecimalColumnSubtractDecimalColumn() {
+    VectorizedRowBatch b = getVectorizedRowBatch3DecimalCols();
+    VectorExpression expr = new DecimalColSubtractDecimalColumn(0, 1, 2);
+    DecimalColumnVector r = (DecimalColumnVector) b.cols[2];
+
+    // test without nulls
+    expr.evaluate(b);
+    assertTrue(r.vector[0].equals(new Decimal128("0.20", (short) 2)));
+    assertTrue(r.vector[1].equals(new Decimal128("-4.30", (short) 2)));
+    assertTrue(r.vector[2].equals(new Decimal128("-1.00", (short) 2)));
+
+    // test that underflow produces NULL
+    b = getVectorizedRowBatch3DecimalCols();
+    DecimalColumnVector c0 = (DecimalColumnVector) b.cols[0];
+    c0.vector[0].update("-9999999999999999.99", (short) 2); // set to min possible value
+    r = (DecimalColumnVector) b.cols[2];
+    expr.evaluate(b); // will cause underflow for result at position 0, must yield NULL
+    assertTrue(!r.noNulls && r.isNull[0]);
+  }
+
+  // Spot check decimal column-column multiply
+  @Test
+  public void testDecimalColumnMultiplyDecimalColumn() {
+    VectorizedRowBatch b = getVectorizedRowBatch3DecimalCols();
+    VectorExpression expr = new DecimalColMultiplyDecimalColumn(0, 1, 2);
+    DecimalColumnVector r = (DecimalColumnVector) b.cols[2];
+
+    // test without nulls
+    expr.evaluate(b);
+    assertTrue(r.vector[0].equals(new Decimal128("1.20", (short) 2)));
+    assertTrue(r.vector[1].equals(new Decimal128("-3.30", (short) 2)));
+    assertTrue(r.vector[2].equals(new Decimal128("0.00", (short) 2)));
+
+    // test that underflow produces NULL
+    b = getVectorizedRowBatch3DecimalCols();
+    DecimalColumnVector c0 = (DecimalColumnVector) b.cols[0];
+    c0.vector[0].update("9999999999999999.99", (short) 2); // set to max possible value
+    DecimalColumnVector c1 = (DecimalColumnVector) b.cols[1];
+    c1.vector[0].update("2", (short) 2);
+    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]);
+  }
+
+  /* Test decimal column to decimal scalar addition. This is used to cover all the
+   * cases used in the source code template ColumnArithmeticScalarDecimal.txt.
+   */
+  @Test
+  public void testDecimalColAddDecimalScalar() {
+    VectorizedRowBatch b = getVectorizedRowBatch3DecimalCols();
+    Decimal128 d = new Decimal128(1);
+    VectorExpression expr = new DecimalColAddDecimalScalar(0, d, 2);
+
+    // test without nulls
+    expr.evaluate(b);
+    DecimalColumnVector r = (DecimalColumnVector) b.cols[2];
+    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 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("2.20", (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 overflow produces null
+    b = getVectorizedRowBatch3DecimalCols();
+    in = (DecimalColumnVector) b.cols[0];
+    in.vector[0].update("9999999999999999.99", (short) 2); // set to max possible value
+    expr.evaluate(b);
+    r = (DecimalColumnVector) b.cols[2];
+    assertFalse(r.noNulls);
+    assertTrue(r.isNull[0]);
+  }
+
+  /* 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.
+   */
+  @Test
+  public void testDecimalColSubtractDecimalScalar() {
+    VectorizedRowBatch b = getVectorizedRowBatch3DecimalCols();
+    Decimal128 d = new Decimal128(1);
+    VectorExpression expr = new DecimalColSubtractDecimalScalar(0, d, 2);
+
+    // test without nulls
+    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("-4.30", (short) 2)));
+    assertTrue(r.vector[2].equals(new Decimal128("-1.00", (short) 2)));
+
+    // test that underflow produces null
+    b = getVectorizedRowBatch3DecimalCols();
+    DecimalColumnVector in = (DecimalColumnVector) b.cols[0];
+    in.vector[0].update("-9999999999999999.99", (short) 2); // set to min possible value
+    expr.evaluate(b);
+    r = (DecimalColumnVector) b.cols[2];
+    assertFalse(r.noNulls);
+    assertTrue(r.isNull[0]);
+  }
+
+  /* Spot check correctness of decimal column multiply decimal scalar. The case for
+   * addition checks all the cases for the template, so don't do that redundantly here.
+   */
+  @Test
+  public void testDecimalColMultiplyDecimalScalar() {
+    VectorizedRowBatch b = getVectorizedRowBatch3DecimalCols();
+    Decimal128 d = new Decimal128(2);
+    VectorExpression expr = new DecimalColMultiplyDecimalScalar(0, d, 2);
+
+    // test without nulls
+    expr.evaluate(b);
+    DecimalColumnVector r = (DecimalColumnVector) b.cols[2];
+    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 that overflow produces null
+    b = getVectorizedRowBatch3DecimalCols();
+    DecimalColumnVector in = (DecimalColumnVector) b.cols[0];
+    in.vector[0].update("9999999999999999.99", (short) 2); // set to max possible value
+    expr.evaluate(b);
+    r = (DecimalColumnVector) b.cols[2];
+    assertFalse(r.noNulls);
+    assertTrue(r.isNull[0]);
+  }
+
+  /* Test decimal scalar to decimal column addition. This is used to cover all the
+   * cases used in the source code template ScalarArithmeticColumnDecimal.txt.
+   */
+  @Test
+  public void testDecimalScalarAddDecimalColumn() {
+    VectorizedRowBatch b = getVectorizedRowBatch3DecimalCols();
+    Decimal128 d = new Decimal128(1);
+    VectorExpression expr = new DecimalScalarAddDecimalColumn(d, 0, 2);
+
+    // test without nulls
+    expr.evaluate(b);
+    DecimalColumnVector r = (DecimalColumnVector) b.cols[2];
+    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 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("2.20", (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 overflow produces null
+    b = getVectorizedRowBatch3DecimalCols();
+    in = (DecimalColumnVector) b.cols[0];
+    in.vector[0].update("9999999999999999.99", (short) 2); // set to max possible value
+    expr.evaluate(b);
+    r = (DecimalColumnVector) b.cols[2];
+    assertFalse(r.noNulls);
+    assertTrue(r.isNull[0]);
+  }
+
+  /* Spot check correctness of decimal scalar subtract decimal column. The case for
+   * addition checks all the cases for the template, so don't do that redundantly here.
+   */
+  @Test
+  public void testDecimalScalarSubtractDecimalColumn() {
+    VectorizedRowBatch b = getVectorizedRowBatch3DecimalCols();
+    Decimal128 d = new Decimal128(1);
+    VectorExpression expr = new DecimalScalarSubtractDecimalColumn(d, 0, 2);
+
+    // test without nulls
+    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("4.30", (short) 2)));
+    assertTrue(r.vector[2].equals(new Decimal128("1.00", (short) 2)));
+
+    // test that overflow produces null
+    b = getVectorizedRowBatch3DecimalCols();
+    DecimalColumnVector in = (DecimalColumnVector) b.cols[0];
+    in.vector[0].update("-9999999999999999.99", (short) 2); // set to min possible value
+    expr.evaluate(b);
+    r = (DecimalColumnVector) b.cols[2];
+    assertFalse(r.noNulls);
+    assertTrue(r.isNull[0]);
+  }
+
+  /* Spot check correctness of decimal scalar multiply decimal column. The case for
+   * addition checks all the cases for the template, so don't do that redundantly here.
+   */
+
+  @Test
+  public void testDecimalScalarMultiplyDecimalColumn() {
+    VectorizedRowBatch b = getVectorizedRowBatch3DecimalCols();
+    Decimal128 d = new Decimal128(2);
+    VectorExpression expr = new DecimalScalarMultiplyDecimalColumn(d, 0, 2);
+
+    // test without nulls
+    expr.evaluate(b);
+    DecimalColumnVector r = (DecimalColumnVector) b.cols[2];
+    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 that overflow produces null
+    b = getVectorizedRowBatch3DecimalCols();
+    DecimalColumnVector in = (DecimalColumnVector) b.cols[0];
+    in.vector[0].update("9999999999999999.99", (short) 2); // set to max possible value
+    expr.evaluate(b);
+    r = (DecimalColumnVector) b.cols[2];
+    assertFalse(r.noNulls);
+    assertTrue(r.isNull[0]);
+  }
+
+  // Make a decimal batch with three columns, including two for inputs and one for the result.
   private VectorizedRowBatch getVectorizedRowBatch3DecimalCols() {
     VectorizedRowBatch b = new VectorizedRowBatch(3);
     DecimalColumnVector v0, v1;



Mime
View raw message