You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by br...@apache.org on 2013/11/04 22:32:20 UTC
svn commit: r1538778 - in /hive/trunk/ql/src:
java/org/apache/hadoop/hive/ql/exec/
java/org/apache/hadoop/hive/ql/exec/vector/expressions/
java/org/apache/hadoop/hive/ql/optimizer/physical/
java/org/apache/hadoop/hive/ql/udf/ java/org/apache/hadoop/hiv...
Author: brock
Date: Mon Nov 4 21:32:20 2013
New Revision: 1538778
URL: http://svn.apache.org/r1538778
Log:
HIVE-4523 - round() function with specified decimal places not consistent with mysql (Xuefu Zhang via Brock Noland)
Added:
hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFRound.java
hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/RoundUtils.java
hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/udf/generic/TestGenericUDFRound.java
Removed:
hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFRound.java
hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/udf/TestUDFRound.java
Modified:
hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java
hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/RoundWithNumDigitsDoubleToDouble.java
hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/optimizer/physical/Vectorizer.java
hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/exec/vector/TestVectorizationContext.java
hive/trunk/ql/src/test/queries/clientpositive/udf_round.q
hive/trunk/ql/src/test/results/clientpositive/decimal_udf.q.out
hive/trunk/ql/src/test/results/clientpositive/udf_round.q.out
hive/trunk/ql/src/test/results/compiler/plan/udf4.q.xml
Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java?rev=1538778&r1=1538777&r2=1538778&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java Mon Nov 4 21:32:20 2013
@@ -105,7 +105,6 @@ import org.apache.hadoop.hive.ql.udf.UDF
import org.apache.hadoop.hive.ql.udf.UDFRegExpReplace;
import org.apache.hadoop.hive.ql.udf.UDFRepeat;
import org.apache.hadoop.hive.ql.udf.UDFReverse;
-import org.apache.hadoop.hive.ql.udf.UDFRound;
import org.apache.hadoop.hive.ql.udf.UDFRpad;
import org.apache.hadoop.hive.ql.udf.UDFSecond;
import org.apache.hadoop.hive.ql.udf.UDFSign;
@@ -203,7 +202,7 @@ public final class FunctionRegistry {
registerGenericUDF("size", GenericUDFSize.class);
- registerUDF("round", UDFRound.class, false);
+ registerGenericUDF("round", GenericUDFRound.class);
registerUDF("floor", UDFFloor.class, false);
registerUDF("sqrt", UDFSqrt.class, false);
registerUDF("ceil", UDFCeil.class, false);
Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/RoundWithNumDigitsDoubleToDouble.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/RoundWithNumDigitsDoubleToDouble.java?rev=1538778&r1=1538777&r2=1538778&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/RoundWithNumDigitsDoubleToDouble.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/RoundWithNumDigitsDoubleToDouble.java Mon Nov 4 21:32:20 2013
@@ -19,8 +19,7 @@
package org.apache.hadoop.hive.ql.exec.vector.expressions;
import org.apache.hadoop.hive.ql.exec.vector.VectorExpressionDescriptor;
-import org.apache.hadoop.hive.ql.udf.UDFRound;
-import org.apache.hadoop.hive.serde2.io.DoubleWritable;
+import org.apache.hadoop.hive.ql.udf.generic.RoundUtils;
import org.apache.hadoop.io.IntWritable;
// Vectorized implementation of ROUND(Col, N) function
@@ -29,28 +28,21 @@ public class RoundWithNumDigitsDoubleToD
private static final long serialVersionUID = 1L;
private IntWritable decimalPlaces;
- private transient UDFRound roundFunc;
- private transient DoubleWritable dw;
public RoundWithNumDigitsDoubleToDouble(int colNum, long scalarVal, int outputColumn) {
super(colNum, outputColumn);
this.decimalPlaces = new IntWritable();
- roundFunc = new UDFRound();
- dw = new DoubleWritable();
decimalPlaces.set((int) scalarVal);
}
public RoundWithNumDigitsDoubleToDouble() {
super();
- dw = new DoubleWritable();
- roundFunc = new UDFRound();
}
// Round to the specified number of decimal places using the standard Hive round function.
@Override
public double func(double d) {
- dw.set(d);
- return roundFunc.evaluate(dw, decimalPlaces).get();
+ return RoundUtils.round(d, decimalPlaces.get());
}
void setDecimalPlaces(IntWritable decimalPlaces) {
@@ -61,14 +53,6 @@ public class RoundWithNumDigitsDoubleToD
return this.decimalPlaces;
}
- void setRoundFunc(UDFRound roundFunc) {
- this.roundFunc = roundFunc;
- }
-
- UDFRound getRoundFunc() {
- return this.roundFunc;
- }
-
@Override
public void setArg(long l) {
this.decimalPlaces.set((int) l);
Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/optimizer/physical/Vectorizer.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/optimizer/physical/Vectorizer.java?rev=1538778&r1=1538777&r2=1538778&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/optimizer/physical/Vectorizer.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/optimizer/physical/Vectorizer.java Mon Nov 4 21:32:20 2013
@@ -73,6 +73,7 @@ import org.apache.hadoop.hive.ql.udf.gen
import org.apache.hadoop.hive.ql.udf.generic.GenericUDFOPNotNull;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDFOPNull;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDFOPOr;
+import org.apache.hadoop.hive.ql.udf.generic.GenericUDFRound;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDFTimestamp;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDFToUnixTimeStamp;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDFUpper;
@@ -158,7 +159,7 @@ public class Vectorizer implements Physi
supportedGenericUDFs.add(UDFLog.class);
supportedGenericUDFs.add(UDFPower.class);
supportedGenericUDFs.add(UDFPosMod.class);
- supportedGenericUDFs.add(UDFRound.class);
+ supportedGenericUDFs.add(GenericUDFRound.class);
supportedGenericUDFs.add(UDFSqrt.class);
supportedGenericUDFs.add(UDFSign.class);
supportedGenericUDFs.add(UDFRand.class);
Added: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFRound.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFRound.java?rev=1538778&view=auto
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFRound.java (added)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFRound.java Mon Nov 4 21:32:20 2013
@@ -0,0 +1,267 @@
+/**
+ * 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.udf.generic;
+
+import org.apache.hadoop.hive.common.type.HiveDecimal;
+import org.apache.hadoop.hive.ql.exec.Description;
+import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
+import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException;
+import org.apache.hadoop.hive.ql.exec.vector.VectorizedExpressions;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.RoundWithNumDigitsDoubleToDouble;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.FuncRoundDoubleToDouble;
+import org.apache.hadoop.hive.ql.metadata.HiveException;
+import org.apache.hadoop.hive.serde2.io.ByteWritable;
+import org.apache.hadoop.hive.serde2.io.DoubleWritable;
+import org.apache.hadoop.hive.serde2.io.HiveDecimalWritable;
+import org.apache.hadoop.hive.serde2.io.ShortWritable;
+import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
+import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector.Category;
+import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorConverters;
+import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorConverters.Converter;
+import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
+import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector.PrimitiveCategory;
+import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
+import org.apache.hadoop.hive.serde2.objectinspector.primitive.WritableConstantByteObjectInspector;
+import org.apache.hadoop.hive.serde2.objectinspector.primitive.WritableConstantIntObjectInspector;
+import org.apache.hadoop.hive.serde2.objectinspector.primitive.WritableConstantLongObjectInspector;
+import org.apache.hadoop.hive.serde2.objectinspector.primitive.WritableConstantShortObjectInspector;
+import org.apache.hadoop.hive.serde2.typeinfo.DecimalTypeInfo;
+import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory;
+import org.apache.hadoop.io.FloatWritable;
+import org.apache.hadoop.io.IntWritable;
+import org.apache.hadoop.io.LongWritable;
+
+/**
+ * Note: rounding function permits rounding off integer digits in decimal numbers, which essentially
+ * downgrades the scale to negative territory. However, Hive decimal only allow non-negative scales.
+ * This can cause confusion, for example, when a decimal number 1234.567 of type decimal(7,3) is
+ * rounded with -2 scale, which produces a decimal number, 1200. The type of the output is
+ * decimal(5,0), which does not exactly represents what the number means. Thus, user should
+ * be aware of this, and use negative rounding for decimal with caution. However, Hive is in line
+ * with the behavior that MYSQL demonstrates.
+ *
+ * At a certain point, we should probably support negative scale for decimal type.
+ *
+ * GenericUDFRound.
+ *
+ */
+@Description(name = "round",
+ value = "_FUNC_(x[, d]) - round x to d decimal places",
+ extended = "Example:\n"
+ + " > SELECT _FUNC_(12.3456, 1) FROM src LIMIT 1;\n" + " 12.3'")
+@VectorizedExpressions({FuncRoundDoubleToDouble.class, RoundWithNumDigitsDoubleToDouble.class})
+public class GenericUDFRound extends GenericUDF {
+ private transient PrimitiveObjectInspector inputOI;
+ private int scale = 0;
+
+ private transient PrimitiveCategory inputType;
+ private transient Converter converterFromString;
+
+ @Override
+ public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
+ if (arguments.length < 1 || arguments.length > 2) {
+ throw new UDFArgumentLengthException(
+ "ROUND requires one or two argument, got " + arguments.length);
+ }
+
+ inputOI = (PrimitiveObjectInspector) arguments[0];
+ if (inputOI.getCategory() != Category.PRIMITIVE) {
+ throw new UDFArgumentException(
+ "ROUND input only takes primitive types, got " + inputOI.getTypeName());
+ }
+
+ if (arguments.length == 2) {
+ PrimitiveObjectInspector scaleOI = (PrimitiveObjectInspector) arguments[1];
+ switch (scaleOI.getPrimitiveCategory()) {
+ case VOID:
+ break;
+ case BYTE:
+ if (!(scaleOI instanceof WritableConstantByteObjectInspector)) {
+ throw new UDFArgumentException("ROUND second argument only takes constant");
+ }
+ scale = ((WritableConstantByteObjectInspector)scaleOI).getWritableConstantValue().get();
+ break;
+ case SHORT:
+ if (!(scaleOI instanceof WritableConstantShortObjectInspector)) {
+ throw new UDFArgumentException("ROUND second argument only takes constant");
+ }
+ scale = ((WritableConstantShortObjectInspector)scaleOI).getWritableConstantValue().get();
+ break;
+ case INT:
+ if (!(scaleOI instanceof WritableConstantIntObjectInspector)) {
+ throw new UDFArgumentException("ROUND second argument only takes constant");
+ }
+ scale = ((WritableConstantIntObjectInspector)scaleOI).getWritableConstantValue().get();
+ break;
+ case LONG:
+ if (!(scaleOI instanceof WritableConstantLongObjectInspector)) {
+ throw new UDFArgumentException("ROUND second argument only takes constant");
+ }
+ long l = ((WritableConstantLongObjectInspector)scaleOI).getWritableConstantValue().get();
+ if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) {
+ throw new UDFArgumentException("ROUND scale argument out of allowed range");
+ }
+ scale = (int)l;
+ break;
+ default:
+ throw new UDFArgumentException("ROUND second argument only takes integer constant");
+ }
+ }
+
+ inputType = inputOI.getPrimitiveCategory();
+ ObjectInspector outputOI = null;
+ switch (inputType) {
+ case DECIMAL:
+ DecimalTypeInfo inputTypeInfo = (DecimalTypeInfo) inputOI.getTypeInfo();
+ DecimalTypeInfo typeInfo = getOutputTypeInfo(inputTypeInfo, scale);
+ outputOI = PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(typeInfo);
+ break;
+ case VOID:
+ case BYTE:
+ case SHORT:
+ case INT:
+ case LONG:
+ case FLOAT:
+ case DOUBLE:
+ outputOI = PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(inputType);
+ break;
+ case STRING:
+ case VARCHAR:
+ outputOI = PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(PrimitiveCategory.DOUBLE);
+ converterFromString = ObjectInspectorConverters.getConverter(inputOI, outputOI);
+ break;
+ default:
+ throw new UDFArgumentException("Only numeric data types are allowed for ROUND function. Got " +
+ inputType.name());
+ }
+
+ return outputOI;
+ }
+
+ private static DecimalTypeInfo getOutputTypeInfo(DecimalTypeInfo inputTypeInfo, int dec) {
+ int prec = inputTypeInfo.precision();
+ int scale = inputTypeInfo.scale();
+ int intParts = prec - scale;
+
+ // If we are rounding, we may introduce one more integer digit.
+ int newIntParts = dec < scale ? intParts + 1 : intParts;
+
+ int newScale = dec < 0 ? 0 : Math.min(dec, HiveDecimal.MAX_SCALE);
+
+ int newPrec = Math.min(newIntParts + newScale, HiveDecimal.MAX_PRECISION);
+
+ return TypeInfoFactory.getDecimalTypeInfo(newPrec, newScale);
+ }
+
+ @Override
+ public Object evaluate(DeferredObject[] arguments) throws HiveException {
+ if (arguments.length == 2 && (arguments[1] == null || arguments[1].get() == null)) {
+ return null;
+ }
+
+ if (arguments[0] == null) {
+ return null;
+ }
+
+ Object input = arguments[0].get();
+ if (input == null) {
+ return null;
+ }
+
+ switch (inputType) {
+ case VOID:
+ return null;
+ case DECIMAL:
+ HiveDecimalWritable decimalWritable = (HiveDecimalWritable) inputOI.getPrimitiveWritableObject(input);
+ HiveDecimal dec = RoundUtils.round(decimalWritable.getHiveDecimal(), scale);
+ if (dec == null) {
+ return null;
+ }
+ return new HiveDecimalWritable(dec);
+ case BYTE:
+ ByteWritable byteWritable = (ByteWritable)inputOI.getPrimitiveWritableObject(input);
+ if (scale >= 0) {
+ return byteWritable;
+ } else {
+ return new ByteWritable((byte)RoundUtils.round(byteWritable.get(), scale));
+ }
+ case SHORT:
+ ShortWritable shortWritable = (ShortWritable)inputOI.getPrimitiveWritableObject(input);
+ if (scale >= 0) {
+ return shortWritable;
+ } else {
+ return new ShortWritable((short)RoundUtils.round(shortWritable.get(), scale));
+ }
+ case INT:
+ IntWritable intWritable = (IntWritable)inputOI.getPrimitiveWritableObject(input);
+ if (scale >= 0) {
+ return intWritable;
+ } else {
+ return new IntWritable((int)RoundUtils.round(intWritable.get(), scale));
+ }
+ case LONG:
+ LongWritable longWritable = (LongWritable)inputOI.getPrimitiveWritableObject(input);
+ if (scale >= 0) {
+ return longWritable;
+ } else {
+ return new LongWritable(RoundUtils.round(longWritable.get(), scale));
+ }
+ case FLOAT:
+ float f = ((FloatWritable)inputOI.getPrimitiveWritableObject(input)).get();
+ return new FloatWritable((float)RoundUtils.round(f, scale));
+ case DOUBLE:
+ return round(((DoubleWritable)inputOI.getPrimitiveWritableObject(input)), scale);
+ case STRING:
+ case VARCHAR:
+ DoubleWritable doubleValue = (DoubleWritable) converterFromString.convert(input);
+ if (doubleValue == null) {
+ return null;
+ }
+ return round(doubleValue, scale);
+ default:
+ throw new UDFArgumentException("Only numeric data types are allowed for ROUND function. Got " +
+ inputType.name());
+ }
+ }
+
+ private static DoubleWritable round(DoubleWritable input, int scale) {
+ double d = input.get();
+ if (Double.isNaN(d) || Double.isInfinite(d)) {
+ return new DoubleWritable(d);
+ } else {
+ return new DoubleWritable(RoundUtils.round(d, scale));
+ }
+ }
+
+ @Override
+ public String getDisplayString(String[] children) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("round(");
+ if (children.length > 0) {
+ sb.append(children[0]);
+ for (int i = 1; i < children.length; i++) {
+ sb.append(", ");
+ sb.append(children[i]);
+ }
+ }
+ sb.append(")");
+ return sb.toString();
+ }
+
+}
Added: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/RoundUtils.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/RoundUtils.java?rev=1538778&view=auto
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/RoundUtils.java (added)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/RoundUtils.java Mon Nov 4 21:32:20 2013
@@ -0,0 +1,60 @@
+/**
+ * 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.udf.generic;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+import org.apache.hadoop.hive.common.type.HiveDecimal;
+
+/**
+ * Utility class for generic round UDF.
+ *
+ */
+public class RoundUtils {
+
+ private RoundUtils() {
+ }
+
+ /**
+ * Rounding a double is approximate, as the double value itself is approximate.
+ * A double literal, such as 3.15, may not be represented internally exactly as
+ * 3.15. thus, the rounding value of it can be off on the surface. For accurate
+ * rounding, consider using decimal type.
+ *
+ * @param input input value
+ * @param scale decimal place
+ * @return rounded value
+ */
+ public static double round(double input, int scale) {
+ if (Double.isNaN(input) || Double.isInfinite(input)) {
+ return input;
+ }
+ return BigDecimal.valueOf(input).setScale(scale, RoundingMode.HALF_UP).doubleValue();
+ }
+
+ public static long round(long input, int scale) {
+ return BigDecimal.valueOf(input).setScale(scale, RoundingMode.HALF_UP).longValue();
+ }
+
+ public static HiveDecimal round(HiveDecimal input, int scale) {
+ return input.setScale(scale, HiveDecimal.ROUND_HALF_UP);
+ }
+
+}
Modified: hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/exec/vector/TestVectorizationContext.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/exec/vector/TestVectorizationContext.java?rev=1538778&r1=1538777&r2=1538778&view=diff
==============================================================================
--- hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/exec/vector/TestVectorizationContext.java (original)
+++ hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/exec/vector/TestVectorizationContext.java Mon Nov 4 21:32:20 2013
@@ -28,7 +28,27 @@ import java.util.Map;
import junit.framework.Assert;
-import org.apache.hadoop.hive.ql.exec.vector.expressions.*;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.ColAndCol;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.ColOrCol;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.FilterExprAndExpr;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.FilterExprOrExpr;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.FuncLogWithBaseDoubleToDouble;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.FuncLogWithBaseLongToDouble;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.FuncPowerDoubleToDouble;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.IsNotNull;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.IsNull;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.NotCol;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.RoundWithNumDigitsDoubleToDouble;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.SelectColumnIsFalse;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.SelectColumnIsNotNull;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.SelectColumnIsNull;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.SelectColumnIsTrue;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.StringLTrim;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.StringLower;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.StringUpper;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.VectorExpression;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.VectorUDFUnixTimeStampLong;
+import org.apache.hadoop.hive.ql.exec.vector.expressions.VectorUDFYearLong;
import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.DoubleColUnaryMinus;
import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.FilterDoubleColLessDoubleScalar;
import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.FilterDoubleColumnBetween;
@@ -59,7 +79,6 @@ import org.apache.hadoop.hive.ql.plan.Ex
import org.apache.hadoop.hive.ql.plan.ExprNodeConstantDesc;
import org.apache.hadoop.hive.ql.plan.ExprNodeDesc;
import org.apache.hadoop.hive.ql.plan.ExprNodeGenericFuncDesc;
-import org.apache.hadoop.hive.ql.plan.api.OperatorType;
import org.apache.hadoop.hive.ql.udf.UDFLTrim;
import org.apache.hadoop.hive.ql.udf.UDFLog;
import org.apache.hadoop.hive.ql.udf.UDFOPMinus;
@@ -68,7 +87,6 @@ import org.apache.hadoop.hive.ql.udf.UDF
import org.apache.hadoop.hive.ql.udf.UDFOPNegative;
import org.apache.hadoop.hive.ql.udf.UDFOPPlus;
import org.apache.hadoop.hive.ql.udf.UDFPower;
-import org.apache.hadoop.hive.ql.udf.UDFRound;
import org.apache.hadoop.hive.ql.udf.UDFSin;
import org.apache.hadoop.hive.ql.udf.UDFYear;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
@@ -83,6 +101,7 @@ import org.apache.hadoop.hive.ql.udf.gen
import org.apache.hadoop.hive.ql.udf.generic.GenericUDFOPNotNull;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDFOPNull;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDFOPOr;
+import org.apache.hadoop.hive.ql.udf.generic.GenericUDFRound;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDFToUnixTimeStamp;
import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory;
import org.junit.Test;
@@ -766,15 +785,14 @@ public class TestVectorizationContext {
Assert.assertEquals(FuncSinDoubleToDouble.class, ve.getClass());
// Round without digits
- gudfBridge = new GenericUDFBridge("round", false, UDFRound.class.getName());
- mathFuncExpr.setGenericUDF(gudfBridge);
+ GenericUDFRound udfRound = new GenericUDFRound();
+ mathFuncExpr.setGenericUDF(udfRound);
mathFuncExpr.setChildren(children2);
ve = vc.getVectorExpression(mathFuncExpr);
Assert.assertEquals(FuncRoundDoubleToDouble.class, ve.getClass());
// Round with digits
- gudfBridge = new GenericUDFBridge("round", false, UDFRound.class.getName());
- mathFuncExpr.setGenericUDF(gudfBridge);
+ mathFuncExpr.setGenericUDF(udfRound);
children2.add(new ExprNodeConstantDesc(4));
mathFuncExpr.setChildren(children2);
ve = vc.getVectorExpression(mathFuncExpr);
@@ -829,8 +847,7 @@ public class TestVectorizationContext {
Assert.assertTrue(4.5 == ((FuncPowerDoubleToDouble) ve).getPower());
//Round with default decimal places
- gudfBridge = new GenericUDFBridge("round", false, UDFRound.class.getName());
- mathFuncExpr.setGenericUDF(gudfBridge);
+ mathFuncExpr.setGenericUDF(udfRound);
children2.clear();
children2.add(colDesc2);
mathFuncExpr.setChildren(children2);
Added: hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/udf/generic/TestGenericUDFRound.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/udf/generic/TestGenericUDFRound.java?rev=1538778&view=auto
==============================================================================
--- hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/udf/generic/TestGenericUDFRound.java (added)
+++ hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/udf/generic/TestGenericUDFRound.java Mon Nov 4 21:32:20 2013
@@ -0,0 +1,153 @@
+/**
+ * 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.udf.generic;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.Assert;
+
+import org.apache.hadoop.hive.common.type.HiveDecimal;
+import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
+import org.apache.hadoop.hive.ql.parse.TypeCheckProcFactory;
+import org.apache.hadoop.hive.ql.plan.ExprNodeConstantDesc;
+import org.apache.hadoop.hive.ql.plan.ExprNodeDesc;
+import org.apache.hadoop.hive.ql.testutil.BaseScalarUdfTest;
+import org.apache.hadoop.hive.ql.testutil.DataBuilder;
+import org.apache.hadoop.hive.ql.testutil.OperatorTestUtils;
+import org.apache.hadoop.hive.serde2.io.ByteWritable;
+import org.apache.hadoop.hive.serde2.io.DoubleWritable;
+import org.apache.hadoop.hive.serde2.io.HiveDecimalWritable;
+import org.apache.hadoop.hive.serde2.io.ShortWritable;
+import org.apache.hadoop.hive.serde2.objectinspector.InspectableObject;
+import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
+import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
+import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
+import org.apache.hadoop.hive.serde2.typeinfo.DecimalTypeInfo;
+import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory;
+import org.apache.hadoop.io.FloatWritable;
+import org.apache.hadoop.io.IntWritable;
+import org.apache.hadoop.io.LongWritable;
+import org.junit.Test;
+
+public class TestGenericUDFRound extends BaseScalarUdfTest {
+ private static final String[] cols = {"s", "i", "d", "f", "b", "sh", "l", "dec"};
+
+ @Override
+ public InspectableObject[] getBaseTable() {
+ DataBuilder db = new DataBuilder();
+ db.setColumnNames(cols);
+ db.setColumnTypes(
+ PrimitiveObjectInspectorFactory.javaStringObjectInspector,
+ PrimitiveObjectInspectorFactory.javaIntObjectInspector,
+ PrimitiveObjectInspectorFactory.javaDoubleObjectInspector,
+ PrimitiveObjectInspectorFactory.javaFloatObjectInspector,
+ PrimitiveObjectInspectorFactory.javaByteObjectInspector,
+ PrimitiveObjectInspectorFactory.javaShortObjectInspector,
+ PrimitiveObjectInspectorFactory.javaLongObjectInspector,
+ PrimitiveObjectInspectorFactory.getPrimitiveJavaObjectInspector(TypeInfoFactory.getDecimalTypeInfo(15, 5)));
+ db.addRow("one", 170, new Double("1.1"), new Float("32.1234"), new Byte("25"), new Short("1234"), 123456L, HiveDecimal.create("983.7235"));
+ db.addRow( "-234", null, null, new Float("0.347232"), new Byte("109"), new Short("551"), 923L, HiveDecimal.create("983723.005"));
+ db.addRow("454.45", 22345, new Double("-23.00009"), new Float("-3.4"), new Byte("76"), new Short("2321"), 9232L, HiveDecimal.create("-932032.7"));
+ return db.createRows();
+ }
+
+ @Override
+ public InspectableObject[] getExpectedResult() {
+ DataBuilder db = new DataBuilder();
+ db.setColumnNames("_col1", "_col2", "_col3", "_col4", "_col5", "_col6", "_col7", "_col8");
+ db.setColumnTypes(PrimitiveObjectInspectorFactory.javaStringObjectInspector,
+ PrimitiveObjectInspectorFactory.writableIntObjectInspector,
+ PrimitiveObjectInspectorFactory.writableDoubleObjectInspector,
+ PrimitiveObjectInspectorFactory.writableFloatObjectInspector,
+ PrimitiveObjectInspectorFactory.writableByteObjectInspector,
+ PrimitiveObjectInspectorFactory.writableShortObjectInspector,
+ PrimitiveObjectInspectorFactory.writableLongObjectInspector,
+ PrimitiveObjectInspectorFactory.writableHiveDecimalObjectInspector);
+ db.addRow(null, new IntWritable(170), new DoubleWritable(1.1), new FloatWritable(32f),
+ new ByteWritable((byte)0), new ShortWritable((short)1234), new LongWritable(123500L), new HiveDecimalWritable(HiveDecimal.create("983.724")));
+ db.addRow(new DoubleWritable(-200), null, null, new FloatWritable(0f),
+ new ByteWritable((byte)100), new ShortWritable((short)551), new LongWritable(900L), new HiveDecimalWritable(HiveDecimal.create("983723.005")));
+ db.addRow(new DoubleWritable(500), new IntWritable(22345), new DoubleWritable(-23.000), new FloatWritable(-3f),
+ new ByteWritable((byte)100), new ShortWritable((short)2321), new LongWritable(9200L), new HiveDecimalWritable(HiveDecimal.create("-932032.7")));
+ return db.createRows();
+ }
+
+ @Override
+ public List<ExprNodeDesc> getExpressionList() throws UDFArgumentException {
+ List<ExprNodeDesc> exprs = new ArrayList<ExprNodeDesc>(cols.length);
+ for (int i = 0; i < cols.length; i++) {
+ exprs.add(OperatorTestUtils.getStringColumn(cols[i]));
+ }
+
+ ExprNodeDesc[] scales = { new ExprNodeConstantDesc(TypeInfoFactory.intTypeInfo, -2),
+ new ExprNodeConstantDesc(TypeInfoFactory.byteTypeInfo, (byte)0),
+ new ExprNodeConstantDesc(TypeInfoFactory.shortTypeInfo, (short)3),
+ new ExprNodeConstantDesc(TypeInfoFactory.intTypeInfo, 0),
+ new ExprNodeConstantDesc(TypeInfoFactory.longTypeInfo, -2L),
+ new ExprNodeConstantDesc(TypeInfoFactory.intTypeInfo, 0),
+ new ExprNodeConstantDesc(TypeInfoFactory.intTypeInfo, -2),
+ new ExprNodeConstantDesc(TypeInfoFactory.intTypeInfo, 3) };
+
+ List<ExprNodeDesc> earr = new ArrayList<ExprNodeDesc>();
+ for (int j = 0; j < cols.length; j++) {
+ ExprNodeDesc r = TypeCheckProcFactory.DefaultExprProcessor.getFuncExprNodeDesc("round", exprs.get(j), scales[j]);
+ earr.add(r);
+ }
+
+ return earr;
+ }
+
+ @Test
+ public void testDecimalRoundingMetaData() throws UDFArgumentException {
+ GenericUDFRound udf = new GenericUDFRound();
+ ObjectInspector[] inputOIs = {
+ PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(TypeInfoFactory.getDecimalTypeInfo(7, 3)),
+ PrimitiveObjectInspectorFactory.getPrimitiveWritableConstantObjectInspector(TypeInfoFactory.intTypeInfo, new IntWritable(2))
+ };
+ PrimitiveObjectInspector outputOI = (PrimitiveObjectInspector) udf.initialize(inputOIs);
+ DecimalTypeInfo outputTypeInfo = (DecimalTypeInfo)outputOI.getTypeInfo();
+ Assert.assertEquals(TypeInfoFactory.getDecimalTypeInfo(7, 2), outputTypeInfo);
+ }
+
+ @Test
+ public void testDecimalRoundingMetaData1() throws UDFArgumentException {
+ GenericUDFRound udf = new GenericUDFRound();
+ ObjectInspector[] inputOIs = {
+ PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(TypeInfoFactory.getDecimalTypeInfo(7, 3)),
+ PrimitiveObjectInspectorFactory.getPrimitiveWritableConstantObjectInspector(TypeInfoFactory.intTypeInfo, new IntWritable(-2))
+ };
+ PrimitiveObjectInspector outputOI = (PrimitiveObjectInspector) udf.initialize(inputOIs);
+ DecimalTypeInfo outputTypeInfo = (DecimalTypeInfo)outputOI.getTypeInfo();
+ Assert.assertEquals(TypeInfoFactory.getDecimalTypeInfo(5, 0), outputTypeInfo);
+ }
+
+ @Test
+ public void testDecimalRoundingMetaData2() throws UDFArgumentException {
+ GenericUDFRound udf = new GenericUDFRound();
+ ObjectInspector[] inputOIs = {
+ PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(TypeInfoFactory.getDecimalTypeInfo(7, 3)),
+ PrimitiveObjectInspectorFactory.getPrimitiveWritableConstantObjectInspector(TypeInfoFactory.intTypeInfo, new IntWritable(5))
+ };
+ PrimitiveObjectInspector outputOI = (PrimitiveObjectInspector) udf.initialize(inputOIs);
+ DecimalTypeInfo outputTypeInfo = (DecimalTypeInfo)outputOI.getTypeInfo();
+ Assert.assertEquals(TypeInfoFactory.getDecimalTypeInfo(9, 5), outputTypeInfo);
+ }
+
+}
Modified: hive/trunk/ql/src/test/queries/clientpositive/udf_round.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientpositive/udf_round.q?rev=1538778&r1=1538777&r2=1538778&view=diff
==============================================================================
--- hive/trunk/ql/src/test/queries/clientpositive/udf_round.q (original)
+++ hive/trunk/ql/src/test/queries/clientpositive/udf_round.q Mon Nov 4 21:32:20 2013
@@ -42,5 +42,5 @@ SELECT
round(3.141592653589793, 15), round(3.141592653589793, 16)
FROM src tablesample (1 rows);
-SELECT round(1809242.3151111344, 9), round(-1809242.3151111344, 9)
+SELECT round(1809242.3151111344, 9), round(-1809242.3151111344, 9), round(1809242.3151111344BD, 9), round(-1809242.3151111344BD, 9)
FROM src tablesample (1 rows);
Modified: hive/trunk/ql/src/test/results/clientpositive/decimal_udf.q.out
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/results/clientpositive/decimal_udf.q.out?rev=1538778&r1=1538777&r2=1538778&view=diff
==============================================================================
--- hive/trunk/ql/src/test/results/clientpositive/decimal_udf.q.out (original)
+++ hive/trunk/ql/src/test/results/clientpositive/decimal_udf.q.out Mon Nov 4 21:32:20 2013
@@ -1742,7 +1742,7 @@ STAGE PLANS:
Select Operator
expressions:
expr: round(key, 2)
- type: decimal(65,30)
+ type: decimal(38,2)
outputColumnNames: _col0
ListSink
Modified: hive/trunk/ql/src/test/results/clientpositive/udf_round.q.out
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/results/clientpositive/udf_round.q.out?rev=1538778&r1=1538777&r2=1538778&view=diff
==============================================================================
--- hive/trunk/ql/src/test/results/clientpositive/udf_round.q.out (original)
+++ hive/trunk/ql/src/test/results/clientpositive/udf_round.q.out Mon Nov 4 21:32:20 2013
@@ -40,7 +40,7 @@ FROM src tablesample (1 rows)
POSTHOOK: type: QUERY
POSTHOOK: Input: default@src
#### A masked pattern was here ####
-55555 55555.0 55555.0 55555.0 55555.0 55560.0 55600.0 56000.0 60000.0 100000.0 0.0 0.0 0.0
+55555 55555 55555 55555 55555 55560 55600 56000 60000 100000 0 0 0
PREHOOK: query: SELECT
round(125.315), round(125.315, 0),
round(125.315, 1), round(125.315, 2), round(125.315, 3), round(125.315, 4),
@@ -109,14 +109,14 @@ POSTHOOK: type: QUERY
POSTHOOK: Input: default@src
#### A masked pattern was here ####
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3.0 3.1 3.14 3.142 3.1416 3.14159 3.141593 3.1415927 3.14159265 3.141592654 3.1415926536 3.14159265359 3.14159265359 3.1415926535898 3.1415926535898 3.14159265358979 3.141592653589793 3.141592653589793
-PREHOOK: query: SELECT round(1809242.3151111344, 9), round(-1809242.3151111344, 9)
+PREHOOK: query: SELECT round(1809242.3151111344, 9), round(-1809242.3151111344, 9), round(1809242.3151111344BD, 9), round(-1809242.3151111344BD, 9)
FROM src tablesample (1 rows)
PREHOOK: type: QUERY
PREHOOK: Input: default@src
#### A masked pattern was here ####
-POSTHOOK: query: SELECT round(1809242.3151111344, 9), round(-1809242.3151111344, 9)
+POSTHOOK: query: SELECT round(1809242.3151111344, 9), round(-1809242.3151111344, 9), round(1809242.3151111344BD, 9), round(-1809242.3151111344BD, 9)
FROM src tablesample (1 rows)
POSTHOOK: type: QUERY
POSTHOOK: Input: default@src
#### A masked pattern was here ####
-1809242.315111134 -1809242.315111134
+1809242.315111134 -1809242.315111134 1809242.315111134 -1809242.315111134
Modified: hive/trunk/ql/src/test/results/compiler/plan/udf4.q.xml
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/results/compiler/plan/udf4.q.xml?rev=1538778&r1=1538777&r2=1538778&view=diff
==============================================================================
--- hive/trunk/ql/src/test/results/compiler/plan/udf4.q.xml (original)
+++ hive/trunk/ql/src/test/results/compiler/plan/udf4.q.xml Mon Nov 4 21:32:20 2013
@@ -835,14 +835,7 @@
</object>
</void>
<void property="genericUDF">
- <object class="org.apache.hadoop.hive.ql.udf.generic.GenericUDFBridge">
- <void property="udfClassName">
- <string>org.apache.hadoop.hive.ql.udf.UDFRound</string>
- </void>
- <void property="udfName">
- <string>round</string>
- </void>
- </object>
+ <object class="org.apache.hadoop.hive.ql.udf.generic.GenericUDFRound"/>
</void>
<void property="typeInfo">
<object idref="PrimitiveTypeInfo0"/>
@@ -867,14 +860,7 @@
</object>
</void>
<void property="genericUDF">
- <object class="org.apache.hadoop.hive.ql.udf.generic.GenericUDFBridge">
- <void property="udfClassName">
- <string>org.apache.hadoop.hive.ql.udf.UDFRound</string>
- </void>
- <void property="udfName">
- <string>round</string>
- </void>
- </object>
+ <object class="org.apache.hadoop.hive.ql.udf.generic.GenericUDFRound"/>
</void>
<void property="typeInfo">
<object idref="PrimitiveTypeInfo0"/>
@@ -1243,14 +1229,7 @@
</object>
</void>
<void property="genericUDF">
- <object class="org.apache.hadoop.hive.ql.udf.generic.GenericUDFBridge">
- <void property="udfClassName">
- <string>org.apache.hadoop.hive.ql.udf.UDFRound</string>
- </void>
- <void property="udfName">
- <string>round</string>
- </void>
- </object>
+ <object class="org.apache.hadoop.hive.ql.udf.generic.GenericUDFRound"/>
</void>
<void property="typeInfo">
<object idref="PrimitiveTypeInfo0"/>