Index: jdbc/src/java/org/apache/hive/jdbc/HiveQueryResultSet.java =================================================================== --- jdbc/src/java/org/apache/hive/jdbc/HiveQueryResultSet.java +++ jdbc/src/java/org/apache/hive/jdbc/HiveQueryResultSet.java @@ -51,6 +51,7 @@ private TCLIService.Iface client; private TOperationHandle stmtHandle; + private HiveStatement hiveStatement; private TSessionHandle sessHandle; private int maxRows; private int fetchSize; @@ -66,6 +67,7 @@ private TCLIService.Iface client = null; private TOperationHandle stmtHandle = null; private TSessionHandle sessHandle = null; + private HiveStatement hiveStatement = null; /** * Sets the limit for the maximum number of rows that any ResultSet object produced by this @@ -94,6 +96,11 @@ return this; } + public Builder setHiveStatement(HiveStatement hiveStatement) { + this.hiveStatement = hiveStatement; + return this; + } + public Builder setMaxRows(int maxRows) { this.maxRows = maxRows; return this; @@ -128,6 +135,7 @@ this.stmtHandle = builder.stmtHandle; this.sessHandle = builder.sessHandle; this.fetchSize = builder.fetchSize; + this.hiveStatement = builder.hiveStatement; columnNames = new ArrayList(); columnTypes = new ArrayList(); if (builder.retrieveSchema) { @@ -196,9 +204,13 @@ @Override public void close() throws SQLException { + if (hiveStatement != null) { + hiveStatement.closeClientOperation(); + } // Need reset during re-open when needed client = null; stmtHandle = null; + hiveStatement = null; sessHandle = null; isClosed = true; } Index: jdbc/src/java/org/apache/hive/jdbc/HiveStatement.java =================================================================== --- jdbc/src/java/org/apache/hive/jdbc/HiveStatement.java +++ jdbc/src/java/org/apache/hive/jdbc/HiveStatement.java @@ -43,7 +43,7 @@ */ public class HiveStatement implements java.sql.Statement { private TCLIService.Iface client; - private TOperationHandle stmtHandle; + private TOperationHandle stmtHandle = null; private final TSessionHandle sessHandle; Map sessConf = new HashMap(); private int fetchSize = 50; @@ -102,6 +102,10 @@ throw new SQLException("Can't cancel after statement has been closed"); } + if (stmtHandle == null) { + return; + } + TCancelOperationReq cancelReq = new TCancelOperationReq(); cancelReq.setOperationHandle(stmtHandle); try { @@ -134,7 +138,7 @@ warningChain = null; } - private void closeClientOperation() throws SQLException { + void closeClientOperation() throws SQLException { try { if (stmtHandle != null) { TCloseOperationReq closeReq = new TCloseOperationReq(); @@ -149,17 +153,19 @@ } stmtHandle = null; } + /* * (non-Javadoc) * * @see java.sql.Statement#close() */ - public void close() throws SQLException { if (isClosed) { return; } - closeClientOperation(); + if (stmtHandle != null) { + closeClientOperation(); + } client = null; resultSet = null; isClosed = true; @@ -182,7 +188,10 @@ } try { - closeClientOperation(); + if (stmtHandle != null) { + closeClientOperation(); + } + TExecuteStatementReq execReq = new TExecuteStatementReq(sessHandle, sql); execReq.setConfOverlay(sessConf); TExecuteStatementResp execResp = client.ExecuteStatement(execReq); @@ -236,7 +245,7 @@ return false; } resultSet = new HiveQueryResultSet.Builder().setClient(client).setSessionHandle(sessHandle) - .setStmtHandle(stmtHandle).setMaxRows(maxRows).setFetchSize(fetchSize) + .setStmtHandle(stmtHandle).setHiveStatement(this).setMaxRows(maxRows).setFetchSize(fetchSize) .build(); return true; } Index: jdbc/src/test/org/apache/hive/jdbc/TestJdbcDriver2.java =================================================================== --- jdbc/src/test/org/apache/hive/jdbc/TestJdbcDriver2.java +++ jdbc/src/test/org/apache/hive/jdbc/TestJdbcDriver2.java @@ -130,7 +130,7 @@ stmt.execute("create table " + partitionedTableName + " (under_col int, value string) comment '"+partitionedTableComment - +"' partitioned by (" + partitionedColumnName + " STRING)"); + +"' partitioned by (" + partitionedColumnName + " STRING)"); // load data stmt.execute("load data local inpath '" @@ -145,7 +145,7 @@ fail(ex.toString()); } - stmt.execute("create table " + dataTypeTableName + stmt.execute("create table " + dataTypeTableName + " (c1 int, c2 boolean, c3 double, c4 string," + " c5 array, c6 map, c7 map," + " c8 struct," @@ -158,7 +158,7 @@ + " c18 decimal, " + " c19 binary, " + " c20 date) comment'" + dataTypeTableComment - +"' partitioned by (dt STRING)"); + +"' partitioned by (dt STRING)"); stmt.execute("load data local inpath '" + dataTypeDataFilePath.toString() + "' into table " + dataTypeTableName @@ -173,7 +173,7 @@ // create view stmt.execute("create view " + viewName + " comment '"+viewComment - +"' as select * from "+ tableName); + +"' as select * from "+ tableName); } @Override @@ -205,7 +205,7 @@ public void testBadURL() throws Exception { checkBadUrl("jdbc:hive2://localhost:10000;principal=test"); checkBadUrl("jdbc:hive2://localhost:10000;" + - "principal=hive/HiveServer2Host@YOUR-REALM.COM"); + "principal=hive/HiveServer2Host@YOUR-REALM.COM"); checkBadUrl("jdbc:hive2://localhost:10000test"); } @@ -270,7 +270,7 @@ ResultSet res = stmt.executeQuery( "explain select c1, c2, c3, c4, c5 as a, c6, c7, c8, c9, c10, c11, c12, " + - "c1*2, sentences(null, null, null) as b from " + dataTypeTableName + " limit 1"); + "c1*2, sentences(null, null, null) as b from " + dataTypeTableName + " limit 1"); ResultSetMetaData md = res.getMetaData(); assertEquals(md.getColumnCount(), 1); // only one result column @@ -288,7 +288,7 @@ + " and date '2012-01-01' = date ?" + " ) t select '2011-03-25' ddate,'China',true bv, 10 num limit 10"; - /////////////////////////////////////////////// + /////////////////////////////////////////////// //////////////////// correct testcase ////////////////////////////////////////////// try { @@ -340,7 +340,7 @@ fail(e.toString()); } - /////////////////////////////////////////////// + /////////////////////////////////////////////// //////////////////// other failure testcases ////////////////////////////////////////////// // set nothing for prepared sql @@ -506,15 +506,13 @@ public void testNullResultSet() throws Exception { List setupQueries = new ArrayList(); String testQuery; - boolean hasResultSet; Statement stmt = con.createStatement(); // -select- should return a ResultSet try { stmt.executeQuery("select * from " + tableName); System.out.println("select: success"); - } - catch(SQLException e) { + } catch(SQLException e) { failWithExceptionMsg(e); } @@ -540,6 +538,39 @@ stmt.close(); } + public void testCloseResultSet() throws Exception { + Statement stmt = con.createStatement(); + + // execute query, ignore exception if any + ResultSet res = stmt.executeQuery("select * from " + tableName); + // close ResultSet, ignore exception if any + res.close(); + // A statement should be open even after ResultSet#close + assertFalse(stmt.isClosed()); + // A Statement#cancel after ResultSet#close should be a no-op + try { + stmt.cancel(); + } catch(SQLException e) { + failWithExceptionMsg(e); + } + stmt.close(); + + stmt = con.createStatement(); + // execute query, ignore exception if any + res = stmt.executeQuery("select * from " + tableName); + // close ResultSet, ignore exception if any + res.close(); + // A Statement#execute after ResultSet#close should be fine too + try { + stmt.executeQuery("select * from " + tableName); + } catch(SQLException e) { + failWithExceptionMsg(e); + } + // A Statement#close after ResultSet#close should close the statement + stmt.close(); + assertTrue(stmt.isClosed()); + } + public void testDataTypes() throws Exception { Statement stmt = con.createStatement(); @@ -673,7 +704,7 @@ ResultSetMetaData meta = res.getMetaData(); int expectedColCount = isPartitionTable ? 3 : 2; assertEquals( - "Unexpected column count", expectedColCount, meta.getColumnCount()); + "Unexpected column count", expectedColCount, meta.getColumnCount()); boolean moreRow = res.next(); while (moreRow) { @@ -740,7 +771,7 @@ doTestErrorCase("SELECT invalid_column FROM " + tableName, "Invalid table alias or column reference", invalidSyntaxSQLState, 10004); doTestErrorCase("SELECT invalid_function(under_col) FROM " + tableName, - "Invalid function", invalidSyntaxSQLState, 10011); + "Invalid function", invalidSyntaxSQLState, 10011); // TODO: execute errors like this currently don't return good error // codes and messages. This should be fixed. @@ -810,17 +841,17 @@ private void getTablesTest(String tableTypeName, String viewTypeName) throws SQLException { Map tests = new HashMap(); tests.put("test%jdbc%", new Object[]{"testhivejdbcdriver_table" - , "testhivejdbcdriverpartitionedtable" - , "testhivejdbcdriverview"}); + , "testhivejdbcdriverpartitionedtable" + , "testhivejdbcdriverview"}); tests.put("%jdbcdriver\\_table", new Object[]{"testhivejdbcdriver_table"}); tests.put("testhivejdbcdriver\\_table", new Object[]{"testhivejdbcdriver_table"}); tests.put("test_ivejdbcdri_er\\_table", new Object[]{"testhivejdbcdriver_table"}); tests.put("test_ivejdbcdri_er_table", new Object[]{"testhivejdbcdriver_table"}); tests.put("test_ivejdbcdri_er%table", new Object[]{ "testhivejdbcdriver_table", "testhivejdbcdriverpartitionedtable" }); tests.put("%jdbc%", new Object[]{ "testhivejdbcdriver_table" - , "testhivejdbcdriverpartitionedtable" - , "testhivejdbcdriverview"}); + , "testhivejdbcdriverpartitionedtable" + , "testhivejdbcdriverview"}); tests.put("", new Object[]{}); for (String checkPattern: tests.keySet()) { @@ -854,7 +885,7 @@ // only ask for the views. ResultSet rs = (ResultSet)con.getMetaData().getTables("default", null, null - , new String[]{viewTypeName}); + , new String[]{viewTypeName}); int cnt=0; while (rs.next()) { cnt++; @@ -881,7 +912,7 @@ assertTrue(rs.next()); assertEquals("default", rs.getString(1)); -// assertNull(rs.getString(2)); + // assertNull(rs.getString(2)); assertFalse(rs.next()); rs.close(); @@ -930,7 +961,7 @@ tests.put(new String[]{"testhiveJDBC%", null}, 7); tests.put(new String[]{"%jdbcdriver\\_table", null}, 2); tests.put(new String[]{"%jdbcdriver\\_table%", "under\\_col"}, 1); -// tests.put(new String[]{"%jdbcdriver\\_table%", "under\\_COL"}, 1); + // tests.put(new String[]{"%jdbcdriver\\_table%", "under\\_COL"}, 1); tests.put(new String[]{"%jdbcdriver\\_table%", "under\\_co_"}, 1); tests.put(new String[]{"%jdbcdriver\\_table%", "under_col"}, 1); tests.put(new String[]{"%jdbcdriver\\_table%", "und%"}, 1); @@ -950,16 +981,16 @@ String columnname = rs.getString("COLUMN_NAME"); int ordinalPos = rs.getInt("ORDINAL_POSITION"); switch(cnt) { - case 0: - assertEquals("Wrong column name found", "under_col", columnname); - assertEquals("Wrong ordinal position found", ordinalPos, 1); - break; - case 1: - assertEquals("Wrong column name found", "value", columnname); - assertEquals("Wrong ordinal position found", ordinalPos, 2); - break; - default: - break; + case 0: + assertEquals("Wrong column name found", "under_col", columnname); + assertEquals("Wrong ordinal position found", ordinalPos, 1); + break; + case 1: + assertEquals("Wrong column name found", "value", columnname); + assertEquals("Wrong ordinal position found", ordinalPos, 2); + break; + default: + break; } cnt++; } @@ -973,7 +1004,7 @@ */ public void testMetaDataGetColumnsMetaData() throws SQLException { ResultSet rs = (ResultSet)con.getMetaData().getColumns(null, null - , "testhivejdbcdriver\\_table", null); + , "testhivejdbcdriver\\_table", null); ResultSetMetaData rsmd = rs.getMetaData(); @@ -1026,7 +1057,7 @@ } } } - */ + */ public void testDescribeTable() throws SQLException { Statement stmt = con.createStatement(); @@ -1069,7 +1100,7 @@ ResultSet res = stmt.executeQuery( "select c1, c2, c3, c4, c5 as a, c6, c7, c8, c9, c10, c11, c12, " + - "c1*2, sentences(null, null, null) as b, c17, c18, c20 from " + dataTypeTableName + + "c1*2, sentences(null, null, null) as b, c17, c18, c20 from " + dataTypeTableName + " limit 1"); ResultSetMetaData meta = res.getMetaData(); @@ -1293,10 +1324,10 @@ // [url] [host] [port] [db] private static final String[][] URL_PROPERTIES = new String[][] { - {"jdbc:hive2://", "", "", "default"}, - {"jdbc:hive2://localhost:10001/default", "localhost", "10001", "default"}, - {"jdbc:hive2://localhost/notdefault", "localhost", "10000", "notdefault"}, - {"jdbc:hive2://foo:1243", "foo", "1243", "default"}}; + {"jdbc:hive2://", "", "", "default"}, + {"jdbc:hive2://localhost:10001/default", "localhost", "10001", "default"}, + {"jdbc:hive2://localhost/notdefault", "localhost", "10000", "notdefault"}, + {"jdbc:hive2://foo:1243", "foo", "1243", "default"}}; public void testDriverProperties() throws SQLException { HiveDriver driver = new HiveDriver();