You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by xu...@apache.org on 2014/03/17 21:42:40 UTC

svn commit: r1578558 - in /hive/trunk/ql/src: java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFPrintf.java test/org/apache/hadoop/hive/ql/udf/generic/TestGenericUDFPrintf.java

Author: xuefu
Date: Mon Mar 17 20:42:39 2014
New Revision: 1578558

URL: http://svn.apache.org/r1578558
Log:
HIVE-6620: UDF printf doesn't take either CHAR or VARCHAR as the first argument (reviewed by Jason)

Added:
    hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/udf/generic/TestGenericUDFPrintf.java
Modified:
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFPrintf.java

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFPrintf.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFPrintf.java?rev=1578558&r1=1578557&r2=1578558&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFPrintf.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFPrintf.java Mon Mar 17 20:42:39 2014
@@ -29,18 +29,13 @@ import org.apache.hadoop.hive.ql.exec.UD
 import org.apache.hadoop.hive.ql.metadata.HiveException;
 import org.apache.hadoop.hive.serde.serdeConstants;
 import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
+import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorConverters;
 import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector.Category;
+import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorConverters.Converter;
 import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
-import org.apache.hadoop.hive.serde2.objectinspector.primitive.BooleanObjectInspector;
-import org.apache.hadoop.hive.serde2.objectinspector.primitive.ByteObjectInspector;
-import org.apache.hadoop.hive.serde2.objectinspector.primitive.DoubleObjectInspector;
-import org.apache.hadoop.hive.serde2.objectinspector.primitive.FloatObjectInspector;
-import org.apache.hadoop.hive.serde2.objectinspector.primitive.IntObjectInspector;
-import org.apache.hadoop.hive.serde2.objectinspector.primitive.LongObjectInspector;
 import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
