Repository: hive Updated Branches: refs/heads/master 78a90a62d -> f7c51b6ce
HIVE-14340: Add a new hook triggers before query compilation and after query execution (Chao Sun, reviewed by Xuefu Zhang) Project: http://git-wip-us.apache.org/repos/asf/hive/repo Commit: http://git-wip-us.apache.org/repos/asf/hive/commit/f7c51b6c Tree: http://git-wip-us.apache.org/repos/asf/hive/tree/f7c51b6c Diff: http://git-wip-us.apache.org/repos/asf/hive/diff/f7c51b6c Branch: refs/heads/master Commit: f7c51b6cee5dddf47d58781f1c6087e0ac237cd3 Parents: 78a90a6 Author: Chao Sun <sunc...@apache.org> Authored: Tue Aug 2 09:20:40 2016 -0700 Committer: Chao Sun <sunc...@apache.org> Committed: Tue Aug 2 09:20:40 2016 -0700 ---------------------------------------------------------------------- .../org/apache/hadoop/hive/conf/HiveConf.java | 4 +- .../java/org/apache/hadoop/hive/ql/Driver.java | 67 +++++++++- .../hadoop/hive/ql/hooks/QueryLifeTimeHook.java | 57 +++++++++ .../hive/ql/hooks/QueryLifeTimeHookContext.java | 69 ++++++++++ .../ql/hooks/QueryLifeTimeHookContextImpl.java | 57 +++++++++ .../hadoop/hive/ql/hooks/TestQueryHooks.java | 127 +++++++++++++++++++ .../hive/ql/hooks/TestQueryLifeTimeHook.java | 43 +++++++ .../clientpositive/query_lifetime_hook.q | 3 + .../clientpositive/query_lifetime_hook.q.out | 21 +++ 9 files changed, 446 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hive/blob/f7c51b6c/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java ---------------------------------------------------------------------- diff --git a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java index 598684e..1b64c77 100644 --- a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java +++ b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java @@ -2113,7 +2113,9 @@ public class HiveConf extends Configuration { "hive.exec.temporary.table.storage", "default", new StringSet("memory", "ssd", "default"), "Define the storage policy for temporary tables." + "Choices between memory, ssd and default"), - + HIVE_QUERY_LIFETIME_HOOKS("hive.query.lifetime.hooks", "", + "A comma separated list of hooks which implement QueryLifeTimeHook. These will be triggered" + + " before/after query compilation and before/after query execution, in the order specified"), HIVE_DRIVER_RUN_HOOKS("hive.exec.driver.run.hooks", "", "A comma separated list of hooks which implement HiveDriverRunHook. Will be run at the beginning " + "and end of Driver.run, these will be run in the order specified."), http://git-wip-us.apache.org/repos/asf/hive/blob/f7c51b6c/ql/src/java/org/apache/hadoop/hive/ql/Driver.java ---------------------------------------------------------------------- diff --git a/ql/src/java/org/apache/hadoop/hive/ql/Driver.java b/ql/src/java/org/apache/hadoop/hive/ql/Driver.java index 0278673..e1494da 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/Driver.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/Driver.java @@ -63,6 +63,9 @@ import org.apache.hadoop.hive.ql.hooks.HookContext; import org.apache.hadoop.hive.ql.hooks.HookUtils; import org.apache.hadoop.hive.ql.hooks.PostExecute; import org.apache.hadoop.hive.ql.hooks.PreExecute; +import org.apache.hadoop.hive.ql.hooks.QueryLifeTimeHook; +import org.apache.hadoop.hive.ql.hooks.QueryLifeTimeHookContext; +import org.apache.hadoop.hive.ql.hooks.QueryLifeTimeHookContextImpl; import org.apache.hadoop.hive.ql.hooks.ReadEntity; import org.apache.hadoop.hive.ql.hooks.WriteEntity; import org.apache.hadoop.hive.ql.lockmgr.HiveLock; @@ -169,6 +172,9 @@ public class Driver implements CommandProcessor { // Query specific info private QueryState queryState; + // Query hooks that execute before compilation and after execution + List<QueryLifeTimeHook> queryHooks; + private boolean checkConcurrency() { boolean supportConcurrency = conf.getBoolVar(HiveConf.ConfVars.HIVE_SUPPORT_CONCURRENCY); if (!supportConcurrency) { @@ -372,6 +378,9 @@ public class Driver implements CommandProcessor { SessionState.get().setupQueryCurrentTimestamp(); + // Whether any error occurred during query compilation. Used for query lifetime hook. + boolean compileError = false; + try { // Initialize the transaction manager. This must be done before analyze is called. final HiveTxnManager txnManager = SessionState.get().initTxnMgr(conf); @@ -403,6 +412,17 @@ public class Driver implements CommandProcessor { tree = ParseUtils.findRootNonNullToken(tree); perfLogger.PerfLogEnd(CLASS_NAME, PerfLogger.PARSE); + // Trigger query hook before compilation + queryHooks = getHooks(ConfVars.HIVE_QUERY_LIFETIME_HOOKS, QueryLifeTimeHook.class); + if (queryHooks != null && !queryHooks.isEmpty()) { + QueryLifeTimeHookContext qhc = new QueryLifeTimeHookContextImpl(); + qhc.setHiveConf(conf); + qhc.setCommand(command); + + for (QueryLifeTimeHook hook : queryHooks) { + hook.beforeCompile(qhc); + } + } perfLogger.PerfLogBegin(CLASS_NAME, PerfLogger.ANALYZE); BaseSemanticAnalyzer sem = SemanticAnalyzerFactory.get(queryState, tree); @@ -491,8 +511,11 @@ public class Driver implements CommandProcessor { } } } + return 0; } catch (Exception e) { + compileError = true; + ErrorMsg error = ErrorMsg.getErrorMsg(e.getMessage()); errorMessage = "FAILED: " + e.getClass().getSimpleName(); if (error != ErrorMsg.GENERIC_ERROR) { @@ -517,6 +540,19 @@ public class Driver implements CommandProcessor { return error.getErrorCode();//todo: this is bad if returned as cmd shell exit // since it exceeds valid range of shell return values } finally { + + // Trigger post compilation hook. Note that if the compilation fails here then + // before/after execution hook will never be executed. + if (queryHooks != null && !queryHooks.isEmpty()) { + QueryLifeTimeHookContext qhc = new QueryLifeTimeHookContextImpl(); + qhc.setHiveConf(conf); + qhc.setCommand(command); + + for (QueryLifeTimeHook hook : queryHooks) { + hook.afterCompile(qhc, compileError); + } + } + double duration = perfLogger.PerfLogEnd(CLASS_NAME, PerfLogger.COMPILE)/1000.00; ImmutableMap<String, Long> compileHMSTimings = dumpMetaCallTimingWithoutEx("compilation"); queryDisplay.setHmsTimings(QueryDisplay.Phase.COMPILATION, compileHMSTimings); @@ -1513,6 +1549,9 @@ public class Driver implements CommandProcessor { HookContext hookContext = null; + // Whether there's any error occurred during query execution. Used for query lifetime hook. + boolean executionError = false; + try { LOG.info("Executing command(queryId=" + queryId + "): " + queryStr); // compile and execute can get called from different threads in case of HS2 @@ -1549,6 +1588,19 @@ public class Driver implements CommandProcessor { perfLogger.PerfLogEnd(CLASS_NAME, PerfLogger.PRE_HOOK + peh.getClass().getName()); } } + + // Trigger query hooks before query execution. + if (queryHooks != null && !queryHooks.isEmpty()) { + QueryLifeTimeHookContext qhc = new QueryLifeTimeHookContextImpl(); + qhc.setHiveConf(conf); + qhc.setCommand(ctx.getCmd()); + qhc.setHookContext(hookContext); + + for (QueryLifeTimeHook hook : queryHooks) { + hook.beforeExecution(qhc); + } + } + setQueryDisplays(plan.getRootTasks()); int mrJobs = Utilities.getMRTasks(plan.getRootTasks()).size(); int jobs = mrJobs @@ -1715,15 +1767,16 @@ public class Driver implements CommandProcessor { } } - if (SessionState.get() != null) { SessionState.get().getHiveHistory().setQueryProperty(queryId, Keys.QUERY_RET_CODE, String.valueOf(0)); SessionState.get().getHiveHistory().printRowCount(queryId); } } catch (CommandNeedRetryException e) { + executionError = true; throw e; } catch (Exception e) { + executionError = true; ctx.restoreOriginalTracker(); if (SessionState.get() != null) { SessionState.get().getHiveHistory().setQueryProperty(queryId, Keys.QUERY_RET_CODE, @@ -1744,6 +1797,18 @@ public class Driver implements CommandProcessor { + org.apache.hadoop.util.StringUtils.stringifyException(e)); return (12); } finally { + // Trigger query hooks after query completes its execution. + if (queryHooks != null && !queryHooks.isEmpty()) { + QueryLifeTimeHookContext qhc = new QueryLifeTimeHookContextImpl(); + qhc.setHiveConf(conf); + qhc.setCommand(ctx.getCmd()); + qhc.setHookContext(hookContext); + + for (QueryLifeTimeHook hook : queryHooks) { + hook.afterExecution(qhc, executionError); + } + } + if (SessionState.get() != null) { SessionState.get().getHiveHistory().endQuery(queryId); } http://git-wip-us.apache.org/repos/asf/hive/blob/f7c51b6c/ql/src/java/org/apache/hadoop/hive/ql/hooks/QueryLifeTimeHook.java ---------------------------------------------------------------------- diff --git a/ql/src/java/org/apache/hadoop/hive/ql/hooks/QueryLifeTimeHook.java b/ql/src/java/org/apache/hadoop/hive/ql/hooks/QueryLifeTimeHook.java new file mode 100644 index 0000000..be57452 --- /dev/null +++ b/ql/src/java/org/apache/hadoop/hive/ql/hooks/QueryLifeTimeHook.java @@ -0,0 +1,57 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.hooks; + +/** + * A type of hook which triggers before query compilation and after query execution. + */ +public interface QueryLifeTimeHook extends Hook { + + /** + * Invoked before a query enters the compilation phase. + * + * @param ctx the context for the hook + */ + void beforeCompile(QueryLifeTimeHookContext ctx); + + /** + * Invoked after a query compilation. Note: if 'hasError' is true, + * the query won't enter the following execution phase. + * + * @param ctx the context for the hook + * @param hasError whether any error occurred during compilation. + */ + void afterCompile(QueryLifeTimeHookContext ctx, boolean hasError); + + /** + * Invoked before a query enters the execution phase. + * + * @param ctx the context for the hook + */ + void beforeExecution(QueryLifeTimeHookContext ctx); + + /** + * Invoked after a query finishes its execution. + * + * @param ctx the context for the hook + * @param hasError whether any error occurred during query execution. + */ + void afterExecution(QueryLifeTimeHookContext ctx, boolean hasError); + +} http://git-wip-us.apache.org/repos/asf/hive/blob/f7c51b6c/ql/src/java/org/apache/hadoop/hive/ql/hooks/QueryLifeTimeHookContext.java ---------------------------------------------------------------------- diff --git a/ql/src/java/org/apache/hadoop/hive/ql/hooks/QueryLifeTimeHookContext.java b/ql/src/java/org/apache/hadoop/hive/ql/hooks/QueryLifeTimeHookContext.java new file mode 100644 index 0000000..c599173 --- /dev/null +++ b/ql/src/java/org/apache/hadoop/hive/ql/hooks/QueryLifeTimeHookContext.java @@ -0,0 +1,69 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.hooks; + +import org.apache.hadoop.hive.conf.HiveConf; + +/** + * Hook context for {@link QueryLifeTimeHook}. + */ +public interface QueryLifeTimeHookContext { + /** + * Get the current Hive configuration + * + * @return the Hive configuration being used + */ + HiveConf getHiveConf(); + + /** + * Set Hive configuration + */ + void setHiveConf(HiveConf conf); + + /** + * Get the current command. + * + * @return the current query command + */ + String getCommand(); + + /** + * Set the current command + * + * @param command the query command to set + */ + void setCommand(String command); + + + /** + * Get the hook context for query execution. + * Note: this result value is null during query compilation phase. + * + * @return a {@link HookContext} instance containing information such as query + * plan, list of tasks, etc. + */ + HookContext getHookContext(); + + /** + * Set the hook context + * + * @param hc a {@link HookContext} containing information for the current query. + */ + void setHookContext(HookContext hc); +} http://git-wip-us.apache.org/repos/asf/hive/blob/f7c51b6c/ql/src/java/org/apache/hadoop/hive/ql/hooks/QueryLifeTimeHookContextImpl.java ---------------------------------------------------------------------- diff --git a/ql/src/java/org/apache/hadoop/hive/ql/hooks/QueryLifeTimeHookContextImpl.java b/ql/src/java/org/apache/hadoop/hive/ql/hooks/QueryLifeTimeHookContextImpl.java new file mode 100644 index 0000000..5340848 --- /dev/null +++ b/ql/src/java/org/apache/hadoop/hive/ql/hooks/QueryLifeTimeHookContextImpl.java @@ -0,0 +1,57 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.hooks; + +import org.apache.hadoop.hive.conf.HiveConf; + +public class QueryLifeTimeHookContextImpl implements QueryLifeTimeHookContext { + private HiveConf conf; + private String command; + private HookContext hc = null; + + @Override + public HiveConf getHiveConf() { + return conf; + } + + @Override + public void setHiveConf(HiveConf conf) { + this.conf = conf; + } + + @Override + public String getCommand() { + return command; + } + + @Override + public void setCommand(String command) { + this.command = command; + } + + @Override + public HookContext getHookContext() { + return hc; + } + + @Override + public void setHookContext(HookContext hc) { + this.hc = hc; + } +} http://git-wip-us.apache.org/repos/asf/hive/blob/f7c51b6c/ql/src/test/org/apache/hadoop/hive/ql/hooks/TestQueryHooks.java ---------------------------------------------------------------------- diff --git a/ql/src/test/org/apache/hadoop/hive/ql/hooks/TestQueryHooks.java b/ql/src/test/org/apache/hadoop/hive/ql/hooks/TestQueryHooks.java new file mode 100644 index 0000000..aa5d429 --- /dev/null +++ b/ql/src/test/org/apache/hadoop/hive/ql/hooks/TestQueryHooks.java @@ -0,0 +1,127 @@ +/** + * 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.hooks; + +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hadoop.hive.ql.Driver; +import org.apache.hadoop.hive.ql.session.SessionState; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +public class TestQueryHooks { + private static HiveConf conf; + private static QueryLifeTimeHookContext[] ctxs; + + @BeforeClass + public static void setUpBeforeClass() { + conf = new HiveConf(TestQueryHooks.class); + conf.setVar(HiveConf.ConfVars.HIVE_QUERY_LIFETIME_HOOKS, TestLifeTimeHook.class.getName()); + conf.setBoolVar(HiveConf.ConfVars.HIVE_SUPPORT_CONCURRENCY, false); + conf.setVar(HiveConf.ConfVars.HIVE_AUTHORIZATION_MANAGER, + "org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactory"); + } + + @Before + public void setUpBefore() { + ctxs = new QueryLifeTimeHookContext[4]; + } + + @Test + public void testCompile() throws Exception { + Driver driver = createDriver(); + int ret = driver.compile("SELECT 1"); + assertEquals("Expected compilation to succeed", 0, ret); + assertNotNull(ctxs[0]); + assertNotNull(ctxs[1]); + assertNull(ctxs[2]); + assertNull(ctxs[3]); + assertEquals("SELECT 1", ctxs[0].getCommand()); + assertEquals("SELECT 1", ctxs[1].getCommand()); + } + + @Test + public void testCompileFailure() { + Driver driver = createDriver(); + int ret = driver.compile("SELECT * FROM foo"); + assertNotEquals("Expected compilation to fail", 0, ret); + assertNotNull(ctxs[0]); + assertNotNull(ctxs[1]); + assertNull(ctxs[2]); + assertNull(ctxs[3]); + assertEquals("SELECT * FROM foo", ctxs[0].getCommand()); + assertEquals("SELECT * FROM foo", ctxs[1].getCommand()); + } + + @Test + public void testAll() throws Exception { + Driver driver = createDriver(); + int ret = driver.run("SELECT 1").getResponseCode(); + assertEquals("Expected query to run", 0, ret); + assertNotNull(ctxs[0]); + assertNotNull(ctxs[1]); + assertNotNull(ctxs[2]); + assertNotNull(ctxs[3]); + for (int i = 0; i < ctxs.length; i++) { + assertEquals("SELECT 1", ctxs[i].getCommand()); + } + assertNotNull(ctxs[2].getHookContext()); + assertNotNull(ctxs[3].getHookContext()); + } + + private static Driver createDriver() { + SessionState.start(conf); + Driver driver = new Driver(conf); + driver.init(); + return driver; + } + + /** + * Testing hook which just saves the context + */ + private static class TestLifeTimeHook implements QueryLifeTimeHook { + public TestLifeTimeHook() { + } + + @Override + public void beforeCompile(QueryLifeTimeHookContext ctx) { + ctxs[0] = ctx; + } + + @Override + public void afterCompile(QueryLifeTimeHookContext ctx, boolean hasError) { + ctxs[1] = ctx; + } + + @Override + public void beforeExecution(QueryLifeTimeHookContext ctx) { + ctxs[2] = ctx; + } + + @Override + public void afterExecution(QueryLifeTimeHookContext ctx, boolean hasError) { + ctxs[3] = ctx; + } + } +} http://git-wip-us.apache.org/repos/asf/hive/blob/f7c51b6c/ql/src/test/org/apache/hadoop/hive/ql/hooks/TestQueryLifeTimeHook.java ---------------------------------------------------------------------- diff --git a/ql/src/test/org/apache/hadoop/hive/ql/hooks/TestQueryLifeTimeHook.java b/ql/src/test/org/apache/hadoop/hive/ql/hooks/TestQueryLifeTimeHook.java new file mode 100644 index 0000000..1f6239c --- /dev/null +++ b/ql/src/test/org/apache/hadoop/hive/ql/hooks/TestQueryLifeTimeHook.java @@ -0,0 +1,43 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.hooks; + +import org.apache.hadoop.hive.ql.session.SessionState; + +public class TestQueryLifeTimeHook implements QueryLifeTimeHook { + @Override + public void beforeCompile(QueryLifeTimeHookContext ctx) { + SessionState.getConsole().getOutStream().println("beforeCompile: " + ctx.getCommand()); + } + + @Override + public void afterCompile(QueryLifeTimeHookContext ctx, boolean hasError) { + SessionState.getConsole().getOutStream().println("afterCompile: " + ctx.getCommand()); + } + + @Override + public void beforeExecution(QueryLifeTimeHookContext ctx) { + SessionState.getConsole().getOutStream().println("beforeExecution: " + ctx.getCommand()); + } + + @Override + public void afterExecution(QueryLifeTimeHookContext ctx, boolean hasError) { + SessionState.getConsole().getOutStream().println("afterExecution: " + ctx.getCommand()); + } +} http://git-wip-us.apache.org/repos/asf/hive/blob/f7c51b6c/ql/src/test/queries/clientpositive/query_lifetime_hook.q ---------------------------------------------------------------------- diff --git a/ql/src/test/queries/clientpositive/query_lifetime_hook.q b/ql/src/test/queries/clientpositive/query_lifetime_hook.q new file mode 100644 index 0000000..8fda055 --- /dev/null +++ b/ql/src/test/queries/clientpositive/query_lifetime_hook.q @@ -0,0 +1,3 @@ +SET hive.query.lifetime.hooks=org.apache.hadoop.hive.ql.hooks.TestQueryLifeTimeHook; + +SELECT * FROM src LIMIT 1; http://git-wip-us.apache.org/repos/asf/hive/blob/f7c51b6c/ql/src/test/results/clientpositive/query_lifetime_hook.q.out ---------------------------------------------------------------------- diff --git a/ql/src/test/results/clientpositive/query_lifetime_hook.q.out b/ql/src/test/results/clientpositive/query_lifetime_hook.q.out new file mode 100644 index 0000000..4a8e7ee --- /dev/null +++ b/ql/src/test/results/clientpositive/query_lifetime_hook.q.out @@ -0,0 +1,21 @@ +beforeCompile: + +SELECT * FROM src LIMIT 1 +afterCompile: + +SELECT * FROM src LIMIT 1 +PREHOOK: query: SELECT * FROM src LIMIT 1 +PREHOOK: type: QUERY +PREHOOK: Input: default@src +#### A masked pattern was here #### +beforeExecution: + +SELECT * FROM src LIMIT 1 +POSTHOOK: query: SELECT * FROM src LIMIT 1 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@src +#### A masked pattern was here #### +afterExecution: + +SELECT * FROM src LIMIT 1 +238 val_238