LENS-1242 : Fix JDBCDriver cancel query to call statement.cancel
Project: http://git-wip-us.apache.org/repos/asf/lens/repo Commit: http://git-wip-us.apache.org/repos/asf/lens/commit/9b402aee Tree: http://git-wip-us.apache.org/repos/asf/lens/tree/9b402aee Diff: http://git-wip-us.apache.org/repos/asf/lens/diff/9b402aee Branch: refs/heads/current-release-line Commit: 9b402aee35e52fcf235974429cee760883b42271 Parents: f4da1f0 Author: Amareshwari Sriramadasu <[email protected]> Authored: Fri Jul 29 18:07:28 2016 +0530 Committer: Puneet <[email protected]> Committed: Fri Jul 29 18:07:28 2016 +0530 ---------------------------------------------------------------------- .../org/apache/lens/driver/jdbc/JDBCDriver.java | 28 +++++++- .../driver/jdbc/JDBCDriverConfConstants.java | 3 + .../src/main/resources/jdbcdriver-default.xml | 7 ++ .../apache/lens/driver/jdbc/TestJdbcDriver.java | 68 +++++++++++++++----- .../drivers/jdbc/jdbc1/jdbcdriver-site.xml | 3 +- src/site/apt/admin/jdbcdriver-config.apt | 6 +- 6 files changed, 95 insertions(+), 20 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lens/blob/9b402aee/lens-driver-jdbc/src/main/java/org/apache/lens/driver/jdbc/JDBCDriver.java ---------------------------------------------------------------------- diff --git a/lens-driver-jdbc/src/main/java/org/apache/lens/driver/jdbc/JDBCDriver.java b/lens-driver-jdbc/src/main/java/org/apache/lens/driver/jdbc/JDBCDriver.java index 8047302..15a1826 100644 --- a/lens-driver-jdbc/src/main/java/org/apache/lens/driver/jdbc/JDBCDriver.java +++ b/lens-driver-jdbc/src/main/java/org/apache/lens/driver/jdbc/JDBCDriver.java @@ -112,6 +112,7 @@ public class JDBCDriver extends AbstractLensDriver { private ImmutableSet<QueryLaunchingConstraint> queryConstraints; private ImmutableSet<WaitingQueriesSelectionPolicy> selectionPolicies; + private boolean isStatementCancelSupported; /** * Data related to a query submitted to JDBCDriver. */ @@ -209,6 +210,29 @@ public class JDBCDriver extends AbstractLensDriver { isClosed = true; } + public boolean cancel() { + boolean ret; + log.debug("Canceling resultFuture object"); + ret = resultFuture.cancel(true); + log.debug("Done resultFuture cancel!"); + // queryResult object would be null if query is not yet launched - since we did future.cancel, no other cancel is + // required. + if (queryResult != null && isStatementCancelSupported) { + log.debug("Cancelling query through statement cancel"); + try { + queryResult.stmt.cancel(); + log.debug("Done statement cancel!"); + ret = true; + } catch (SQLFeatureNotSupportedException se) { + log.warn("Statement cancel not supported", se); + } catch(SQLException e) { + log.warn("Statement cancel failed", e); + ret = false; + } + } + return ret; + } + public String getQueryHandleString() { return this.lensContext.getQueryHandleString(); } @@ -484,6 +508,7 @@ public class JDBCDriver extends AbstractLensDriver { this.logSegregationContext = new MappedDiagnosticLogSegregationContext(); this.queryConstraints = getImplementations(QUERY_LAUNCHING_CONSTRAINT_FACTORIES_KEY, this.conf); this.selectionPolicies = getImplementations(WAITING_QUERIES_SELECTION_POLICY_FACTORIES_KEY, this.conf); + this.isStatementCancelSupported = conf.getBoolean(STATEMENT_CANCEL_SUPPORTED, DEFAULT_STATEMENT_CANCEL_SUPPORTED); } /** @@ -1045,7 +1070,8 @@ public class JDBCDriver extends AbstractLensDriver { public boolean cancelQuery(QueryHandle handle) throws LensException { checkConfigured(); JdbcQueryContext context = getQueryContext(handle); - boolean cancelResult = context.getResultFuture().cancel(true); + log.info("{} cancel request on query {}", getFullyQualifiedName(), handle); + boolean cancelResult = context.cancel(); if (cancelResult) { context.setCancelled(true); // this is required because future.cancel does not guarantee http://git-wip-us.apache.org/repos/asf/lens/blob/9b402aee/lens-driver-jdbc/src/main/java/org/apache/lens/driver/jdbc/JDBCDriverConfConstants.java ---------------------------------------------------------------------- diff --git a/lens-driver-jdbc/src/main/java/org/apache/lens/driver/jdbc/JDBCDriverConfConstants.java b/lens-driver-jdbc/src/main/java/org/apache/lens/driver/jdbc/JDBCDriverConfConstants.java index ac0682d..3c34eb1 100644 --- a/lens-driver-jdbc/src/main/java/org/apache/lens/driver/jdbc/JDBCDriverConfConstants.java +++ b/lens-driver-jdbc/src/main/java/org/apache/lens/driver/jdbc/JDBCDriverConfConstants.java @@ -110,4 +110,7 @@ public final class JDBCDriverConfConstants { public static final String WAITING_QUERIES_SELECTION_POLICY_FACTORIES_KEY = JDBC_DRIVER_PFX + "waiting.queries.selection.policy.factories"; public static final String REGEX_REPLACEMENT_VALUES = JDBC_DRIVER_PFX + "regex.replacement.values"; + public static final String STATEMENT_CANCEL_SUPPORTED = JDBC_DRIVER_PFX + "statement.cancel.supported"; + public static final boolean DEFAULT_STATEMENT_CANCEL_SUPPORTED = true; + } http://git-wip-us.apache.org/repos/asf/lens/blob/9b402aee/lens-driver-jdbc/src/main/resources/jdbcdriver-default.xml ---------------------------------------------------------------------- diff --git a/lens-driver-jdbc/src/main/resources/jdbcdriver-default.xml b/lens-driver-jdbc/src/main/resources/jdbcdriver-default.xml index 66645b9..89726c4 100644 --- a/lens-driver-jdbc/src/main/resources/jdbcdriver-default.xml +++ b/lens-driver-jdbc/src/main/resources/jdbcdriver-default.xml @@ -254,4 +254,11 @@ is enabled by using org.apache.lens.server.api.query.constraint.MaxConcurrentDriverQueriesConstraintFactory as one of the factories in lens.driver.jdbc.query.constraint.factories property.</description> </property> + + <property> + <name>lens.driver.jdbc.statement.cancel.supported</name> + <value>true</value> + <description>Flag to indicate Whether cancel on JDBC statement is supported. If not supported, + framework wont call cancel on JDBC statement.</description> + </property> </configuration> http://git-wip-us.apache.org/repos/asf/lens/blob/9b402aee/lens-driver-jdbc/src/test/java/org/apache/lens/driver/jdbc/TestJdbcDriver.java ---------------------------------------------------------------------- diff --git a/lens-driver-jdbc/src/test/java/org/apache/lens/driver/jdbc/TestJdbcDriver.java b/lens-driver-jdbc/src/test/java/org/apache/lens/driver/jdbc/TestJdbcDriver.java index 491aa69..e7636d2 100644 --- a/lens-driver-jdbc/src/test/java/org/apache/lens/driver/jdbc/TestJdbcDriver.java +++ b/lens-driver-jdbc/src/test/java/org/apache/lens/driver/jdbc/TestJdbcDriver.java @@ -139,13 +139,17 @@ public class TestJdbcDriver { } synchronized void createTable(String table, Connection conn) throws Exception { + runTestSetupQuery(conn, "CREATE TABLE " + table + " (ID INT)"); + } + + void runTestSetupQuery(Connection conn, String query) throws Exception { Statement stmt = null; try { if (conn == null) { conn = driver.getConnection(); } stmt = conn.createStatement(); - stmt.execute("CREATE TABLE " + table + " (ID INT)"); + stmt.execute(query); conn.commit(); } finally { @@ -163,13 +167,16 @@ public class TestJdbcDriver { insertData(table, null); } + void insertData(String table, Connection conn) throws Exception { + insertData(table, conn, 10); + } /** * Insert data. * * @param table the table * @throws Exception the exception */ - void insertData(String table, Connection conn) throws Exception { + void insertData(String table, Connection conn, int numRows) throws Exception { PreparedStatement stmt = null; try { if (conn == null) { @@ -177,7 +184,7 @@ public class TestJdbcDriver { } stmt = conn.prepareStatement("INSERT INTO " + table + " VALUES(?)"); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < numRows; i++) { stmt.setInt(1, i); stmt.executeUpdate(); } @@ -449,7 +456,7 @@ public class TestJdbcDriver { /** - * Data provider for test case {@link #testExecuteWithPreFetch()} + * Data provider for test case {@link #testExecuteWithPreFetch(int, boolean, int, boolean, long)} ()} * @return */ @DataProvider @@ -822,29 +829,58 @@ public class TestJdbcDriver { driver.execute(validCtx); } + public static int sleep(int t) { + try { + Thread.sleep(t * 1000); + } catch (InterruptedException ie) { + // ignore + } + return t; + } + + @DataProvider(name = "waitBeforeCancel") + public Object[][] mediaTypeData() { + return new Object[][] { + {true}, + {false}, + }; + } + + boolean setupCancel = false; + private void setupCancelQuery() throws Exception { + if (!setupCancel) { + createTable("cancel_query_test"); + insertData("cancel_query_test", null, 1); + final String function = "create function sleep(t int) returns int no sql language java PARAMETER STYLE JAVA" + + " EXTERNAL NAME 'CLASSPATH:org.apache.lens.driver.jdbc.TestJdbcDriver.sleep'"; + runTestSetupQuery(null, function); + setupCancel = true; + } + } /** * Test cancel query. * * @throws Exception the exception */ - @Test - public void testCancelQuery() throws Exception { - createTable("cancel_query_test"); - insertData("cancel_query_test"); - final String query = "SELECT * FROM cancel_query_test"; + @Test(dataProvider = "waitBeforeCancel") + public void testCancelQuery(boolean waitBeforeCancel) throws Exception { + setupCancelQuery(); + // picked function as positive with udf mapping to sleep - sothat the signature of both are same. + // Here we need a UDF mapping because the function sleep is not available in Hive functions and semantic analysis + // would fail otherwise. + final String query = "SELECT positive(5) FROM cancel_query_test"; QueryContext context = createQueryContext(query); System.out.println("@@@ test_cancel:" + context.getQueryHandle()); executeAsync(context); QueryHandle handle = context.getQueryHandle(); + // without wait query may not be launched. + if (waitBeforeCancel) { + Thread.sleep(100); + } boolean isCancelled = driver.cancelQuery(handle); driver.updateStatus(context); - - if (isCancelled) { - assertEquals(context.getDriverStatus().getState(), DriverQueryState.CANCELED); - } else { - // Query completed before cancelQuery call - assertEquals(context.getDriverStatus().getState(), DriverQueryState.SUCCESSFUL); - } + assertTrue(isCancelled); + assertEquals(context.getDriverStatus().getState(), DriverQueryState.CANCELED); assertTrue(context.getDriverStatus().getDriverStartTime() > 0); assertTrue(context.getDriverStatus().getDriverFinishTime() > 0); http://git-wip-us.apache.org/repos/asf/lens/blob/9b402aee/lens-driver-jdbc/src/test/resources/drivers/jdbc/jdbc1/jdbcdriver-site.xml ---------------------------------------------------------------------- diff --git a/lens-driver-jdbc/src/test/resources/drivers/jdbc/jdbc1/jdbcdriver-site.xml b/lens-driver-jdbc/src/test/resources/drivers/jdbc/jdbc1/jdbcdriver-site.xml index 1202074..ac5e43d 100644 --- a/lens-driver-jdbc/src/test/resources/drivers/jdbc/jdbc1/jdbcdriver-site.xml +++ b/lens-driver-jdbc/src/test/resources/drivers/jdbc/jdbc1/jdbcdriver-site.xml @@ -64,7 +64,8 @@ <property> <name>lens.driver.jdbc.regex.replacement.values</name> - <value>weekofyear=week, to_date=date, format_number=format, date_sub\((.*?)\,\s*([0-9]+\s*)\)=date_sub($1\, interval$2 day), date_add\((.*?)\,\s*([0-9]+\s*)\)=date_add($1\, interval $2 day)</value> + <value>weekofyear=week, to_date=date, format_number=format, date_sub\((.*?)\,\s*([0-9]+\s*)\)=date_sub($1\, + interval$2 day), date_add\((.*?)\,\s*([0-9]+\s*)\)=date_add($1\, interval $2 day),positive=sleep</value> <description>Rewriting the HQL to optimized sql queries</description> </property> </configuration> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/lens/blob/9b402aee/src/site/apt/admin/jdbcdriver-config.apt ---------------------------------------------------------------------- diff --git a/src/site/apt/admin/jdbcdriver-config.apt b/src/site/apt/admin/jdbcdriver-config.apt index 96c98ad..c64d6ee 100644 --- a/src/site/apt/admin/jdbcdriver-config.apt +++ b/src/site/apt/admin/jdbcdriver-config.apt @@ -85,8 +85,10 @@ Jdbc driver configuration *--+--+---+--+ |30|lens.driver.jdbc.regex.replacement.values|to_date=date, format_number=format, date_sub\((.*?)\,\s*([0-9]+\s*)\)=date_sub($1\, interval $2 day), date_add\((.*?)\,\s*([0-9]+\s*)\)=date_add($1\, interval $2 day)|Rewriting the HQL to optimized sql queries| *--+--+---+--+ -|31|lens.driver.jdbc.validate.through.prepare|true|Flag to enable query syntactic and semantic validation using prepared statement.| +|31|lens.driver.jdbc.statement.cancel.supported|true|Flag to indicate Whether cancel on JDBC statement is supported. If not supported, framework wont call cancel on JDBC statement.| *--+--+---+--+ -|32|lens.driver.jdbc.waiting.queries.selection.policy.factories|org.apache.lens.server.api.query.collect.DriverSpecificWaitingQueriesSelectionPolicyFactory|Factories used to instantiate driver specific waiting queries selection policies. Every factory should be an implementation of org.apache.lens.server.api.common.ConfigBasedObjectCreationFactory and create an implementation of org.apache.lens.server.api.query.collect.WaitingQueriesSelectionPolicy.| +|32|lens.driver.jdbc.validate.through.prepare|true|Flag to enable query syntactic and semantic validation using prepared statement.| +*--+--+---+--+ +|33|lens.driver.jdbc.waiting.queries.selection.policy.factories|org.apache.lens.server.api.query.collect.DriverSpecificWaitingQueriesSelectionPolicyFactory|Factories used to instantiate driver specific waiting queries selection policies. Every factory should be an implementation of org.apache.lens.server.api.common.ConfigBasedObjectCreationFactory and create an implementation of org.apache.lens.server.api.query.collect.WaitingQueriesSelectionPolicy.| *--+--+---+--+ The configuration parameters and their default values
