diff --git a/ql/src/java/org/apache/hadoop/hive/ql/exec/DDLTask.java b/ql/src/java/org/apache/hadoop/hive/ql/exec/DDLTask.java index caf98b5..9ab3e98 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/exec/DDLTask.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/exec/DDLTask.java @@ -3731,7 +3731,12 @@ private int createDatabase(Hive db, CreateDatabaseDesc crtDb) private int dropDatabase(Hive db, DropDatabaseDesc dropDb) throws HiveException { try { - db.dropDatabase(dropDb.getDatabaseName(), true, dropDb.getIfExists(), dropDb.isCasdade()); + String dbName = dropDb.getDatabaseName(); + db.dropDatabase(dbName, true, dropDb.getIfExists(), dropDb.isCasdade()); + // Unregister the functions as well + if (dropDb.isCasdade()) { + FunctionRegistry.unregisterPermanentFunctions(dbName); + } } catch (NoSuchObjectException ex) { throw new HiveException(ex, ErrorMsg.DATABASE_NOT_EXISTS, dropDb.getDatabaseName()); 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 de8e98c..2196ca9 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 @@ -1571,6 +1571,15 @@ public static void unregisterPermanentFunction(String functionName) throws HiveE unregisterTemporaryUDF(functionName); } + /** + * Unregisters all the functions under the database dbName + * @param dbName specified database name + * @throws HiveException + */ + public static void unregisterPermanentFunctions(String dbName) throws HiveException { + system.unregisterFunctions(dbName); + } + private FunctionRegistry() { // prevent instantiation } 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 1121819..ea9813c 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 @@ -419,6 +419,18 @@ public synchronized void unregisterFunction(String functionName) throws HiveExce } } + /** + * Unregisters all the functions belonging to the specified database + * @param dbName database name + * @throws HiveException + */ + public synchronized void unregisterFunctions(String dbName) throws HiveException { + Set funcNames = getFunctionNames(dbName.toLowerCase() + "\\..*"); + for (String funcName : funcNames) { + unregisterFunction(funcName); + } + } + public GenericUDAFResolver getGenericUDAFResolver(String functionName) throws SemanticException { FunctionInfo info = getFunctionInfo(functionName); if (info != null) { diff --git a/ql/src/test/queries/clientnegative/drop_database_cascade.q b/ql/src/test/queries/clientnegative/drop_database_cascade.q new file mode 100644 index 0000000..d544692 --- /dev/null +++ b/ql/src/test/queries/clientnegative/drop_database_cascade.q @@ -0,0 +1,26 @@ +-- This test verifies that if the functions and tables unregistered when the database is dropped +-- and other databases are not affected + +CREATE DATABASE TEST_database; + +USE TEST_database; + +CREATE TABLE test_table (key STRING, value STRING); + +CREATE FUNCTION test_func as 'org.apache.hadoop.hive.ql.udf.UDFAscii'; + +USE default; + +CREATE TABLE test_table (key STRING, value STRING); + +CREATE FUNCTION test_func as 'org.apache.hadoop.hive.ql.udf.UDFAscii'; + +DROP DATABASE TEST_database CASCADE; + +describe test_table; + +describe function test_func; + +describe function TEST_database.test_func; + +describe TEST_database.test_table; diff --git a/ql/src/test/results/clientnegative/drop_database_cascade.q.out b/ql/src/test/results/clientnegative/drop_database_cascade.q.out new file mode 100644 index 0000000..304b967 --- /dev/null +++ b/ql/src/test/results/clientnegative/drop_database_cascade.q.out @@ -0,0 +1,85 @@ +PREHOOK: query: -- This test verifies that if the functions and tables unregistered when the database is dropped +-- and other databases are not affected + +CREATE DATABASE TEST_database +PREHOOK: type: CREATEDATABASE +PREHOOK: Output: database:TEST_database +POSTHOOK: query: -- This test verifies that if the functions and tables unregistered when the database is dropped +-- and other databases are not affected + +CREATE DATABASE TEST_database +POSTHOOK: type: CREATEDATABASE +POSTHOOK: Output: database:TEST_database +PREHOOK: query: USE TEST_database +PREHOOK: type: SWITCHDATABASE +PREHOOK: Input: database:test_database +POSTHOOK: query: USE TEST_database +POSTHOOK: type: SWITCHDATABASE +POSTHOOK: Input: database:test_database +PREHOOK: query: CREATE TABLE test_table (key STRING, value STRING) +PREHOOK: type: CREATETABLE +PREHOOK: Output: TEST_database@test_table +PREHOOK: Output: database:test_database +POSTHOOK: query: CREATE TABLE test_table (key STRING, value STRING) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: TEST_database@test_table +POSTHOOK: Output: database:test_database +PREHOOK: query: CREATE FUNCTION test_func as 'org.apache.hadoop.hive.ql.udf.UDFAscii' +PREHOOK: type: CREATEFUNCTION +PREHOOK: Output: database:test_database +PREHOOK: Output: test_database.test_func +POSTHOOK: query: CREATE FUNCTION test_func as 'org.apache.hadoop.hive.ql.udf.UDFAscii' +POSTHOOK: type: CREATEFUNCTION +POSTHOOK: Output: database:test_database +POSTHOOK: Output: test_database.test_func +PREHOOK: query: USE default +PREHOOK: type: SWITCHDATABASE +PREHOOK: Input: database:default +POSTHOOK: query: USE default +POSTHOOK: type: SWITCHDATABASE +POSTHOOK: Input: database:default +PREHOOK: query: CREATE TABLE test_table (key STRING, value STRING) +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@test_table +POSTHOOK: query: CREATE TABLE test_table (key STRING, value STRING) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@test_table +PREHOOK: query: CREATE FUNCTION test_func as 'org.apache.hadoop.hive.ql.udf.UDFAscii' +PREHOOK: type: CREATEFUNCTION +PREHOOK: Output: database:default +PREHOOK: Output: default.test_func +POSTHOOK: query: CREATE FUNCTION test_func as 'org.apache.hadoop.hive.ql.udf.UDFAscii' +POSTHOOK: type: CREATEFUNCTION +POSTHOOK: Output: database:default +POSTHOOK: Output: default.test_func +PREHOOK: query: DROP DATABASE TEST_database CASCADE +PREHOOK: type: DROPDATABASE +PREHOOK: Input: database:test_database +PREHOOK: Output: database:test_database +PREHOOK: Output: test_database@test_table +POSTHOOK: query: DROP DATABASE TEST_database CASCADE +POSTHOOK: type: DROPDATABASE +POSTHOOK: Input: database:test_database +POSTHOOK: Output: database:test_database +POSTHOOK: Output: test_database@test_table +PREHOOK: query: describe test_table +PREHOOK: type: DESCTABLE +PREHOOK: Input: default@test_table +POSTHOOK: query: describe test_table +POSTHOOK: type: DESCTABLE +POSTHOOK: Input: default@test_table +key string +value string +PREHOOK: query: describe function test_func +PREHOOK: type: DESCFUNCTION +POSTHOOK: query: describe function test_func +POSTHOOK: type: DESCFUNCTION +test_func(str) - returns the numeric value of the first character of str +PREHOOK: query: describe function TEST_database.test_func +PREHOOK: type: DESCFUNCTION +POSTHOOK: query: describe function TEST_database.test_func +POSTHOOK: type: DESCFUNCTION +Function 'TEST_database.test_func' does not exist. +FAILED: SemanticException [Error 10001]: Table not found TEST_database.test_table