Skip to content

Commit a732ae0

Browse files
authored
HIVE-29443: NPE in FunctionRegistry#getFunctionInfo when session not available (#6301)
1 parent f5ce542 commit a732ae0

File tree

4 files changed

+52
-11
lines changed

4 files changed

+52
-11
lines changed

ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -817,8 +817,7 @@ public static String getNormalizedFunctionName(String fn) throws SemanticExcepti
817817
// Does the same thing as getFunctionInfo, except for getting the function info.
818818
fn = fn.toLowerCase();
819819
return (FunctionUtils.isQualifiedFunctionName(fn) || getFunctionInfo(fn) != null) ? fn
820-
: FunctionUtils.qualifyFunctionName(
821-
fn, SessionState.get().getCurrentDatabase().toLowerCase());
820+
: FunctionUtils.qualifyFunctionName(fn);
822821
}
823822

824823
public static FunctionInfo getFunctionInfo(String functionName) throws SemanticException {

ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionUtils.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import com.google.common.collect.HashMultimap;
2222
import com.google.common.collect.Multimap;
23+
import org.apache.hadoop.hive.metastore.Warehouse;
2324
import org.apache.hadoop.hive.metastore.api.ResourceType;
2425
import org.apache.hadoop.hive.metastore.api.ResourceUri;
2526
import org.apache.hadoop.hive.ql.exec.FunctionInfo.FunctionResource;
@@ -104,6 +105,20 @@ public static boolean isQualifiedFunctionName(String functionName) {
104105
return functionName.indexOf('.') >= 0;
105106
}
106107

108+
/**
109+
* Qualifies the provided function name with the current database if it is not already qualified.
110+
* If a session is not available, the default database name will be used for qualification.
111+
* @return a qualified function name with the current database
112+
*/
113+
public static String qualifyFunctionName(String functionName) {
114+
if (isQualifiedFunctionName(functionName)) {
115+
return functionName;
116+
}
117+
SessionState ss = SessionState.get();
118+
String dbName = ss != null ? ss.getCurrentDatabase().toLowerCase() : Warehouse.DEFAULT_DATABASE_NAME;
119+
return dbName + "." + functionName;
120+
}
121+
107122
public static String qualifyFunctionName(String functionName, String dbName) {
108123
if (isQualifiedFunctionName(functionName)) {
109124
return functionName;

ql/src/java/org/apache/hadoop/hive/ql/exec/Registry.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -312,8 +312,7 @@ public FunctionInfo registerPermanentFunction(String functionName,
312312
FunctionInfo function = new FunctionInfo(functionName, className, resources);
313313
// register to session first for backward compatibility
314314
if (registerToSession) {
315-
String qualifiedName = FunctionUtils.qualifyFunctionName(
316-
functionName, SessionState.get().getCurrentDatabase().toLowerCase());
315+
String qualifiedName = FunctionUtils.qualifyFunctionName(functionName);
317316
FunctionInfo newFunction = registerToSessionRegistry(qualifiedName, function);
318317
if (newFunction != null) {
319318
addFunction(functionName, function);
@@ -367,8 +366,7 @@ public FunctionInfo getFunctionInfo(String functionName) throws SemanticExceptio
367366
throw new SemanticException ("UDF " + functionName + " is not allowed");
368367
}
369368
if (functionInfo == null) {
370-
functionName = FunctionUtils.qualifyFunctionName(
371-
functionName, SessionState.get().getCurrentDatabase().toLowerCase());
369+
functionName = FunctionUtils.qualifyFunctionName(functionName);
372370
functionInfo = getQualifiedFunctionInfo(functionName);
373371
}
374372
addToCurrentFunctions(functionName, functionInfo);
@@ -386,8 +384,7 @@ public WindowFunctionInfo getWindowFunctionInfo(String functionName) throws Sema
386384
FunctionInfo info = getFunctionInfo(WINDOW_FUNC_PREFIX + functionName);
387385
// Try qualifying with current db name for permanent functions and try register function to session
388386
if (info == null && FunctionRegistry.getFunctionInfo(functionName) != null) {
389-
String qualifiedName = FunctionUtils.qualifyFunctionName(
390-
functionName, SessionState.get().getCurrentDatabase().toLowerCase());
387+
String qualifiedName = FunctionUtils.qualifyFunctionName(functionName);
391388
info = getFunctionInfo(WINDOW_FUNC_PREFIX + qualifiedName);
392389
}
393390
if (info instanceof WindowFunctionInfo) {

ql/src/test/org/apache/hadoop/hive/ql/exec/TestFunctionRegistry.java

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727

2828
import org.apache.hadoop.hive.common.type.HiveVarchar;
29-
import org.apache.hadoop.hive.conf.HiveConf;
3029
import org.apache.hadoop.hive.conf.HiveConfForTest;
3130
import org.apache.hadoop.hive.ql.exec.FunctionInfo.FunctionResource;
3231
import org.apache.hadoop.hive.ql.plan.ExprNodeDesc;
@@ -53,6 +52,8 @@
5352
import org.junit.Assert;
5453
import static org.junit.Assert.assertEquals;
5554
import static org.junit.Assert.assertFalse;
55+
import static org.junit.Assert.assertNotNull;
56+
import static org.junit.Assert.assertNull;
5657
import static org.junit.Assert.assertTrue;
5758
import org.junit.Before;
5859
import org.junit.After;
@@ -97,8 +98,6 @@ public void setUp() {
9798
varchar5 = TypeInfoFactory.getPrimitiveTypeInfo("varchar(5)");
9899
char10 = TypeInfoFactory.getPrimitiveTypeInfo("char(10)");
99100
char5 = TypeInfoFactory.getPrimitiveTypeInfo("char(5)");
100-
HiveConf conf = new HiveConfForTest(getClass());
101-
SessionState.start(conf);
102101
}
103102

104103
private void implicit(TypeInfo a, TypeInfo b, boolean convertible) {
@@ -440,6 +439,7 @@ public void testImpliesOrder() throws Exception {
440439

441440
@Test
442441
public void testRegisterTemporaryFunctions() throws Exception {
442+
SessionState state = SessionState.start(new HiveConfForTest(TestFunctionRegistry.class));
443443
FunctionResource[] emptyResources = new FunctionResource[] {};
444444

445445
// UDF
@@ -463,10 +463,12 @@ public void testRegisterTemporaryFunctions() throws Exception {
463463
FunctionRegistry.registerTemporaryUDF("tmp_explode", GenericUDTFExplode.class, emptyResources);
464464
functionInfo = FunctionRegistry.getFunctionInfo("tmp_explode");
465465
assertFalse(functionInfo.isNative());
466+
state.close();
466467
}
467468

468469
@Test
469470
public void testRegisterPermanentFunction() throws Exception {
471+
SessionState state = SessionState.start(new HiveConfForTest(TestFunctionRegistry.class));
470472
FunctionResource[] emptyResources = new FunctionResource[] {};
471473

472474
// UDF
@@ -505,6 +507,7 @@ public void testRegisterPermanentFunction() throws Exception {
505507
assertTrue(functionInfo.isPersistent());
506508
assertTrue(functionInfo.isNative());
507509
assertFalse(functionInfo.isBuiltIn());
510+
state.close();
508511
}
509512

510513
@Test
@@ -516,6 +519,7 @@ public void testBuiltInFunction() throws Exception {
516519

517520
@Test
518521
public void testIsPermanentFunction() throws Exception {
522+
SessionState state = SessionState.start(new HiveConfForTest(TestFunctionRegistry.class));
519523
// Setup exprNode
520524
GenericUDF udf = new GenericUDFCurrentTimestamp();
521525
List<ExprNodeDesc> children = new ArrayList<ExprNodeDesc>();
@@ -530,6 +534,32 @@ public void testIsPermanentFunction() throws Exception {
530534
GenericUDFCurrentTimestamp.class.getName(), true, emptyResources);
531535

532536
assertTrue("Function should now be recognized as permanent function", FunctionRegistry.isPermanentFunction(fnExpr));
537+
state.close();
538+
}
539+
540+
@Test
541+
public void testGetFunctionInfoNoSessionValidName() throws Exception {
542+
assertNotNull(FunctionRegistry.getFunctionInfo("concat"));
543+
}
544+
545+
@Test
546+
public void testGetFunctionInfoNoSessionMissingName() throws Exception {
547+
assertNull(FunctionRegistry.getFunctionInfo("nofn"));
548+
}
549+
550+
@Test
551+
public void testGetWindowFunctionInfoNoSessionValidName() throws Exception {
552+
assertNotNull(FunctionRegistry.getWindowFunctionInfo("max"));
553+
}
554+
555+
@Test
556+
public void testGetWindowFunctionInfoNoSessionMissingName() throws Exception {
557+
assertNull(FunctionRegistry.getWindowFunctionInfo("nofn"));
558+
}
559+
560+
@Test
561+
public void testGetWindowFunctionInfoNoSessionInvalidName() throws Exception {
562+
assertNull(FunctionRegistry.getWindowFunctionInfo("concat"));
533563
}
534564

535565
private GenericUDF getUDF(String udfName) throws Exception {

0 commit comments

Comments
 (0)