1 /*
   2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package test.rowset.cachedrowset;
  24 
  25 import java.math.BigDecimal;
  26 import java.sql.Array;
  27 import java.sql.Date;
  28 import java.sql.JDBCType;
  29 import java.sql.Ref;
  30 import java.sql.ResultSet;
  31 import java.sql.ResultSetMetaData;
  32 import java.sql.SQLException;
  33 import java.sql.Time;
  34 import java.sql.Timestamp;
  35 import java.sql.Types;
  36 import java.time.LocalDate;
  37 import java.time.LocalDateTime;
  38 import java.time.LocalTime;
  39 import java.util.Collection;
  40 import javax.sql.RowSet;
  41 import javax.sql.rowset.CachedRowSet;
  42 import javax.sql.rowset.RowSetMetaDataImpl;
  43 import javax.sql.rowset.serial.SerialRef;
  44 import javax.sql.rowset.spi.SyncFactory;
  45 import javax.sql.rowset.spi.SyncProvider;
  46 import javax.sql.rowset.spi.SyncProviderException;
  47 import static org.testng.Assert.assertEquals;
  48 import static org.testng.Assert.assertFalse;
  49 import static org.testng.Assert.assertNull;
  50 import static org.testng.Assert.assertTrue;
  51 import org.testng.annotations.DataProvider;
  52 import org.testng.annotations.Test;
  53 import test.rowset.CommonRowSetTests;
  54 import util.StubArray;
  55 import util.StubRef;
  56 import util.StubSyncProvider;
  57 import util.TestRowSetListener;
  58 
  59 public abstract class CommonCachedRowSetTests extends CommonRowSetTests {
  60 
  61     /*
  62      * DATATYPES Table column names
  63      */
  64     private final String[] DATATYPES_COLUMN_NAMES = {"AINTEGER", "ACHAR",
  65         "AVARCHAR", "ALONG", "ABOOLEAN", "ASHORT", "ADOUBLE", "ABIGDECIMAL",
  66         "AREAL", "ABYTE", "ADATE", "ATIME", "ATIMESTAMP", "ABYTES", "ARRAY",
  67         "AREF", "AFLOAT"};
  68 
  69     /*
  70      * Initializes a RowSet containing the DATAYPES data
  71      */
  72     protected <T extends RowSet> T createDataTypesRowSet() throws SQLException {
  73         T rs = (T) newInstance();
  74         initDataTypesMetaData((CachedRowSet) rs);
  75         createDataTypesRows(rs);
  76         // Make sure you are not on the insertRow
  77         rs.moveToCurrentRow();
  78         return rs;
  79     }
  80 
  81     //DataProviders to use for common tests
  82 
  83     /*
  84      * DataProvider that uses a RowSet with the COFFEE_HOUSES Table
  85      */
  86     @DataProvider(name = "rowsetUsingCoffeeHouses")
  87     protected Object[][] rowsetUsingCoffeeHouses() throws Exception {
  88         RowSet rs = createCoffeeHousesRowSet();
  89         return new Object[][]{
  90             {rs}
  91         };
  92     }
  93 
  94     /*
  95      * DataProvider that uses a RowSet with the COFFEES Table
  96      */
  97     @DataProvider(name = "rowsetUsingCoffees")
  98     protected Object[][] rowsetUsingCoffees() throws Exception {
  99         RowSet rs = createCoffeesRowSet();
 100         return new Object[][]{
 101             {rs}
 102         };
 103     }
 104 
 105     /*
 106      * DataProvider that uses a RowSet with the DATAYPES Table and
 107      * used to validate the various supported data types
 108      */
 109     @DataProvider(name = "rowsetUsingDataTypes")
 110     protected Object[][] rowsetUsingDataTypes() throws Exception {
 111 
 112         CachedRowSet rs = createDataTypesRowSet();
 113         return new Object[][]{
 114             {rs, JDBCType.INTEGER},
 115             {rs, JDBCType.CHAR},
 116             {rs, JDBCType.VARCHAR},
 117             {rs, JDBCType.BIGINT},
 118             {rs, JDBCType.BOOLEAN},
 119             {rs, JDBCType.SMALLINT},
 120             {rs, JDBCType.DOUBLE},
 121             {rs, JDBCType.DECIMAL},
 122             {rs, JDBCType.REAL},
 123             {rs, JDBCType.TINYINT},
 124             {rs, JDBCType.DATE},
 125             {rs, JDBCType.TIME},
 126             {rs, JDBCType.TIMESTAMP},
 127             {rs, JDBCType.VARBINARY},
 128             {rs, JDBCType.ARRAY},
 129             {rs, JDBCType.REF},
 130             {rs, JDBCType.FLOAT}
 131         };
 132     }
 133 
 134     /*
 135      * Initializes the DATAYPES table metadata
 136      */
 137     protected void initDataTypesMetaData(CachedRowSet crs) throws SQLException {
 138         RowSetMetaDataImpl rsmd = new RowSetMetaDataImpl();
 139         crs.setType(RowSet.TYPE_SCROLL_INSENSITIVE);
 140 
 141         rsmd.setColumnCount(DATATYPES_COLUMN_NAMES.length);
 142 
 143         for (int i = 1; i <= DATATYPES_COLUMN_NAMES.length; i++) {
 144             rsmd.setColumnName(i, DATATYPES_COLUMN_NAMES[i - 1]);
 145             rsmd.setColumnLabel(i, rsmd.getColumnName(i));
 146         }
 147 
 148         rsmd.setColumnType(1, Types.INTEGER);
 149         rsmd.setColumnType(2, Types.CHAR);
 150         rsmd.setColumnType(3, Types.VARCHAR);
 151         rsmd.setColumnType(4, Types.BIGINT);
 152         rsmd.setColumnType(5, Types.BOOLEAN);
 153         rsmd.setColumnType(6, Types.SMALLINT);
 154         rsmd.setColumnType(7, Types.DOUBLE);
 155         rsmd.setColumnType(8, Types.DECIMAL);
 156         rsmd.setColumnType(9, Types.REAL);
 157         rsmd.setColumnType(10, Types.TINYINT);
 158         rsmd.setColumnType(11, Types.DATE);
 159         rsmd.setColumnType(12, Types.TIME);
 160         rsmd.setColumnType(13, Types.TIMESTAMP);
 161         rsmd.setColumnType(14, Types.VARBINARY);
 162         rsmd.setColumnType(15, Types.ARRAY);
 163         rsmd.setColumnType(16, Types.REF);
 164         rsmd.setColumnType(17, Types.FLOAT);
 165         crs.setMetaData(rsmd);
 166 
 167     }
 168 
 169     /*
 170      * Add rows to DATAYPES table
 171      */
 172     protected void createDataTypesRows(RowSet crs) throws SQLException {
 173 
 174         Integer aInteger = 100;
 175         String aChar = "Oswald Cobblepot";
 176         Long aLong = Long.MAX_VALUE;
 177         Short aShort = Short.MAX_VALUE;
 178         Double aDouble = Double.MAX_VALUE;
 179         BigDecimal aBigDecimal = BigDecimal.ONE;
 180         Boolean aBoolean = false;
 181         Float aFloat = Float.MAX_VALUE;
 182         Byte aByte = Byte.MAX_VALUE;
 183         Date aDate = Date.valueOf(LocalDate.now());
 184         Time aTime = Time.valueOf(LocalTime.now());
 185         Timestamp aTimeStamp = Timestamp.valueOf(LocalDateTime.now());
 186         Array aArray = new StubArray("INTEGER", new Object[1]);
 187         Ref aRef = new SerialRef(new StubRef("INTEGER", query));
 188         byte[] bytes = new byte[10];
 189         crs.moveToInsertRow();
 190         crs.updateInt(1, aInteger);
 191         crs.updateString(2, aChar);
 192         crs.updateString(3, aChar);
 193         crs.updateLong(4, aLong);
 194         crs.updateBoolean(5, aBoolean);
 195         crs.updateShort(6, aShort);
 196         crs.updateDouble(7, aDouble);
 197         crs.updateBigDecimal(8, aBigDecimal);
 198         crs.updateFloat(9, aFloat);
 199         crs.updateByte(10, aByte);
 200         crs.updateDate(11, aDate);
 201         crs.updateTime(12, aTime);
 202         crs.updateTimestamp(13, aTimeStamp);
 203         crs.updateBytes(14, bytes);
 204         crs.updateArray(15, aArray);
 205         crs.updateRef(16, aRef);
 206         crs.updateDouble(17, aDouble);
 207         crs.insertRow();
 208         crs.moveToCurrentRow();
 209 
 210     }
 211 
 212     /*
 213      * Dermine if a Row exists in a ResultSet by its primary key
 214      * If the parameter deleteRow is true, delete the row and validate
 215      * the RowSet indicates it is deleted
 216      */
 217     protected boolean findRowByPrimaryKey(RowSet rs, int id, int idPos,
 218             boolean deleteRow) throws Exception {
 219         boolean foundRow = false;
 220         rs.beforeFirst();
 221         while (rs.next()) {
 222             if (rs.getInt(idPos) == id) {
 223                 foundRow = true;
 224                 if (deleteRow) {
 225                     rs.deleteRow();
 226                     // validate row is marked as deleted
 227                     assertTrue(rs.rowDeleted());
 228                 }
 229                 break;
 230             }
 231         }
 232         return foundRow;
 233     }
 234 
 235     /*
 236      * Wrapper method to find if a row exists within a RowSet by its primary key
 237      */
 238     protected boolean findRowByPrimaryKey(RowSet rs, int id, int idPos) throws Exception {
 239         return findRowByPrimaryKey(rs, id, idPos, false);
 240     }
 241 
 242     /*
 243      * Wrapper method to find if a row exists within a RowSet by its primary key
 244      * and delete it
 245      */
 246     protected boolean deleteRowByPrimaryKey(RowSet rs, int id, int idPos) throws Exception {
 247         return findRowByPrimaryKey(rs, id, idPos, true);
 248     }
 249 
 250     /*
 251      * Utility method that compares two ResultSetMetaDataImpls for containing
 252      * the same values
 253      */
 254     private void compareMetaData(ResultSetMetaData rsmd,
 255             ResultSetMetaData rsmd1) throws SQLException {
 256 
 257         assertEquals(rsmd1.getColumnCount(), rsmd.getColumnCount());
 258         int cols = rsmd.getColumnCount();
 259         for (int i = 1; i <= cols; i++) {
 260             assertTrue(rsmd1.getCatalogName(i).equals(rsmd.getCatalogName(i)));
 261             assertTrue(rsmd1.getColumnClassName(i).equals(rsmd.getColumnClassName(i)));
 262             assertTrue(rsmd1.getColumnDisplaySize(i) == rsmd.getColumnDisplaySize(i));
 263             assertTrue(rsmd1.getColumnLabel(i).equals(rsmd.getColumnLabel(i)));
 264             assertTrue(rsmd1.getColumnName(i).equals(rsmd.getColumnName(i)));
 265             assertTrue(rsmd1.getColumnType(i) == rsmd.getColumnType(i));
 266             assertTrue(rsmd1.getPrecision(i) == rsmd.getPrecision(i));
 267             assertTrue(rsmd1.getScale(i) == rsmd.getScale(i));
 268             assertTrue(rsmd1.getSchemaName(i).equals(rsmd.getSchemaName(i)));
 269             assertTrue(rsmd1.getTableName(i).equals(rsmd.getTableName(i)));
 270             assertTrue(rsmd1.isAutoIncrement(i) == rsmd.isAutoIncrement(i));
 271             assertTrue(rsmd1.isCaseSensitive(i) == rsmd.isCaseSensitive(i));
 272             assertTrue(rsmd1.isCurrency(i) == rsmd.isCurrency(i));
 273             assertTrue(rsmd1.isDefinitelyWritable(i) == rsmd.isDefinitelyWritable(i));
 274             assertTrue(rsmd1.isNullable(i) == rsmd.isNullable(i));
 275             assertTrue(rsmd1.isReadOnly(i) == rsmd.isReadOnly(i));
 276             assertTrue(rsmd1.isSearchable(i) == rsmd.isSearchable(i));
 277             assertTrue(rsmd1.isSigned(i) == rsmd.isSigned(i));
 278             assertTrue(rsmd1.isWritable(i) == rsmd.isWritable(i));
 279 
 280         }
 281     }
 282 
 283     /*
 284      * Utility method to compare two rowsets
 285      */
 286     private void compareRowSets(CachedRowSet crs, CachedRowSet crs1) throws Exception {
 287 
 288         int rows = crs.size();
 289         assertTrue(rows == crs1.size());
 290 
 291         ResultSetMetaData rsmd = crs.getMetaData();
 292 
 293         compareMetaData(rsmd, crs1.getMetaData());
 294         int cols = rsmd.getColumnCount();
 295 
 296         for (int row = 1; row <= rows; row++) {
 297             crs.absolute((row));
 298             crs1.absolute(row);
 299             for (int col = 1; col <= cols; col++) {
 300                 compareColumnValue(JDBCType.valueOf(rsmd.getColumnType(col)),
 301                         crs, crs1, col);
 302             }
 303         }
 304 
 305     }
 306 
 307     /*
 308      * Utility method to compare two columns
 309      */
 310     private void compareColumnValue(JDBCType type, ResultSet rs, ResultSet rs1,
 311             int col) throws SQLException {
 312 
 313         switch (type) {
 314             case INTEGER:
 315                 assertTrue(rs.getInt(col) == rs1.getInt(col));
 316                 break;
 317             case CHAR:
 318             case VARCHAR:
 319                 assertTrue(rs.getString(col).equals(rs1.getString(col)));
 320                 break;
 321             case BIGINT:
 322                 assertTrue(rs.getLong(col) == rs1.getLong(col));
 323                 break;
 324             case BOOLEAN:
 325                 assertTrue(rs.getBoolean(col) == rs1.getBoolean(col));
 326                 break;
 327             case SMALLINT:
 328                 assertTrue(rs.getShort(col) == rs1.getShort(col));
 329                 break;
 330             case DOUBLE:
 331             case FLOAT:
 332                 assertTrue(rs.getDouble(col) == rs1.getDouble(col));
 333                 break;
 334             case DECIMAL:
 335                 assertTrue(rs.getBigDecimal(col).equals(rs1.getBigDecimal(col)));
 336                 break;
 337             case REAL:
 338                 assertTrue(rs.getFloat(col) == rs1.getFloat(col));
 339                 break;
 340             case TINYINT:
 341                 assertTrue(rs.getByte(col) == rs1.getByte(col));
 342                 break;
 343             case DATE:
 344                 assertTrue(rs.getDate(col).equals(rs1.getDate(col)));
 345                 break;
 346             case TIME:
 347                 assertTrue(rs.getTime(col).equals(rs1.getTime(col)));
 348                 break;
 349             case TIMESTAMP:
 350                 assertTrue(rs.getTimestamp(col).equals(rs1.getTimestamp(col)));
 351                 break;
 352         }
 353     }
 354 
 355     /*
 356      * Validate SyncProviderException is thrown when acceptChanges is called
 357      * but there is not a way to make a connection to the datasource
 358      */
 359     @Test(dataProvider = "rowSetType", expectedExceptions = SyncProviderException.class)
 360     public void commonCachedRowSetTest0000(CachedRowSet rs) throws Exception {
 361         rs.acceptChanges();
 362         rs.close();
 363     }
 364 
 365     /*
 366      * Validate SyncProviderException is thrown when acceptChanges is called
 367      * when null is passed as the datasource
 368      */
 369     @Test(dataProvider = "rowSetType", expectedExceptions = SyncProviderException.class)
 370     public void commonCachedRowSetTest0001(CachedRowSet rs) throws Exception {
 371         rs.acceptChanges(null);
 372         rs.close();
 373     }
 374 
 375     /*
 376      * Validate that that RIOPtimsticProvider is the default SyncProvider
 377      */
 378     @Test(dataProvider = "rowSetType")
 379     public void commonCachedRowSetTest0002(CachedRowSet rs) throws SQLException {
 380         SyncProvider sp = rs.getSyncProvider();
 381         assertTrue(sp instanceof com.sun.rowset.providers.RIOptimisticProvider);
 382         rs.close();
 383     }
 384 
 385     /*
 386      * Validate that you can specify a SyncProvider
 387      */
 388     @Test(dataProvider = "rowSetType")
 389     public void commonCachedRowSetTest0003(CachedRowSet rs) throws SQLException {
 390 
 391         // Register a provider and make sure it is avaiable
 392         SyncFactory.registerProvider(stubProvider);
 393         rs.setSyncProvider(stubProvider);
 394         SyncProvider sp = rs.getSyncProvider();
 395         assertTrue(sp instanceof StubSyncProvider);
 396         SyncFactory.unregisterProvider(stubProvider);
 397         rs.close();
 398     }
 399 
 400     /*
 401      * Create a RowSetListener and validate that notifyRowSetChanged is called
 402      */
 403     @Test(dataProvider = "rowSetType")
 404     public void commonCachedRowSetTest0004(CachedRowSet rs) throws Exception {
 405         TestRowSetListener rsl = new TestRowSetListener();
 406         rs.addRowSetListener(rsl);
 407         rs.release();
 408         assertTrue(rsl.isNotified(TestRowSetListener.ROWSET_CHANGED));
 409         rs.close();
 410     }
 411 
 412     /*
 413      * Create a RowSetListener and validate that notifyRowSetChanged is called
 414      */
 415     @Test(dataProvider = "rowSetType")
 416     public void commonCachedRowSetTest0005(CachedRowSet rs) throws Exception {
 417         TestRowSetListener rsl = new TestRowSetListener();
 418         rs.addRowSetListener(rsl);
 419         rs.restoreOriginal();
 420         assertTrue(rsl.isNotified(TestRowSetListener.ROWSET_CHANGED));
 421         rs.close();
 422     }
 423 
 424     /*
 425      * Create a RowSetListener and validate that notifyRowChanged is called
 426      */
 427     @Test(dataProvider = "rowsetUsingCoffeeHouses")
 428     public void commonCachedRowSetTest0006(RowSet rs) throws Exception {
 429         TestRowSetListener rsl = new TestRowSetListener();
 430         rs.addRowSetListener(rsl);
 431         rs.moveToInsertRow();
 432         rs.updateInt(1, 10024);
 433         rs.updateString(2, "Sacramento");
 434         rs.updateInt(3, 1987);
 435         rs.updateInt(4, 2341);
 436         rs.updateInt(5, 4328);
 437         rs.insertRow();
 438         assertTrue(rsl.isNotified(TestRowSetListener.ROW_CHANGED));
 439         rs.close();
 440     }
 441 
 442     /*
 443      * Create a multiple RowSetListeners and validate that notifyRowChanged,
 444      * notifiyMoved is called on all listners
 445      */
 446     @Test(dataProvider = "rowsetUsingCoffeeHouses")
 447     public void commonCachedRowSetTest0007(RowSet rs) throws Exception {
 448         TestRowSetListener rsl = new TestRowSetListener();
 449         TestRowSetListener rsl2 = new TestRowSetListener();
 450         rs.addRowSetListener(rsl);
 451         rs.addRowSetListener(rsl2);
 452         rs.first();
 453         rs.updateInt(1, 1961);
 454         rs.updateString(2, "Pittsburgh");
 455         rs.updateInt(3, 1987);
 456         rs.updateInt(4, 2341);
 457         rs.updateInt(5, 6689);
 458         rs.updateRow();
 459         assertTrue(rsl.isNotified(TestRowSetListener.CURSOR_MOVED
 460                 | TestRowSetListener.ROW_CHANGED));
 461         assertTrue(rsl2.isNotified(TestRowSetListener.CURSOR_MOVED
 462                 | TestRowSetListener.ROW_CHANGED));
 463         rs.close();
 464     }
 465 
 466     /*
 467      * Create a RowSetListener and validate that notifyRowChanged  and
 468      * notifyCursorMoved are  called
 469      */
 470     @Test(dataProvider = "rowsetUsingCoffeeHouses")
 471     public void commonCachedRowSetTest0008(CachedRowSet rs) throws Exception {
 472         TestRowSetListener rsl = new TestRowSetListener();
 473         rs.addRowSetListener(rsl);
 474 
 475         rs.first();
 476         assertTrue(rsl.isNotified(TestRowSetListener.CURSOR_MOVED));
 477         rs.deleteRow();
 478         assertTrue(
 479                 rsl.isNotified(TestRowSetListener.ROW_CHANGED | TestRowSetListener.CURSOR_MOVED));
 480         rsl.resetFlag();
 481         rs.setShowDeleted(true);
 482         rs.undoDelete();
 483         assertTrue(rsl.isNotified(TestRowSetListener.ROW_CHANGED));
 484         rs.close();
 485     }
 486 
 487     /*
 488      * Create a RowSetListener and validate that notifyCursorMoved is called
 489      */
 490     @Test(dataProvider = "rowSetType")
 491     public void commonCachedRowSetTest0009(RowSet rs) throws Exception {
 492         TestRowSetListener rsl = new TestRowSetListener();
 493         rs.addRowSetListener(rsl);
 494         rs.beforeFirst();
 495         assertTrue(rsl.isNotified(TestRowSetListener.CURSOR_MOVED));
 496         rs.close();
 497     }
 498 
 499     /*
 500      * Validate that getTableName() returns the proper values
 501      */
 502     @Test(dataProvider = "rowSetType")
 503     public void commonCachedRowSetTest0010(CachedRowSet rs) throws Exception {
 504         assertNull(rs.getTableName());
 505         rs.setTableName(COFFEE_HOUSES_TABLE);
 506         assertTrue(rs.getTableName().equals(COFFEE_HOUSES_TABLE));
 507         rs.close();
 508     }
 509 
 510     /*
 511      * Validate that getKeyColumns() returns the proper values
 512      */
 513     @Test(dataProvider = "rowSetType")
 514     public void commonCachedRowSetTest0011(CachedRowSet rs) throws Exception {
 515         int[] pkeys = {1, 3};
 516         assertNull(rs.getKeyColumns());
 517         rs.setKeyColumns(pkeys);
 518         assertEquals(rs.getKeyColumns(), pkeys);
 519         rs.close();
 520     }
 521 
 522     /*
 523      * Validate that setMatchColumn throws a SQLException if the column
 524      * index specified is out of range
 525      */
 526     @Test(dataProvider = "rowsetUsingCoffeeHouses",
 527             expectedExceptions = SQLException.class)
 528     public void commonCachedRowSetTest0012(CachedRowSet rs) throws Exception {
 529         rs.setMatchColumn(-1);
 530         rs.close();
 531     }
 532 
 533     /*
 534      * Validate that setMatchColumn throws a SQLException if the column
 535      * index specified is out of range
 536      */
 537     @Test(dataProvider = "rowsetUsingCoffeeHouses",
 538             expectedExceptions = SQLException.class)
 539     public void commonCachedRowSetTest0013(CachedRowSet rs) throws Exception {
 540         int[] cols = {1, -1};
 541         rs.setMatchColumn(cols);
 542         rs.close();
 543     }
 544 
 545     /*
 546      * Validate that setMatchColumn throws a SQLException if the column
 547      * index specified is out of range
 548      */
 549     @Test(dataProvider = "rowsetUsingCoffeeHouses",
 550             expectedExceptions = SQLException.class)
 551     public void commonCachedRowSetTest0014(CachedRowSet rs) throws Exception {
 552         rs.setMatchColumn((String) null);
 553         rs.close();
 554     }
 555 
 556     /*
 557      * Validate that setMatchColumn throws a SQLException if the column
 558      * index specified is out of range
 559      */
 560     @Test(dataProvider = "rowsetUsingCoffeeHouses",
 561             expectedExceptions = SQLException.class)
 562     public void commonCachedRowSetTest0015(CachedRowSet rs) throws Exception {
 563         String[] cols = {"ID", null};
 564         rs.setMatchColumn(cols);
 565     }
 566 
 567     /*
 568      * Validate that getMatchColumn returns the same value specified by
 569      * setMatchColumn
 570      */
 571     @Test(dataProvider = "rowsetUsingCoffeeHouses", enabled = false)
 572     public void commonCachedRowSetTest0016(CachedRowSet rs) throws Exception {
 573         int[] expectedCols = {1};
 574         String[] expectedColNames = {"ID"};
 575         rs.setMatchColumn(1);
 576         int[] actualCols = rs.getMatchColumnIndexes();
 577         String[] actualColNames = rs.getMatchColumnNames();
 578         for (int i = 0; i < actualCols.length; i++) {
 579             System.out.println(actualCols[i]);
 580         }
 581         assertEquals(actualCols, expectedCols);
 582         assertEquals(actualColNames, expectedColNames);
 583         rs.close();
 584     }
 585 
 586     /*
 587      * Validate that getMatchColumn returns the same value specified by
 588      * setMatchColumn
 589      */
 590     @Test(dataProvider = "rowsetUsingCoffeeHouses", enabled = false)
 591     public void commonCachedRowSetTest0017(CachedRowSet rs) throws Exception {
 592         int[] expectedCols = {1};
 593         String[] expectedColNames = {"ID"};
 594         rs.setMatchColumn(expectedColNames[0]);
 595         int[] actualCols = rs.getMatchColumnIndexes();
 596         String[] actualColNames = rs.getMatchColumnNames();
 597         assertEquals(actualCols, expectedCols);
 598         assertEquals(actualColNames, expectedColNames);
 599         rs.close();
 600     }
 601 
 602     /*
 603      * Validate that getMatchColumn returns the same valid value specified by
 604      * setMatchColumn
 605      */
 606     @Test(dataProvider = "rowsetUsingCoffeeHouses", enabled = false)
 607     public void commonCachedRowSetTest0018(CachedRowSet rs) throws Exception {
 608         int[] expectedCols = {1, 3};
 609         String[] expectedColNames = {"COF_ID", "SUP_ID"};
 610         rs.setMatchColumn(expectedCols);
 611         int[] actualCols = rs.getMatchColumnIndexes();
 612         String[] actualColNames = rs.getMatchColumnNames();
 613         assertEquals(actualCols, expectedCols);
 614         assertEquals(actualColNames, expectedColNames);
 615         assertEquals(actualCols, expectedCols);
 616         rs.close();
 617     }
 618 
 619     /*
 620      * Validate that getMatchColumn returns the same valid value specified by
 621      * setMatchColumn
 622      */
 623     @Test(dataProvider = "rowsetUsingCoffeeHouses", enabled = false)
 624     public void commonCachedRowSetTest0019(CachedRowSet rs) throws Exception {
 625         int[] expectedCols = {1, 3};
 626         String[] expectedColNames = {"COF_ID", "SUP_ID"};
 627         rs.setMatchColumn(expectedColNames);
 628         int[] actualCols = rs.getMatchColumnIndexes();
 629         String[] actualColNames = rs.getMatchColumnNames();
 630         assertEquals(actualCols, expectedCols);
 631         assertEquals(actualColNames, expectedColNames);
 632         rs.close();
 633     }
 634 
 635     /*
 636      * Validate that getMatchColumnIndexes throws a SQLException if
 637      * unsetMatchColumn has been called
 638      */
 639     @Test(dataProvider = "rowsetUsingCoffeeHouses",
 640             expectedExceptions = SQLException.class)
 641     public void commonCachedRowSetTest0020(CachedRowSet rs) throws Exception {
 642         rs.setMatchColumn(1);
 643         int[] actualCols = rs.getMatchColumnIndexes();
 644         assertTrue(actualCols != null);
 645         rs.unsetMatchColumn(1);
 646         actualCols = rs.getMatchColumnIndexes();
 647         rs.close();
 648     }
 649 
 650     /*
 651      * Validate that getMatchColumnNames throws a SQLException if
 652      * unsetMatchColumn has been called
 653      */
 654     @Test(dataProvider = "rowsetUsingCoffeeHouses",
 655             expectedExceptions = SQLException.class)
 656     public void commonCachedRowSetTest0021(CachedRowSet rs) throws Exception {
 657         String matchColumn = "ID";
 658         rs.setMatchColumn(matchColumn);
 659         String[] actualColNames = rs.getMatchColumnNames();
 660         assertTrue(actualColNames != null);
 661         rs.unsetMatchColumn(matchColumn);
 662         actualColNames = rs.getMatchColumnNames();
 663         rs.close();
 664     }
 665 
 666     /*
 667      * Validate that getMatchColumnIndexes throws a SQLException if
 668      * unsetMatchColumn has been called
 669      */
 670     @Test(dataProvider = "rowsetUsingCoffeeHouses",
 671             expectedExceptions = SQLException.class)
 672     public void commonCachedRowSetTest0022(CachedRowSet rs) throws Exception {
 673         int[] expectedCols = {1, 3};
 674         rs.setMatchColumn(expectedCols);
 675         int[] actualCols = rs.getMatchColumnIndexes();
 676         assertTrue(actualCols != null);
 677         rs.unsetMatchColumn(expectedCols);
 678         actualCols = rs.getMatchColumnIndexes();
 679         rs.close();
 680     }
 681 
 682     /*
 683      * Validate that getMatchColumnNames throws a SQLException if
 684      * unsetMatchColumn has been called
 685      */
 686     @Test(dataProvider = "rowsetUsingCoffeeHouses",
 687             expectedExceptions = SQLException.class)
 688     public void commonCachedRowSetTest0023(CachedRowSet rs) throws Exception {
 689         String[] expectedColNames = {"COF_ID", "SUP_ID"};
 690         rs.setMatchColumn(expectedColNames);
 691         String[] actualColNames = rs.getMatchColumnNames();
 692         assertTrue(actualColNames != null);
 693         rs.unsetMatchColumn(expectedColNames);
 694         actualColNames = rs.getMatchColumnNames();
 695         rs.close();
 696     }
 697 
 698     /*
 699      * Validate size() returns the correct number of rows
 700      */
 701     @Test(dataProvider = "rowsetUsingCoffeeHouses")
 702     public void commonCachedRowSetTest0024(CachedRowSet rs) throws Exception {
 703         assertTrue(rs.size() == COFFEE_HOUSES_ROWS);
 704         rs.close();
 705     }
 706 
 707     /*
 708      * Validate that the correct rows are returned comparing the primary
 709      * keys
 710      */
 711     @Test(dataProvider = "rowsetUsingCoffeeHouses")
 712     public void commonCachedRowSetTest0025(RowSet rs) throws SQLException {
 713         assertEquals(getPrimaryKeys(rs), COFFEE_HOUSES_PRIMARY_KEYS);
 714         rs.close();
 715     }
 716 
 717     /*
 718      * Delete a row within the RowSet using its primary key
 719      * Validate the visibility of the row depending on the value of
 720      * setShowdelete
 721      */
 722     @Test(dataProvider = "rowsetUsingCoffeeHouses")
 723     public void commonCachedRowSetTest0026(CachedRowSet rs) throws Exception {
 724         Object[] afterDelete = {
 725             10023, 33002, 10040, 32001, 10042, 10024, 10039, 10041,
 726             33005, 33010, 10037, 10034, 32004
 727         };
 728         int rowToDelete = 10035;
 729         // All rows should be found
 730         assertEquals(getPrimaryKeys(rs), COFFEE_HOUSES_PRIMARY_KEYS);
 731         // Delete the row
 732         assertTrue(deleteRowByPrimaryKey(rs, rowToDelete, 1));
 733         // With setShowDeleted(false) which is the default,
 734         // the deleted row should not be visible
 735         assertFalse(findRowByPrimaryKey(rs, rowToDelete, 1));
 736         assertEquals(getPrimaryKeys(rs), afterDelete);
 737         assertTrue(rs.size() == COFFEE_HOUSES_ROWS);
 738         // With setShowDeleted(true), the deleted row should be visible
 739         rs.setShowDeleted(true);
 740         assertTrue(findRowByPrimaryKey(rs, rowToDelete, 1));
 741         rs.close();
 742     }
 743 
 744     /*
 745      * Validate that there is no page size by default
 746      */
 747     @Test(dataProvider = "rowSetType")
 748     public void commonCachedRowSetTest0027(CachedRowSet rs) throws Exception {
 749         assertTrue(rs.getPageSize() == 0);
 750         rs.close();
 751     }
 752 
 753     /*
 754      * Validate the value you set via setPageSize is returned by getPageSize
 755      * then reset to having no limit
 756      */
 757     @Test(dataProvider = "rowSetType")
 758     public void commonCachedRowSetTest0028(CachedRowSet rs) throws Exception {
 759         int rows = 100;
 760         rs.setPageSize(rows);
 761         assertTrue(rows == rs.getPageSize());
 762         rs.setPageSize(0);
 763         assertTrue(rs.getPageSize() == 0);
 764         rs.close();
 765     }
 766 
 767     /*
 768      * Validate SQLException is thrown when an invalid value is specified
 769      * for setPageSize
 770      */
 771     @Test(dataProvider = "rowSetType", expectedExceptions = SQLException.class)
 772     public void commonCachedRowSetTest0029(CachedRowSet rs) throws Exception {
 773         rs.setPageSize(-1);
 774         rs.close();
 775     }
 776 
 777     /*
 778      * Validate SQLException is thrown when nextPage is called without a
 779      * call to populate or execute
 780      */
 781     @Test(dataProvider = "rowSetType", expectedExceptions = SQLException.class)
 782     public void commonCachedRowSetTest0030(CachedRowSet rs) throws Exception {
 783         rs.nextPage();
 784         rs.close();
 785     }
 786 
 787     /*
 788      * Validate SQLException is thrown when previousPage is called without a
 789      * call to populate or execute
 790      */
 791     @Test(dataProvider = "rowSetType", expectedExceptions = SQLException.class)
 792     public void commonCachedRowSetTest0031(CachedRowSet rs) throws Exception {
 793         rs.previousPage();
 794         rs.close();
 795     }
 796 
 797 
 798     /*
 799      * Validate SQLException is thrown when execute is called
 800      * but there is not a way to make a connection to the datasource
 801      */
 802     @Test(dataProvider = "rowSetType", expectedExceptions = SQLException.class)
 803     public void commonCachedRowSetTest0032(CachedRowSet rs) throws Exception {
 804         rs.execute(null);
 805         rs.close();
 806     }
 807 
 808     /*
 809      * Validate SQLException is thrown when execute is called
 810      * but there is not a way to make a connection to the datasource
 811      */
 812     @Test(dataProvider = "rowSetType", expectedExceptions = SQLException.class)
 813     public void commonCachedRowSetTest0033(CachedRowSet rs) throws Exception {
 814         rs.execute();
 815         rs.close();
 816     }
 817 
 818     /*
 819      * Validate that toCollection(<column>) returns the proper values
 820      */
 821     @Test(dataProvider = "rowsetUsingCoffeeHouses")
 822     public void commonCachedRowSetTest0034(CachedRowSet rs) throws Exception {
 823         Object[] cities = {"Mendocino", "Seattle", "SF", "Portland", "SF",
 824             "Sacramento", "Carmel", "LA", "Olympia", "Seattle", "SF",
 825             "LA", "San Jose", "Eugene"};
 826         rs.beforeFirst();
 827         assertEquals(rs.toCollection(2).toArray(), cities);
 828         assertEquals(rs.toCollection("CITY").toArray(), cities);
 829         rs.close();
 830     }
 831 
 832     /*
 833      * Validate that toCollection() returns the proper values
 834      */
 835     @Test(dataProvider = "rowsetUsingCoffeeHouses")
 836     public void commonCachedRowSetTest0035(CachedRowSet rs) throws Exception {
 837         Collection<?> col = rs.toCollection();
 838         assertTrue(rs.size() == col.size());
 839         assertTrue(rs.toCollection().containsAll(col)
 840                 && col.containsAll(rs.toCollection()));
 841         try ( // Validate that False is returned when compared to a different RowSet;
 842                 CachedRowSet crs1 = createCoffeesRowSet()) {
 843             assertFalse(crs1.toCollection().containsAll(col)
 844                     && col.containsAll(crs1.toCollection()));
 845         }
 846         rs.close();
 847 
 848     }
 849 
 850     /*
 851      * Validate that createCopy() returns the proper values
 852      */
 853     @Test(dataProvider = "rowsetUsingCoffeeHouses")
 854     public void commonCachedRowSetTest0036(CachedRowSet rs) throws Exception {
 855         try (CachedRowSet crs1 = rs.createCopy()) {
 856             compareRowSets(rs, crs1);
 857         }
 858         rs.close();
 859     }
 860 
 861     /*
 862      * Validate that createCopySchema() returns the proper values
 863      */
 864     @Test(dataProvider = "rowsetUsingCoffeeHouses")
 865     public void commonCachedRowSetTest0037(CachedRowSet rs) throws Exception {
 866         try (CachedRowSet crs1 = rs.createCopySchema()) {
 867             assertTrue(crs1.size() == 0);
 868             compareMetaData(crs1.getMetaData(), rs.getMetaData());
 869         }
 870         rs.close();
 871     }
 872 
 873     /*
 874      * Validate that createCopyNoConstraints() returns the proper values
 875      * and getMatchColumnIndexes should throw a SQLException. This test
 876      * specifies setMatchColumn(int)
 877      */
 878     @Test(dataProvider = "rowsetUsingCoffeeHouses")
 879     public void commonCachedRowSetTest0038(CachedRowSet rs) throws Exception {
 880         rs.setMatchColumn(1);
 881         try (CachedRowSet crs1 = rs.createCopyNoConstraints()) {
 882             assertTrue(crs1.size() == COFFEE_HOUSES_ROWS);
 883             compareRowSets(rs, crs1);
 884             boolean recievedSQE = false;
 885             try {
 886                 int[] indexes = crs1.getMatchColumnIndexes();
 887             } catch (SQLException e) {
 888                 recievedSQE = true;
 889             }
 890             assertTrue(recievedSQE);
 891             recievedSQE = false;
 892             try {
 893                 String[] colNames = crs1.getMatchColumnNames();
 894             } catch (SQLException e) {
 895                 recievedSQE = true;
 896             }
 897             assertTrue(recievedSQE);
 898         }
 899         rs.close();
 900     }
 901 
 902     /*
 903      * Validate that createCopyNoConstraints() returns the proper values
 904      * and getMatchColumnIndexes should throw a SQLException. This test
 905      * specifies setMatchColumn(String)
 906      */
 907     @Test(dataProvider = "rowsetUsingCoffeeHouses")
 908     public void commonCachedRowSetTest0039(CachedRowSet rs) throws Exception {
 909         rs.setMatchColumn("ID");
 910         try (CachedRowSet crs1 = rs.createCopyNoConstraints()) {
 911             assertTrue(crs1.size() == COFFEE_HOUSES_ROWS);
 912             compareRowSets(rs, crs1);
 913             boolean recievedSQE = false;
 914             try {
 915                 int[] indexes = crs1.getMatchColumnIndexes();
 916             } catch (SQLException e) {
 917                 recievedSQE = true;
 918             }
 919             assertTrue(recievedSQE);
 920             recievedSQE = false;
 921             try {
 922                 String[] colNames = crs1.getMatchColumnNames();
 923             } catch (SQLException e) {
 924                 recievedSQE = true;
 925             }
 926             assertTrue(recievedSQE);
 927         }
 928         rs.close();
 929     }
 930 
 931     /*
 932      * Validate that columnUpdated works with the various datatypes specifying
 933      * the column index
 934      */
 935     @Test(dataProvider = "rowsetUsingDataTypes")
 936     public void commonCachedRowSetTest0040(CachedRowSet rs, JDBCType type) throws Exception {
 937         rs.beforeFirst();
 938         assertTrue(rs.next());
 939         switch (type) {
 940             case INTEGER:
 941                 assertFalse(rs.columnUpdated(1));
 942                 rs.updateInt(1, Integer.MIN_VALUE);
 943                 assertTrue(rs.columnUpdated(1));
 944                 break;
 945             case CHAR:
 946                 assertFalse(rs.columnUpdated(2));
 947                 rs.updateString(2, "foo");
 948                 assertTrue(rs.columnUpdated(2));
 949                 break;
 950             case VARCHAR:
 951                 assertFalse(rs.columnUpdated(3));
 952                 rs.updateString(3, "foo");
 953                 assertTrue(rs.columnUpdated(3));
 954                 break;
 955             case BIGINT:
 956                 assertFalse(rs.columnUpdated(4));
 957                 rs.updateLong(4, Long.MIN_VALUE);
 958                 assertTrue(rs.columnUpdated(4));
 959                 break;
 960             case BOOLEAN:
 961                 assertFalse(rs.columnUpdated(5));
 962                 rs.updateBoolean(5, false);
 963                 assertTrue(rs.columnUpdated(5));
 964                 break;
 965             case SMALLINT:
 966                 assertFalse(rs.columnUpdated(6));
 967                 rs.updateShort(6, Short.MIN_VALUE);
 968                 assertTrue(rs.columnUpdated(6));
 969                 break;
 970             case DOUBLE:
 971                 assertFalse(rs.columnUpdated(7));
 972                 rs.updateDouble(7, Double.MIN_VALUE);
 973                 assertTrue(rs.columnUpdated(7));
 974                 break;
 975             case DECIMAL:
 976                 assertFalse(rs.columnUpdated(8));
 977                 rs.updateBigDecimal(8, BigDecimal.TEN);
 978                 assertTrue(rs.columnUpdated(8));
 979                 break;
 980             case REAL:
 981                 assertFalse(rs.columnUpdated(9));
 982                 rs.updateFloat(9, Float.MIN_VALUE);
 983                 assertTrue(rs.columnUpdated(9));
 984                 break;
 985             case TINYINT:
 986                 assertFalse(rs.columnUpdated(10));
 987                 rs.updateByte(10, Byte.MIN_VALUE);
 988                 assertTrue(rs.columnUpdated(10));
 989                 break;
 990             case DATE:
 991                 assertFalse(rs.columnUpdated(11));
 992                 rs.updateDate(11, Date.valueOf(LocalDate.now()));
 993                 assertTrue(rs.columnUpdated(11));
 994                 break;
 995             case TIME:
 996                 assertFalse(rs.columnUpdated(12));
 997                 rs.updateTime(12, Time.valueOf(LocalTime.now()));
 998                 assertTrue(rs.columnUpdated(12));
 999                 break;
1000             case TIMESTAMP:
1001                 assertFalse(rs.columnUpdated(13));
1002                 rs.updateTimestamp(13, Timestamp.valueOf(LocalDateTime.now()));
1003                 assertTrue(rs.columnUpdated(13));
1004                 break;
1005             case VARBINARY:
1006                 assertFalse(rs.columnUpdated(14));
1007                 rs.updateBytes(14, new byte[1]);
1008                 assertTrue(rs.columnUpdated(14));
1009                 break;
1010             case ARRAY:
1011                 assertFalse(rs.columnUpdated(15));
1012                 rs.updateArray(15, new StubArray("VARCHAR", new Object[10]));
1013                 assertTrue(rs.columnUpdated(15));
1014                 break;
1015             case REF:
1016                 assertFalse(rs.columnUpdated(16));
1017                 rs.updateRef(16, new StubRef("INTEGER", query));
1018                 assertTrue(rs.columnUpdated(16));
1019                 break;
1020             case FLOAT:
1021                 assertFalse(rs.columnUpdated(17));
1022                 rs.updateDouble(17, Double.MIN_NORMAL);
1023                 assertTrue(rs.columnUpdated(17));
1024         }
1025 
1026     }
1027 
1028     /*
1029      * Validate that columnUpdated works with the various datatypes specifying
1030      * the column name
1031      */
1032     @Test(dataProvider = "rowsetUsingDataTypes")
1033     public void commonCachedRowSetTest0041(CachedRowSet rs, JDBCType type) throws Exception {
1034         rs.beforeFirst();
1035         assertTrue(rs.next());
1036         switch (type) {
1037             case INTEGER:
1038                 assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[0]));
1039                 rs.updateInt(DATATYPES_COLUMN_NAMES[0], Integer.MIN_VALUE);
1040                 assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[0]));
1041                 break;
1042             case CHAR:
1043                 assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[1]));
1044                 rs.updateString(DATATYPES_COLUMN_NAMES[1], "foo");
1045                 assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[1]));
1046                 break;
1047             case VARCHAR:
1048                 assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[2]));
1049                 rs.updateString(DATATYPES_COLUMN_NAMES[2], "foo");
1050                 assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[2]));
1051                 break;
1052             case BIGINT:
1053                 assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[3]));
1054                 rs.updateLong(DATATYPES_COLUMN_NAMES[3], Long.MIN_VALUE);
1055                 assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[3]));
1056                 break;
1057             case BOOLEAN:
1058                 assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[4]));
1059                 rs.updateBoolean(DATATYPES_COLUMN_NAMES[4], false);
1060                 assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[4]));
1061                 break;
1062             case SMALLINT:
1063                 assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[5]));
1064                 rs.updateShort(DATATYPES_COLUMN_NAMES[5], Short.MIN_VALUE);
1065                 assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[5]));
1066                 break;
1067             case DOUBLE:
1068                 assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[6]));
1069                 rs.updateDouble(DATATYPES_COLUMN_NAMES[6], Double.MIN_VALUE);
1070                 assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[6]));
1071                 break;
1072             case DECIMAL:
1073                 assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[7]));
1074                 rs.updateBigDecimal(DATATYPES_COLUMN_NAMES[7], BigDecimal.TEN);
1075                 assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[7]));
1076                 break;
1077             case REAL:
1078                 assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[8]));
1079                 rs.updateFloat(DATATYPES_COLUMN_NAMES[8], Float.MIN_VALUE);
1080                 assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[8]));
1081                 break;
1082             case TINYINT:
1083                 assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[9]));
1084                 rs.updateByte(DATATYPES_COLUMN_NAMES[9], Byte.MIN_VALUE);
1085                 assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[9]));
1086                 break;
1087             case DATE:
1088                 assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[10]));
1089                 rs.updateDate(DATATYPES_COLUMN_NAMES[10], Date.valueOf(LocalDate.now()));
1090                 assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[10]));
1091                 break;
1092             case TIME:
1093                 assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[11]));
1094                 rs.updateTime(DATATYPES_COLUMN_NAMES[11], Time.valueOf(LocalTime.now()));
1095                 assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[11]));
1096                 break;
1097             case TIMESTAMP:
1098                 assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[12]));
1099                 rs.updateTimestamp(DATATYPES_COLUMN_NAMES[12], Timestamp.valueOf(LocalDateTime.now()));
1100                 assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[12]));
1101                 break;
1102             case VARBINARY:
1103                 assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[13]));
1104                 rs.updateBytes(DATATYPES_COLUMN_NAMES[13], new byte[1]);
1105                 assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[13]));
1106                 break;
1107             case ARRAY:
1108                 assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[14]));
1109                 rs.updateArray(DATATYPES_COLUMN_NAMES[14], new StubArray("VARCHAR", new Object[10]));
1110                 assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[14]));
1111                 break;
1112             case REF:
1113                 assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[15]));
1114                 rs.updateRef(DATATYPES_COLUMN_NAMES[15], new StubRef("INTEGER", query));
1115                 assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[15]));
1116                 break;
1117             case FLOAT:
1118                 assertFalse(rs.columnUpdated(DATATYPES_COLUMN_NAMES[16]));
1119                 rs.updateDouble(DATATYPES_COLUMN_NAMES[16], Double.MIN_NORMAL);
1120                 assertTrue(rs.columnUpdated(DATATYPES_COLUMN_NAMES[16]));
1121                 break;
1122         }
1123 
1124     }
1125 
1126     /*
1127      * Validate isBeforeFirst(), isFirst() and first() return the correct
1128      * results
1129      */
1130     @Test(dataProvider = "rowsetUsingCoffeeHouses")
1131     public void commonCachedRowSetTest0042(RowSet rs) throws Exception {
1132         assertFalse(rs.isBeforeFirst());
1133         assertFalse(rs.isFirst());
1134         rs.beforeFirst();
1135         assertTrue(rs.isBeforeFirst());
1136         assertFalse(rs.isFirst());
1137         rs.next();
1138         assertFalse(rs.isBeforeFirst());
1139         assertTrue(rs.isFirst());
1140         rs.next();
1141         assertFalse(rs.isBeforeFirst());
1142         assertFalse(rs.isFirst());
1143         rs.first();
1144         assertFalse(rs.isBeforeFirst());
1145         assertTrue(rs.isFirst());
1146         rs.close();
1147     }
1148 
1149     /*
1150      * Validate isAfterLast(), isLast() and last() return the correct
1151      * results
1152      */
1153     @Test(dataProvider = "rowsetUsingCoffeeHouses")
1154     public void commonCachedRowSetTest0043(RowSet rs) throws Exception {
1155         assertFalse(rs.isAfterLast());
1156         assertFalse(rs.isLast());
1157         rs.afterLast();
1158         assertTrue(rs.isAfterLast());
1159         assertFalse(rs.isLast());
1160         rs.previous();
1161         assertFalse(rs.isAfterLast());
1162         assertTrue(rs.isLast());
1163         rs.previous();
1164         assertFalse(rs.isAfterLast());
1165         assertFalse(rs.isLast());
1166         rs.last();
1167         assertFalse(rs.isAfterLast());
1168         assertTrue(rs.isLast());
1169         rs.close();
1170     }
1171 
1172     /*
1173      * Validate a SQLException is thrown when undoDelete is called on the
1174      * insertRow
1175      */
1176     @Test(dataProvider = "rowsetUsingCoffeeHouses",
1177             expectedExceptions = SQLException.class)
1178     public void commonCachedRowSetTest0044(CachedRowSet rs) throws Exception {
1179         rs.insertRow();
1180         rs.undoDelete();
1181         rs.close();
1182     }
1183 
1184     /*
1185      * Validate a SQLException is thrown when undoDelete is called when
1186      * cursor is before the first row
1187      */
1188     @Test(dataProvider = "rowsetUsingCoffeeHouses",
1189             expectedExceptions = SQLException.class)
1190     public void commonCachedRowSetTest0045(CachedRowSet rs) throws Exception {
1191         rs.setShowDeleted(true);
1192         rs.beforeFirst();
1193         rs.undoDelete();
1194         rs.close();
1195     }
1196 
1197     /*
1198      * Validate a SQLException is thrown when undoDelete is called when
1199      * cursor is after the last row
1200      */
1201     @Test(dataProvider = "rowsetUsingCoffeeHouses",
1202             expectedExceptions = SQLException.class)
1203     public void commonCachedRowSetTest0046(CachedRowSet rs) throws Exception {
1204         rs.setShowDeleted(true);
1205         rs.afterLast();
1206         rs.undoDelete();
1207         rs.close();
1208     }
1209 
1210     /*
1211      * Validate a SQLException is thrown when undoUpdate is called on the
1212      * insertRow
1213      */
1214     @Test(dataProvider = "rowsetUsingCoffeeHouses",
1215             expectedExceptions = SQLException.class)
1216     public void commonCachedRowSetTest0047(CachedRowSet rs) throws Exception {
1217         rs.insertRow();
1218         rs.undoUpdate();
1219         rs.close();
1220     }
1221 
1222     /*
1223      * Validate a SQLException is thrown when undoUpdate is called when
1224      * cursor is before the first row
1225      */
1226     @Test(dataProvider = "rowsetUsingCoffeeHouses",
1227             expectedExceptions = SQLException.class)
1228     public void commonCachedRowSetTest0048(CachedRowSet rs) throws Exception {
1229         rs.setShowDeleted(true);
1230         rs.beforeFirst();
1231         rs.undoUpdate();
1232         rs.close();
1233     }
1234 
1235     /*
1236      * Validate a SQLException is thrown when undoUpdate is called when
1237      * cursor is after the last row
1238      */
1239     @Test(dataProvider = "rowsetUsingCoffeeHouses",
1240             expectedExceptions = SQLException.class)
1241     public void commonCachedRowSetTest0049(CachedRowSet rs) throws Exception {
1242         rs.setShowDeleted(true);
1243         rs.afterLast();
1244         rs.undoUpdate();
1245         rs.close();
1246     }
1247 
1248     /*
1249      * Validate a SQLException is thrown when undoInsert is called on the
1250      * insertRow
1251      */
1252     @Test(dataProvider = "rowsetUsingCoffeeHouses",
1253             expectedExceptions = SQLException.class)
1254     public void commonCachedRowSetTest0050(CachedRowSet rs) throws Exception {
1255         rs.insertRow();
1256         rs.undoInsert();
1257         rs.close();
1258     }
1259 
1260     /*
1261      * Validate a SQLException is thrown when undoInsert is called when
1262      * cursor is before the first row
1263      */
1264     @Test(dataProvider = "rowsetUsingCoffeeHouses",
1265             expectedExceptions = SQLException.class)
1266     public void commonCachedRowSetTest0051(CachedRowSet rs) throws Exception {
1267         rs.setShowDeleted(true);
1268         rs.beforeFirst();
1269         rs.undoInsert();
1270         rs.close();
1271     }
1272 
1273     /*
1274      * Validate a SQLException is thrown when undoInsert is called when
1275      * cursor is after the last row
1276      */
1277     @Test(dataProvider = "rowsetUsingCoffeeHouses",
1278             expectedExceptions = SQLException.class)
1279     public void commonCachedRowSetTest0052(CachedRowSet rs) throws Exception {
1280         rs.setShowDeleted(true);
1281         rs.afterLast();
1282         rs.undoInsert();
1283         rs.close();
1284     }
1285 
1286     /*
1287      * Insert a row, then call undoInsert to roll back the insert and validate
1288      * the row is not there
1289      */
1290     @Test(dataProvider = "rowsetUsingCoffeeHouses")
1291     public void commonCachedRowSetTest0053(CachedRowSet rs) throws Exception {
1292         int rowToInsert = 1961;
1293         assertTrue(rs.size() == COFFEE_HOUSES_ROWS);
1294         // Add new row
1295         rs.moveToInsertRow();
1296         rs.updateInt(1, rowToInsert);
1297         rs.updateString(2, "GOTHAM");
1298         rs.updateInt(3, 3450);
1299         rs.updateInt(4, 2005);
1300         rs.updateInt(5, 5455);
1301         rs.insertRow();
1302         rs.moveToCurrentRow();
1303         // check that the number of rows has increased
1304         assertTrue(rs.size() == COFFEE_HOUSES_ROWS + 1);
1305         assertTrue(findRowByPrimaryKey(rs, rowToInsert, 1));
1306         rs.undoInsert();
1307         // Check to make sure the row is no longer there
1308         assertTrue(rs.size() == COFFEE_HOUSES_ROWS);
1309         assertFalse(findRowByPrimaryKey(rs, rowToInsert, 1));
1310         rs.close();
1311     }
1312 
1313     /*
1314      * Insert a row, delete the row and then call undoDelete to make sure it
1315      * is comes back
1316      */
1317     @Test(dataProvider = "rowsetUsingCoffeeHouses")
1318     public void commonCachedRowSetTest0054(CachedRowSet rs) throws Exception {
1319         int rowToDelete = 1961;
1320         assertTrue(rs.size() == COFFEE_HOUSES_ROWS);
1321         // Add new row
1322         rs.moveToInsertRow();
1323         rs.updateInt(1, rowToDelete);
1324         rs.updateString(2, "GOTHAM");
1325         rs.updateInt(3, 3450);
1326         rs.updateInt(4, 2005);
1327         rs.updateInt(5, 5455);
1328         rs.insertRow();
1329         rs.moveToCurrentRow();
1330         // check that the number of rows has increased
1331         assertTrue(rs.size() == COFFEE_HOUSES_ROWS + 1);
1332         assertTrue(findRowByPrimaryKey(rs, rowToDelete, 1));
1333         rs.absolute(COFFEE_HOUSES_ROWS + 1);
1334         rs.deleteRow();
1335         // Check to make sure the row is no longer there
1336         //assertTrue(rs.size() ==  COFFEE_HOUSES_ROWS);
1337         assertFalse(findRowByPrimaryKey(rs, rowToDelete, 1));
1338         rs.setShowDeleted(true);
1339         rs.absolute(COFFEE_HOUSES_ROWS + 1);
1340         rs.undoDelete();
1341         // check that the row is back
1342         assertTrue(rs.size() == COFFEE_HOUSES_ROWS + 1);
1343         assertTrue(findRowByPrimaryKey(rs, rowToDelete, 1));
1344         rs.close();
1345     }
1346 
1347     /*
1348      * Insert a row, modify a field and then call undoUpdate to revert the
1349      * insert
1350      */
1351     @Test(dataProvider = "rowsetUsingCoffeeHouses")
1352     public void commonCachedRowSetTest0055(CachedRowSet rs) throws Exception {
1353         int rowToInsert = 1961;
1354         assertTrue(rs.size() == COFFEE_HOUSES_ROWS);
1355         // Add new row
1356         rs.moveToInsertRow();
1357         rs.updateInt(1, rowToInsert);
1358         rs.updateString(2, "GOTHAM");
1359         rs.updateInt(3, 3450);
1360         rs.updateInt(4, 2005);
1361         rs.updateInt(5, 5455);
1362         rs.insertRow();
1363         rs.moveToCurrentRow();
1364         // check that the number of rows has increased
1365         assertTrue(rs.size() == COFFEE_HOUSES_ROWS + 1);
1366         assertTrue(findRowByPrimaryKey(rs, rowToInsert, 1));
1367         rs.absolute(COFFEE_HOUSES_ROWS + 1);
1368         // Save off the original column values
1369         String f2 = rs.getString(2);
1370         int f3 = rs.getInt(3);
1371         rs.updateString(2, "SMALLVILLE");
1372         rs.updateInt(3, 500);
1373         // Validate the columns have been updated
1374         assertTrue(rs.columnUpdated(2));
1375         assertTrue(rs.columnUpdated(3));
1376         // Undo the update and validate it has taken place
1377         rs.absolute(COFFEE_HOUSES_ROWS + 1);
1378         rs.undoUpdate();
1379         assertTrue(rs.size() == COFFEE_HOUSES_ROWS);
1380         assertFalse(findRowByPrimaryKey(rs, rowToInsert, 1));
1381         rs.close();
1382     }
1383 
1384     /*
1385      * Validate getOriginal returns a ResultSet which is a copy of the original
1386      * RowSet
1387      */
1388     @Test(dataProvider = "rowsetUsingCoffees")
1389     public void commonCachedRowSetTest0056(CachedRowSet rs) throws Exception {
1390         String coffee = "Hazelnut";
1391         int sales = 100;
1392         int id = 200;
1393         Object[] updatedPkeys = {1, id, 3, 4, 5};
1394         // Change the coffee name and sales total for row 2 and save the
1395         // previous values
1396         rs.absolute(2);
1397         int origId = rs.getInt(1);
1398         String origCoffee = rs.getString(2);
1399         int origSales = rs.getInt(5);
1400         rs.updateInt(1, id);
1401         rs.updateString(2, coffee);
1402         rs.updateInt(5, sales);
1403         // MetaData should match
1404         try ( // Get the original original RowSet and validate that the changes
1405                 // are only made to the current, not the original
1406                 ResultSet rs1 = rs.getOriginal()) {
1407             // MetaData should match
1408             compareMetaData(rs.getMetaData(), rs1.getMetaData());
1409             assertTrue(rs1.isBeforeFirst());
1410             assertTrue(rs1.getConcurrency() == ResultSet.CONCUR_UPDATABLE);
1411             assertTrue(rs1.getType() == ResultSet.TYPE_SCROLL_INSENSITIVE);
1412             rs1.absolute(2);
1413             // Check original rowset is not changed
1414             assertTrue(rs1.getInt(1) == origId);
1415             assertTrue(rs1.getString(2).equals(origCoffee));
1416             assertTrue(rs1.getInt(5) == origSales);
1417             assertEquals(getPrimaryKeys(rs1), COFFEES_PRIMARY_KEYS);
1418             // Check current rowset
1419             assertTrue(rs.getInt(1) == id);
1420             assertTrue(rs.getString(2).equals(coffee));
1421             assertTrue(rs.getInt(5) == sales);
1422             assertEquals(getPrimaryKeys(rs), updatedPkeys);
1423         }
1424         rs.close();
1425     }
1426 
1427     /*
1428      * Validate getOriginalRow returns a ResultSet which is a copy of the
1429      * original row that was modified
1430      */
1431     @Test(dataProvider = "rowsetUsingCoffees")
1432     public void commonCachedRowSetTest0057(CachedRowSet rs) throws Exception {
1433         String coffee = "Hazelnut";
1434         int sales = 100;
1435         int id = 200;
1436         Object[] updatedPkeys = {1, id, 3, 4, 5};
1437         // Change the coffee name and sales total for row 2 and save the
1438         // previous values
1439         rs.absolute(2);
1440         int origId = rs.getInt(1);
1441         String origCoffee = rs.getString(2);
1442         int origSales = rs.getInt(5);
1443         rs.updateInt(1, id);
1444         rs.updateString(2, coffee);
1445         rs.updateInt(5, sales);
1446         // MetaData should match
1447         try ( // Get the original original row and validate that the changes
1448                 // are only made to the current, not the original
1449                 ResultSet rs1 = rs.getOriginalRow()) {
1450             // MetaData should match
1451             compareMetaData(rs.getMetaData(), rs1.getMetaData());
1452             assertTrue(rs1.isBeforeFirst());
1453             assertTrue(rs1.getConcurrency() == ResultSet.CONCUR_UPDATABLE);
1454             assertTrue(rs1.getType() == ResultSet.TYPE_SCROLL_INSENSITIVE);
1455             rs1.next();
1456             assertTrue(rs1.isFirst() && rs1.isLast());
1457             assertTrue(rs1.getRow() == 1);
1458             // Check original row is not changed
1459             assertTrue(rs1.getInt(1) == origId);
1460             assertTrue(rs1.getString(2).equals(origCoffee));
1461             assertTrue(rs1.getInt(5) == origSales);
1462             // Check current row
1463             assertTrue(rs.getInt(1) == id);
1464             assertTrue(rs.getString(2).equals(coffee));
1465             assertTrue(rs.getInt(5) == sales);
1466             assertEquals(getPrimaryKeys(rs), updatedPkeys);
1467         }
1468         rs.close();
1469     }
1470 
1471     /*
1472      * Validate that restoreOrginal will restore the RowSet to its
1473      * state prior to the insert of a row
1474      */
1475     @Test(dataProvider = "rowsetUsingCoffeeHouses")
1476     public void commonCachedRowSetTest0058(CachedRowSet rs) throws Exception {
1477         int rowToInsert = 1961;
1478         assertTrue(rs.size() == COFFEE_HOUSES_ROWS);
1479         try ( // Add new row
1480                 CachedRowSet crs1 = rsf.createCachedRowSet()) {
1481             rs.beforeFirst();
1482             crs1.populate(rs);
1483             TestRowSetListener rsl = new TestRowSetListener();
1484             crs1.addRowSetListener(rsl);
1485             crs1.moveToInsertRow();
1486             crs1.updateInt(1, rowToInsert);
1487             crs1.updateString(2, "GOTHAM");
1488             crs1.updateInt(3, 3450);
1489             crs1.updateInt(4, 2005);
1490             crs1.updateInt(5, 5455);
1491             crs1.insertRow();
1492             assertTrue(rsl.isNotified(TestRowSetListener.ROW_CHANGED));
1493             crs1.moveToCurrentRow();
1494             assertTrue(findRowByPrimaryKey(crs1, rowToInsert, 1));
1495             // Restore back to our original state and the
1496             // previously inserted row should not be there
1497             rsl.resetFlag();
1498             crs1.restoreOriginal();
1499             assertTrue(rsl.isNotified(TestRowSetListener.ROWSET_CHANGED));
1500             assertTrue(crs1.isBeforeFirst());
1501             crs1.last();
1502             assertFalse(crs1.rowInserted());
1503             assertFalse(findRowByPrimaryKey(crs1, rowToInsert, 1));
1504         }
1505         rs.close();
1506     }
1507 
1508     /*
1509      * Validate that restoreOrginal will restore the RowSet to its
1510      * state prior to deleting a row
1511      */
1512     @Test(dataProvider = "rowsetUsingCoffees", enabled = true)
1513     public void commonCachedRowSetTest0059(CachedRowSet rs) throws Exception {
1514         int rowToDelete = 2;
1515         try (CachedRowSet crs1 = rsf.createCachedRowSet()) {
1516             rs.beforeFirst();
1517             crs1.populate(rs);
1518             TestRowSetListener rsl = new TestRowSetListener();
1519             crs1.addRowSetListener(rsl);
1520             // Delete a row, the PK is also the absolute position as a List
1521             // backs the RowSet
1522             crs1.absolute(rowToDelete);
1523             crs1.deleteRow();
1524             assertTrue(crs1.rowDeleted());
1525             assertFalse(findRowByPrimaryKey(crs1, rowToDelete, 1));
1526             // Restore back to our original state and the
1527             // previously deleted row should be there
1528             rsl.resetFlag();
1529             crs1.restoreOriginal();
1530             assertTrue(rsl.isNotified(TestRowSetListener.ROWSET_CHANGED));
1531             assertTrue(crs1.isBeforeFirst());
1532             crs1.absolute(rowToDelete);
1533             assertFalse(crs1.rowDeleted());
1534             assertTrue(findRowByPrimaryKey(crs1, rowToDelete, 1));
1535         }
1536         rs.close();
1537     }
1538 
1539     /*
1540      * Validate that restoreOrginal will restore the RowSet to its
1541      * state prior to updating a row
1542      */
1543     @Test(dataProvider = "rowsetUsingCoffees", enabled = true)
1544     public void commonCachedRowSetTest0060(CachedRowSet rs) throws Exception {
1545         int rowToUpdate = 2;
1546         String coffee = "Hazelnut";
1547         try (CachedRowSet crs1 = rsf.createCachedRowSet()) {
1548             rs.beforeFirst();
1549             crs1.populate(rs);
1550             TestRowSetListener rsl = new TestRowSetListener();
1551             crs1.addRowSetListener(rsl);
1552             // Delete a row, the PK is also the absolute position as a List
1553             // backs the RowSet
1554             crs1.absolute(rowToUpdate);
1555             String origCoffee = crs1.getString(2);
1556             crs1.updateString(2, coffee);
1557             assertTrue(crs1.columnUpdated(2));
1558             crs1.updateRow();
1559             assertTrue(crs1.rowUpdated());
1560             assertFalse(origCoffee.equals(crs1.getString(2)));
1561             // Restore back to our original state and the
1562             // previous value for the column within the row should be there
1563             rsl.resetFlag();
1564             crs1.restoreOriginal();
1565             assertTrue(rsl.isNotified(TestRowSetListener.ROWSET_CHANGED));
1566             assertTrue(crs1.isBeforeFirst());
1567             // absolute() is failing for some reason so need to look at this later
1568             crs1.next();
1569             crs1.next();
1570             assertFalse(crs1.columnUpdated(2));
1571             assertFalse(crs1.rowUpdated());
1572             assertTrue(origCoffee.equals(crs1.getString(2)));
1573         }
1574         rs.close();
1575     }
1576 
1577     /*
1578      * Initialize a RowSet via the populate method. Validate it matches
1579      * the original ResultSet
1580      */
1581     @Test(dataProvider = "rowsetUsingCoffeeHouses")
1582     public void commonCachedRowSetTest0061(CachedRowSet rs) throws Exception {
1583         try (CachedRowSet crs1 = rsf.createCachedRowSet()) {
1584             rs.beforeFirst();
1585             crs1.populate(rs);
1586             compareRowSets(rs, crs1);
1587         }
1588         rs.close();
1589     }
1590 
1591     /*
1592      * Initialize a RowSet via the populate method specifying a starting row.
1593      * Validate it matches the original ResultSet starting for the specofied
1594      * offset
1595      */
1596     @Test(dataProvider = "rowsetUsingCoffeeHouses")
1597     public void commonCachedRowSetTest0062(CachedRowSet rs) throws Exception {
1598         Object[] expectedRows = {
1599             32001, 10042, 10024, 10039, 10041, 33005, 33010, 10035, 10037,
1600             10034, 32004
1601         };
1602         int startingRow = 4;
1603         try (CachedRowSet crs1 = rsf.createCachedRowSet()) {
1604             rs.beforeFirst();
1605             crs1.populate(rs, startingRow);
1606             assertEquals(crs1.size(), COFFEE_HOUSES_ROWS - startingRow + 1);
1607             assertEquals(getPrimaryKeys(crs1), expectedRows);
1608         }
1609         rs.close();
1610     }
1611 
1612 }