/**
* 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;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import junit.framework.TestCase;
import org.apache.hadoop.hive.common.type.HiveVarchar;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.hive.ql.exec.FunctionInfo.FunctionResource;
import org.apache.hadoop.hive.ql.exec.FunctionInfo.FunctionType;
import org.apache.hadoop.hive.ql.plan.ExprNodeDesc;
import org.apache.hadoop.hive.ql.plan.ExprNodeGenericFuncDesc;
import org.apache.hadoop.hive.ql.session.SessionState;
import org.apache.hadoop.hive.ql.udf.UDFLn;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFMax;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDFConcat;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDFCurrentTimestamp;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDTFExplode;
import org.apache.hadoop.hive.serde2.io.DateWritable;
import org.apache.hadoop.hive.serde2.io.DoubleWritable;
import org.apache.hadoop.hive.serde2.io.HiveDecimalWritable;
import org.apache.hadoop.hive.serde2.io.TimestampWritable;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector.PrimitiveCategory;
import org.apache.hadoop.hive.serde2.typeinfo.PrimitiveTypeInfo;
import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo;
import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory;
import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoUtils;
import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.junit.Assert;
public class TestFunctionRegistry extends TestCase {
public class TestUDF {
public void same(DoubleWritable x, DoubleWritable y) {}
public void same(HiveDecimalWritable x, HiveDecimalWritable y) {}
public void same(Text x, Text y) {}
public void one(IntWritable x, HiveDecimalWritable y) {}
public void one(IntWritable x, DoubleWritable y) {}
public void one(IntWritable x, IntWritable y) {}
public void mismatch(DateWritable x, HiveDecimalWritable y) {}
public void mismatch(TimestampWritable x, HiveDecimalWritable y) {}
public void mismatch(BytesWritable x, DoubleWritable y) {}
public void typeaffinity1(DateWritable x) {}
public void typeaffinity1(DoubleWritable x) {};
public void typeaffinity1(Text x) {}
public void typeaffinity2(IntWritable x) {}
public void typeaffinity2(DoubleWritable x) {}
}
TypeInfo varchar5;
TypeInfo varchar10;
TypeInfo maxVarchar;
TypeInfo char5;
TypeInfo char10;
@Override
protected void setUp() {
String maxVarcharTypeName = "varchar(" + HiveVarchar.MAX_VARCHAR_LENGTH + ")";
maxVarchar = TypeInfoFactory.getPrimitiveTypeInfo(maxVarcharTypeName);
varchar10 = TypeInfoFactory.getPrimitiveTypeInfo("varchar(10)");
varchar5 = TypeInfoFactory.getPrimitiveTypeInfo("varchar(5)");
char10 = TypeInfoFactory.getPrimitiveTypeInfo("char(10)");
char5 = TypeInfoFactory.getPrimitiveTypeInfo("char(5)");
SessionState.start(new HiveConf());
}
private void implicit(TypeInfo a, TypeInfo b, boolean convertible) {
assertEquals(convertible, TypeInfoUtils.implicitConvertible(a, b));
}
public void testImplicitConversion() {
implicit(TypeInfoFactory.intTypeInfo, TypeInfoFactory.decimalTypeInfo, true);
implicit(TypeInfoFactory.longTypeInfo, TypeInfoFactory.decimalTypeInfo, true);
implicit(TypeInfoFactory.floatTypeInfo, TypeInfoFactory.decimalTypeInfo, false);
implicit(TypeInfoFactory.doubleTypeInfo, TypeInfoFactory.decimalTypeInfo, false);
implicit(TypeInfoFactory.stringTypeInfo, TypeInfoFactory.decimalTypeInfo, false);
implicit(TypeInfoFactory.dateTypeInfo, TypeInfoFactory.decimalTypeInfo, false);
implicit(TypeInfoFactory.timestampTypeInfo, TypeInfoFactory.decimalTypeInfo, false);
implicit(varchar10, TypeInfoFactory.stringTypeInfo, true);
implicit(TypeInfoFactory.stringTypeInfo, varchar10, true);
// Try with parameterized varchar types
TypeInfo varchar10 = TypeInfoFactory.getPrimitiveTypeInfo("varchar(10)");
TypeInfo varchar20 = TypeInfoFactory.getPrimitiveTypeInfo("varchar(20)");
implicit(varchar10, TypeInfoFactory.stringTypeInfo, true);
implicit(varchar20, TypeInfoFactory.stringTypeInfo, true);
implicit(TypeInfoFactory.stringTypeInfo, varchar10, true);
implicit(TypeInfoFactory.stringTypeInfo, varchar20, true);
implicit(varchar20, varchar10, true);
implicit(char10, TypeInfoFactory.stringTypeInfo, true);
implicit(TypeInfoFactory.stringTypeInfo, char10, true);
implicit(char5, char10, true);
implicit(char5, varchar10, true);
implicit(varchar5, char10, true);
implicit(TypeInfoFactory.intTypeInfo, char10, true);
implicit(TypeInfoFactory.intTypeInfo, varchar10, true);
implicit(TypeInfoFactory.intTypeInfo, TypeInfoFactory.stringTypeInfo, true);
}
private static List<Method> getMethods(Class<?> udfClass, String methodName) {
List<Method> mlist = new ArrayList<Method>();
for (Method m : udfClass.getMethods()) {
if (m.getName().equals(methodName)) {
mlist.add(m);
}
}
return mlist;
}
private void typeAffinity(String methodName, TypeInfo inputType,
int expectedNumFoundMethods, Class expectedFoundType) {
List<Method> mlist = getMethods(TestUDF.class, methodName);
assertEquals(true, 1 < mlist.size());
List<TypeInfo> inputTypes = new ArrayList<TypeInfo>();
inputTypes.add(inputType);
// narrow down the possible choices based on type affinity
FunctionRegistry.filterMethodsByTypeAffinity(mlist, inputTypes);
assertEquals(expectedNumFoundMethods, mlist.size());
if (expectedNumFoundMethods == 1) {
assertEquals(expectedFoundType, mlist.get(0).getParameterTypes()[0]);
}
}
public void testTypeAffinity() {
// Prefer numeric type arguments over other method signatures
typeAffinity("typeaffinity1", TypeInfoFactory.shortTypeInfo, 1, DoubleWritable.class);
typeAffinity("typeaffinity1", TypeInfoFactory.intTypeInfo, 1, DoubleWritable.class);
typeAffinity("typeaffinity1", TypeInfoFactory.floatTypeInfo, 1, DoubleWritable.class);
// Prefer date type arguments over other method signatures
typeAffinity("typeaffinity1", TypeInfoFactory.dateTypeInfo, 1, DateWritable.class);
typeAffinity("typeaffinity1", TypeInfoFactory.timestampTypeInfo, 1, DateWritable.class);
// String type affinity
typeAffinity("typeaffinity1", TypeInfoFactory.stringTypeInfo, 1, Text.class);
typeAffinity("typeaffinity1", char5, 1, Text.class);
typeAffinity("typeaffinity1", varchar5, 1, Text.class);
// Type affinity does not help when multiple methods have the same type affinity.
typeAffinity("typeaffinity2", TypeInfoFactory.shortTypeInfo, 2, null);
// Type affinity does not help when type affinity does not match input args
typeAffinity("typeaffinity2", TypeInfoFactory.dateTypeInfo, 2, null);
}
private void verify(Class udf, String name, TypeInfo ta, TypeInfo tb,
Class a, Class b, boolean throwException) {
List<TypeInfo> args = new LinkedList<TypeInfo>();
args.add(ta);
args.add(tb);
Method result = null;
try {
result = FunctionRegistry.getMethodInternal(udf, name, false, args);
} catch (UDFArgumentException e) {
assert(throwException);
return;
}
assert(!throwException);
assertEquals(2, result.getParameterTypes().length);
assertEquals(a, result.getParameterTypes()[0]);
assertEquals(b, result.getParameterTypes()[1]);
}
public void testGetMethodInternal() {
verify(TestUDF.class, "same", TypeInfoFactory.intTypeInfo, TypeInfoFactory.intTypeInfo,
HiveDecimalWritable.class, HiveDecimalWritable.class, false);
verify(TestUDF.class, "same", TypeInfoFactory.doubleTypeInfo, TypeInfoFactory.doubleTypeInfo,
DoubleWritable.class, DoubleWritable.class, false);
verify(TestUDF.class, "same", TypeInfoFactory.doubleTypeInfo, TypeInfoFactory.decimalTypeInfo,
DoubleWritable.class, DoubleWritable.class, false);
verify(TestUDF.class, "same", TypeInfoFactory.decimalTypeInfo, TypeInfoFactory.doubleTypeInfo,
DoubleWritable.class, DoubleWritable.class, false);
verify(TestUDF.class, "same", TypeInfoFactory.decimalTypeInfo, TypeInfoFactory.decimalTypeInfo,
HiveDecimalWritable.class, HiveDecimalWritable.class, false);
verify(TestUDF.class, "one", TypeInfoFactory.intTypeInfo, TypeInfoFactory.decimalTypeInfo,
IntWritable.class, HiveDecimalWritable.class, false);
verify(TestUDF.class, "one", TypeInfoFactory.intTypeInfo, TypeInfoFactory.floatTypeInfo,
IntWritable.class, DoubleWritable.class, false);
verify(TestUDF.class, "one", TypeInfoFactory.intTypeInfo, TypeInfoFactory.intTypeInfo,
IntWritable.class, IntWritable.class, false);
// Passing char/varchar arguments should prefer the version of evaluate() with Text args.
verify(TestUDF.class, "same", varchar5, varchar10, Text.class, Text.class, false);
verify(TestUDF.class, "same", char5, char10, Text.class, Text.class, false);
verify(TestUDF.class, "mismatch", TypeInfoFactory.voidTypeInfo, TypeInfoFactory.intTypeInfo,
null, null, true);
}
private void common(TypeInfo a, TypeInfo b, TypeInfo result) {
assertEquals(result, FunctionRegistry.getCommonClass(a,b));
}
public void testCommonClass() {
common(TypeInfoFactory.intTypeInfo, TypeInfoFactory.decimalTypeInfo,
TypeInfoFactory.decimalTypeInfo);
common(TypeInfoFactory.stringTypeInfo, TypeInfoFactory.decimalTypeInfo,
TypeInfoFactory.stringTypeInfo);
common(TypeInfoFactory.doubleTypeInfo, TypeInfoFactory.decimalTypeInfo,
TypeInfoFactory.doubleTypeInfo);
common(TypeInfoFactory.doubleTypeInfo, TypeInfoFactory.stringTypeInfo,
TypeInfoFactory.stringTypeInfo);
common(TypeInfoFactory.stringTypeInfo, varchar10, TypeInfoFactory.stringTypeInfo);
common(varchar10, TypeInfoFactory.stringTypeInfo, TypeInfoFactory.stringTypeInfo);
common(TypeInfoFactory.stringTypeInfo, char10, TypeInfoFactory.stringTypeInfo);
common(char10, TypeInfoFactory.stringTypeInfo, TypeInfoFactory.stringTypeInfo);
// common class between char/varchar is string?
common(char5, varchar10, TypeInfoFactory.stringTypeInfo);
}
private void comparison(TypeInfo a, TypeInfo b, TypeInfo result) {
assertEquals(result, FunctionRegistry.getCommonClassForComparison(a,b));
}
public void testCommonClassComparison() {
comparison(TypeInfoFactory.intTypeInfo, TypeInfoFactory.decimalTypeInfo,
TypeInfoFactory.decimalTypeInfo);
comparison(TypeInfoFactory.stringTypeInfo, TypeInfoFactory.decimalTypeInfo,
TypeInfoFactory.doubleTypeInfo);
comparison(TypeInfoFactory.doubleTypeInfo, TypeInfoFactory.decimalTypeInfo,
TypeInfoFactory.doubleTypeInfo);
comparison(TypeInfoFactory.doubleTypeInfo, TypeInfoFactory.stringTypeInfo,
TypeInfoFactory.doubleTypeInfo);
comparison(TypeInfoFactory.dateTypeInfo, TypeInfoFactory.stringTypeInfo,
TypeInfoFactory.dateTypeInfo);
comparison(TypeInfoFactory.stringTypeInfo, TypeInfoFactory.dateTypeInfo,
TypeInfoFactory.dateTypeInfo);
comparison(TypeInfoFactory.timestampTypeInfo, TypeInfoFactory.stringTypeInfo,
TypeInfoFactory.timestampTypeInfo);
comparison(TypeInfoFactory.stringTypeInfo, TypeInfoFactory.timestampTypeInfo,
TypeInfoFactory.timestampTypeInfo);
comparison(TypeInfoFactory.intTypeInfo, TypeInfoFactory.timestampTypeInfo,
TypeInfoFactory.doubleTypeInfo);
comparison(TypeInfoFactory.timestampTypeInfo, TypeInfoFactory.intTypeInfo,
TypeInfoFactory.doubleTypeInfo);
comparison(TypeInfoFactory.timestampTypeInfo, TypeInfoFactory.dateTypeInfo,
TypeInfoFactory.timestampTypeInfo);
comparison(TypeInfoFactory.stringTypeInfo, varchar10, TypeInfoFactory.stringTypeInfo);
comparison(varchar10, TypeInfoFactory.stringTypeInfo, TypeInfoFactory.stringTypeInfo);
comparison(varchar5, varchar10, varchar10);
comparison(TypeInfoFactory.stringTypeInfo, char10, TypeInfoFactory.stringTypeInfo);
comparison(char10, TypeInfoFactory.stringTypeInfo, TypeInfoFactory.stringTypeInfo);
comparison(char5, char10, char10);
// common comparison class for char/varchar is string?
comparison(char10, varchar5, TypeInfoFactory.stringTypeInfo);
}
/**
* Method to print out the comparison/conversion behavior for data types.
*/
public void testPrintTypeCompatibility() {
if (true) {
return;
}
String[] typeStrings = {
"void", "boolean", "tinyint", "smallint", "int", "bigint", "float", "double",
"string", "timestamp", "date", "binary", "decimal", "varchar(10)", "varchar(5)",
};
for (String cat1 : typeStrings) {
TypeInfo ti1 = null;
try {
ti1 = TypeInfoUtils.getTypeInfoFromTypeString(cat1);
} catch (Exception err) {
System.out.println(err);
System.out.println("Unable to get TypeInfo for " + cat1 + ", skipping ...");
continue;
}
for (String cat2 : typeStrings) {
TypeInfo commonClass = null;
boolean implicitConvertable = false;
try {
TypeInfo ti2 = TypeInfoUtils.getTypeInfoFromTypeString(cat2);
try {
commonClass = FunctionRegistry.getCommonClassForComparison(ti1, ti2);
//implicitConvertable = FunctionRegistry.implicitConvertable(ti1, ti2);
} catch (Exception err) {
System.out.println("Failed to get common class for " + ti1 + ", " + ti2 + ": " + err);
err.printStackTrace();
//System.out.println("Unable to get TypeInfo for " + cat2 + ", skipping ...");
}
System.out.println(cat1 + " - " + cat2 + ": " + commonClass);
//System.out.println(cat1 + " - " + cat2 + ": " + implicitConvertable);
} catch (Exception err) {
System.out.println(err);
System.out.println("Unable to get TypeInfo for " + cat2 + ", skipping ...");
continue;
}
}
}
}
private void unionAll(TypeInfo a, TypeInfo b, TypeInfo result) {
assertEquals(result, FunctionRegistry.getCommonClassForUnionAll(a,b));
}
public void testCommonClassUnionAll() {
unionAll(TypeInfoFactory.doubleTypeInfo, TypeInfoFactory.intTypeInfo,
TypeInfoFactory.doubleTypeInfo);
unionAll(TypeInfoFactory.intTypeInfo, TypeInfoFactory.decimalTypeInfo,
TypeInfoFactory.decimalTypeInfo);
unionAll(TypeInfoFactory.doubleTypeInfo, TypeInfoFactory.decimalTypeInfo,
TypeInfoFactory.doubleTypeInfo);
unionAll(varchar5, varchar10, varchar10);
unionAll(varchar10, varchar5, varchar10);
unionAll(varchar10, TypeInfoFactory.stringTypeInfo, TypeInfoFactory.stringTypeInfo);
unionAll(TypeInfoFactory.stringTypeInfo, varchar10, TypeInfoFactory.stringTypeInfo);
unionAll(char5, char10, char10);
unionAll(char10, char5, char10);
unionAll(char10, TypeInfoFactory.stringTypeInfo, TypeInfoFactory.stringTypeInfo);
unionAll(TypeInfoFactory.stringTypeInfo, char10, TypeInfoFactory.stringTypeInfo);
unionAll(TypeInfoFactory.timestampTypeInfo, TypeInfoFactory.dateTypeInfo,
TypeInfoFactory.timestampTypeInfo);
// Invalid cases
unionAll(TypeInfoFactory.stringTypeInfo, TypeInfoFactory.decimalTypeInfo, null);
unionAll(TypeInfoFactory.doubleTypeInfo, varchar10, null);
}
public void testGetTypeInfoForPrimitiveCategory() {
// varchar should take string length into account.
// varchar(5), varchar(10) => varchar(10)
assertEquals(varchar10, FunctionRegistry.getTypeInfoForPrimitiveCategory(
(PrimitiveTypeInfo) varchar5, (PrimitiveTypeInfo) varchar10, PrimitiveCategory.VARCHAR));
assertEquals(varchar10, FunctionRegistry.getTypeInfoForPrimitiveCategory(
(PrimitiveTypeInfo) varchar10, (PrimitiveTypeInfo) varchar5, PrimitiveCategory.VARCHAR));
assertEquals(char10, FunctionRegistry.getTypeInfoForPrimitiveCategory(
(PrimitiveTypeInfo) char5, (PrimitiveTypeInfo) char10, PrimitiveCategory.CHAR));
assertEquals(char10, FunctionRegistry.getTypeInfoForPrimitiveCategory(
(PrimitiveTypeInfo) char10, (PrimitiveTypeInfo) char5, PrimitiveCategory.CHAR));
assertEquals(varchar10, FunctionRegistry.getTypeInfoForPrimitiveCategory(
(PrimitiveTypeInfo) varchar5, (PrimitiveTypeInfo) char10, PrimitiveCategory.VARCHAR));
// non-qualified types should simply return the TypeInfo associated with that type
assertEquals(TypeInfoFactory.stringTypeInfo, FunctionRegistry.getTypeInfoForPrimitiveCategory(
(PrimitiveTypeInfo) varchar10, TypeInfoFactory.stringTypeInfo,
PrimitiveCategory.STRING));
assertEquals(TypeInfoFactory.stringTypeInfo, FunctionRegistry.getTypeInfoForPrimitiveCategory(
TypeInfoFactory.stringTypeInfo,
TypeInfoFactory.stringTypeInfo,
PrimitiveCategory.STRING));
assertEquals(TypeInfoFactory.doubleTypeInfo, FunctionRegistry.getTypeInfoForPrimitiveCategory(
TypeInfoFactory.doubleTypeInfo,
TypeInfoFactory.stringTypeInfo,
PrimitiveCategory.DOUBLE));
}
@Override
protected void tearDown() {
}
public void testIsRankingFunction() throws Exception {
Assert.assertTrue(FunctionRegistry.isRankingFunction("rank"));
Assert.assertTrue(FunctionRegistry.isRankingFunction("dense_rank"));
Assert.assertTrue(FunctionRegistry.isRankingFunction("percent_rank"));
Assert.assertTrue(FunctionRegistry.isRankingFunction("cume_dist"));
Assert.assertFalse(FunctionRegistry.isRankingFunction("min"));
}
public void testImpliesOrder() throws Exception {
Assert.assertTrue(FunctionRegistry.impliesOrder("rank"));
Assert.assertTrue(FunctionRegistry.impliesOrder("dense_rank"));
Assert.assertTrue(FunctionRegistry.impliesOrder("percent_rank"));
Assert.assertTrue(FunctionRegistry.impliesOrder("cume_dist"));
Assert.assertTrue(FunctionRegistry.impliesOrder("first_value"));
Assert.assertTrue(FunctionRegistry.impliesOrder("last_value"));
Assert.assertTrue(FunctionRegistry.impliesOrder("lead"));
Assert.assertTrue(FunctionRegistry.impliesOrder("lag"));
Assert.assertFalse(FunctionRegistry.impliesOrder("min"));
}
public void testRegisterTemporaryFunctions() throws Exception {
FunctionResource[] emptyResources = new FunctionResource[] {};
// UDF
FunctionRegistry.registerTemporaryUDF("tmp_ln", UDFLn.class, emptyResources);
FunctionInfo functionInfo = FunctionRegistry.getFunctionInfo("tmp_ln");
assertFalse(functionInfo.isNative());
// GenericUDF
FunctionRegistry.registerTemporaryUDF("tmp_concat", GenericUDFConcat.class, emptyResources);
functionInfo = FunctionRegistry.getFunctionInfo("tmp_concat");
assertFalse(functionInfo.isNative());
// GenericUDAF
FunctionRegistry.registerTemporaryUDF("tmp_max",GenericUDAFMax.class, emptyResources);
functionInfo = FunctionRegistry.getFunctionInfo("tmp_max");
assertFalse(functionInfo.isNative());
functionInfo = FunctionRegistry.getWindowFunctionInfo("tmp_max");
assertFalse(functionInfo.isNative());
// UDTF
FunctionRegistry.registerTemporaryUDF("tmp_explode", GenericUDTFExplode.class, emptyResources);
functionInfo = FunctionRegistry.getFunctionInfo("tmp_explode");
assertFalse(functionInfo.isNative());
}
public void testRegisterPermanentFunction() throws Exception {
FunctionResource[] emptyResources = new FunctionResource[] {};
// UDF
FunctionRegistry.registerPermanentFunction("perm_ln", UDFLn.class.getName(), true, emptyResources);
FunctionInfo functionInfo = FunctionRegistry.getFunctionInfo("perm_ln");
assertTrue(functionInfo.isPersistent());
assertTrue(functionInfo.isNative());
assertFalse(functionInfo.isBuiltIn());
functionInfo = FunctionRegistry.getFunctionInfo("default.perm_ln");
assertTrue(functionInfo.isPersistent());
assertTrue(functionInfo.isNative());
assertFalse(functionInfo.isBuiltIn());
// GenericUDF
FunctionRegistry.registerPermanentFunction("default.perm_concat",
GenericUDFConcat.class.getName(), true, emptyResources);
functionInfo = FunctionRegistry.getFunctionInfo("default.perm_concat");
assertTrue(functionInfo.isPersistent());
assertTrue(functionInfo.isNative());
assertFalse(functionInfo.isBuiltIn());
// GenericUDAF
FunctionRegistry.registerPermanentFunction("default.perm_max",
GenericUDAFMax.class.getName(), true, emptyResources);
functionInfo = FunctionRegistry.getFunctionInfo("default.perm_max");
assertTrue(functionInfo.isPersistent());
functionInfo = FunctionRegistry.getWindowFunctionInfo("default.perm_max");
assertTrue(functionInfo.isPersistent());
assertTrue(functionInfo.isNative());
assertFalse(functionInfo.isBuiltIn());
// UDTF
FunctionRegistry.registerPermanentFunction("default.perm_explode",
GenericUDTFExplode.class.getName(), true, emptyResources);
functionInfo = FunctionRegistry.getFunctionInfo("default.perm_explode");
assertTrue(functionInfo.isPersistent());
assertTrue(functionInfo.isNative());
assertFalse(functionInfo.isBuiltIn());
}
public void testBuiltInFunction() throws Exception {
FunctionInfo functionInfo = FunctionRegistry.getFunctionInfo("ln");
assertTrue(functionInfo.isBuiltIn());
assertTrue(functionInfo.isNative());
}
public void testIsPermanentFunction() throws Exception {
// Setup exprNode
GenericUDF udf = new GenericUDFCurrentTimestamp();
List<ExprNodeDesc> children = new ArrayList<ExprNodeDesc>();
ExprNodeGenericFuncDesc fnExpr =
new ExprNodeGenericFuncDesc(TypeInfoFactory.timestampTypeInfo, udf, children);
assertFalse("Function not added as permanent yet", FunctionRegistry.isPermanentFunction(fnExpr));
// Now register as permanent function
FunctionResource[] emptyResources = new FunctionResource[] {};
FunctionRegistry.registerPermanentFunction("default.perm_current_timestamp",
GenericUDFCurrentTimestamp.class.getName(), true, emptyResources);
assertTrue("Function should now be recognized as permanent function", FunctionRegistry.isPermanentFunction(fnExpr));
}
}