001 package com.mockrunner.jdbc;
002
003 import java.sql.SQLException;
004 import java.util.ArrayList;
005 import java.util.Collections;
006 import java.util.List;
007 import java.util.Map;
008 import java.util.TreeMap;
009
010 import com.mockrunner.mock.jdbc.MockResultSet;
011 import com.mockrunner.util.common.ArrayUtil;
012
013 /**
014 * Abstract base class for all <code>ResultSet</code> handlers.
015 * Used to coordinate <code>ResultSet</code> objects for a
016 * statement. You can use this class to prepare <code>ResultSet</code>
017 * objects and update count values that are returned by the
018 * <code>execute</code> method of a statement, if the current
019 * SQL string matches.
020 * Furthermore it can be used to create <code>ResultSet</code> objects.
021 * Please note that the <code>ResultSet</code> objects you create and
022 * prepare with this handler are cloned when executing statements.
023 * So you cannot rely on object identity. You have to use the id
024 * of the <code>ResultSet</code> to identify it.
025 * The <code>ResultSet</code> objects returned by {@link #getReturnedResultSets}
026 * are actually the instances the executed statements returned.
027 */
028 public abstract class AbstractResultSetHandler
029 {
030 private boolean caseSensitive = false;
031 private boolean exactMatch = false;
032 private boolean useRegularExpressions = false;
033 private boolean continueProcessingOnBatchFailure = false;
034 private Object globalResultSets;
035 private Map resultSetsForStatement = new TreeMap();
036 private Object globalUpdateCounts;
037 private Map updateCountForStatement = new TreeMap();
038 private MockResultSet globalGeneratedKeys;
039 private Map generatedKeysForStatement = new TreeMap();
040 private Map returnsResultSetMap = new TreeMap();
041 private Map throwsSQLException = new TreeMap();
042 private List executedStatements = new ArrayList();
043 private List returnedResultSets = new ArrayList();
044
045 /**
046 * Creates a new <code>ResultSet</code> with a
047 * random id.
048 * @return the new <code>ResultSet</code>
049 */
050 public MockResultSet createResultSet()
051 {
052 return new MockResultSet(String.valueOf(Math.random()));
053 }
054
055 /**
056 * Creates a new <code>ResultSet</code> with the specified id.
057 * @param id the id
058 * @return the new <code>ResultSet</code>
059 */
060 public MockResultSet createResultSet(String id)
061 {
062 return new MockResultSet(id);
063 }
064
065 /**
066 * Returns a new <code>ResultSet</code> created by the specified factory.
067 * Creates a random id.
068 * @param factory the {@link ResultSetFactory}
069 * @return the new <code>ResultSet</code>
070 */
071 public MockResultSet createResultSet(ResultSetFactory factory)
072 {
073 return factory.create(String.valueOf(Math.random()));
074 }
075
076 /**
077 * Returns a new <code>ResultSet</code> created by the specified factory.
078 * @param id the id
079 * @param factory the {@link ResultSetFactory}
080 * @return the new <code>ResultSet</code>
081 */
082 public MockResultSet createResultSet(String id, ResultSetFactory factory)
083 {
084 return factory.create(id);
085 }
086
087 /**
088 * Set if specified SQL strings should be handled case sensitive.
089 * Defaults to to <code>false</code>, i.e. <i>INSERT</i> is the same
090 * as <i>insert</i>.
091 * Please note that this method controls SQL statement
092 * matching for prepared results and update counts, i.e. what
093 * statements the tested application has to execute to receive
094 * a specified result. Unlike {@link JDBCTestModule#setCaseSensitive(boolean)}
095 * it does not control the statement matching of {@link JDBCTestModule}
096 * methods.
097 * @param caseSensitive enable or disable case sensitivity
098 */
099 public void setCaseSensitive(boolean caseSensitive)
100 {
101 this.caseSensitive = caseSensitive;
102 }
103
104 /**
105 * Set if specified SQL statements must match exactly.
106 * Defaults to <code>false</code>, i.e. the SQL string
107 * does not need to match exactly. If the original statement
108 * is <i>insert into mytable values(?, ?, ?)</i>
109 * the string <i>insert into mytable</i> will match this statement.
110 * Usually <code>false</code> is the best choice, so
111 * prepared <code>ResultSet</code> objects do not have
112 * to match exactly the current statements SQL string.
113 * The current SQL string just has to contain the SQL string
114 * for the prepared prepared <code>ResultSet</code>.
115 * Please note that this method controls SQL statement
116 * matching for prepared results and update counts, i.e. what
117 * statements the tested application has to execute to receive
118 * a specified result. Unlike {@link JDBCTestModule#setExactMatch(boolean)}
119 * it does not control the statement matching of {@link JDBCTestModule}
120 * methods.
121 * @param exactMatch enable or disable exact matching
122 */
123 public void setExactMatch(boolean exactMatch)
124 {
125 this.exactMatch = exactMatch;
126 }
127
128 /**
129 * Set if regular expressions should be used when matching
130 * SQL statements. Irrelevant if <code>exactMatch</code> is
131 * <code>true</code>. Default is <code>false</code>, i.e. you
132 * cannot use regular expressions and matching is based
133 * on string comparison.
134 * Please note that this method controls SQL statement
135 * matching for prepared results and update counts, i.e. what
136 * statements the tested application has to execute to receive
137 * a specified result. Unlike {@link JDBCTestModule#setUseRegularExpressions(boolean)}
138 * it does not control the statement matching of {@link JDBCTestModule}
139 * methods.
140 * @param useRegularExpressions should regular expressions be used
141 */
142 public void setUseRegularExpressions(boolean useRegularExpressions)
143 {
144 this.useRegularExpressions = useRegularExpressions;
145 }
146
147 /**
148 * Set if batch processing should be continued if one of the commands
149 * in the batch fails. This behaviour is driver dependend. The default is
150 * <code>false</code>, i.e. if a command fails with an exception,
151 * batch processing will not continue and the remaining commands
152 * will not be executed.
153 * @param continueProcessingOnBatchFailure should batch processing be continued
154 */
155 public void setContinueProcessingOnBatchFailure(boolean continueProcessingOnBatchFailure)
156 {
157 this.continueProcessingOnBatchFailure = continueProcessingOnBatchFailure;
158 }
159
160 /**
161 * Collects all SQL strings that were executed.
162 * @param sql the SQL string
163 */
164 public void addExecutedStatement(String sql)
165 {
166 executedStatements.add(sql);
167 }
168
169 /**
170 * Collects all <code>ResultSet</code> objects that were returned by
171 * a <code>Statement</code>, <code>PreparedStatement</code> or
172 * <code>CallableStatement</code>.
173 * @param resultSet the <code>ResultSet</code>
174 */
175 public void addReturnedResultSet(MockResultSet resultSet)
176 {
177 if(null == resultSet) return;
178 returnedResultSets.add(resultSet);
179 }
180
181 /**
182 * Collects all <code>ResultSet[]</code> objects that were returned by
183 * a <code>Statement</code>, <code>PreparedStatement</code> or
184 * <code>CallableStatement</code>. Called if a statement returns
185 * multiple result sets.
186 * @param resultSets the <code>ResultSet[]</code>
187 */
188 public void addReturnedResultSets(MockResultSet[] resultSets)
189 {
190 if(null == resultSets) return;
191 returnedResultSets.add(resultSets);
192 }
193
194 /**
195 * Returns the <code>List</code> of all executed SQL strings.
196 * @return the <code>List</code> of executed SQL strings
197 */
198 public List getExecutedStatements()
199 {
200 return Collections.unmodifiableList(executedStatements);
201 }
202
203 /**
204 * Returns the <code>List</code> of all returned <code>ResultSet</code>
205 * or <code>ResultSet[]</code> objects. The <code>List</code> contains
206 * arrays of result sets, if a query returned multiple result sets.
207 * If a query returned multiple result sets, the list will always contain
208 * the full array of <code>ResultSet</code> objects that were prepared, even
209 * if {@link com.mockrunner.mock.jdbc.MockStatement#getMoreResults()} was
210 * not called for all the result sets.
211 * @return the <code>List</code> of returned <code>ResultSet</code> or <code>ResultSet[]</code> objects
212 */
213 public List getReturnedResultSets()
214 {
215 return Collections.unmodifiableList(returnedResultSets);
216 }
217
218 /**
219 * Clears all prepared <code>ResultSet</code> objects.
220 */
221 public void clearResultSets()
222 {
223 resultSetsForStatement.clear();
224 }
225
226 /**
227 * Clears all prepared update counts.
228 */
229 public void clearUpdateCounts()
230 {
231 updateCountForStatement.clear();
232 }
233
234 /**
235 * Clears the definitions if statements return
236 * <code>ResultSet</code> objects or update counts.
237 */
238 public void clearReturnsResultSet()
239 {
240 returnsResultSetMap.clear();
241 }
242
243 /**
244 * Clears the list of statements that should throw an exception.
245 */
246 public void clearThrowsSQLException()
247 {
248 throwsSQLException.clear();
249 }
250
251 /**
252 * Clears the list of statements that return generated keys.
253 */
254 public void clearGeneratedKeys()
255 {
256 generatedKeysForStatement.clear();
257 }
258
259 /**
260 * Clears the prepared global <code>ResultSet</code>.
261 */
262 public void clearGlobalResultSet()
263 {
264 this.globalResultSets = null;
265 }
266
267 /**
268 * Clears the prepared global generated keys <code>ResultSet</code>.
269 */
270 public void clearGlobalGeneratedKeys()
271 {
272 this.globalGeneratedKeys = null;
273 }
274
275 /**
276 * Clears the prepared global update count.
277 */
278 public void clearGlobalUpdateCount()
279 {
280 this.globalUpdateCounts = null;
281 }
282
283 /**
284 * Returns the <code>Map</code> of all <code>ResultSet</code>
285 * objects, that were added with {@link #prepareResultSet(String, MockResultSet)}.
286 * The SQL strings map to the corresponding <code>ResultSet</code>.
287 * @return the <code>Map</code> of <code>ResultSet</code> objects
288 */
289 public Map getResultSetMap()
290 {
291 return Collections.unmodifiableMap(resultSetsForStatement);
292 }
293
294 /**
295 * Returns the <code>Map</code> of all update counts, that were added
296 * with {@link #prepareUpdateCount(String, int)}.
297 * The SQL strings map to the corresponding update count as
298 * <code>Integer</code> object.
299 * @return the <code>Map</code> of <code>ResultSet</code> objects
300 */
301 public Map getUpdateCountMap()
302 {
303 return Collections.unmodifiableMap(updateCountForStatement);
304 }
305
306 /**
307 * Returns the <code>Map</code> of all generated keys <code>ResultSet</code>
308 * objects, that were added with {@link #prepareGeneratedKeys(String, MockResultSet)}.
309 * The SQL strings map to the corresponding generated keys <code>ResultSet</code>.
310 * @return the <code>Map</code> of generated keys <code>ResultSet</code> objects
311 */
312 public Map getGeneratedKeysMap()
313 {
314 return Collections.unmodifiableMap(generatedKeysForStatement);
315 }
316
317 /**
318 * Returns the first <code>ResultSet</code> that matches the
319 * specified SQL string. If the specified SQL string was
320 * prepared to return multiple result sets, the first one will
321 * be returned.
322 * Please note that you can modify the match parameters with {@link #setCaseSensitive},
323 * {@link #setExactMatch} and {@link #setUseRegularExpressions}.
324 * @param sql the SQL string
325 * @return the corresponding {@link MockResultSet}
326 */
327 public MockResultSet getResultSet(String sql)
328 {
329 Object resultSets = getMatchingResultSets(sql);
330 if(null == resultSets) return null;
331 if(resultSets instanceof MockResultSet)
332 {
333 return (MockResultSet)resultSets;
334 }
335 else if(resultSets instanceof MockResultSet[])
336 {
337 MockResultSet[] actualResults = (MockResultSet[])resultSets;
338 if(actualResults.length > 0)
339 {
340 return actualResults[0];
341 }
342 }
343 return null;
344 }
345
346 /**
347 * Returns the first <code>ResultSet[]</code> that matches the
348 * specified SQL string. If the specified SQL string was
349 * prepared to return one single result set, this <code>ResultSet</code>
350 * will be wrapped in an array with one element.
351 * Please note that you can modify the match parameters with {@link #setCaseSensitive},
352 * {@link #setExactMatch} and {@link #setUseRegularExpressions}.
353 * @param sql the SQL string
354 * @return the corresponding <code>MockResultSet[]</code>
355 */
356 public MockResultSet[] getResultSets(String sql)
357 {
358 Object resultSets = getMatchingResultSets(sql);
359 if(null == resultSets) return null;
360 if(resultSets instanceof MockResultSet)
361 {
362 return new MockResultSet[] {(MockResultSet)resultSets};
363 }
364 else if(resultSets instanceof MockResultSet[])
365 {
366 return (MockResultSet[])resultSets;
367 }
368 return null;
369 }
370
371 /**
372 * Returns the if the specified SQL string returns multiple result sets.
373 * Please note that you can modify the match parameters with {@link #setCaseSensitive},
374 * {@link #setExactMatch} and {@link #setUseRegularExpressions}.
375 * @param sql the SQL string
376 * @return <code>true</code> if the query returns multiple result sets,
377 * <code>false</code> otherwise
378 */
379 public boolean hasMultipleResultSets(String sql)
380 {
381 Object resultSets = getMatchingResultSets(sql);
382 return (resultSets instanceof MockResultSet[]);
383 }
384
385 private Object getMatchingResultSets(String sql)
386 {
387 SQLStatementMatcher matcher = new SQLStatementMatcher(getCaseSensitive(), getExactMatch(), getUseRegularExpressions());
388 List list = matcher.getMatchingObjects(resultSetsForStatement, sql, true, true);
389 if(null != list && list.size() > 0)
390 {
391 return list.get(0);
392 }
393 return null;
394 }
395
396 /**
397 * Returns the global <code>ResultSet</code>.
398 * If an array of global result sets was prepared, the first one will
399 * be returned.
400 * @return the global {@link MockResultSet}
401 */
402 public MockResultSet getGlobalResultSet()
403 {
404 if(null == globalResultSets) return null;
405 if(globalResultSets instanceof MockResultSet)
406 {
407 return (MockResultSet)globalResultSets;
408 }
409 MockResultSet[] resultSets = getGlobalResultSets();
410 if(null != resultSets && resultSets.length > 0)
411 {
412 return resultSets[0];
413 }
414 return null;
415 }
416
417 /**
418 * Returns the global <code>ResultSet[]</code>.
419 * If one single <code>ResultSet</code> was prepared, this <code>ResultSet</code>
420 * will be wrapped in an array with one element.
421 * @return the global <code>MockResultSet[]</code>
422 */
423 public MockResultSet[] getGlobalResultSets()
424 {
425 if(null == globalResultSets) return null;
426 if(globalResultSets instanceof MockResultSet[])
427 {
428 return (MockResultSet[])globalResultSets;
429 }
430 return new MockResultSet[] {(MockResultSet)globalResultSets};
431 }
432
433 /**
434 * Returns if multiple global result sets have been prepared, i.e. if
435 * an array of global result sets was prepared.
436 * @return <code>true</code> if an array of global result sets was prepared,
437 * <code>false</code> otherwise
438 */
439 public boolean hasMultipleGlobalResultSets()
440 {
441 return (globalResultSets instanceof MockResultSet[]);
442 }
443
444 /**
445 * Returns the first update count that matches the
446 * specified SQL string. If the specified SQL string was
447 * prepared to return multiple update counts, the first one will
448 * be returned.
449 * Please note that you can modify the match parameters with {@link #setCaseSensitive},
450 * {@link #setExactMatch} and {@link #setUseRegularExpressions}.
451 * @param sql the SQL string
452 * @return the corresponding update count
453 */
454 public Integer getUpdateCount(String sql)
455 {
456 Object updateCounts = getMatchingUpdateCounts(sql);
457 if(null == updateCounts) return null;
458 if(updateCounts instanceof Integer)
459 {
460 return (Integer)updateCounts;
461 }
462 else if(updateCounts instanceof Integer[])
463 {
464 Integer[] actualUpdateCounts = (Integer[])updateCounts;
465 if(actualUpdateCounts.length > 0)
466 {
467 return actualUpdateCounts[0];
468 }
469 }
470 return null;
471 }
472
473 /**
474 * Returns the first update count array that matches the
475 * specified SQL string. If the specified SQL string was
476 * prepared to return one update count, this value
477 * will be wrapped in an array with one element.
478 * Please note that you can modify the match parameters with {@link #setCaseSensitive},
479 * {@link #setExactMatch} and {@link #setUseRegularExpressions}.
480 * @param sql the SQL string
481 * @return the corresponding update count array
482 */
483 public Integer[] getUpdateCounts(String sql)
484 {
485 Object updateCounts = getMatchingUpdateCounts(sql);
486 if(null == updateCounts) return null;
487 if(updateCounts instanceof Integer)
488 {
489 return new Integer[] {(Integer)updateCounts};
490 }
491 else if(updateCounts instanceof Integer[])
492 {
493 return (Integer[])updateCounts;
494 }
495 return null;
496 }
497
498 /**
499 * Returns the if the specified SQL string returns multiple update counts.
500 * Please note that you can modify the match parameters with {@link #setCaseSensitive},
501 * {@link #setExactMatch} and {@link #setUseRegularExpressions}.
502 * @param sql the SQL string
503 * @return <code>true</code> if the SQL string returns multiple update counts,
504 * <code>false</code> otherwise
505 */
506 public boolean hasMultipleUpdateCounts(String sql)
507 {
508 Object updateCounts = getMatchingUpdateCounts(sql);
509 return (updateCounts instanceof Integer[]);
510 }
511
512 private Object getMatchingUpdateCounts(String sql)
513 {
514 SQLStatementMatcher matcher = new SQLStatementMatcher(getCaseSensitive(), getExactMatch(), getUseRegularExpressions());
515 List list = matcher.getMatchingObjects(updateCountForStatement, sql, true, true);
516 if(null != list && list.size() > 0)
517 {
518 return list.get(0);
519 }
520 return null;
521 }
522
523 /**
524 * Returns the global update count for <code>executeUpdate</code> calls.
525 * If an array of global update counts was prepared, the first one will
526 * be returned.
527 * @return the global update count
528 */
529 public int getGlobalUpdateCount()
530 {
531 if(null == globalUpdateCounts) return 0;
532 if(globalUpdateCounts instanceof Integer)
533 {
534 return ((Integer)globalUpdateCounts).intValue();
535 }
536 int[] updateCounts = getGlobalUpdateCounts();
537 if(null != updateCounts && updateCounts.length > 0)
538 {
539 return updateCounts[0];
540 }
541 return 0;
542 }
543
544 /**
545 * Returns the array of global update counts.
546 * If one single update count value was prepared, this value
547 * will be wrapped in an array with one element.
548 * @return the array of global update counts
549 */
550 public int[] getGlobalUpdateCounts()
551 {
552 if(null == globalUpdateCounts) return null;
553 if(globalUpdateCounts instanceof int[])
554 {
555 return (int[])globalUpdateCounts;
556 }
557 return new int[] {((Integer)globalUpdateCounts).intValue()};
558 }
559
560 /**
561 * Returns if multiple global update counts have been prepared, i.e. if
562 * an array of global update counts was prepared.
563 * @return <code>true</code> if an array of global update counts was prepared,
564 * <code>false</code> otherwise
565 */
566 public boolean hasMultipleGlobalUpdateCounts()
567 {
568 return (globalUpdateCounts instanceof int[]);
569 }
570
571 /**
572 * Returns the first generated keys <code>ResultSet</code> that
573 * matches the specified SQL string. Please note that you can modify
574 * the match parameters with {@link #setCaseSensitive},
575 * {@link #setExactMatch} and {@link #setUseRegularExpressions}.
576 * @param sql the SQL string
577 * @return the corresponding generated keys {@link MockResultSet}
578 */
579 public MockResultSet getGeneratedKeys(String sql)
580 {
581 SQLStatementMatcher matcher = new SQLStatementMatcher(getCaseSensitive(), getExactMatch(), getUseRegularExpressions());
582 List list = matcher.getMatchingObjects(generatedKeysForStatement, sql, true, true);
583 if(null != list && list.size() > 0)
584 {
585 return (MockResultSet)list.get(0);
586 }
587 return null;
588 }
589
590 /**
591 * Returns the global generated keys <code>ResultSet</code>.
592 * @return the global generated keys {@link MockResultSet}
593 */
594 public MockResultSet getGlobalGeneratedKeys()
595 {
596 return globalGeneratedKeys;
597 }
598
599 /**
600 * Returns if the specified SQL string is a <i>select</i> that returns
601 * a <code>ResultSet</code>.
602 * Usually you do not have to specify this.
603 * It is assumed that an SQL string returns a <code>ResultSet</code>
604 * if it contains the string <i>select</i> (case insensitive).
605 * Please note that you can modify the match parameters with
606 * {@link #setCaseSensitive}, {@link #setExactMatch} and
607 * {@link #setUseRegularExpressions}.
608 * @param sql the SQL string
609 * @return <code>true</code> if the SQL string returns a <code>ResultSet</code>
610 */
611 public Boolean getReturnsResultSet(String sql)
612 {
613 SQLStatementMatcher matcher = new SQLStatementMatcher(getCaseSensitive(), getExactMatch(), getUseRegularExpressions());
614 List list = matcher.getMatchingObjects(returnsResultSetMap, sql, true, true);
615 if(null != list && list.size() > 0)
616 {
617 return (Boolean)list.get(0);
618 }
619 return null;
620 }
621
622 /**
623 * Returns if the specified SQL string should raise an exception.
624 * This can be used to simulate database exceptions.
625 * Please note that you can modify the match parameters with
626 * {@link #setCaseSensitive}, {@link #setExactMatch} and
627 * {@link #setUseRegularExpressions}.
628 * @param sql the SQL string
629 * @return <code>true</code> if the specified SQL string should raise an exception,
630 * <code>false</code> otherwise
631 */
632 public boolean getThrowsSQLException(String sql)
633 {
634 return (getSQLException(sql) != null);
635 }
636
637 /**
638 * Returns the <code>SQLException</code> the specified SQL string
639 * should throw. Returns <code>null</code> if the specified SQL string
640 * should not throw an exception.
641 * This can be used to simulate database exceptions.
642 * Please note that you can modify the match parameters with
643 * {@link #setCaseSensitive}, {@link #setExactMatch} and
644 * {@link #setUseRegularExpressions}.
645 * @param sql the SQL string
646 * @return the <code>SQLException</code> or <code>null</code>
647 */
648 public SQLException getSQLException(String sql)
649 {
650 SQLStatementMatcher matcher = new SQLStatementMatcher(getCaseSensitive(), getExactMatch(), getUseRegularExpressions());
651 List list = matcher.getMatchingObjects(throwsSQLException, sql, true, true);
652 if(null == list || list.size() == 0) return null;
653 return (SQLException)list.get(0);
654 }
655
656 /**
657 * Prepare a <code>ResultSet</code> for a specified SQL string.
658 * Please note that you can modify the match parameters with
659 * {@link #setCaseSensitive}, {@link #setExactMatch} and
660 * {@link #setUseRegularExpressions}.
661 * @param sql the SQL string
662 * @param resultSet the corresponding {@link MockResultSet}
663 */
664 public void prepareResultSet(String sql, MockResultSet resultSet)
665 {
666 resultSetsForStatement.put(sql, resultSet);
667 }
668
669 /**
670 * Prepare an array of <code>ResultSet</code> objects for a specified SQL string.
671 * This method can be used for queries that return multiple result sets.
672 * Please note that you can modify the match parameters with
673 * {@link #setCaseSensitive}, {@link #setExactMatch} and
674 * {@link #setUseRegularExpressions}.
675 * @param sql the SQL string
676 * @param resultSets the corresponding <code>MockResultSet[]</code>
677 */
678 public void prepareResultSets(String sql, MockResultSet[] resultSets)
679 {
680 resultSetsForStatement.put(sql, resultSets.clone());
681 }
682
683 /**
684 * Prepare the global <code>ResultSet</code>.
685 * @param resultSet the {@link MockResultSet}
686 */
687 public void prepareGlobalResultSet(MockResultSet resultSet)
688 {
689 this.globalResultSets = resultSet;
690 }
691
692 /**
693 * Prepare an array of global <code>ResultSet</code> objects.
694 * @param resultSets the corresponding <code>MockResultSet[]</code>
695 */
696 public void prepareGlobalResultSets(MockResultSet[] resultSets)
697 {
698 this.globalResultSets = (MockResultSet[])resultSets.clone();
699 }
700
701 /**
702 * Prepare the update count for <code>executeUpdate</code> calls
703 * for a specified SQL string. Please note that you can modify
704 * the match parameters with {@link #setCaseSensitive},
705 * {@link #setExactMatch} and {@link #setUseRegularExpressions}.
706 * @param sql the SQL string
707 * @param updateCount the update count
708 */
709 public void prepareUpdateCount(String sql, int updateCount)
710 {
711 updateCountForStatement.put(sql, new Integer(updateCount));
712 }
713
714 /**
715 * Prepare an array update count values for <code>executeUpdate</code> calls
716 * for a specified SQL string. This method can be used if multiple update counts
717 * are returned.
718 * Please note that you can modify the match parameters with {@link #setCaseSensitive},
719 * {@link #setExactMatch} and {@link #setUseRegularExpressions}.
720 * @param sql the SQL string
721 * @param updateCounts the update count array
722 */
723 public void prepareUpdateCounts(String sql, int[] updateCounts)
724 {
725 updateCountForStatement.put(sql, ArrayUtil.convertToObjectArray(updateCounts));
726 }
727
728 /**
729 * Prepare the global update count for <code>executeUpdate</code> calls.
730 * @param updateCount the update count
731 */
732 public void prepareGlobalUpdateCount(int updateCount)
733 {
734 this.globalUpdateCounts = new Integer(updateCount);
735 }
736
737 /**
738 * Prepare an array of global update count values for <code>executeUpdate</code> calls.
739 * @param updateCounts the update count array
740 */
741 public void prepareGlobalUpdateCounts(int[] updateCounts)
742 {
743 this.globalUpdateCounts = (int[])updateCounts.clone();
744 }
745
746 /**
747 * Prepare the generated keys <code>ResultSet</code>
748 * for a specified SQL string. Please note that you can modify
749 * the match parameters with {@link #setCaseSensitive},
750 * {@link #setExactMatch} and {@link #setUseRegularExpressions}.
751 * @param sql the SQL string
752 * @param generatedKeysResult the generated keys {@link MockResultSet}
753 */
754 public void prepareGeneratedKeys(String sql, MockResultSet generatedKeysResult)
755 {
756 generatedKeysForStatement.put(sql, generatedKeysResult);
757 }
758
759 /**
760 * Prepare the global generated keys <code>ResultSet</code>.
761 * @param generatedKeysResult the generated keys {@link MockResultSet}
762 */
763 public void prepareGlobalGeneratedKeys(MockResultSet generatedKeysResult)
764 {
765 this.globalGeneratedKeys = generatedKeysResult;
766 }
767
768 /**
769 * Prepare if the specified SQL string is a <i>select</i> that returns
770 * a <code>ResultSet</code>. Usually you do not have to specify this.
771 * It is assumed that an SQL string returns a <code>ResultSet</code>
772 * if it contains the string <i>select</i> (case insensitive).
773 * Please note that you can modify the match parameters with
774 * {@link #setCaseSensitive}, {@link #setExactMatch} and
775 * {@link #setUseRegularExpressions}.
776 * @param sql the SQL string
777 * @param returnsResultSet specify if the SQL string returns a <code>ResultSet</code>
778 */
779 public void prepareReturnsResultSet(String sql, boolean returnsResultSet)
780 {
781 returnsResultSetMap.put(sql, new Boolean(returnsResultSet));
782 }
783
784 /**
785 * Prepare that the specified SQL string should raise an exception.
786 * This can be used to simulate database exceptions. This method
787 * creates an <code>SQLException</code> and will throw this exception.
788 * With {@link #prepareThrowsSQLException(String, SQLException)} you
789 * can specify the exception.
790 * Please note that you can modify the match parameters with
791 * {@link #setCaseSensitive}, {@link #setExactMatch} and
792 * {@link #setUseRegularExpressions}.
793 * @param sql the SQL string
794 */
795 public void prepareThrowsSQLException(String sql)
796 {
797 throwsSQLException.put(sql, new SQLException("Statement " + sql + " was specified to throw an exception"));
798 }
799
800 /**
801 * Prepare that the specified SQL string should raise an exception.
802 * This can be used to simulate database exceptions. This method
803 * takes an exception object that will be thrown.
804 * Please note that you can modify the match parameters with
805 * {@link #setCaseSensitive}, {@link #setExactMatch} and
806 * {@link #setUseRegularExpressions}.
807 * @param sql the SQL string
808 * @param exc the <code>SQLException</code> that should be thrown
809 */
810 public void prepareThrowsSQLException(String sql, SQLException exc)
811 {
812 throwsSQLException.put(sql, exc);
813 }
814
815 /**
816 * Returns if specified SQL strings should be handled case sensitive.
817 * @return is case sensitivity enabled or disabled
818 */
819 protected boolean getCaseSensitive()
820 {
821 return caseSensitive;
822 }
823
824 /**
825 * Returns if specified SQL statements must match exactly.
826 * @return is exact matching enabled or disabled
827 */
828 protected boolean getExactMatch()
829 {
830 return exactMatch;
831 }
832
833 /**
834 * Returns if regular expression matching is enabled
835 * @return if regular expression matching is enabled
836 */
837 protected boolean getUseRegularExpressions()
838 {
839 return useRegularExpressions;
840 }
841
842 /**
843 * Returns if batch processing should be continued if one of
844 * the commands in the batch fails.
845 * @return if batch processing should be continued
846 */
847 public boolean getContinueProcessingOnBatchFailure()
848 {
849 return continueProcessingOnBatchFailure;
850 }
851 }