-import org.apache.hadoop.hive.serde2.objectinspector.primitive.ShortObjectInspector;
-import org.apache.hadoop.hive.serde2.objectinspector.primitive.StringObjectInspector;
-import org.apache.hadoop.hive.serde2.objectinspector.primitive.TimestampObjectInspector;
+import org.apache.hadoop.hive.serde2.objectinspector.primitive.WritableHiveDecimalObjectInspector;
+import org.apache.hadoop.hive.serde2.objectinspector.primitive.WritableStringObjectInspector;
 import org.apache.hadoop.io.Text;
 
 /**
@@ -58,6 +53,8 @@ import org.apache.hadoop.io.Text;
     + "  \"Hello World 100 days\"")
 public class GenericUDFPrintf extends GenericUDF {
   private transient ObjectInspector[] argumentOIs;
+  protected transient Converter converterFormat;
+
   private final Text resultText = new Text();
 
   @Override
@@ -67,12 +64,25 @@ public class GenericUDFPrintf extends Ge
           "The function PRINTF(String format, Obj... args) needs at least one arguments.");
     }
 
-    if (arguments[0].getTypeName() != serdeConstants.STRING_TYPE_NAME
-      && arguments[0].getTypeName() != serdeConstants.VOID_TYPE_NAME) {
+    WritableStringObjectInspector resultOI = PrimitiveObjectInspectorFactory.writableStringObjectInspector;
+
+    if (arguments[0].getCategory() == ObjectInspector.Category.PRIMITIVE) {
+      PrimitiveObjectInspector poi = ((PrimitiveObjectInspector) arguments[0]);
+      if (poi.getPrimitiveCategory() == PrimitiveObjectInspector.PrimitiveCategory.STRING ||
+          poi.getPrimitiveCategory() == PrimitiveObjectInspector.PrimitiveCategory.CHAR ||
+          poi.getPrimitiveCategory() == PrimitiveObjectInspector.PrimitiveCategory.VARCHAR ||
+          poi.getPrimitiveCategory() == PrimitiveObjectInspector.PrimitiveCategory.VOID) {
+        converterFormat = ObjectInspectorConverters.getConverter(arguments[0], resultOI);
+      } else {
         throw new UDFArgumentTypeException(0, "Argument 1"
-        + " of function PRINTF must be \"" + serdeConstants.STRING_TYPE_NAME
-        + "\", but \"" + arguments[0].getTypeName() + "\" was found.");
+            + " of function PRINTF must be \"" + serdeConstants.STRING_TYPE_NAME
+            + "\", but \"" + arguments[0].getTypeName() + "\" was found.");
       }
+    } else {
+      throw new UDFArgumentTypeException(0, "Argument 1"
+          + " of function PRINTF must be \"" + serdeConstants.STRING_TYPE_NAME
+          + "\", but \"" + arguments[0].getTypeName() + "\" was found.");
+    }
 
     for (int i = 1; i < arguments.length; i++) {
       if (!arguments[i].getCategory().equals(Category.PRIMITIVE)){
@@ -83,58 +93,46 @@ public class GenericUDFPrintf extends Ge
     }
 
     argumentOIs = arguments;
-    return PrimitiveObjectInspectorFactory.writableStringObjectInspector;
+    return resultOI;
   }
 
   @Override
   public Object evaluate(DeferredObject[] arguments) throws HiveException {
+    // If the first argument is null, return null. (It's okay for other arguments to be null, in
+    // which case, "null" will be printed.)
+    if (arguments[0].get() == null) {
+      return null;
+    }
+
     StringBuilder sb = new StringBuilder();
     Formatter formatter = new Formatter(sb, Locale.US);
 
-    String pattern = ((StringObjectInspector) argumentOIs[0])
-        .getPrimitiveJavaObject(arguments[0].get());
+    Text pattern = (Text)converterFormat.convert(arguments[0].get());
 
-    ArrayList argumentList = new ArrayList();
+    ArrayList<Object> argumentList = new ArrayList<Object>();
     for (int i = 1; i < arguments.length; i++) {
       switch (((PrimitiveObjectInspector)argumentOIs[i]).getPrimitiveCategory()) {
         case BOOLEAN:
-          argumentList.add(((BooleanObjectInspector)argumentOIs[i]).get(arguments[i].get()));
-          break;
         case BYTE:
-          argumentList.add(((ByteObjectInspector)argumentOIs[i]).get(arguments[i].get()));
-          break;
         case SHORT:
-          argumentList.add(((ShortObjectInspector)argumentOIs[i]).get(arguments[i].get()));
-          break;
         case INT:
-          argumentList.add(((IntObjectInspector)argumentOIs[i]).get(arguments[i].get()));
-          break;
         case LONG:
-          argumentList.add(((LongObjectInspector)argumentOIs[i]).get(arguments[i].get()));
-          break;
         case FLOAT:
-          argumentList.add(((FloatObjectInspector)argumentOIs[i]).get(arguments[i].get()));
-          break;
         case DOUBLE:
-          argumentList.add(((DoubleObjectInspector)argumentOIs[i]).get(arguments[i].get()));
-          break;
+        case CHAR:
+        case VARCHAR:
         case STRING:
-          argumentList.add(((StringObjectInspector)argumentOIs[i])
-            .getPrimitiveJavaObject(arguments[i].get()));
-          break;
         case TIMESTAMP:
-          argumentList.add(((TimestampObjectInspector)argumentOIs[i])
+        case DECIMAL:
+          argumentList.add(((PrimitiveObjectInspector)argumentOIs[i])
             .getPrimitiveJavaObject(arguments[i].get()));
           break;
-        case BINARY:
-          argumentList.add(arguments[i].get());
-          break;
         default:
           argumentList.add(arguments[i].get());
           break;
       }
     }
-    formatter.format(pattern, argumentList.toArray());
+    formatter.format(pattern.toString(), argumentList.toArray());
 
     resultText.set(sb.toString());
     return resultText;

Added: hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/udf/generic/TestGenericUDFPrintf.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/udf/generic/TestGenericUDFPrintf.java?rev=1578558&view=auto
==============================================================================
--- hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/udf/generic/TestGenericUDFPrintf.java (added)
+++ hive/trunk/ql/src/test/org/apache/hadoop/hive/ql/udf/generic/TestGenericUDFPrintf.java Mon Mar 17 20:42:39 2014
@@ -0,0 +1,140 @@
+/**
+ * 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.metadata.HiveException;
+import org.apache.hadoop.hive.ql.udf.generic.GenericUDF.DeferredJavaObject;
+import org.apache.hadoop.hive.ql.udf.generic.GenericUDF.DeferredObject;
+import org.apache.hadoop.hive.serde2.io.HiveCharWritable;
+import org.apache.hadoop.hive.serde2.io.HiveDecimalWritable;
+import org.apache.hadoop.hive.serde2.io.HiveVarcharWritable;
+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.TypeInfoFactory;
+import org.apache.hadoop.io.Text;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestGenericUDFPrintf {
+
+  @Test
+  public void testCharVarcharArgs() throws HiveException {
+    GenericUDFPrintf udf = new GenericUDFPrintf();
+
+    ObjectInspector[] inputOIs = {
+        PrimitiveObjectInspectorFactory.writableStringObjectInspector,
+        PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(TypeInfoFactory.getCharTypeInfo(5)),
+        PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(TypeInfoFactory.getVarcharTypeInfo(7))
+    };
+
+    HiveCharWritable argChar = new HiveCharWritable();
+    argChar.set("hello");
+    HiveVarcharWritable argVarchar = new HiveVarcharWritable();
+    argVarchar.set("world");
+    DeferredObject[] args = {
+        new DeferredJavaObject(new Text("1st: %s, 2nd: %s")),
+        new DeferredJavaObject(argChar),
+        new DeferredJavaObject(argVarchar)
+    };
+
+    PrimitiveObjectInspector oi = (PrimitiveObjectInspector) udf.initialize(inputOIs);
+    Assert.assertEquals(PrimitiveObjectInspectorFactory.writableStringObjectInspector, oi);
+    Text res = (Text) udf.evaluate(args);
+    Assert.assertEquals("1st: hello, 2nd: world", res.toString());
+  }
+
+  @Test
+  public void testCharFormat() throws HiveException {
+    GenericUDFPrintf udf = new GenericUDFPrintf();
+
+    ObjectInspector[] inputOIs = {
+        PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(TypeInfoFactory.getCharTypeInfo(10)),
+        PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(TypeInfoFactory.getVarcharTypeInfo(7))
+    };
+
+    HiveCharWritable formatChar = new HiveCharWritable();
+    formatChar.set("arg1=%s");
+    HiveVarcharWritable argVarchar = new HiveVarcharWritable();
+    argVarchar.set("world");
+    DeferredObject[] args = {
+        new DeferredJavaObject(formatChar),
+        new DeferredJavaObject(argVarchar)
+    };
+
+    PrimitiveObjectInspector oi = (PrimitiveObjectInspector) udf.initialize(inputOIs);
+    Assert.assertEquals(PrimitiveObjectInspectorFactory.writableStringObjectInspector, oi);
+    Text res = (Text) udf.evaluate(args);
+    Assert.assertEquals("arg1=world", res.toString());
+  }
+
+  @Test
+  public void testVarcharFormat() throws HiveException {
+    GenericUDFPrintf udf = new GenericUDFPrintf();
+
+    ObjectInspector[] inputOIs = {
+        PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(TypeInfoFactory.getVarcharTypeInfo(7)),
+        PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(TypeInfoFactory.getCharTypeInfo(5))
+    };
+
+    HiveCharWritable argChar = new HiveCharWritable();
+    argChar.set("hello");
+    HiveVarcharWritable formatVarchar = new HiveVarcharWritable();
+    formatVarchar.set("arg1=%s");
+    DeferredObject[] args = {
+        new DeferredJavaObject(formatVarchar),
+        new DeferredJavaObject(argChar)
+    };
+
+    PrimitiveObjectInspector oi = (PrimitiveObjectInspector) udf.initialize(inputOIs);
+    Assert.assertEquals(PrimitiveObjectInspectorFactory.writableStringObjectInspector, oi);
+    Text res = (Text) udf.evaluate(args);
+    Assert.assertEquals("arg1=hello", res.toString());
+  }
+
+  @Test
+  public void testDecimalArgs() throws HiveException {
+    GenericUDFPrintf udf = new GenericUDFPrintf();
+
+    ObjectInspector[] inputOIs = {
+        PrimitiveObjectInspectorFactory.writableStringObjectInspector,
+        PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(TypeInfoFactory.getDecimalTypeInfo(5, 2)),
+        PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(TypeInfoFactory.getDecimalTypeInfo(3, 2))
+    };
+
+    HiveDecimalWritable argDec1 = new HiveDecimalWritable();
+    argDec1.set(HiveDecimal.create("234.789"));
+    HiveDecimalWritable argDec2 = new HiveDecimalWritable();
+    argDec2.set(HiveDecimal.create("3.5"));
+
+    DeferredObject[] args = {
+        new DeferredJavaObject(new Text("1st: %s, 2nd: %s")),
+        new DeferredJavaObject(argDec1),
+        new DeferredJavaObject(argDec2)
+    };
+
+    PrimitiveObjectInspector oi = (PrimitiveObjectInspector) udf.initialize(inputOIs);
+    Assert.assertEquals(PrimitiveObjectInspectorFactory.writableStringObjectInspector, oi);
+    Text res = (Text) udf.evaluate(args);
+    Assert.assertEquals("1st: 234.79, 2nd: 3.5", res.toString());
+  }
+
+}