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