001 package com.mockrunner.mock.jdbc;
002
003 import java.io.InputStream;
004 import java.io.Reader;
005 import java.math.BigDecimal;
006 import java.net.URL;
007 import java.sql.Array;
008 import java.sql.BatchUpdateException;
009 import java.sql.Blob;
010 import java.sql.Clob;
011 import java.sql.Connection;
012 import java.sql.Date;
013 import java.sql.ParameterMetaData;
014 import java.sql.PreparedStatement;
015 import java.sql.Ref;
016 import java.sql.ResultSet;
017 import java.sql.ResultSetMetaData;
018 import java.sql.SQLException;
019 import java.sql.Time;
020 import java.sql.Timestamp;
021 import java.util.ArrayList;
022 import java.util.Calendar;
023 import java.util.Collections;
024 import java.util.HashMap;
025 import java.util.Iterator;
026 import java.util.List;
027 import java.util.Map;
028
029 import com.mockrunner.jdbc.AbstractParameterResultSetHandler;
030 import com.mockrunner.jdbc.ParameterUtil;
031 import com.mockrunner.util.common.StringUtil;
032
033 /**
034 * Mock implementation of <code>PreparedStatement</code>.
035 */
036 public class MockPreparedStatement extends MockStatement implements PreparedStatement
037 {
038 private AbstractParameterResultSetHandler resultSetHandler;
039 private Map paramObjects = new HashMap();
040 private List batchParameters = new ArrayList();
041 private String sql;
042 private MockParameterMetaData parameterMetaData;
043
044 public MockPreparedStatement(Connection connection, String sql)
045 {
046 super(connection);
047 this.sql = sql;
048 prepareParameterMetaData();
049 }
050
051 public MockPreparedStatement(Connection connection, String sql, int resultSetType, int resultSetConcurrency)
052 {
053 super(connection, resultSetType, resultSetConcurrency);
054 this.sql = sql;
055 prepareParameterMetaData();
056 }
057
058 public MockPreparedStatement(Connection connection, String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
059 {
060 super(connection, resultSetType, resultSetConcurrency, resultSetHoldability);
061 this.sql = sql;
062 prepareParameterMetaData();
063 }
064
065 public void setPreparedStatementResultSetHandler(AbstractParameterResultSetHandler resultSetHandler)
066 {
067 super.setResultSetHandler(resultSetHandler);
068 this.resultSetHandler = resultSetHandler;
069 }
070
071 private void prepareParameterMetaData()
072 {
073 int number = StringUtil.countMatches(sql, "?");
074 parameterMetaData = new MockParameterMetaData();
075 parameterMetaData.setParameterCount(number);
076 }
077
078 public String getSQL()
079 {
080 return sql;
081 }
082
083 public Map getIndexedParameterMap()
084 {
085 return Collections.unmodifiableMap(paramObjects);
086 }
087
088 public Map getParameterMap()
089 {
090 return getIndexedParameterMap();
091 }
092
093 public Object getParameter(int index)
094 {
095 return paramObjects.get(new Integer(index));
096 }
097
098 public void setObject(int index, Object object) throws SQLException
099 {
100 paramObjects.put(new Integer(index), object);
101 }
102
103 public void setObject(int parameterIndex, Object object, int targetSqlType, int scale) throws SQLException
104 {
105 setObject(parameterIndex, object);
106 }
107
108 public void setObject(int parameterIndex, Object object, int targetSqlType) throws SQLException
109 {
110 setObject(parameterIndex, object);
111 }
112
113 public void addBatch() throws SQLException
114 {
115 batchParameters.add(new HashMap(paramObjects));
116 }
117
118 public void clearParameters() throws SQLException
119 {
120 paramObjects.clear();
121 }
122
123 public boolean execute() throws SQLException
124 {
125 boolean callExecuteQuery = isQuery(getSQL());
126 if(callExecuteQuery)
127 {
128 executeQuery();
129 }
130 else
131 {
132 executeUpdate();
133 }
134 return callExecuteQuery;
135 }
136
137 public ResultSet executeQuery() throws SQLException
138 {
139 return executeQuery(paramObjects);
140 }
141
142 protected ResultSet executeQuery(Map params) throws SQLException
143 {
144 if(resultSetHandler.getThrowsSQLException(getSQL(), params))
145 {
146 throw new SQLException("Statement " + getSQL() + " was specified to throw an exception");
147 }
148 if(resultSetHandler.getThrowsSQLException(getSQL()))
149 {
150 throw new SQLException("Statement " + getSQL() + " was specified to throw an exception");
151 }
152 MockResultSet result = resultSetHandler.getResultSet(getSQL(), params);
153 resultSetHandler.addParameterMapForExecutedStatement(getSQL(), getParameterMapCopy(params));
154 if(null != result)
155 {
156 resultSetHandler.addExecutedStatement(getSQL());
157 result = cloneResultSet(result);
158 resultSetHandler.addReturnedResultSet(result);
159 setNextResultSet(result);
160 return result;
161 }
162 return super.executeQuery(getSQL());
163 }
164
165 public int executeUpdate() throws SQLException
166 {
167 return executeUpdate(paramObjects);
168 }
169
170 protected int executeUpdate(Map params) throws SQLException
171 {
172 if(resultSetHandler.getThrowsSQLException(getSQL(), params))
173 {
174 throw new SQLException("Statement " + getSQL() + " was specified to throw an exception");
175 }
176 if(resultSetHandler.getThrowsSQLException(getSQL()))
177 {
178 throw new SQLException("Statement " + getSQL() + " was specified to throw an exception");
179 }
180 Integer updateCount = resultSetHandler.getUpdateCount(getSQL(), params);
181 resultSetHandler.addParameterMapForExecutedStatement(getSQL(), getParameterMapCopy(params));
182 if(null != updateCount)
183 {
184 resultSetHandler.addExecutedStatement(getSQL());
185 int updateCountInt = updateCount.intValue();
186 setNextUpdateCount(updateCountInt);
187 return updateCountInt;
188 }
189 return super.executeUpdate(getSQL());
190 }
191
192 public int[] executeBatch() throws SQLException
193 {
194 return executeBatch(this.batchParameters);
195 }
196
197 protected int[] executeBatch(List batchParams) throws SQLException
198 {
199 int[] results = new int[batchParams.size()];
200 if(isQuery(getSQL()))
201 {
202 throw new BatchUpdateException("SQL " + getSQL() + " returned a ResultSet.", null);
203 }
204 for(int ii = 0; ii < results.length; ii++)
205 {
206 Map currentParameters = (Map)batchParams.get(ii);
207 results[ii] = executeUpdate(currentParameters);
208 }
209 return results;
210 }
211
212 public ResultSetMetaData getMetaData() throws SQLException
213 {
214 return new MockResultSetMetaData();
215 }
216
217 public ParameterMetaData getParameterMetaData() throws SQLException
218 {
219 return parameterMetaData;
220 }
221
222 public void setArray(int parameterIndex, Array array) throws SQLException
223 {
224 setObject(parameterIndex, array);
225 }
226
227 public void setAsciiStream(int parameterIndex, InputStream stream, int length) throws SQLException
228 {
229 setObject(parameterIndex, stream);
230 }
231
232 public void setBigDecimal(int parameterIndex, BigDecimal bigDecimal) throws SQLException
233 {
234 setObject(parameterIndex, bigDecimal);
235 }
236
237 public void setBinaryStream(int parameterIndex, InputStream stream, int length) throws SQLException
238 {
239 setObject(parameterIndex, stream);
240 }
241
242 public void setBlob(int parameterIndex, Blob blob) throws SQLException
243 {
244 setObject(parameterIndex, blob);
245 }
246
247 public void setBoolean(int parameterIndex, boolean bool) throws SQLException
248 {
249 setObject(parameterIndex, new Boolean(bool));
250 }
251
252 public void setByte(int parameterIndex, byte byteValue) throws SQLException
253 {
254 setObject(parameterIndex, new Byte(byteValue));
255 }
256
257 public void setBytes(int parameterIndex, byte[] byteArray) throws SQLException
258 {
259 setObject(parameterIndex, byteArray);
260 }
261
262 public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException
263 {
264 setObject(parameterIndex, reader);
265 }
266
267 public void setClob(int parameterIndex, Clob clob) throws SQLException
268 {
269 setObject(parameterIndex, clob);
270 }
271
272 public void setDate(int parameterIndex, Date date, Calendar calendar) throws SQLException
273 {
274 setObject(parameterIndex, date);
275 }
276
277 public void setDate(int parameterIndex, Date date) throws SQLException
278 {
279 setObject(parameterIndex, date);
280 }
281
282 public void setDouble(int parameterIndex, double doubleValue) throws SQLException
283 {
284 setObject(parameterIndex, new Double(doubleValue));
285 }
286
287 public void setFloat(int parameterIndex, float floatValue) throws SQLException
288 {
289 setObject(parameterIndex, new Float(floatValue));
290 }
291
292 public void setInt(int parameterIndex, int intValue) throws SQLException
293 {
294 setObject(parameterIndex, new Integer(intValue));
295 }
296
297 public void setLong(int parameterIndex, long longValue) throws SQLException
298 {
299 setObject(parameterIndex, new Long(longValue));
300 }
301
302 public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException
303 {
304 setObject(parameterIndex, null);
305 }
306
307 public void setNull(int parameterIndex, int sqlType) throws SQLException
308 {
309 setObject(parameterIndex, null);
310 }
311
312 public void setRef(int parameterIndex, Ref ref) throws SQLException
313 {
314 setObject(parameterIndex, ref);
315 }
316
317 public void setShort(int parameterIndex, short shortValue) throws SQLException
318 {
319 setObject(parameterIndex, new Short(shortValue));
320 }
321
322 public void setString(int parameterIndex, String string) throws SQLException
323 {
324 setObject(parameterIndex, string);
325 }
326
327 public void setTime(int parameterIndex, Time time, Calendar calendar) throws SQLException
328 {
329 setObject(parameterIndex, time);
330 }
331
332 public void setTime(int parameterIndex, Time time) throws SQLException
333 {
334 setObject(parameterIndex, time);
335 }
336
337 public void setTimestamp(int parameterIndex, Timestamp timeStamp, Calendar cal) throws SQLException
338 {
339 setObject(parameterIndex, timeStamp);
340 }
341
342 public void setTimestamp(int parameterIndex, Timestamp timeStamp) throws SQLException
343 {
344 setObject(parameterIndex, timeStamp);
345 }
346
347 public void setUnicodeStream(int parameterIndex, InputStream stream, int length) throws SQLException
348 {
349 setObject(parameterIndex, stream);
350 }
351
352 public void setURL(int parameterIndex, URL url) throws SQLException
353 {
354 setObject(parameterIndex, url);
355 }
356
357 private Map getParameterMapCopy(Map actualParameters)
358 {
359 Map copyParameters = new HashMap();
360 Iterator keys = actualParameters.keySet().iterator();
361 while(keys.hasNext())
362 {
363 Object key = keys.next();
364 Object actualParameter = actualParameters.get(key);
365 Object copyParameter = ParameterUtil.copyParameter(actualParameter);
366 copyParameters.put(key, copyParameter);
367 }
368 return copyParameters;
369 }
370 }