diff --git a/itests/hive-unit/src/test/java/org/apache/hive/service/cli/CLIServiceTest.java b/itests/hive-unit/src/test/java/org/apache/hive/service/cli/CLIServiceTest.java new file mode 100644 index 0000000..c85836f --- /dev/null +++ b/itests/hive-unit/src/test/java/org/apache/hive/service/cli/CLIServiceTest.java @@ -0,0 +1,326 @@ +/** + * 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.hive.service.cli; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hadoop.hive.ql.ErrorMsg; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * CLIServiceTest. + * + */ +public abstract class CLIServiceTest { + + protected static CLIServiceClient client; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() throws Exception { + } + + @Test + public void openSessionTest() throws Exception { + SessionHandle sessionHandle = client.openSession( + "tom", "password", Collections.emptyMap()); + assertNotNull(sessionHandle); + client.closeSession(sessionHandle); + + sessionHandle = client.openSession("tom", "password"); + assertNotNull(sessionHandle); + client.closeSession(sessionHandle); + } + + @Test + public void getFunctionsTest() throws Exception { + SessionHandle sessionHandle = client.openSession("tom", "password"); + assertNotNull(sessionHandle); + + OperationHandle opHandle = client.getFunctions(sessionHandle, null, null, "*"); + TableSchema schema = client.getResultSetMetadata(opHandle); + + ColumnDescriptor columnDesc = schema.getColumnDescriptorAt(0); + assertEquals("FUNCTION_CAT", columnDesc.getName()); + assertEquals(Type.STRING_TYPE, columnDesc.getType()); + + columnDesc = schema.getColumnDescriptorAt(1); + assertEquals("FUNCTION_SCHEM", columnDesc.getName()); + assertEquals(Type.STRING_TYPE, columnDesc.getType()); + + columnDesc = schema.getColumnDescriptorAt(2); + assertEquals("FUNCTION_NAME", columnDesc.getName()); + assertEquals(Type.STRING_TYPE, columnDesc.getType()); + + columnDesc = schema.getColumnDescriptorAt(3); + assertEquals("REMARKS", columnDesc.getName()); + assertEquals(Type.STRING_TYPE, columnDesc.getType()); + + columnDesc = schema.getColumnDescriptorAt(4); + assertEquals("FUNCTION_TYPE", columnDesc.getName()); + assertEquals(Type.INT_TYPE, columnDesc.getType()); + + columnDesc = schema.getColumnDescriptorAt(5); + assertEquals("SPECIFIC_NAME", columnDesc.getName()); + assertEquals(Type.STRING_TYPE, columnDesc.getType()); + + // Cleanup + client.closeOperation(opHandle); + client.closeSession(sessionHandle); + } + + @Test + public void getInfoTest() throws Exception { + SessionHandle sessionHandle = client.openSession( + "tom", "password", new HashMap()); + assertNotNull(sessionHandle); + + GetInfoValue value = client.getInfo(sessionHandle, GetInfoType.CLI_DBMS_NAME); + System.out.println(value.getStringValue()); + + value = client.getInfo(sessionHandle, GetInfoType.CLI_SERVER_NAME); + System.out.println(value.getStringValue()); + + value = client.getInfo(sessionHandle, GetInfoType.CLI_DBMS_VER); + System.out.println(value.getStringValue()); + + client.closeSession(sessionHandle); + } + + @Test + public void testExecuteStatement() throws Exception { + HashMap confOverlay = new HashMap(); + SessionHandle sessionHandle = client.openSession( + "tom", "password", new HashMap()); + assertNotNull(sessionHandle); + + OperationHandle opHandle; + + // Change lock manager, otherwise unit-test doesn't go through + String queryString = "SET hive.lock.manager=" + + "org.apache.hadoop.hive.ql.lockmgr.EmbeddedLockManager"; + opHandle = client.executeStatement(sessionHandle, queryString, confOverlay); + client.closeOperation(opHandle); + + queryString = "DROP TABLE IF EXISTS TEST_EXEC"; + opHandle = client.executeStatement(sessionHandle, queryString, confOverlay); + client.closeOperation(opHandle); + + // Create a test table + queryString = "CREATE TABLE TEST_EXEC(ID STRING)"; + opHandle = client.executeStatement(sessionHandle, queryString, confOverlay); + client.closeOperation(opHandle); + + // Blocking execute + queryString = "SELECT ID FROM TEST_EXEC"; + opHandle = client.executeStatement(sessionHandle, queryString, confOverlay); + // Expect query to be completed now + assertEquals("Query should be finished", + OperationState.FINISHED, client.getOperationStatus(opHandle).getState()); + client.closeOperation(opHandle); + + // Cleanup + queryString = "DROP TABLE IF EXISTS TEST_EXEC"; + opHandle = client.executeStatement(sessionHandle, queryString, confOverlay); + client.closeOperation(opHandle); + client.closeSession(sessionHandle); + } + + @Test + public void testExecuteStatementAsync() throws Exception { + HashMap confOverlay = new HashMap(); + SessionHandle sessionHandle = client.openSession("tom", "password", + new HashMap()); + assertNotNull(sessionHandle); + + // Timeout for the poll in case of asynchronous execute + long pollTimeout = System.currentTimeMillis() + 100000; + OperationState state = null; + OperationHandle opHandle; + + // Change lock manager, otherwise unit-test doesn't go through + String queryString = "SET hive.lock.manager=" + + "org.apache.hadoop.hive.ql.lockmgr.EmbeddedLockManager"; + opHandle = client.executeStatement(sessionHandle, queryString, confOverlay); + client.closeOperation(opHandle); + + // Drop the table if it exists + queryString = "DROP TABLE IF EXISTS TEST_EXEC_ASYNC"; + opHandle = client.executeStatement(sessionHandle, queryString, confOverlay); + client.closeOperation(opHandle); + + // Create a test table + queryString = "CREATE TABLE TEST_EXEC_ASYNC(ID STRING)"; + opHandle = client.executeStatement(sessionHandle, queryString, confOverlay); + client.closeOperation(opHandle); + + // Test async execution response when query is malformed + // This query will throw an error with errorCode: 10004 + // Refer org.apache.hadoop.hive.ql.ErrorMsg for details + String wrongQueryString = "SELECT NON_EXISTANT_COLUMN FROM TEST_EXEC_ASYNC"; + opHandle = client.executeStatementAsync(sessionHandle, wrongQueryString, confOverlay); + + int count = 0; + while (true) { + // Break if polling times out + if (System.currentTimeMillis() > pollTimeout) { + System.out.println("Polling timed out"); + break; + } + try { + // This will throw an exeption when in ERROR state + state = client.getOperationStatus(opHandle).getState(); + System.out.println("Polling: " + opHandle + " count=" + (++count) + + " state=" + state); + assertFalse("Expected OperationState: " + OperationState.ERROR + "; is " + state, + (OperationState.ERROR == state)); + } + catch (HiveSQLException e) { + System.out.println("Caught an expected HiveSQLException: " + e.getMessage()); + // The expected error message should be a substring of the returned error message + String errorMsg = e.getMessage().toLowerCase(); + String expectedErrorMsg = ErrorMsg.getErrorMsg(10004).getMsg().toLowerCase(); + assertTrue("Incorrect error message", errorMsg.contains(expectedErrorMsg)); + break; + } + Thread.sleep(1000); + } + client.closeOperation(opHandle); + + // Test async execution when query is well formed + queryString = "SELECT ID FROM TEST_EXEC_ASYNC"; + opHandle = client.executeStatementAsync(sessionHandle, queryString, confOverlay); + + count = 0; + while (true) { + // Break if polling times out + if (System.currentTimeMillis() > pollTimeout) { + System.out.println("Polling timed out"); + break; + } + state = client.getOperationStatus(opHandle).getState(); + System.out.println("Polling: " + opHandle + " count=" + (++count) + + " state=" + state); + + if (OperationState.CANCELED == state || state == OperationState.CLOSED + || state == OperationState.FINISHED || state == OperationState.ERROR) { + break; + } + Thread.sleep(1000); + } + assertEquals("Query should be finished", OperationState.FINISHED, state); + client.closeOperation(opHandle); + + // Cancellation test + opHandle = client.executeStatementAsync(sessionHandle, queryString, confOverlay); + System.out.println("cancelling " + opHandle); + client.cancelOperation(opHandle); + state = client.getOperationStatus(opHandle).getState(); + System.out.println(opHandle + " after cancelling, state= " + state); + assertEquals("Query should be cancelled", OperationState.CANCELED, state); + + // Cleanup + queryString = "DROP TABLE IF EXISTS TEST_EXEC_ASYNC"; + opHandle = client.executeStatement(sessionHandle, queryString, confOverlay); + client.closeOperation(opHandle); + client.closeSession(sessionHandle); + } + + /** + * Test per statement configuration overlay. + * Create a table using hiveconf: var substitution, with the conf var passed + * via confOverlay.Verify the confOverlay works for the query and does set the + * value in the session configuration + * @throws Exception + */ + @Test + public void testConfOverlay() throws Exception { + SessionHandle sessionHandle = client.openSession("tom", "password", new HashMap()); + assertNotNull(sessionHandle); + String tabName = "TEST_CONF_EXEC"; + String tabNameVar = "tabNameVar"; + + String setLockMgr = "SET " + HiveConf.ConfVars.HIVE_SUPPORT_CONCURRENCY.varname + + " = false"; + OperationHandle opHandle = client.executeStatement(sessionHandle, setLockMgr, null); + client.closeOperation(opHandle); + + String dropTable = "DROP TABLE IF EXISTS " + tabName; + opHandle = client.executeStatement(sessionHandle, dropTable, null); + client.closeOperation(opHandle); + + // set a pass a property to operation and check if its set the query config + Map confOverlay = new HashMap(); + confOverlay.put(tabNameVar, tabName); + + // execute statement with the conf overlay + String createTab = "CREATE TABLE ${hiveconf:" + tabNameVar + "} (id int)"; + opHandle = client.executeStatement(sessionHandle, createTab, confOverlay); + assertNotNull(opHandle); + // query should pass and create the table + assertEquals("Query should be finished", + OperationState.FINISHED, client.getOperationStatus(opHandle).getState()); + client.closeOperation(opHandle); + + // select from the new table should pass + String selectTab = "SELECT * FROM " + tabName; + opHandle = client.executeStatement(sessionHandle, selectTab, null); + assertNotNull(opHandle); + // query should pass and create the table + assertEquals("Query should be finished", + OperationState.FINISHED, client.getOperationStatus(opHandle).getState()); + client.closeOperation(opHandle); + + // the settings in conf overlay should not be part of session config + // another query referring that property with the conf overlay should fail + selectTab = "SELECT * FROM ${hiveconf:" + tabNameVar + "}"; + try { + opHandle = client.executeStatement(sessionHandle, selectTab, null); + fail("Query should fail"); + } catch (HiveSQLException e) { + // Expected exception + } + + // cleanup + dropTable = "DROP TABLE IF EXISTS " + tabName; + opHandle = client.executeStatement(sessionHandle, dropTable, null); + client.closeOperation(opHandle); + client.closeSession(sessionHandle); + } +} diff --git a/itests/hive-unit/src/test/java/org/apache/hive/service/cli/thrift/ThriftCLIServiceTest.java b/itests/hive-unit/src/test/java/org/apache/hive/service/cli/thrift/ThriftCLIServiceTest.java new file mode 100644 index 0000000..d9d828a --- /dev/null +++ b/itests/hive-unit/src/test/java/org/apache/hive/service/cli/thrift/ThriftCLIServiceTest.java @@ -0,0 +1,399 @@ +/** + * 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.hive.service.cli.thrift; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.util.Collection; + +import javax.security.auth.login.LoginException; + +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hadoop.hive.conf.HiveConf.ConfVars; +import org.apache.hadoop.hive.metastore.MetaStoreUtils; +import org.apache.hadoop.hive.ql.ErrorMsg; +import org.apache.hive.service.Service; +import org.apache.hive.service.auth.HiveAuthFactory; +import org.apache.hive.service.auth.PlainSaslHelper; +import org.apache.hive.service.cli.CLIService; +import org.apache.hive.service.cli.HiveSQLException; +import org.apache.hive.service.cli.OperationState; +import org.apache.hive.service.cli.SessionHandle; +import org.apache.hive.service.cli.session.HiveSession; +import org.apache.hive.service.cli.session.SessionManager; +import org.apache.hive.service.server.HiveServer2; +import org.apache.thrift.protocol.TBinaryProtocol; +import org.apache.thrift.protocol.TProtocol; +import org.apache.thrift.transport.TSocket; +import org.apache.thrift.transport.TTransport; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * ThriftCLIServiceTest. + * This is the abstract class that tests ThriftCLIService. + * Subclass this to test more specific behaviour. + * + */ +public abstract class ThriftCLIServiceTest { + + protected static int port; + protected static String host = "localhost"; + protected static HiveServer2 hiveServer2; + protected static TCLIService.Client client; + protected static HiveConf hiveConf; + protected static String anonymousUser = "anonymous"; + protected static String anonymousPasswd = "anonymous"; + + /** + * @throws java.lang.Exception + */ + @BeforeClass + public static void setUpBeforeClass() throws Exception { + // Find a free port + port = MetaStoreUtils.findFreePort(); + hiveServer2 = new HiveServer2(); + hiveConf = new HiveConf(); + } + + /** + * @throws java.lang.Exception + */ + @AfterClass + public static void tearDownAfterClass() throws Exception { + stopHiveServer2(); + } + + protected static void startHiveServer2WithConf(HiveConf hiveConf) throws Exception { + hiveServer2.init(hiveConf); + // Start HiveServer2 with given config + // Fail if server doesn't start + try { + hiveServer2.start(); + } catch (Throwable t) { + t.printStackTrace(); + fail(); + } + // Wait for startup to complete + Thread.sleep(2000); + System.out.println("HiveServer2 started on port " + port); + } + + protected static void stopHiveServer2() throws Exception { + if (hiveServer2 != null) { + hiveServer2.stop(); + } + } + + protected static TTransport createBinaryTransport() throws Exception { + return PlainSaslHelper.getPlainTransport(anonymousUser, anonymousPasswd, + new TSocket(host, port)); + } + + protected static void initClient(TTransport transport) { + // Create the corresponding client + TProtocol protocol = new TBinaryProtocol(transport); + client = new TCLIService.Client(protocol); + } + + @Test + public void testOpenSession() throws Exception { + // Create a new request object + TOpenSessionReq openReq = new TOpenSessionReq(); + + // Get the response; ignore exception if any + TOpenSessionResp openResp = client.OpenSession(openReq); + assertNotNull("Response should not be null", openResp); + + TSessionHandle sessHandle = openResp.getSessionHandle(); + assertNotNull("Session handle should not be null", sessHandle); + + assertEquals(openResp.getStatus().getStatusCode(), TStatusCode.SUCCESS_STATUS); + + // Close the session; ignore exception if any + TCloseSessionReq closeReq = new TCloseSessionReq(sessHandle); + client.CloseSession(closeReq); + } + + @Test + public void testGetFunctions() throws Exception { + // Create a new open session request object + TOpenSessionReq openReq = new TOpenSessionReq(); + TSessionHandle sessHandle = client.OpenSession(openReq).getSessionHandle(); + assertNotNull(sessHandle); + + TGetFunctionsReq funcReq = new TGetFunctionsReq(); + funcReq.setSessionHandle(sessHandle); + funcReq.setFunctionName("*"); + funcReq.setCatalogName(null); + funcReq.setSchemaName(null); + + TGetFunctionsResp funcResp = client.GetFunctions(funcReq); + assertNotNull(funcResp); + assertNotNull(funcResp.getStatus()); + assertFalse(funcResp.getStatus().getStatusCode() == TStatusCode.ERROR_STATUS); + + // Close the session; ignore exception if any + TCloseSessionReq closeReq = new TCloseSessionReq(sessHandle); + client.CloseSession(closeReq); + } + + /** + * Test synchronous query execution + * @throws Exception + */ + @Test + public void testExecuteStatement() throws Exception { + // Create a new request object + TOpenSessionReq openReq = new TOpenSessionReq(); + TSessionHandle sessHandle = client.OpenSession(openReq).getSessionHandle(); + assertNotNull(sessHandle); + + // Change lock manager to embedded mode + String queryString = "SET hive.lock.manager=" + + "org.apache.hadoop.hive.ql.lockmgr.EmbeddedLockManager"; + executeQuery(queryString, sessHandle, false); + + // Drop the table if it exists + queryString = "DROP TABLE IF EXISTS TEST_EXEC_THRIFT"; + executeQuery(queryString, sessHandle, false); + + // Create a test table + queryString = "CREATE TABLE TEST_EXEC_THRIFT(ID STRING)"; + executeQuery(queryString, sessHandle, false); + + // Execute another query + queryString = "SELECT ID FROM TEST_EXEC_THRIFT"; + TExecuteStatementResp execResp = executeQuery(queryString, sessHandle, false); + TOperationHandle operationHandle = execResp.getOperationHandle(); + assertNotNull(operationHandle); + + TGetOperationStatusReq opStatusReq = new TGetOperationStatusReq(); + opStatusReq.setOperationHandle(operationHandle); + assertNotNull(opStatusReq); + TGetOperationStatusResp opStatusResp = client.GetOperationStatus(opStatusReq); + TOperationState state = opStatusResp.getOperationStatus().getOperationState(); + // Expect query to be completed now + assertEquals("Query should be finished", TOperationState.FINISHED_STATE, state); + + // Cleanup + queryString = "DROP TABLE TEST_EXEC_THRIFT"; + executeQuery(queryString, sessHandle, false); + + // Close the session; ignore exception if any + TCloseSessionReq closeReq = new TCloseSessionReq(sessHandle); + client.CloseSession(closeReq); + } + + /** + * Test asynchronous query execution and error message reporting to the client + * @throws Exception + */ + @Test + public void testExecuteStatementAsync() throws Exception { + // Create a new request object + TOpenSessionReq openReq = new TOpenSessionReq(); + TSessionHandle sessHandle = client.OpenSession(openReq).getSessionHandle(); + assertNotNull(sessHandle); + + // Change lock manager to embedded mode + String queryString = "SET hive.lock.manager=" + + "org.apache.hadoop.hive.ql.lockmgr.EmbeddedLockManager"; + executeQuery(queryString, sessHandle, false); + + // Drop the table if it exists + queryString = "DROP TABLE IF EXISTS TEST_EXEC_ASYNC_THRIFT"; + executeQuery(queryString, sessHandle, false); + + // Create a test table + queryString = "CREATE TABLE TEST_EXEC_ASYNC_THRIFT(ID STRING)"; + executeQuery(queryString, sessHandle, false); + + // Execute another query + queryString = "SELECT ID FROM TEST_EXEC_ASYNC_THRIFT"; + System.out.println("Will attempt to execute: " + queryString); + TExecuteStatementResp execResp = executeQuery(queryString, sessHandle, true); + TOperationHandle operationHandle = execResp.getOperationHandle(); + assertNotNull(operationHandle); + + // Poll on the operation status till the query is completed + boolean isQueryRunning = true; + TGetOperationStatusReq opStatusReq; + TGetOperationStatusResp opStatusResp = null; + TOperationState state = null; + long pollTimeout = System.currentTimeMillis() + 100000; + + while(isQueryRunning) { + // Break if polling times out + if (System.currentTimeMillis() > pollTimeout) { + System.out.println("Polling timed out"); + break; + } + opStatusReq = new TGetOperationStatusReq(); + opStatusReq.setOperationHandle(operationHandle); + assertNotNull(opStatusReq); + opStatusResp = client.GetOperationStatus(opStatusReq); + state = opStatusResp.getOperationStatus().getOperationState(); + System.out.println("Current state: " + state); + + if (state == TOperationState.CANCELED_STATE || state == TOperationState.CLOSED_STATE + || state == TOperationState.FINISHED_STATE || state == TOperationState.ERROR_STATE) { + isQueryRunning = false; + } + Thread.sleep(1000); + } + + // Expect query to be successfully completed now + assertEquals("Query should be finished", + TOperationState.FINISHED_STATE, state); + + // Execute a malformed query + queryString = "SELECT NON_EXISTING_COLUMN FROM TEST_EXEC_ASYNC_THRIFT"; + System.out.println("Will attempt to execute: " + queryString); + execResp = executeQuery(queryString, sessHandle, true); + operationHandle = execResp.getOperationHandle(); + assertNotNull(operationHandle); + isQueryRunning = true; + while(isQueryRunning) { + // Break if polling times out + if (System.currentTimeMillis() > pollTimeout) { + System.out.println("Polling timed out"); + break; + } + opStatusReq = new TGetOperationStatusReq(); + opStatusReq.setOperationHandle(operationHandle); + assertNotNull(opStatusReq); + opStatusResp = client.GetOperationStatus(opStatusReq); + state = opStatusResp.getOperationStatus().getOperationState(); + System.out.println("Current state: " + state); + + if (state == TOperationState.CANCELED_STATE || state == TOperationState.CLOSED_STATE + || state == TOperationState.FINISHED_STATE || state == TOperationState.ERROR_STATE) { + isQueryRunning = false; + } + Thread.sleep(1000); + } + + // Expect query to return an error state + assertEquals("Query should be finished", TOperationState.ERROR_STATE, state); + + // sqlState, errorCode and errorMsg should be set to appropriate values + // Refer org.apache.hadoop.hive.ql.ErrorMsg for details + assertEquals(opStatusResp.getStatus().getSqlState(), "42000"); + assertEquals(opStatusResp.getStatus().getErrorCode(), 10004); + // The expected error message should be a substring of the returned error message + String errorMsg = opStatusResp.getStatus().getErrorMessage().toLowerCase(); + String expectedErrorMsg = ErrorMsg.getErrorMsg(10004).getMsg().toLowerCase(); + assertTrue("Incorrect error message", errorMsg.contains(expectedErrorMsg)); + + // Cleanup + queryString = "DROP TABLE TEST_EXEC_ASYNC_THRIFT"; + executeQuery(queryString, sessHandle, false); + + // Close the session; ignore exception if any + TCloseSessionReq closeReq = new TCloseSessionReq(sessHandle); + client.CloseSession(closeReq); + } + + private TExecuteStatementResp executeQuery(String queryString, TSessionHandle sessHandle, boolean runAsync) + throws Exception { + TExecuteStatementReq execReq = new TExecuteStatementReq(); + execReq.setSessionHandle(sessHandle); + execReq.setStatement(queryString); + execReq.setRunAsync(runAsync); + TExecuteStatementResp execResp = client.ExecuteStatement(execReq); + assertNotNull(execResp); + assertFalse(execResp.getStatus().getStatusCode() == TStatusCode.ERROR_STATUS); + return execResp; + } + + protected void testOpenSessionExpectedException() { + boolean caughtEx = false; + // Create a new open session request object + TOpenSessionReq openReq = new TOpenSessionReq(); + try { + client.OpenSession(openReq).getSessionHandle(); + } catch (Exception e) { + caughtEx = true; + System.out.println("Exception expected: " + e.toString()); + } + assertTrue("Exception expected", caughtEx); + } + + /** + * Test setting {@link HiveConf.ConfVars}} config parameter + * HIVE_SERVER2_ENABLE_DOAS for kerberos secure mode + * @throws IOException + * @throws LoginException + * @throws HiveSQLException + */ + @Test + public void testDoAs() throws HiveSQLException, LoginException, IOException { + HiveConf hconf = new HiveConf(); + assertTrue("default value of hive server2 doAs should be true", + hconf.getBoolVar(ConfVars.HIVE_SERVER2_ENABLE_DOAS)); + + hconf.setVar(ConfVars.HIVE_SERVER2_AUTHENTICATION, + HiveAuthFactory.AuthTypes.KERBEROS.toString()); + + CLIService cliService = new CLIService(); + cliService.init(hconf); + ThriftCLIService tcliService = new ThriftBinaryCLIService(cliService); + TOpenSessionReq req = new TOpenSessionReq(); + req.setUsername("testuser1"); + SessionHandle sHandle = tcliService.getSessionHandle(req ); + SessionManager sManager = getSessionManager(cliService.getServices()); + HiveSession session = sManager.getSession(sHandle); + + //Proxy class for doing doAs on all calls is used when doAs is enabled + // and kerberos security is on + assertTrue("check if session class is a proxy", session instanceof java.lang.reflect.Proxy); + } + + private SessionManager getSessionManager(Collection services) { + for(Service s : services){ + if(s instanceof SessionManager){ + return (SessionManager)s; + } + } + return null; + } + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() throws Exception { + + } +} diff --git a/jdbc/src/java/org/apache/hive/jdbc/HiveStatement.java b/jdbc/src/java/org/apache/hive/jdbc/HiveStatement.java index fce19bf..5c20e02 100644 --- a/jdbc/src/java/org/apache/hive/jdbc/HiveStatement.java +++ b/jdbc/src/java/org/apache/hive/jdbc/HiveStatement.java @@ -217,8 +217,8 @@ public boolean execute(String sql) throws SQLException { try { TGetOperationStatusResp statusResp = client.GetOperationStatus(statusReq); Utils.verifySuccessWithInfo(statusResp.getStatus()); - if (statusResp.isSetOperationState()) { - switch (statusResp.getOperationState()) { + if (statusResp.isSetOperationStatus()) { + switch (statusResp.getOperationStatus().getOperationState()) { case CLOSED_STATE: case FINISHED_STATE: return false; @@ -231,6 +231,7 @@ public boolean execute(String sql) throws SQLException { case UKNOWN_STATE: throw new SQLException("Unknown query", "HY000"); case INITIALIZED_STATE: + case PENDING_STATE: case RUNNING_STATE: break; } diff --git a/service/if/TCLIService.thrift b/service/if/TCLIService.thrift index 1f49445..4d0b7c1 100644 --- a/service/if/TCLIService.thrift +++ b/service/if/TCLIService.thrift @@ -391,6 +391,20 @@ enum TOperationState { PENDING_STATE, } +// The return status of an operation +struct TOperationStatus { + 1: required TOperationState operationState + + // If operationState is ERROR_STATE, then the following fields may be set + // sqlState as defined in the ISO/IEF CLI specification + 2: optional string sqlState + + // Internal error code + 3: optional i32 errorCode + + // Error message + 4: optional string errorMessage +} // A string identifier. This is interpreted literally. typedef string TIdentifier @@ -900,7 +914,7 @@ struct TGetOperationStatusReq { struct TGetOperationStatusResp { 1: required TStatus status - 2: optional TOperationState operationState + 2: optional TOperationStatus operationStatus } diff --git a/service/src/java/org/apache/hive/service/cli/CLIService.java b/service/src/java/org/apache/hive/service/cli/CLIService.java index 8c85386..0c0a83e 100644 --- a/service/src/java/org/apache/hive/service/cli/CLIService.java +++ b/service/src/java/org/apache/hive/service/cli/CLIService.java @@ -38,6 +38,7 @@ import org.apache.hive.service.CompositeService; import org.apache.hive.service.ServiceException; import org.apache.hive.service.auth.HiveAuthFactory; +import org.apache.hive.service.cli.operation.OperationManager; import org.apache.hive.service.cli.session.SessionManager; /** @@ -268,11 +269,13 @@ public OperationHandle getFunctions(SessionHandle sessionHandle, * @see org.apache.hive.service.cli.ICLIService#getOperationStatus(org.apache.hive.service.cli.OperationHandle) */ @Override - public OperationState getOperationStatus(OperationHandle opHandle) + public OperationStatus getOperationStatus(OperationHandle opHandle) throws HiveSQLException { - OperationState opState = sessionManager.getOperationManager().getOperationState(opHandle); + OperationManager opManager = sessionManager.getOperationManager(); + OperationState opState = opManager.getOperationState(opHandle); + HiveSQLException runException = opManager.getOperationRunException(opHandle); LOG.info(opHandle + ": getOperationStatus()"); - return opState; + return new OperationStatus(opState, runException); } /* (non-Javadoc) diff --git a/service/src/java/org/apache/hive/service/cli/CLIServiceClient.java b/service/src/java/org/apache/hive/service/cli/CLIServiceClient.java index 14ef54f..b9d1489 100644 --- a/service/src/java/org/apache/hive/service/cli/CLIServiceClient.java +++ b/service/src/java/org/apache/hive/service/cli/CLIServiceClient.java @@ -19,8 +19,6 @@ package org.apache.hive.service.cli; import java.util.Collections; -import java.util.List; -import java.util.Map; /** @@ -29,127 +27,12 @@ */ public abstract class CLIServiceClient implements ICLIService { - /* (non-Javadoc) - * @see org.apache.hive.service.cli.ICLIService#openSession(java.lang.String, java.lang.String, java.util.Map) - */ - @Override - public abstract SessionHandle openSession(String username, String password, - Map configuration) throws HiveSQLException; - - public SessionHandle openSession(String username, String password) throws HiveSQLException { return openSession(username, password, Collections.emptyMap()); } /* (non-Javadoc) - * @see org.apache.hive.service.cli.ICLIService#closeSession(org.apache.hive.service.cli.SessionHandle) - */ - @Override - public abstract void closeSession(SessionHandle sessionHandle) throws HiveSQLException; - - /* (non-Javadoc) - * @see org.apache.hive.service.cli.ICLIService#getInfo(org.apache.hive.service.cli.SessionHandle, java.util.List) - */ - @Override - public abstract GetInfoValue getInfo(SessionHandle sessionHandle, GetInfoType getInfoType) - throws HiveSQLException; - - /* (non-Javadoc) - * @see org.apache.hive.service.cli.ICLIService#executeStatement(org.apache.hive.service.cli.SessionHandle, - * java.lang.String, java.util.Map) - */ - @Override - public abstract OperationHandle executeStatement(SessionHandle sessionHandle, String statement, - Map confOverlay) throws HiveSQLException; - - /* (non-Javadoc) - * @see org.apache.hive.service.cli.ICLIService#executeStatementAsync(org.apache.hive.service.cli.SessionHandle, - * java.lang.String, java.util.Map) - */ - @Override - public abstract OperationHandle executeStatementAsync(SessionHandle sessionHandle, String statement, - Map confOverlay) throws HiveSQLException; - - /* (non-Javadoc) - * @see org.apache.hive.service.cli.ICLIService#getTypeInfo(org.apache.hive.service.cli.SessionHandle) - */ - @Override - public abstract OperationHandle getTypeInfo(SessionHandle sessionHandle) throws HiveSQLException; - - /* (non-Javadoc) - * @see org.apache.hive.service.cli.ICLIService#getCatalogs(org.apache.hive.service.cli.SessionHandle) - */ - @Override - public abstract OperationHandle getCatalogs(SessionHandle sessionHandle) throws HiveSQLException; - - /* (non-Javadoc) - * @see org.apache.hive.service.cli.ICLIService#getSchemas(org.apache.hive.service.cli.SessionHandle, java.lang.String, java.lang.String) - */ - @Override - public abstract OperationHandle getSchemas(SessionHandle sessionHandle, String catalogName, - String schemaName) throws HiveSQLException; - - /* (non-Javadoc) - * @see org.apache.hive.service.cli.ICLIService#getTables(org.apache.hive.service.cli.SessionHandle, java.lang.String, java.lang.String, java.lang.String, java.util.List) - */ - @Override - public abstract OperationHandle getTables(SessionHandle sessionHandle, String catalogName, - String schemaName, String tableName, List tableTypes) throws HiveSQLException; - - /* (non-Javadoc) - * @see org.apache.hive.service.cli.ICLIService#getTableTypes(org.apache.hive.service.cli.SessionHandle) - */ - @Override - public abstract OperationHandle getTableTypes(SessionHandle sessionHandle) throws HiveSQLException; - - /* (non-Javadoc) - * @see org.apache.hive.service.cli.ICLIService#getColumns(org.apache.hive.service.cli.SessionHandle, java.lang.String, java.lang.String, java.lang.String, java.lang.String) - */ - @Override - public abstract OperationHandle getColumns(SessionHandle sessionHandle, String catalogName, - String schemaName, String tableName, String columnName) throws HiveSQLException; - - /* (non-Javadoc) - * @see org.apache.hive.service.cli.ICLIService#getFunctions(org.apache.hive.service.cli.SessionHandle, java.lang.String) - */ - @Override - public abstract OperationHandle getFunctions(SessionHandle sessionHandle, - String catalogName, String schemaName, String functionName) - throws HiveSQLException; - - /* (non-Javadoc) - * @see org.apache.hive.service.cli.ICLIService#getOperationStatus(org.apache.hive.service.cli.OperationHandle) - */ - @Override - public abstract OperationState getOperationStatus(OperationHandle opHandle) throws HiveSQLException; - - /* (non-Javadoc) - * @see org.apache.hive.service.cli.ICLIService#cancelOperation(org.apache.hive.service.cli.OperationHandle) - */ - @Override - public abstract void cancelOperation(OperationHandle opHandle) throws HiveSQLException; - - /* (non-Javadoc) - * @see org.apache.hive.service.cli.ICLIService#closeOperation(org.apache.hive.service.cli.OperationHandle) - */ - @Override - public abstract void closeOperation(OperationHandle opHandle) throws HiveSQLException; - - /* (non-Javadoc) - * @see org.apache.hive.service.cli.ICLIService#getResultSetMetadata(org.apache.hive.service.cli.OperationHandle) - */ - @Override - public abstract TableSchema getResultSetMetadata(OperationHandle opHandle) throws HiveSQLException; - - /* (non-Javadoc) - * @see org.apache.hive.service.cli.ICLIService#fetchResults(org.apache.hive.service.cli.OperationHandle, org.apache.hive.service.cli.FetchOrientation, long) - */ - @Override - public abstract RowSet fetchResults(OperationHandle opHandle, FetchOrientation orientation, long maxRows) - throws HiveSQLException; - - /* (non-Javadoc) * @see org.apache.hive.service.cli.ICLIService#fetchResults(org.apache.hive.service.cli.OperationHandle) */ @Override diff --git a/service/src/java/org/apache/hive/service/cli/EmbeddedCLIServiceClient.java b/service/src/java/org/apache/hive/service/cli/EmbeddedCLIServiceClient.java index 9dca874..8abdce9 100644 --- a/service/src/java/org/apache/hive/service/cli/EmbeddedCLIServiceClient.java +++ b/service/src/java/org/apache/hive/service/cli/EmbeddedCLIServiceClient.java @@ -151,7 +151,7 @@ public OperationHandle getFunctions(SessionHandle sessionHandle, * @see org.apache.hive.service.cli.CLIServiceClient#getOperationStatus(org.apache.hive.service.cli.OperationHandle) */ @Override - public OperationState getOperationStatus(OperationHandle opHandle) throws HiveSQLException { + public OperationStatus getOperationStatus(OperationHandle opHandle) throws HiveSQLException { return cliService.getOperationStatus(opHandle); } diff --git a/service/src/java/org/apache/hive/service/cli/ICLIService.java b/service/src/java/org/apache/hive/service/cli/ICLIService.java index f647ce6..2b1712d 100644 --- a/service/src/java/org/apache/hive/service/cli/ICLIService.java +++ b/service/src/java/org/apache/hive/service/cli/ICLIService.java @@ -72,7 +72,7 @@ public abstract OperationHandle getFunctions(SessionHandle sessionHandle, String catalogName, String schemaName, String functionName) throws HiveSQLException; - public abstract OperationState getOperationStatus(OperationHandle opHandle) + public abstract OperationStatus getOperationStatus(OperationHandle opHandle) throws HiveSQLException; public abstract void cancelOperation(OperationHandle opHandle) diff --git a/service/src/java/org/apache/hive/service/cli/OperationStatus.java b/service/src/java/org/apache/hive/service/cli/OperationStatus.java new file mode 100644 index 0000000..ac7532b --- /dev/null +++ b/service/src/java/org/apache/hive/service/cli/OperationStatus.java @@ -0,0 +1,55 @@ +/** + * 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.hive.service.cli; + +import org.apache.hive.service.cli.thrift.TOperationStatus; + +/** + * OperationStatus. + * + */ +public class OperationStatus { + + private final OperationState state; + private final HiveSQLException runException; + + public OperationStatus(OperationState state, HiveSQLException runException) { + this.state = state; + this.runException = runException; + } + + public OperationState getState() { + return state; + } + + public HiveSQLException getRunException() { + return runException; + } + + public TOperationStatus toTOperationStatus() { + TOperationStatus tOperationStatus = new TOperationStatus(); + tOperationStatus.setOperationState(state.toTOperationState()); + if (runException != null) { + tOperationStatus.setSqlState(runException.getSQLState()); + tOperationStatus.setErrorCode(runException.getErrorCode()); + tOperationStatus.setErrorMessage(runException.getMessage()); + } + return tOperationStatus; + } +} \ No newline at end of file diff --git a/service/src/java/org/apache/hive/service/cli/operation/Operation.java b/service/src/java/org/apache/hive/service/cli/operation/Operation.java index 6f4b8dc..d66627e 100644 --- a/service/src/java/org/apache/hive/service/cli/operation/Operation.java +++ b/service/src/java/org/apache/hive/service/cli/operation/Operation.java @@ -70,6 +70,10 @@ public OperationState getState() { return state; } + public HiveSQLException getRunException() { + return null; + } + public boolean hasResultSet() { return hasResultSet; } diff --git a/service/src/java/org/apache/hive/service/cli/operation/OperationManager.java b/service/src/java/org/apache/hive/service/cli/operation/OperationManager.java index bcdb67f..9d71afb 100644 --- a/service/src/java/org/apache/hive/service/cli/operation/OperationManager.java +++ b/service/src/java/org/apache/hive/service/cli/operation/OperationManager.java @@ -144,6 +144,10 @@ public OperationState getOperationState(OperationHandle opHandle) throws HiveSQL return getOperation(opHandle).getState(); } + public HiveSQLException getOperationRunException(OperationHandle opHandle) throws HiveSQLException { + return getOperation(opHandle).getRunException(); + } + public void cancelOperation(OperationHandle opHandle) throws HiveSQLException { getOperation(opHandle).cancel(); } diff --git a/service/src/java/org/apache/hive/service/cli/operation/SQLOperation.java b/service/src/java/org/apache/hive/service/cli/operation/SQLOperation.java index 4ee1b74..a57e29d 100644 --- a/service/src/java/org/apache/hive/service/cli/operation/SQLOperation.java +++ b/service/src/java/org/apache/hive/service/cli/operation/SQLOperation.java @@ -67,7 +67,8 @@ private Schema mResultSchema = null; private SerDe serde = null; private final boolean runAsync; - private Future backgroundHandle; + private volatile Future backgroundHandle; + private volatile HiveSQLException runException = null; public SQLOperation(HiveSession parentSession, String statement, Map confOverlay, boolean runInBackground) { @@ -76,20 +77,11 @@ public SQLOperation(HiveSession parentSession, String statement, Map