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 }