001 package com.mockrunner.jdbc;
002
003 import java.sql.SQLException;
004 import java.util.ArrayList;
005 import java.util.Arrays;
006 import java.util.Collections;
007 import java.util.HashMap;
008 import java.util.Iterator;
009 import java.util.List;
010 import java.util.Map;
011 import java.util.TreeMap;
012
013 import com.mockrunner.mock.jdbc.MockResultSet;
014 import com.mockrunner.util.common.ArrayUtil;
015
016 /**
017 * Abstract base class for all statement types
018 * that support parameters, i.e. <code>PreparedStatement</code>
019 * and <code>CallableStatement</code>.
020 */
021 public abstract class AbstractParameterResultSetHandler extends AbstractResultSetHandler
022 {
023 private boolean exactMatchParameter = false;
024 private Map resultSetsForStatement = new TreeMap();
025 private Map updateCountForStatement = new TreeMap();
026 private Map throwsSQLException = new TreeMap();
027 private Map generatedKeysForStatement = new TreeMap();
028 private Map executedStatementParameters = new TreeMap();
029
030 /**
031 * Collects all SQL strings that were executed.
032 * @param sql the SQL string
033 * @param parameters a copy of the corresponding parameter map
034 */
035 public void addParameterMapForExecutedStatement(String sql, Map parameters)
036 {
037 if(null != parameters)
038 {
039 if(null == executedStatementParameters.get(sql))
040 {
041 executedStatementParameters.put(sql, new ParameterSets(sql));
042 }
043 ParameterSets sets = (ParameterSets)executedStatementParameters.get(sql);
044 sets.addParameterSet(parameters);
045 }
046 }
047
048 /**
049 * Returns the <code>ParameterSets</code> for a specified
050 * SQL string.
051 * @param sql the SQL string
052 * @return the <code>Map</code> of parameters
053 */
054 public ParameterSets getParametersForExecutedStatement(String sql)
055 {
056 return (ParameterSets)executedStatementParameters.get(sql);
057 }
058
059 /**
060 * Returns the <code>Map</code> of executed SQL strings.
061 * Each string maps to the corresponding {@link ParameterSets}
062 * object.
063 * @return the <code>Map</code> of parameters
064 */
065 public Map getExecutedStatementParameterMap()
066 {
067 return Collections.unmodifiableMap(executedStatementParameters);
068 }
069
070 /**
071 * @deprecated use {@link #getExecutedStatementParameterMap}
072 */
073 public Map getExecutedStatementParameter()
074 {
075 return getExecutedStatementParameterMap();
076 }
077
078 /**
079 * Sets if the specified parameters must match exactly
080 * in order and number.
081 * Defaults to <code>false</code>, i.e. the specified
082 * parameters must be present in the actual parameter
083 * list of the prepared statement with the correct index
084 * but it's ok if there are more actual parameters.
085 * @param exactMatchParameter must parameters match exactly
086 */
087 public void setExactMatchParameter(boolean exactMatchParameter)
088 {
089 this.exactMatchParameter = exactMatchParameter;
090 }
091
092 /**
093 * Returns the first update count that matches the
094 * specified SQL string and the specified parameters.
095 * If the specified SQL string was prepared to return multiple update
096 * counts, the first one will be returned.
097 * Please note that you can modify the match parameters with
098 * {@link #setCaseSensitive}, {@link #setExactMatch} and
099 * {@link #setUseRegularExpressions} and the match parameters for the
100 * specified parameter list with {@link #setExactMatchParameter}.
101 * @param sql the SQL string
102 * @param parameters the parameters
103 * @return the corresponding update count
104 */
105 public Integer getUpdateCount(String sql, Map parameters)
106 {
107 Integer[] updateCounts = getUpdateCounts(sql, parameters);
108 if(null != updateCounts && updateCounts.length > 0)
109 {
110 return updateCounts[0];
111 }
112 return null;
113 }
114
115 /**
116 * Returns the first update count array that matches the
117 * specified SQL string and the specified parameters.
118 * If the specified SQL string was prepared to return one update count,
119 * this value will be wrapped in an array with one element.
120 * Please note that you can modify the match parameters with
121 * {@link #setCaseSensitive}, {@link #setExactMatch} and
122 * {@link #setUseRegularExpressions} and the match parameters for the
123 * specified parameter list with {@link #setExactMatchParameter}.
124 * @param sql the SQL string
125 * @param parameters the parameters
126 * @return the corresponding update count
127 */
128 public Integer[] getUpdateCounts(String sql, Map parameters)
129 {
130 ParameterWrapper wrapper = (ParameterWrapper)getMatchingParameterWrapper(sql, parameters, updateCountForStatement);
131 if(null != wrapper)
132 {
133 if(wrapper instanceof MockUpdateCountWrapper)
134 {
135 return new Integer[] {((MockUpdateCountWrapper)wrapper).getUpdateCount()};
136 }
137 else if(wrapper instanceof MockUpdateCountArrayWrapper)
138 {
139 return ((MockUpdateCountArrayWrapper)wrapper).getUpdateCount();
140 }
141 }
142 return null;
143 }
144
145 /**
146 * Returns the if the specified SQL string with the specified parameters
147 * returns multiple update counts.
148 * Please note that you can modify the match parameters with {@link #setCaseSensitive},
149 * {@link #setExactMatch} and {@link #setUseRegularExpressions}.
150 * @param sql the SQL string
151 * @return <code>true</code> if the SQL string returns multiple update counts,
152 * <code>false</code> otherwise
153 */
154 public boolean hasMultipleUpdateCounts(String sql, Map parameters)
155 {
156 ParameterWrapper wrapper = (ParameterWrapper)getMatchingParameterWrapper(sql, parameters, updateCountForStatement);
157 return (wrapper instanceof MockUpdateCountArrayWrapper);
158 }
159
160 /**
161 * Returns the first <code>ResultSet</code> that matches the
162 * specified SQL string and the specified parameters.
163 * If the specified SQL string was prepared to return multiple result
164 * sets, the first one will be returned.
165 * Please note that you can modify the match parameters with
166 * {@link #setCaseSensitive}, {@link #setExactMatch} and
167 * {@link #setUseRegularExpressions} and the match parameters for the
168 * specified parameter list with {@link #setExactMatchParameter}.
169 * @param sql the SQL string
170 * @param parameters the parameters
171 * @return the corresponding {@link MockResultSet}
172 */
173 public MockResultSet getResultSet(String sql, Map parameters)
174 {
175 MockResultSet[] resultSets = getResultSets(sql, parameters);
176 if(null != resultSets && resultSets.length > 0)
177 {
178 return resultSets[0];
179 }
180 return null;
181 }
182
183 /**
184 * Returns the first <code>ResultSet[]</code> that matches the
185 * specified SQL string and the specified parameters.
186 * If the specified SQL string was prepared to return one single
187 * <code>ResultSet</code>, this <code>ResultSet</code> will be wrapped
188 * in an array with one element.
189 * Please note that you can modify the match parameters with
190 * {@link #setCaseSensitive}, {@link #setExactMatch} and
191 * {@link #setUseRegularExpressions} and the match parameters for the
192 * specified parameter list with {@link #setExactMatchParameter}.
193 * @param sql the SQL string
194 * @param parameters the parameters
195 * @return the corresponding update count
196 */
197 public MockResultSet[] getResultSets(String sql, Map parameters)
198 {
199 ParameterWrapper wrapper = (ParameterWrapper)getMatchingParameterWrapper(sql, parameters, resultSetsForStatement);
200 if(null != wrapper)
201 {
202 if(wrapper instanceof MockResultSetWrapper)
203 {
204 return new MockResultSet[] {((MockResultSetWrapper)wrapper).getResultSet()};
205 }
206 else if(wrapper instanceof MockResultSetArrayWrapper)
207 {
208 return ((MockResultSetArrayWrapper)wrapper).getResultSets();
209 }
210 }
211 return null;
212 }
213
214 /**
215 * Returns the if the specified SQL string with the specified parameters
216 * returns multiple result sets.
217 * Please note that you can modify the match parameters with {@link #setCaseSensitive},
218 * {@link #setExactMatch} and {@link #setUseRegularExpressions}.
219 * @param sql the SQL string
220 * @return <code>true</code> if the SQL string returns multiple update counts,
221 * <code>false</code> otherwise
222 */
223 public boolean hasMultipleResultSets(String sql, Map parameters)
224 {
225 ParameterWrapper wrapper = (ParameterWrapper)getMatchingParameterWrapper(sql, parameters, resultSetsForStatement);
226 return (wrapper instanceof MockResultSetArrayWrapper);
227 }
228
229 /**
230 * Returns if the specified SQL string with the specified parameters
231 * should raise an exception.
232 * This can be used to simulate database exceptions.
233 * Please note that you can modify the match parameters with
234 * {@link #setCaseSensitive}, {@link #setExactMatch} and
235 * {@link #setUseRegularExpressions} and the match parameters for the
236 * specified parameter list with {@link #setExactMatchParameter}.
237 * @param sql the SQL string
238 * @param parameters the parameters
239 * @return <code>true</code> if the specified SQL string should raise an exception,
240 * <code>false</code> otherwise
241 */
242 public boolean getThrowsSQLException(String sql, Map parameters)
243 {
244 return (getSQLException(sql, parameters) != null);
245 }
246
247 /**
248 * Returns the <code>SQLException</code> the specified SQL string
249 * should throw. Returns <code>null</code> if the specified SQL string
250 * should not throw an exception.
251 * This can be used to simulate database exceptions.
252 * Please note that you can modify the match parameters with
253 * {@link #setCaseSensitive}, {@link #setExactMatch} and
254 * {@link #setUseRegularExpressions} and the match parameters for the
255 * specified parameter list with {@link #setExactMatchParameter}.
256 * @param sql the SQL string
257 * @param parameters the parameters
258 * @return the <code>SQLException</code> or <code>null</code>
259 */
260 public SQLException getSQLException(String sql, Map parameters)
261 {
262 MockSQLExceptionWrapper wrapper = (MockSQLExceptionWrapper)getMatchingParameterWrapper(sql, parameters, throwsSQLException);
263 if(null != wrapper)
264 {
265 return wrapper.getException();
266 }
267 return null;
268 }
269
270 /**
271 * Returns the first generated keys <code>ResultSet</code> that
272 * matches the specified SQL string.
273 * Please note that you can modify the match parameters with
274 * {@link #setCaseSensitive}, {@link #setExactMatch} and
275 * {@link #setUseRegularExpressions} and the match parameters for the
276 * specified parameter list with {@link #setExactMatchParameter}.
277 * @param sql the SQL string
278 * @param parameters the parameters
279 * @return the corresponding generated keys {@link MockResultSet}
280 */
281 public MockResultSet getGeneratedKeys(String sql, Map parameters)
282 {
283 MockResultSetWrapper wrapper = (MockResultSetWrapper)getMatchingParameterWrapper(sql, parameters, generatedKeysForStatement);
284 if(null != wrapper)
285 {
286 return wrapper.getResultSet();
287 }
288 return null;
289 }
290
291 protected ParameterWrapper getMatchingParameterWrapper(String sql, Map parameters, Map statementMap)
292 {
293 SQLStatementMatcher matcher = new SQLStatementMatcher(getCaseSensitive(), getExactMatch(), getUseRegularExpressions());
294 List list = matcher.getMatchingObjects(statementMap, sql, true, true);
295 for(int ii = 0; ii < list.size(); ii++)
296 {
297 ParameterWrapper wrapper = (ParameterWrapper)list.get(ii);
298 if(doParameterMatch(wrapper.getParamters(), parameters))
299 {
300 return wrapper;
301 }
302 }
303 return null;
304 }
305
306 private boolean doParameterMatch(Map expectedParameters, Map actualParameters)
307 {
308 if(exactMatchParameter)
309 {
310 if(actualParameters.size() != expectedParameters.size()) return false;
311 Iterator iterator = actualParameters.keySet().iterator();
312 while(iterator.hasNext())
313 {
314 Object currentKey = iterator.next();
315 if(!actualParameters.containsKey(currentKey)) return false;
316 Object expectedObject = expectedParameters.get(currentKey);
317 if(!ParameterUtil.compareParameter(actualParameters.get(currentKey), expectedObject))
318 {
319 return false;
320 }
321 }
322 return true;
323 }
324 else
325 {
326 Iterator iterator = expectedParameters.keySet().iterator();
327 while(iterator.hasNext())
328 {
329 Object currentKey = iterator.next();
330 if(!actualParameters.containsKey(currentKey)) return false;
331 Object actualObject = actualParameters.get(currentKey);
332 if(!ParameterUtil.compareParameter(actualObject, expectedParameters.get(currentKey)))
333 {
334 return false;
335 }
336 }
337 return true;
338 }
339 }
340
341 /**
342 * Clears the <code>ResultSet</code> objects.
343 */
344 public void clearResultSets()
345 {
346 super.clearResultSets();
347 resultSetsForStatement.clear();
348 }
349
350 /**
351 * Clears the update counts.
352 */
353 public void clearUpdateCounts()
354 {
355 super.clearUpdateCounts();
356 updateCountForStatement.clear();
357 }
358
359 /**
360 * Clears the list of statements that should throw an exception
361 */
362 public void clearThrowsSQLException()
363 {
364 super.clearThrowsSQLException();
365 throwsSQLException.clear();
366 }
367
368 /**
369 * Clears the list of statements that return generated keys.
370 */
371 public void clearGeneratedKeys()
372 {
373 super.clearGeneratedKeys();
374 generatedKeysForStatement.clear();
375 }
376
377 /**
378 * Prepare a <code>ResultSet</code> for a specified SQL string and
379 * the specified parameters. The specified parameters array
380 * must contain the parameters in the correct order starting with index 0 for
381 * the first parameter. Please keep in mind that parameters in
382 * <code>PreparedStatement</code> objects start with 1 as the first
383 * parameter. So <code>parameters[0]</code> maps to the
384 * parameter with index 1.
385 * Please note that you can modify the match parameters with
386 * {@link #setCaseSensitive}, {@link #setExactMatch} and
387 * {@link #setUseRegularExpressions} and the match parameters for the
388 * specified parameter list with {@link #setExactMatchParameter}.
389 * @param sql the SQL string
390 * @param resultSet the corresponding {@link MockResultSet}
391 * @param parameters the parameters
392 */
393 public void prepareResultSet(String sql, MockResultSet resultSet, Object[] parameters)
394 {
395 prepareResultSet(sql, resultSet, Arrays.asList(parameters));
396 }
397
398 /**
399 * Prepare an array of <code>ResultSet</code> objects for a specified SQL string and
400 * the specified parameters. This method can be used for queries that return
401 * multiple result sets. The specified parameters array
402 * must contain the parameters in the correct order starting with index 0 for
403 * the first parameter. Please keep in mind that parameters in
404 * <code>PreparedStatement</code> objects start with 1 as the first
405 * parameter. So <code>parameters[0]</code> maps to the
406 * parameter with index 1.
407 * Please note that you can modify the match parameters with
408 * {@link #setCaseSensitive}, {@link #setExactMatch} and
409 * {@link #setUseRegularExpressions} and the match parameters for the
410 * specified parameter list with {@link #setExactMatchParameter}.
411 * @param sql the SQL string
412 * @param resultSets the corresponding <code>MockResultSet[]</code>
413 * @param parameters the parameters
414 */
415 public void prepareResultSets(String sql, MockResultSet[] resultSets, Object[] parameters)
416 {
417 prepareResultSets(sql, resultSets, Arrays.asList(parameters));
418 }
419
420 /**
421 * Prepare a <code>ResultSet</code> for a specified SQL string and
422 * the specified parameters. The specified parameters <code>List</code>
423 * must contain the parameters in the correct order starting with index 0 for
424 * the first parameter. Please keep in mind that parameters in
425 * <code>PreparedStatement</code> objects start with 1 as the first
426 * parameter. So <code>parameters.get(0)</code> maps to the
427 * parameter with index 1.
428 * Please note that you can modify the match parameters with
429 * {@link #setCaseSensitive}, {@link #setExactMatch} and
430 * {@link #setUseRegularExpressions} and the match parameters for the
431 * specified parameter list with {@link #setExactMatchParameter}.
432 * @param sql the SQL string
433 * @param resultSet the corresponding {@link MockResultSet}
434 * @param parameters the parameters
435 */
436 public void prepareResultSet(String sql, MockResultSet resultSet, List parameters)
437 {
438 Map params = createParameterMap(parameters);
439 prepareResultSet(sql, resultSet, params);
440 }
441
442 /**
443 * Prepare an array of <code>ResultSet</code> objects for a specified SQL string and
444 * the specified parameters. This method can be used for queries that return
445 * multiple result sets. The specified parameters <code>List</code>
446 * must contain the parameters in the correct order starting with index 0 for
447 * the first parameter. Please keep in mind that parameters in
448 * <code>PreparedStatement</code> objects start with 1 as the first
449 * parameter. So <code>parameters.get(0)</code> maps to the
450 * parameter with index 1.
451 * Please note that you can modify the match parameters with
452 * {@link #setCaseSensitive}, {@link #setExactMatch} and
453 * {@link #setUseRegularExpressions} and the match parameters for the
454 * specified parameter list with {@link #setExactMatchParameter}.
455 * @param sql the SQL string
456 * @param resultSets the corresponding <code>MockResultSet[]</code>
457 * @param parameters the parameters
458 */
459 public void prepareResultSets(String sql, MockResultSet[] resultSets, List parameters)
460 {
461 Map params = createParameterMap(parameters);
462 prepareResultSets(sql, resultSets, params);
463 }
464
465 /**
466 * Prepare a <code>ResultSet</code> for a specified SQL string and
467 * the specified parameters. The specified parameters <code>Map</code>
468 * must contain the parameters by mapping <code>Integer</code> objects
469 * to the corresponding parameter. The <code>Integer</code> object
470 * is the index of the parameter. In the case of a <code>CallableStatement</code>,
471 * <code>String</code> keys for named parameters are also allowed.
472 * Please note that you can modify the match parameters with
473 * {@link #setCaseSensitive}, {@link #setExactMatch} and
474 * {@link #setUseRegularExpressions} and the match parameters for the
475 * specified parameter list with {@link #setExactMatchParameter}.
476 * @param sql the SQL string
477 * @param resultSet the corresponding {@link MockResultSet}
478 * @param parameters the parameters
479 */
480 public void prepareResultSet(String sql, MockResultSet resultSet, Map parameters)
481 {
482 List list = getListFromMapForSQLStatement(sql, resultSetsForStatement);
483 list.add(new MockResultSetWrapper(resultSet, new HashMap(parameters)));
484 }
485
486 /**
487 * Prepare an array of <code>ResultSet</code> objects for a specified SQL string and
488 * the specified parameters. This method can be used for queries that return
489 * multiple result sets. The specified parameters <code>Map</code>
490 * must contain the parameters by mapping <code>Integer</code> objects
491 * to the corresponding parameter. The <code>Integer</code> object
492 * is the index of the parameter. In the case of a <code>CallableStatement</code>,
493 * <code>String</code> keys for named parameters are also allowed.
494 * Please note that you can modify the match parameters with
495 * {@link #setCaseSensitive}, {@link #setExactMatch} and
496 * {@link #setUseRegularExpressions} and the match parameters for the
497 * specified parameter list with {@link #setExactMatchParameter}.
498 * @param sql the SQL string
499 * @param resultSets the corresponding <code>MockResultSet[]</code>
500 * @param parameters the parameters
501 */
502 public void prepareResultSets(String sql, MockResultSet[] resultSets, Map parameters)
503 {
504 List list = getListFromMapForSQLStatement(sql, resultSetsForStatement);
505 list.add(new MockResultSetArrayWrapper((MockResultSet[])resultSets.clone(), new HashMap(parameters)));
506 }
507
508 /**
509 * Prepare that the specified SQL string with the specified parameters
510 * should raise an exception.
511 * This can be used to simulate database exceptions.
512 * This method creates an <code>SQLException</code> and will throw this
513 * exception. With {@link #prepareThrowsSQLException(String, SQLException, Object[])}
514 * you can specify the exception.
515 * The specified parameters array must contain the parameters in
516 * the correct order starting with index 0 for the first parameter.
517 * Please keep in mind that parameters in <code>PreparedStatement</code>
518 * objects start with 1 as the first parameter. So <code>parameters[0]</code>
519 * maps to the parameter with index 1.
520 * Please note that you can modify the match parameters with
521 * {@link #setCaseSensitive}, {@link #setExactMatch} and
522 * {@link #setUseRegularExpressions} and the match parameters for the
523 * specified parameter list with {@link #setExactMatchParameter}.
524 * @param sql the SQL string
525 * @param parameters the parameters
526 */
527 public void prepareThrowsSQLException(String sql, Object[] parameters)
528 {
529 SQLException exc = new SQLException("Statement " + sql + " was specified to throw an exception");
530 prepareThrowsSQLException(sql, exc, parameters);
531 }
532
533 /**
534 * Prepare that the specified SQL string with the specified parameters
535 * should raise an exception.
536 * This can be used to simulate database exceptions.
537 * This method creates an <code>SQLException</code> and will throw this
538 * exception. With {@link #prepareThrowsSQLException(String, SQLException, List)}
539 * you can specify the exception.
540 * The specified parameters <code>List</code> must contain the
541 * parameters in the correct order starting with index 0 for the first
542 * parameter. Please keep in mind that parameters in
543 * <code>PreparedStatement</code> objects start with 1 as the first
544 * parameter. So <code>parameters.get(0)</code> maps to the parameter
545 * with index 1.
546 * Please note that you can modify the match parameters with
547 * {@link #setCaseSensitive}, {@link #setExactMatch} and
548 * {@link #setUseRegularExpressions} and the match parameters for the
549 * specified parameter list with {@link #setExactMatchParameter}.
550 * @param sql the SQL string
551 * @param parameters the parameters
552 */
553 public void prepareThrowsSQLException(String sql, List parameters)
554 {
555 SQLException exc = new SQLException("Statement " + sql + " was specified to throw an exception");
556 prepareThrowsSQLException(sql, exc, parameters);
557 }
558
559 /**
560 * Prepare that the specified SQL string with the specified parameters
561 * should raise an exception.
562 * This can be used to simulate database exceptions.
563 * This method creates an <code>SQLException</code> and will throw this
564 * exception. With {@link #prepareThrowsSQLException(String, SQLException, Map)}
565 * you can specify the exception.
566 * The specified parameters <code>Map</code> must contain the parameters by
567 * mapping <code>Integer</code> objects to the corresponding parameter.
568 * The <code>Integer</code> object is the index of the parameter. In the case
569 * of a <code>CallableStatement</code>,
570 * <code>String</code> keys for named parameters are also allowed.
571 * Please note that you can modify the match parameters with
572 * {@link #setCaseSensitive}, {@link #setExactMatch} and
573 * {@link #setUseRegularExpressions} and the match parameters for the
574 * specified parameter list with {@link #setExactMatchParameter}.
575 * @param sql the SQL string
576 * @param parameters the parameters
577 */
578 public void prepareThrowsSQLException(String sql, Map parameters)
579 {
580 SQLException exc = new SQLException("Statement " + sql + " was specified to throw an exception");
581 prepareThrowsSQLException(sql, exc, parameters);
582 }
583
584 /**
585 * Prepare that the specified SQL string with the specified parameters
586 * should raise an exception.
587 * This can be used to simulate database exceptions.
588 * This method takes an exception object that will be thrown.
589 * The specified parameters array must contain the parameters in
590 * the correct order starting with index 0 for the first parameter.
591 * Please keep in mind that parameters in <code>PreparedStatement</code>
592 * objects start with 1 as the first parameter. So <code>parameters[0]</code>
593 * maps to the parameter with index 1.
594 * Please note that you can modify the match parameters with
595 * {@link #setCaseSensitive}, {@link #setExactMatch} and
596 * {@link #setUseRegularExpressions} and the match parameters for the
597 * specified parameter list with {@link #setExactMatchParameter}.
598 * @param sql the SQL string
599 * @param exc the <code>SQLException</code> that should be thrown
600 * @param parameters the parameters
601 */
602 public void prepareThrowsSQLException(String sql, SQLException exc, Object[] parameters)
603 {
604 prepareThrowsSQLException(sql, exc, Arrays.asList(parameters));
605 }
606
607 /**
608 * Prepare that the specified SQL string with the specified parameters
609 * should raise an exception.
610 * This can be used to simulate database exceptions.
611 * This method takes an exception object that will be thrown.
612 * The specified parameters <code>List</code> must contain the
613 * parameters in the correct order starting with index 0 for the first
614 * parameter. Please keep in mind that parameters in
615 * <code>PreparedStatement</code> objects start with 1 as the first
616 * parameter. So <code>parameters.get(0)</code> maps to the parameter
617 * with index 1.
618 * Please note that you can modify the match parameters with
619 * {@link #setCaseSensitive}, {@link #setExactMatch} and
620 * {@link #setUseRegularExpressions} and the match parameters for the
621 * specified parameter list with {@link #setExactMatchParameter}.
622 * @param sql the SQL string
623 * @param exc the <code>SQLException</code> that should be thrown
624 * @param parameters the parameters
625 */
626 public void prepareThrowsSQLException(String sql, SQLException exc, List parameters)
627 {
628 Map params = createParameterMap(parameters);
629 prepareThrowsSQLException(sql, exc, params);
630 }
631
632 /**
633 * Prepare that the specified SQL string with the specified parameters
634 * should raise an exception.
635 * This can be used to simulate database exceptions.
636 * This method takes an exception object that will be thrown.
637 * The specified parameters <code>Map</code> must contain the parameters by
638 * mapping <code>Integer</code> objects to the corresponding parameter.
639 * The <code>Integer</code> object is the index of the parameter. In the case
640 * of a <code>CallableStatement</code>,
641 * <code>String</code> keys for named parameters are also allowed.
642 * Please note that you can modify the match parameters with
643 * {@link #setCaseSensitive}, {@link #setExactMatch} and
644 * {@link #setUseRegularExpressions} and the match parameters for the
645 * specified parameter list with {@link #setExactMatchParameter}.
646 * @param sql the SQL string
647 * @param exc the <code>SQLException</code> that should be thrown
648 * @param parameters the parameters
649 */
650 public void prepareThrowsSQLException(String sql, SQLException exc, Map parameters)
651 {
652 List list = getListFromMapForSQLStatement(sql, throwsSQLException);
653 list.add(new MockSQLExceptionWrapper(exc, new HashMap(parameters)));
654 }
655
656 /**
657 * Prepare the update count for execute update calls for a specified SQL string
658 * and the specified parameters. The specified parameters array
659 * must contain the parameters in the correct order starting with index 0 for
660 * the first parameter. Please keep in mind that parameters in
661 * <code>PreparedStatement</code> objects start with 1 as the first
662 * parameter. So <code>parameters[0]</code> maps to the
663 * parameter with index 1.
664 * Please note that you can modify the match parameters with
665 * {@link #setCaseSensitive}, {@link #setExactMatch} and
666 * {@link #setUseRegularExpressions} and the match parameters for the
667 * specified parameter list with {@link #setExactMatchParameter}.
668 * @param sql the SQL string
669 * @param updateCount the update count
670 * @param parameters the parameters
671 */
672 public void prepareUpdateCount(String sql, int updateCount, Object[] parameters)
673 {
674 prepareUpdateCount(sql, updateCount, Arrays.asList(parameters));
675 }
676
677 /**
678 * Prepare an array update count values for execute update calls for a specified SQL string
679 * and the specified parameters. This method can be used if multiple update counts
680 * are returned. The specified parameters array
681 * must contain the parameters in the correct order starting with index 0 for
682 * the first parameter. Please keep in mind that parameters in
683 * <code>PreparedStatement</code> objects start with 1 as the first
684 * parameter. So <code>parameters[0]</code> maps to the
685 * parameter with index 1.
686 * Please note that you can modify the match parameters with
687 * {@link #setCaseSensitive}, {@link #setExactMatch} and
688 * {@link #setUseRegularExpressions} and the match parameters for the
689 * specified parameter list with {@link #setExactMatchParameter}.
690 * @param sql the SQL string
691 * @param updateCounts the update count array
692 * @param parameters the parameters
693 */
694 public void prepareUpdateCounts(String sql, int[] updateCounts, Object[] parameters)
695 {
696 prepareUpdateCounts(sql, updateCounts, Arrays.asList(parameters));
697 }
698
699 /**
700 * Prepare the update count for execute update calls for a specified SQL string
701 * and the specified parameters. The specified parameters <code>List</code>
702 * must contain the parameters in the correct order starting with index 0 for
703 * the first parameter. Please keep in mind that parameters in
704 * <code>PreparedStatement</code> objects start with 1 as the first
705 * parameter. So <code>parameters.get(0)</code> maps to the
706 * parameter with index 1.
707 * Please note that you can modify the match parameters with
708 * {@link #setCaseSensitive}, {@link #setExactMatch} and
709 * {@link #setUseRegularExpressions} and the match parameters for the
710 * specified parameter list with {@link #setExactMatchParameter}.
711 * @param sql the SQL string
712 * @param updateCount the update count
713 * @param parameters the parameters
714 */
715 public void prepareUpdateCount(String sql, int updateCount, List parameters)
716 {
717 Map params = createParameterMap(parameters);
718 prepareUpdateCount(sql, updateCount, params);
719 }
720
721 /**
722 * Prepare an array update count values for execute update calls for a specified SQL string
723 * and the specified parameters. This method can be used if multiple update counts
724 * are returned. The specified parameters <code>List</code>
725 * must contain the parameters in the correct order starting with index 0 for
726 * the first parameter. Please keep in mind that parameters in
727 * <code>PreparedStatement</code> objects start with 1 as the first
728 * parameter. So <code>parameters.get(0)</code> maps to the
729 * parameter with index 1.
730 * Please note that you can modify the match parameters with
731 * {@link #setCaseSensitive}, {@link #setExactMatch} and
732 * {@link #setUseRegularExpressions} and the match parameters for the
733 * specified parameter list with {@link #setExactMatchParameter}.
734 * @param sql the SQL string
735 * @param updateCounts the update count array
736 * @param parameters the parameters
737 */
738 public void prepareUpdateCounts(String sql, int[] updateCounts, List parameters)
739 {
740 Map params = createParameterMap(parameters);
741 prepareUpdateCounts(sql, updateCounts, params);
742 }
743
744 /**
745 * Prepare the update count for execute update calls for a specified SQL string
746 * and the specified parameters. The specified parameters <code>Map</code>
747 * must contain the parameters by mapping <code>Integer</code> objects
748 * to the corresponding parameter. The <code>Integer</code> object
749 * is the index of the parameter. In the case of a <code>CallableStatement</code>,
750 * <code>String</code> keys for named parameters are also allowed.
751 * Please note that you can modify the match parameters with
752 * {@link #setCaseSensitive}, {@link #setExactMatch} and
753 * {@link #setUseRegularExpressions} and the match parameters for the
754 * specified parameter list with {@link #setExactMatchParameter}.
755 * @param sql the SQL string
756 * @param updateCount the update count
757 * @param parameters the parameters
758 */
759 public void prepareUpdateCount(String sql, int updateCount, Map parameters)
760 {
761 List list = getListFromMapForSQLStatement(sql, updateCountForStatement);
762 list.add(new MockUpdateCountWrapper(updateCount, new HashMap(parameters)));
763 }
764
765 /**
766 * Prepare an array update count values for execute update calls for a specified SQL string
767 * and the specified parameters. This method can be used if multiple update counts
768 * are returned. The specified parameters <code>Map</code>
769 * must contain the parameters by mapping <code>Integer</code> objects
770 * to the corresponding parameter. The <code>Integer</code> object
771 * is the index of the parameter. In the case of a <code>CallableStatement</code>,
772 * <code>String</code> keys for named parameters are also allowed.
773 * Please note that you can modify the match parameters with
774 * {@link #setCaseSensitive}, {@link #setExactMatch} and
775 * {@link #setUseRegularExpressions} and the match parameters for the
776 * specified parameter list with {@link #setExactMatchParameter}.
777 * @param sql the SQL string
778 * @param updateCounts the update count array
779 * @param parameters the parameters
780 */
781 public void prepareUpdateCounts(String sql, int[] updateCounts, Map parameters)
782 {
783 List list = getListFromMapForSQLStatement(sql, updateCountForStatement);
784 list.add(new MockUpdateCountArrayWrapper((int[])updateCounts.clone(), new HashMap(parameters)));
785 }
786
787 /**
788 * Prepare the generated keys <code>ResultSet</code>
789 * for a specified SQL string.
790 * The specified parameters array must contain the parameters in
791 * the correct order starting with index 0 for the first parameter.
792 * Please keep in mind that parameters in <code>PreparedStatement</code>
793 * objects start with 1 as the first parameter. So <code>parameters[0]</code>
794 * maps to the parameter with index 1.
795 * Please note that you can modify the match parameters with
796 * {@link #setCaseSensitive}, {@link #setExactMatch} and
797 * {@link #setUseRegularExpressions} and the match parameters for the
798 * specified parameter list with {@link #setExactMatchParameter}.
799 * @param sql the SQL string
800 * @param generatedKeysResult the generated keys {@link MockResultSet}
801 * @param parameters the parameters
802 */
803 public void prepareGeneratedKeys(String sql, MockResultSet generatedKeysResult, Object[] parameters)
804 {
805 prepareGeneratedKeys(sql, generatedKeysResult, Arrays.asList(parameters));
806 }
807
808 /**
809 * Prepare the generated keys <code>ResultSet</code>
810 * for a specified SQL string.
811 * The specified parameters <code>List</code> must contain the
812 * parameters in the correct order starting with index 0 for the first
813 * parameter. Please keep in mind that parameters in
814 * <code>PreparedStatement</code> objects start with 1 as the first
815 * parameter. So <code>parameters.get(0)</code> maps to the parameter
816 * with index 1.
817 * Please note that you can modify the match parameters with
818 * {@link #setCaseSensitive}, {@link #setExactMatch} and
819 * {@link #setUseRegularExpressions} and the match parameters for the
820 * specified parameter list with {@link #setExactMatchParameter}.
821 * @param sql the SQL string
822 * @param generatedKeysResult the generated keys {@link MockResultSet}
823 * @param parameters the parameters
824 */
825 public void prepareGeneratedKeys(String sql, MockResultSet generatedKeysResult, List parameters)
826 {
827 Map params = createParameterMap(parameters);
828 prepareGeneratedKeys(sql, generatedKeysResult, params);
829 }
830
831 /**
832 * Prepare the generated keys <code>ResultSet</code>
833 * for a specified SQL string.
834 * The specified parameters <code>Map</code> must contain the parameters by
835 * mapping <code>Integer</code> objects to the corresponding parameter.
836 * The <code>Integer</code> object is the index of the parameter. In the case
837 * of a <code>CallableStatement</code>,
838 * <code>String</code> keys for named parameters are also allowed.
839 * Please note that you can modify the match parameters with
840 * {@link #setCaseSensitive}, {@link #setExactMatch} and
841 * {@link #setUseRegularExpressions} and the match parameters for the
842 * specified parameter list with {@link #setExactMatchParameter}.
843 * @param sql the SQL string
844 * @param generatedKeysResult the generated keys {@link MockResultSet}
845 * @param parameters the parameters
846 */
847 public void prepareGeneratedKeys(String sql, MockResultSet generatedKeysResult, Map parameters)
848 {
849 List list = getListFromMapForSQLStatement(sql, generatedKeysForStatement);
850 list.add(new MockResultSetWrapper(generatedKeysResult, new HashMap(parameters)));
851 }
852
853 private List getListFromMapForSQLStatement(String sql, Map map)
854 {
855 List list = (List)map.get(sql);
856 if(null == list)
857 {
858 list = new ArrayList();
859 map.put(sql, list);
860 }
861 return list;
862 }
863
864 private Map createParameterMap(List parameters)
865 {
866 Map params = new HashMap();
867 for(int ii = 0; ii < parameters.size(); ii++)
868 {
869 params.put(new Integer(ii + 1), parameters.get(ii));
870 }
871 return params;
872 }
873
874 protected class ParameterWrapper
875 {
876 private Map parameters;
877
878 public ParameterWrapper(Map parameters)
879 {
880 this.parameters = parameters;
881 }
882
883 public Map getParamters()
884 {
885 return parameters;
886 }
887 }
888
889 private class MockSQLExceptionWrapper extends ParameterWrapper
890 {
891 private SQLException exception;
892
893
894 public MockSQLExceptionWrapper(SQLException exception, Map parameters)
895 {
896 super(parameters);
897 this.exception = exception;
898 }
899
900 public SQLException getException()
901 {
902 return exception;
903 }
904 }
905
906 private class MockResultSetWrapper extends ParameterWrapper
907 {
908 private MockResultSet resultSet;
909
910 public MockResultSetWrapper(MockResultSet resultSet, Map parameters)
911 {
912 super(parameters);
913 this.resultSet = resultSet;
914 }
915
916 public MockResultSet getResultSet()
917 {
918 return resultSet;
919 }
920 }
921
922 private class MockResultSetArrayWrapper extends ParameterWrapper
923 {
924 private MockResultSet[] resultSets;
925
926 public MockResultSetArrayWrapper(MockResultSet[] resultSets, Map parameters)
927 {
928 super(parameters);
929 this.resultSets = resultSets;
930 }
931
932 public MockResultSet[] getResultSets()
933 {
934 return resultSets;
935 }
936 }
937
938 private class MockUpdateCountWrapper extends ParameterWrapper
939 {
940 private Integer updateCount;
941
942 public MockUpdateCountWrapper(int updateCount, Map parameters)
943 {
944 super(parameters);
945 this.updateCount = new Integer(updateCount);
946 }
947
948 public Integer getUpdateCount()
949 {
950 return updateCount;
951 }
952 }
953
954 private class MockUpdateCountArrayWrapper extends ParameterWrapper
955 {
956 private Integer[] updateCounts;
957
958 public MockUpdateCountArrayWrapper(int[] updateCounts, Map parameters)
959 {
960 super(parameters);
961 this.updateCounts = (Integer[])ArrayUtil.convertToObjectArray(updateCounts);
962 }
963
964 public Integer[] getUpdateCount()
965 {
966 return updateCounts;
967 }
968 }
969 }