This is an automated email from the ASF dual-hosted git repository.
zabetak pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git
The following commit(s) were added to refs/heads/master by this push:
new a732ae0f071 HIVE-29443: NPE in FunctionRegistry#getFunctionInfo when
session not available (#6301)
a732ae0f071 is described below
commit a732ae0f071b0e9a3e9e030db8fc0acb441c6f68
Author: Stamatis Zampetakis <[email protected]>
AuthorDate: Mon Feb 9 09:39:28 2026 +0100
HIVE-29443: NPE in FunctionRegistry#getFunctionInfo when session not
available (#6301)
---
.../hadoop/hive/ql/exec/FunctionRegistry.java | 3 +-
.../apache/hadoop/hive/ql/exec/FunctionUtils.java | 15 +++++++++
.../org/apache/hadoop/hive/ql/exec/Registry.java | 9 ++----
.../hadoop/hive/ql/exec/TestFunctionRegistry.java | 36 ++++++++++++++++++++--
4 files changed, 52 insertions(+), 11 deletions(-)
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java
b/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java
index eda1360293f..46ee2ad7bc7 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java
@@ -817,8 +817,7 @@ public static String getNormalizedFunctionName(String fn)
throws SemanticExcepti
// Does the same thing as getFunctionInfo, except for getting the function
info.
fn = fn.toLowerCase();
return (FunctionUtils.isQualifiedFunctionName(fn) || getFunctionInfo(fn)
!= null) ? fn
- : FunctionUtils.qualifyFunctionName(
- fn, SessionState.get().getCurrentDatabase().toLowerCase());
+ : FunctionUtils.qualifyFunctionName(fn);
}
public static FunctionInfo getFunctionInfo(String functionName) throws
SemanticException {
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionUtils.java
b/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionUtils.java
index 9a916397c9c..78adb6c2937 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionUtils.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionUtils.java
@@ -20,6 +20,7 @@
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
+import org.apache.hadoop.hive.metastore.Warehouse;
import org.apache.hadoop.hive.metastore.api.ResourceType;
import org.apache.hadoop.hive.metastore.api.ResourceUri;
import org.apache.hadoop.hive.ql.exec.FunctionInfo.FunctionResource;
@@ -104,6 +105,20 @@ public static boolean isQualifiedFunctionName(String
functionName) {
return functionName.indexOf('.') >= 0;
}
+ /**
+ * Qualifies the provided function name with the current database if it is
not already qualified.
+ * If a session is not available, the default database name will be used for
qualification.
+ * @return a qualified function name with the current database
+ */
+ public static String qualifyFunctionName(String functionName) {
+ if (isQualifiedFunctionName(functionName)) {
+ return functionName;
+ }
+ SessionState ss = SessionState.get();
+ String dbName = ss != null ? ss.getCurrentDatabase().toLowerCase() :
Warehouse.DEFAULT_DATABASE_NAME;
+ return dbName + "." + functionName;
+ }
+
public static String qualifyFunctionName(String functionName, String dbName)
{
if (isQualifiedFunctionName(functionName)) {
return functionName;
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/exec/Registry.java
b/ql/src/java/org/apache/hadoop/hive/ql/exec/Registry.java
index 8c8d90f2537..6fb92776862 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/exec/Registry.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/exec/Registry.java
@@ -312,8 +312,7 @@ public FunctionInfo registerPermanentFunction(String
functionName,
FunctionInfo function = new FunctionInfo(functionName, className,
resources);
// register to session first for backward compatibility
if (registerToSession) {
- String qualifiedName = FunctionUtils.qualifyFunctionName(
- functionName, SessionState.get().getCurrentDatabase().toLowerCase());
+ String qualifiedName = FunctionUtils.qualifyFunctionName(functionName);
FunctionInfo newFunction = registerToSessionRegistry(qualifiedName,
function);
if (newFunction != null) {
addFunction(functionName, function);
@@ -367,8 +366,7 @@ public FunctionInfo getFunctionInfo(String functionName)
throws SemanticExceptio
throw new SemanticException ("UDF " + functionName + " is not
allowed");
}
if (functionInfo == null) {
- functionName = FunctionUtils.qualifyFunctionName(
- functionName,
SessionState.get().getCurrentDatabase().toLowerCase());
+ functionName = FunctionUtils.qualifyFunctionName(functionName);
functionInfo = getQualifiedFunctionInfo(functionName);
}
addToCurrentFunctions(functionName, functionInfo);
@@ -386,8 +384,7 @@ public WindowFunctionInfo getWindowFunctionInfo(String
functionName) throws Sema
FunctionInfo info = getFunctionInfo(WINDOW_FUNC_PREFIX + functionName);
// Try qualifying with current db name for permanent functions and try
register function to session
if (info == null && FunctionRegistry.getFunctionInfo(functionName) !=
null) {
- String qualifiedName = FunctionUtils.qualifyFunctionName(
- functionName,
SessionState.get().getCurrentDatabase().toLowerCase());
+ String qualifiedName = FunctionUtils.qualifyFunctionName(functionName);
info = getFunctionInfo(WINDOW_FUNC_PREFIX + qualifiedName);
}
if (info instanceof WindowFunctionInfo) {
diff --git
a/ql/src/test/org/apache/hadoop/hive/ql/exec/TestFunctionRegistry.java
b/ql/src/test/org/apache/hadoop/hive/ql/exec/TestFunctionRegistry.java
index 15bf768895a..e183449b904 100644
--- a/ql/src/test/org/apache/hadoop/hive/ql/exec/TestFunctionRegistry.java
+++ b/ql/src/test/org/apache/hadoop/hive/ql/exec/TestFunctionRegistry.java
@@ -26,7 +26,6 @@
import org.apache.hadoop.hive.common.type.HiveVarchar;
-import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.hive.conf.HiveConfForTest;
import org.apache.hadoop.hive.ql.exec.FunctionInfo.FunctionResource;
import org.apache.hadoop.hive.ql.plan.ExprNodeDesc;
@@ -53,6 +52,8 @@
import org.junit.Assert;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.After;
@@ -97,8 +98,6 @@ public void setUp() {
varchar5 = TypeInfoFactory.getPrimitiveTypeInfo("varchar(5)");
char10 = TypeInfoFactory.getPrimitiveTypeInfo("char(10)");
char5 = TypeInfoFactory.getPrimitiveTypeInfo("char(5)");
- HiveConf conf = new HiveConfForTest(getClass());
- SessionState.start(conf);
}
private void implicit(TypeInfo a, TypeInfo b, boolean convertible) {
@@ -440,6 +439,7 @@ public void testImpliesOrder() throws Exception {
@Test
public void testRegisterTemporaryFunctions() throws Exception {
+ SessionState state = SessionState.start(new
HiveConfForTest(TestFunctionRegistry.class));
FunctionResource[] emptyResources = new FunctionResource[] {};
// UDF
@@ -463,10 +463,12 @@ public void testRegisterTemporaryFunctions() throws
Exception {
FunctionRegistry.registerTemporaryUDF("tmp_explode",
GenericUDTFExplode.class, emptyResources);
functionInfo = FunctionRegistry.getFunctionInfo("tmp_explode");
assertFalse(functionInfo.isNative());
+ state.close();
}
@Test
public void testRegisterPermanentFunction() throws Exception {
+ SessionState state = SessionState.start(new
HiveConfForTest(TestFunctionRegistry.class));
FunctionResource[] emptyResources = new FunctionResource[] {};
// UDF
@@ -505,6 +507,7 @@ public void testRegisterPermanentFunction() throws
Exception {
assertTrue(functionInfo.isPersistent());
assertTrue(functionInfo.isNative());
assertFalse(functionInfo.isBuiltIn());
+ state.close();
}
@Test
@@ -516,6 +519,7 @@ public void testBuiltInFunction() throws Exception {
@Test
public void testIsPermanentFunction() throws Exception {
+ SessionState state = SessionState.start(new
HiveConfForTest(TestFunctionRegistry.class));
// Setup exprNode
GenericUDF udf = new GenericUDFCurrentTimestamp();
List<ExprNodeDesc> children = new ArrayList<ExprNodeDesc>();
@@ -530,6 +534,32 @@ public void testIsPermanentFunction() throws Exception {
GenericUDFCurrentTimestamp.class.getName(), true, emptyResources);
assertTrue("Function should now be recognized as permanent function",
FunctionRegistry.isPermanentFunction(fnExpr));
+ state.close();
+ }
+
+ @Test
+ public void testGetFunctionInfoNoSessionValidName() throws Exception {
+ assertNotNull(FunctionRegistry.getFunctionInfo("concat"));
+ }
+
+ @Test
+ public void testGetFunctionInfoNoSessionMissingName() throws Exception {
+ assertNull(FunctionRegistry.getFunctionInfo("nofn"));
+ }
+
+ @Test
+ public void testGetWindowFunctionInfoNoSessionValidName() throws Exception {
+ assertNotNull(FunctionRegistry.getWindowFunctionInfo("max"));
+ }
+
+ @Test
+ public void testGetWindowFunctionInfoNoSessionMissingName() throws Exception
{
+ assertNull(FunctionRegistry.getWindowFunctionInfo("nofn"));
+ }
+
+ @Test
+ public void testGetWindowFunctionInfoNoSessionInvalidName() throws Exception
{
+ assertNull(FunctionRegistry.getWindowFunctionInfo("concat"));
}
private GenericUDF getUDF(String udfName) throws Exception {