001 package com.mockrunner.mock.jdbc; 002 003 import java.io.ByteArrayInputStream; 004 import java.io.InputStream; 005 import java.io.Reader; 006 import java.io.StringReader; 007 import java.io.UnsupportedEncodingException; 008 import java.math.BigDecimal; 009 import java.net.MalformedURLException; 010 import java.net.URL; 011 import java.sql.Array; 012 import java.sql.Blob; 013 import java.sql.Clob; 014 import java.sql.Date; 015 import java.sql.Ref; 016 import java.sql.ResultSet; 017 import java.sql.ResultSetMetaData; 018 import java.sql.SQLException; 019 import java.sql.SQLWarning; 020 import java.sql.Statement; 021 import java.sql.Time; 022 import java.sql.Timestamp; 023 import java.util.ArrayList; 024 import java.util.Calendar; 025 import java.util.Collections; 026 import java.util.Iterator; 027 import java.util.List; 028 import java.util.Map; 029 030 import com.mockrunner.base.NestedApplicationException; 031 import com.mockrunner.jdbc.ParameterUtil; 032 import com.mockrunner.jdbc.SQLUtil; 033 import com.mockrunner.util.common.ArrayUtil; 034 import com.mockrunner.util.common.CaseAwareMap; 035 import com.mockrunner.util.common.CollectionUtil; 036 import com.mockrunner.util.common.StreamUtil; 037 import com.mockrunner.util.common.StringUtil; 038 039 /** 040 * Mock implementation of <code>ResultSet</code>. 041 * Can be used to add simulated database entries. 042 * You can add Java objects of any type. This 043 * mock implementation does not care about SQL 044 * data types. It tries to perform the necessary 045 * type conversions for the Java objects (e.g. it will convert a 046 * <code>String</code> "1" to <code>int</code> 1). 047 * Please check out the documentation of <code>ResultSet</code> 048 * for the description of the methods in this interface. 049 * The additional methods are described here. 050 */ 051 public class MockResultSet implements ResultSet, Cloneable 052 { 053 private Statement statement; 054 private String id; 055 private Map columnMap; 056 private Map columnMapCopy; 057 private Map insertRow; 058 private List columnNameList; 059 private List updatedRows; 060 private List deletedRows; 061 private List insertedRows; 062 private int cursor; 063 private boolean isCursorInInsertRow; 064 private boolean wasNull; 065 private String cursorName; 066 private int fetchSize = 0; 067 private int fetchDirection = ResultSet.FETCH_FORWARD; 068 private int resultSetType = ResultSet.TYPE_SCROLL_INSENSITIVE; 069 private int resultSetConcurrency = ResultSet.CONCUR_READ_ONLY; 070 private boolean isDatabaseView; 071 private ResultSetMetaData resultSetMetaData; 072 private boolean closed; 073 private boolean columnsCaseSensitive; 074 075 public MockResultSet(String id) 076 { 077 this(id, ""); 078 } 079 080 public MockResultSet(String id, String cursorName) 081 { 082 init(); 083 this.cursorName = cursorName; 084 this.id = id; 085 columnsCaseSensitive = false; 086 } 087 088 private void init() 089 { 090 columnMap = createCaseAwareMap(); 091 columnNameList = new ArrayList(); 092 updatedRows = new ArrayList(); 093 deletedRows = new ArrayList(); 094 insertedRows = new ArrayList(); 095 cursor = -1; 096 wasNull = false; 097 closed = false; 098 isCursorInInsertRow = false; 099 isDatabaseView = false; 100 resultSetMetaData = null; 101 copyColumnMap(); 102 adjustInsertRow(); 103 } 104 105 /** 106 * Set if column names are case sensitive. Default is 107 * <code>false</code>. Please note, that switching this 108 * attribute clears and resets the complete <code>ResultSet</code>. 109 * @param columnsCaseSensitive are column names case sensitive 110 */ 111 public void setColumnsCaseSensitive(boolean columnsCaseSensitive) 112 { 113 this.columnsCaseSensitive = columnsCaseSensitive; 114 init(); 115 } 116 117 /** 118 * Copies this <code>ResultSet</code>. The data of the 119 * <code>ResultSet</code> is copied using the 120 * {@link com.mockrunner.jdbc.ParameterUtil#copyParameter} 121 * method. 122 * @return a copy of this <code>ResultSet</code> 123 */ 124 public Object clone() 125 { 126 try 127 { 128 MockResultSet copy = (MockResultSet)super.clone(); 129 copy.columnNameList = new ArrayList(columnNameList); 130 copy.updatedRows = new ArrayList(updatedRows); 131 copy.deletedRows = new ArrayList(deletedRows); 132 copy.insertedRows = new ArrayList(insertedRows); 133 copy.insertRow = copyColumnDataMap(insertRow); 134 copy.columnMap = copyColumnDataMap(columnMap); 135 copy.columnMapCopy = copyColumnDataMap(columnMapCopy); 136 return copy; 137 } 138 catch(CloneNotSupportedException exc) 139 { 140 throw new NestedApplicationException(exc); 141 } 142 } 143 144 /** 145 * Returns the id of this <code>ResultSet</code>. Ids are used 146 * to identify <code>ResultSet</code> objects in tests, because 147 * they are usually cloned when executing statements, so 148 * you cannot rely on the object identity. 149 * @return the id of this <code>ResultSet</code> 150 */ 151 public String getId() 152 { 153 return id; 154 } 155 156 /** 157 * Returns if this <code>ResultSet</code> is closed. 158 * @return <code>true</code> if this <code>ResultSet</code> is closed, 159 * <code>false</code> otherwise 160 */ 161 public boolean isClosed() 162 { 163 return closed; 164 } 165 166 /** 167 * Sets the <code>ResultSetMetaData</code> for this <code>ResultSet</code>. 168 * The specified object will be returned when calling {@link #getMetaData}. 169 * If no <code>ResultSetMetaData</code> is set, the method {@link #getMetaData} 170 * will return an object of {@link MockResultSetMetaData}. The 171 * <code>MockResultSetMetaData</code> returns default values for most 172 * of its attributes (however the correct number of columns will be 173 * returned). Usually you do not have to set the <code>ResultSetMetaData</code>. 174 * @param resultSetMetaData the <code>ResultSetMetaData</code> 175 */ 176 public void setResultSetMetaData(ResultSetMetaData resultSetMetaData) 177 { 178 this.resultSetMetaData = resultSetMetaData; 179 } 180 181 /** 182 * Sets the <code>Statement</code> for this <code>ResultSet</code>. 183 * The <code>ResultSet</code> takes the result set type, result 184 * set concurrency and the fetch direction from the specified 185 * <code>Statement</code>. 186 * @param statement the statement 187 */ 188 public void setStatement(Statement statement) 189 { 190 this.statement = statement; 191 try 192 { 193 fetchDirection = statement.getFetchDirection(); 194 resultSetType = statement.getResultSetType(); 195 resultSetConcurrency = statement.getResultSetConcurrency(); 196 fetchSize = statement.getFetchSize(); 197 cursorName = ((MockStatement)statement).getCursorName(); 198 } 199 catch(SQLException exc) 200 { 201 202 } 203 } 204 205 /** 206 * Sets the cursor name. It's not possible to set 207 * this in a real <code>ResultSet</code>. 208 * @param cursorName the cursor name 209 */ 210 public void setCursorName(String cursorName) 211 { 212 this.cursorName = cursorName; 213 } 214 215 /** 216 * Sets the result set type. It's not possible to set 217 * this in a real <code>ResultSet</code>, but in tests 218 * it can make sense to change it. 219 * @param resultSetType the result set type 220 */ 221 public void setResultSetType(int resultSetType) 222 { 223 this.resultSetType = resultSetType; 224 } 225 226 /** 227 * Sets the result set concurrency. It's not possible to set 228 * this in a real <code>ResultSet</code>, but in tests 229 * it can make sense to change it. 230 * @param resultSetConcurrency the result set concurrency 231 */ 232 public void setResultSetConcurrency(int resultSetConcurrency) 233 { 234 this.resultSetConcurrency = resultSetConcurrency; 235 } 236 237 /** 238 * The <code>MockResultSet</code> keeps the data that's 239 * stored in the simulated database and a copy of the data 240 * that represents the current <code>ResultSet</code> data. 241 * The <code>update</code> methods only update the 242 * <code>ResultSet</code> data. This data will be persisted 243 * when you call {@link #updateRow}. When you set <i>databaseView</i> 244 * to <code>true</code> the <code>get</code> methods will return the 245 * data in the database, otherwise the current <code>ResultSet</code> 246 * data is returned. 247 * @param databaseView <code>false</code> = get the data from the 248 * <code>ResultSet</code>, <code>true</code> = get the data 249 * from the database, default is <code>false</code> 250 * 251 */ 252 public void setDatabaseView(boolean databaseView) 253 { 254 this.isDatabaseView = databaseView; 255 } 256 257 /** 258 * Adds a row to the simulated database table. 259 * If there are not enough columns (initially there 260 * are no columns, you have to specify them with the 261 * <code>addColumn</code> methods) the missing columns will 262 * be added automatically. Automatically created columns 263 * will get the name <i>ColumnX</i> where <i>X</i> is 264 * the column index. 265 * @param values the row data as array, the array index 266 * corresponds to the column index, i.e. 267 * values[0] will be stored in the first column 268 * and so on 269 */ 270 public void addRow(Object[] values) 271 { 272 List valueList = ArrayUtil.getListFromObjectArray(values); 273 addRow(valueList); 274 } 275 276 /** 277 * Adds a row to the simulated database table. 278 * If there are not enough columns (initially there 279 * are no columns, you have to specify them with the 280 * <code>addColumn</code> methods) the missing columns will 281 * be added automatically. Automatically created columns 282 * will get the name <i>ColumnX</i> where <i>X</i> is 283 * the column index. 284 * @param values the row data as <code>List</code>, the index 285 * in the <code>List</code> corresponds to the column 286 * index, i.e. values.get(0) will be stored in the first 287 * column and so on 288 */ 289 public void addRow(List values) 290 { 291 int missingColumns = values.size() - columnNameList.size(); 292 for(int yy = 0; yy < missingColumns; yy++) 293 { 294 addColumn(); 295 } 296 adjustColumns(); 297 for(int ii = 0; ii < values.size(); ii++) 298 { 299 Object nextValue = values.get(ii); 300 String nextColumnName = (String)columnNameList.get(ii); 301 List nextColumnList = (List)columnMap.get(nextColumnName); 302 nextColumnList.add(nextValue); 303 } 304 adjustColumns(); 305 copyColumnMap(); 306 adjustFlags(); 307 } 308 309 /** 310 * Adds a column to the simulated database table. 311 * The column will get the name <i>ColumnX</i> where 312 * <i>X</i> is the column index. The first added column 313 * will have the name <i>Column1</i>. No data will be stored 314 * in the column. 315 */ 316 public void addColumn() 317 { 318 addColumn(determineValidColumnName()); 319 } 320 321 /** 322 * Adds a column to the simulated database table. 323 * The column will get the specified name. 324 * No data will be stored in the column. 325 * @param columnName the column name 326 */ 327 public void addColumn(String columnName) 328 { 329 addColumn(columnName, new ArrayList()); 330 } 331 332 /** 333 * Adds a column to the simulated database table. 334 * The column will get the name <i>ColumnX</i> where 335 * <i>X</i> is the column index. 336 * The specified data will be stored in the new column. If there 337 * are other columns with not enough rows, the other 338 * columns will be extended and filled with <code>null</code> 339 * values. 340 * @param values the column data as array, the array index 341 * corresponds to the row index, i.e. 342 * values[0] will be stored in the first row 343 * and so on 344 */ 345 public void addColumn(Object[] values) 346 { 347 addColumn(determineValidColumnName(), values); 348 } 349 350 /** 351 * Adds a column to the simulated database table. 352 * The column will get the name <i>ColumnX</i> where 353 * <i>X</i> is the column index. 354 * The specified data will be stored in the new column. If there 355 * are other columns with not enough rows, the other 356 * columns will be extended and filled with <code>null</code> 357 * values. 358 * @param values the column data as <code>List</code>, the index 359 * in the <code>List</code> corresponds to the row 360 * index, i.e. values.get(0) will be stored in the first 361 * row and so on 362 */ 363 public void addColumn(List values) 364 { 365 addColumn(determineValidColumnName(), values); 366 } 367 368 /** 369 * Adds a column to the simulated database table. 370 * The column will get the specified name. 371 * The specified data will be stored in the new column. If there 372 * are other columns with not enough rows, the other 373 * columns will be extended and filled with <code>null</code> 374 * values. 375 * @param columnName the column name 376 * @param values the column data as array, the array index 377 * corresponds to the row index, i.e. 378 * values[0] will be stored in the first row 379 * and so on 380 */ 381 public void addColumn(String columnName, Object[] values) 382 { 383 List columnValues = ArrayUtil.getListFromObjectArray(values); 384 addColumn(columnName, columnValues); 385 } 386 387 /** 388 * Adds a column to the simulated database table. 389 * The column will get the specified name. 390 * The specified data will be stored in the new column. If there 391 * are other columns with not enough rows, the other 392 * columns will be extended and filled with <code>null</code> 393 * values. 394 * @param columnName the column name 395 * @param values the column data as <code>List</code>, the index 396 * in the <code>List</code> corresponds to the row 397 * index, i.e. values.get(0) will be stored in the first 398 * row and so on 399 */ 400 public void addColumn(String columnName, List values) 401 { 402 List column = new ArrayList(values); 403 columnMap.put(columnName, column); 404 columnNameList.add(columnName); 405 adjustColumns(); 406 adjustInsertRow(); 407 copyColumnMap(); 408 adjustFlags(); 409 } 410 411 /** 412 * Returns the current number of rows. 413 * @return the number of rows 414 */ 415 public int getRowCount() 416 { 417 if(columnMapCopy.size() == 0) return 0; 418 List column = (List)columnMapCopy.values().iterator().next(); 419 return column.size(); 420 } 421 422 /** 423 * Returns the current number of columns. 424 * @return the number of columns 425 */ 426 public int getColumnCount() 427 { 428 return columnMapCopy.size(); 429 } 430 431 /** 432 * Returns if the row with the specified number was inserted 433 * The first row has the number 1. 434 * @param number the number of the row 435 * @return <code>true</code> if the row was inserted, 436 * <code>false</code> otherwise 437 */ 438 public boolean rowInserted(int number) 439 { 440 if(number < 1) return false; 441 return ((Boolean)insertedRows.get(number - 1)).booleanValue(); 442 } 443 444 /** 445 * Returns if the row with the specified number was deleted 446 * The first row has the number 1. 447 * @param number the number of the row 448 * @return <code>true</code> if the row was deleted, 449 * <code>false</code> otherwise 450 */ 451 public boolean rowDeleted(int number) 452 { 453 if(number < 1) return false; 454 return ((Boolean)deletedRows.get(number - 1)).booleanValue(); 455 } 456 457 /** 458 * Returns if the row with the specified number was updated 459 * The first row has the number 1. 460 * @param number the number of the row 461 * @return <code>true</code> if the row was updated, 462 * <code>false</code> otherwise 463 */ 464 public boolean rowUpdated(int number) 465 { 466 if(number < 1) return false; 467 return ((Boolean)updatedRows.get(number - 1)).booleanValue(); 468 } 469 470 /** 471 * Returns if the row with the specified number is 472 * equal to the specified data. Uses {@link com.mockrunner.jdbc.ParameterUtil#compareParameter}. 473 * The first row has the number 1. If the compared parameters are not of 474 * the same type (and cannot be equal according to the 475 * {@link com.mockrunner.jdbc.ParameterUtil#compareParameter} method) they 476 * will be converted to a string with the <code>toString()</code> method before 477 * comparison. 478 * @param number the number of the row 479 * @param rowData the row data 480 * @return <code>true</code> if the row is equal to the specified data, 481 * <code>false</code> otherwise 482 */ 483 public boolean isRowEqual(int number, List rowData) 484 { 485 List currentRow = getRow(number); 486 if(null == currentRow) return false; 487 if(currentRow.size() != rowData.size()) return false; 488 for(int ii = 0; ii < currentRow.size(); ii++) 489 { 490 Object source = currentRow.get(ii); 491 Object target = rowData.get(ii); 492 if(!source.getClass().isAssignableFrom(target.getClass()) && !target.getClass().isAssignableFrom(source.getClass())) 493 { 494 source = source.toString(); 495 target = target.toString(); 496 } 497 if(!ParameterUtil.compareParameter(source, target)) 498 { 499 return false; 500 } 501 } 502 return true; 503 } 504 505 /** 506 * Returns if the column with the specified number is 507 * equal to the specified data. Uses {@link com.mockrunner.jdbc.ParameterUtil#compareParameter}. 508 * The first column has the number 1. If the compared parameters are not of 509 * the same type (and cannot be equal according to the 510 * {@link com.mockrunner.jdbc.ParameterUtil#compareParameter} method) they 511 * will be converted to a string with the <code>toString()</code> method before 512 * comparison. 513 * @param number the number of the column 514 * @param columnData the column data 515 * @return <code>true</code> if the column is equal to the specified data, 516 * <code>false</code> otherwise 517 */ 518 public boolean isColumnEqual(int number, List columnData) 519 { 520 List currentColumn = getColumn(number); 521 if(null == currentColumn) return false; 522 if(currentColumn.size() != columnData.size()) return false; 523 for(int ii = 0; ii < currentColumn.size(); ii++) 524 { 525 Object source = currentColumn.get(ii); 526 Object target = columnData.get(ii); 527 if(!source.getClass().isAssignableFrom(target.getClass()) && !target.getClass().isAssignableFrom(source.getClass())) 528 { 529 source = source.toString(); 530 target = target.toString(); 531 } 532 if(!ParameterUtil.compareParameter(source, target)) 533 { 534 return false; 535 } 536 } 537 return true; 538 } 539 540 /** 541 * Returns if the column with the specified name is 542 * equal to the specified data. Uses {@link com.mockrunner.jdbc.ParameterUtil#compareParameter}. 543 * The first column has the number 1. If the compared parameters are not of 544 * the same type (and cannot be equal according to the 545 * {@link com.mockrunner.jdbc.ParameterUtil#compareParameter} method) they 546 * will be converted to a string with the <code>toString()</code> method before 547 * comparison. 548 * @param name the name of the column 549 * @param columnData the column data 550 * @return <code>true</code> if the column is equal to the specified data, 551 * <code>false</code> otherwise 552 */ 553 public boolean isColumnEqual(String name, List columnData) 554 { 555 List currentColumn = getColumn(name); 556 if(null == currentColumn) return false; 557 if(currentColumn.size() != columnData.size()) return false; 558 for(int ii = 0; ii < currentColumn.size(); ii++) 559 { 560 Object source = currentColumn.get(ii); 561 Object target = columnData.get(ii); 562 if(!source.getClass().isAssignableFrom(target.getClass()) && !target.getClass().isAssignableFrom(source.getClass())) 563 { 564 source = source.toString(); 565 target = target.toString(); 566 } 567 if(!ParameterUtil.compareParameter(source, target)) 568 { 569 return false; 570 } 571 } 572 return true; 573 } 574 575 /** 576 * Returns if the specified <code>ResultSet</code> is equal to 577 * this <code>ResultSet</code>. If the compared parameters are not of 578 * the same type (and cannot be equal according to the 579 * {@link com.mockrunner.jdbc.ParameterUtil#compareParameter} method) they 580 * will be converted to a string with the <code>toString()</code> method before 581 * comparison. 582 * @return <code>true</code> if the two <code>ResultSet</code> objects are equal, 583 * <code>false</code> otherwise 584 */ 585 public boolean isEqual(MockResultSet resultSet) 586 { 587 if(null == resultSet) return false; 588 Map thisMap; 589 Map otherMap; 590 if(isDatabaseView) 591 { 592 thisMap = columnMap; 593 } 594 else 595 { 596 thisMap = columnMapCopy; 597 } 598 if(resultSet.isDatabaseView) 599 { 600 otherMap = resultSet.columnMap; 601 } 602 else 603 { 604 otherMap = resultSet.columnMapCopy; 605 } 606 Iterator keys = thisMap.keySet().iterator(); 607 while(keys.hasNext()) 608 { 609 String currentKey = (String)keys.next(); 610 List thisList = (List)thisMap.get(currentKey); 611 List otherList = (List)otherMap.get(currentKey); 612 if(null == otherList) return false; 613 if(thisList.size() != otherList.size()) return false; 614 for(int ii = 0; ii < thisList.size(); ii++) 615 { 616 Object source = thisList.get(ii); 617 Object target = otherList.get(ii); 618 if(!source.getClass().isAssignableFrom(target.getClass()) && !target.getClass().isAssignableFrom(source.getClass())) 619 { 620 source = source.toString(); 621 target = target.toString(); 622 } 623 if(!ParameterUtil.compareParameter(source, target)) 624 { 625 return false; 626 } 627 } 628 } 629 return true; 630 } 631 632 /** 633 * Returns the row with the specified number. 634 * The first row has the number 1. 635 * If number is less than 1 or higher than the 636 * current row count, <code>null</code> will 637 * be returned. The result of this method depends 638 * on the setting of <i>databaseView</i>. 639 * See {@link #setDatabaseView}. 640 * @param number the number of the row 641 * @return the row data as <code>List</code> 642 */ 643 public List getRow(int number) 644 { 645 if(number > getRowCount()) return null; 646 if(number < 1) return null; 647 int index = number - 1; 648 List list = new ArrayList(); 649 for(int ii = 0; ii < columnNameList.size(); ii++) 650 { 651 String nextColumnName = (String)columnNameList.get(ii); 652 List nextColumnList; 653 if(isDatabaseView) 654 { 655 nextColumnList = (List)columnMap.get(nextColumnName); 656 } 657 else 658 { 659 nextColumnList = (List)columnMapCopy.get(nextColumnName); 660 } 661 list.add(nextColumnList.get(index)); 662 } 663 return list; 664 } 665 666 /** 667 * Returns the column with the specified number. 668 * The first column has the number 1. 669 * If number is less than 1 or higher than the 670 * current column count, <code>null</code> will 671 * be returned. 672 * @param number the number of the column 673 * @return the column data as <code>List</code> 674 */ 675 public List getColumn(int number) 676 { 677 if(number > getColumnCount()) return null; 678 if(number < 1) return null; 679 int index = number - 1; 680 String columnName = (String)columnNameList.get(index); 681 return getColumn(columnName); 682 } 683 684 /** 685 * Returns the column with the specified name. 686 * If a column with that name does not exist, 687 * <code>null</code> will be returned. 688 * @param name the name of the column 689 * @return the column data as <code>List</code> 690 */ 691 public List getColumn(String name) 692 { 693 List list = new ArrayList(); 694 List columnList; 695 if(isDatabaseView) 696 { 697 columnList = (List)columnMap.get(name); 698 } 699 else 700 { 701 columnList = (List)columnMapCopy.get(name); 702 } 703 if(null == columnList) return null; 704 list.addAll(columnList); 705 return list; 706 } 707 708 public void close() throws SQLException 709 { 710 closed = true; 711 } 712 713 public boolean wasNull() throws SQLException 714 { 715 return wasNull; 716 } 717 718 public Object getObject(int columnIndex) throws SQLException 719 { 720 checkColumnBounds(columnIndex); 721 if(!isCurrentRowValid()) 722 { 723 wasNull = true; 724 return null; 725 } 726 String columnName = (String)columnNameList.get(columnIndex - 1); 727 return getObject(columnName); 728 } 729 730 public Object getObject(String columnName) throws SQLException 731 { 732 checkColumnName(columnName); 733 if(!isCurrentRowValid()) 734 { 735 wasNull = true; 736 return null; 737 } 738 if(rowDeleted()) throw new SQLException("row was deleted"); 739 List column; 740 if(isDatabaseView) 741 { 742 column = (List)columnMap.get(columnName); 743 } 744 else 745 { 746 column = (List)columnMapCopy.get(columnName); 747 } 748 Object value = column.get(cursor); 749 wasNull = (null == value); 750 return value; 751 } 752 753 public Object getObject(int columnIndex, Map map) throws SQLException 754 { 755 return getObject(columnIndex); 756 } 757 758 public Object getObject(String colName, Map map) throws SQLException 759 { 760 return getObject(colName); 761 } 762 763 public String getString(int columnIndex) throws SQLException 764 { 765 Object value = getObject(columnIndex); 766 if(null != value) return value.toString(); 767 return null; 768 } 769 770 public String getString(String columnName) throws SQLException 771 { 772 Object value = getObject(columnName); 773 if(null != value) return value.toString(); 774 return null; 775 } 776 777 778 public boolean getBoolean(int columnIndex) throws SQLException 779 { 780 Object value = getObject(columnIndex); 781 if(null != value) 782 { 783 if(value instanceof Boolean) return ((Boolean)value).booleanValue(); 784 return new Boolean(value.toString()).booleanValue(); 785 } 786 return false; 787 } 788 789 public boolean getBoolean(String columnName) throws SQLException 790 { 791 Object value = getObject(columnName); 792 if(null != value) 793 { 794 if(value instanceof Boolean) return ((Boolean)value).booleanValue(); 795 return new Boolean(value.toString()).booleanValue(); 796 } 797 return false; 798 } 799 800 public byte getByte(int columnIndex) throws SQLException 801 { 802 Object value = getObject(columnIndex); 803 if(null != value) 804 { 805 if(value instanceof Number) return ((Number)value).byteValue(); 806 return new Byte(value.toString()).byteValue(); 807 } 808 return 0; 809 } 810 811 public byte getByte(String columnName) throws SQLException 812 { 813 Object value = getObject(columnName); 814 if(null != value) 815 { 816 if(value instanceof Number) return ((Number)value).byteValue(); 817 return new Byte(value.toString()).byteValue(); 818 } 819 return 0; 820 } 821 822 public short getShort(int columnIndex) throws SQLException 823 { 824 Object value = getObject(columnIndex); 825 if(null != value) 826 { 827 if(value instanceof Number) return ((Number)value).shortValue(); 828 return new Short(value.toString()).shortValue(); 829 } 830 return 0; 831 } 832 833 public short getShort(String columnName) throws SQLException 834 { 835 Object value = getObject(columnName); 836 if(null != value) 837 { 838 if(value instanceof Number) return ((Number)value).shortValue(); 839 return new Short(value.toString()).shortValue(); 840 } 841 return 0; 842 } 843 844 public int getInt(int columnIndex) throws SQLException 845 { 846 Object value = getObject(columnIndex); 847 if(null != value) 848 { 849 if(value instanceof Number) return ((Number)value).intValue(); 850 return new Integer(value.toString()).intValue(); 851 } 852 return 0; 853 } 854 855 public int getInt(String columnName) throws SQLException 856 { 857 Object value = getObject(columnName); 858 if(null != value) 859 { 860 if(value instanceof Number) return ((Number)value).intValue(); 861 return new Integer(value.toString()).intValue(); 862 } 863 return 0; 864 } 865 866 public long getLong(int columnIndex) throws SQLException 867 { 868 Object value = getObject(columnIndex); 869 if(null != value) 870 { 871 if(value instanceof Number) return ((Number)value).longValue(); 872 return new Long(value.toString()).longValue(); 873 } 874 return 0; 875 } 876 877 public long getLong(String columnName) throws SQLException 878 { 879 Object value = getObject(columnName); 880 if(null != value) 881 { 882 if(value instanceof Number) return ((Number)value).longValue(); 883 return new Long(value.toString()).longValue(); 884 } 885 return 0; 886 } 887 888 public float getFloat(int columnIndex) throws SQLException 889 { 890 Object value = getObject(columnIndex); 891 if(null != value) 892 { 893 if(value instanceof Number) return ((Number)value).floatValue(); 894 return new Float(value.toString()).floatValue(); 895 } 896 return 0; 897 } 898 899 public float getFloat(String columnName) throws SQLException 900 { 901 Object value = getObject(columnName); 902 if(null != value) 903 { 904 if(value instanceof Number) return ((Number)value).floatValue(); 905 return new Float(value.toString()).floatValue(); 906 } 907 return 0; 908 } 909 910 public double getDouble(int columnIndex) throws SQLException 911 { 912 Object value = getObject(columnIndex); 913 if(null != value) 914 { 915 if(value instanceof Number) return ((Number)value).doubleValue(); 916 return new Double(value.toString()).doubleValue(); 917 } 918 return 0; 919 } 920 921 public double getDouble(String columnName) throws SQLException 922 { 923 Object value = getObject(columnName); 924 if(null != value) 925 { 926 if(value instanceof Number) return ((Number)value).doubleValue(); 927 return new Double(value.toString()).doubleValue(); 928 } 929 return 0; 930 } 931 932 public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException 933 { 934 BigDecimal value = getBigDecimal(columnIndex); 935 if(null != value) 936 { 937 value.setScale(scale); 938 } 939 return null; 940 } 941 942 public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException 943 { 944 BigDecimal value = getBigDecimal(columnName); 945 if(null != value) 946 { 947 value.setScale(scale); 948 } 949 return null; 950 } 951 952 public BigDecimal getBigDecimal(int columnIndex) throws SQLException 953 { 954 Object value = getObject(columnIndex); 955 if(null != value) 956 { 957 if(value instanceof Number) return new BigDecimal(((Number)value).doubleValue()); 958 return new BigDecimal(value.toString()); 959 } 960 return null; 961 } 962 963 public BigDecimal getBigDecimal(String columnName) throws SQLException 964 { 965 Object value = getObject(columnName); 966 if(null != value) 967 { 968 if(value instanceof Number) return new BigDecimal(((Number)value).doubleValue()); 969 return new BigDecimal(value.toString()); 970 } 971 return null; 972 } 973 974 public byte[] getBytes(int columnIndex) throws SQLException 975 { 976 Object value = getObject(columnIndex); 977 if(null != value) 978 { 979 if(value instanceof byte[]) return (byte[])value; 980 return value.toString().getBytes(); 981 } 982 return null; 983 } 984 985 public byte[] getBytes(String columnName) throws SQLException 986 { 987 Object value = getObject(columnName); 988 if(null != value) 989 { 990 if(value instanceof byte[]) return (byte[])value; 991 return value.toString().getBytes(); 992 } 993 return null; 994 } 995 996 public Date getDate(int columnIndex) throws SQLException 997 { 998 Object value = getObject(columnIndex); 999 if(null != value) 1000 { 1001 if(value instanceof Date) return (Date)value; 1002 return Date.valueOf(value.toString()); 1003 } 1004 return null; 1005 } 1006 1007 public Date getDate(String columnName) throws SQLException 1008 { 1009 Object value = getObject(columnName); 1010 if(null != value) 1011 { 1012 if(value instanceof Date) return (Date)value; 1013 return Date.valueOf(value.toString()); 1014 } 1015 return null; 1016 } 1017 1018 public Date getDate(int columnIndex, Calendar calendar) throws SQLException 1019 { 1020 return getDate(columnIndex); 1021 } 1022 1023 public Date getDate(String columnName, Calendar calendar) throws SQLException 1024 { 1025 return getDate(columnName); 1026 } 1027 1028 public Time getTime(int columnIndex) throws SQLException 1029 { 1030 Object value = getObject(columnIndex); 1031 if(null != value) 1032 { 1033 if(value instanceof Time) return (Time)value; 1034 return Time.valueOf(value.toString()); 1035 } 1036 return null; 1037 } 1038 1039 public Time getTime(String columnName) throws SQLException 1040 { 1041 Object value = getObject(columnName); 1042 if(null != value) 1043 { 1044 if(value instanceof Time) return (Time)value; 1045 return Time.valueOf(value.toString()); 1046 } 1047 return null; 1048 } 1049 1050 public Time getTime(int columnIndex, Calendar calendar) throws SQLException 1051 { 1052 return getTime(columnIndex); 1053 } 1054 1055 public Time getTime(String columnName, Calendar calendar) throws SQLException 1056 { 1057 return getTime(columnName); 1058 } 1059 1060 public Timestamp getTimestamp(int columnIndex) throws SQLException 1061 { 1062 Object value = getObject(columnIndex); 1063 if(null != value) 1064 { 1065 if(value instanceof Timestamp) return (Timestamp)value; 1066 return Timestamp.valueOf(value.toString()); 1067 } 1068 return null; 1069 } 1070 1071 public Timestamp getTimestamp(String columnName) throws SQLException 1072 { 1073 Object value = getObject(columnName); 1074 if(null != value) 1075 { 1076 if(value instanceof Timestamp) return (Timestamp)value; 1077 return Timestamp.valueOf(value.toString()); 1078 } 1079 return null; 1080 } 1081 1082 public Timestamp getTimestamp(int columnIndex, Calendar calendar) throws SQLException 1083 { 1084 return getTimestamp(columnIndex); 1085 } 1086 1087 public Timestamp getTimestamp(String columnName, Calendar calendar) throws SQLException 1088 { 1089 return getTimestamp(columnName); 1090 } 1091 1092 public URL getURL(int columnIndex) throws SQLException 1093 { 1094 Object value = getObject(columnIndex); 1095 if(null != value) 1096 { 1097 if(value instanceof URL) return (URL)value; 1098 try 1099 { 1100 return new URL(value.toString()); 1101 } 1102 catch(MalformedURLException exc) 1103 { 1104 1105 } 1106 } 1107 return null; 1108 } 1109 1110 public URL getURL(String columnName) throws SQLException 1111 { 1112 Object value = getObject(columnName); 1113 if(null != value) 1114 { 1115 if(value instanceof URL) return (URL)value; 1116 try 1117 { 1118 return new URL(value.toString()); 1119 } 1120 catch(MalformedURLException exc) 1121 { 1122 1123 } 1124 } 1125 return null; 1126 } 1127 1128 public Blob getBlob(int columnIndex) throws SQLException 1129 { 1130 Object value = getObject(columnIndex); 1131 if(null != value) 1132 { 1133 if(value instanceof Blob) return (Blob)value; 1134 return new MockBlob(getBytes(columnIndex)); 1135 } 1136 return null; 1137 } 1138 1139 public Blob getBlob(String columnName) throws SQLException 1140 { 1141 Object value = getObject(columnName); 1142 if(null != value) 1143 { 1144 if(value instanceof Blob) return (Blob)value; 1145 return new MockBlob(getBytes(columnName)); 1146 } 1147 return null; 1148 } 1149 1150 public Clob getClob(int columnIndex) throws SQLException 1151 { 1152 Object value = getObject(columnIndex); 1153 if(null != value) 1154 { 1155 if(value instanceof Clob) return (Clob)value; 1156 return new MockClob(getString(columnIndex)); 1157 } 1158 return null; 1159 } 1160 1161 public Clob getClob(String columnName) throws SQLException 1162 { 1163 Object value = getObject(columnName); 1164 if(null != value) 1165 { 1166 if(value instanceof Clob) return (Clob)value; 1167 return new MockClob(getString(columnName)); 1168 } 1169 return null; 1170 } 1171 1172 public Array getArray(int columnIndex) throws SQLException 1173 { 1174 Object value = getObject(columnIndex); 1175 if(null != value) 1176 { 1177 if(value instanceof Array) return (Array)value; 1178 return new MockArray(value); 1179 } 1180 return null; 1181 } 1182 1183 public Array getArray(String columnName) throws SQLException 1184 { 1185 Object value = getObject(columnName); 1186 if(null != value) 1187 { 1188 if(value instanceof Array) return (Array)value; 1189 return new MockArray(value); 1190 } 1191 return null; 1192 } 1193 1194 public Ref getRef(int columnIndex) throws SQLException 1195 { 1196 Object value = getObject(columnIndex); 1197 if(null != value) 1198 { 1199 if(value instanceof Ref) return (Ref)value; 1200 return new MockRef(value); 1201 } 1202 return null; 1203 } 1204 1205 public Ref getRef(String columnName) throws SQLException 1206 { 1207 Object value = getObject(columnName); 1208 if(null != value) 1209 { 1210 if(value instanceof Ref) return (Ref)value; 1211 return new MockRef(value); 1212 } 1213 return null; 1214 } 1215 1216 public InputStream getAsciiStream(int columnIndex) throws SQLException 1217 { 1218 return getBinaryStream(columnIndex); 1219 } 1220 1221 public InputStream getAsciiStream(String columnName) throws SQLException 1222 { 1223 return getBinaryStream(columnName); 1224 } 1225 1226 public InputStream getBinaryStream(int columnIndex) throws SQLException 1227 { 1228 Object value = getObject(columnIndex); 1229 if(null != value) 1230 { 1231 if(value instanceof InputStream) return (InputStream)value; 1232 return new ByteArrayInputStream(getBytes(columnIndex)); 1233 } 1234 return null; 1235 } 1236 1237 public InputStream getBinaryStream(String columnName) throws SQLException 1238 { 1239 Object value = getObject(columnName); 1240 if(null != value) 1241 { 1242 if(value instanceof InputStream) return (InputStream)value; 1243 return new ByteArrayInputStream(getBytes(columnName)); 1244 } 1245 return null; 1246 } 1247 1248 public InputStream getUnicodeStream(int columnIndex) throws SQLException 1249 { 1250 Object value = getObject(columnIndex); 1251 if(null != value) 1252 { 1253 if(value instanceof InputStream) return (InputStream)value; 1254 try 1255 { 1256 return new ByteArrayInputStream(getString(columnIndex).getBytes("UTF-8")); 1257 } 1258 catch(UnsupportedEncodingException exc) 1259 { 1260 1261 } 1262 } 1263 return null; 1264 } 1265 1266 public InputStream getUnicodeStream(String columnName) throws SQLException 1267 { 1268 Object value = getObject(columnName); 1269 if(null != value) 1270 { 1271 if(value instanceof InputStream) return (InputStream)value; 1272 try 1273 { 1274 return new ByteArrayInputStream(getString(columnName).getBytes("UTF-8")); 1275 } 1276 catch(UnsupportedEncodingException exc) 1277 { 1278 1279 } 1280 } 1281 return null; 1282 } 1283 1284 public Reader getCharacterStream(int columnIndex) throws SQLException 1285 { 1286 Object value = getObject(columnIndex); 1287 if(null != value) 1288 { 1289 if(value instanceof Reader) return (Reader)value; 1290 return new StringReader(getString(columnIndex)); 1291 } 1292 return null; 1293 } 1294 1295 public Reader getCharacterStream(String columnName) throws SQLException 1296 { 1297 Object value = getObject(columnName); 1298 if(null != value) 1299 { 1300 if(value instanceof Reader) return (Reader)value; 1301 return new StringReader(getString(columnName)); 1302 } 1303 return null; 1304 } 1305 1306 1307 public SQLWarning getWarnings() throws SQLException 1308 { 1309 return null; 1310 } 1311 1312 public void clearWarnings() throws SQLException 1313 { 1314 1315 } 1316 1317 public String getCursorName() throws SQLException 1318 { 1319 return cursorName; 1320 } 1321 1322 public ResultSetMetaData getMetaData() throws SQLException 1323 { 1324 if(null != resultSetMetaData) return resultSetMetaData; 1325 MockResultSetMetaData metaData = new MockResultSetMetaData(); 1326 metaData.setColumnCount(getColumnCount()); 1327 for(int ii = 0; ii < columnNameList.size(); ii++) 1328 { 1329 metaData.setColumnName(ii + 1, (String)columnNameList.get(ii)); 1330 } 1331 return metaData; 1332 } 1333 1334 public Statement getStatement() throws SQLException 1335 { 1336 return statement; 1337 } 1338 1339 public boolean isBeforeFirst() throws SQLException 1340 { 1341 // Counterintuitively, this method is supposed to return false when the 1342 // result set is empty. 1343 return (getRowCount() != 0) && (cursor == -1); 1344 } 1345 1346 public boolean isAfterLast() throws SQLException 1347 { 1348 return cursor >= getRowCount(); 1349 } 1350 1351 public boolean isFirst() throws SQLException 1352 { 1353 return cursor == 0; 1354 } 1355 1356 public boolean isLast() throws SQLException 1357 { 1358 return (cursor != -1) && (cursor == getRowCount() - 1); 1359 } 1360 1361 public void beforeFirst() throws SQLException 1362 { 1363 if(isCursorInInsertRow) throw new SQLException("cursor is in insert row"); 1364 checkResultSetType(); 1365 cursor = -1; 1366 } 1367 1368 public void afterLast() throws SQLException 1369 { 1370 if(isCursorInInsertRow) throw new SQLException("cursor is in insert row"); 1371 checkResultSetType(); 1372 if(getRowCount() == 0) return; 1373 cursor = getRowCount(); 1374 } 1375 1376 public boolean next() throws SQLException 1377 { 1378 if(isCursorInInsertRow) throw new SQLException("cursor is in insert row"); 1379 if(getRowCount() == 0) return false; 1380 cursor++; 1381 adjustCursor(); 1382 return isCurrentRowValid(); 1383 } 1384 1385 1386 public boolean first() throws SQLException 1387 { 1388 if(isCursorInInsertRow) throw new SQLException("cursor is in insert row"); 1389 checkResultSetType(); 1390 if(getRowCount() == 0) return false; 1391 cursor = 0; 1392 return true; 1393 } 1394 1395 public boolean last() throws SQLException 1396 { 1397 if(isCursorInInsertRow) throw new SQLException("cursor is in insert row"); 1398 checkResultSetType(); 1399 if(getRowCount() == 0) return false; 1400 cursor = getRowCount() - 1; 1401 return true; 1402 } 1403 1404 public boolean absolute(int row) throws SQLException 1405 { 1406 if(isCursorInInsertRow) throw new SQLException("cursor is in insert row"); 1407 checkResultSetType(); 1408 if(getRowCount() == 0) return false; 1409 if(row > 0) cursor = row - 1; 1410 if(row < 0) cursor = getRowCount() + row; 1411 adjustCursor(); 1412 return isCurrentRowValid(); 1413 } 1414 1415 public boolean relative(int rows) throws SQLException 1416 { 1417 if(isCursorInInsertRow) throw new SQLException("cursor is in insert row"); 1418 checkResultSetType(); 1419 if(getRowCount() == 0) return false; 1420 cursor += rows; 1421 adjustCursor(); 1422 return isCurrentRowValid(); 1423 } 1424 1425 public int getRow() throws SQLException 1426 { 1427 return cursor + 1; 1428 } 1429 1430 public boolean previous() throws SQLException 1431 { 1432 if(isCursorInInsertRow) throw new SQLException("cursor is in insert row"); 1433 checkResultSetType(); 1434 if(getRowCount() == 0) return false; 1435 cursor--; 1436 adjustCursor(); 1437 return isCurrentRowValid(); 1438 } 1439 1440 public void setFetchDirection(int fetchDirection) throws SQLException 1441 { 1442 checkFetchDirectionArguments(fetchDirection); 1443 if(this.fetchDirection == fetchDirection) return; 1444 if(this.fetchDirection == ResultSet.FETCH_UNKNOWN || fetchDirection == ResultSet.FETCH_UNKNOWN) 1445 { 1446 this.fetchDirection = fetchDirection; 1447 return; 1448 } 1449 this.fetchDirection = fetchDirection; 1450 Iterator columns = columnMapCopy.values().iterator(); 1451 while(columns.hasNext()) 1452 { 1453 List column = (List)columns.next(); 1454 Collections.reverse(column); 1455 } 1456 if(-1 != cursor) cursor = getRowCount() - cursor - 1; 1457 } 1458 1459 public int getFetchDirection() throws SQLException 1460 { 1461 return fetchDirection; 1462 } 1463 1464 public void setFetchSize(int fetchSize) throws SQLException 1465 { 1466 this.fetchSize = fetchSize; 1467 } 1468 1469 public int getFetchSize() throws SQLException 1470 { 1471 return fetchSize; 1472 } 1473 1474 public int getType() throws SQLException 1475 { 1476 return resultSetType; 1477 } 1478 1479 public int getConcurrency() throws SQLException 1480 { 1481 return resultSetConcurrency; 1482 } 1483 1484 public int findColumn(String columnName) throws SQLException 1485 { 1486 for(int ii = 0; ii < columnNameList.size(); ii++) 1487 { 1488 if(columnName.equals(columnNameList.get(ii))) return ii + 1; 1489 } 1490 throw new SQLException("No column with name " + columnName + " found"); 1491 } 1492 1493 public void updateObject(int columnIndex, Object value) throws SQLException 1494 { 1495 checkColumnBounds(columnIndex); 1496 checkRowBounds(); 1497 if(rowDeleted()) throw new SQLException("row was deleted"); 1498 String columnName = (String)columnNameList.get(columnIndex - 1); 1499 updateObject(columnName, value); 1500 } 1501 1502 public void updateObject(int columnIndex, Object value, int scale) throws SQLException 1503 { 1504 updateObject(columnIndex, value); 1505 } 1506 1507 public void updateObject(String columnName, Object value, int scale) throws SQLException 1508 { 1509 updateObject(columnName, value); 1510 } 1511 1512 public void updateObject(String columnName, Object value) throws SQLException 1513 { 1514 checkColumnName(columnName); 1515 checkRowBounds(); 1516 checkResultSetConcurrency(); 1517 if(rowDeleted()) throw new SQLException("row was deleted"); 1518 if(isCursorInInsertRow) 1519 { 1520 List column = (List)insertRow.get(columnName); 1521 column.set(0, value); 1522 } 1523 else 1524 { 1525 List column = (List)columnMapCopy.get(columnName); 1526 column.set(cursor, value); 1527 } 1528 } 1529 1530 public void updateString(int columnIndex, String value) throws SQLException 1531 { 1532 updateObject(columnIndex, value); 1533 } 1534 1535 public void updateString(String columnName, String value) throws SQLException 1536 { 1537 updateObject(columnName, value); 1538 } 1539 1540 public void updateNull(int columnIndex) throws SQLException 1541 { 1542 updateObject(columnIndex, null); 1543 } 1544 1545 public void updateNull(String columnName) throws SQLException 1546 { 1547 updateObject(columnName, null); 1548 } 1549 1550 public void updateBoolean(int columnIndex, boolean booleanValue) throws SQLException 1551 { 1552 updateObject(columnIndex, new Boolean(booleanValue)); 1553 } 1554 1555 public void updateBoolean(String columnName, boolean booleanValue) throws SQLException 1556 { 1557 updateObject(columnName, new Boolean(booleanValue)); 1558 } 1559 1560 public void updateByte(int columnIndex, byte byteValue) throws SQLException 1561 { 1562 updateObject(columnIndex, new Byte(byteValue)); 1563 } 1564 1565 public void updateByte(String columnName, byte byteValue) throws SQLException 1566 { 1567 updateObject(columnName, new Byte(byteValue)); 1568 } 1569 1570 public void updateShort(int columnIndex, short shortValue) throws SQLException 1571 { 1572 updateObject(columnIndex, new Short(shortValue)); 1573 } 1574 1575 public void updateShort(String columnName, short shortValue) throws SQLException 1576 { 1577 updateObject(columnName, new Short(shortValue)); 1578 } 1579 1580 public void updateInt(int columnIndex, int intValue) throws SQLException 1581 { 1582 updateObject(columnIndex, new Integer(intValue)); 1583 } 1584 1585 public void updateInt(String columnName, int intValue) throws SQLException 1586 { 1587 updateObject(columnName, new Integer(intValue)); 1588 } 1589 1590 public void updateLong(int columnIndex, long longValue) throws SQLException 1591 { 1592 updateObject(columnIndex, new Long(longValue)); 1593 } 1594 1595 public void updateLong(String columnName, long longValue) throws SQLException 1596 { 1597 updateObject(columnName, new Long(longValue)); 1598 } 1599 1600 public void updateFloat(int columnIndex, float floatValue) throws SQLException 1601 { 1602 updateObject(columnIndex, new Float(floatValue)); 1603 } 1604 1605 public void updateFloat(String columnName, float floatValue) throws SQLException 1606 { 1607 updateObject(columnName, new Float(floatValue)); 1608 } 1609 1610 public void updateDouble(int columnIndex, double doubleValue) throws SQLException 1611 { 1612 updateObject(columnIndex, new Double(doubleValue)); 1613 } 1614 1615 public void updateDouble(String columnName, double doubleValue) throws SQLException 1616 { 1617 updateObject(columnName, new Double(doubleValue)); 1618 } 1619 1620 public void updateBigDecimal(int columnIndex, BigDecimal bigDecimal) throws SQLException 1621 { 1622 updateObject(columnIndex, bigDecimal); 1623 } 1624 1625 public void updateBigDecimal(String columnName, BigDecimal bigDecimal) throws SQLException 1626 { 1627 updateObject(columnName, bigDecimal); 1628 } 1629 1630 public void updateBytes(int columnIndex, byte[] byteArray) throws SQLException 1631 { 1632 updateObject(columnIndex, byteArray); 1633 } 1634 1635 public void updateBytes(String columnName, byte[] byteArray) throws SQLException 1636 { 1637 updateObject(columnName, byteArray); 1638 } 1639 1640 public void updateDate(int columnIndex, Date date) throws SQLException 1641 { 1642 updateObject(columnIndex, date); 1643 } 1644 1645 public void updateDate(String columnName, Date date) throws SQLException 1646 { 1647 updateObject(columnName, date); 1648 } 1649 1650 public void updateTime(int columnIndex, Time time) throws SQLException 1651 { 1652 updateObject(columnIndex, time); 1653 } 1654 1655 public void updateTime(String columnName, Time time) throws SQLException 1656 { 1657 updateObject(columnName, time); 1658 } 1659 1660 public void updateTimestamp(int columnIndex, Timestamp timeStamp) throws SQLException 1661 { 1662 updateObject(columnIndex, timeStamp); 1663 } 1664 1665 public void updateTimestamp(String columnName, Timestamp timeStamp) throws SQLException 1666 { 1667 updateObject(columnName, timeStamp); 1668 } 1669 1670 public void updateAsciiStream(int columnIndex, InputStream stream, int length) throws SQLException 1671 { 1672 updateBinaryStream(columnIndex, stream, length); 1673 } 1674 1675 public void updateAsciiStream(String columnName, InputStream stream, int length) throws SQLException 1676 { 1677 updateBinaryStream(columnName, stream, length); 1678 } 1679 1680 public void updateBinaryStream(int columnIndex, InputStream stream, int length) throws SQLException 1681 { 1682 byte[] data = StreamUtil.getStreamAsByteArray(stream, length); 1683 updateObject(columnIndex, new ByteArrayInputStream(data)); 1684 } 1685 1686 public void updateBinaryStream(String columnName, InputStream stream, int length) throws SQLException 1687 { 1688 byte[] data = StreamUtil.getStreamAsByteArray(stream, length); 1689 updateObject(columnName, new ByteArrayInputStream(data)); 1690 } 1691 1692 public void updateCharacterStream(int columnIndex, Reader reader, int length) throws SQLException 1693 { 1694 String data = StreamUtil.getReaderAsString(reader, length); 1695 updateObject(columnIndex, new StringReader(data)); 1696 } 1697 1698 public void updateCharacterStream(String columnName, Reader reader, int length) throws SQLException 1699 { 1700 String data = StreamUtil.getReaderAsString(reader, length); 1701 updateObject(columnName, new StringReader(data)); 1702 } 1703 1704 public void updateRef(int columnIndex, Ref ref) throws SQLException 1705 { 1706 updateObject(columnIndex, ref); 1707 } 1708 1709 public void updateRef(String columnName, Ref ref) throws SQLException 1710 { 1711 updateObject(columnName, ref); 1712 } 1713 1714 public void updateBlob(int columnIndex, Blob blob) throws SQLException 1715 { 1716 updateObject(columnIndex, blob); 1717 } 1718 1719 public void updateBlob(String columnName, Blob blob) throws SQLException 1720 { 1721 updateObject(columnName, blob); 1722 } 1723 1724 public void updateClob(int columnIndex, Clob clob) throws SQLException 1725 { 1726 updateObject(columnIndex, clob); 1727 } 1728 1729 public void updateClob(String columnName, Clob clob) throws SQLException 1730 { 1731 updateObject(columnName, clob); 1732 } 1733 1734 public void updateArray(int columnIndex, Array array) throws SQLException 1735 { 1736 updateObject(columnIndex, array); 1737 } 1738 1739 public void updateArray(String columnName, Array array) throws SQLException 1740 { 1741 updateObject(columnName, array); 1742 } 1743 1744 public boolean rowUpdated() throws SQLException 1745 { 1746 checkRowBounds(); 1747 return ((Boolean)updatedRows.get(cursor)).booleanValue(); 1748 } 1749 1750 public boolean rowInserted() throws SQLException 1751 { 1752 checkRowBounds(); 1753 return ((Boolean)insertedRows.get(cursor)).booleanValue(); 1754 } 1755 1756 public boolean rowDeleted() throws SQLException 1757 { 1758 checkRowBounds(); 1759 return ((Boolean)deletedRows.get(cursor)).booleanValue(); 1760 } 1761 1762 public void insertRow() throws SQLException 1763 { 1764 if(!isCursorInInsertRow) throw new SQLException("cursor is in insert row"); 1765 insertRow(cursor); 1766 } 1767 1768 public void updateRow() throws SQLException 1769 { 1770 if(isCursorInInsertRow) throw new SQLException("cursor is in insert row"); 1771 if(rowDeleted()) throw new SQLException("row was deleted"); 1772 checkRowBounds(); 1773 updateRow(cursor, true); 1774 updatedRows.set(cursor, new Boolean(true)); 1775 } 1776 1777 public void deleteRow() throws SQLException 1778 { 1779 if(isCursorInInsertRow) throw new SQLException("cursor is in insert row"); 1780 checkRowBounds(); 1781 deleteRow(cursor); 1782 deletedRows.set(cursor, new Boolean(true)); 1783 } 1784 1785 public void refreshRow() throws SQLException 1786 { 1787 cancelRowUpdates(); 1788 } 1789 1790 public void cancelRowUpdates() throws SQLException 1791 { 1792 if(isCursorInInsertRow) throw new SQLException("cursor is in insert row"); 1793 if(rowDeleted()) throw new SQLException("row was deleted"); 1794 checkRowBounds(); 1795 updateRow(cursor, false); 1796 updatedRows.set(cursor, new Boolean(false)); 1797 } 1798 1799 public void moveToInsertRow() throws SQLException 1800 { 1801 isCursorInInsertRow = true; 1802 } 1803 1804 public void moveToCurrentRow() throws SQLException 1805 { 1806 isCursorInInsertRow = false; 1807 } 1808 1809 private void checkColumnName(String columnName) throws SQLException 1810 { 1811 if(!columnMap.containsKey(columnName)) 1812 { 1813 throw new SQLException("No column " + columnName); 1814 } 1815 } 1816 1817 private void checkColumnBounds(int columnIndex) throws SQLException 1818 { 1819 if(!(columnIndex - 1 < columnNameList.size())) 1820 { 1821 throw new SQLException("Index " + columnIndex + " out of bounds"); 1822 } 1823 } 1824 1825 private void checkRowBounds() throws SQLException 1826 { 1827 if(!isCurrentRowValid()) 1828 { 1829 throw new SQLException("Current row invalid"); 1830 } 1831 } 1832 1833 private boolean isCurrentRowValid() 1834 { 1835 return (cursor < getRowCount()) && (-1 != cursor); 1836 } 1837 1838 private void checkResultSetType() throws SQLException 1839 { 1840 if(resultSetType == ResultSet.TYPE_FORWARD_ONLY) 1841 { 1842 throw new SQLException("ResultSet is TYPE_FORWARD_ONLY"); 1843 } 1844 } 1845 1846 private void checkResultSetConcurrency() throws SQLException 1847 { 1848 if(resultSetConcurrency == ResultSet.CONCUR_READ_ONLY) 1849 { 1850 throw new SQLException("ResultSet is CONCUR_READ_ONLY"); 1851 } 1852 } 1853 1854 private void checkFetchDirectionArguments(int fetchDirection) throws SQLException 1855 { 1856 SQLUtil.checkFetchDirection(fetchDirection); 1857 if(resultSetType == ResultSet.TYPE_FORWARD_ONLY && fetchDirection != ResultSet.FETCH_FORWARD) 1858 { 1859 throw new SQLException("resultSetType is TYPE_FORWARD_ONLY, only FETCH_FORWARD allowed"); 1860 } 1861 } 1862 1863 private void insertRow(int index) 1864 { 1865 Iterator columnNames = columnMapCopy.keySet().iterator(); 1866 while(columnNames.hasNext()) 1867 { 1868 String currentColumnName = (String)columnNames.next(); 1869 List copyColumn = (List)columnMapCopy.get(currentColumnName); 1870 List databaseColumn = (List)columnMap.get(currentColumnName); 1871 List sourceColumn = (List)insertRow.get(currentColumnName); 1872 copyColumn.add(index, sourceColumn.get(0)); 1873 databaseColumn.add(index, sourceColumn.get(0)); 1874 } 1875 updatedRows.add(index, new Boolean(false)); 1876 deletedRows.add(index, new Boolean(false)); 1877 insertedRows.add(index, new Boolean(true)); 1878 } 1879 1880 private void deleteRow(int index) 1881 { 1882 Iterator columnNames = columnMapCopy.keySet().iterator(); 1883 while(columnNames.hasNext()) 1884 { 1885 String currentColumnName = (String)columnNames.next(); 1886 List copyColumn = (List)columnMapCopy.get(currentColumnName); 1887 List databaseColumn = (List)columnMap.get(currentColumnName); 1888 copyColumn.set(index, null); 1889 databaseColumn.set(index, null); 1890 } 1891 } 1892 1893 private void updateRow(int index, boolean toDatabase) 1894 { 1895 Iterator columnNames = columnMapCopy.keySet().iterator(); 1896 while(columnNames.hasNext()) 1897 { 1898 String currentColumnName = (String)columnNames.next(); 1899 List sourceColumn; 1900 List targetColumn; 1901 if(toDatabase) 1902 { 1903 sourceColumn = (List)columnMapCopy.get(currentColumnName); 1904 targetColumn = (List)columnMap.get(currentColumnName); 1905 } 1906 else 1907 { 1908 sourceColumn = (List)columnMap.get(currentColumnName); 1909 targetColumn = (List)columnMapCopy.get(currentColumnName); 1910 } 1911 targetColumn.set(index, sourceColumn.get(index)); 1912 } 1913 } 1914 1915 private void adjustCursor() 1916 { 1917 if(cursor < 0) cursor = -1; 1918 if(cursor >= getRowCount()) cursor = getRowCount(); 1919 } 1920 1921 private void adjustColumns() 1922 { 1923 int rowCount = 0; 1924 Iterator columns = columnMap.values().iterator(); 1925 while(columns.hasNext()) 1926 { 1927 List nextColumn = (List)columns.next(); 1928 rowCount = Math.max(rowCount, nextColumn.size()); 1929 } 1930 columns = columnMap.values().iterator(); 1931 while(columns.hasNext()) 1932 { 1933 List nextColumn = (List)columns.next(); 1934 CollectionUtil.fillList(nextColumn, rowCount); 1935 } 1936 } 1937 1938 private void adjustFlags() 1939 { 1940 for(int ii = updatedRows.size(); ii < getRowCount(); ii++) 1941 { 1942 updatedRows.add(new Boolean(false)); 1943 } 1944 for(int ii = deletedRows.size(); ii < getRowCount(); ii++) 1945 { 1946 deletedRows.add(new Boolean(false)); 1947 } 1948 for(int ii = insertedRows.size(); ii < getRowCount(); ii++) 1949 { 1950 insertedRows.add(new Boolean(false)); 1951 } 1952 } 1953 1954 private void adjustInsertRow() 1955 { 1956 insertRow = createCaseAwareMap(); 1957 Iterator columns = columnMap.keySet().iterator(); 1958 while(columns.hasNext()) 1959 { 1960 ArrayList list = new ArrayList(1); 1961 list.add(null); 1962 insertRow.put((String)columns.next(), list); 1963 } 1964 } 1965 1966 private void copyColumnMap() 1967 { 1968 columnMapCopy = copyColumnDataMap(columnMap); 1969 } 1970 1971 private String determineValidColumnName() 1972 { 1973 String name = "Column"; 1974 int count = columnNameList.size() + 1; 1975 while(columnMap.containsKey(name + count)) 1976 { 1977 count ++; 1978 } 1979 return name + count; 1980 } 1981 1982 private Map copyColumnDataMap(Map columnMap) 1983 { 1984 Map copy = createCaseAwareMap(); 1985 Iterator columns = columnMap.keySet().iterator(); 1986 while(columns.hasNext()) 1987 { 1988 List copyList = new ArrayList(); 1989 String nextKey = (String)columns.next(); 1990 List nextColumnList = (List)columnMap.get(nextKey); 1991 for(int ii = 0; ii < nextColumnList.size(); ii++) 1992 { 1993 Object copyParameter = ParameterUtil.copyParameter(nextColumnList.get(ii)); 1994 copyList.add(copyParameter); 1995 } 1996 copy.put(nextKey, copyList); 1997 } 1998 return copy; 1999 } 2000 2001 private Map createCaseAwareMap() 2002 { 2003 return new CaseAwareMap(columnsCaseSensitive); 2004 } 2005 2006 public String toString() 2007 { 2008 StringBuffer buffer = new StringBuffer("ResultSet " + id + ":\n"); 2009 buffer.append("Number of rows: " + getRowCount() + "\n"); 2010 buffer.append("Number of columns: " + getColumnCount() + "\n"); 2011 buffer.append("Column names:\n"); 2012 StringUtil.appendObjectsAsString(buffer, columnNameList); 2013 buffer.append("Data:\n"); 2014 for(int ii = 1; ii <= getRowCount(); ii++) 2015 { 2016 buffer.append("Row number " + ii + ":\n"); 2017 StringUtil.appendObjectsAsString(buffer, getRow(ii)); 2018 } 2019 return buffer.toString(); 2020 } 2021 }