Author: loleary
Date: 2009-05-01 10:18:00 -0400 (Fri, 01 May 2009)
New Revision: 854
Added:
trunk/client-jdbc/src/test/java/com/metamatrix/jdbc/TestMMPreparedStatement.java
Modified:
trunk/client-jdbc/src/main/java/com/metamatrix/jdbc/MMPreparedStatement.java
Log:
TEIID-521: Added clearBatch() method to MMPreparedStatement to override method from
MMStatement.
Fixed type-safety compiler warnings caused by the use of List without a type in
MMPreparedStatement.
Reviewed By: rreddy
Modified: trunk/client-jdbc/src/main/java/com/metamatrix/jdbc/MMPreparedStatement.java
===================================================================
---
trunk/client-jdbc/src/main/java/com/metamatrix/jdbc/MMPreparedStatement.java 2009-04-30
21:31:54 UTC (rev 853)
+++
trunk/client-jdbc/src/main/java/com/metamatrix/jdbc/MMPreparedStatement.java 2009-05-01
14:18:00 UTC (rev 854)
@@ -95,7 +95,7 @@
private Calendar serverCalendar;
/**
- * Factory Constuctor
+ * Factory Constructor
* @param connection
* @param sql
* @param resultSetType
@@ -139,6 +139,18 @@
}
/**
+ * Makes the set of commands in the current batch empty.
+ *
+ * @throws SQLException if a database access error occurs or the
+ * driver does not support batch statements
+ */
+ public void clearBatch() throws SQLException {
+ if (batchParameterList != null ) {
+ batchParameterList.clear();
+ }
+ }
+
+ /**
* <p>Clears the values set for the PreparedStatement object's IN
parameters and
* releases the resources used by those values. In general, parameter values
* remain in force for repeated use of statement.
@@ -545,11 +557,12 @@
parameterMap = new TreeMap<Integer, Object>();
}
+ Object val = null;
if (serverCalendar != null && value instanceof java.util.Date) {
- value = TimestampWithTimezone.create((java.util.Date)value,
getDefaultCalendar().getTimeZone(), serverCalendar, value.getClass());
- }
+ val = TimestampWithTimezone.create((java.util.Date)value,
getDefaultCalendar().getTimeZone(), serverCalendar, value.getClass());
+ } else val = value;
- parameterMap.put(new Integer(parameterIndex), value);
+ parameterMap.put(new Integer(parameterIndex), val);
}
/**
@@ -645,18 +658,18 @@
setObject(parameterIndex, x);
}
- List getParameterValuesList() {
+ List<List<Object>> getParameterValuesList() {
if(batchParameterList == null || batchParameterList.isEmpty()){
- return Collections.EMPTY_LIST;
+ return Collections.emptyList();
}
- return new ArrayList(batchParameterList);
+ return new ArrayList<List<Object>>(batchParameterList);
}
- List getParameterValues() {
+ List<Object> getParameterValues() {
if(parameterMap == null || parameterMap.isEmpty()){
- return Collections.EMPTY_LIST;
+ return Collections.emptyList();
}
- return new ArrayList(parameterMap.values());
+ return new ArrayList<Object>(parameterMap.values());
}
/* (non-Javadoc)
Added: trunk/client-jdbc/src/test/java/com/metamatrix/jdbc/TestMMPreparedStatement.java
===================================================================
--- trunk/client-jdbc/src/test/java/com/metamatrix/jdbc/TestMMPreparedStatement.java
(rev 0)
+++
trunk/client-jdbc/src/test/java/com/metamatrix/jdbc/TestMMPreparedStatement.java 2009-05-01
14:18:00 UTC (rev 854)
@@ -0,0 +1,340 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package com.metamatrix.jdbc;
+
+import static org.junit.Assert.*;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.TimeZone;
+
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.mockito.Mockito;
+
+import com.metamatrix.common.comm.api.ServerConnection;
+import com.metamatrix.dqp.client.ClientSideDQP;
+import com.metamatrix.dqp.client.ResultsFuture;
+import com.metamatrix.dqp.message.RequestMessage;
+import com.metamatrix.dqp.message.ResultsMessage;
+import com.metamatrix.platform.security.api.LogonResult;
+
+/**
+ * Test case to validate general operations on an <code>MMPreparedStatement
+ * </code>
+ */
+public class TestMMPreparedStatement {
+
+ /**
+ * Test that <code>MMPreparedStatement</code>'s
<code>execute()</code> method
+ * will throw a <code>MMSQLException</code> if a connection does not exist.
+ *
+ * @throws Exception
+ */
+ @Test(expected=MMSQLException.class) public void testUpdateException() throws Exception
{
+ MMPreparedStatement statement = getMMPreparedStatement("delete from table");
//$NON-NLS-1$
+ statement.execute();
+ }
+
+ /**
+ * Verify that the <code>executeBatch()</code> method of <code>
+ * MMPreparedStatement</code> is resulting in the correct command,
+ * parameter values for each command of the batch, and the request type
+ * are being set in the request message that would normally be sent to the
+ * server.
+ *
+ * @throws Exception
+ */
+ @Test public void testBatchedUpdateExecution() throws Exception {
+ // Build up a fake connection instance for use with the prepared statement
+ MMConnection conn = Mockito.mock(MMConnection.class);
+ ClientSideDQP dqp = Mockito.mock(ClientSideDQP.class);
+ ServerConnection serverConn = Mockito.mock(ServerConnection.class);
+ LogonResult logonResult = Mockito.mock(LogonResult.class);
+
+ // stub methods
+ Mockito.stub(conn.getServerConnection()).toReturn(serverConn);
+ Mockito.stub(serverConn.getLogonResult()).toReturn(logonResult);
+ Mockito.stub(logonResult.getTimeZone()).toReturn(TimeZone.getDefault());
+
+ // a dummy result message that is specific to this test case
+ ResultsFuture<ResultsMessage> results = new
ResultsFuture<ResultsMessage>();
+ Mockito.stub(dqp.executeRequest(Matchers.anyLong(),
(RequestMessage)Matchers.anyObject())).toReturn(results);
+ ResultsMessage rm = new ResultsMessage();
+ rm.setResults(new List<?>[] {Arrays.asList(0), Arrays.asList(0),
Arrays.asList(0)});
+ rm.setUpdateResult(true);
+ results.getResultsReceiver().receiveResults(rm);
+ Mockito.stub(conn.getDQP()).toReturn(dqp);
+
+ // some update SQL
+ String sqlCommand = "delete from table where col=?"; //$NON-NLS-1$
+ TestableMMPreparedStatement statement = (TestableMMPreparedStatement)
getMMPreparedStatement(conn, sqlCommand);
+
+ ArrayList<ArrayList<Object>> expectedParameterValues = new
ArrayList<ArrayList<Object>>(3);
+ // Add some batches and their parameter values
+ expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] {
new Integer(1) } ) ) );
+ statement.setInt(1, new Integer(1));
+ statement.addBatch();
+ expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] {
new Integer(2) } ) ) );
+ statement.setInt(1, new Integer(2));
+ statement.addBatch();
+ expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] {
new Integer(3) } ) ) );
+ statement.setInt(1, new Integer(3));
+ statement.addBatch();
+
+ // execute the batch and verify that it matches our dummy results
+ // message set earlier
+ assertTrue(Arrays.equals(new int[] {0, 0, 0}, statement.executeBatch()));
+
+ // Now verify the statement's RequestMessage is what we expect
+ assertEquals("Command does not match", sqlCommand,
statement.requestMessage.getCommandString()); //$NON-NLS-1$
+ assertEquals("Parameter values do not match", expectedParameterValues,
statement.requestMessage.getParameterValues()); //$NON-NLS-1$
+ assertTrue("RequestMessage.isPreparedBatchUpdate should be true",
statement.requestMessage.isPreparedBatchUpdate()); //$NON-NLS-1$
+ assertFalse("RequestMessage.isBatchedUpdate should be false",
statement.requestMessage.isBatchedUpdate()); //$NON-NLS-1$
+ assertFalse("RequestMessage.isCallableStatement should be false",
statement.requestMessage.isCallableStatement()); //$NON-NLS-1$
+ assertTrue("RequestMessage.isPreparedStatement should be true",
statement.requestMessage.isPreparedStatement()); //$NON-NLS-1$
+ }
+
+ /**
+ * Verify that the <code>clearBatch()</code> method of
+ * <code>MMPreparedStatement</code> is clearing the list of batched
+ * commands.
+ * <p>
+ * This is done by first adding command parameter values to the batch and
+ * then invoking the <code>clearBatch()</code> method.
+ *
+ * @throws Exception
+ */
+ @Test public void testClearBatch() throws Exception {
+ MMPreparedStatement statement = getMMPreparedStatement("delete from table where
col=?"); //$NON-NLS-1$
+ // Add some stuff
+ statement.setInt(1, new Integer(1));
+ statement.addBatch();
+ statement.setInt(1, new Integer(2));
+ statement.addBatch();
+ // Make sure something is really there
+ assertTrue("MMPreparedStatement.ParameterValuesList should not be empty",
statement.getParameterValuesList().size() > 0); //$NON-NLS-1$
+ // Now clear it
+ statement.clearBatch();
+ assertTrue("MMPreparedStatement.ParameterValuesList should be empty",
statement.getParameterValuesList().size() == 0); //$NON-NLS-1$
+ }
+
+ /**
+ * Adds additional batches of command parameter values to a prepared
+ * statement after a previous list has been cleared.
+ * <p>
+ * This is done by first adding command parameter values to the batch and
+ * then invoking the <code>clearBatch()</code> method. Then a different
+ * set of command parameter values are added to the existing batch command.
+ * <p>
+ * The expected result is the command parameter list for the batches will
+ * only reflect what was added after <code>clearBatch()</code> was invoked.
+ *
+ * @throws Exception
+ */
+ @Test public void testClearBatchAddBatch() throws Exception {
+ MMPreparedStatement statement = getMMPreparedStatement("delete from table where
col=?"); //$NON-NLS-1$
+
+ statement.setInt(1, new Integer(1));
+ statement.addBatch();
+ statement.setInt(1, new Integer(2));
+ statement.addBatch();
+ // Make sure something is really there
+ assertTrue("MMPreparedStatement.ParameterValuesList should not be empty",
statement.getParameterValuesList().size() > 0); //$NON-NLS-1$
+ // Now clear it
+ statement.clearBatch();
+ // Make sure it is empty now
+ assertTrue("MMPreparedStatement.ParameterValuesList should be empty",
statement.getParameterValuesList().size() == 0); //$NON-NLS-1$
+
+ ArrayList<ArrayList<Object>> expectedParameterValues = new
ArrayList<ArrayList<Object>>(1);
+
+ // Now add something for validation
+ expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] {
new Integer(5) } ) ) );
+ statement.setInt(1, new Integer(5));
+ statement.addBatch();
+ assertEquals("MMPreparedStatement.ParameterValuesList does not match",
expectedParameterValues, statement.getParameterValuesList()); //$NON-NLS-1$
+ }
+
+ /**
+ * Test the <code>addBatch()</code> method of
<code>MMPreparedStatement</code>
+ * to verify that the command parameter values of the batch are added to the
+ * command parameter values list.
+ *
+ * @throws Exception
+ */
+ @Test public void testAddBatch() throws Exception {
+ MMPreparedStatement statement = getMMPreparedStatement("delete from table where
col=?"); //$NON-NLS-1$
+
+ ArrayList<ArrayList<Object>> expectedParameterValues = new
ArrayList<ArrayList<Object>>(1);
+
+ // First we add a single batch
+ expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] {
new Integer(1) } ) ) );
+ statement.setInt(1, new Integer(1));
+ statement.addBatch();
+ assertEquals("MMPreparedStatement.ParameterValuesList does not match",
expectedParameterValues, statement.getParameterValuesList()); //$NON-NLS-1$
+
+ // Now add some more batches just for sanity sake
+ expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] {
new Integer(3) } ) ) );
+ expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] {
new Integer(5) } ) ) );
+ statement.setInt(1, new Integer(3));
+ statement.addBatch();
+ statement.setInt(1, new Integer(5));
+ statement.addBatch();
+ assertEquals("MMPreparedStatement.ParameterValuesList does not match",
expectedParameterValues, statement.getParameterValuesList()); //$NON-NLS-1$
+ }
+
+ /**
+ * Test the <code>addBatch()</code> method of
<code>MMPreparedStatement</code>
+ * using a batch with an empty parameter value list. The test will verify
+ * no failures occur when there are no command parameter values defined
+ * when the <code>addBatch()</code> method is invoked.
+ * <p>
+ * It is valid to add an empty parameter value list to a batch list.
+ * <p>
+ * For example:
+ * <p>
+ * <code>PreparedStatement stmt = conn.prepareStatement(sql);<br \>
+ * stmt.addBatch();<br \>
+ * stmt.addBatch();<br \>
+ * stmt.executeBatch();</code>
+ *
+ * @throws Exception
+ */
+ @Test public void testAddBatchNoParameterValues() throws Exception {
+ MMPreparedStatement statement = getMMPreparedStatement("delete from table where
col=?"); //$NON-NLS-1$
+
+ // This will hold our expected values list
+ ArrayList<ArrayList<Object>> expectedParameterValues = new
ArrayList<ArrayList<Object>>(1);
+
+ // First batch has an empty parameter value list
+ expectedParameterValues.add( new ArrayList<Object>(Collections.emptyList()) );
+
+ // No values have been set so we are adding a batch with an empty
+ // parameter value list
+ statement.addBatch();
+
+ // Second batch contains a parameter value list
+ expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] {
new Integer(1) } ) ) );
+
+ // We now are adding a batch that does have parameter values
+ statement.setInt(1, new Integer(1));
+ statement.addBatch();
+
+ // Check to see if our statement contains our expected parameter value list
+ assertEquals("MMPreparedStatement.ParameterValuesList does not match",
expectedParameterValues, statement.getParameterValuesList()); //$NON-NLS-1$
+ }
+
+ /**
+ * A helper method to get an <code>MMPreparedStatement</code> that can be
+ * used for simple test cases.
+ * <p>
+ * The returned value is an instance of
<code>TestableMMPreparedStatement</code>
+ * <p>
+ * This method invokes <code>getMMPreparedStatement(final MMConnection conn,
+ * final String sql)</code> with a fake connection object constructed by
+ * <code>Mockito</code>.
+ *
+ * @param sql the query for the prepared statement
+ * @return an instance of TestableMMPreparedStatement
+ * @throws SQLException
+ */
+ protected MMPreparedStatement getMMPreparedStatement(final String sql) throws
SQLException {
+ MMConnection conn = Mockito.mock(MMConnection.class);
+ ServerConnection serverConn = Mockito.mock(ServerConnection.class);
+ LogonResult logonResult = Mockito.mock(LogonResult.class);
+
+ Mockito.stub(conn.getServerConnection()).toReturn(serverConn);
+ Mockito.stub(serverConn.getLogonResult()).toReturn(logonResult);
+ Mockito.stub(logonResult.getTimeZone()).toReturn(TimeZone.getDefault());
+
+ return getMMPreparedStatement(conn, sql);
+ }
+
+ /**
+ * A helper method to get an <code>MMPreparedStatement</code> that can be
+ * used for simple test cases.
+ * <p>
+ * The returned value is an instance of
<code>TestableMMPreparedStatement</code>
+ * <p>
+ * <code>conn</code> should be a valid instance of
<code>MMConnection</code>
+ * or this method will fail.
+ *
+ * @param conn an instance of <code>MMConnection</code>
+ * @param sql the query for the prepared statement
+ * @return an instance of TestableMMPreparedStatement
+ * @throws SQLException
+ */
+ protected MMPreparedStatement getMMPreparedStatement(final MMConnection conn, final
String sql) throws SQLException {
+ TestableMMPreparedStatement statement = new TestableMMPreparedStatement(conn, sql,
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+
+ // Make sure everything is empty on start
+ assertTrue("MMPreparedStatement.ParameterValuesList should be empty",
statement.getParameterValuesList().size() == 0); //$NON-NLS-1$
+ assertTrue("MMPreparedStatement.ParameterValues should be empty",
statement.getParameterValues().size() == 0); //$NON-NLS-1$
+
+ return statement;
+ }
+
+ /**
+ * Represents an extension to <code>MMPreparedStatement</code> that
+ * gives access to the <code>RequestMessage</code> that is passed
+ * around inside <code>MMPreparedStatement</code>.
+ * <p>
+ * This extension simply adds a field named <code>requestMessage</code>
+ * which is <code>public</code>. This field gets set when the
<code>protected</code>
+ * method <code>createRequestMessage()</code> is called.
+ * <p>
+ * This extension also overrides <code>RequestMessage
createRequestMessage(String[] commands,
+ * boolean isBatchedCommand, Boolean requiresResultSet)</code> so that
+ * reference to the created <code>RequestMessage</code> can be retained in
+ * the field <code>requestMessage</code>.
+ */
+ class TestableMMPreparedStatement extends MMPreparedStatement {
+ /**
+ * Contains a reference to the <code>RequestMessage</code> created by
+ * a call to <code>createRequestMessage(String[] commands,
+ * boolean isBatchedCommand, Boolean requiresResultSet)</code>. This
+ * will allow easy access to the prepared statement's request message
+ * generated by a call to one of the statement's execute methods.
+ */
+ public RequestMessage requestMessage;
+ @Override
+ protected RequestMessage createRequestMessage(String[] commands,
+ boolean isBatchedCommand, Boolean requiresResultSet) {
+ this.requestMessage = super
+ .createRequestMessage(commands, isBatchedCommand, requiresResultSet);
+ return this.requestMessage;
+ }
+
+ public TestableMMPreparedStatement(MMConnection connection,
+ String sql, int resultSetType, int resultSetConcurrency)
+ throws SQLException {
+ super(connection, sql, resultSetType, resultSetConcurrency);
+ }
+
+ }
+
+}
Property changes on:
trunk/client-jdbc/src/test/java/com/metamatrix/jdbc/TestMMPreparedStatement.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain