001: /*
002: *
003: * Derby - Class StatementTest
004: *
005: * Licensed to the Apache Software Foundation (ASF) under one or more
006: * contributor license agreements. See the NOTICE file distributed with
007: * this work for additional information regarding copyright ownership.
008: * The ASF licenses this file to you under the Apache License, Version 2.0
009: * (the "License"); you may not use this file except in compliance with
010: * the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
017: * either express or implied. See the License for the specific
018: * language governing permissions and limitations under the License.
019: */
020:
021: package org.apache.derbyTesting.functionTests.tests.jdbc4;
022:
023: import org.apache.derbyTesting.functionTests.util.SQLStateConstants;
024: import org.apache.derbyTesting.junit.BaseJDBCTestCase;
025:
026: import junit.framework.*;
027:
028: import java.sql.*;
029:
030: /**
031: * Tests for new methods added for Statement in JDBC4.
032: */
033: public class StatementTest extends BaseJDBCTestCase {
034:
035: /** Default statement used by the tests. */
036: private Statement stmt = null;
037:
038: /**
039: * Create a new test with the given name.
040: *
041: * @param name name of the test.
042: */
043: public StatementTest(String name) {
044: super (name);
045: }
046:
047: /**
048: * Create default connection and statement.
049: *
050: * @throws SQLException if setAutoCommit, createStatement or
051: * BaseJDBCTestCase.getConnection fails.
052: */
053: protected void setUp() throws SQLException {
054: getConnection().setAutoCommit(false);
055: // Create a default statement.
056: stmt = createStatement();
057: assertFalse("First statement must be open initially", stmt
058: .isClosed());
059: }
060:
061: /**
062: * Close default connection and statement if necessary.
063: *
064: * @throws SQLException if a database access exception occurs.
065: */
066: protected void tearDown() throws Exception {
067: // Close default statement
068: if (stmt != null) {
069: stmt.close();
070: }
071:
072: super .tearDown();
073: }
074:
075: /**
076: * Check that <code>isClosed</code> returns <code>true</code> after
077: * the statement has been explicitly closed.
078: */
079: public void testIsClosedBasic() throws SQLException {
080: ResultSet rs = stmt
081: .executeQuery("select count(*) from stmtTable");
082: assertFalse("Statement should still be open", stmt.isClosed());
083: rs.close();
084: assertFalse(
085: "Statement should be open after ResultSet has been "
086: + "closed", stmt.isClosed());
087: stmt.close();
088: assertTrue(
089: "Statement should be closed, close() has been called",
090: stmt.isClosed());
091: }
092:
093: /**
094: * Test that creating two statements on the same connection does not
095: * cause side effects on the statements.
096: */
097: public void testIsClosedWithTwoStatementsOnSameConnection()
098: throws SQLException {
099: // Create a second statement on the default connection.
100: Statement stmt2 = createStatement();
101: assertFalse("Second statement must be open initially", stmt2
102: .isClosed());
103: assertFalse("First statement should not be closed when "
104: + "creating a second statement", stmt.isClosed());
105: ResultSet rs = stmt2
106: .executeQuery("select count(*) from stmtTable");
107: assertFalse("Second statement should be open after call to "
108: + "execute()", stmt2.isClosed());
109: assertFalse("First statement should be open after call to "
110: + "second statment's execute()", stmt.isClosed());
111: stmt2.close();
112: assertTrue("Second statement should be closed, close() has "
113: + "been called!", stmt2.isClosed());
114: assertFalse("First statement should be open after call to "
115: + "second statment's close()", stmt.isClosed());
116: }
117:
118: /**
119: * Test that the two statements created on the connection are closed
120: * when the connection itself is closed.
121: */
122: public void testIsClosedWhenClosingConnection() throws SQLException {
123: // Create an extra statement for good measure.
124: Statement stmt2 = createStatement();
125: assertFalse("Second statement must be open initially", stmt2
126: .isClosed());
127: // Exeute something on it, as opposed to the default statement.
128: stmt2.execute("select count(*) from stmtTable");
129: assertFalse("Second statement should be open after call to "
130: + "execute()", stmt2.isClosed());
131: // Close the connection. We must commit/rollback first, or else a
132: // "Invalid transaction state" exception is raised.
133: rollback();
134: Connection con = getConnection();
135: con.close();
136: assertTrue("Connection should be closed after close()", con
137: .isClosed());
138: assertTrue("First statement should be closed, as parent "
139: + "connection has been closed", stmt.isClosed());
140: assertTrue("Second statement should be closed, as parent "
141: + "connection has been closed", stmt2.isClosed());
142: }
143:
144: /**
145: * Check the state of the statement when the connection is first attempted
146: * closed when in an invalid transaction state, then closed after a
147: * commit. According to the JDBC 4 API documentation: </i>"It is strongly
148: * recommended that an application explictly commits or rolls back an
149: * active transaction prior to calling the close method. If the close
150: * method is called and there is an active transaction,
151: * the results are implementation-defined."</i>
152: * Derby throws an exception and keeps the connection open.
153: */
154: public void testIsClosedWhenClosingConnectionInInvalidState()
155: throws SQLException {
156: stmt.executeQuery("select count(*) from stmtTable");
157: // Connection should now be in an invalid transaction state.
158: Connection con = stmt.getConnection();
159: try {
160: con.close();
161: fail("Invalid transaction state exception was not thrown");
162: } catch (SQLException sqle) {
163: // The SQL State is incorrect in the embedded client, see
164: // JIRA id DERBY-1168
165: String expectedState;
166: if (this .usingDerbyNetClient())
167: expectedState = SQLStateConstants.INVALID_TRANSACTION_STATE_ACTIVE_SQL_TRANSACTION;
168: else
169: expectedState = SQLStateConstants.INVALID_TRANSACTION_STATE_NO_SUBCLASS;
170:
171: if (!expectedState.equals(sqle.getSQLState())) {
172: System.err
173: .println("ERROR: Unexpected SQL State encountered; "
174: + "got "
175: + sqle.getSQLState()
176: + ", expected "
177: + expectedState
178: + ". Unexpected exception message is "
179: + sqle.getMessage());
180:
181: throw sqle;
182: }
183: }
184: assertFalse("Statement should still be open, because "
185: + "Connection.close() failed", stmt.isClosed());
186: assertFalse("Connection should still be open", con.isClosed());
187: // Do a commit here, since we do a rollback in another test.
188: con.commit();
189: con.close();
190: assertTrue("Connection should be closed after close()", con
191: .isClosed());
192: assertTrue("Statement should be closed, because "
193: + "the connection has been closed", stmt.isClosed());
194: stmt.close();
195: assertTrue("Statement should still be closed", stmt.isClosed());
196: }
197:
198: /**
199: * Execute a query on a statement after the parent connection has been
200: * closed.
201: */
202: public void testStatementExecuteAfterConnectionClose()
203: throws SQLException {
204: Connection con = stmt.getConnection();
205: con.close();
206: assertTrue("Connection should be closed after close()", con
207: .isClosed());
208: try {
209: stmt.executeQuery("select count(*) from stmtTable");
210: } catch (SQLException sqle) {
211: assertEquals(
212: "Unexpected SQL state for performing "
213: + "operations on a closed statement.",
214: SQLStateConstants.CONNECTION_EXCEPTION_CONNECTION_DOES_NOT_EXIST,
215: sqle.getSQLState());
216: }
217: assertTrue("Statement should be closed, because "
218: + "the connection has been closed", stmt.isClosed());
219: }
220:
221: public void testIsWrapperForStatement() throws SQLException {
222: assertTrue(stmt.isWrapperFor(Statement.class));
223: }
224:
225: public void testIsNotWrapperForPreparedStatement()
226: throws SQLException {
227: assertFalse(stmt.isWrapperFor(PreparedStatement.class));
228: }
229:
230: public void testIsNotWrapperForCallableStatement()
231: throws SQLException {
232: assertFalse(stmt.isWrapperFor(CallableStatement.class));
233: }
234:
235: public void testIsNotWrapperForResultSet() throws SQLException {
236: assertFalse(stmt.isWrapperFor(ResultSet.class));
237: }
238:
239: public void testUnwrapStatement() throws SQLException {
240: Statement stmt2 = stmt.unwrap(Statement.class);
241: assertSame("Unwrap returned wrong object.", stmt, stmt2);
242: }
243:
244: public void testUnwrapPreparedStatement() {
245: try {
246: PreparedStatement ps = stmt.unwrap(PreparedStatement.class);
247: fail("Unwrap didn't fail.");
248: } catch (SQLException e) {
249: assertSQLState("XJ128", e);
250: }
251: }
252:
253: public void testUnwrapCallableStatement() {
254: try {
255: CallableStatement cs = stmt.unwrap(CallableStatement.class);
256: fail("Unwrap didn't fail.");
257: } catch (SQLException e) {
258: assertSQLState("XJ128", e);
259: }
260: }
261:
262: public void testUnwrapResultSet() throws SQLException {
263: try {
264: ResultSet rs = stmt.unwrap(ResultSet.class);
265: fail("Unwrap didn't fail.");
266: } catch (SQLException e) {
267: assertSQLState("XJ128", e);
268: }
269: }
270:
271: /**
272: * Tests isPoolable, setPoolable, and the default poolability.
273: */
274: public void testPoolable() throws SQLException {
275: assertFalse("Statement cannot be poolable by default", stmt
276: .isPoolable());
277: stmt.setPoolable(true);
278: assertTrue("Statement must be poolable", stmt.isPoolable());
279:
280: stmt.setPoolable(false);
281: assertFalse("Statement cannot be poolable", stmt.isPoolable());
282: }
283:
284: /**
285: * Create test suite for StatementTest.
286: */
287: public static Test suite() {
288: TestSuite suite = new TestSuite("StatementTest suite");
289: // Decorate test suite with a TestSetup class.
290: suite.addTest(new StatementTestSetup(new TestSuite(
291: StatementTest.class)));
292:
293: return suite;
294: }
295:
296: } // End class StatementTest
|