diff --git a/.reviewboardrc b/.reviewboardrc index abc33f91a44b76573cbba334c33417307c63956f..6f21b3ad057d0abaa10bc39cfab87b6b0f9e62bc 100644 --- a/.reviewboardrc +++ b/.reviewboardrc @@ -28,6 +28,6 @@ REPOSITORY='hive-git' REVIEWBOARD_URL='https://reviews.apache.org' -TRACKING_BRANCH='origin/master' +TRACKING_BRANCH='gh/master' TARGET_GROUPS='hive' -GUESS_FIELDS='true' +GUESS_FIELDS='yes' diff --git a/conf/ivysettings.xml b/conf/ivysettings.xml index bda842a89bb07710fdcd7180a00833a7388ada8f..ccf12b7b18c7d78017a0b52c34e1c9923a3ec47b 100644 --- a/conf/ivysettings.xml +++ b/conf/ivysettings.xml @@ -1,4 +1,3 @@ - + + + + - + + diff --git a/itests/custom-udfs/pom.xml b/itests/custom-udfs/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..2445f2d7652a6709ff0bc66c382a84af9e4c16fc --- /dev/null +++ b/itests/custom-udfs/pom.xml @@ -0,0 +1,83 @@ + + + + 4.0.0 + + org.apache.hive + hive-it + 2.0.0-SNAPSHOT + ../pom.xml + + + hive-it-custom-udfs + pom + Hive Integration - Custom udfs + Custom udfs used in hive itest can be defined under this module + + + ../.. + + + + + udf-classloader-util + udf-classloader-udf1 + udf-classloader-udf2 + + + + + + org.apache.hive + hive-exec + ${project.version} + true + + + + + + hadoop-1 + + + org.apache.hadoop + hadoop-core + ${hadoop-20S.version} + true + + + + + + hadoop-2 + + + org.apache.hadoop + hadoop-common + ${hadoop-23.version} + true + + + + + + diff --git a/itests/custom-udfs/udf-classloader-udf1/pom.xml b/itests/custom-udfs/udf-classloader-udf1/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..a4e75ad858896ea1b93d7e4db3ebd75791b6789b --- /dev/null +++ b/itests/custom-udfs/udf-classloader-udf1/pom.xml @@ -0,0 +1,43 @@ + + + + 4.0.0 + + org.apache.hive + hive-it-custom-udfs + 2.0.0-SNAPSHOT + ../pom.xml + + + org.apache.hive.hive-it-custom-udfs + udf-classloader-udf1 + jar + Hive Integration - Custom UDFs - udf-classloader-udf1 + + + + org.apache.hive.hive-it-custom-udfs + udf-classloader-util + ${project.version} + + + + + ../../.. + + + diff --git a/itests/custom-udfs/udf-classloader-udf1/src/main/java/hive/it/custom/udfs/UDF1.java b/itests/custom-udfs/udf-classloader-udf1/src/main/java/hive/it/custom/udfs/UDF1.java new file mode 100644 index 0000000000000000000000000000000000000000..681619049ee99b7efd21f2ef13954f5ebf5e350c --- /dev/null +++ b/itests/custom-udfs/udf-classloader-udf1/src/main/java/hive/it/custom/udfs/UDF1.java @@ -0,0 +1,58 @@ +/** + * 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 hive.it.custom.udfs; + +import org.apache.hadoop.hive.ql.exec.UDFArgumentException; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; + + +public class UDF1 extends GenericUDF { + public UDF1() { + Util util = new Util(); + System.out.println( + "constructor: " + getClass().getSimpleName() + " classloader: " + getClass().getClassLoader() + ", " + util + " classloader: " + + util.getClass().getClassLoader()); + } + + @Override + public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { + Util util = new Util(); + System.out.println( + "initialize: " + getClass().getSimpleName() + " classloader: " + getClass().getClassLoader() + ", " + util + " classloader: " + + util.getClass().getClassLoader()); + return PrimitiveObjectInspectorFactory.javaStringObjectInspector; + } + + @Override + public Object evaluate(DeferredObject[] arguments) throws HiveException { + Util util = new Util(); + System.out.println( + "evaluate: " + getClass().getSimpleName() + " classloader: " + getClass().getClassLoader() + ", " + util + " classloader: " + + util.getClass().getClassLoader()); + return getClass().getSimpleName(); + } + + @Override + public String getDisplayString(String[] children) { + return getClass().getName(); + } +} diff --git a/itests/custom-udfs/udf-classloader-udf2/pom.xml b/itests/custom-udfs/udf-classloader-udf2/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..e9f01b4f6ac049da6052e0970ffdaca2c12ad596 --- /dev/null +++ b/itests/custom-udfs/udf-classloader-udf2/pom.xml @@ -0,0 +1,43 @@ + + + + 4.0.0 + + org.apache.hive + hive-it-custom-udfs + 2.0.0-SNAPSHOT + ../pom.xml + + + org.apache.hive.hive-it-custom-udfs + udf-classloader-udf2 + jar + Hive Integration - Custom UDFs - udf-classloader-udf2 + + + + org.apache.hive.hive-it-custom-udfs + udf-classloader-util + ${project.version} + + + + + ../../.. + + + diff --git a/itests/custom-udfs/udf-classloader-udf2/src/main/java/hive/it/custom/udfs/UDF2.java b/itests/custom-udfs/udf-classloader-udf2/src/main/java/hive/it/custom/udfs/UDF2.java new file mode 100644 index 0000000000000000000000000000000000000000..4bb8772d0e09a190ffc78d310ef7d43602055c31 --- /dev/null +++ b/itests/custom-udfs/udf-classloader-udf2/src/main/java/hive/it/custom/udfs/UDF2.java @@ -0,0 +1,60 @@ +/** + * 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 hive.it.custom.udfs; + +import org.apache.hadoop.hive.ql.exec.UDFArgumentException; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; + + +public class UDF2 extends GenericUDF { + public UDF2() { + Util util = new Util(); + System.out.println( + "constructor: " + getClass().getSimpleName() + " classloader: " + getClass().getClassLoader() + ", " + util + + " classloader: " + + util.getClass().getClassLoader()); + } + + @Override + public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { + Util util = new Util(); + System.out.println( + "initialize: " + getClass().getSimpleName() + " classloader: " + getClass().getClassLoader() + ", " + util + + " classloader: " + + util.getClass().getClassLoader()); + return PrimitiveObjectInspectorFactory.javaStringObjectInspector; + } + + @Override + public Object evaluate(DeferredObject[] arguments) throws HiveException { + Util util = new Util(); + System.out.println( + "evaluate: " + getClass().getSimpleName() + " classloader: " + getClass().getClassLoader() + ", " + util + + " classloader: " + + util.getClass().getClassLoader()); + return getClass().getSimpleName(); + } + + @Override + public String getDisplayString(String[] children) { + return getClass().getName(); + } +} diff --git a/itests/custom-udfs/udf-classloader-util/pom.xml b/itests/custom-udfs/udf-classloader-util/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..68d4c5918a5b7b8abc87c6c7a9c44cc2d8545edc --- /dev/null +++ b/itests/custom-udfs/udf-classloader-util/pom.xml @@ -0,0 +1,35 @@ + + + + 4.0.0 + + org.apache.hive + hive-it-custom-udfs + 2.0.0-SNAPSHOT + ../pom.xml + + + org.apache.hive.hive-it-custom-udfs + udf-classloader-util + jar + Hive Integration - Custom UDFs - udf-classloader-util + + + ../../.. + + + diff --git a/itests/custom-udfs/udf-classloader-util/src/main/java/hive/it/custom/udfs/Util.java b/itests/custom-udfs/udf-classloader-util/src/main/java/hive/it/custom/udfs/Util.java new file mode 100644 index 0000000000000000000000000000000000000000..8881ec70ec4fb78c9335bff4403d8fa760c3dddb --- /dev/null +++ b/itests/custom-udfs/udf-classloader-util/src/main/java/hive/it/custom/udfs/Util.java @@ -0,0 +1,25 @@ +/** + * 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 hive.it.custom.udfs; + +public class Util { + @Override + public String toString() { + return getClass().getSimpleName(); + } +} diff --git a/itests/pom.xml b/itests/pom.xml index acce7131948edd5aeab34af6879d781daa12ba30..8a5de04895b1a80fa2ab63a083f23aa4218e05c4 100644 --- a/itests/pom.xml +++ b/itests/pom.xml @@ -33,6 +33,7 @@ custom-serde + custom-udfs hcatalog-unit hive-unit util diff --git a/itests/qtest/pom.xml b/itests/qtest/pom.xml index 74ca88f586b7ff9ddc38e8bc22a9445c85790c87..caaf8deb4424ed83036a9c7b9c3ed0b9dcd4c1f1 100644 --- a/itests/qtest/pom.xml +++ b/itests/qtest/pom.xml @@ -650,7 +650,6 @@ initScript="${initScript}" cleanupScript="q_test_cleanup.sql"/> - diff --git a/ql/src/java/org/apache/hadoop/hive/ql/exec/UDFClassLoader.java b/ql/src/java/org/apache/hadoop/hive/ql/exec/UDFClassLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..c3638035e3da41db2bd0838636e201e461d116d8 --- /dev/null +++ b/ql/src/java/org/apache/hadoop/hive/ql/exec/UDFClassLoader.java @@ -0,0 +1,70 @@ +/** + * 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 com.google.common.base.Preconditions; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import org.apache.hadoop.hive.ql.session.SessionState; + + +/** + * {@link UDFClassLoader} is used to dynamically register + * udf (and related) jars + * + * This was introducted to fix HIVE-11878 + * + * Each session will have its own instance of {@link UDFClassLoader} + * This is to support HiveServer2 where there can be multiple + * active sessions. Addition/removal of jars/resources in one + * session should not affect other sessions. + */ +public class UDFClassLoader extends URLClassLoader { + private boolean isClosed; + + public UDFClassLoader(URL[] urls) { + super(urls); + isClosed = false; + } + + public UDFClassLoader(URL[] urls, ClassLoader parent) { + super(urls, parent); + isClosed = false; + } + + @Override + public void addURL(URL url) { + Preconditions.checkState(!isClosed, getClass().getSimpleName() + " is already closed"); + super.addURL(url); + } + + /** + * See {@link URLClassLoader#close} + */ + public boolean isClosed() { + return isClosed; + } + + @Override + public void close() throws IOException { + isClosed = true; + super.close(); + } +} diff --git a/ql/src/java/org/apache/hadoop/hive/ql/exec/Utilities.java b/ql/src/java/org/apache/hadoop/hive/ql/exec/Utilities.java index bcf85a471c421dd0de62a894fd6c90024dff5691..e55dff07fe984452ff7c849bd98dc89e07db052b 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/exec/Utilities.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/exec/Utilities.java @@ -20,6 +20,8 @@ import static com.google.common.base.Preconditions.checkNotNull; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import java.beans.DefaultPersistenceDelegate; import java.beans.Encoder; import java.beans.ExceptionListener; @@ -2245,6 +2247,19 @@ private static URL urlFromPathString(String onestr) { return result; } + private static boolean useExistingClassLoader(ClassLoader cl) { + if (!(cl instanceof UDFClassLoader)) { + // Cannot use the same classloader if it is not an instance of {@code UDFClassLoader} + return false; + } + final UDFClassLoader udfClassLoader = (UDFClassLoader) cl; + if (udfClassLoader.isClosed()) { + // The classloader may have been closed, Cannot add to the same instance + return false; + } + return true; + } + /** * Add new elements to the classpath. * @@ -2252,24 +2267,28 @@ private static URL urlFromPathString(String onestr) { * Array of classpath elements */ public static ClassLoader addToClassPath(ClassLoader cloader, String[] newPaths) throws Exception { - URLClassLoader loader = (URLClassLoader) cloader; - List curPath = Arrays.asList(loader.getURLs()); - ArrayList newPath = new ArrayList(); - - // get a list with the current classpath components - for (URL onePath : curPath) { - newPath.add(onePath); + final URLClassLoader loader = (URLClassLoader) cloader; + if (useExistingClassLoader(cloader)) { + final UDFClassLoader udfClassLoader = (UDFClassLoader) loader; + for (String path : newPaths) { + udfClassLoader.addURL(urlFromPathString(path)); + } + return udfClassLoader; + } else { + return createUDFClassLoader(loader, newPaths); } - curPath = newPath; + } + public static ClassLoader createUDFClassLoader(URLClassLoader loader, String[] newPaths) { + final Set curPathsSet = Sets.newHashSet(loader.getURLs()); + final List curPaths = Lists.newArrayList(curPathsSet); for (String onestr : newPaths) { - URL oneurl = urlFromPathString(onestr); - if (oneurl != null && !curPath.contains(oneurl)) { - curPath.add(oneurl); + final URL oneurl = urlFromPathString(onestr); + if (oneurl != null && !curPathsSet.contains(oneurl)) { + curPaths.add(oneurl); } } - - return new URLClassLoader(curPath.toArray(new URL[0]), loader); + return new UDFClassLoader(curPaths.toArray(new URL[0]), loader); } /** @@ -2290,13 +2309,13 @@ public static void removeFromClassPath(String[] pathsToRemove) throws Exception } } JavaUtils.closeClassLoader(loader); -//this loader is closed, remove it from cached registry loaders to avoid remove it again. + // This loader is closed, remove it from cached registry loaders to avoid removing it again. Registry reg = SessionState.getRegistry(); if(reg != null) { reg.removeFromUDFLoaders(loader); } - loader = new URLClassLoader(newPath.toArray(new URL[0])); + loader = new UDFClassLoader(newPath.toArray(new URL[0])); curThread.setContextClassLoader(loader); SessionState.get().getConf().setClassLoader(loader); } diff --git a/ql/src/java/org/apache/hadoop/hive/ql/session/SessionState.java b/ql/src/java/org/apache/hadoop/hive/ql/session/SessionState.java index dc8c336c01921c8e4ae251f3627a80ce95a66182..811ba7e9b04ff716058965f2df811ba10eabab3f 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/session/SessionState.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/session/SessionState.java @@ -85,7 +85,6 @@ import org.apache.hadoop.hive.shims.ShimLoader; import org.apache.hadoop.hive.shims.Utils; import org.apache.hadoop.security.UserGroupInformation; -import org.apache.hadoop.util.ReflectionUtils; import org.apache.hadoop.util.Shell; import com.google.common.base.Preconditions; @@ -356,6 +355,10 @@ public SessionState(HiveConf conf, String userName) { conf.setVar(HiveConf.ConfVars.HIVESESSIONID, makeSessionId()); } parentLoader = JavaUtils.getClassLoader(); + // Make sure that each session has its own UDFClassloader. For details see {@link UDFClassLoader} + final ClassLoader currentLoader = Utilities.createUDFClassLoader((URLClassLoader) parentLoader, new String[]{}); + Thread.currentThread().setContextClassLoader(currentLoader); + this.conf.setClassLoader(currentLoader); } public void setCmd(String cmdString) { @@ -1256,7 +1259,7 @@ private static String getURLType(String value) throws URISyntaxException { return scheme; } - List resolveAndDownload(ResourceType t, String value, boolean convertToUnix) throws URISyntaxException, + protected List resolveAndDownload(ResourceType t, String value, boolean convertToUnix) throws URISyntaxException, IOException { URI uri = createURI(value); if (getURLType(value).equals("file")) { diff --git a/ql/src/test/queries/clientpositive/udf_classloader.q b/ql/src/test/queries/clientpositive/udf_classloader.q new file mode 100644 index 0000000000000000000000000000000000000000..82678c21bf1cca29675618486fc06dd4620c7c95 --- /dev/null +++ b/ql/src/test/queries/clientpositive/udf_classloader.q @@ -0,0 +1,16 @@ +ADD JAR ${system:maven.local.repository}/org/apache/hive/hive-it-custom-udfs/udf-classloader-udf1/${system:hive.version}/udf-classloader-udf1-${system:hive.version}.jar; +ADD JAR ${system:maven.local.repository}/org/apache/hive/hive-it-custom-udfs/udf-classloader-util/${system:hive.version}/udf-classloader-util-${system:hive.version}.jar; +ADD JAR ${system:maven.local.repository}/org/apache/hive/hive-it-custom-udfs/udf-classloader-udf2/${system:hive.version}/udf-classloader-udf2-${system:hive.version}.jar; + +CREATE TEMPORARY FUNCTION f1 AS 'hive.it.custom.udfs.UDF1'; +CREATE TEMPORARY FUNCTION f2 AS 'hive.it.custom.udfs.UDF2'; + +-- udf-classloader-udf1.jar contains f1 which relies on udf-classloader-util.jar, +-- similiary udf-classloader-udf2.jar contains f2 which also relies on udf-classloader-util.jar. +SELECT f1(*), f2(*) FROM SRC limit 1; + +DELETE JAR ${system:maven.local.repository}/org/apache/hive/hive-it-custom-udfs/udf-classloader-udf2/${system:hive.version}/udf-classloader-udf2-${system:hive.version}.jar; +SELECT f1(*) FROM SRC limit 1; + +ADD JAR ${system:maven.local.repository}/org/apache/hive/hive-it-custom-udfs/udf-classloader-udf2/${system:hive.version}/udf-classloader-udf2-${system:hive.version}.jar; +SELECT f2(*) FROM SRC limit 1; diff --git a/ql/src/test/queries/clientpositive/udf_classloader_dynamic_dependency_resolution.q b/ql/src/test/queries/clientpositive/udf_classloader_dynamic_dependency_resolution.q new file mode 100644 index 0000000000000000000000000000000000000000..2ceeaa32f3c0b9425d01af2d7325cbde15435caf --- /dev/null +++ b/ql/src/test/queries/clientpositive/udf_classloader_dynamic_dependency_resolution.q @@ -0,0 +1,16 @@ +ADD JAR ivy://org.apache.hive.hive-it-custom-udfs:udf-classloader-udf1:+; +ADD JAR ivy://org.apache.hive.hive-it-custom-udfs:udf-classloader-util:+; +ADD JAR ivy://org.apache.hive.hive-it-custom-udfs:udf-classloader-udf2:+; + +CREATE TEMPORARY FUNCTION f1 AS 'hive.it.custom.udfs.UDF1'; +CREATE TEMPORARY FUNCTION f2 AS 'hive.it.custom.udfs.UDF2'; + +-- udf-classloader-udf1.jar contains f1 which relies on udf-classloader-util.jar, +-- similiary udf-classloader-udf2.jar contains f2 which also relies on udf-classloader-util.jar. +SELECT f1(*), f2(*) FROM SRC limit 1; + +DELETE JAR ivy://org.apache.hive.hive-it-custom-udfs:udf-classloader-udf2:+; +SELECT f1(*) FROM SRC limit 1; + +ADD JAR ivy://org.apache.hive.hive-it-custom-udfs:udf-classloader-udf2:+; +SELECT f2(*) FROM SRC limit 1; diff --git a/ql/src/test/results/clientpositive/udf_classloader.q.out b/ql/src/test/results/clientpositive/udf_classloader.q.out new file mode 100644 index 0000000000000000000000000000000000000000..031d88afd3df28a38d23be89434ebcb697e4465e --- /dev/null +++ b/ql/src/test/results/clientpositive/udf_classloader.q.out @@ -0,0 +1,43 @@ +PREHOOK: query: CREATE TEMPORARY FUNCTION f1 AS 'hive.it.custom.udfs.UDF1' +PREHOOK: type: CREATEFUNCTION +PREHOOK: Output: f1 +POSTHOOK: query: CREATE TEMPORARY FUNCTION f1 AS 'hive.it.custom.udfs.UDF1' +POSTHOOK: type: CREATEFUNCTION +POSTHOOK: Output: f1 +PREHOOK: query: CREATE TEMPORARY FUNCTION f2 AS 'hive.it.custom.udfs.UDF2' +PREHOOK: type: CREATEFUNCTION +PREHOOK: Output: f2 +POSTHOOK: query: CREATE TEMPORARY FUNCTION f2 AS 'hive.it.custom.udfs.UDF2' +POSTHOOK: type: CREATEFUNCTION +POSTHOOK: Output: f2 +PREHOOK: query: -- udf-classloader-udf1.jar contains f1 which relies on udf-classloader-util.jar, +-- similiary udf-classloader-udf2.jar contains f2 which also relies on udf-classloader-util.jar. +SELECT f1(*), f2(*) FROM SRC limit 1 +PREHOOK: type: QUERY +PREHOOK: Input: default@src +#### A masked pattern was here #### +POSTHOOK: query: -- udf-classloader-udf1.jar contains f1 which relies on udf-classloader-util.jar, +-- similiary udf-classloader-udf2.jar contains f2 which also relies on udf-classloader-util.jar. +SELECT f1(*), f2(*) FROM SRC limit 1 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@src +#### A masked pattern was here #### +UDF1 UDF2 +PREHOOK: query: SELECT f1(*) FROM SRC limit 1 +PREHOOK: type: QUERY +PREHOOK: Input: default@src +#### A masked pattern was here #### +POSTHOOK: query: SELECT f1(*) FROM SRC limit 1 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@src +#### A masked pattern was here #### +UDF1 +PREHOOK: query: SELECT f2(*) FROM SRC limit 1 +PREHOOK: type: QUERY +PREHOOK: Input: default@src +#### A masked pattern was here #### +POSTHOOK: query: SELECT f2(*) FROM SRC limit 1 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@src +#### A masked pattern was here #### +UDF2 diff --git a/ql/src/test/results/clientpositive/udf_classloader_dynamic_dependency_resolution.q.out b/ql/src/test/results/clientpositive/udf_classloader_dynamic_dependency_resolution.q.out new file mode 100644 index 0000000000000000000000000000000000000000..031d88afd3df28a38d23be89434ebcb697e4465e --- /dev/null +++ b/ql/src/test/results/clientpositive/udf_classloader_dynamic_dependency_resolution.q.out @@ -0,0 +1,43 @@ +PREHOOK: query: CREATE TEMPORARY FUNCTION f1 AS 'hive.it.custom.udfs.UDF1' +PREHOOK: type: CREATEFUNCTION +PREHOOK: Output: f1 +POSTHOOK: query: CREATE TEMPORARY FUNCTION f1 AS 'hive.it.custom.udfs.UDF1' +POSTHOOK: type: CREATEFUNCTION +POSTHOOK: Output: f1 +PREHOOK: query: CREATE TEMPORARY FUNCTION f2 AS 'hive.it.custom.udfs.UDF2' +PREHOOK: type: CREATEFUNCTION +PREHOOK: Output: f2 +POSTHOOK: query: CREATE TEMPORARY FUNCTION f2 AS 'hive.it.custom.udfs.UDF2' +POSTHOOK: type: CREATEFUNCTION +POSTHOOK: Output: f2 +PREHOOK: query: -- udf-classloader-udf1.jar contains f1 which relies on udf-classloader-util.jar, +-- similiary udf-classloader-udf2.jar contains f2 which also relies on udf-classloader-util.jar. +SELECT f1(*), f2(*) FROM SRC limit 1 +PREHOOK: type: QUERY +PREHOOK: Input: default@src +#### A masked pattern was here #### +POSTHOOK: query: -- udf-classloader-udf1.jar contains f1 which relies on udf-classloader-util.jar, +-- similiary udf-classloader-udf2.jar contains f2 which also relies on udf-classloader-util.jar. +SELECT f1(*), f2(*) FROM SRC limit 1 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@src +#### A masked pattern was here #### +UDF1 UDF2 +PREHOOK: query: SELECT f1(*) FROM SRC limit 1 +PREHOOK: type: QUERY +PREHOOK: Input: default@src +#### A masked pattern was here #### +POSTHOOK: query: SELECT f1(*) FROM SRC limit 1 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@src +#### A masked pattern was here #### +UDF1 +PREHOOK: query: SELECT f2(*) FROM SRC limit 1 +PREHOOK: type: QUERY +PREHOOK: Input: default@src +#### A masked pattern was here #### +POSTHOOK: query: SELECT f2(*) FROM SRC limit 1 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@src +#### A masked pattern was here #### +UDF2