diff --git a/ant/src/org/apache/hadoop/hive/ant/GenVectorCode.java b/ant/src/org/apache/hadoop/hive/ant/GenVectorCode.java index 2ee0451..a9abb2e 100644 --- a/ant/src/org/apache/hadoop/hive/ant/GenVectorCode.java +++ b/ant/src/org/apache/hadoop/hive/ant/GenVectorCode.java @@ -215,6 +215,9 @@ {"FilterStringColumnCompareScalar", "Greater", ">"}, {"FilterStringColumnCompareScalar", "GreaterEqual", ">="}, + {"FilterStringColumnBetween", ""}, + {"FilterStringColumnBetween", "!"}, + {"StringColumnCompareScalar", "Equal", "=="}, {"StringColumnCompareScalar", "NotEqual", "!="}, {"StringColumnCompareScalar", "Less", "<"}, @@ -276,6 +279,11 @@ {"FilterColumnCompareColumn", "GreaterEqual", "long", "long", ">="}, {"FilterColumnCompareColumn", "GreaterEqual", "double", "long", ">="}, + {"FilterColumnBetween", "long", ""}, + {"FilterColumnBetween", "double", ""}, + {"FilterColumnBetween", "long", "!"}, + {"FilterColumnBetween", "double", "!"}, + {"ColumnCompareColumn", "Equal", "long", "double", "=="}, {"ColumnCompareColumn", "Equal", "double", "double", "=="}, {"ColumnCompareColumn", "NotEqual", "long", "double", "!="}, @@ -511,6 +519,8 @@ private void generate() throws Exception { generateFilterColumnCompareScalar(tdesc); } else if (tdesc[0].equals("FilterScalarCompareColumn")) { generateFilterScalarCompareColumn(tdesc); + } else if (tdesc[0].equals("FilterColumnBetween")) { + generateFilterColumnBetween(tdesc); } else if (tdesc[0].equals("ScalarArithmeticColumn")) { generateScalarArithmeticColumn(tdesc); } else if (tdesc[0].equals("FilterColumnCompareColumn")) { @@ -535,6 +545,8 @@ private void generate() throws Exception { generateVectorUDAFVar(tdesc); } else if (tdesc[0].equals("FilterStringColumnCompareScalar")) { generateFilterStringColumnCompareScalar(tdesc); + } else if (tdesc[0].equals("FilterStringColumnBetween")) { + generateFilterStringColumnBetween(tdesc); } else if (tdesc[0].equals("StringColumnCompareScalar")) { generateStringColumnCompareScalar(tdesc); } else if (tdesc[0].equals("FilterStringScalarCompareColumn")) { @@ -553,6 +565,40 @@ private void generate() throws Exception { testCodeGen.generateTestSuites(); } + private void generateFilterStringColumnBetween(String[] tdesc) throws IOException { + String optionalNot = tdesc[1]; + String className = "FilterStringColumn" + (optionalNot.equals("!") ? "Not" : "") + + "Between"; + String outputFile = joinPath(this.expressionOutputDirectory, className + ".java"); + + // Read the template into a string, expand it, and write it. + String templateFile = joinPath(this.expressionTemplateDirectory, tdesc[0] + ".txt"); + String templateString = readFile(templateFile); + templateString = templateString.replaceAll("", className); + templateString = templateString.replaceAll("", optionalNot); + writeFile(outputFile, templateString); + } + + private void generateFilterColumnBetween(String[] tdesc) throws IOException { + String operandType = tdesc[1]; + String optionalNot = tdesc[2]; + + String className = "Filter" + getCamelCaseType(operandType) + "Column" + + (optionalNot.equals("!") ? "Not" : "") + "Between"; + String inputColumnVectorType = getColumnVectorType(operandType); + String outputFile = joinPath(this.expressionOutputDirectory, className + ".java"); + + // Read the template into a string, expand it, and write it. + String templateFile = joinPath(this.expressionTemplateDirectory, tdesc[0] + ".txt"); + String templateString = readFile(templateFile); + templateString = templateString.replaceAll("", className); + templateString = templateString.replaceAll("", inputColumnVectorType); + templateString = templateString.replaceAll("", operandType); + templateString = templateString.replaceAll("", optionalNot); + + writeFile(outputFile, templateString); + } + private void generateColumnCompareColumn(String[] tdesc) throws IOException { //The variables are all same as ColumnCompareScalar except that //this template doesn't need a return type. Pass anything as return type. diff --git a/ql/src/gen/vectorization/ExpressionTemplates/FilterColumnBetween.txt b/ql/src/gen/vectorization/ExpressionTemplates/FilterColumnBetween.txt new file mode 100644 index 0000000..47be94a --- /dev/null +++ b/ql/src/gen/vectorization/ExpressionTemplates/FilterColumnBetween.txt @@ -0,0 +1,175 @@ +/** + * 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.; +import org.apache.hadoop.hive.ql.exec.vector.VectorizedRowBatch; + +/** + * Generated from template FilterColumnBetween.txt, which covers [NOT] BETWEEN filter + * expressions where a column is [NOT] between one scalar and another. + * Output is not produced in a separate column. The selected vector of the input + * {@link VectorizedRowBatch} is updated for in-place filtering. + */ +public class extends VectorExpression { + + private static final long serialVersionUID = 1L; + + private int colNum; + + // The comparison is of the form "column BETWEEN leftValue AND rightValue" + private leftValue; + private rightValue; + + public (int colNum, leftValue, rightValue) { + this.colNum = colNum; + this.leftValue = leftValue; + this.rightValue = rightValue; + } + + public () { + } + + @Override + public void evaluate(VectorizedRowBatch batch) { + + if (childExpressions != null) { + super.evaluateChildren(batch); + } + + inputColVector = () batch.cols[colNum]; + int[] sel = batch.selected; + boolean[] nullPos = inputColVector.isNull; + int n = batch.size; + [] vector = inputColVector.vector; + + // return immediately if batch is empty + if (n == 0) { + return; + } + + if (inputColVector.noNulls) { + if (inputColVector.isRepeating) { + + // All must be selected otherwise size would be zero. + // Repeating property will not change. + if ((vector[0] < leftValue || vector[0] > rightValue)) { + + // Entire batch is filtered out. + batch.size = 0; + } + } else if (batch.selectedInUse) { + int newSize = 0; + for(int j = 0; j != n; j++) { + int i = sel[j]; + if ((leftValue <= vector[i] && vector[i] <= rightValue)) { + sel[newSize++] = i; + } + } + batch.size = newSize; + } else { + int newSize = 0; + for(int i = 0; i != n; i++) { + if ((leftValue <= vector[i] && vector[i] <= rightValue)) { + sel[newSize++] = i; + } + } + if (newSize < n) { + batch.size = newSize; + batch.selectedInUse = true; + } + } + } else { + if (inputColVector.isRepeating) { + + // All must be selected otherwise size would be zero. + // Repeating property will not change. + if (!nullPos[0]) { + if ((vector[0] < leftValue || vector[0] > rightValue)) { + + // Entire batch is filtered out. + batch.size = 0; + } + } else { + batch.size = 0; + } + } else if (batch.selectedInUse) { + int newSize = 0; + for(int j = 0; j != n; j++) { + int i = sel[j]; + if (!nullPos[i]) { + if ((leftValue <= vector[i] && vector[i] <= rightValue)) { + sel[newSize++] = i; + } + } + } + //Change the selected vector + batch.size = newSize; + } else { + int newSize = 0; + for(int i = 0; i != n; i++) { + if (!nullPos[i]) { + if ((leftValue <= vector[i] && vector[i] <= rightValue)) { + sel[newSize++] = i; + } + } + } + if (newSize < n) { + batch.size = newSize; + batch.selectedInUse = true; + } + } + } + } + + @Override + public int getOutputColumn() { + return -1; + } + + @Override + public String getOutputType() { + return "boolean"; + } + + public int getColNum() { + return colNum; + } + + public void setColNum(int colNum) { + this.colNum = colNum; + } + + public getLeftValue() { + return leftValue; + } + + public void setLeftValue( value) { + this.leftValue = value; + } + + public getRightValue() { + return rightValue; + } + + public void setRightValue( value) { + this.leftValue = value; + } +} diff --git a/ql/src/gen/vectorization/ExpressionTemplates/FilterStringColumnBetween.txt b/ql/src/gen/vectorization/ExpressionTemplates/FilterStringColumnBetween.txt new file mode 100644 index 0000000..b40d8b7 --- /dev/null +++ b/ql/src/gen/vectorization/ExpressionTemplates/FilterStringColumnBetween.txt @@ -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.expressions.StringExpr; +import org.apache.hadoop.hive.ql.exec.vector.BytesColumnVector; +import org.apache.hadoop.hive.ql.exec.vector.VectorizedRowBatch; + +/** + * This is a generated class to evaluate a [NOT] BETWEEN comparison on a vector of strings. + */ +public class extends VectorExpression { + + private static final long serialVersionUID = 1L; + + private int colNum; + private byte[] left; + private byte[] right; + + public (int colNum, byte[] left, byte[] right) { + this.colNum = colNum; + this.left = left; + this.right = right; + } + + public () { + } + + @Override + public void evaluate(VectorizedRowBatch batch) { + if (childExpressions != null) { + super.evaluateChildren(batch); + } + BytesColumnVector inputColVector = (BytesColumnVector) batch.cols[colNum]; + int[] sel = batch.selected; + boolean[] nullPos = inputColVector.isNull; + int n = batch.size; + byte[][] vector = inputColVector.vector; + int[] length = inputColVector.length; + int[] start = inputColVector.start; + + + // return immediately if batch is empty + if (n == 0) { + return; + } + + if (inputColVector.noNulls) { + if (inputColVector.isRepeating) { + + // All must be selected otherwise size would be zero. Repeating property will not change. + if ((StringExpr.compare(vector[0], start[0], length[0], left, 0, left.length) < 0 + || StringExpr.compare(right, 0, right.length, vector[0], start[0], length[0]) < 0)) { + + //Entire batch is filtered out. + batch.size = 0; + } + } else if (batch.selectedInUse) { + int newSize = 0; + for(int j = 0; j != n; j++) { + int i = sel[j]; + if ((StringExpr.compare(left, 0, left.length, vector[i], start[i], length[i]) <= 0 + && StringExpr.compare(vector[i], start[i], length[i], right, 0, right.length) <= 0)) { + sel[newSize++] = i; + } + } + batch.size = newSize; + } else { + int newSize = 0; + for(int i = 0; i != n; i++) { + if ((StringExpr.compare(left, 0, left.length, vector[i], start[i], length[i]) <= 0 + && StringExpr.compare(vector[i], start[i], length[i], right, 0, right.length) <= 0)) { + sel[newSize++] = i; + } + } + if (newSize < n) { + batch.size = newSize; + batch.selectedInUse = true; + } + } + } else { + if (inputColVector.isRepeating) { + + // All must be selected otherwise size would be zero. Repeating property will not change. + if (!nullPos[0]) { + if ((StringExpr.compare(vector[0], start[0], length[0], left, 0, left.length) < 0 + || StringExpr.compare(right, 0, right.length, vector[0], start[0], length[0]) < 0)) { + + //Entire batch is filtered out. + batch.size = 0; + } + } else { + batch.size = 0; + } + } else if (batch.selectedInUse) { + int newSize = 0; + for(int j=0; j != n; j++) { + int i = sel[j]; + if (!nullPos[i]) { + if ((StringExpr.compare(left, 0, left.length, vector[i], start[i], length[i]) <= 0 + && StringExpr.compare(vector[i], start[i], length[i], right, 0, right.length) <= 0)) { + sel[newSize++] = i; + } + } + } + + //Change the selected vector + batch.size = newSize; + } else { + int newSize = 0; + for(int i = 0; i != n; i++) { + if (!nullPos[i]) { + if ((StringExpr.compare(left, 0, left.length, vector[i], start[i], length[i]) <= 0 + && StringExpr.compare(vector[i], start[i], length[i], right, 0, right.length) <= 0)) { + sel[newSize++] = i; + } + } + } + if (newSize < n) { + batch.size = newSize; + batch.selectedInUse = true; + } + } + } + } + + @Override + public int getOutputColumn() { + return -1; + } + + @Override + public String getOutputType() { + return "boolean"; + } + + public int getColNum() { + return colNum; + } + + public void setColNum(int colNum) { + this.colNum = colNum; + } + + public byte[] getLeft() { + return left; + } + + public void setLeft(byte[] value) { + this.left = value; + } + + public byte[] getRight() { + return right; + } + + public void setRight(byte[] value) { + this.right = value; + } +} diff --git a/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/VectorizationContext.java b/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/VectorizationContext.java index 79437a5..53c5d5f 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/VectorizationContext.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/VectorizationContext.java @@ -19,6 +19,7 @@ package org.apache.hadoop.hive.ql.exec.vector; import java.lang.reflect.Constructor; +import java.sql.Timestamp; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -76,6 +77,12 @@ import org.apache.hadoop.hive.ql.exec.vector.expressions.aggregates.gen.VectorUDAFVarSampDouble; import org.apache.hadoop.hive.ql.exec.vector.expressions.aggregates.gen.VectorUDAFVarSampLong; import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.CastLongToBooleanViaLongToLong; +import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.FilterDoubleColumnBetween; +import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.FilterDoubleColumnNotBetween; +import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.FilterLongColumnBetween; +import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.FilterLongColumnNotBetween; +import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.FilterStringColumnBetween; +import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.FilterStringColumnNotBetween; import org.apache.hadoop.hive.ql.exec.vector.udf.VectorUDFAdaptor; import org.apache.hadoop.hive.ql.exec.vector.udf.VectorUDFArgDesc; import org.apache.hadoop.hive.ql.metadata.HiveException; @@ -86,6 +93,7 @@ import org.apache.hadoop.hive.ql.plan.ExprNodeGenericFuncDesc; import org.apache.hadoop.hive.ql.plan.api.OperatorType; import org.apache.hadoop.hive.ql.udf.generic.GenericUDFConcat; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDFBetween; import org.apache.hadoop.hive.ql.udf.UDFAcos; import org.apache.hadoop.hive.ql.udf.UDFAsin; import org.apache.hadoop.hive.ql.udf.UDFAtan; @@ -158,10 +166,13 @@ import org.apache.hadoop.hive.ql.udf.generic.GenericUDFToUnixTimeStamp; import org.apache.hadoop.hive.ql.udf.generic.GenericUDFUpper; import org.apache.hadoop.hive.serde2.io.DoubleWritable; +import org.apache.hadoop.hive.serde2.io.TimestampWritable; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils; +import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.LongWritable; +import org.apache.hadoop.io.BooleanWritable; import org.apache.hadoop.io.Text; /** @@ -606,11 +617,124 @@ private VectorExpression getVectorExpression(GenericUDF udf, return getUnaryAbsExpression(childExpr); } else if (udf instanceof GenericUDFTimestamp) { return getCastToTimestamp(childExpr); + } else if (udf instanceof GenericUDFBetween) { + return getBetweenFilterExpression(childExpr); } throw new HiveException("Udf: "+udf.getClass().getSimpleName()+", is not supported"); } + // Get a [NOT] BETWEEN filter expression + private VectorExpression getBetweenFilterExpression(List childExpr) + throws HiveException { + + ExprNodeDesc colExpr = childExpr.get(1); + ExprNodeDesc leftExpr = childExpr.get(2); + ExprNodeDesc rightExpr = childExpr.get(3); + + // Fold constants for - or + operators in front of constant values + leftExpr = foldConstantsForUnaryExpression(leftExpr); + rightExpr = foldConstantsForUnaryExpression(rightExpr); + + VectorExpression v1 = null; + VectorExpression expr = null; + int inputCol; + ExprNodeConstantDesc constDesc; + boolean notKeywordPresent = getBooleanScalar(childExpr.get(0)); + long leftL = Long.MIN_VALUE; + long rightL = Long.MIN_VALUE; + double leftD = Double.NaN; + double rightD = Double.NaN; + byte[] leftS = null; + byte[] rightS = null; + + String colType = colExpr.getTypeString(); + if (isIntFamily(colType)) { + leftL = getLongScalar(leftExpr); + rightL = getLongScalar(rightExpr); + } else if (isFloatFamily(colType)) { + leftD = getDoubleScalar(leftExpr); + rightD = getDoubleScalar(rightExpr); + } else if (colType.equals("timestamp")) { + leftL = getTimestampScalar(leftExpr); + rightL = getTimestampScalar(rightExpr); + } else if (colType.equals("string")) { + leftS = getStringScalar(leftExpr); + rightS = getStringScalar(rightExpr); + } else { + throw new HiveException("Invalid type '" + + colType + "' for vectorized [NOT] BETWEEN"); + } + + // TODO finish the rest + + // It's assumed that the code will not allow us into this function unless + // The left and right arguments are constants and their types match + // the input column or expression type. + + if ((colExpr instanceof ExprNodeColumnDesc) + && (isIntFamily(colType) || colType.equals("timestamp"))) { + ExprNodeColumnDesc colDesc = (ExprNodeColumnDesc) colExpr; + inputCol = getInputColumnIndex(colDesc.getColumn()); + if (notKeywordPresent) { + expr = new FilterLongColumnNotBetween(inputCol, leftL, rightL); + } else { + expr = new FilterLongColumnBetween(inputCol, leftL, rightL); + } + } else if ((colExpr instanceof ExprNodeGenericFuncDesc) + && (isIntFamily(colType) || colType.equals("timestamp"))) { + v1 = getVectorExpression(colExpr); + inputCol = v1.getOutputColumn(); + if (notKeywordPresent) { + expr = new FilterLongColumnNotBetween(inputCol, leftL, rightL); + } else { + expr = new FilterLongColumnBetween(inputCol, leftL, rightL); + } + } else if ((colExpr instanceof ExprNodeColumnDesc) + && isFloatFamily(colType)) { + ExprNodeColumnDesc colDesc = (ExprNodeColumnDesc) colExpr; + inputCol = getInputColumnIndex(colDesc.getColumn()); + if (notKeywordPresent) { + expr = new FilterDoubleColumnNotBetween(inputCol, leftD, rightD); + } else { + expr = new FilterDoubleColumnBetween(inputCol, leftD, rightD); + } + } else if ((colExpr instanceof ExprNodeGenericFuncDesc) + && isFloatFamily(colType)) { + v1 = getVectorExpression(colExpr); + inputCol = v1.getOutputColumn(); + if (notKeywordPresent) { + expr = new FilterDoubleColumnNotBetween(inputCol, leftD, rightD); + } else { + expr = new FilterDoubleColumnBetween(inputCol, leftD, rightD); + } + } else if ((colExpr instanceof ExprNodeColumnDesc) && colType.equals("string")) { + ExprNodeColumnDesc colDesc = (ExprNodeColumnDesc) colExpr; + inputCol = getInputColumnIndex(colDesc.getColumn()); + if (notKeywordPresent) { + expr = new FilterStringColumnNotBetween(inputCol, leftS, rightS); + } else { + expr = new FilterStringColumnBetween(inputCol, leftS, rightS); + } + } else if ((colExpr instanceof ExprNodeGenericFuncDesc) && colType.equals("string")) { + v1 = getVectorExpression(colExpr); + inputCol = v1.getOutputColumn(); + if (notKeywordPresent) { + expr = new FilterDoubleColumnNotBetween(inputCol, leftD, rightD); + } else { + expr = new FilterDoubleColumnBetween(inputCol, leftD, rightD); + } + } else { + throw new HiveException("Type " + colType + + "not supported for vectorized BETWEEN"); + } + if (v1 != null) { + expr.setChildExpressions(new VectorExpression [] {v1}); + ocm.freeOutputColumn(v1.getOutputColumn()); + } + return expr; + } + private VectorExpression getUnaryAbsExpression(List childExpr) throws HiveException { String argType = childExpr.get(0).getTypeString(); @@ -1016,6 +1140,80 @@ private long getLongScalar(ExprNodeDesc expr) throws HiveException { + "Expecting integer or bigint"); } + // Get a string scalar value as a byte array + private byte[] getStringScalar(ExprNodeDesc expr) throws HiveException { + if (!(expr instanceof ExprNodeConstantDesc)) { + throw new HiveException("Constant string value expected for expression argument. " + + "Non-constant argument not supported for vectorization."); + } + ExprNodeConstantDesc constExpr = (ExprNodeConstantDesc) expr; + if (constExpr.getTypeString().equals("string")) { + String s = (String) constExpr.getValue(); + byte[] result; + try { + result = s.getBytes("UTF-8"); + } catch (Exception e) { + throw new HiveException ("Unable to convert string constant '" + s + "' to UTF-8"); + } + return result; + } + + throw new HiveException("Udf: unhandled constant type for scalar argument. " + + "Expecting string."); + } + + // Get a timestamp as a long in number of nanos, from a string constant. + private long getTimestampScalar(ExprNodeDesc expr) throws HiveException { + if (!(expr instanceof ExprNodeConstantDesc)) { + throw new HiveException("Constant timestamp value expected for expression argument. " + + "Non-constant argument not supported for vectorization."); + } + ExprNodeConstantDesc constExpr = (ExprNodeConstantDesc) expr; + if (constExpr.getTypeString().equals("string")) { + + // create expression tree with type cast from string to timestamp + ExprNodeGenericFuncDesc expr2 = new ExprNodeGenericFuncDesc(); + GenericUDFTimestamp f = new GenericUDFTimestamp(); + expr2.setGenericUDF(f); + ArrayList children = new ArrayList(); + children.add(expr); + expr2.setChildExprs(children); + + // initialize and evaluate + ExprNodeEvaluator evaluator = ExprNodeEvaluatorFactory.get(expr2); + ObjectInspector output = evaluator.initialize(null); + Object constant = evaluator.evaluate(null); + Object java = ObjectInspectorUtils.copyToStandardJavaObject(constant, output); + + if (!(java instanceof Timestamp)) { + throw new HiveException("Udf: failed to convert from string to timestamp"); + } + Timestamp ts = (Timestamp) java; + long result = ts.getTime(); + result *= 1000000; // shift left 6 digits to make room for nanos below ms precision + result += ts.getNanos() % 1000000; // add in nanos, after removing the ms portion + return result; + } + + throw new HiveException("Udf: unhandled constant type for scalar argument. " + + "Expecting string."); + } + + private boolean getBooleanScalar(ExprNodeDesc expr) throws HiveException { + if (!(expr instanceof ExprNodeConstantDesc)) { + throw new HiveException("Constant value expected for UDF argument. " + + "Non-constant argument not supported for vectorization."); + } + ExprNodeConstantDesc constExpr = (ExprNodeConstantDesc) expr; + + if (constExpr.getTypeString().equalsIgnoreCase("boolean")) { + return (Boolean) constExpr.getValue(); + } + + throw new HiveException("Udf: unhandled constant type for scalar argument. " + + "Expecting boolean"); + } + /* Return a vector expression for string concatenation, including the column-scalar, * scalar-column, and column-column cases. */ diff --git a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/physical/Vectorizer.java b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/physical/Vectorizer.java index 3e6edb5..8932825 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/physical/Vectorizer.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/physical/Vectorizer.java @@ -125,6 +125,7 @@ import org.apache.hadoop.hive.ql.udf.UDFYear; import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; import org.apache.hadoop.hive.ql.udf.generic.GenericUDFAbs; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDFBetween; import org.apache.hadoop.hive.ql.udf.generic.GenericUDFBridge; import org.apache.hadoop.hive.ql.udf.generic.GenericUDFConcat; import org.apache.hadoop.hive.ql.udf.generic.GenericUDFLower; @@ -235,6 +236,7 @@ public Vectorizer() { supportedGenericUDFs.add(GenericUDFUpper.class); supportedGenericUDFs.add(GenericUDFConcat.class); supportedGenericUDFs.add(GenericUDFAbs.class); + supportedGenericUDFs.add(GenericUDFBetween.class); // For type casts supportedGenericUDFs.add(UDFToLong.class);