1 /*
   2  * Copyright (c) 2003, 2017, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.rowset;
  27 
  28 import java.sql.*;
  29 import javax.sql.*;
  30 import java.io.*;
  31 import java.math.*;
  32 import java.util.*;
  33 import java.text.*;
  34 import java.security.AccessController;
  35 import java.security.PrivilegedActionException;
  36 import java.security.PrivilegedExceptionAction;
  37 
  38 import javax.sql.rowset.*;
  39 import javax.sql.rowset.spi.*;
  40 import javax.sql.rowset.serial.*;
  41 import com.sun.rowset.internal.*;
  42 import com.sun.rowset.providers.*;
  43 import sun.reflect.misc.ReflectUtil;
  44 
  45 /**
  46  * The standard implementation of the <code>CachedRowSet</code> interface.
  47  *
  48  * See interface definition for full behavior and implementation requirements.
  49  * This reference implementation has made provision for a one-to-one write back
  50  * facility and it is curremtly be possible to change the peristence provider
  51  * during the life-time of any CachedRowSetImpl.
  52  *
  53  * @author Jonathan Bruce, Amit Handa
  54  */
  55 
  56 public class CachedRowSetImpl extends BaseRowSet implements RowSet, RowSetInternal, Serializable, Cloneable, CachedRowSet {
  57 
  58     /**
  59      * The <code>SyncProvider</code> used by the CachedRowSet
  60      */
  61     private SyncProvider provider;
  62 
  63     /**
  64      * The <code>RowSetReaderImpl</code> object that is the reader
  65      * for this rowset.  The method <code>execute</code> uses this
  66      * reader as part of its implementation.
  67      * @serial
  68      */
  69     private RowSetReader rowSetReader;
  70 
  71     /**
  72      * The <code>RowSetWriterImpl</code> object that is the writer
  73      * for this rowset.  The method <code>acceptChanges</code> uses
  74      * this writer as part of its implementation.
  75      * @serial
  76      */
  77     private RowSetWriter rowSetWriter;
  78 
  79     /**
  80      * The <code>Connection</code> object that connects with this
  81      * <code>CachedRowSetImpl</code> object's current underlying data source.
  82      */
  83     private transient Connection conn;
  84 
  85     /**
  86      * The <code>ResultSetMetaData</code> object that contains information
  87      * about the columns in the <code>ResultSet</code> object that is the
  88      * current source of data for this <code>CachedRowSetImpl</code> object.
  89      */
  90     private transient ResultSetMetaData RSMD;
  91 
  92     /**
  93      * The <code>RowSetMetaData</code> object that contains information about
  94      * the columns in this <code>CachedRowSetImpl</code> object.
  95      * @serial
  96      */
  97     private RowSetMetaDataImpl RowSetMD;
  98 
  99     // Properties of this RowSet
 100 
 101     /**
 102      * An array containing the columns in this <code>CachedRowSetImpl</code>
 103      * object that form a unique identifier for a row. This array
 104      * is used by the writer.
 105      * @serial
 106      */
 107     private int keyCols[];
 108 
 109     /**
 110      * The name of the table in the underlying database to which updates
 111      * should be written.  This name is needed because most drivers
 112      * do not return this information in a <code>ResultSetMetaData</code>
 113      * object.
 114      * @serial
 115      */
 116     private String tableName;
 117 
 118     /**
 119      * A <code>Vector</code> object containing the <code>Row</code>
 120      * objects that comprise  this <code>CachedRowSetImpl</code> object.
 121      * @serial
 122      */
 123     private Vector<Object> rvh;
 124 
 125     /**
 126      * The current position of the cursor in this <code>CachedRowSetImpl</code>
 127      * object.
 128      * @serial
 129      */
 130     private int cursorPos;
 131 
 132     /**
 133      * The current position of the cursor in this <code>CachedRowSetImpl</code>
 134      * object not counting rows that have been deleted, if any.
 135      * <P>
 136      * For example, suppose that the cursor is on the last row of a rowset
 137      * that started with five rows and subsequently had the second and third
 138      * rows deleted. The <code>absolutePos</code> would be <code>3</code>,
 139      * whereas the <code>cursorPos</code> would be <code>5</code>.
 140      * @serial
 141      */
 142     private int absolutePos;
 143 
 144     /**
 145      * The number of deleted rows currently in this <code>CachedRowSetImpl</code>
 146      * object.
 147      * @serial
 148      */
 149     private int numDeleted;
 150 
 151     /**
 152      * The total number of rows currently in this <code>CachedRowSetImpl</code>
 153      * object.
 154      * @serial
 155      */
 156     private int numRows;
 157 
 158     /**
 159      * A special row used for constructing a new row. A new
 160      * row is constructed by using <code>ResultSet.updateXXX</code>
 161      * methods to insert column values into the insert row.
 162      * @serial
 163      */
 164     private InsertRow insertRow;
 165 
 166     /**
 167      * A <code>boolean</code> indicating whether the cursor is
 168      * currently on the insert row.
 169      * @serial
 170      */
 171     private boolean onInsertRow;
 172 
 173     /**
 174      * The field that temporarily holds the last position of the
 175      * cursor before it moved to the insert row, thus preserving
 176      * the number of the current row to which the cursor may return.
 177      * @serial
 178      */
 179     private int currentRow;
 180 
 181     /**
 182      * A <code>boolean</code> indicating whether the last value
 183      * returned was an SQL <code>NULL</code>.
 184      * @serial
 185      */
 186     private boolean lastValueNull;
 187 
 188     /**
 189      * A <code>SQLWarning</code> which logs on the warnings
 190      */
 191     private SQLWarning sqlwarn;
 192 
 193     /**
 194      * Used to track match column for JoinRowSet consumption
 195      */
 196     private String strMatchColumn ="";
 197 
 198     /**
 199      * Used to track match column for JoinRowSet consumption
 200      */
 201     private int iMatchColumn = -1;
 202 
 203     /**
 204      * A <code>RowSetWarning</code> which logs on the warnings
 205      */
 206     private RowSetWarning rowsetWarning;
 207 
 208     /**
 209      * The default SyncProvider for the RI CachedRowSetImpl
 210      */
 211     private String DEFAULT_SYNC_PROVIDER = "com.sun.rowset.providers.RIOptimisticProvider";
 212 
 213     /**
 214      * The boolean variable indicating locatorsUpdateValue
 215      */
 216     private boolean dbmslocatorsUpdateCopy;
 217 
 218     /**
 219      * The <code>ResultSet</code> object that is used to maintain the data when
 220      * a ResultSet and start position are passed as parameters to the populate function
 221      */
 222     private transient ResultSet resultSet;
 223 
 224     /**
 225      * The integer value indicating the end position in the ResultSetwhere the picking
 226      * up of rows for populating a CachedRowSet object was left off.
 227      */
 228     private int endPos;
 229 
 230     /**
 231      * The integer value indicating the end position in the ResultSetwhere the picking
 232      * up of rows for populating a CachedRowSet object was left off.
 233      */
 234     private int prevEndPos;
 235 
 236     /**
 237      * The integer value indicating the position in the ResultSet, to populate the
 238      * CachedRowSet object.
 239      */
 240     private int startPos;
 241 
 242     /**
 243      * The integer value indicating the position from where the page prior to this
 244      * was populated.
 245      */
 246     private int startPrev;
 247 
 248     /**
 249      * The integer value indicating size of the page.
 250      */
 251     private int pageSize;
 252 
 253     /**
 254      * The integer value indicating number of rows that have been processed so far.
 255      * Used for checking whether maxRows has been reached or not.
 256      */
 257     private int maxRowsreached;
 258     /**
 259      * The boolean value when true signifies that pages are still to follow and a
 260      * false value indicates that this is the last page.
 261      */
 262     private boolean pagenotend = true;
 263 
 264     /**
 265      * The boolean value indicating whether this is the first page or not.
 266      */
 267     private boolean onFirstPage;
 268 
 269     /**
 270      * The boolean value indicating whether this is the last page or not.
 271      */
 272     private boolean onLastPage;
 273 
 274     /**
 275      * The integer value indicating how many times the populate function has been called.
 276      */
 277     private int populatecallcount;
 278 
 279     /**
 280      * The integer value indicating the total number of rows to be processed in the
 281      * ResultSet object passed to the populate function.
 282      */
 283     private int totalRows;
 284 
 285     /**
 286      * The boolean value indicating how the CahedRowSet object has been populated for
 287      * paging purpose. True indicates that connection parameter is passed.
 288      */
 289     private boolean callWithCon;
 290 
 291     /**
 292      * CachedRowSet reader object to read the data from the ResultSet when a connection
 293      * parameter is passed to populate the CachedRowSet object for paging.
 294      */
 295     private CachedRowSetReader crsReader;
 296 
 297     /**
 298      * The Vector holding the Match Columns
 299      */
 300     private Vector<Integer> iMatchColumns;
 301 
 302     /**
 303      * The Vector that will hold the Match Column names.
 304      */
 305     private Vector<String> strMatchColumns;
 306 
 307     /**
 308      * Trigger that indicates whether the active SyncProvider is exposes the
 309      * additional TransactionalWriter method
 310      */
 311     private boolean tXWriter = false;
 312 
 313     /**
 314      * The field object for a transactional RowSet writer
 315      */
 316     private TransactionalWriter tWriter = null;
 317 
 318     protected transient JdbcRowSetResourceBundle resBundle;
 319 
 320     private boolean updateOnInsert;
 321 
 322 
 323 
 324     /**
 325      * Constructs a new default <code>CachedRowSetImpl</code> object with
 326      * the capacity to hold 100 rows. This new object has no metadata
 327      * and has the following default values:
 328      * <pre>
 329      *     onInsertRow = false
 330      *     insertRow = null
 331      *     cursorPos = 0
 332      *     numRows = 0
 333      *     showDeleted = false
 334      *     queryTimeout = 0
 335      *     maxRows = 0
 336      *     maxFieldSize = 0
 337      *     rowSetType = ResultSet.TYPE_SCROLL_INSENSITIVE
 338      *     concurrency = ResultSet.CONCUR_UPDATABLE
 339      *     readOnly = false
 340      *     isolation = Connection.TRANSACTION_READ_COMMITTED
 341      *     escapeProcessing = true
 342      *     onInsertRow = false
 343      *     insertRow = null
 344      *     cursorPos = 0
 345      *     absolutePos = 0
 346      *     numRows = 0
 347      * </pre>
 348      * A <code>CachedRowSetImpl</code> object is configured to use the default
 349      * <code>RIOptimisticProvider</code> implementation to provide connectivity
 350      * and synchronization capabilities to the set data source.
 351      * <P>
 352      * @throws SQLException if an error occurs
 353      */
 354     public CachedRowSetImpl() throws SQLException {
 355 
 356         try {
 357            resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
 358         } catch(IOException ioe) {
 359             throw new RuntimeException(ioe);
 360         }
 361 
 362         // set the Reader, this maybe overridden latter
 363         try {
 364             provider = AccessController.doPrivileged(new PrivilegedExceptionAction<>() {
 365                 @Override
 366                 public SyncProvider run() throws SyncFactoryException {
 367                     return SyncFactory.getInstance(DEFAULT_SYNC_PROVIDER);
 368                 }
 369             }, null, new RuntimePermission("accessClassInPackage.com.sun.rowset.providers"));
 370         } catch (PrivilegedActionException pae) {
 371             throw (SyncFactoryException) pae.getException();
 372         }
 373 
 374         if (!(provider instanceof RIOptimisticProvider)) {
 375             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidp").toString());
 376         }
 377 
 378         rowSetReader = (CachedRowSetReader)provider.getRowSetReader();
 379         rowSetWriter = (CachedRowSetWriter)provider.getRowSetWriter();
 380 
 381         // allocate the parameters collection
 382         initParams();
 383 
 384         initContainer();
 385 
 386         // set up some default values
 387         initProperties();
 388 
 389         // insert row setup
 390         onInsertRow = false;
 391         insertRow = null;
 392 
 393         // set the warninings
 394         sqlwarn = new SQLWarning();
 395         rowsetWarning = new RowSetWarning();
 396 
 397     }
 398 
 399     /**
 400      * Provides a <code>CachedRowSetImpl</code> instance with the same default properties as
 401      * as the zero parameter constructor.
 402      * <pre>
 403      *     onInsertRow = false
 404      *     insertRow = null
 405      *     cursorPos = 0
 406      *     numRows = 0
 407      *     showDeleted = false
 408      *     queryTimeout = 0
 409      *     maxRows = 0
 410      *     maxFieldSize = 0
 411      *     rowSetType = ResultSet.TYPE_SCROLL_INSENSITIVE
 412      *     concurrency = ResultSet.CONCUR_UPDATABLE
 413      *     readOnly = false
 414      *     isolation = Connection.TRANSACTION_READ_COMMITTED
 415      *     escapeProcessing = true
 416      *     onInsertRow = false
 417      *     insertRow = null
 418      *     cursorPos = 0
 419      *     absolutePos = 0
 420      *     numRows = 0
 421      * </pre>
 422      *
 423      * However, applications will have the means to specify at runtime the
 424      * desired <code>SyncProvider</code> object.
 425      * <p>
 426      * For example, creating a <code>CachedRowSetImpl</code> object as follows ensures
 427      * that a it is established with the <code>com.foo.provider.Impl</code> synchronization
 428      * implementation providing the synchronization mechanism for this disconnected
 429      * <code>RowSet</code> object.
 430      * <pre>
 431      *     Hashtable env = new Hashtable();
 432      *     env.put(javax.sql.rowset.spi.SyncFactory.ROWSET_PROVIDER_NAME,
 433      *         "com.foo.provider.Impl");
 434      *     CachedRowSetImpl crs = new CachedRowSet(env);
 435      * </pre>
 436      * <p>
 437      * Calling this constructor with a <code>null</code> parameter will
 438      * cause the <code>SyncFactory</code> to provide the reference
 439      * optimistic provider <code>com.sun.rowset.providers.RIOptimisticProvider</code>.
 440      * <p>
 441      * In addition, the following properties can be associated with the
 442      * provider to assist in determining the choice of the synchronizaton
 443      * provider such as:
 444      * <ul>
 445      * <li><code>ROWSET_SYNC_PROVIDER</code> - the property specifying the
 446      * <code>SyncProvider</code> class name to be instantiated by the
 447      * <code>SyncFacttory</code>
 448      * <li><code>ROWSET_SYNC_VENDOR</code> - the property specifying the software
 449      * vendor associated with a <code>SyncProvider</code> implementation.
 450      * <li><code>ROWSET_SYNC_PROVIDER_VER</code> - the property specifying the
 451      * version of the <code>SyncProvider</code> implementation provided by the
 452      * software vendor.
 453      * </ul>
 454      * More specific detailes are available in the <code>SyncFactory</code>
 455      * and <code>SyncProvider</code> specificiations later in this document.
 456      * <p>
 457      * @param env a <code>Hashtable</code> object with a list of desired
 458      *        synchronization providers
 459      * @throws SQLException if the requested provider cannot be found by the
 460      * synchronization factory
 461      * @see SyncProvider
 462      */
 463     public CachedRowSetImpl(@SuppressWarnings("rawtypes") Hashtable env) throws SQLException {
 464 
 465 
 466         try {
 467            resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
 468         } catch(IOException ioe) {
 469             throw new RuntimeException(ioe);
 470         }
 471 
 472         if (env == null) {
 473             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.nullhash").toString());
 474         }
 475 
 476         String providerName = (String)env.get(
 477         javax.sql.rowset.spi.SyncFactory.ROWSET_SYNC_PROVIDER);
 478 
 479         // set the Reader, this maybe overridden latter
 480         provider =
 481         SyncFactory.getInstance(providerName);
 482 
 483         rowSetReader = provider.getRowSetReader();
 484         rowSetWriter = provider.getRowSetWriter();
 485 
 486         initParams(); // allocate the parameters collection
 487         initContainer();
 488         initProperties(); // set up some default values
 489     }
 490 
 491     /**
 492      * Sets the <code>rvh</code> field to a new <code>Vector</code>
 493      * object with a capacity of 100 and sets the
 494      * <code>cursorPos</code> and <code>numRows</code> fields to zero.
 495      */
 496     private void initContainer() {
 497 
 498         rvh = new Vector<Object>(100);
 499         cursorPos = 0;
 500         absolutePos = 0;
 501         numRows = 0;
 502         numDeleted = 0;
 503     }
 504 
 505     /**
 506      * Sets the properties for this <code>CachedRowSetImpl</code> object to
 507      * their default values. This method is called internally by the
 508      * default constructor.
 509      */
 510 
 511     private void initProperties() throws SQLException {
 512 
 513         if(resBundle == null) {
 514             try {
 515                resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
 516             } catch(IOException ioe) {
 517                 throw new RuntimeException(ioe);
 518             }
 519         }
 520         setShowDeleted(false);
 521         setQueryTimeout(0);
 522         setMaxRows(0);
 523         setMaxFieldSize(0);
 524         setType(ResultSet.TYPE_SCROLL_INSENSITIVE);
 525         setConcurrency(ResultSet.CONCUR_UPDATABLE);
 526         if((rvh.size() > 0) && (isReadOnly() == false))
 527             setReadOnly(false);
 528         else
 529             setReadOnly(true);
 530         setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
 531         setEscapeProcessing(true);
 532         //setTypeMap(null);
 533         checkTransactionalWriter();
 534 
 535         //Instantiating the vector for MatchColumns
 536 
 537         iMatchColumns = new Vector<Integer>(10);
 538         for(int i = 0; i < 10 ; i++) {
 539            iMatchColumns.add(i, -1);
 540         }
 541 
 542         strMatchColumns = new Vector<String>(10);
 543         for(int j = 0; j < 10; j++) {
 544            strMatchColumns.add(j,null);
 545         }
 546     }
 547 
 548     /**
 549      * Determine whether the SyncProvider's writer implements the
 550      * <code>TransactionalWriter<code> interface
 551      */
 552     private void checkTransactionalWriter() {
 553         if (rowSetWriter != null) {
 554             Class<?> c = rowSetWriter.getClass();
 555             if (c != null) {
 556                 Class<?>[] theInterfaces = c.getInterfaces();
 557                 for (int i = 0; i < theInterfaces.length; i++) {
 558                     if ((theInterfaces[i].getName()).indexOf("TransactionalWriter") > 0) {
 559                         tXWriter = true;
 560                         establishTransactionalWriter();
 561                     }
 562                 }
 563             }
 564         }
 565     }
 566 
 567     /**
 568      * Sets an private field to all transaction bounddaries to be set
 569      */
 570     private void establishTransactionalWriter() {
 571         tWriter = (TransactionalWriter)provider.getRowSetWriter();
 572     }
 573 
 574     //-----------------------------------------------------------------------
 575     // Properties
 576     //-----------------------------------------------------------------------
 577 
 578     /**
 579      * Sets this <code>CachedRowSetImpl</code> object's command property
 580      * to the given <code>String</code> object and clears the parameters,
 581      * if any, that were set for the previous command.
 582      * <P>
 583      * The command property may not be needed
 584      * if the rowset is produced by a data source, such as a spreadsheet,
 585      * that does not support commands. Thus, this property is optional
 586      * and may be <code>null</code>.
 587      *
 588      * @param cmd a <code>String</code> object containing an SQL query
 589      *            that will be set as the command; may be <code>null</code>
 590      * @throws SQLException if an error occurs
 591      */
 592     public void setCommand(String cmd) throws SQLException {
 593 
 594         super.setCommand(cmd);
 595 
 596         if(!buildTableName(cmd).equals("")) {
 597             this.setTableName(buildTableName(cmd));
 598         }
 599     }
 600 
 601 
 602     //---------------------------------------------------------------------
 603     // Reading and writing data
 604     //---------------------------------------------------------------------
 605 
 606     /**
 607      * Populates this <code>CachedRowSetImpl</code> object with data from
 608      * the given <code>ResultSet</code> object.  This
 609      * method is an alternative to the method <code>execute</code>
 610      * for filling the rowset with data.  The method <code>populate</code>
 611      * does not require that the properties needed by the method
 612      * <code>execute</code>, such as the <code>command</code> property,
 613      * be set. This is true because the method <code>populate</code>
 614      * is given the <code>ResultSet</code> object from
 615      * which to get data and thus does not need to use the properties
 616      * required for setting up a connection and executing this
 617      * <code>CachedRowSetImpl</code> object's command.
 618      * <P>
 619      * After populating this rowset with data, the method
 620      * <code>populate</code> sets the rowset's metadata and
 621      * then sends a <code>RowSetChangedEvent</code> object
 622      * to all registered listeners prior to returning.
 623      *
 624      * @param data the <code>ResultSet</code> object containing the data
 625      *             to be read into this <code>CachedRowSetImpl</code> object
 626      * @throws SQLException if an error occurs; or the max row setting is
 627      *          violated while populating the RowSet
 628      * @see #execute
 629      */
 630 
 631      public void populate(ResultSet data) throws SQLException {
 632         int rowsFetched;
 633         Row currentRow;
 634         int numCols;
 635         int i;
 636         Map<String, Class<?>> map = getTypeMap();
 637         Object obj;
 638         int mRows;
 639 
 640         if (data == null) {
 641             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.populate").toString());
 642         }
 643         this.resultSet = data;
 644 
 645         // get the meta data for this ResultSet
 646         RSMD = data.getMetaData();
 647 
 648         // set up the metadata
 649         RowSetMD = new RowSetMetaDataImpl();
 650         initMetaData(RowSetMD, RSMD);
 651 
 652         // release the meta-data so that aren't tempted to use it.
 653         RSMD = null;
 654         numCols = RowSetMD.getColumnCount();
 655         mRows = this.getMaxRows();
 656         rowsFetched = 0;
 657         currentRow = null;
 658 
 659         while ( data.next()) {
 660 
 661             currentRow = new Row(numCols);
 662 
 663             if ( rowsFetched > mRows && mRows > 0) {
 664                 rowsetWarning.setNextWarning(new RowSetWarning("Populating rows "
 665                 + "setting has exceeded max row setting"));
 666             }
 667             for ( i = 1; i <= numCols; i++) {
 668                 /*
 669                  * check if the user has set a map. If no map
 670                  * is set then use plain getObject. This lets
 671                  * us work with drivers that do not support
 672                  * getObject with a map in fairly sensible way
 673                  */
 674                 if (map == null || map.isEmpty()) {
 675                     obj = data.getObject(i);
 676                 } else {
 677                     obj = data.getObject(i, map);
 678                 }
 679                 /*
 680                  * the following block checks for the various
 681                  * types that we have to serialize in order to
 682                  * store - right now only structs have been tested
 683                  */
 684                 if (obj instanceof Struct) {
 685                     obj = new SerialStruct((Struct)obj, map);
 686                 } else if (obj instanceof SQLData) {
 687                     obj = new SerialStruct((SQLData)obj, map);
 688                 } else if (obj instanceof Blob) {
 689                     obj = new SerialBlob((Blob)obj);
 690                 } else if (obj instanceof Clob) {
 691                     obj = new SerialClob((Clob)obj);
 692                 } else if (obj instanceof java.sql.Array) {
 693                     if(map != null)
 694                         obj = new SerialArray((java.sql.Array)obj, map);
 695                     else
 696                         obj = new SerialArray((java.sql.Array)obj);
 697                 }
 698 
 699                 currentRow.initColumnObject(i, obj);
 700             }
 701             rowsFetched++;
 702             rvh.add(currentRow);
 703         }
 704 
 705         numRows = rowsFetched ;
 706         // Also rowsFetched should be equal to rvh.size()
 707 
 708         // notify any listeners that the rowset has changed
 709         notifyRowSetChanged();
 710 
 711 
 712     }
 713 
 714     /**
 715      * Initializes the given <code>RowSetMetaData</code> object with the values
 716      * in the given <code>ResultSetMetaData</code> object.
 717      *
 718      * @param md the <code>RowSetMetaData</code> object for this
 719      *           <code>CachedRowSetImpl</code> object, which will be set with
 720      *           values from rsmd
 721      * @param rsmd the <code>ResultSetMetaData</code> object from which new
 722      *             values for md will be read
 723      * @throws SQLException if an error occurs
 724      */
 725     private void initMetaData(RowSetMetaDataImpl md, ResultSetMetaData rsmd) throws SQLException {
 726         int numCols = rsmd.getColumnCount();
 727 
 728         md.setColumnCount(numCols);
 729         for (int col=1; col <= numCols; col++) {
 730             md.setAutoIncrement(col, rsmd.isAutoIncrement(col));
 731             if(rsmd.isAutoIncrement(col))
 732                 updateOnInsert = true;
 733             md.setCaseSensitive(col, rsmd.isCaseSensitive(col));
 734             md.setCurrency(col, rsmd.isCurrency(col));
 735             md.setNullable(col, rsmd.isNullable(col));
 736             md.setSigned(col, rsmd.isSigned(col));
 737             md.setSearchable(col, rsmd.isSearchable(col));
 738              /*
 739              * The PostgreSQL drivers sometimes return negative columnDisplaySize,
 740              * which causes an exception to be thrown.  Check for it.
 741              */
 742             int size = rsmd.getColumnDisplaySize(col);
 743             if (size < 0) {
 744                 size = 0;
 745             }
 746             md.setColumnDisplaySize(col, size);
 747             md.setColumnLabel(col, rsmd.getColumnLabel(col));
 748             md.setColumnName(col, rsmd.getColumnName(col));
 749             md.setSchemaName(col, rsmd.getSchemaName(col));
 750             /*
 751              * Drivers return some strange values for precision, for non-numeric data, including reports of
 752              * non-integer values; maybe we should check type, & set to 0 for non-numeric types.
 753              */
 754             int precision = rsmd.getPrecision(col);
 755             if (precision < 0) {
 756                 precision = 0;
 757             }
 758             md.setPrecision(col, precision);
 759 
 760             /*
 761              * It seems, from a bug report, that a driver can sometimes return a negative
 762              * value for scale.  javax.sql.rowset.RowSetMetaDataImpl will throw an exception
 763              * if we attempt to set a negative value.  As such, we'll check for this case.
 764              */
 765             int scale = rsmd.getScale(col);
 766             if (scale < 0) {
 767                 scale = 0;
 768             }
 769             md.setScale(col, scale);
 770             md.setTableName(col, rsmd.getTableName(col));
 771             md.setCatalogName(col, rsmd.getCatalogName(col));
 772             md.setColumnType(col, rsmd.getColumnType(col));
 773             md.setColumnTypeName(col, rsmd.getColumnTypeName(col));
 774         }
 775 
 776         if( conn != null){
 777            // JDBC 4.0 mandates as does the Java EE spec that all DataBaseMetaData methods
 778            // must be implemented, therefore, the previous fix for 5055528 is being backed out
 779             dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy();
 780         }
 781     }
 782 
 783     /**
 784      * Populates this <code>CachedRowSetImpl</code> object with data,
 785      * using the given connection to produce the result set from
 786      * which data will be read.  A second form of this method,
 787      * which takes no arguments, uses the values from this rowset's
 788      * user, password, and either url or data source properties to
 789      * create a new database connection. The form of <code>execute</code>
 790      * that is given a connection ignores these properties.
 791      *
 792      * @param conn A standard JDBC <code>Connection</code> object that this
 793      * <code>CachedRowSet</code> object can pass to a synchronization provider
 794      * to establish a connection to the data source
 795      * @throws SQLException if an invalid <code>Connection</code> is supplied
 796      *           or an error occurs in establishing the connection to the
 797      *           data source
 798      * @see #populate
 799      * @see java.sql.Connection
 800      */
 801     public void execute(Connection conn) throws SQLException {
 802         // store the connection so the reader can find it.
 803         setConnection(conn);
 804 
 805         if(getPageSize() != 0){
 806             crsReader = (CachedRowSetReader)provider.getRowSetReader();
 807             crsReader.setStartPosition(1);
 808             callWithCon = true;
 809             crsReader.readData((RowSetInternal)this);
 810         }
 811 
 812         // Now call the current reader's readData method
 813         else {
 814            rowSetReader.readData((RowSetInternal)this);
 815         }
 816         RowSetMD = (RowSetMetaDataImpl)this.getMetaData();
 817 
 818         if(conn != null){
 819             // JDBC 4.0 mandates as does the Java EE spec that all DataBaseMetaData methods
 820             // must be implemented, therefore, the previous fix for 5055528 is being backed out
 821             dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy();
 822         }
 823 
 824     }
 825 
 826     /**
 827      * Sets this <code>CachedRowSetImpl</code> object's connection property
 828      * to the given <code>Connection</code> object.  This method is called
 829      * internally by the version of the method <code>execute</code> that takes a
 830      * <code>Connection</code> object as an argument. The reader for this
 831      * <code>CachedRowSetImpl</code> object can retrieve the connection stored
 832      * in the rowset's connection property by calling its
 833      * <code>getConnection</code> method.
 834      *
 835      * @param connection the <code>Connection</code> object that was passed in
 836      *                   to the method <code>execute</code> and is to be stored
 837      *                   in this <code>CachedRowSetImpl</code> object's connection
 838      *                   property
 839      */
 840     private void setConnection (Connection connection) {
 841         conn = connection;
 842     }
 843 
 844 
 845     /**
 846      * Propagates all row update, insert, and delete changes to the
 847      * underlying data source backing this <code>CachedRowSetImpl</code>
 848      * object.
 849      * <P>
 850      * <b>Note</b>In the reference implementation an optimistic concurrency implementation
 851      * is provided as a sample implementation of a the <code>SyncProvider</code>
 852      * abstract class.
 853      * <P>
 854      * This method fails if any of the updates cannot be propagated back
 855      * to the data source.  When it fails, the caller can assume that
 856      * none of the updates are reflected in the data source.
 857      * When an exception is thrown, the current row
 858      * is set to the first "updated" row that resulted in an exception
 859      * unless the row that caused the exception is a "deleted" row.
 860      * In that case, when deleted rows are not shown, which is usually true,
 861      * the current row is not affected.
 862      * <P>
 863      * If no <code>SyncProvider</code> is configured, the reference implementation
 864      * leverages the <code>RIOptimisticProvider</code> available which provides the
 865      * default and reference synchronization capabilities for disconnected
 866      * <code>RowSets</code>.
 867      *
 868      * @throws SQLException if the cursor is on the insert row or the underlying
 869      *          reference synchronization provider fails to commit the updates
 870      *          to the datasource
 871      * @throws SyncProviderException if an internal error occurs within the
 872      *          <code>SyncProvider</code> instance during either during the
 873      *          process or at any time when the <code>SyncProvider</code>
 874      *          instance touches the data source.
 875      * @see #acceptChanges(java.sql.Connection)
 876      * @see javax.sql.RowSetWriter
 877      * @see javax.sql.rowset.spi.SyncProvider
 878      */
 879     public void acceptChanges() throws SyncProviderException {
 880         if (onInsertRow == true) {
 881             throw new SyncProviderException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
 882         }
 883 
 884         int saveCursorPos = cursorPos;
 885         boolean success = false;
 886         boolean conflict = false;
 887 
 888         try {
 889             if (rowSetWriter != null) {
 890                 saveCursorPos = cursorPos;
 891                 conflict = rowSetWriter.writeData((RowSetInternal)this);
 892                 cursorPos = saveCursorPos;
 893             }
 894 
 895             if (tXWriter) {
 896                 // do commit/rollback's here
 897                 if (!conflict) {
 898                     tWriter = (TransactionalWriter)rowSetWriter;
 899                     tWriter.rollback();
 900                     success = false;
 901                 } else {
 902                     tWriter = (TransactionalWriter)rowSetWriter;
 903                     if (tWriter instanceof CachedRowSetWriter) {
 904                         ((CachedRowSetWriter)tWriter).commit(this, updateOnInsert);
 905                     } else {
 906                         tWriter.commit();
 907                     }
 908 
 909                     success = true;
 910                 }
 911             }
 912 
 913             if (success == true) {
 914                 setOriginal();
 915             } else if (!(success) ) {
 916                 throw new SyncProviderException(resBundle.handleGetObject("cachedrowsetimpl.accfailed").toString());
 917             }
 918 
 919         } catch (SyncProviderException spe) {
 920                throw spe;
 921         } catch (SQLException e) {
 922             e.printStackTrace();
 923             throw new SyncProviderException(e.getMessage());
 924         } catch (SecurityException e) {
 925             throw new SyncProviderException(e.getMessage());
 926         }
 927     }
 928 
 929     /**
 930      * Propagates all row update, insert, and delete changes to the
 931      * data source backing this <code>CachedRowSetImpl</code> object
 932      * using the given <code>Connection</code> object.
 933      * <P>
 934      * The reference implementation <code>RIOptimisticProvider</code>
 935      * modifies its synchronization to a write back function given
 936      * the updated connection
 937      * The reference implementation modifies its synchronization behaviour
 938      * via the <code>SyncProvider</code> to ensure the synchronization
 939      * occurs according to the updated JDBC <code>Connection</code>
 940      * properties.
 941      *
 942      * @param con a standard JDBC <code>Connection</code> object
 943      * @throws SQLException if the cursor is on the insert row or the underlying
 944      *                   synchronization provider fails to commit the updates
 945      *                   back to the data source
 946      * @see #acceptChanges
 947      * @see javax.sql.RowSetWriter
 948      * @see javax.sql.rowset.spi.SyncFactory
 949      * @see javax.sql.rowset.spi.SyncProvider
 950      */
 951     public void acceptChanges(Connection con) throws SyncProviderException{
 952       setConnection(con);
 953       acceptChanges();
 954     }
 955 
 956     /**
 957      * Restores this <code>CachedRowSetImpl</code> object to its original state,
 958      * that is, its state before the last set of changes.
 959      * <P>
 960      * Before returning, this method moves the cursor before the first row
 961      * and sends a <code>rowSetChanged</code> event to all registered
 962      * listeners.
 963      * @throws SQLException if an error is occurs rolling back the RowSet
 964      *           state to the definied original value.
 965      * @see javax.sql.RowSetListener#rowSetChanged
 966      */
 967     public void restoreOriginal() throws SQLException {
 968         Row currentRow;
 969         for (Iterator<?> i = rvh.iterator(); i.hasNext();) {
 970             currentRow = (Row)i.next();
 971             if (currentRow.getInserted() == true) {
 972                 i.remove();
 973                 --numRows;
 974             } else {
 975                 if (currentRow.getDeleted() == true) {
 976                     currentRow.clearDeleted();
 977                 }
 978                 if (currentRow.getUpdated() == true) {
 979                     currentRow.clearUpdated();
 980                 }
 981             }
 982         }
 983         // move to before the first
 984         cursorPos = 0;
 985 
 986         // notify any listeners
 987         notifyRowSetChanged();
 988     }
 989 
 990     /**
 991      * Releases the current contents of this <code>CachedRowSetImpl</code>
 992      * object and sends a <code>rowSetChanged</code> event object to all
 993      * registered listeners.
 994      *
 995      * @throws SQLException if an error occurs flushing the contents of
 996      *           RowSet.
 997      * @see javax.sql.RowSetListener#rowSetChanged
 998      */
 999     public void release() throws SQLException {
1000         initContainer();
1001         notifyRowSetChanged();
1002     }
1003 
1004     /**
1005      * Cancels deletion of the current row and notifies listeners that
1006      * a row has changed.
1007      * <P>
1008      * Note:  This method can be ignored if deleted rows are not being shown,
1009      * which is the normal case.
1010      *
1011      * @throws SQLException if the cursor is not on a valid row
1012      */
1013     public void undoDelete() throws SQLException {
1014         if (getShowDeleted() == false) {
1015             return;
1016         }
1017         // make sure we are on a row
1018         checkCursor();
1019 
1020         // don't want this to happen...
1021         if (onInsertRow == true) {
1022             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1023         }
1024 
1025         Row currentRow = (Row)getCurrentRow();
1026         if (currentRow.getDeleted() == true) {
1027             currentRow.clearDeleted();
1028             --numDeleted;
1029             notifyRowChanged();
1030         }
1031     }
1032 
1033     /**
1034      * Immediately removes the current row from this
1035      * <code>CachedRowSetImpl</code> object if the row has been inserted, and
1036      * also notifies listeners the a row has changed.  An exception is thrown
1037      * if the row is not a row that has been inserted or the cursor is before
1038      * the first row, after the last row, or on the insert row.
1039      * <P>
1040      * This operation cannot be undone.
1041      *
1042      * @throws SQLException if an error occurs,
1043      *                         the cursor is not on a valid row,
1044      *                         or the row has not been inserted
1045      */
1046     public void undoInsert() throws SQLException {
1047         // make sure we are on a row
1048         checkCursor();
1049 
1050         // don't want this to happen...
1051         if (onInsertRow == true) {
1052             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1053         }
1054 
1055         Row currentRow = (Row)getCurrentRow();
1056         if (currentRow.getInserted() == true) {
1057             rvh.remove(cursorPos-1);
1058             --numRows;
1059             notifyRowChanged();
1060         } else {
1061             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.illegalop").toString());
1062         }
1063     }
1064 
1065     /**
1066      * Immediately reverses the last update operation if the
1067      * row has been modified. This method can be
1068      * called to reverse updates on a all columns until all updates in a row have
1069      * been rolled back to their originating state since the last synchronization
1070      * (<code>acceptChanges</code>) or population. This method may also be called
1071      * while performing updates to the insert row.
1072      * <P>
1073      * {@code undoUpdate} may be called at any time during the life-time of a
1074      * rowset, however after a synchronization has occurs this method has no
1075      * affect until further modification to the RowSet data occurs.
1076      *
1077      * @throws SQLException if cursor is before the first row, after the last
1078      *     row in rowset.
1079      * @see #undoDelete
1080      * @see #undoInsert
1081      * @see java.sql.ResultSet#cancelRowUpdates
1082      */
1083     public void undoUpdate() throws SQLException {
1084         // if on insert row, cancel the insert row
1085         // make the insert row flag,
1086         // cursorPos back to the current row
1087         moveToCurrentRow();
1088 
1089         // else if not on insert row
1090         // call undoUpdate or undoInsert
1091         undoDelete();
1092 
1093         undoInsert();
1094 
1095     }
1096 
1097     //--------------------------------------------------------------------
1098     // Views
1099     //--------------------------------------------------------------------
1100 
1101     /**
1102      * Returns a new <code>RowSet</code> object backed by the same data as
1103      * that of this <code>CachedRowSetImpl</code> object and sharing a set of cursors
1104      * with it. This allows cursors to interate over a shared set of rows, providing
1105      * multiple views of the underlying data.
1106      *
1107      * @return a <code>RowSet</code> object that is a copy of this <code>CachedRowSetImpl</code>
1108      * object and shares a set of cursors with it
1109      * @throws SQLException if an error occurs or cloning is
1110      *                         not supported
1111      * @see javax.sql.RowSetEvent
1112      * @see javax.sql.RowSetListener
1113      */
1114     public RowSet createShared() throws SQLException {
1115         RowSet clone;
1116         try {
1117             clone = (RowSet)clone();
1118         } catch (CloneNotSupportedException ex) {
1119             throw new SQLException(ex.getMessage());
1120         }
1121         return clone;
1122     }
1123 
1124     /**
1125      * Returns a new <code>RowSet</code> object containing by the same data
1126      * as this <code>CachedRowSetImpl</code> object.  This method
1127      * differs from the method <code>createCopy</code> in that it throws a
1128      * <code>CloneNotSupportedException</code> object instead of an
1129      * <code>SQLException</code> object, as the method <code>createShared</code>
1130      * does.  This <code>clone</code>
1131      * method is called internally by the method <code>createShared</code>,
1132      * which catches the <code>CloneNotSupportedException</code> object
1133      * and in turn throws a new <code>SQLException</code> object.
1134      *
1135      * @return a copy of this <code>CachedRowSetImpl</code> object
1136      * @throws CloneNotSupportedException if an error occurs when
1137      * attempting to clone this <code>CachedRowSetImpl</code> object
1138      * @see #createShared
1139      */
1140     protected Object clone() throws CloneNotSupportedException  {
1141         return (super.clone());
1142     }
1143 
1144     /**
1145      * Creates a <code>RowSet</code> object that is a deep copy of
1146      * this <code>CachedRowSetImpl</code> object's data, including
1147      * constraints.  Updates made
1148      * on a copy are not visible to the original rowset;
1149      * a copy of a rowset is completely independent from the original.
1150      * <P>
1151      * Making a copy saves the cost of creating an identical rowset
1152      * from first principles, which can be quite expensive.
1153      * For example, it can eliminate the need to query a
1154      * remote database server.
1155      * @return a new <code>CachedRowSet</code> object that is a deep copy
1156      *           of this <code>CachedRowSet</code> object and is
1157      *           completely independent from this <code>CachedRowSetImpl</code>
1158      *           object.
1159      * @throws SQLException if an error occurs in generating the copy of this
1160      *           of the <code>CachedRowSetImpl</code>
1161      * @see #createShared
1162      * @see javax.sql.RowSetEvent
1163      * @see javax.sql.RowSetListener
1164      */
1165     public CachedRowSet createCopy() throws SQLException {
1166         ObjectOutputStream out;
1167         ByteArrayOutputStream bOut = new ByteArrayOutputStream();
1168         try {
1169             out = new ObjectOutputStream(bOut);
1170             out.writeObject(this);
1171         } catch (IOException ex) {
1172             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1173         }
1174 
1175         ObjectInputStream in;
1176 
1177         try {
1178             ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
1179             in = new ObjectInputStream(bIn);
1180         } catch (StreamCorruptedException ex) {
1181             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1182         } catch (IOException ex) {
1183             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1184         }
1185 
1186         try {
1187             //return ((CachedRowSet)(in.readObject()));
1188             CachedRowSetImpl crsTemp = (CachedRowSetImpl)in.readObject();
1189             crsTemp.resBundle = this.resBundle;
1190             return ((CachedRowSet)crsTemp);
1191 
1192         } catch (ClassNotFoundException ex) {
1193             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1194         } catch (OptionalDataException ex) {
1195             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1196         } catch (IOException ex) {
1197             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1198         }
1199     }
1200 
1201     /**
1202      * Creates a <code>RowSet</code> object that is a copy of
1203      * this <code>CachedRowSetImpl</code> object's table structure
1204      * and the constraints only.
1205      * There will be no data in the object being returned.
1206      * Updates made on a copy are not visible to the original rowset.
1207      * <P>
1208      * This helps in getting the underlying XML schema which can
1209      * be used as the basis for populating a <code>WebRowSet</code>.
1210      *
1211      * @return a new <code>CachedRowSet</code> object that is a copy
1212      * of this <code>CachedRowSetImpl</code> object's schema and
1213      * retains all the constraints on the original rowset but contains
1214      * no data
1215      * @throws SQLException if an error occurs in generating the copy
1216      * of the <code>CachedRowSet</code> object
1217      * @see #createShared
1218      * @see #createCopy
1219      * @see #createCopyNoConstraints
1220      * @see javax.sql.RowSetEvent
1221      * @see javax.sql.RowSetListener
1222      */
1223     public CachedRowSet createCopySchema() throws SQLException {
1224         // Copy everything except data i.e all constraints
1225 
1226         // Store the number of rows of "this"
1227         // and make numRows equals zero.
1228         // and make data also zero.
1229         int nRows = numRows;
1230         numRows = 0;
1231 
1232         CachedRowSet crs = this.createCopy();
1233 
1234         // reset this object back to number of rows.
1235         numRows = nRows;
1236 
1237         return crs;
1238     }
1239 
1240     /**
1241      * Creates a <code>CachedRowSet</code> object that is a copy of
1242      * this <code>CachedRowSetImpl</code> object's data only.
1243      * All constraints set in this object will not be there
1244      * in the returning object.  Updates made
1245      * on a copy are not visible to the original rowset.
1246      *
1247      * @return a new <code>CachedRowSet</code> object that is a deep copy
1248      * of this <code>CachedRowSetImpl</code> object and is
1249      * completely independent from this <code>CachedRowSetImpl</code> object
1250      * @throws SQLException if an error occurs in generating the copy of the
1251      * of the <code>CachedRowSet</code>
1252      * @see #createShared
1253      * @see #createCopy
1254      * @see #createCopySchema
1255      * @see javax.sql.RowSetEvent
1256      * @see javax.sql.RowSetListener
1257      */
1258     public CachedRowSet createCopyNoConstraints() throws SQLException {
1259         // Copy the whole data ONLY without any constraints.
1260         CachedRowSetImpl crs;
1261         crs = (CachedRowSetImpl)this.createCopy();
1262 
1263         crs.initProperties();
1264         try {
1265             crs.unsetMatchColumn(crs.getMatchColumnIndexes());
1266         } catch(SQLException sqle) {
1267             //do nothing, if the setMatchColumn is not set.
1268         }
1269 
1270         try {
1271             crs.unsetMatchColumn(crs.getMatchColumnNames());
1272         } catch(SQLException sqle) {
1273             //do nothing, if the setMatchColumn is not set.
1274         }
1275 
1276         return crs;
1277     }
1278 
1279     /**
1280      * Converts this <code>CachedRowSetImpl</code> object to a collection
1281      * of tables. The sample implementation utilitizes the <code>TreeMap</code>
1282      * collection type.
1283      * This class guarantees that the map will be in ascending key order,
1284      * sorted according to the natural order for the key's class.
1285      *
1286      * @return a <code>Collection</code> object consisting of tables,
1287      *         each of which is a copy of a row in this
1288      *         <code>CachedRowSetImpl</code> object
1289      * @throws SQLException if an error occurs in generating the collection
1290      * @see #toCollection(int)
1291      * @see #toCollection(String)
1292      * @see java.util.TreeMap
1293      */
1294     public Collection<?> toCollection() throws SQLException {
1295 
1296         TreeMap<Integer, Object> tMap = new TreeMap<>();
1297 
1298         for (int i = 0; i<numRows; i++) {
1299             tMap.put(i, rvh.get(i));
1300         }
1301 
1302         return (tMap.values());
1303     }
1304 
1305     /**
1306      * Returns the specified column of this <code>CachedRowSetImpl</code> object
1307      * as a <code>Collection</code> object.  This method makes a copy of the
1308      * column's data and utilitizes the <code>Vector</code> to establish the
1309      * collection. The <code>Vector</code> class implements a growable array
1310      * objects allowing the individual components to be accessed using an
1311      * an integer index similar to that of an array.
1312      *
1313      * @return a <code>Collection</code> object that contains the value(s)
1314      *         stored in the specified column of this
1315      *         <code>CachedRowSetImpl</code>
1316      *         object
1317      * @throws SQLException if an error occurs generated the collection; or
1318      *          an invalid column is provided.
1319      * @see #toCollection()
1320      * @see #toCollection(String)
1321      * @see java.util.Vector
1322      */
1323     public Collection<?> toCollection(int column) throws SQLException {
1324 
1325         int nRows = numRows;
1326         Vector<Object> vec = new Vector<>(nRows);
1327 
1328         // create a copy
1329         CachedRowSetImpl crsTemp;
1330         crsTemp = (CachedRowSetImpl) this.createCopy();
1331 
1332         while(nRows!=0) {
1333             crsTemp.next();
1334             vec.add(crsTemp.getObject(column));
1335             nRows--;
1336         }
1337 
1338         return (Collection)vec;
1339     }
1340 
1341     /**
1342      * Returns the specified column of this <code>CachedRowSetImpl</code> object
1343      * as a <code>Collection</code> object.  This method makes a copy of the
1344      * column's data and utilitizes the <code>Vector</code> to establish the
1345      * collection. The <code>Vector</code> class implements a growable array
1346      * objects allowing the individual components to be accessed using an
1347      * an integer index similar to that of an array.
1348      *
1349      * @return a <code>Collection</code> object that contains the value(s)
1350      *         stored in the specified column of this
1351      *         <code>CachedRowSetImpl</code>
1352      *         object
1353      * @throws SQLException if an error occurs generated the collection; or
1354      *          an invalid column is provided.
1355      * @see #toCollection()
1356      * @see #toCollection(int)
1357      * @see java.util.Vector
1358      */
1359     public Collection<?> toCollection(String column) throws SQLException {
1360         return toCollection(getColIdxByName(column));
1361     }
1362 
1363     //--------------------------------------------------------------------
1364     // Advanced features
1365     //--------------------------------------------------------------------
1366 
1367 
1368     /**
1369      * Returns the <code>SyncProvider</code> implementation being used
1370      * with this <code>CachedRowSetImpl</code> implementation rowset.
1371      *
1372      * @return the SyncProvider used by the rowset. If not provider was
1373      *          set when the rowset was instantiated, the reference
1374      *          implementation (default) provider is returned.
1375      * @throws SQLException if error occurs while return the
1376      *          <code>SyncProvider</code> instance.
1377      */
1378     public SyncProvider getSyncProvider() throws SQLException {
1379         return provider;
1380     }
1381 
1382     /**
1383      * Sets the active <code>SyncProvider</code> and attempts to load
1384      * load the new provider using the <code>SyncFactory</code> SPI.
1385      *
1386      * @throws SQLException if an error occurs while resetting the
1387      *          <code>SyncProvider</code>.
1388      */
1389     public void setSyncProvider(String providerStr) throws SQLException {
1390         provider =
1391         SyncFactory.getInstance(providerStr);
1392 
1393         rowSetReader = provider.getRowSetReader();
1394         rowSetWriter = provider.getRowSetWriter();
1395     }
1396 
1397 
1398     //-----------------
1399     // methods inherited from RowSet
1400     //-----------------
1401 
1402 
1403 
1404 
1405 
1406 
1407     //---------------------------------------------------------------------
1408     // Reading and writing data
1409     //---------------------------------------------------------------------
1410 
1411     /**
1412      * Populates this <code>CachedRowSetImpl</code> object with data.
1413      * This form of the method uses the rowset's user, password, and url or
1414      * data source name properties to create a database
1415      * connection.  If properties that are needed
1416      * have not been set, this method will throw an exception.
1417      * <P>
1418      * Another form of this method uses an existing JDBC <code>Connection</code>
1419      * object instead of creating a new one; therefore, it ignores the
1420      * properties used for establishing a new connection.
1421      * <P>
1422      * The query specified by the command property is executed to create a
1423      * <code>ResultSet</code> object from which to retrieve data.
1424      * The current contents of the rowset are discarded, and the
1425      * rowset's metadata is also (re)set.  If there are outstanding updates,
1426      * they are also ignored.
1427      * <P>
1428      * The method <code>execute</code> closes any database connections that it
1429      * creates.
1430      *
1431      * @throws SQLException if an error occurs or the
1432      *                         necessary properties have not been set
1433      */
1434     public void execute() throws SQLException {
1435         execute(null);
1436     }
1437 
1438 
1439 
1440     //-----------------------------------
1441     // Methods inherited from ResultSet
1442     //-----------------------------------
1443 
1444     /**
1445      * Moves the cursor down one row from its current position and
1446      * returns <code>true</code> if the new cursor position is a
1447      * valid row.
1448      * The cursor for a new <code>ResultSet</code> object is initially
1449      * positioned before the first row. The first call to the method
1450      * <code>next</code> moves the cursor to the first row, making it
1451      * the current row; the second call makes the second row the
1452      * current row, and so on.
1453      *
1454      * <P>If an input stream from the previous row is open, it is
1455      * implicitly closed. The <code>ResultSet</code> object's warning
1456      * chain is cleared when a new row is read.
1457      *
1458      * @return <code>true</code> if the new current row is valid;
1459      *         <code>false</code> if there are no more rows
1460      * @throws SQLException if an error occurs or
1461      *            the cursor is not positioned in the rowset, before
1462      *            the first row, or after the last row
1463      */
1464     public boolean next() throws SQLException {
1465         /*
1466          * make sure things look sane. The cursor must be
1467          * positioned in the rowset or before first (0) or
1468          * after last (numRows + 1)
1469          */
1470         if (cursorPos < 0 || cursorPos >= numRows + 1) {
1471             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1472         }
1473         // now move and notify
1474         boolean ret = this.internalNext();
1475         notifyCursorMoved();
1476 
1477         return ret;
1478     }
1479 
1480     /**
1481      * Moves this <code>CachedRowSetImpl</code> object's cursor to the next
1482      * row and returns <code>true</code> if the cursor is still in the rowset;
1483      * returns <code>false</code> if the cursor has moved to the position after
1484      * the last row.
1485      * <P>
1486      * This method handles the cases where the cursor moves to a row that
1487      * has been deleted.
1488      * If this rowset shows deleted rows and the cursor moves to a row
1489      * that has been deleted, this method moves the cursor to the next
1490      * row until the cursor is on a row that has not been deleted.
1491      * <P>
1492      * The method <code>internalNext</code> is called by methods such as
1493      * <code>next</code>, <code>absolute</code>, and <code>relative</code>,
1494      * and, as its name implies, is only called internally.
1495      * <p>
1496      * This is a implementation only method and is not required as a standard
1497      * implementation of the <code>CachedRowSet</code> interface.
1498      *
1499      * @return <code>true</code> if the cursor is on a valid row in this
1500      *         rowset; <code>false</code> if it is after the last row
1501      * @throws SQLException if an error occurs
1502      */
1503     protected boolean internalNext() throws SQLException {
1504         boolean ret = false;
1505 
1506         do {
1507             if (cursorPos < numRows) {
1508                 ++cursorPos;
1509                 ret = true;
1510             } else if (cursorPos == numRows) {
1511                 // increment to after last
1512                 ++cursorPos;
1513                 ret = false;
1514                 break;
1515             }
1516         } while ((getShowDeleted() == false) && (rowDeleted() == true));
1517 
1518         /* each call to internalNext may increment cursorPos multiple
1519          * times however, the absolutePos only increments once per call.
1520          */
1521         if (ret == true)
1522             absolutePos++;
1523         else
1524             absolutePos = 0;
1525 
1526         return ret;
1527     }
1528 
1529     /**
1530      * Closes this <code>CachedRowSetImpl</code> objecy and releases any resources
1531      * it was using.
1532      *
1533      * @throws SQLException if an error occurs when releasing any resources in use
1534      * by this <code>CachedRowSetImpl</code> object
1535      */
1536     public void close() throws SQLException {
1537 
1538         // close all data structures holding
1539         // the disconnected rowset
1540 
1541         cursorPos = 0;
1542         absolutePos = 0;
1543         numRows = 0;
1544         numDeleted = 0;
1545 
1546         // set all insert(s), update(s) & delete(s),
1547         // if at all, to their initial values.
1548         initProperties();
1549 
1550         // clear the vector of it's present contents
1551         rvh.clear();
1552 
1553         // this will make it eligible for gc
1554         // rvh = null;
1555     }
1556 
1557     /**
1558      * Reports whether the last column read was SQL <code>NULL</code>.
1559      * Note that you must first call the method <code>getXXX</code>
1560      * on a column to try to read its value and then call the method
1561      * <code>wasNull</code> to determine whether the value was
1562      * SQL <code>NULL</code>.
1563      *
1564      * @return <code>true</code> if the value in the last column read
1565      *         was SQL <code>NULL</code>; <code>false</code> otherwise
1566      * @throws SQLException if an error occurs
1567      */
1568     public boolean wasNull() throws SQLException {
1569         return lastValueNull;
1570     }
1571 
1572     /**
1573      * Sets the field <code>lastValueNull</code> to the given
1574      * <code>boolean</code> value.
1575      *
1576      * @param value <code>true</code> to indicate that the value of
1577      *        the last column read was SQL <code>NULL</code>;
1578      *        <code>false</code> to indicate that it was not
1579      */
1580     private void setLastValueNull(boolean value) {
1581         lastValueNull = value;
1582     }
1583 
1584     // Methods for accessing results by column index
1585 
1586     /**
1587      * Checks to see whether the given index is a valid column number
1588      * in this <code>CachedRowSetImpl</code> object and throws
1589      * an <code>SQLException</code> if it is not. The index is out of bounds
1590      * if it is less than <code>1</code> or greater than the number of
1591      * columns in this rowset.
1592      * <P>
1593      * This method is called internally by the <code>getXXX</code> and
1594      * <code>updateXXX</code> methods.
1595      *
1596      * @param idx the number of a column in this <code>CachedRowSetImpl</code>
1597      *            object; must be between <code>1</code> and the number of
1598      *            rows in this rowset
1599      * @throws SQLException if the given index is out of bounds
1600      */
1601     private void checkIndex(int idx) throws SQLException {
1602         if (idx < 1 || idx > RowSetMD.getColumnCount()) {
1603             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcol").toString());
1604         }
1605     }
1606 
1607     /**
1608      * Checks to see whether the cursor for this <code>CachedRowSetImpl</code>
1609      * object is on a row in the rowset and throws an
1610      * <code>SQLException</code> if it is not.
1611      * <P>
1612      * This method is called internally by <code>getXXX</code> methods, by
1613      * <code>updateXXX</code> methods, and by methods that update, insert,
1614      * or delete a row or that cancel a row update, insert, or delete.
1615      *
1616      * @throws SQLException if the cursor for this <code>CachedRowSetImpl</code>
1617      *         object is not on a valid row
1618      */
1619     private void checkCursor() throws SQLException {
1620         if (isAfterLast() == true || isBeforeFirst() == true) {
1621             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1622         }
1623     }
1624 
1625     /**
1626      * Returns the column number of the column with the given name in this
1627      * <code>CachedRowSetImpl</code> object.  This method throws an
1628      * <code>SQLException</code> if the given name is not the name of
1629      * one of the columns in this rowset.
1630      *
1631      * @param name a <code>String</code> object that is the name of a column in
1632      *              this <code>CachedRowSetImpl</code> object
1633      * @throws SQLException if the given name does not match the name of one of
1634      *         the columns in this rowset
1635      */
1636     private int getColIdxByName(String name) throws SQLException {
1637         RowSetMD = (RowSetMetaDataImpl)this.getMetaData();
1638         int cols = RowSetMD.getColumnCount();
1639 
1640         for (int i=1; i <= cols; ++i) {
1641             String colName = RowSetMD.getColumnName(i);
1642             if (colName != null)
1643                 if (name.equalsIgnoreCase(colName))
1644                     return (i);
1645                 else
1646                     continue;
1647         }
1648         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalcolnm").toString());
1649 
1650     }
1651 
1652     /**
1653      * Returns the insert row or the current row of this
1654      * <code>CachedRowSetImpl</code>object.
1655      *
1656      * @return the <code>Row</code> object on which this <code>CachedRowSetImpl</code>
1657      * objects's cursor is positioned
1658      */
1659     protected BaseRow getCurrentRow() {
1660         if (onInsertRow == true) {
1661             return (BaseRow)insertRow;
1662         } else {
1663             return (BaseRow)(rvh.get(cursorPos - 1));
1664         }
1665     }
1666 
1667     /**
1668      * Removes the row on which the cursor is positioned.
1669      * <p>
1670      * This is a implementation only method and is not required as a standard
1671      * implementation of the <code>CachedRowSet</code> interface.
1672      *
1673      * @throws SQLException if the cursor is positioned on the insert
1674      *            row
1675      */
1676     protected void removeCurrentRow() {
1677         ((Row)getCurrentRow()).setDeleted();
1678         rvh.remove(cursorPos - 1);
1679         --numRows;
1680     }
1681 
1682 
1683     /**
1684      * Retrieves the value of the designated column in the current row
1685      * of this <code>CachedRowSetImpl</code> object as a
1686      * <code>String</code> object.
1687      *
1688      * @param columnIndex the first column is <code>1</code>, the second
1689      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1690      *        and equal to or less than the number of columns in the rowset
1691      * @return the column value; if the value is SQL <code>NULL</code>, the
1692      *         result is <code>null</code>
1693      * @throws SQLException if (1) the given column index is out of bounds,
1694      * (2) the cursor is not on one of this rowset's rows or its
1695      * insert row, or (3) the designated column does not store an
1696      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
1697      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, <b>CHAR</b>, <b>VARCHAR</b></code>
1698      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1699      * recommended return type.
1700      */
1701     public String getString(int columnIndex) throws SQLException {
1702         Object value;
1703 
1704         // sanity check.
1705         checkIndex(columnIndex);
1706         // make sure the cursor is on a valid row
1707         checkCursor();
1708 
1709         setLastValueNull(false);
1710         value = getCurrentRow().getColumnObject(columnIndex);
1711 
1712         // check for SQL NULL
1713         if (value == null) {
1714             setLastValueNull(true);
1715             return null;
1716         }
1717 
1718         return value.toString();
1719     }
1720 
1721     /**
1722      * Retrieves the value of the designated column in the current row
1723      * of this <code>CachedRowSetImpl</code> object as a
1724      * <code>boolean</code> value.
1725      *
1726      * @param columnIndex the first column is <code>1</code>, the second
1727      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1728      *        and equal to or less than the number of columns in the rowset
1729      * @return the column value as a <code>boolean</code> in the Java progamming language;
1730      *        if the value is SQL <code>NULL</code>, the result is <code>false</code>
1731      * @throws SQLException if (1) the given column index is out of bounds,
1732      *            (2) the cursor is not on one of this rowset's rows or its
1733      *            insert row, or (3) the designated column does not store an
1734      *            SQL <code>BOOLEAN</code> value
1735      * @see #getBoolean(String)
1736      */
1737     public boolean getBoolean(int columnIndex) throws SQLException {
1738         Object value;
1739 
1740         // sanity check.
1741         checkIndex(columnIndex);
1742         // make sure the cursor is on a valid row
1743         checkCursor();
1744 
1745         setLastValueNull(false);
1746         value = getCurrentRow().getColumnObject(columnIndex);
1747 
1748         // check for SQL NULL
1749         if (value == null) {
1750             setLastValueNull(true);
1751             return false;
1752         }
1753 
1754         // check for Boolean...
1755         if (value instanceof Boolean) {
1756             return ((Boolean)value).booleanValue();
1757         }
1758 
1759         // convert to a Double and compare to zero
1760         try {
1761             return Double.compare(Double.parseDouble(value.toString()), 0) != 0;
1762         } catch (NumberFormatException ex) {
1763             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.boolfail").toString(),
1764                   new Object[] {value.toString().trim(), columnIndex}));
1765         }
1766     }
1767 
1768     /**
1769      * Retrieves the value of the designated column in the current row
1770      * of this <code>CachedRowSetImpl</code> object as a
1771      * <code>byte</code> value.
1772      *
1773      * @param columnIndex the first column is <code>1</code>, the second
1774      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1775      *        and equal to or less than the number of columns in the rowset
1776      * @return the column value as a <code>byte</code> in the Java programming
1777      * language; if the value is SQL <code>NULL</code>, the result is <code>0</code>
1778      * @throws SQLException if (1) the given column index is out of bounds,
1779      *            (2) the cursor is not on one of this rowset's rows or its
1780      *            insert row, or (3) the designated column does not store an
1781      *            SQL <code><b>TINYINT</b>, SMALLINT, INTEGER, BIGINT, REAL,
1782      *            FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1783      *            or <code>LONGVARCHAR</code> value. The bold SQL type
1784      *            designates the recommended return type.
1785      * @see #getByte(String)
1786      */
1787     public byte getByte(int columnIndex) throws SQLException {
1788         Object value;
1789 
1790         // sanity check.
1791         checkIndex(columnIndex);
1792         // make sure the cursor is on a valid row
1793         checkCursor();
1794 
1795         setLastValueNull(false);
1796         value = getCurrentRow().getColumnObject(columnIndex);
1797 
1798         // check for SQL NULL
1799         if (value == null) {
1800             setLastValueNull(true);
1801             return (byte)0;
1802         }
1803         try {
1804             return ((Byte.valueOf(value.toString())).byteValue());
1805         } catch (NumberFormatException ex) {
1806             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.bytefail").toString(),
1807                   new Object[] {value.toString().trim(), columnIndex}));
1808         }
1809     }
1810 
1811     /**
1812      * Retrieves the value of the designated column in the current row
1813      * of this <code>CachedRowSetImpl</code> object as a
1814      * <code>short</code> value.
1815      *
1816      * @param columnIndex the first column is <code>1</code>, the second
1817      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1818      *        and equal to or less than the number of columns in the rowset
1819      * @return the column value; if the value is SQL <code>NULL</code>, the
1820      *         result is <code>0</code>
1821      * @throws SQLException if (1) the given column index is out of bounds,
1822      * (2) the cursor is not on one of this rowset's rows or its
1823      * insert row, or (3) the designated column does not store an
1824      * SQL <code>TINYINT, <b>SMALLINT</b>, INTEGER, BIGINT, REAL
1825      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1826      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1827      * recommended return type.
1828      * @see #getShort(String)
1829      */
1830     public short getShort(int columnIndex) throws SQLException {
1831         Object value;
1832 
1833         // sanity check.
1834         checkIndex(columnIndex);
1835         // make sure the cursor is on a valid row
1836         checkCursor();
1837 
1838         setLastValueNull(false);
1839         value = getCurrentRow().getColumnObject(columnIndex);
1840 
1841         // check for SQL NULL
1842         if (value == null) {
1843             setLastValueNull(true);
1844             return (short)0;
1845         }
1846 
1847         try {
1848             return ((Short.valueOf(value.toString().trim())).shortValue());
1849         } catch (NumberFormatException ex) {
1850             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.shortfail").toString(),
1851                   new Object[] {value.toString().trim(), columnIndex}));
1852         }
1853     }
1854 
1855     /**
1856      * Retrieves the value of the designated column in the current row
1857      * of this <code>CachedRowSetImpl</code> object as an
1858      * <code>int</code> value.
1859      *
1860      * @param columnIndex the first column is <code>1</code>, the second
1861      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1862      *        and equal to or less than the number of columns in the rowset
1863      * @return the column value; if the value is SQL <code>NULL</code>, the
1864      *         result is <code>0</code>
1865      * @throws SQLException if (1) the given column index is out of bounds,
1866      * (2) the cursor is not on one of this rowset's rows or its
1867      * insert row, or (3) the designated column does not store an
1868      * SQL <code>TINYINT, SMALLINT, <b>INTEGER</b>, BIGINT, REAL
1869      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1870      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1871      * recommended return type.
1872      */
1873     public int getInt(int columnIndex) throws SQLException {
1874         Object value;
1875 
1876         // sanity check.
1877         checkIndex(columnIndex);
1878         // make sure the cursor is on a valid row
1879         checkCursor();
1880 
1881         setLastValueNull(false);
1882         value = getCurrentRow().getColumnObject(columnIndex);
1883 
1884         // check for SQL NULL
1885         if (value == null) {
1886             setLastValueNull(true);
1887             return 0;
1888         }
1889 
1890         try {
1891             return ((Integer.valueOf(value.toString().trim())).intValue());
1892         } catch (NumberFormatException ex) {
1893             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.intfail").toString(),
1894                   new Object[] {value.toString().trim(), columnIndex}));
1895         }
1896     }
1897 
1898     /**
1899      * Retrieves the value of the designated column in the current row
1900      * of this <code>CachedRowSetImpl</code> object as a
1901      * <code>long</code> value.
1902      *
1903      * @param columnIndex the first column is <code>1</code>, the second
1904      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1905      *        and equal to or less than the number of columns in the rowset
1906      * @return the column value; if the value is SQL <code>NULL</code>, the
1907      *         result is <code>0</code>
1908      * @throws SQLException if (1) the given column index is out of bounds,
1909      * (2) the cursor is not on one of this rowset's rows or its
1910      * insert row, or (3) the designated column does not store an
1911      * SQL <code>TINYINT, SMALLINT, INTEGER, <b>BIGINT</b>, REAL
1912      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1913      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1914      * recommended return type.
1915      * @see #getLong(String)
1916      */
1917     public long getLong(int columnIndex) throws SQLException {
1918         Object value;
1919 
1920         // sanity check.
1921         checkIndex(columnIndex);
1922         // make sure the cursor is on a valid row
1923         checkCursor();
1924 
1925         setLastValueNull(false);
1926         value = getCurrentRow().getColumnObject(columnIndex);
1927 
1928         // check for SQL NULL
1929         if (value == null) {
1930             setLastValueNull(true);
1931             return (long)0;
1932         }
1933         try {
1934             return ((Long.valueOf(value.toString().trim())).longValue());
1935         } catch (NumberFormatException ex) {
1936             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.longfail").toString(),
1937                   new Object[] {value.toString().trim(), columnIndex}));
1938         }
1939     }
1940 
1941     /**
1942      * Retrieves the value of the designated column in the current row
1943      * of this <code>CachedRowSetImpl</code> object as a
1944      * <code>float</code> value.
1945      *
1946      * @param columnIndex the first column is <code>1</code>, the second
1947      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1948      *        and equal to or less than the number of columns in the rowset
1949      * @return the column value; if the value is SQL <code>NULL</code>, the
1950      *         result is <code>0</code>
1951      * @throws SQLException if (1) the given column index is out of bounds,
1952      * (2) the cursor is not on one of this rowset's rows or its
1953      * insert row, or (3) the designated column does not store an
1954      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, <b>REAL</b>,
1955      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1956      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1957      * recommended return type.
1958      * @see #getFloat(String)
1959      */
1960     public float getFloat(int columnIndex) throws SQLException {
1961         Object value;
1962 
1963         // sanity check.
1964         checkIndex(columnIndex);
1965         // make sure the cursor is on a valid row
1966         checkCursor();
1967 
1968         setLastValueNull(false);
1969         value = getCurrentRow().getColumnObject(columnIndex);
1970 
1971         // check for SQL NULL
1972         if (value == null) {
1973             setLastValueNull(true);
1974             return (float)0;
1975         }
1976         try {
1977             return Float.parseFloat(value.toString());
1978         } catch (NumberFormatException ex) {
1979             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.floatfail").toString(),
1980                   new Object[] {value.toString().trim(), columnIndex}));
1981         }
1982     }
1983 
1984     /**
1985      * Retrieves the value of the designated column in the current row
1986      * of this <code>CachedRowSetImpl</code> object as a
1987      * <code>double</code> value.
1988      *
1989      * @param columnIndex the first column is <code>1</code>, the second
1990      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1991      *        and equal to or less than the number of columns in the rowset
1992      * @return the column value; if the value is SQL <code>NULL</code>, the
1993      *         result is <code>0</code>
1994      * @throws SQLException if (1) the given column index is out of bounds,
1995      * (2) the cursor is not on one of this rowset's rows or its
1996      * insert row, or (3) the designated column does not store an
1997      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
1998      * <b>FLOAT</b>, <b>DOUBLE</b>, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1999      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
2000      * recommended return type.
2001      * @see #getDouble(String)
2002      *
2003      */
2004     public double getDouble(int columnIndex) throws SQLException {
2005         Object value;
2006 
2007         // sanity check.
2008         checkIndex(columnIndex);
2009         // make sure the cursor is on a valid row
2010         checkCursor();
2011 
2012         setLastValueNull(false);
2013         value = getCurrentRow().getColumnObject(columnIndex);
2014 
2015         // check for SQL NULL
2016         if (value == null) {
2017             setLastValueNull(true);
2018             return (double)0;
2019         }
2020         try {
2021             return Double.parseDouble(value.toString().trim());
2022         } catch (NumberFormatException ex) {
2023             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.doublefail").toString(),
2024                   new Object[] {value.toString().trim(), columnIndex}));
2025         }
2026     }
2027 
2028     /**
2029      * Retrieves the value of the designated column in the current row
2030      * of this <code>CachedRowSetImpl</code> object as a
2031      * <code>java.math.BigDecimal</code> object.
2032      * <P>
2033      * This method is deprecated; use the version of <code>getBigDecimal</code>
2034      * that does not take a scale parameter and returns a value with full
2035      * precision.
2036      *
2037      * @param columnIndex the first column is <code>1</code>, the second
2038      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2039      *        and equal to or less than the number of columns in the rowset
2040      * @param scale the number of digits to the right of the decimal point in the
2041      *        value returned
2042      * @return the column value with the specified number of digits to the right
2043      *         of the decimal point; if the value is SQL <code>NULL</code>, the
2044      *         result is <code>null</code>
2045      * @throws SQLException if the given column index is out of bounds,
2046      *            the cursor is not on a valid row, or this method fails
2047      * @deprecated
2048      */
2049     @Deprecated
2050     public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
2051         Object value;
2052         BigDecimal bDecimal, retVal;
2053 
2054         // sanity check.
2055         checkIndex(columnIndex);
2056         // make sure the cursor is on a valid row
2057         checkCursor();
2058 
2059         setLastValueNull(false);
2060         value = getCurrentRow().getColumnObject(columnIndex);
2061 
2062         // check for SQL NULL
2063         if (value == null) {
2064             setLastValueNull(true);
2065             return (new BigDecimal(0));
2066         }
2067 
2068         bDecimal = this.getBigDecimal(columnIndex);
2069 
2070         retVal = bDecimal.setScale(scale);
2071 
2072         return retVal;
2073     }
2074 
2075     /**
2076      * Retrieves the value of the designated column in the current row
2077      * of this <code>CachedRowSetImpl</code> object as a
2078      * <code>byte</code> array value.
2079      *
2080      * @param columnIndex the first column is <code>1</code>, the second
2081      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2082      *        and equal to or less than the number of columns in the rowset
2083      * @return the column value as a <code>byte</code> array in the Java programming
2084      * language; if the value is SQL <code>NULL</code>, the
2085      * result is <code>null</code>
2086      *
2087      * @throws SQLException if (1) the given column index is out of bounds,
2088      * (2) the cursor is not on one of this rowset's rows or its
2089      * insert row, or (3) the designated column does not store an
2090      * SQL <code><b>BINARY</b>, <b>VARBINARY</b> or
2091      * LONGVARBINARY</code> value.
2092      * The bold SQL type designates the recommended return type.
2093      * @see #getBytes(String)
2094      */
2095     public byte[] getBytes(int columnIndex) throws SQLException {
2096         // sanity check.
2097         checkIndex(columnIndex);
2098         // make sure the cursor is on a valid row
2099         checkCursor();
2100 
2101         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
2102             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2103         }
2104 
2105         return (byte[])(getCurrentRow().getColumnObject(columnIndex));
2106     }
2107 
2108     /**
2109      * Retrieves the value of the designated column in the current row
2110      * of this <code>CachedRowSetImpl</code> object as a
2111      * <code>java.sql.Date</code> object.
2112      *
2113      * @param columnIndex the first column is <code>1</code>, the second
2114      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2115      *        and equal to or less than the number of columns in the rowset
2116      * @return the column value as a <code>java.sql.Data</code> object; if
2117      *        the value is SQL <code>NULL</code>, the
2118      *        result is <code>null</code>
2119      * @throws SQLException if the given column index is out of bounds,
2120      *            the cursor is not on a valid row, or this method fails
2121      */
2122     public java.sql.Date getDate(int columnIndex) throws SQLException {
2123         Object value;
2124 
2125         // sanity check.
2126         checkIndex(columnIndex);
2127         // make sure the cursor is on a valid row
2128         checkCursor();
2129 
2130         setLastValueNull(false);
2131         value = getCurrentRow().getColumnObject(columnIndex);
2132 
2133         // check for SQL NULL
2134         if (value == null) {
2135             setLastValueNull(true);
2136             return null;
2137         }
2138 
2139         /*
2140          * The object coming back from the db could be
2141          * a date, a timestamp, or a char field variety.
2142          * If it's a date type return it, a timestamp
2143          * we turn into a long and then into a date,
2144          * char strings we try to parse. Yuck.
2145          */
2146         switch (RowSetMD.getColumnType(columnIndex)) {
2147             case java.sql.Types.DATE: {
2148                 long sec = ((java.sql.Date)value).getTime();
2149                 return new java.sql.Date(sec);
2150             }
2151             case java.sql.Types.TIMESTAMP: {
2152                 long sec = ((java.sql.Timestamp)value).getTime();
2153                 return new java.sql.Date(sec);
2154             }
2155             case java.sql.Types.CHAR:
2156             case java.sql.Types.VARCHAR:
2157             case java.sql.Types.LONGVARCHAR: {
2158                 try {
2159                     DateFormat df = DateFormat.getDateInstance();
2160                     return ((java.sql.Date)(df.parse(value.toString())));
2161                 } catch (ParseException ex) {
2162                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.datefail").toString(),
2163                         new Object[] {value.toString().trim(), columnIndex}));
2164                 }
2165             }
2166             default: {
2167                 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.datefail").toString(),
2168                         new Object[] {value.toString().trim(), columnIndex}));
2169             }
2170         }
2171     }
2172 
2173     /**
2174      * Retrieves the value of the designated column in the current row
2175      * of this <code>CachedRowSetImpl</code> object as a
2176      * <code>java.sql.Time</code> object.
2177      *
2178      * @param columnIndex the first column is <code>1</code>, the second
2179      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2180      *        and equal to or less than the number of columns in the rowset
2181      * @return the column value; if the value is SQL <code>NULL</code>, the
2182      *         result is <code>null</code>
2183      * @throws SQLException if the given column index is out of bounds,
2184      *         the cursor is not on a valid row, or this method fails
2185      */
2186     public java.sql.Time getTime(int columnIndex) throws SQLException {
2187         Object value;
2188 
2189         // sanity check.
2190         checkIndex(columnIndex);
2191         // make sure the cursor is on a valid row
2192         checkCursor();
2193 
2194         setLastValueNull(false);
2195         value = getCurrentRow().getColumnObject(columnIndex);
2196 
2197         // check for SQL NULL
2198         if (value == null) {
2199             setLastValueNull(true);
2200             return null;
2201         }
2202 
2203         /*
2204          * The object coming back from the db could be
2205          * a date, a timestamp, or a char field variety.
2206          * If it's a date type return it, a timestamp
2207          * we turn into a long and then into a date,
2208          * char strings we try to parse. Yuck.
2209          */
2210         switch (RowSetMD.getColumnType(columnIndex)) {
2211             case java.sql.Types.TIME: {
2212                 return (java.sql.Time)value;
2213             }
2214             case java.sql.Types.TIMESTAMP: {
2215                 long sec = ((java.sql.Timestamp)value).getTime();
2216                 return new java.sql.Time(sec);
2217             }
2218             case java.sql.Types.CHAR:
2219             case java.sql.Types.VARCHAR:
2220             case java.sql.Types.LONGVARCHAR: {
2221                 try {
2222                     DateFormat tf = DateFormat.getTimeInstance();
2223                     return ((java.sql.Time)(tf.parse(value.toString())));
2224                 } catch (ParseException ex) {
2225                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2226                         new Object[] {value.toString().trim(), columnIndex}));
2227                 }
2228             }
2229             default: {
2230                 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2231                         new Object[] {value.toString().trim(), columnIndex}));
2232             }
2233         }
2234     }
2235 
2236     /**
2237      * Retrieves the value of the designated column in the current row
2238      * of this <code>CachedRowSetImpl</code> object as a
2239      * <code>java.sql.Timestamp</code> object.
2240      *
2241      * @param columnIndex the first column is <code>1</code>, the second
2242      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2243      *        and equal to or less than the number of columns in the rowset
2244      * @return the column value; if the value is SQL <code>NULL</code>, the
2245      *         result is <code>null</code>
2246      * @throws SQLException if the given column index is out of bounds,
2247      *            the cursor is not on a valid row, or this method fails
2248      */
2249     public java.sql.Timestamp getTimestamp(int columnIndex) throws SQLException {
2250         Object value;
2251 
2252         // sanity check.
2253         checkIndex(columnIndex);
2254         // make sure the cursor is on a valid row
2255         checkCursor();
2256 
2257         setLastValueNull(false);
2258         value = getCurrentRow().getColumnObject(columnIndex);
2259 
2260         // check for SQL NULL
2261         if (value == null) {
2262             setLastValueNull(true);
2263             return null;
2264         }
2265 
2266         /*
2267          * The object coming back from the db could be
2268          * a date, a timestamp, or a char field variety.
2269          * If it's a date type return it; a timestamp
2270          * we turn into a long and then into a date;
2271          * char strings we try to parse. Yuck.
2272          */
2273         switch (RowSetMD.getColumnType(columnIndex)) {
2274             case java.sql.Types.TIMESTAMP: {
2275                 return (java.sql.Timestamp)value;
2276             }
2277             case java.sql.Types.TIME: {
2278                 long sec = ((java.sql.Time)value).getTime();
2279                 return new java.sql.Timestamp(sec);
2280             }
2281             case java.sql.Types.DATE: {
2282                 long sec = ((java.sql.Date)value).getTime();
2283                 return new java.sql.Timestamp(sec);
2284             }
2285             case java.sql.Types.CHAR:
2286             case java.sql.Types.VARCHAR:
2287             case java.sql.Types.LONGVARCHAR: {
2288                 try {
2289                     DateFormat tf = DateFormat.getTimeInstance();
2290                     return ((java.sql.Timestamp)(tf.parse(value.toString())));
2291                 } catch (ParseException ex) {
2292                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2293                         new Object[] {value.toString().trim(), columnIndex}));
2294                 }
2295             }
2296             default: {
2297                 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2298                         new Object[] {value.toString().trim(), columnIndex}));
2299             }
2300         }
2301     }
2302 
2303     /**
2304      * Retrieves the value of the designated column in the current row of this
2305      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2306      * object.
2307      *
2308      * A column value can be retrieved as a stream of ASCII characters
2309      * and then read in chunks from the stream.  This method is particularly
2310      * suitable for retrieving large <code>LONGVARCHAR</code> values.  The JDBC
2311      * driver will do any necessary conversion from the database format into ASCII.
2312      *
2313      * <P><B>Note:</B> All the data in the returned stream must be
2314      * read prior to getting the value of any other column. The next
2315      * call to a get method implicitly closes the stream. . Also, a
2316      * stream may return <code>0</code> for <code>CachedRowSetImpl.available()</code>
2317      * whether there is data available or not.
2318      *
2319      * @param columnIndex the first column is <code>1</code>, the second
2320      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2321      *        and equal to or less than the number of columns in this rowset
2322      * @return a Java input stream that delivers the database column value
2323      *         as a stream of one-byte ASCII characters.  If the value is SQL
2324      *         <code>NULL</code>, the result is <code>null</code>.
2325      * @throws SQLException if (1) the given column index is out of bounds,
2326      * (2) the cursor is not on one of this rowset's rows or its
2327      * insert row, or (3) the designated column does not store an
2328      * SQL <code>CHAR, VARCHAR</code>, <code><b>LONGVARCHAR</b></code>
2329      * <code>BINARY, VARBINARY</code> or <code>LONGVARBINARY</code> value. The
2330      * bold SQL type designates the recommended return types that this method is
2331      * used to retrieve.
2332      * @see #getAsciiStream(String)
2333      */
2334     public java.io.InputStream getAsciiStream(int columnIndex) throws SQLException {
2335         Object value;
2336 
2337         // always free an old stream
2338         asciiStream = null;
2339 
2340         // sanity check
2341         checkIndex(columnIndex);
2342         //make sure the cursor is on a vlid row
2343         checkCursor();
2344 
2345         value =  getCurrentRow().getColumnObject(columnIndex);
2346         if (value == null) {
2347             lastValueNull = true;
2348             return null;
2349         }
2350 
2351         try {
2352             if (isString(RowSetMD.getColumnType(columnIndex))) {
2353                 asciiStream = new ByteArrayInputStream(((String)value).getBytes("ASCII"));
2354             } else {
2355                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2356             }
2357         } catch (java.io.UnsupportedEncodingException ex) {
2358             throw new SQLException(ex.getMessage());
2359         }
2360 
2361         return asciiStream;
2362     }
2363 
2364     /**
2365      * A column value can be retrieved as a stream of Unicode characters
2366      * and then read in chunks from the stream.  This method is particularly
2367      * suitable for retrieving large LONGVARCHAR values.  The JDBC driver will
2368      * do any necessary conversion from the database format into Unicode.
2369      *
2370      * <P><B>Note:</B> All the data in the returned stream must be
2371      * read prior to getting the value of any other column. The next
2372      * call to a get method implicitly closes the stream. . Also, a
2373      * stream may return 0 for available() whether there is data
2374      * available or not.
2375      *
2376      * @param columnIndex the first column is <code>1</code>, the second
2377      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2378      *        and equal to or less than the number of columns in this rowset
2379      * @return a Java input stream that delivers the database column value
2380      * as a stream of two byte Unicode characters.  If the value is SQL NULL
2381      * then the result is null.
2382      * @throws SQLException if an error occurs
2383      * @deprecated
2384      */
2385     @Deprecated
2386     public java.io.InputStream getUnicodeStream(int columnIndex) throws SQLException {
2387         // always free an old stream
2388         unicodeStream = null;
2389 
2390         // sanity check.
2391         checkIndex(columnIndex);
2392         // make sure the cursor is on a valid row
2393         checkCursor();
2394 
2395         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false &&
2396         isString(RowSetMD.getColumnType(columnIndex)) == false) {
2397             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2398         }
2399 
2400         Object value = getCurrentRow().getColumnObject(columnIndex);
2401         if (value == null) {
2402             lastValueNull = true;
2403             return null;
2404         }
2405 
2406         unicodeStream = new StringBufferInputStream(value.toString());
2407 
2408         return unicodeStream;
2409     }
2410 
2411     /**
2412      * Retrieves the value of the designated column in the current row of this
2413      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2414      * object.
2415      * <P>
2416      * A column value can be retrieved as a stream of uninterpreted bytes
2417      * and then read in chunks from the stream.  This method is particularly
2418      * suitable for retrieving large <code>LONGVARBINARY</code> values.
2419      *
2420      * <P><B>Note:</B> All the data in the returned stream must be
2421      * read prior to getting the value of any other column. The next
2422      * call to a get method implicitly closes the stream. Also, a
2423      * stream may return <code>0</code> for
2424      * <code>CachedRowSetImpl.available()</code> whether there is data
2425      * available or not.
2426      *
2427      * @param columnIndex the first column is <code>1</code>, the second
2428      * is <code>2</code>, and so on; must be <code>1</code> or larger
2429      * and equal to or less than the number of columns in the rowset
2430      * @return a Java input stream that delivers the database column value
2431      * as a stream of uninterpreted bytes.  If the value is SQL <code>NULL</code>
2432      * then the result is <code>null</code>.
2433      * @throws SQLException if (1) the given column index is out of bounds,
2434      * (2) the cursor is not on one of this rowset's rows or its
2435      * insert row, or (3) the designated column does not store an
2436      * SQL <code>BINARY, VARBINARY</code> or <code><b>LONGVARBINARY</b></code>
2437      * The bold type indicates the SQL type that this method is recommened
2438      * to retrieve.
2439      * @see #getBinaryStream(String)
2440      */
2441     public java.io.InputStream getBinaryStream(int columnIndex) throws SQLException {
2442 
2443         // always free an old stream
2444         binaryStream = null;
2445 
2446         // sanity check.
2447         checkIndex(columnIndex);
2448         // make sure the cursor is on a valid row
2449         checkCursor();
2450 
2451         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
2452             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2453         }
2454 
2455         Object value = getCurrentRow().getColumnObject(columnIndex);
2456         if (value == null) {
2457             lastValueNull = true;
2458             return null;
2459         }
2460 
2461         binaryStream = new ByteArrayInputStream((byte[])value);
2462 
2463         return binaryStream;
2464 
2465     }
2466 
2467 
2468     // Methods for accessing results by column name
2469 
2470     /**
2471      * Retrieves the value stored in the designated column
2472      * of the current row as a <code>String</code> object.
2473      *
2474      * @param columnName a <code>String</code> object giving the SQL name of
2475      *        a column in this <code>CachedRowSetImpl</code> object
2476      * @return the column value; if the value is SQL <code>NULL</code>,
2477      *         the result is <code>null</code>
2478      * @throws SQLException if (1) the given column name is not the name of
2479      * a column in this rowset, (2) the cursor is not on one of
2480      * this rowset's rows or its insert row, or (3) the designated
2481      * column does not store an SQL {@code TINYINT, SMALLINT, INTEGER
2482      * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, }
2483      * <b>{@code CHAR, VARCHAR}</b> or
2484      * <b>{@code LONGVARCHAR}</b> value.
2485      * The bold SQL type designates the recommended return type.
2486      */
2487     public String getString(String columnName) throws SQLException {
2488         return getString(getColIdxByName(columnName));
2489     }
2490 
2491     /**
2492      * Retrieves the value stored in the designated column
2493      * of the current row as a <code>boolean</code> value.
2494      *
2495      * @param columnName a <code>String</code> object giving the SQL name of
2496      *        a column in this <code>CachedRowSetImpl</code> object
2497      * @return the column value as a <code>boolean</code> in the Java programming
2498      *        language; if the value is SQL <code>NULL</code>,
2499      *        the result is <code>false</code>
2500      * @throws SQLException if (1) the given column name is not the name of
2501      *            a column in this rowset, (2) the cursor is not on one of
2502      *            this rowset's rows or its insert row, or (3) the designated
2503      *            column does not store an SQL <code>BOOLEAN</code> value
2504      * @see #getBoolean(int)
2505      */
2506     public boolean getBoolean(String columnName) throws SQLException {
2507         return getBoolean(getColIdxByName(columnName));
2508     }
2509 
2510     /**
2511      * Retrieves the value stored in the designated column
2512      * of the current row as a <code>byte</code> value.
2513      *
2514      * @param columnName a <code>String</code> object giving the SQL name of
2515      *        a column in this <code>CachedRowSetImpl</code> object
2516      * @return the column value as a <code>byte</code> in the Java programming
2517      * language; if the value is SQL <code>NULL</code>, the result is <code>0</code>
2518      * @throws SQLException if (1) the given column name is not the name of
2519      * a column in this rowset, (2) the cursor is not on one of
2520      * this rowset's rows or its insert row, or (3) the designated
2521      * column does not store an SQL <code><B>TINYINT</B>, SMALLINT, INTEGER,
2522      * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2523      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The
2524      * bold type designates the recommended return type
2525      */
2526     public byte getByte(String columnName) throws SQLException {
2527         return getByte(getColIdxByName(columnName));
2528     }
2529 
2530     /**
2531      * Retrieves the value stored in the designated column
2532      * of the current row as a <code>short</code> value.
2533      *
2534      * @param columnName a <code>String</code> object giving the SQL name of
2535      *        a column in this <code>CachedRowSetImpl</code> object
2536      * @return the column value; if the value is SQL <code>NULL</code>,
2537      *         the result is <code>0</code>
2538      * @throws SQLException if (1) the given column name is not the name of
2539      * a column in this rowset, (2) the cursor is not on one of
2540      * this rowset's rows or its insert row, or (3) the designated
2541      * column does not store an SQL <code>TINYINT, <b>SMALLINT</b>, INTEGER
2542      * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2543      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2544      * designates the recommended return type.
2545      * @see #getShort(int)
2546      */
2547     public short getShort(String columnName) throws SQLException {
2548         return getShort(getColIdxByName(columnName));
2549     }
2550 
2551     /**
2552      * Retrieves the value stored in the designated column
2553      * of the current row as an <code>int</code> value.
2554      *
2555      * @param columnName a <code>String</code> object giving the SQL name of
2556      *        a column in this <code>CachedRowSetImpl</code> object
2557      * @return the column value; if the value is SQL <code>NULL</code>,
2558      *         the result is <code>0</code>
2559      * @throws SQLException if (1) the given column name is not the name
2560      * of a column in this rowset,
2561      * (2) the cursor is not on one of this rowset's rows or its
2562      * insert row, or (3) the designated column does not store an
2563      * SQL <code>TINYINT, SMALLINT, <b>INTEGER</b>, BIGINT, REAL
2564      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
2565      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
2566      * recommended return type.
2567      */
2568     public int getInt(String columnName) throws SQLException {
2569         return getInt(getColIdxByName(columnName));
2570     }
2571 
2572     /**
2573      * Retrieves the value stored in the designated column
2574      * of the current row as a <code>long</code> value.
2575      *
2576      * @param columnName a <code>String</code> object giving the SQL name of
2577      *        a column in this <code>CachedRowSetImpl</code> object
2578      * @return the column value; if the value is SQL <code>NULL</code>,
2579      *         the result is <code>0</code>
2580      * @throws SQLException if (1) the given column name is not the name of
2581      * a column in this rowset, (2) the cursor is not on one of
2582      * this rowset's rows or its insert row, or (3) the designated
2583      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2584      * <b>BIGINT</b>, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2585      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2586      * designates the recommended return type.
2587      * @see #getLong(int)
2588      */
2589     public long getLong(String columnName) throws SQLException {
2590         return getLong(getColIdxByName(columnName));
2591     }
2592 
2593     /**
2594      * Retrieves the value stored in the designated column
2595      * of the current row as a <code>float</code> value.
2596      *
2597      * @param columnName a <code>String</code> object giving the SQL name of
2598      *        a column in this <code>CachedRowSetImpl</code> object
2599      * @return the column value; if the value is SQL <code>NULL</code>,
2600      *         the result is <code>0</code>
2601      * @throws SQLException if (1) the given column name is not the name of
2602      * a column in this rowset, (2) the cursor is not on one of
2603      * this rowset's rows or its insert row, or (3) the designated
2604      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2605      * BIGINT, <b>REAL</b>, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2606      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2607      * designates the recommended return type.
2608      * @see #getFloat(String)
2609      */
2610     public float getFloat(String columnName) throws SQLException {
2611         return getFloat(getColIdxByName(columnName));
2612     }
2613 
2614     /**
2615      * Retrieves the value stored in the designated column
2616      * of the current row of this <code>CachedRowSetImpl</code> object
2617      * as a <code>double</code> value.
2618      *
2619      * @param columnName a <code>String</code> object giving the SQL name of
2620      *        a column in this <code>CachedRowSetImpl</code> object
2621      * @return the column value; if the value is SQL <code>NULL</code>,
2622      *         the result is <code>0</code>
2623      * @throws SQLException if (1) the given column name is not the name of
2624      * a column in this rowset, (2) the cursor is not on one of
2625      * this rowset's rows or its insert row, or (3) the designated
2626      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2627      * BIGINT, REAL, <b>FLOAT</b>, <b>DOUBLE</b>, DECIMAL, NUMERIC, BIT, CHAR,
2628      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2629      * designates the recommended return types.
2630      * @see #getDouble(int)
2631      */
2632     public double getDouble(String columnName) throws SQLException {
2633         return getDouble(getColIdxByName(columnName));
2634     }
2635 
2636     /**
2637      * Retrieves the value stored in the designated column
2638      * of the current row as a <code>java.math.BigDecimal</code> object.
2639      *
2640      * @param columnName a <code>String</code> object giving the SQL name of
2641      *        a column in this <code>CachedRowSetImpl</code> object
2642      * @param scale the number of digits to the right of the decimal point
2643      * @return a java.math.BugDecimal object with <code><i>scale</i></code>
2644      * number of digits to the right of the decimal point.
2645      * @throws SQLException if (1) the given column name is not the name of
2646      * a column in this rowset, (2) the cursor is not on one of
2647      * this rowset's rows or its insert row, or (3) the designated
2648      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2649      * BIGINT, REAL, FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT CHAR,
2650      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2651      * designates the recommended return type that this method is used to
2652      * retrieve.
2653      * @deprecated Use the <code>getBigDecimal(String columnName)</code>
2654      *             method instead
2655      */
2656     @Deprecated
2657     public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {
2658         return getBigDecimal(getColIdxByName(columnName), scale);
2659     }
2660 
2661     /**
2662      * Retrieves the value stored in the designated column
2663      * of the current row as a <code>byte</code> array.
2664      * The bytes represent the raw values returned by the driver.
2665      *
2666      * @param columnName a <code>String</code> object giving the SQL name of
2667      *        a column in this <code>CachedRowSetImpl</code> object
2668      * @return the column value as a <code>byte</code> array in the Java programming
2669      * language; if the value is SQL <code>NULL</code>, the result is <code>null</code>
2670      * @throws SQLException if (1) the given column name is not the name of
2671      * a column in this rowset, (2) the cursor is not on one of
2672      * this rowset's rows or its insert row, or (3) the designated
2673      * column does not store an SQL <code><b>BINARY</b>, <b>VARBINARY</b>
2674      * </code> or <code>LONGVARBINARY</code> values
2675      * The bold SQL type designates the recommended return type.
2676      * @see #getBytes(int)
2677      */
2678     public byte[] getBytes(String columnName) throws SQLException {
2679         return getBytes(getColIdxByName(columnName));
2680     }
2681 
2682     /**
2683      * Retrieves the value stored in the designated column
2684      * of the current row as a <code>java.sql.Date</code> object.
2685      *
2686      * @param columnName a <code>String</code> object giving the SQL name of
2687      *        a column in this <code>CachedRowSetImpl</code> object
2688      * @return the column value; if the value is SQL <code>NULL</code>,
2689      *         the result is <code>null</code>
2690      * @throws SQLException if (1) the given column name is not the name of
2691      *            a column in this rowset, (2) the cursor is not on one of
2692      *            this rowset's rows or its insert row, or (3) the designated
2693      *            column does not store an SQL <code>DATE</code> or
2694      *            <code>TIMESTAMP</code> value
2695      */
2696     public java.sql.Date getDate(String columnName) throws SQLException {
2697         return getDate(getColIdxByName(columnName));
2698     }
2699 
2700     /**
2701      * Retrieves the value stored in the designated column
2702      * of the current row as a <code>java.sql.Time</code> object.
2703      *
2704      * @param columnName a <code>String</code> object giving the SQL name of
2705      *        a column in this <code>CachedRowSetImpl</code> object
2706      * @return the column value; if the value is SQL <code>NULL</code>,
2707      *         the result is <code>null</code>
2708      * @throws SQLException if the given column name does not match one of
2709      *            this rowset's column names or the cursor is not on one of
2710      *            this rowset's rows or its insert row
2711      */
2712     public java.sql.Time getTime(String columnName) throws SQLException {
2713         return getTime(getColIdxByName(columnName));
2714     }
2715 
2716     /**
2717      * Retrieves the value stored in the designated column
2718      * of the current row as a <code>java.sql.Timestamp</code> object.
2719      *
2720      * @param columnName a <code>String</code> object giving the SQL name of
2721      *        a column in this <code>CachedRowSetImpl</code> object
2722      * @return the column value; if the value is SQL <code>NULL</code>,
2723      *         the result is <code>null</code>
2724      * @throws SQLException if the given column name does not match one of
2725      *            this rowset's column names or the cursor is not on one of
2726      *            this rowset's rows or its insert row
2727      */
2728     public java.sql.Timestamp getTimestamp(String columnName) throws SQLException {
2729         return getTimestamp(getColIdxByName(columnName));
2730     }
2731 
2732     /**
2733      * Retrieves the value of the designated column in the current row of this
2734      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2735      * object.
2736      *
2737      * A column value can be retrieved as a stream of ASCII characters
2738      * and then read in chunks from the stream. This method is particularly
2739      * suitable for retrieving large <code>LONGVARCHAR</code> values. The
2740      * <code>SyncProvider</code> will rely on the JDBC driver to do any necessary
2741      * conversion from the database format into ASCII format.
2742      *
2743      * <P><B>Note:</B> All the data in the returned stream must
2744      * be read prior to getting the value of any other column. The
2745      * next call to a <code>getXXX</code> method implicitly closes the stream.
2746      *
2747      * @param columnName a <code>String</code> object giving the SQL name of
2748      *        a column in this <code>CachedRowSetImpl</code> object
2749      * @return a Java input stream that delivers the database column value
2750      *         as a stream of one-byte ASCII characters.  If the value is SQL
2751      *         <code>NULL</code>, the result is <code>null</code>.
2752      * @throws SQLException if (1) the given column name is not the name of
2753      * a column in this rowset
2754      * (2) the cursor is not on one of this rowset's rows or its
2755      * insert row, or (3) the designated column does not store an
2756      * SQL <code>CHAR, VARCHAR</code>, <code><b>LONGVARCHAR</b></code>
2757      * <code>BINARY, VARBINARY</code> or <code>LONGVARBINARY</code> value. The
2758      * bold SQL type designates the recommended return types that this method is
2759      * used to retrieve.
2760      * @see #getAsciiStream(int)
2761      */
2762     public java.io.InputStream getAsciiStream(String columnName) throws SQLException {
2763         return getAsciiStream(getColIdxByName(columnName));
2764 
2765     }
2766 
2767     /**
2768      * A column value can be retrieved as a stream of Unicode characters
2769      * and then read in chunks from the stream.  This method is particularly
2770      * suitable for retrieving large <code>LONGVARCHAR</code> values.
2771      * The JDBC driver will do any necessary conversion from the database
2772      * format into Unicode.
2773      *
2774      * <P><B>Note:</B> All the data in the returned stream must
2775      * be read prior to getting the value of any other column. The
2776      * next call to a <code>getXXX</code> method implicitly closes the stream.
2777      *
2778      * @param columnName a <code>String</code> object giving the SQL name of
2779      *        a column in this <code>CachedRowSetImpl</code> object
2780      * @return a Java input stream that delivers the database column value
2781      *         as a stream of two-byte Unicode characters.  If the value is
2782      *         SQL <code>NULL</code>, the result is <code>null</code>.
2783      * @throws SQLException if the given column name does not match one of
2784      *            this rowset's column names or the cursor is not on one of
2785      *            this rowset's rows or its insert row
2786      * @deprecated use the method <code>getCharacterStream</code> instead
2787      */
2788     @Deprecated
2789     public java.io.InputStream getUnicodeStream(String columnName) throws SQLException {
2790         return getUnicodeStream(getColIdxByName(columnName));
2791     }
2792 
2793     /**
2794      * Retrieves the value of the designated column in the current row of this
2795      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2796      * object.
2797      * <P>
2798      * A column value can be retrieved as a stream of uninterpreted bytes
2799      * and then read in chunks from the stream.  This method is particularly
2800      * suitable for retrieving large <code>LONGVARBINARY</code> values.
2801      *
2802      * <P><B>Note:</B> All the data in the returned stream must be
2803      * read prior to getting the value of any other column. The next
2804      * call to a get method implicitly closes the stream. Also, a
2805      * stream may return <code>0</code> for <code>CachedRowSetImpl.available()</code>
2806      * whether there is data available or not.
2807      *
2808      * @param columnName a <code>String</code> object giving the SQL name of
2809      *        a column in this <code>CachedRowSetImpl</code> object
2810      * @return a Java input stream that delivers the database column value
2811      *         as a stream of uninterpreted bytes.  If the value is SQL
2812      *         <code>NULL</code>, the result is <code>null</code>.
2813      * @throws SQLException if (1) the given column name is unknown,
2814      * (2) the cursor is not on one of this rowset's rows or its
2815      * insert row, or (3) the designated column does not store an
2816      * SQL <code>BINARY, VARBINARY</code> or <code><b>LONGVARBINARY</b></code>
2817      * The bold type indicates the SQL type that this method is recommened
2818      * to retrieve.
2819      * @see #getBinaryStream(int)
2820      *
2821      */
2822     public java.io.InputStream getBinaryStream(String columnName) throws SQLException {
2823         return getBinaryStream(getColIdxByName(columnName));
2824     }
2825 
2826 
2827     // Advanced features:
2828 
2829     /**
2830      * The first warning reported by calls on this <code>CachedRowSetImpl</code>
2831      * object is returned. Subsequent <code>CachedRowSetImpl</code> warnings will
2832      * be chained to this <code>SQLWarning</code>.
2833      *
2834      * <P>The warning chain is automatically cleared each time a new
2835      * row is read.
2836      *
2837      * <P><B>Note:</B> This warning chain only covers warnings caused
2838      * by <code>ResultSet</code> methods.  Any warning caused by statement
2839      * methods (such as reading OUT parameters) will be chained on the
2840      * <code>Statement</code> object.
2841      *
2842      * @return the first SQLWarning or null
2843      */
2844     public SQLWarning getWarnings() {
2845         return sqlwarn;
2846     }
2847 
2848     /**
2849      * Clears all the warnings reporeted for the <code>CachedRowSetImpl</code>
2850      * object. After a call to this method, the <code>getWarnings</code> method
2851      * returns <code>null</code> until a new warning is reported for this
2852      * <code>CachedRowSetImpl</code> object.
2853      */
2854     public void clearWarnings() {
2855         sqlwarn = null;
2856     }
2857 
2858     /**
2859      * Retrieves the name of the SQL cursor used by this
2860      * <code>CachedRowSetImpl</code> object.
2861      *
2862      * <P>In SQL, a result table is retrieved through a cursor that is
2863      * named. The current row of a <code>ResultSet</code> can be updated or deleted
2864      * using a positioned update/delete statement that references the
2865      * cursor name. To ensure that the cursor has the proper isolation
2866      * level to support an update operation, the cursor's <code>SELECT</code>
2867      * statement should be of the form <code>select for update</code>.
2868      * If the <code>for update</code> clause
2869      * is omitted, positioned updates may fail.
2870      *
2871      * <P>JDBC supports this SQL feature by providing the name of the
2872      * SQL cursor used by a <code>ResultSet</code> object. The current row
2873      * of a result set is also the current row of this SQL cursor.
2874      *
2875      * <P><B>Note:</B> If positioned updates are not supported, an
2876      * <code>SQLException</code> is thrown.
2877      *
2878      * @return the SQL cursor name for this <code>CachedRowSetImpl</code> object's
2879      *         cursor
2880      * @throws SQLException if an error occurs
2881      */
2882     public String getCursorName() throws SQLException {
2883         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.posupdate").toString());
2884     }
2885 
2886     /**
2887      * Retrieves a <code>ResultSetMetaData</code> object instance that
2888      * contains information about the <code>CachedRowSet</code> object.
2889      * However, applications should cast the returned object to a
2890      * <code>RowSetMetaData</code> interface implementation. In the
2891      * reference implementation, this cast can be done on the
2892      * <code>RowSetMetaDataImpl</code> class.
2893      * <P>
2894      * For example:
2895      * <pre>
2896      * CachedRowSet crs = new CachedRowSetImpl();
2897      * RowSetMetaDataImpl metaData =
2898      *     (RowSetMetaDataImpl)crs.getMetaData();
2899      * // Set the number of columns in the RowSet object for
2900      * // which this RowSetMetaDataImpl object was created to the
2901      * // given number.
2902      * metaData.setColumnCount(3);
2903      * crs.setMetaData(metaData);
2904      * </pre>
2905      *
2906      * @return the <code>ResultSetMetaData</code> object that describes this
2907      *         <code>CachedRowSetImpl</code> object's columns
2908      * @throws SQLException if an error occurs in generating the RowSet
2909      * meta data; or if the <code>CachedRowSetImpl</code> is empty.
2910      * @see javax.sql.RowSetMetaData
2911      */
2912     public ResultSetMetaData getMetaData() throws SQLException {
2913         return (ResultSetMetaData)RowSetMD;
2914     }
2915 
2916 
2917     /**
2918      * Retrieves the value of the designated column in the current row
2919      * of this <code>CachedRowSetImpl</code> object as an
2920      * <code>Object</code> value.
2921      * <P>
2922      * The type of the <code>Object</code> will be the default
2923      * Java object type corresponding to the column's SQL type,
2924      * following the mapping for built-in types specified in the JDBC 3.0
2925      * specification.
2926      * <P>
2927      * This method may also be used to read datatabase-specific
2928      * abstract data types.
2929      * <P>
2930      * This implementation of the method <code>getObject</code> extends its
2931      * behavior so that it gets the attributes of an SQL structured type
2932      * as an array of <code>Object</code> values.  This method also custom
2933      * maps SQL user-defined types to classes in the Java programming language.
2934      * When the specified column contains
2935      * a structured or distinct value, the behavior of this method is as
2936      * if it were a call to the method <code>getObject(columnIndex,
2937      * this.getStatement().getConnection().getTypeMap())</code>.
2938      *
2939      * @param columnIndex the first column is <code>1</code>, the second
2940      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2941      *        and equal to or less than the number of columns in the rowset
2942      * @return a <code>java.lang.Object</code> holding the column value;
2943      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
2944      * @throws SQLException if the given column index is out of bounds,
2945      *            the cursor is not on a valid row, or there is a problem getting
2946      *            the <code>Class</code> object for a custom mapping
2947      * @see #getObject(String)
2948      */
2949     public Object getObject(int columnIndex) throws SQLException {
2950         Object value;
2951         Map<String, Class<?>> map;
2952 
2953         // sanity check.
2954         checkIndex(columnIndex);
2955         // make sure the cursor is on a valid row
2956         checkCursor();
2957 
2958         setLastValueNull(false);
2959         value = getCurrentRow().getColumnObject(columnIndex);
2960 
2961         // check for SQL NULL
2962         if (value == null) {
2963             setLastValueNull(true);
2964             return null;
2965         }
2966         if (value instanceof Struct) {
2967             Struct s = (Struct)value;
2968             map = getTypeMap();
2969             // look up the class in the map
2970             Class<?> c = map.get(s.getSQLTypeName());
2971             if (c != null) {
2972                 // create new instance of the class
2973                 SQLData obj = null;
2974                 try {
2975                     ReflectUtil.checkPackageAccess(c);
2976                     @SuppressWarnings("deprecation")
2977                     Object tmp = c.newInstance();
2978                     obj = (SQLData) tmp;
2979                 } catch(Exception ex) {
2980                     throw new SQLException("Unable to Instantiate: ", ex);
2981                 }
2982                 // get the attributes from the struct
2983                 Object attribs[] = s.getAttributes(map);
2984                 // create the SQLInput "stream"
2985                 SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
2986                 // read the values...
2987                 obj.readSQL(sqlInput, s.getSQLTypeName());
2988                 return (Object)obj;
2989             }
2990         }
2991         return value;
2992     }
2993 
2994     /**
2995      * Retrieves the value of the designated column in the current row
2996      * of this <code>CachedRowSetImpl</code> object as an
2997      * <code>Object</code> value.
2998      * <P>
2999      * The type of the <code>Object</code> will be the default
3000      * Java object type corresponding to the column's SQL type,
3001      * following the mapping for built-in types specified in the JDBC 3.0
3002      * specification.
3003      * <P>
3004      * This method may also be used to read datatabase-specific
3005      * abstract data types.
3006      * <P>
3007      * This implementation of the method <code>getObject</code> extends its
3008      * behavior so that it gets the attributes of an SQL structured type
3009      * as an array of <code>Object</code> values.  This method also custom
3010      * maps SQL user-defined types to classes
3011      * in the Java programming language. When the specified column contains
3012      * a structured or distinct value, the behavior of this method is as
3013      * if it were a call to the method <code>getObject(columnIndex,
3014      * this.getStatement().getConnection().getTypeMap())</code>.
3015      *
3016      * @param columnName a <code>String</code> object that must match the
3017      *        SQL name of a column in this rowset, ignoring case
3018      * @return a <code>java.lang.Object</code> holding the column value;
3019      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3020      * @throws SQLException if (1) the given column name does not match one of
3021      *            this rowset's column names, (2) the cursor is not
3022      *            on a valid row, or (3) there is a problem getting
3023      *            the <code>Class</code> object for a custom mapping
3024      * @see #getObject(int)
3025      */
3026     public Object getObject(String columnName) throws SQLException {
3027         return getObject(getColIdxByName(columnName));
3028     }
3029 
3030     //----------------------------------------------------------------
3031 
3032     /**
3033      * Maps the given column name for one of this <code>CachedRowSetImpl</code>
3034      * object's columns to its column number.
3035      *
3036      * @param columnName a <code>String</code> object that must match the
3037      *        SQL name of a column in this rowset, ignoring case
3038      * @return the column index of the given column name
3039      * @throws SQLException if the given column name does not match one
3040      *            of this rowset's column names
3041      */
3042     public int findColumn(String columnName) throws SQLException {
3043         return getColIdxByName(columnName);
3044     }
3045 
3046 
3047     //--------------------------JDBC 2.0-----------------------------------
3048 
3049     //---------------------------------------------------------------------
3050     // Getter's and Setter's
3051     //---------------------------------------------------------------------
3052 
3053     /**
3054      * Retrieves the value stored in the designated column
3055      * of the current row as a <code>java.io.Reader</code> object.
3056      *
3057      * <P><B>Note:</B> All the data in the returned stream must
3058      * be read prior to getting the value of any other column. The
3059      * next call to a <code>getXXX</code> method implicitly closes the stream.
3060      *
3061      * @param columnIndex the first column is <code>1</code>, the second
3062      *        is <code>2</code>, and so on; must be <code>1</code> or larger
3063      *        and equal to or less than the number of columns in the rowset
3064      * @return a Java character stream that delivers the database column value
3065      * as a stream of two-byte unicode characters in a
3066      * <code>java.io.Reader</code> object.  If the value is
3067      * SQL <code>NULL</code>, the result is <code>null</code>.
3068      * @throws SQLException if (1) the given column index is out of bounds,
3069      * (2) the cursor is not on one of this rowset's rows or its
3070      * insert row, or (3) the designated column does not store an
3071      * SQL <code>CHAR, VARCHAR, <b>LONGVARCHAR</b>, BINARY, VARBINARY</code> or
3072      * <code>LONGVARBINARY</code> value.
3073      * The bold SQL type designates the recommended return type.
3074      * @see #getCharacterStream(String)
3075      */
3076     public java.io.Reader getCharacterStream(int columnIndex) throws SQLException{
3077 
3078         // sanity check.
3079         checkIndex(columnIndex);
3080         // make sure the cursor is on a valid row
3081         checkCursor();
3082 
3083         if (isBinary(RowSetMD.getColumnType(columnIndex))) {
3084             Object value = getCurrentRow().getColumnObject(columnIndex);
3085             if (value == null) {
3086                 lastValueNull = true;
3087                 return null;
3088             }
3089             charStream = new InputStreamReader
3090             (new ByteArrayInputStream((byte[])value));
3091         } else if (isString(RowSetMD.getColumnType(columnIndex))) {
3092             Object value = getCurrentRow().getColumnObject(columnIndex);
3093             if (value == null) {
3094                 lastValueNull = true;
3095                 return null;
3096             }
3097             charStream = new StringReader(value.toString());
3098         } else {
3099             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
3100         }
3101 
3102         return charStream;
3103     }
3104 
3105     /**
3106      * Retrieves the value stored in the designated column
3107      * of the current row as a <code>java.io.Reader</code> object.
3108      *
3109      * <P><B>Note:</B> All the data in the returned stream must
3110      * be read prior to getting the value of any other column. The
3111      * next call to a <code>getXXX</code> method implicitly closes the stream.
3112      *
3113      * @param columnName a <code>String</code> object giving the SQL name of
3114      *        a column in this <code>CachedRowSetImpl</code> object
3115      * @return a Java input stream that delivers the database column value
3116      *         as a stream of two-byte Unicode characters.  If the value is
3117      *         SQL <code>NULL</code>, the result is <code>null</code>.
3118      * @throws SQLException if (1) the given column name is not the name of
3119      * a column in this rowset, (2) the cursor is not on one of
3120      * this rowset's rows or its insert row, or (3) the designated
3121      * column does not store an SQL <code>CHAR, VARCHAR, <b>LONGVARCHAR</b>,
3122      * BINARY, VARYBINARY</code> or <code>LONGVARBINARY</code> value.
3123      * The bold SQL type designates the recommended return type.
3124      */
3125     public java.io.Reader getCharacterStream(String columnName) throws SQLException {
3126         return getCharacterStream(getColIdxByName(columnName));
3127     }
3128 
3129     /**
3130      * Retrieves the value of the designated column in the current row
3131      * of this <code>CachedRowSetImpl</code> object as a
3132      * <code>java.math.BigDecimal</code> object.
3133      *
3134      * @param columnIndex the first column is <code>1</code>, the second
3135      *        is <code>2</code>, and so on; must be <code>1</code> or larger
3136      *        and equal to or less than the number of columns in the rowset
3137      * @return a <code>java.math.BigDecimal</code> value with full precision;
3138      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3139      * @throws SQLException if (1) the given column index is out of bounds,
3140      * (2) the cursor is not on one of this rowset's rows or its
3141      * insert row, or (3) the designated column does not store an
3142      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
3143      * FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT, CHAR, VARCHAR</code>
3144      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
3145      * recommended return types that this method is used to retrieve.
3146      * @see #getBigDecimal(String)
3147      */
3148     public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
3149         Object value;
3150 
3151         // sanity check.
3152         checkIndex(columnIndex);
3153         // make sure the cursor is on a valid row
3154         checkCursor();
3155 
3156         setLastValueNull(false);
3157         value = getCurrentRow().getColumnObject(columnIndex);
3158 
3159         // check for SQL NULL
3160         if (value == null) {
3161             setLastValueNull(true);
3162             return null;
3163         }
3164         try {
3165             return (new BigDecimal(value.toString().trim()));
3166         } catch (NumberFormatException ex) {
3167             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.doublefail").toString(),
3168                 new Object[] {value.toString().trim(), columnIndex}));
3169         }
3170     }
3171 
3172     /**
3173      * Retrieves the value of the designated column in the current row
3174      * of this <code>CachedRowSetImpl</code> object as a
3175      * <code>java.math.BigDecimal</code> object.
3176      *
3177      * @param columnName a <code>String</code> object that must match the
3178      *        SQL name of a column in this rowset, ignoring case
3179      * @return a <code>java.math.BigDecimal</code> value with full precision;
3180      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3181      * @throws SQLException if (1) the given column name is not the name of
3182      * a column in this rowset, (2) the cursor is not on one of
3183      * this rowset's rows or its insert row, or (3) the designated
3184      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
3185      * BIGINT, REAL, FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT CHAR,
3186      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
3187      * designates the recommended return type that this method is used to
3188      * retrieve
3189      * @see #getBigDecimal(int)
3190      */
3191     public BigDecimal getBigDecimal(String columnName) throws SQLException {
3192         return getBigDecimal(getColIdxByName(columnName));
3193     }
3194 
3195     //---------------------------------------------------------------------
3196     // Traversal/Positioning
3197     //---------------------------------------------------------------------
3198 
3199     /**
3200      * Returns the number of rows in this <code>CachedRowSetImpl</code> object.
3201      *
3202      * @return number of rows in the rowset
3203      */
3204     public int size() {
3205         return numRows;
3206     }
3207 
3208     /**
3209      * Indicates whether the cursor is before the first row in this
3210      * <code>CachedRowSetImpl</code> object.
3211      *
3212      * @return <code>true</code> if the cursor is before the first row;
3213      *         <code>false</code> otherwise or if the rowset contains no rows
3214      * @throws SQLException if an error occurs
3215      */
3216     public boolean isBeforeFirst() throws SQLException {
3217         if (cursorPos == 0 && numRows > 0) {
3218             return true;
3219         } else {
3220             return false;
3221         }
3222     }
3223 
3224     /**
3225      * Indicates whether the cursor is after the last row in this
3226      * <code>CachedRowSetImpl</code> object.
3227      *
3228      * @return <code>true</code> if the cursor is after the last row;
3229      *         <code>false</code> otherwise or if the rowset contains no rows
3230      * @throws SQLException if an error occurs
3231      */
3232     public boolean isAfterLast() throws SQLException {
3233         if (cursorPos == numRows+1 && numRows > 0) {
3234             return true;
3235         } else {
3236             return false;
3237         }
3238     }
3239 
3240     /**
3241      * Indicates whether the cursor is on the first row in this
3242      * <code>CachedRowSetImpl</code> object.
3243      *
3244      * @return <code>true</code> if the cursor is on the first row;
3245      *         <code>false</code> otherwise or if the rowset contains no rows
3246      * @throws SQLException if an error occurs
3247      */
3248     public boolean isFirst() throws SQLException {
3249         // this becomes nasty because of deletes.
3250         int saveCursorPos = cursorPos;
3251         int saveAbsoluteCursorPos = absolutePos;
3252         internalFirst();
3253         if (cursorPos == saveCursorPos) {
3254             return true;
3255         } else {
3256             cursorPos = saveCursorPos;
3257             absolutePos = saveAbsoluteCursorPos;
3258             return false;
3259         }
3260     }
3261 
3262     /**
3263      * Indicates whether the cursor is on the last row in this
3264      * <code>CachedRowSetImpl</code> object.
3265      * <P>
3266      * Note: Calling the method <code>isLast</code> may be expensive
3267      * because the JDBC driver might need to fetch ahead one row in order
3268      * to determine whether the current row is the last row in this rowset.
3269      *
3270      * @return <code>true</code> if the cursor is on the last row;
3271      *         <code>false</code> otherwise or if this rowset contains no rows
3272      * @throws SQLException if an error occurs
3273      */
3274     public boolean isLast() throws SQLException {
3275         int saveCursorPos = cursorPos;
3276         int saveAbsoluteCursorPos = absolutePos;
3277         boolean saveShowDeleted = getShowDeleted();
3278         setShowDeleted(true);
3279         internalLast();
3280         if (cursorPos == saveCursorPos) {
3281             setShowDeleted(saveShowDeleted);
3282             return true;
3283         } else {
3284             setShowDeleted(saveShowDeleted);
3285             cursorPos = saveCursorPos;
3286             absolutePos = saveAbsoluteCursorPos;
3287             return false;
3288         }
3289     }
3290 
3291     /**
3292      * Moves this <code>CachedRowSetImpl</code> object's cursor to the front of
3293      * the rowset, just before the first row. This method has no effect if
3294      * this rowset contains no rows.
3295      *
3296      * @throws SQLException if an error occurs or the type of this rowset
3297      *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3298      */
3299     public void beforeFirst() throws SQLException {
3300        if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3301             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.beforefirst").toString());
3302         }
3303         cursorPos = 0;
3304         absolutePos = 0;
3305         notifyCursorMoved();
3306     }
3307 
3308     /**
3309      * Moves this <code>CachedRowSetImpl</code> object's cursor to the end of
3310      * the rowset, just after the last row. This method has no effect if
3311      * this rowset contains no rows.
3312      *
3313      * @throws SQLException if an error occurs
3314      */
3315     public void afterLast() throws SQLException {
3316         if (numRows > 0) {
3317             cursorPos = numRows + 1;
3318             absolutePos = 0;
3319             notifyCursorMoved();
3320         }
3321     }
3322 
3323     /**
3324      * Moves this <code>CachedRowSetImpl</code> object's cursor to the first row
3325      * and returns <code>true</code> if the operation was successful.  This
3326      * method also notifies registered listeners that the cursor has moved.
3327      *
3328      * @return <code>true</code> if the cursor is on a valid row;
3329      *         <code>false</code> otherwise or if there are no rows in this
3330      *         <code>CachedRowSetImpl</code> object
3331      * @throws SQLException if the type of this rowset
3332      *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3333      */
3334     public boolean first() throws SQLException {
3335         if(getType() == ResultSet.TYPE_FORWARD_ONLY) {
3336             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.first").toString());
3337         }
3338 
3339         // move and notify
3340         boolean ret = this.internalFirst();
3341         notifyCursorMoved();
3342 
3343         return ret;
3344     }
3345 
3346     /**
3347      * Moves this <code>CachedRowSetImpl</code> object's cursor to the first
3348      * row and returns <code>true</code> if the operation is successful.
3349      * <P>
3350      * This method is called internally by the methods <code>first</code>,
3351      * <code>isFirst</code>, and <code>absolute</code>.
3352      * It in turn calls the method <code>internalNext</code> in order to
3353      * handle the case where the first row is a deleted row that is not visible.
3354      * <p>
3355      * This is a implementation only method and is not required as a standard
3356      * implementation of the <code>CachedRowSet</code> interface.
3357      *
3358      * @return <code>true</code> if the cursor moved to the first row;
3359      *         <code>false</code> otherwise
3360      * @throws SQLException if an error occurs
3361      */
3362     protected boolean internalFirst() throws SQLException {
3363         boolean ret = false;
3364 
3365         if (numRows > 0) {
3366             cursorPos = 1;
3367             if ((getShowDeleted() == false) && (rowDeleted() == true)) {
3368                 ret = internalNext();
3369             } else {
3370                 ret = true;
3371             }
3372         }
3373 
3374         if (ret == true)
3375             absolutePos = 1;
3376         else
3377             absolutePos = 0;
3378 
3379         return ret;
3380     }
3381 
3382     /**
3383      * Moves this <code>CachedRowSetImpl</code> object's cursor to the last row
3384      * and returns <code>true</code> if the operation was successful.  This
3385      * method also notifies registered listeners that the cursor has moved.
3386      *
3387      * @return <code>true</code> if the cursor is on a valid row;
3388      *         <code>false</code> otherwise or if there are no rows in this
3389      *         <code>CachedRowSetImpl</code> object
3390      * @throws SQLException if the type of this rowset
3391      *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3392      */
3393     public boolean last() throws SQLException {
3394         if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3395             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.last").toString());
3396         }
3397 
3398         // move and notify
3399         boolean ret = this.internalLast();
3400         notifyCursorMoved();
3401 
3402         return ret;
3403     }
3404 
3405     /**
3406      * Moves this <code>CachedRowSetImpl</code> object's cursor to the last
3407      * row and returns <code>true</code> if the operation is successful.
3408      * <P>
3409      * This method is called internally by the method <code>last</code>
3410      * when rows have been deleted and the deletions are not visible.
3411      * The method <code>internalLast</code> handles the case where the
3412      * last row is a deleted row that is not visible by in turn calling
3413      * the method <code>internalPrevious</code>.
3414      * <p>
3415      * This is a implementation only method and is not required as a standard
3416      * implementation of the <code>CachedRowSet</code> interface.
3417      *
3418      * @return <code>true</code> if the cursor moved to the last row;
3419      *         <code>false</code> otherwise
3420      * @throws SQLException if an error occurs
3421      */
3422     protected boolean internalLast() throws SQLException {
3423         boolean ret = false;
3424 
3425         if (numRows > 0) {
3426             cursorPos = numRows;
3427             if ((getShowDeleted() == false) && (rowDeleted() == true)) {
3428                 ret = internalPrevious();
3429             } else {
3430                 ret = true;
3431             }
3432         }
3433         if (ret == true)
3434             absolutePos = numRows - numDeleted;
3435         else
3436             absolutePos = 0;
3437         return ret;
3438     }
3439 
3440     /**
3441      * Returns the number of the current row in this <code>CachedRowSetImpl</code>
3442      * object. The first row is number 1, the second number 2, and so on.
3443      *
3444      * @return the number of the current row;  <code>0</code> if there is no
3445      *         current row
3446      * @throws SQLException if an error occurs; or if the <code>CacheRowSetImpl</code>
3447      *         is empty
3448      */
3449     public int getRow() throws SQLException {
3450         // are we on a valid row? Valid rows are between first and last
3451         if (numRows > 0 &&
3452         cursorPos > 0 &&
3453         cursorPos < (numRows + 1) &&
3454         (getShowDeleted() == false && rowDeleted() == false)) {
3455             return absolutePos;
3456         } else if (getShowDeleted() == true) {
3457             return cursorPos;
3458         } else {
3459             return 0;
3460         }
3461     }
3462 
3463     /**
3464      * Moves this <code>CachedRowSetImpl</code> object's cursor to the row number
3465      * specified.
3466      *
3467      * <p>If the number is positive, the cursor moves to an absolute row with
3468      * respect to the beginning of the rowset.  The first row is row 1, the second
3469      * is row 2, and so on.  For example, the following command, in which
3470      * <code>crs</code> is a <code>CachedRowSetImpl</code> object, moves the cursor
3471      * to the fourth row, starting from the beginning of the rowset.
3472      * <PRE><code>
3473      *
3474      *    crs.absolute(4);
3475      *
3476      * </code> </PRE>
3477      * <P>
3478      * If the number is negative, the cursor moves to an absolute row position
3479      * with respect to the end of the rowset.  For example, calling
3480      * <code>absolute(-1)</code> positions the cursor on the last row,
3481      * <code>absolute(-2)</code> moves it on the next-to-last row, and so on.
3482      * If the <code>CachedRowSetImpl</code> object <code>crs</code> has five rows,
3483      * the following command moves the cursor to the fourth-to-last row, which
3484      * in the case of a  rowset with five rows, is also the second row, counting
3485      * from the beginning.
3486      * <PRE><code>
3487      *
3488      *    crs.absolute(-4);
3489      *
3490      * </code> </PRE>
3491      *
3492      * If the number specified is larger than the number of rows, the cursor
3493      * will move to the position after the last row. If the number specified
3494      * would move the cursor one or more rows before the first row, the cursor
3495      * moves to the position before the first row.
3496      * <P>
3497      * Note: Calling <code>absolute(1)</code> is the same as calling the
3498      * method <code>first()</code>.  Calling <code>absolute(-1)</code> is the
3499      * same as calling <code>last()</code>.
3500      *
3501      * @param row a positive number to indicate the row, starting row numbering from
3502      *        the first row, which is <code>1</code>; a negative number to indicate
3503      *        the row, starting row numbering from the last row, which is
3504      *        <code>-1</code>; it must not be <code>0</code>
3505      * @return <code>true</code> if the cursor is on the rowset; <code>false</code>
3506      *         otherwise
3507      * @throws SQLException if the given cursor position is <code>0</code> or the
3508      *            type of this rowset is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3509      */
3510     public boolean absolute( int row ) throws SQLException {
3511         if (row == 0 || getType() == ResultSet.TYPE_FORWARD_ONLY) {
3512             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.absolute").toString());
3513         }
3514 
3515         if (row > 0) { // we are moving foward
3516             if (row > numRows) {
3517                 // fell off the end
3518                 afterLast();
3519                 return false;
3520             } else {
3521                 if (absolutePos <= 0)
3522                     internalFirst();
3523             }
3524         } else { // we are moving backward
3525             if (cursorPos + row < 0) {
3526                 // fell off the front
3527                 beforeFirst();
3528                 return false;
3529             } else {
3530                 if (absolutePos >= 0)
3531                     internalLast();
3532             }
3533         }
3534 
3535         // Now move towards the absolute row that we're looking for
3536         while (absolutePos != row) {
3537             if (absolutePos < row) {
3538                 if (!internalNext())
3539                     break;
3540             }
3541             else {
3542                 if (!internalPrevious())
3543                     break;
3544             }
3545         }
3546 
3547         notifyCursorMoved();
3548 
3549         if (isAfterLast() || isBeforeFirst()) {
3550             return false;
3551         } else {
3552             return true;
3553         }
3554     }
3555 
3556     /**
3557      * Moves the cursor the specified number of rows from the current
3558      * position, with a positive number moving it forward and a
3559      * negative number moving it backward.
3560      * <P>
3561      * If the number is positive, the cursor moves the specified number of
3562      * rows toward the end of the rowset, starting at the current row.
3563      * For example, the following command, in which
3564      * <code>crs</code> is a <code>CachedRowSetImpl</code> object with 100 rows,
3565      * moves the cursor forward four rows from the current row.  If the
3566      * current row is 50, the cursor would move to row 54.
3567      * <PRE><code>
3568      *
3569      *    crs.relative(4);
3570      *
3571      * </code> </PRE>
3572      * <P>
3573      * If the number is negative, the cursor moves back toward the beginning
3574      * the specified number of rows, starting at the current row.
3575      * For example, calling the method
3576      * <code>absolute(-1)</code> positions the cursor on the last row,
3577      * <code>absolute(-2)</code> moves it on the next-to-last row, and so on.
3578      * If the <code>CachedRowSetImpl</code> object <code>crs</code> has five rows,
3579      * the following command moves the cursor to the fourth-to-last row, which
3580      * in the case of a  rowset with five rows, is also the second row
3581      * from the beginning.
3582      * <PRE><code>
3583      *
3584      *    crs.absolute(-4);
3585      *
3586      * </code> </PRE>
3587      *
3588      * If the number specified is larger than the number of rows, the cursor
3589      * will move to the position after the last row. If the number specified
3590      * would move the cursor one or more rows before the first row, the cursor
3591      * moves to the position before the first row. In both cases, this method
3592      * throws an <code>SQLException</code>.
3593      * <P>
3594      * Note: Calling <code>absolute(1)</code> is the same as calling the
3595      * method <code>first()</code>.  Calling <code>absolute(-1)</code> is the
3596      * same as calling <code>last()</code>.  Calling <code>relative(0)</code>
3597      * is valid, but it does not change the cursor position.
3598      *
3599      * @param rows an <code>int</code> indicating the number of rows to move
3600      *             the cursor, starting at the current row; a positive number
3601      *             moves the cursor forward; a negative number moves the cursor
3602      *             backward; must not move the cursor past the valid
3603      *             rows
3604      * @return <code>true</code> if the cursor is on a row in this
3605      *         <code>CachedRowSetImpl</code> object; <code>false</code>
3606      *         otherwise
3607      * @throws SQLException if there are no rows in this rowset, the cursor is
3608      *         positioned either before the first row or after the last row, or
3609      *         the rowset is type <code>ResultSet.TYPE_FORWARD_ONLY</code>
3610      */
3611     public boolean relative(int rows) throws SQLException {
3612         if (numRows == 0 || isBeforeFirst() ||
3613         isAfterLast() || getType() == ResultSet.TYPE_FORWARD_ONLY) {
3614             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.relative").toString());
3615         }
3616 
3617         if (rows == 0) {
3618             return true;
3619         }
3620 
3621         if (rows > 0) { // we are moving forward
3622             if (cursorPos + rows > numRows) {
3623                 // fell off the end
3624                 afterLast();
3625             } else {
3626                 for (int i=0; i < rows; i++) {
3627                     if (!internalNext())
3628                         break;
3629                 }
3630             }
3631         } else { // we are moving backward
3632             if (cursorPos + rows < 0) {
3633                 // fell off the front
3634                 beforeFirst();
3635             } else {
3636                 for (int i=rows; i < 0; i++) {
3637                     if (!internalPrevious())
3638                         break;
3639                 }
3640             }
3641         }
3642         notifyCursorMoved();
3643 
3644         if (isAfterLast() || isBeforeFirst()) {
3645             return false;
3646         } else {
3647             return true;
3648         }
3649     }
3650 
3651     /**
3652      * Moves this <code>CachedRowSetImpl</code> object's cursor to the
3653      * previous row and returns <code>true</code> if the cursor is on
3654      * a valid row or <code>false</code> if it is not.
3655      * This method also notifies all listeners registered with this
3656      * <code>CachedRowSetImpl</code> object that its cursor has moved.
3657      * <P>
3658      * Note: calling the method <code>previous()</code> is not the same
3659      * as calling the method <code>relative(-1)</code>.  This is true
3660      * because it is possible to call <code>previous()</code> from the insert
3661      * row, from after the last row, or from the current row, whereas
3662      * <code>relative</code> may only be called from the current row.
3663      * <P>
3664      * The method <code>previous</code> may used in a <code>while</code>
3665      * loop to iterate through a rowset starting after the last row
3666      * and moving toward the beginning. The loop ends when <code>previous</code>
3667      * returns <code>false</code>, meaning that there are no more rows.
3668      * For example, the following code fragment retrieves all the data in
3669      * the <code>CachedRowSetImpl</code> object <code>crs</code>, which has
3670      * three columns.  Note that the cursor must initially be positioned
3671      * after the last row so that the first call to the method
3672      * <code>previous</code> places the cursor on the last line.
3673      * <PRE> <code>
3674      *
3675      *     crs.afterLast();
3676      *     while (previous()) {
3677      *         String name = crs.getString(1);
3678      *         int age = crs.getInt(2);
3679      *         short ssn = crs.getShort(3);
3680      *         System.out.println(name + "   " + age + "   " + ssn);
3681      *     }
3682      *
3683      * </code> </PRE>
3684      * This method throws an <code>SQLException</code> if the cursor is not
3685      * on a row in the rowset, before the first row, or after the last row.
3686      *
3687      * @return <code>true</code> if the cursor is on a valid row;
3688      *         <code>false</code> if it is before the first row or after the
3689      *         last row
3690      * @throws SQLException if the cursor is not on a valid position or the
3691      *           type of this rowset is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3692      */
3693     public boolean previous() throws SQLException {
3694         if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3695             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.last").toString());
3696         }
3697         /*
3698          * make sure things look sane. The cursor must be
3699          * positioned in the rowset or before first (0) or
3700          * after last (numRows + 1)
3701          */
3702         if (cursorPos < 0 || cursorPos > numRows + 1) {
3703             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
3704         }
3705         // move and notify
3706         boolean ret = this.internalPrevious();
3707         notifyCursorMoved();
3708 
3709         return ret;
3710     }
3711 
3712     /**
3713      * Moves the cursor to the previous row in this <code>CachedRowSetImpl</code>
3714      * object, skipping past deleted rows that are not visible; returns
3715      * <code>true</code> if the cursor is on a row in this rowset and
3716      * <code>false</code> when the cursor goes before the first row.
3717      * <P>
3718      * This method is called internally by the method <code>previous</code>.
3719      * <P>
3720      * This is a implementation only method and is not required as a standard
3721      * implementation of the <code>CachedRowSet</code> interface.
3722      *
3723      * @return <code>true</code> if the cursor is on a row in this rowset;
3724      *         <code>false</code> when the cursor reaches the position before
3725      *         the first row
3726      * @throws SQLException if an error occurs
3727      */
3728     protected boolean internalPrevious() throws SQLException {
3729         boolean ret = false;
3730 
3731         do {
3732             if (cursorPos > 1) {
3733                 --cursorPos;
3734                 ret = true;
3735             } else if (cursorPos == 1) {
3736                 // decrement to before first
3737                 --cursorPos;
3738                 ret = false;
3739                 break;
3740             }
3741         } while ((getShowDeleted() == false) && (rowDeleted() == true));
3742 
3743         /*
3744          * Each call to internalPrevious may move the cursor
3745          * over multiple rows, the absolute position moves one row
3746          */
3747         if (ret == true)
3748             --absolutePos;
3749         else
3750             absolutePos = 0;
3751 
3752         return ret;
3753     }
3754 
3755 
3756     //---------------------------------------------------------------------
3757     // Updates
3758     //---------------------------------------------------------------------
3759 
3760     /**
3761      * Indicates whether the current row of this <code>CachedRowSetImpl</code>
3762      * object has been updated.  The value returned
3763      * depends on whether this rowset can detect updates: <code>false</code>
3764      * will always be returned if it does not detect updates.
3765      *
3766      * @return <code>true</code> if the row has been visibly updated
3767      *         by the owner or another and updates are detected;
3768      *         <code>false</code> otherwise
3769      * @throws SQLException if the cursor is on the insert row or not
3770      *            not on a valid row
3771      *
3772      * @see DatabaseMetaData#updatesAreDetected
3773      */
3774     public boolean rowUpdated() throws SQLException {
3775         // make sure the cursor is on a valid row
3776         checkCursor();
3777         if (onInsertRow == true) {
3778             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3779         }
3780         return(((Row)getCurrentRow()).getUpdated());
3781     }
3782 
3783     /**
3784      * Indicates whether the designated column of the current row of
3785      * this <code>CachedRowSetImpl</code> object has been updated. The
3786      * value returned depends on whether this rowset can detcted updates:
3787      * <code>false</code> will always be returned if it does not detect updates.
3788      *
3789      * @param idx the index identifier of the column that may be have been updated.
3790      * @return <code>true</code> is the designated column has been updated
3791      * and the rowset detects updates; <code>false</code> if the rowset has not
3792      * been updated or the rowset does not detect updates
3793      * @throws SQLException if the cursor is on the insert row or not
3794      *          on a valid row
3795      * @see DatabaseMetaData#updatesAreDetected
3796      */
3797     public boolean columnUpdated(int idx) throws SQLException {
3798         // make sure the cursor is on a valid row
3799         checkCursor();
3800         if (onInsertRow == true) {
3801             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3802         }
3803         return (((Row)getCurrentRow()).getColUpdated(idx - 1));
3804     }
3805 
3806     /**
3807      * Indicates whether the designated column of the current row of
3808      * this <code>CachedRowSetImpl</code> object has been updated. The
3809      * value returned depends on whether this rowset can detcted updates:
3810      * <code>false</code> will always be returned if it does not detect updates.
3811      *
3812      * @param columnName the <code>String</code> column name column that may be have
3813      * been updated.
3814      * @return <code>true</code> is the designated column has been updated
3815      * and the rowset detects updates; <code>false</code> if the rowset has not
3816      * been updated or the rowset does not detect updates
3817      * @throws SQLException if the cursor is on the insert row or not
3818      *          on a valid row
3819      * @see DatabaseMetaData#updatesAreDetected
3820      */
3821     public boolean columnUpdated(String columnName) throws SQLException {
3822         return columnUpdated(getColIdxByName(columnName));
3823     }
3824 
3825     /**
3826      * Indicates whether the current row has been inserted.  The value returned
3827      * depends on whether or not the rowset can detect visible inserts.
3828      *
3829      * @return <code>true</code> if a row has been inserted and inserts are detected;
3830      *         <code>false</code> otherwise
3831      * @throws SQLException if the cursor is on the insert row or not
3832      *            not on a valid row
3833      *
3834      * @see DatabaseMetaData#insertsAreDetected
3835      */
3836     public boolean rowInserted() throws SQLException {
3837         // make sure the cursor is on a valid row
3838         checkCursor();
3839         if (onInsertRow == true) {
3840             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3841         }
3842         return(((Row)getCurrentRow()).getInserted());
3843     }
3844 
3845     /**
3846      * Indicates whether the current row has been deleted.  A deleted row
3847      * may leave a visible "hole" in a rowset.  This method can be used to
3848      * detect such holes if the rowset can detect deletions. This method
3849      * will always return <code>false</code> if this rowset cannot detect
3850      * deletions.
3851      *
3852      * @return <code>true</code> if (1)the current row is blank, indicating that
3853      *         the row has been deleted, and (2)deletions are detected;
3854      *         <code>false</code> otherwise
3855      * @throws SQLException if the cursor is on a valid row in this rowset
3856      * @see DatabaseMetaData#deletesAreDetected
3857      */
3858     public boolean rowDeleted() throws SQLException {
3859         // make sure the cursor is on a valid row
3860 
3861         if (isAfterLast() == true ||
3862         isBeforeFirst() == true ||
3863         onInsertRow == true) {
3864 
3865             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
3866         }
3867         return(((Row)getCurrentRow()).getDeleted());
3868     }
3869 
3870     /**
3871      * Indicates whether the given SQL data type is a numberic type.
3872      *
3873      * @param type one of the constants from <code>java.sql.Types</code>
3874      * @return <code>true</code> if the given type is <code>NUMERIC</code>,'
3875      *         <code>DECIMAL</code>, <code>BIT</code>, <code>TINYINT</code>,
3876      *         <code>SMALLINT</code>, <code>INTEGER</code>, <code>BIGINT</code>,
3877      *         <code>REAL</code>, <code>DOUBLE</code>, or <code>FLOAT</code>;
3878      *         <code>false</code> otherwise
3879      */
3880     private boolean isNumeric(int type) {
3881         switch (type) {
3882             case java.sql.Types.NUMERIC:
3883             case java.sql.Types.DECIMAL:
3884             case java.sql.Types.BIT:
3885             case java.sql.Types.TINYINT:
3886             case java.sql.Types.SMALLINT:
3887             case java.sql.Types.INTEGER:
3888             case java.sql.Types.BIGINT:
3889             case java.sql.Types.REAL:
3890             case java.sql.Types.DOUBLE:
3891             case java.sql.Types.FLOAT:
3892                 return true;
3893             default:
3894                 return false;
3895         }
3896     }
3897 
3898     /**
3899      * Indicates whether the given SQL data type is a string type.
3900      *
3901      * @param type one of the constants from <code>java.sql.Types</code>
3902      * @return <code>true</code> if the given type is <code>CHAR</code>,'
3903      *         <code>VARCHAR</code>, or <code>LONGVARCHAR</code>;
3904      *         <code>false</code> otherwise
3905      */
3906     private boolean isString(int type) {
3907         switch (type) {
3908             case java.sql.Types.CHAR:
3909             case java.sql.Types.VARCHAR:
3910             case java.sql.Types.LONGVARCHAR:
3911                 return true;
3912             default:
3913                 return false;
3914         }
3915     }
3916 
3917     /**
3918      * Indicates whether the given SQL data type is a binary type.
3919      *
3920      * @param type one of the constants from <code>java.sql.Types</code>
3921      * @return <code>true</code> if the given type is <code>BINARY</code>,'
3922      *         <code>VARBINARY</code>, or <code>LONGVARBINARY</code>;
3923      *         <code>false</code> otherwise
3924      */
3925     private boolean isBinary(int type) {
3926         switch (type) {
3927             case java.sql.Types.BINARY:
3928             case java.sql.Types.VARBINARY:
3929             case java.sql.Types.LONGVARBINARY:
3930                 return true;
3931             default:
3932                 return false;
3933         }
3934     }
3935 
3936     /**
3937      * Indicates whether the given SQL data type is a temporal type.
3938      * This method is called internally by the conversion methods
3939      * <code>convertNumeric</code> and <code>convertTemporal</code>.
3940      *
3941      * @param type one of the constants from <code>java.sql.Types</code>
3942      * @return <code>true</code> if the given type is <code>DATE</code>,
3943      *         <code>TIME</code>, or <code>TIMESTAMP</code>;
3944      *         <code>false</code> otherwise
3945      */
3946     private boolean isTemporal(int type) {
3947         switch (type) {
3948             case java.sql.Types.DATE:
3949             case java.sql.Types.TIME:
3950             case java.sql.Types.TIMESTAMP:
3951                 return true;
3952             default:
3953                 return false;
3954         }
3955     }
3956 
3957     /**
3958      * Indicates whether the given SQL data type is a boolean type.
3959      * This method is called internally by the conversion methods
3960      * <code>convertNumeric</code> and <code>convertBoolean</code>.
3961      *
3962      * @param type one of the constants from <code>java.sql.Types</code>
3963      * @return <code>true</code> if the given type is <code>BIT</code>,
3964      *         , or <code>BOOLEAN</code>;
3965      *         <code>false</code> otherwise
3966      */
3967     private boolean isBoolean(int type) {
3968         switch (type) {
3969             case java.sql.Types.BIT:
3970             case java.sql.Types.BOOLEAN:
3971                 return true;
3972             default:
3973                 return false;
3974         }
3975     }
3976 
3977 
3978     /**
3979      * Converts the given <code>Object</code> in the Java programming language
3980      * to the standard mapping for the specified SQL target data type.
3981      * The conversion must be to a string or numeric type, but there are no
3982      * restrictions on the type to be converted.  If the source type and target
3983      * type are the same, the given object is simply returned.
3984      *
3985      * @param srcObj the <code>Object</code> in the Java programming language
3986      *               that is to be converted to the target type
3987      * @param srcType the data type that is the standard mapping in SQL of the
3988      *                object to be converted; must be one of the constants in
3989      *                <code>java.sql.Types</code>
3990      * @param trgType the SQL data type to which to convert the given object;
3991      *                must be one of the following constants in
3992      *                <code>java.sql.Types</code>: <code>NUMERIC</code>,
3993      *         <code>DECIMAL</code>, <code>BIT</code>, <code>TINYINT</code>,
3994      *         <code>SMALLINT</code>, <code>INTEGER</code>, <code>BIGINT</code>,
3995      *         <code>REAL</code>, <code>DOUBLE</code>, <code>FLOAT</code>,
3996      *         <code>VARCHAR</code>, <code>LONGVARCHAR</code>, or <code>CHAR</code>
3997      * @return an <code>Object</code> value.that is
3998      *         the standard object mapping for the target SQL type
3999      * @throws SQLException if the given target type is not one of the string or
4000      *         numeric types in <code>java.sql.Types</code>
4001      */
4002     private Object convertNumeric(Object srcObj, int srcType,
4003     int trgType) throws SQLException {
4004 
4005         if (srcType == trgType) {
4006             return srcObj;
4007         }
4008 
4009         if (isNumeric(trgType) == false && isString(trgType) == false) {
4010             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4011         }
4012 
4013         try {
4014             switch (trgType) {
4015                 case java.sql.Types.BIT:
4016                     Integer i = Integer.valueOf(srcObj.toString().trim());
4017                     return i.equals(0) ?
4018                     Boolean.valueOf(false) :
4019                         Boolean.valueOf(true);
4020                 case java.sql.Types.TINYINT:
4021                     return Byte.valueOf(srcObj.toString().trim());
4022                 case java.sql.Types.SMALLINT:
4023                     return Short.valueOf(srcObj.toString().trim());
4024                 case java.sql.Types.INTEGER:
4025                     return Integer.valueOf(srcObj.toString().trim());
4026                 case java.sql.Types.BIGINT:
4027                     return Long.valueOf(srcObj.toString().trim());
4028                 case java.sql.Types.NUMERIC:
4029                 case java.sql.Types.DECIMAL:
4030                     return new BigDecimal(srcObj.toString().trim());
4031                 case java.sql.Types.REAL:
4032                 case java.sql.Types.FLOAT:
4033                     return Float.valueOf(srcObj.toString().trim());
4034                 case java.sql.Types.DOUBLE:
4035                     return Double.valueOf(srcObj.toString().trim());
4036                 case java.sql.Types.CHAR:
4037                 case java.sql.Types.VARCHAR:
4038                 case java.sql.Types.LONGVARCHAR:
4039                     return srcObj.toString();
4040                 default:
4041                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString()+ trgType);
4042             }
4043         } catch (NumberFormatException ex) {
4044             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4045         }
4046     }
4047 
4048     /**
4049      * Converts the given <code>Object</code> in the Java programming language
4050      * to the standard object mapping for the specified SQL target data type.
4051      * The conversion must be to a string or temporal type, and there are also
4052      * restrictions on the type to be converted.
4053      * <P>
4054      * <TABLE ALIGN="CENTER" BORDER CELLPADDING=10 BORDERCOLOR="#0000FF"
4055      * <CAPTION ALIGN="CENTER"><B>Parameters and Return Values</B></CAPTION>
4056      * <TR>
4057      *   <TD><B>Source SQL Type</B>
4058      *   <TD><B>Target SQL Type</B>
4059      *   <TD><B>Object Returned</B>
4060      * </TR>
4061      * <TR>
4062      *   <TD><code>TIMESTAMP</code>
4063      *   <TD><code>DATE</code>
4064      *   <TD><code>java.sql.Date</code>
4065      * </TR>
4066      * <TR>
4067      *   <TD><code>TIMESTAMP</code>
4068      *   <TD><code>TIME</code>
4069      *   <TD><code>java.sql.Time</code>
4070      * </TR>
4071      * <TR>
4072      *   <TD><code>TIME</code>
4073      *   <TD><code>TIMESTAMP</code>
4074      *   <TD><code>java.sql.Timestamp</code>
4075      * </TR>
4076      * <TR>
4077      *   <TD><code>DATE</code>, <code>TIME</code>, or <code>TIMESTAMP</code>
4078      *   <TD><code>CHAR</code>, <code>VARCHAR</code>, or <code>LONGVARCHAR</code>
4079      *   <TD><code>java.lang.String</code>
4080      * </TR>
4081      * </TABLE>
4082      * <P>
4083      * If the source type and target type are the same,
4084      * the given object is simply returned.
4085      *
4086      * @param srcObj the <code>Object</code> in the Java programming language
4087      *               that is to be converted to the target type
4088      * @param srcType the data type that is the standard mapping in SQL of the
4089      *                object to be converted; must be one of the constants in
4090      *                <code>java.sql.Types</code>
4091      * @param trgType the SQL data type to which to convert the given object;
4092      *                must be one of the following constants in
4093      *                <code>java.sql.Types</code>: <code>DATE</code>,
4094      *         <code>TIME</code>, <code>TIMESTAMP</code>, <code>CHAR</code>,
4095      *         <code>VARCHAR</code>, or <code>LONGVARCHAR</code>
4096      * @return an <code>Object</code> value.that is
4097      *         the standard object mapping for the target SQL type
4098      * @throws SQLException if the given target type is not one of the string or
4099      *         temporal types in <code>java.sql.Types</code>
4100      */
4101     private Object convertTemporal(Object srcObj,
4102     int srcType, int trgType) throws SQLException {
4103 
4104         if (srcType == trgType) {
4105             return srcObj;
4106         }
4107 
4108         if (isNumeric(trgType) == true ||
4109         (isString(trgType) == false && isTemporal(trgType) == false)) {
4110             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4111         }
4112 
4113         try {
4114             switch (trgType) {
4115                 case java.sql.Types.DATE:
4116                     if (srcType == java.sql.Types.TIMESTAMP) {
4117                         return new java.sql.Date(((java.sql.Timestamp)srcObj).getTime());
4118                     } else {
4119                         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4120                     }
4121                 case java.sql.Types.TIMESTAMP:
4122                     if (srcType == java.sql.Types.TIME) {
4123                         return new Timestamp(((java.sql.Time)srcObj).getTime());
4124                     } else {
4125                         return new Timestamp(((java.sql.Date)srcObj).getTime());
4126                     }
4127                 case java.sql.Types.TIME:
4128                     if (srcType == java.sql.Types.TIMESTAMP) {
4129                         return new Time(((java.sql.Timestamp)srcObj).getTime());
4130                     } else {
4131                         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4132                     }
4133                 case java.sql.Types.CHAR:
4134                 case java.sql.Types.VARCHAR:
4135                 case java.sql.Types.LONGVARCHAR:
4136                     return srcObj.toString();
4137                 default:
4138                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4139             }
4140         } catch (NumberFormatException ex) {
4141             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4142         }
4143 
4144     }
4145 
4146     /**
4147      * Converts the given <code>Object</code> in the Java programming language
4148      * to the standard mapping for the specified SQL target data type.
4149      * The conversion must be to a string or numeric type, but there are no
4150      * restrictions on the type to be converted.  If the source type and target
4151      * type are the same, the given object is simply returned.
4152      *
4153      * @param srcObj the <code>Object</code> in the Java programming language
4154      *               that is to be converted to the target type
4155      * @param srcType the data type that is the standard mapping in SQL of the
4156      *                object to be converted; must be one of the constants in
4157      *                <code>java.sql.Types</code>
4158      * @param trgType the SQL data type to which to convert the given object;
4159      *                must be one of the following constants in
4160      *                <code>java.sql.Types</code>: <code>BIT</code>,
4161      *         or <code>BOOLEAN</code>
4162      * @return an <code>Object</code> value.that is
4163      *         the standard object mapping for the target SQL type
4164      * @throws SQLException if the given target type is not one of the Boolean
4165      *         types in <code>java.sql.Types</code>
4166      */
4167     private Object convertBoolean(Object srcObj, int srcType,
4168     int trgType) throws SQLException {
4169 
4170         if (srcType == trgType) {
4171             return srcObj;
4172         }
4173 
4174         if (isNumeric(trgType) == true ||
4175         (isString(trgType) == false && isBoolean(trgType) == false)) {
4176             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4177         }
4178 
4179 
4180         try {
4181             switch (trgType) {
4182                 case java.sql.Types.BIT:
4183                     Integer i = Integer.valueOf(srcObj.toString().trim());
4184                     return i.equals(0) ?
4185                     Boolean.valueOf(false) :
4186                         Boolean.valueOf(true);
4187                 case java.sql.Types.BOOLEAN:
4188                     return Boolean.valueOf(srcObj.toString().trim());
4189                 default:
4190                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString()+ trgType);
4191             }
4192         } catch (NumberFormatException ex) {
4193             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4194         }
4195     }
4196 
4197     /**
4198      * Sets the designated nullable column in the current row or the
4199      * insert row of this <code>CachedRowSetImpl</code> object with
4200      * <code>null</code> value.
4201      * <P>
4202      * This method updates a column value in the current row or the insert
4203      * row of this rowset; however, another method must be called to complete
4204      * the update process. If the cursor is on a row in the rowset, the
4205      * method {@link #updateRow} must be called to mark the row as updated
4206      * and to notify listeners that the row has changed.
4207      * If the cursor is on the insert row, the method {@link #insertRow}
4208      * must be called to insert the new row into this rowset and to notify
4209      * listeners that a row has changed.
4210      * <P>
4211      * In order to propagate updates in this rowset to the underlying
4212      * data source, an application must call the method {@link #acceptChanges}
4213      * after it calls either <code>updateRow</code> or <code>insertRow</code>.
4214      *
4215      * @param columnIndex the first column is <code>1</code>, the second
4216      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4217      *        and equal to or less than the number of columns in this rowset
4218      * @throws SQLException if (1) the given column index is out of bounds,
4219      *            (2) the cursor is not on one of this rowset's rows or its
4220      *            insert row, or (3) this rowset is
4221      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4222      */
4223     public void updateNull(int columnIndex) throws SQLException {
4224         // sanity check.
4225         checkIndex(columnIndex);
4226         // make sure the cursor is on a valid row
4227         checkCursor();
4228 
4229         BaseRow row = getCurrentRow();
4230         row.setColumnObject(columnIndex, null);
4231 
4232     }
4233 
4234     /**
4235      * Sets the designated column in either the current row or the insert
4236      * row of this <code>CachedRowSetImpl</code> object with the given
4237      * <code>boolean</code> value.
4238      * <P>
4239      * This method updates a column value in the current row or the insert
4240      * row of this rowset, but it does not update the database.
4241      * If the cursor is on a row in the rowset, the
4242      * method {@link #updateRow} must be called to update the database.
4243      * If the cursor is on the insert row, the method {@link #insertRow}
4244      * must be called, which will insert the new row into both this rowset
4245      * and the database. Both of these methods must be called before the
4246      * cursor moves to another row.
4247      *
4248      * @param columnIndex the first column is <code>1</code>, the second
4249      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4250      *        and equal to or less than the number of columns in this rowset
4251      * @param x the new column value
4252      * @throws SQLException if (1) the given column index is out of bounds,
4253      *            (2) the cursor is not on one of this rowset's rows or its
4254      *            insert row, or (3) this rowset is
4255      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4256      */
4257     public void updateBoolean(int columnIndex, boolean x) throws SQLException {
4258         // sanity check.
4259         checkIndex(columnIndex);
4260         // make sure the cursor is on a valid row
4261         checkCursor();
4262         Object obj = convertBoolean(Boolean.valueOf(x),
4263         java.sql.Types.BIT,
4264         RowSetMD.getColumnType(columnIndex));
4265 
4266         getCurrentRow().setColumnObject(columnIndex, obj);
4267     }
4268 
4269     /**
4270      * Sets the designated column in either the current row or the insert
4271      * row of this <code>CachedRowSetImpl</code> object with the given
4272      * <code>byte</code> value.
4273      * <P>
4274      * This method updates a column value in the current row or the insert
4275      * row of this rowset, but it does not update the database.
4276      * If the cursor is on a row in the rowset, the
4277      * method {@link #updateRow} must be called to update the database.
4278      * If the cursor is on the insert row, the method {@link #insertRow}
4279      * must be called, which will insert the new row into both this rowset
4280      * and the database. Both of these methods must be called before the
4281      * cursor moves to another row.
4282      *
4283      * @param columnIndex the first column is <code>1</code>, the second
4284      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4285      *        and equal to or less than the number of columns in this rowset
4286      * @param x the new column value
4287      * @throws SQLException if (1) the given column index is out of bounds,
4288      *            (2) the cursor is not on one of this rowset's rows or its
4289      *            insert row, or (3) this rowset is
4290      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4291      */
4292     public void updateByte(int columnIndex, byte x) throws SQLException {
4293         // sanity check.
4294         checkIndex(columnIndex);
4295         // make sure the cursor is on a valid row
4296         checkCursor();
4297 
4298         Object obj = convertNumeric(Byte.valueOf(x),
4299         java.sql.Types.TINYINT,
4300         RowSetMD.getColumnType(columnIndex));
4301 
4302         getCurrentRow().setColumnObject(columnIndex, obj);
4303     }
4304 
4305     /**
4306      * Sets the designated column in either the current row or the insert
4307      * row of this <code>CachedRowSetImpl</code> object with the given
4308      * <code>short</code> value.
4309      * <P>
4310      * This method updates a column value in the current row or the insert
4311      * row of this rowset, but it does not update the database.
4312      * If the cursor is on a row in the rowset, the
4313      * method {@link #updateRow} must be called to update the database.
4314      * If the cursor is on the insert row, the method {@link #insertRow}
4315      * must be called, which will insert the new row into both this rowset
4316      * and the database. Both of these methods must be called before the
4317      * cursor moves to another row.
4318      *
4319      * @param columnIndex the first column is <code>1</code>, the second
4320      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4321      *        and equal to or less than the number of columns in this rowset
4322      * @param x the new column value
4323      * @throws SQLException if (1) the given column index is out of bounds,
4324      *            (2) the cursor is not on one of this rowset's rows or its
4325      *            insert row, or (3) this rowset is
4326      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4327      */
4328     public void updateShort(int columnIndex, short x) throws SQLException {
4329         // sanity check.
4330         checkIndex(columnIndex);
4331         // make sure the cursor is on a valid row
4332         checkCursor();
4333 
4334         Object obj = convertNumeric(Short.valueOf(x),
4335         java.sql.Types.SMALLINT,
4336         RowSetMD.getColumnType(columnIndex));
4337 
4338         getCurrentRow().setColumnObject(columnIndex, obj);
4339     }
4340 
4341     /**
4342      * Sets the designated column in either the current row or the insert
4343      * row of this <code>CachedRowSetImpl</code> object with the given
4344      * <code>int</code> value.
4345      * <P>
4346      * This method updates a column value in the current row or the insert
4347      * row of this rowset, but it does not update the database.
4348      * If the cursor is on a row in the rowset, the
4349      * method {@link #updateRow} must be called to update the database.
4350      * If the cursor is on the insert row, the method {@link #insertRow}
4351      * must be called, which will insert the new row into both this rowset
4352      * and the database. Both of these methods must be called before the
4353      * cursor moves to another row.
4354      *
4355      * @param columnIndex the first column is <code>1</code>, the second
4356      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4357      *        and equal to or less than the number of columns in this rowset
4358      * @param x the new column value
4359      * @throws SQLException if (1) the given column index is out of bounds,
4360      *            (2) the cursor is not on one of this rowset's rows or its
4361      *            insert row, or (3) this rowset is
4362      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4363      */
4364     public void updateInt(int columnIndex, int x) throws SQLException {
4365         // sanity check.
4366         checkIndex(columnIndex);
4367         // make sure the cursor is on a valid row
4368         checkCursor();
4369         Object obj = convertNumeric(x,
4370         java.sql.Types.INTEGER,
4371         RowSetMD.getColumnType(columnIndex));
4372 
4373         getCurrentRow().setColumnObject(columnIndex, obj);
4374     }
4375 
4376     /**
4377      * Sets the designated column in either the current row or the insert
4378      * row of this <code>CachedRowSetImpl</code> object with the given
4379      * <code>long</code> value.
4380      * <P>
4381      * This method updates a column value in the current row or the insert
4382      * row of this rowset, but it does not update the database.
4383      * If the cursor is on a row in the rowset, the
4384      * method {@link #updateRow} must be called to update the database.
4385      * If the cursor is on the insert row, the method {@link #insertRow}
4386      * must be called, which will insert the new row into both this rowset
4387      * and the database. Both of these methods must be called before the
4388      * cursor moves to another row.
4389      *
4390      * @param columnIndex the first column is <code>1</code>, the second
4391      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4392      *        and equal to or less than the number of columns in this rowset
4393      * @param x the new column value
4394      * @throws SQLException if (1) the given column index is out of bounds,
4395      *            (2) the cursor is not on one of this rowset's rows or its
4396      *            insert row, or (3) this rowset is
4397      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4398      */
4399     public void updateLong(int columnIndex, long x) throws SQLException {
4400         // sanity check.
4401         checkIndex(columnIndex);
4402         // make sure the cursor is on a valid row
4403         checkCursor();
4404 
4405         Object obj = convertNumeric(Long.valueOf(x),
4406         java.sql.Types.BIGINT,
4407         RowSetMD.getColumnType(columnIndex));
4408 
4409         getCurrentRow().setColumnObject(columnIndex, obj);
4410 
4411     }
4412 
4413     /**
4414      * Sets the designated column in either the current row or the insert
4415      * row of this <code>CachedRowSetImpl</code> object with the given
4416      * <code>float</code> value.
4417      * <P>
4418      * This method updates a column value in the current row or the insert
4419      * row of this rowset, but it does not update the database.
4420      * If the cursor is on a row in the rowset, the
4421      * method {@link #updateRow} must be called to update the database.
4422      * If the cursor is on the insert row, the method {@link #insertRow}
4423      * must be called, which will insert the new row into both this rowset
4424      * and the database. Both of these methods must be called before the
4425      * cursor moves to another row.
4426      *
4427      * @param columnIndex the first column is <code>1</code>, the second
4428      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4429      *        and equal to or less than the number of columns in this rowset
4430      * @param x the new column value
4431      * @throws SQLException if (1) the given column index is out of bounds,
4432      *            (2) the cursor is not on one of this rowset's rows or its
4433      *            insert row, or (3) this rowset is
4434      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4435      */
4436     public void updateFloat(int columnIndex, float x) throws SQLException {
4437         // sanity check.
4438         checkIndex(columnIndex);
4439         // make sure the cursor is on a valid row
4440         checkCursor();
4441 
4442         Object obj = convertNumeric(Float.valueOf(x),
4443         java.sql.Types.REAL,
4444         RowSetMD.getColumnType(columnIndex));
4445 
4446         getCurrentRow().setColumnObject(columnIndex, obj);
4447     }
4448 
4449     /**
4450      * Sets the designated column in either the current row or the insert
4451      * row of this <code>CachedRowSetImpl</code> object with the given
4452      * <code>double</code> value.
4453      *
4454      * This method updates a column value in either the current row or
4455      * the insert row of this rowset, but it does not update the
4456      * database.  If the cursor is on a row in the rowset, the
4457      * method {@link #updateRow} must be called to update the database.
4458      * If the cursor is on the insert row, the method {@link #insertRow}
4459      * must be called, which will insert the new row into both this rowset
4460      * and the database. Both of these methods must be called before the
4461      * cursor moves to another row.
4462      *
4463      * @param columnIndex the first column is <code>1</code>, the second
4464      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4465      *        and equal to or less than the number of columns in this rowset
4466      * @param x the new column value
4467      * @throws SQLException if (1) the given column index is out of bounds,
4468      *            (2) the cursor is not on one of this rowset's rows or its
4469      *            insert row, or (3) this rowset is
4470      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4471      */
4472     public void updateDouble(int columnIndex, double x) throws SQLException {
4473         // sanity check.
4474         checkIndex(columnIndex);
4475         // make sure the cursor is on a valid row
4476         checkCursor();
4477         Object obj = convertNumeric(Double.valueOf(x),
4478         java.sql.Types.DOUBLE,
4479         RowSetMD.getColumnType(columnIndex));
4480 
4481         getCurrentRow().setColumnObject(columnIndex, obj);
4482     }
4483 
4484     /**
4485      * Sets the designated column in either the current row or the insert
4486      * row of this <code>CachedRowSetImpl</code> object with the given
4487      * <code>java.math.BigDecimal</code> object.
4488      * <P>
4489      * This method updates a column value in the current row or the insert
4490      * row of this rowset, but it does not update the database.
4491      * If the cursor is on a row in the rowset, the
4492      * method {@link #updateRow} must be called to update the database.
4493      * If the cursor is on the insert row, the method {@link #insertRow}
4494      * must be called, which will insert the new row into both this rowset
4495      * and the database. Both of these methods must be called before the
4496      * cursor moves to another row.
4497      *
4498      * @param columnIndex the first column is <code>1</code>, the second
4499      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4500      *        and equal to or less than the number of columns in this rowset
4501      * @param x the new column value
4502      * @throws SQLException if (1) the given column index is out of bounds,
4503      *            (2) the cursor is not on one of this rowset's rows or its
4504      *            insert row, or (3) this rowset is
4505      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4506      */
4507     public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {
4508         // sanity check.
4509         checkIndex(columnIndex);
4510         // make sure the cursor is on a valid row
4511         checkCursor();
4512 
4513         Object obj = convertNumeric(x,
4514         java.sql.Types.NUMERIC,
4515         RowSetMD.getColumnType(columnIndex));
4516 
4517         getCurrentRow().setColumnObject(columnIndex, obj);
4518     }
4519 
4520     /**
4521      * Sets the designated column in either the current row or the insert
4522      * row of this <code>CachedRowSetImpl</code> object with the given
4523      * <code>String</code> object.
4524      * <P>
4525      * This method updates a column value in either the current row or
4526      * the insert row of this rowset, but it does not update the
4527      * database.  If the cursor is on a row in the rowset, the
4528      * method {@link #updateRow} must be called to mark the row as updated.
4529      * If the cursor is on the insert row, the method {@link #insertRow}
4530      * must be called to insert the new row into this rowset and mark it
4531      * as inserted. Both of these methods must be called before the
4532      * cursor moves to another row.
4533      * <P>
4534      * The method <code>acceptChanges</code> must be called if the
4535      * updated values are to be written back to the underlying database.
4536      *
4537      * @param columnIndex the first column is <code>1</code>, the second
4538      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4539      *        and equal to or less than the number of columns in this rowset
4540      * @param x the new column value
4541      * @throws SQLException if (1) the given column index is out of bounds,
4542      *            (2) the cursor is not on one of this rowset's rows or its
4543      *            insert row, or (3) this rowset is
4544      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4545      */
4546     public void updateString(int columnIndex, String x) throws SQLException {
4547         // sanity check.
4548         checkIndex(columnIndex);
4549         // make sure the cursor is on a valid row
4550         checkCursor();
4551 
4552         getCurrentRow().setColumnObject(columnIndex, x);
4553     }
4554 
4555     /**
4556      * Sets the designated column in either the current row or the insert
4557      * row of this <code>CachedRowSetImpl</code> object with the given
4558      * <code>byte</code> array.
4559      *
4560      * This method updates a column value in either the current row or
4561      * the insert row of this rowset, but it does not update the
4562      * database.  If the cursor is on a row in the rowset, the
4563      * method {@link #updateRow} must be called to update the database.
4564      * If the cursor is on the insert row, the method {@link #insertRow}
4565      * must be called, which will insert the new row into both this rowset
4566      * and the database. Both of these methods must be called before the
4567      * cursor moves to another row.
4568      *
4569      * @param columnIndex the first column is <code>1</code>, the second
4570      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4571      *        and equal to or less than the number of columns in this rowset
4572      * @param x the new column value
4573      * @throws SQLException if (1) the given column index is out of bounds,
4574      *            (2) the cursor is not on one of this rowset's rows or its
4575      *            insert row, or (3) this rowset is
4576      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4577      */
4578     public void updateBytes(int columnIndex, byte x[]) throws SQLException {
4579         // sanity check.
4580         checkIndex(columnIndex);
4581         // make sure the cursor is on a valid row
4582         checkCursor();
4583 
4584         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4585             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4586         }
4587 
4588         getCurrentRow().setColumnObject(columnIndex, x);
4589     }
4590 
4591     /**
4592      * Sets the designated column in either the current row or the insert
4593      * row of this <code>CachedRowSetImpl</code> object with the given
4594      * <code>Date</code> object.
4595      *
4596      * This method updates a column value in either the current row or
4597      * the insert row of this rowset, but it does not update the
4598      * database.  If the cursor is on a row in the rowset, the
4599      * method {@link #updateRow} must be called to update the database.
4600      * If the cursor is on the insert row, the method {@link #insertRow}
4601      * must be called, which will insert the new row into both this rowset
4602      * and the database. Both of these methods must be called before the
4603      * cursor moves to another row.
4604      *
4605      * @param columnIndex the first column is <code>1</code>, the second
4606      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4607      *        and equal to or less than the number of columns in this rowset
4608      * @param x the new column value
4609      * @throws SQLException if (1) the given column index is out of bounds,
4610      *            (2) the cursor is not on one of this rowset's rows or its
4611      *            insert row, (3) the type of the designated column is not
4612      *            an SQL <code>DATE</code> or <code>TIMESTAMP</code>, or
4613      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4614      */
4615     public void updateDate(int columnIndex, java.sql.Date x) throws SQLException {
4616         // sanity check.
4617         checkIndex(columnIndex);
4618         // make sure the cursor is on a valid row
4619         checkCursor();
4620 
4621         Object obj = convertTemporal(x,
4622         java.sql.Types.DATE,
4623         RowSetMD.getColumnType(columnIndex));
4624 
4625         getCurrentRow().setColumnObject(columnIndex, obj);
4626     }
4627 
4628     /**
4629      * Sets the designated column in either the current row or the insert
4630      * row of this <code>CachedRowSetImpl</code> object with the given
4631      * <code>Time</code> object.
4632      *
4633      * This method updates a column value in either the current row or
4634      * the insert row of this rowset, but it does not update the
4635      * database.  If the cursor is on a row in the rowset, the
4636      * method {@link #updateRow} must be called to update the database.
4637      * If the cursor is on the insert row, the method {@link #insertRow}
4638      * must be called, which will insert the new row into both this rowset
4639      * and the database. Both of these methods must be called before the
4640      * cursor moves to another row.
4641      *
4642      * @param columnIndex the first column is <code>1</code>, the second
4643      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4644      *        and equal to or less than the number of columns in this rowset
4645      * @param x the new column value
4646      * @throws SQLException if (1) the given column index is out of bounds,
4647      *            (2) the cursor is not on one of this rowset's rows or its
4648      *            insert row, (3) the type of the designated column is not
4649      *            an SQL <code>TIME</code> or <code>TIMESTAMP</code>, or
4650      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4651      */
4652     public void updateTime(int columnIndex, java.sql.Time x) throws SQLException {
4653         // sanity check.
4654         checkIndex(columnIndex);
4655         // make sure the cursor is on a valid row
4656         checkCursor();
4657 
4658         Object obj = convertTemporal(x,
4659         java.sql.Types.TIME,
4660         RowSetMD.getColumnType(columnIndex));
4661 
4662         getCurrentRow().setColumnObject(columnIndex, obj);
4663     }
4664 
4665     /**
4666      * Sets the designated column in either the current row or the insert
4667      * row of this <code>CachedRowSetImpl</code> object with the given
4668      * <code>Timestamp</code> object.
4669      *
4670      * This method updates a column value in either the current row or
4671      * the insert row of this rowset, but it does not update the
4672      * database.  If the cursor is on a row in the rowset, the
4673      * method {@link #updateRow} must be called to update the database.
4674      * If the cursor is on the insert row, the method {@link #insertRow}
4675      * must be called, which will insert the new row into both this rowset
4676      * and the database. Both of these methods must be called before the
4677      * cursor moves to another row.
4678      *
4679      * @param columnIndex the first column is <code>1</code>, the second
4680      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4681      *        and equal to or less than the number of columns in this rowset
4682      * @param x the new column value
4683      * @throws SQLException if (1) the given column index is out of bounds,
4684      *            (2) the cursor is not on one of this rowset's rows or its
4685      *            insert row, (3) the type of the designated column is not
4686      *            an SQL <code>DATE</code>, <code>TIME</code>, or
4687      *            <code>TIMESTAMP</code>, or (4) this rowset is
4688      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4689      */
4690     public void updateTimestamp(int columnIndex, java.sql.Timestamp x) throws SQLException {
4691         // sanity check.
4692         checkIndex(columnIndex);
4693         // make sure the cursor is on a valid row
4694         checkCursor();
4695 
4696         Object obj = convertTemporal(x,
4697         java.sql.Types.TIMESTAMP,
4698         RowSetMD.getColumnType(columnIndex));
4699 
4700         getCurrentRow().setColumnObject(columnIndex, obj);
4701     }
4702 
4703     /**
4704      * Sets the designated column in either the current row or the insert
4705      * row of this <code>CachedRowSetImpl</code> object with the given
4706      * ASCII stream value.
4707      * <P>
4708      * This method updates a column value in either the current row or
4709      * the insert row of this rowset, but it does not update the
4710      * database.  If the cursor is on a row in the rowset, the
4711      * method {@link #updateRow} must be called to update the database.
4712      * If the cursor is on the insert row, the method {@link #insertRow}
4713      * must be called, which will insert the new row into both this rowset
4714      * and the database. Both of these methods must be called before the
4715      * cursor moves to another row.
4716      *
4717      * @param columnIndex the first column is <code>1</code>, the second
4718      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4719      *        and equal to or less than the number of columns in this rowset
4720      * @param x the new column value
4721      * @param length the number of one-byte ASCII characters in the stream
4722      * @throws SQLException if this method is invoked
4723      */
4724     public void updateAsciiStream(int columnIndex, java.io.InputStream x, int length) throws SQLException {
4725         // sanity Check
4726         checkIndex(columnIndex);
4727         // make sure the cursor is on a valid row
4728         checkCursor();
4729 
4730 
4731         if (isString(RowSetMD.getColumnType(columnIndex)) == false &&
4732         isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4733             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4734         }
4735 
4736         byte buf[] = new byte[length];
4737         try {
4738             int charsRead = 0;
4739             do {
4740                 charsRead += x.read(buf, charsRead, length - charsRead);
4741             } while (charsRead != length);
4742             //Changed the condition check to check for length instead of -1
4743         } catch (java.io.IOException ex) {
4744             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.asciistream").toString());
4745         }
4746         String str = new String(buf);
4747 
4748         getCurrentRow().setColumnObject(columnIndex, str);
4749 
4750     }
4751 
4752     /**
4753      * Sets the designated column in either the current row or the insert
4754      * row of this <code>CachedRowSetImpl</code> object with the given
4755      * <code>java.io.InputStream</code> object.
4756      * <P>
4757      * This method updates a column value in either the current row or
4758      * the insert row of this rowset, but it does not update the
4759      * database.  If the cursor is on a row in the rowset, the
4760      * method {@link #updateRow} must be called to update the database.
4761      * If the cursor is on the insert row, the method {@link #insertRow}
4762      * must be called, which will insert the new row into both this rowset
4763      * and the database. Both of these methods must be called before the
4764      * cursor moves to another row.
4765      *
4766      * @param columnIndex the first column is <code>1</code>, the second
4767      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4768      *        and equal to or less than the number of columns in this rowset
4769      * @param x the new column value; must be a <code>java.io.InputStream</code>
4770      *          containing <code>BINARY</code>, <code>VARBINARY</code>, or
4771      *          <code>LONGVARBINARY</code> data
4772      * @param length the length of the stream in bytes
4773      * @throws SQLException if (1) the given column index is out of bounds,
4774      *            (2) the cursor is not on one of this rowset's rows or its
4775      *            insert row, (3) the data in the stream is not binary, or
4776      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4777      */
4778     public void updateBinaryStream(int columnIndex, java.io.InputStream x,int length) throws SQLException {
4779         // sanity Check
4780         checkIndex(columnIndex);
4781         // make sure the cursor is on a valid row
4782         checkCursor();
4783 
4784         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4785             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4786         }
4787 
4788         byte buf[] = new byte[length];
4789         try {
4790             int bytesRead = 0;
4791             do {
4792                 bytesRead += x.read(buf, bytesRead, length - bytesRead);
4793             } while (bytesRead != -1);
4794         } catch (java.io.IOException ex) {
4795             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.binstream").toString());
4796         }
4797 
4798         getCurrentRow().setColumnObject(columnIndex, buf);
4799     }
4800 
4801     /**
4802      * Sets the designated column in either the current row or the insert
4803      * row of this <code>CachedRowSetImpl</code> object with the given
4804      * <code>java.io.Reader</code> object.
4805      * <P>
4806      * This method updates a column value in either the current row or
4807      * the insert row of this rowset, but it does not update the
4808      * database.  If the cursor is on a row in the rowset, the
4809      * method {@link #updateRow} must be called to update the database.
4810      * If the cursor is on the insert row, the method {@link #insertRow}
4811      * must be called, which will insert the new row into both this rowset
4812      * and the database. Both of these methods must be called before the
4813      * cursor moves to another row.
4814      *
4815      * @param columnIndex the first column is <code>1</code>, the second
4816      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4817      *        and equal to or less than the number of columns in this rowset
4818      * @param x the new column value; must be a <code>java.io.Reader</code>
4819      *          containing <code>BINARY</code>, <code>VARBINARY</code>,
4820      *          <code>LONGVARBINARY</code>, <code>CHAR</code>, <code>VARCHAR</code>,
4821      *          or <code>LONGVARCHAR</code> data
4822      * @param length the length of the stream in characters
4823      * @throws SQLException if (1) the given column index is out of bounds,
4824      *            (2) the cursor is not on one of this rowset's rows or its
4825      *            insert row, (3) the data in the stream is not a binary or
4826      *            character type, or (4) this rowset is
4827      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4828      */
4829     public void updateCharacterStream(int columnIndex, java.io.Reader x, int length) throws SQLException {
4830         // sanity Check
4831         checkIndex(columnIndex);
4832         // make sure the cursor is on a valid row
4833         checkCursor();
4834 
4835         if (isString(RowSetMD.getColumnType(columnIndex)) == false &&
4836         isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4837             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4838         }
4839 
4840         char buf[] = new char[length];
4841         try {
4842             int charsRead = 0;
4843             do {
4844                 charsRead += x.read(buf, charsRead, length - charsRead);
4845             } while (charsRead != length);
4846             //Changed the condition checking to check for length instead of -1
4847         } catch (java.io.IOException ex) {
4848             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.binstream").toString());
4849         }
4850         String str = new String(buf);
4851 
4852         getCurrentRow().setColumnObject(columnIndex, str);
4853     }
4854 
4855     /**
4856      * Sets the designated column in either the current row or the insert
4857      * row of this <code>CachedRowSetImpl</code> object with the given
4858      * <code>Object</code> value.  The <code>scale</code> parameter indicates
4859      * the number of digits to the right of the decimal point and is ignored
4860      * if the new column value is not a type that will be mapped to an SQL
4861      * <code>DECIMAL</code> or <code>NUMERIC</code> value.
4862      * <P>
4863      * This method updates a column value in either the current row or
4864      * the insert row of this rowset, but it does not update the
4865      * database.  If the cursor is on a row in the rowset, the
4866      * method {@link #updateRow} must be called to update the database.
4867      * If the cursor is on the insert row, the method {@link #insertRow}
4868      * must be called, which will insert the new row into both this rowset
4869      * and the database. Both of these methods must be called before the
4870      * cursor moves to another row.
4871      *
4872      * @param columnIndex the first column is <code>1</code>, the second
4873      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4874      *        and equal to or less than the number of columns in this rowset
4875      * @param x the new column value
4876      * @param scale the number of digits to the right of the decimal point (for
4877      *              <code>DECIMAL</code> and <code>NUMERIC</code> types only)
4878      * @throws SQLException if (1) the given column index is out of bounds,
4879      *            (2) the cursor is not on one of this rowset's rows or its
4880      *            insert row, or (3) this rowset is
4881      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4882      */
4883     public void updateObject(int columnIndex, Object x, int scale) throws SQLException {
4884         // sanity check.
4885         checkIndex(columnIndex);
4886         // make sure the cursor is on a valid row
4887         checkCursor();
4888 
4889         int type = RowSetMD.getColumnType(columnIndex);
4890         if (type == Types.DECIMAL || type == Types.NUMERIC) {
4891             ((java.math.BigDecimal)x).setScale(scale);
4892         }
4893         getCurrentRow().setColumnObject(columnIndex, x);
4894     }
4895 
4896     /**
4897      * Sets the designated column in either the current row or the insert
4898      * row of this <code>CachedRowSetImpl</code> object with the given
4899      * <code>Object</code> value.
4900      * <P>
4901      * This method updates a column value in either the current row or
4902      * the insert row of this rowset, but it does not update the
4903      * database.  If the cursor is on a row in the rowset, the
4904      * method {@link #updateRow} must be called to update the database.
4905      * If the cursor is on the insert row, the method {@link #insertRow}
4906      * must be called, which will insert the new row into both this rowset
4907      * and the database. Both of these methods must be called before the
4908      * cursor moves to another row.
4909      *
4910      * @param columnIndex the first column is <code>1</code>, the second
4911      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4912      *        and equal to or less than the number of columns in this rowset
4913      * @param x the new column value
4914      * @throws SQLException if (1) the given column index is out of bounds,
4915      *            (2) the cursor is not on one of this rowset's rows or its
4916      *            insert row, or (3) this rowset is
4917      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4918      */
4919     public void updateObject(int columnIndex, Object x) throws SQLException {
4920         // sanity check.
4921         checkIndex(columnIndex);
4922         // make sure the cursor is on a valid row
4923         checkCursor();
4924 
4925         getCurrentRow().setColumnObject(columnIndex, x);
4926     }
4927 
4928     /**
4929      * Sets the designated nullable column in the current row or the
4930      * insert row of this <code>CachedRowSetImpl</code> object with
4931      * <code>null</code> value.
4932      * <P>
4933      * This method updates a column value in the current row or the insert
4934      * row of this rowset, but it does not update the database.
4935      * If the cursor is on a row in the rowset, the
4936      * method {@link #updateRow} must be called to update the database.
4937      * If the cursor is on the insert row, the method {@link #insertRow}
4938      * must be called, which will insert the new row into both this rowset
4939      * and the database.
4940      *
4941      * @param columnName a <code>String</code> object that must match the
4942      *        SQL name of a column in this rowset, ignoring case
4943      * @throws SQLException if (1) the given column name does not match the
4944      *            name of a column in this rowset, (2) the cursor is not on
4945      *            one of this rowset's rows or its insert row, or (3) this
4946      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4947      */
4948     public void updateNull(String columnName) throws SQLException {
4949         updateNull(getColIdxByName(columnName));
4950     }
4951 
4952     /**
4953      * Sets the designated column in either the current row or the insert
4954      * row of this <code>CachedRowSetImpl</code> object with the given
4955      * <code>boolean</code> value.
4956      * <P>
4957      * This method updates a column value in the current row or the insert
4958      * row of this rowset, but it does not update the database.
4959      * If the cursor is on a row in the rowset, the
4960      * method {@link #updateRow} must be called to update the database.
4961      * If the cursor is on the insert row, the method {@link #insertRow}
4962      * must be called, which will insert the new row into both this rowset
4963      * and the database. Both of these methods must be called before the
4964      * cursor moves to another row.
4965      *
4966      * @param columnName a <code>String</code> object that must match the
4967      *        SQL name of a column in this rowset, ignoring case
4968      * @param x the new column value
4969      * @throws SQLException if (1) the given column name does not match the
4970      *            name of a column in this rowset, (2) the cursor is not on
4971      *            one of this rowset's rows or its insert row, or (3) this
4972      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4973      */
4974     public void updateBoolean(String columnName, boolean x) throws SQLException {
4975         updateBoolean(getColIdxByName(columnName), x);
4976     }
4977 
4978     /**
4979      * Sets the designated column in either the current row or the insert
4980      * row of this <code>CachedRowSetImpl</code> object with the given
4981      * <code>byte</code> value.
4982      * <P>
4983      * This method updates a column value in the current row or the insert
4984      * row of this rowset, but it does not update the database.
4985      * If the cursor is on a row in the rowset, the
4986      * method {@link #updateRow} must be called to update the database.
4987      * If the cursor is on the insert row, the method {@link #insertRow}
4988      * must be called, which will insert the new row into both this rowset
4989      * and the database. Both of these methods must be called before the
4990      * cursor moves to another row.
4991      *
4992      * @param columnName a <code>String</code> object that must match the
4993      *        SQL name of a column in this rowset, ignoring case
4994      * @param x the new column value
4995      * @throws SQLException if (1) the given column name does not match the
4996      *            name of a column in this rowset, (2) the cursor is not on
4997      *            one of this rowset's rows or its insert row, or (3) this
4998      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4999      */
5000     public void updateByte(String columnName, byte x) throws SQLException {
5001         updateByte(getColIdxByName(columnName), x);
5002     }
5003 
5004     /**
5005      * Sets the designated column in either the current row or the insert
5006      * row of this <code>CachedRowSetImpl</code> object with the given
5007      * <code>short</code> value.
5008      * <P>
5009      * This method updates a column value in the current row or the insert
5010      * row of this rowset, but it does not update the database.
5011      * If the cursor is on a row in the rowset, the
5012      * method {@link #updateRow} must be called to update the database.
5013      * If the cursor is on the insert row, the method {@link #insertRow}
5014      * must be called, which will insert the new row into both this rowset
5015      * and the database. Both of these methods must be called before the
5016      * cursor moves to another row.
5017      *
5018      * @param columnName a <code>String</code> object that must match the
5019      *        SQL name of a column in this rowset, ignoring case
5020      * @param x the new column value
5021      * @throws SQLException if (1) the given column name does not match the
5022      *            name of a column in this rowset, (2) the cursor is not on
5023      *            one of this rowset's rows or its insert row, or (3) this
5024      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5025      */
5026     public void updateShort(String columnName, short x) throws SQLException {
5027         updateShort(getColIdxByName(columnName), x);
5028     }
5029 
5030     /**
5031      * Sets the designated column in either the current row or the insert
5032      * row of this <code>CachedRowSetImpl</code> object with the given
5033      * <code>int</code> value.
5034      * <P>
5035      * This method updates a column value in the current row or the insert
5036      * row of this rowset, but it does not update the database.
5037      * If the cursor is on a row in the rowset, the
5038      * method {@link #updateRow} must be called to update the database.
5039      * If the cursor is on the insert row, the method {@link #insertRow}
5040      * must be called, which will insert the new row into both this rowset
5041      * and the database. Both of these methods must be called before the
5042      * cursor moves to another row.
5043      *
5044      * @param columnName a <code>String</code> object that must match the
5045      *        SQL name of a column in this rowset, ignoring case
5046      * @param x the new column value
5047      * @throws SQLException if (1) the given column name does not match the
5048      *            name of a column in this rowset, (2) the cursor is not on
5049      *            one of this rowset's rows or its insert row, or (3) this
5050      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5051      */
5052     public void updateInt(String columnName, int x) throws SQLException {
5053         updateInt(getColIdxByName(columnName), x);
5054     }
5055 
5056     /**
5057      * Sets the designated column in either the current row or the insert
5058      * row of this <code>CachedRowSetImpl</code> object with the given
5059      * <code>long</code> value.
5060      * <P>
5061      * This method updates a column value in the current row or the insert
5062      * row of this rowset, but it does not update the database.
5063      * If the cursor is on a row in the rowset, the
5064      * method {@link #updateRow} must be called to update the database.
5065      * If the cursor is on the insert row, the method {@link #insertRow}
5066      * must be called, which will insert the new row into both this rowset
5067      * and the database. Both of these methods must be called before the
5068      * cursor moves to another row.
5069      *
5070      * @param columnName a <code>String</code> object that must match the
5071      *        SQL name of a column in this rowset, ignoring case
5072      * @param x the new column value
5073      * @throws SQLException if (1) the given column name does not match the
5074      *            name of a column in this rowset, (2) the cursor is not on
5075      *            one of this rowset's rows or its insert row, or (3) this
5076      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5077      */
5078     public void updateLong(String columnName, long x) throws SQLException {
5079         updateLong(getColIdxByName(columnName), x);
5080     }
5081 
5082     /**
5083      * Sets the designated column in either the current row or the insert
5084      * row of this <code>CachedRowSetImpl</code> object with the given
5085      * <code>float</code> value.
5086      * <P>
5087      * This method updates a column value in the current row or the insert
5088      * row of this rowset, but it does not update the database.
5089      * If the cursor is on a row in the rowset, the
5090      * method {@link #updateRow} must be called to update the database.
5091      * If the cursor is on the insert row, the method {@link #insertRow}
5092      * must be called, which will insert the new row into both this rowset
5093      * and the database. Both of these methods must be called before the
5094      * cursor moves to another row.
5095      *
5096      * @param columnName a <code>String</code> object that must match the
5097      *        SQL name of a column in this rowset, ignoring case
5098      * @param x the new column value
5099      * @throws SQLException if (1) the given column name does not match the
5100      *            name of a column in this rowset, (2) the cursor is not on
5101      *            one of this rowset's rows or its insert row, or (3) this
5102      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5103      */
5104     public void updateFloat(String columnName, float x) throws SQLException {
5105         updateFloat(getColIdxByName(columnName), x);
5106     }
5107 
5108     /**
5109      * Sets the designated column in either the current row or the insert
5110      * row of this <code>CachedRowSetImpl</code> object with the given
5111      * <code>double</code> value.
5112      *
5113      * This method updates a column value in either the current row or
5114      * the insert row of this rowset, but it does not update the
5115      * database.  If the cursor is on a row in the rowset, the
5116      * method {@link #updateRow} must be called to update the database.
5117      * If the cursor is on the insert row, the method {@link #insertRow}
5118      * must be called, which will insert the new row into both this rowset
5119      * and the database. Both of these methods must be called before the
5120      * cursor moves to another row.
5121      *
5122      * @param columnName a <code>String</code> object that must match the
5123      *        SQL name of a column in this rowset, ignoring case
5124      * @param x the new column value
5125      * @throws SQLException if (1) the given column name does not match the
5126      *            name of a column in this rowset, (2) the cursor is not on
5127      *            one of this rowset's rows or its insert row, or (3) this
5128      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5129      */
5130     public void updateDouble(String columnName, double x) throws SQLException {
5131         updateDouble(getColIdxByName(columnName), x);
5132     }
5133 
5134     /**
5135      * Sets the designated column in either the current row or the insert
5136      * row of this <code>CachedRowSetImpl</code> object with the given
5137      * <code>java.math.BigDecimal</code> object.
5138      * <P>
5139      * This method updates a column value in the current row or the insert
5140      * row of this rowset, but it does not update the database.
5141      * If the cursor is on a row in the rowset, the
5142      * method {@link #updateRow} must be called to update the database.
5143      * If the cursor is on the insert row, the method {@link #insertRow}
5144      * must be called, which will insert the new row into both this rowset
5145      * and the database. Both of these methods must be called before the
5146      * cursor moves to another row.
5147      *
5148      * @param columnName a <code>String</code> object that must match the
5149      *        SQL name of a column in this rowset, ignoring case
5150      * @param x the new column value
5151      * @throws SQLException if (1) the given column name does not match the
5152      *            name of a column in this rowset, (2) the cursor is not on
5153      *            one of this rowset's rows or its insert row, or (3) this
5154      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5155      */
5156     public void updateBigDecimal(String columnName, BigDecimal x) throws SQLException {
5157         updateBigDecimal(getColIdxByName(columnName), x);
5158     }
5159 
5160     /**
5161      * Sets the designated column in either the current row or the insert
5162      * row of this <code>CachedRowSetImpl</code> object with the given
5163      * <code>String</code> object.
5164      *
5165      * This method updates a column value in either the current row or
5166      * the insert row of this rowset, but it does not update the
5167      * database.  If the cursor is on a row in the rowset, the
5168      * method {@link #updateRow} must be called to update the database.
5169      * If the cursor is on the insert row, the method {@link #insertRow}
5170      * must be called, which will insert the new row into both this rowset
5171      * and the database. Both of these methods must be called before the
5172      * cursor moves to another row.
5173      *
5174      * @param columnName a <code>String</code> object that must match the
5175      *        SQL name of a column in this rowset, ignoring case
5176      * @param x the new column value
5177      * @throws SQLException if (1) the given column name does not match the
5178      *            name of a column in this rowset, (2) the cursor is not on
5179      *            one of this rowset's rows or its insert row, or (3) this
5180      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5181      */
5182     public void updateString(String columnName, String x) throws SQLException {
5183         updateString(getColIdxByName(columnName), x);
5184     }
5185 
5186     /**
5187      * Sets the designated column in either the current row or the insert
5188      * row of this <code>CachedRowSetImpl</code> object with the given
5189      * <code>byte</code> array.
5190      *
5191      * This method updates a column value in either the current row or
5192      * the insert row of this rowset, but it does not update the
5193      * database.  If the cursor is on a row in the rowset, the
5194      * method {@link #updateRow} must be called to update the database.
5195      * If the cursor is on the insert row, the method {@link #insertRow}
5196      * must be called, which will insert the new row into both this rowset
5197      * and the database. Both of these methods must be called before the
5198      * cursor moves to another row.
5199      *
5200      * @param columnName a <code>String</code> object that must match the
5201      *        SQL name of a column in this rowset, ignoring case
5202      * @param x the new column value
5203      * @throws SQLException if (1) the given column name does not match the
5204      *            name of a column in this rowset, (2) the cursor is not on
5205      *            one of this rowset's rows or its insert row, or (3) this
5206      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5207      */
5208     public void updateBytes(String columnName, byte x[]) throws SQLException {
5209         updateBytes(getColIdxByName(columnName), x);
5210     }
5211 
5212     /**
5213      * Sets the designated column in either the current row or the insert
5214      * row of this <code>CachedRowSetImpl</code> object with the given
5215      * <code>Date</code> object.
5216      *
5217      * This method updates a column value in either the current row or
5218      * the insert row of this rowset, but it does not update the
5219      * database.  If the cursor is on a row in the rowset, the
5220      * method {@link #updateRow} must be called to update the database.
5221      * If the cursor is on the insert row, the method {@link #insertRow}
5222      * must be called, which will insert the new row into both this rowset
5223      * and the database. Both of these methods must be called before the
5224      * cursor moves to another row.
5225      *
5226      * @param columnName a <code>String</code> object that must match the
5227      *        SQL name of a column in this rowset, ignoring case
5228      * @param x the new column value
5229      * @throws SQLException if (1) the given column name does not match the
5230      *            name of a column in this rowset, (2) the cursor is not on
5231      *            one of this rowset's rows or its insert row, (3) the type
5232      *            of the designated column is not an SQL <code>DATE</code> or
5233      *            <code>TIMESTAMP</code>, or (4) this rowset is
5234      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5235      */
5236     public void updateDate(String columnName, java.sql.Date x) throws SQLException {
5237         updateDate(getColIdxByName(columnName), x);
5238     }
5239 
5240     /**
5241      * Sets the designated column in either the current row or the insert
5242      * row of this <code>CachedRowSetImpl</code> object with the given
5243      * <code>Time</code> object.
5244      *
5245      * This method updates a column value in either the current row or
5246      * the insert row of this rowset, but it does not update the
5247      * database.  If the cursor is on a row in the rowset, the
5248      * method {@link #updateRow} must be called to update the database.
5249      * If the cursor is on the insert row, the method {@link #insertRow}
5250      * must be called, which will insert the new row into both this rowset
5251      * and the database. Both of these methods must be called before the
5252      * cursor moves to another row.
5253      *
5254      * @param columnName a <code>String</code> object that must match the
5255      *        SQL name of a column in this rowset, ignoring case
5256      * @param x the new column value
5257      * @throws SQLException if (1) the given column name does not match the
5258      *            name of a column in this rowset, (2) the cursor is not on
5259      *            one of this rowset's rows or its insert row, (3) the type
5260      *            of the designated column is not an SQL <code>TIME</code> or
5261      *            <code>TIMESTAMP</code>, or (4) this rowset is
5262      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5263      */
5264     public void updateTime(String columnName, java.sql.Time x) throws SQLException {
5265         updateTime(getColIdxByName(columnName), x);
5266     }
5267 
5268     /**
5269      * Sets the designated column in either the current row or the insert
5270      * row of this <code>CachedRowSetImpl</code> object with the given
5271      * <code>Timestamp</code> object.
5272      *
5273      * This method updates a column value in either the current row or
5274      * the insert row of this rowset, but it does not update the
5275      * database.  If the cursor is on a row in the rowset, the
5276      * method {@link #updateRow} must be called to update the database.
5277      * If the cursor is on the insert row, the method {@link #insertRow}
5278      * must be called, which will insert the new row into both this rowset
5279      * and the database. Both of these methods must be called before the
5280      * cursor moves to another row.
5281      *
5282      * @param columnName a <code>String</code> object that must match the
5283      *        SQL name of a column in this rowset, ignoring case
5284      * @param x the new column value
5285      * @throws SQLException if the given column index is out of bounds or
5286      *            the cursor is not on one of this rowset's rows or its
5287      *            insert row
5288      * @throws SQLException if (1) the given column name does not match the
5289      *            name of a column in this rowset, (2) the cursor is not on
5290      *            one of this rowset's rows or its insert row, (3) the type
5291      *            of the designated column is not an SQL <code>DATE</code>,
5292      *            <code>TIME</code>, or <code>TIMESTAMP</code>, or (4) this
5293      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5294      */
5295     public void updateTimestamp(String columnName, java.sql.Timestamp x) throws SQLException {
5296         updateTimestamp(getColIdxByName(columnName), x);
5297     }
5298 
5299     /**
5300      * Sets the designated column in either the current row or the insert
5301      * row of this <code>CachedRowSetImpl</code> object with the given
5302      * ASCII stream value.
5303      * <P>
5304      * This method updates a column value in either the current row or
5305      * the insert row of this rowset, but it does not update the
5306      * database.  If the cursor is on a row in the rowset, the
5307      * method {@link #updateRow} must be called to update the database.
5308      * If the cursor is on the insert row, the method {@link #insertRow}
5309      * must be called, which will insert the new row into both this rowset
5310      * and the database. Both of these methods must be called before the
5311      * cursor moves to another row.
5312      *
5313      * @param columnName a <code>String</code> object that must match the
5314      *        SQL name of a column in this rowset, ignoring case
5315      * @param x the new column value
5316      * @param length the number of one-byte ASCII characters in the stream
5317      */
5318     public void updateAsciiStream(String columnName,
5319     java.io.InputStream x,
5320     int length) throws SQLException {
5321         updateAsciiStream(getColIdxByName(columnName), x, length);
5322     }
5323 
5324     /**
5325      * Sets the designated column in either the current row or the insert
5326      * row of this <code>CachedRowSetImpl</code> object with the given
5327      * <code>java.io.InputStream</code> object.
5328      * <P>
5329      * This method updates a column value in either the current row or
5330      * the insert row of this rowset, but it does not update the
5331      * database.  If the cursor is on a row in the rowset, the
5332      * method {@link #updateRow} must be called to update the database.
5333      * If the cursor is on the insert row, the method {@link #insertRow}
5334      * must be called, which will insert the new row into both this rowset
5335      * and the database. Both of these methods must be called before the
5336      * cursor moves to another row.
5337      *
5338      * @param columnName a <code>String</code> object that must match the
5339      *        SQL name of a column in this rowset, ignoring case
5340      * @param x the new column value; must be a <code>java.io.InputStream</code>
5341      *          containing <code>BINARY</code>, <code>VARBINARY</code>, or
5342      *          <code>LONGVARBINARY</code> data
5343      * @param length the length of the stream in bytes
5344      * @throws SQLException if (1) the given column name does not match the
5345      *            name of a column in this rowset, (2) the cursor is not on
5346      *            one of this rowset's rows or its insert row, (3) the data
5347      *            in the stream is not binary, or (4) this rowset is
5348      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5349      */
5350     public void updateBinaryStream(String columnName, java.io.InputStream x, int length) throws SQLException {
5351         updateBinaryStream(getColIdxByName(columnName), x, length);
5352     }
5353 
5354     /**
5355      * Sets the designated column in either the current row or the insert
5356      * row of this <code>CachedRowSetImpl</code> object with the given
5357      * <code>java.io.Reader</code> object.
5358      * <P>
5359      * This method updates a column value in either the current row or
5360      * the insert row of this rowset, but it does not update the
5361      * database.  If the cursor is on a row in the rowset, the
5362      * method {@link #updateRow} must be called to update the database.
5363      * If the cursor is on the insert row, the method {@link #insertRow}
5364      * must be called, which will insert the new row into both this rowset
5365      * and the database. Both of these methods must be called before the
5366      * cursor moves to another row.
5367      *
5368      * @param columnName a <code>String</code> object that must match the
5369      *        SQL name of a column in this rowset, ignoring case
5370      * @param reader the new column value; must be a
5371      * <code>java.io.Reader</code> containing <code>BINARY</code>,
5372      * <code>VARBINARY</code>, <code>LONGVARBINARY</code>, <code>CHAR</code>,
5373      * <code>VARCHAR</code>, or <code>LONGVARCHAR</code> data
5374      * @param length the length of the stream in characters
5375      * @throws SQLException if (1) the given column name does not match the
5376      *            name of a column in this rowset, (2) the cursor is not on
5377      *            one of this rowset's rows or its insert row, (3) the data
5378      *            in the stream is not a binary or character type, or (4) this
5379      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5380      */
5381     public void updateCharacterStream(String columnName,
5382     java.io.Reader reader,
5383     int length) throws SQLException {
5384         updateCharacterStream(getColIdxByName(columnName), reader, length);
5385     }
5386 
5387     /**
5388      * Sets the designated column in either the current row or the insert
5389      * row of this <code>CachedRowSetImpl</code> object with the given
5390      * <code>Object</code> value.  The <code>scale</code> parameter
5391      * indicates the number of digits to the right of the decimal point
5392      * and is ignored if the new column value is not a type that will be
5393      *  mapped to an SQL <code>DECIMAL</code> or <code>NUMERIC</code> value.
5394      * <P>
5395      * This method updates a column value in either the current row or
5396      * the insert row of this rowset, but it does not update the
5397      * database.  If the cursor is on a row in the rowset, the
5398      * method {@link #updateRow} must be called to update the database.
5399      * If the cursor is on the insert row, the method {@link #insertRow}
5400      * must be called, which will insert the new row into both this rowset
5401      * and the database. Both of these methods must be called before the
5402      * cursor moves to another row.
5403      *
5404      * @param columnName a <code>String</code> object that must match the
5405      *        SQL name of a column in this rowset, ignoring case
5406      * @param x the new column value
5407      * @param scale the number of digits to the right of the decimal point (for
5408      *              <code>DECIMAL</code> and <code>NUMERIC</code> types only)
5409      * @throws SQLException if (1) the given column name does not match the
5410      *            name of a column in this rowset, (2) the cursor is not on
5411      *            one of this rowset's rows or its insert row, or (3) this
5412      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5413      */
5414     public void updateObject(String columnName, Object x, int scale) throws SQLException {
5415         updateObject(getColIdxByName(columnName), x, scale);
5416     }
5417 
5418     /**
5419      * Sets the designated column in either the current row or the insert
5420      * row of this <code>CachedRowSetImpl</code> object with the given
5421      * <code>Object</code> value.
5422      * <P>
5423      * This method updates a column value in either the current row or
5424      * the insert row of this rowset, but it does not update the
5425      * database.  If the cursor is on a row in the rowset, the
5426      * method {@link #updateRow} must be called to update the database.
5427      * If the cursor is on the insert row, the method {@link #insertRow}
5428      * must be called, which will insert the new row into both this rowset
5429      * and the database. Both of these methods must be called before the
5430      * cursor moves to another row.
5431      *
5432      * @param columnName a <code>String</code> object that must match the
5433      *        SQL name of a column in this rowset, ignoring case
5434      * @param x the new column value
5435      * @throws SQLException if (1) the given column name does not match the
5436      *            name of a column in this rowset, (2) the cursor is not on
5437      *            one of this rowset's rows or its insert row, or (3) this
5438      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5439      */
5440     public void updateObject(String columnName, Object x) throws SQLException {
5441         updateObject(getColIdxByName(columnName), x);
5442     }
5443 
5444     /**
5445      * Inserts the contents of this <code>CachedRowSetImpl</code> object's insert
5446      * row into this rowset immediately following the current row.
5447      * If the current row is the
5448      * position after the last row or before the first row, the new row will
5449      * be inserted at the end of the rowset.  This method also notifies
5450      * listeners registered with this rowset that the row has changed.
5451      * <P>
5452      * The cursor must be on the insert row when this method is called.
5453      *
5454      * @throws SQLException if (1) the cursor is not on the insert row,
5455      *            (2) one or more of the non-nullable columns in the insert
5456      *            row has not been given a value, or (3) this rowset is
5457      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5458      */
5459     public void insertRow() throws SQLException {
5460         int pos;
5461 
5462         if (onInsertRow == false ||
5463             insertRow.isCompleteRow(RowSetMD) == false) {
5464                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.failedins").toString());
5465         }
5466         // Added the setting of parameters that are passed
5467         // to setXXX methods after an empty CRS Object is
5468         // created through RowSetMetaData object
5469         Object [] toInsert = getParams();
5470 
5471         for(int i = 0;i < toInsert.length; i++) {
5472           insertRow.setColumnObject(i+1,toInsert[i]);
5473         }
5474 
5475         Row insRow = new Row(RowSetMD.getColumnCount(),
5476         insertRow.getOrigRow());
5477         insRow.setInserted();
5478         /*
5479          * The new row is inserted into the RowSet
5480          * immediately following the current row.
5481          *
5482          * If we are afterlast then the rows are
5483          * inserted at the end.
5484          */
5485         if (currentRow >= numRows || currentRow < 0) {
5486             pos = numRows;
5487         } else {
5488             pos = currentRow;
5489         }
5490 
5491         rvh.add(pos, insRow);
5492         ++numRows;
5493         // notify the listeners that the row changed.
5494         notifyRowChanged();
5495     }
5496 
5497     /**
5498      * Marks the current row of this <code>CachedRowSetImpl</code> object as
5499      * updated and notifies listeners registered with this rowset that the
5500      * row has changed.
5501      * <P>
5502      * This method  cannot be called when the cursor is on the insert row, and
5503      * it should be called before the cursor moves to another row.  If it is
5504      * called after the cursor moves to another row, this method has no effect,
5505      * and the updates made before the cursor moved will be lost.
5506      *
5507      * @throws SQLException if the cursor is on the insert row or this
5508      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5509      */
5510     public void updateRow() throws SQLException {
5511         // make sure we aren't on the insert row
5512         if (onInsertRow == true) {
5513             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.updateins").toString());
5514         }
5515 
5516         ((Row)getCurrentRow()).setUpdated();
5517 
5518         // notify the listeners that the row changed.
5519         notifyRowChanged();
5520     }
5521 
5522     /**
5523      * Deletes the current row from this <code>CachedRowSetImpl</code> object and
5524      * notifies listeners registered with this rowset that a row has changed.
5525      * This method cannot be called when the cursor is on the insert row.
5526      * <P>
5527      * This method marks the current row as deleted, but it does not delete
5528      * the row from the underlying data source.  The method
5529      * <code>acceptChanges</code> must be called to delete the row in
5530      * the data source.
5531      *
5532      * @throws SQLException if (1) this method is called when the cursor
5533      *            is on the insert row, before the first row, or after the
5534      *            last row or (2) this rowset is
5535      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5536      */
5537     public void deleteRow() throws SQLException {
5538         // make sure the cursor is on a valid row
5539         checkCursor();
5540 
5541         ((Row)getCurrentRow()).setDeleted();
5542         ++numDeleted;
5543 
5544         // notify the listeners that the row changed.
5545         notifyRowChanged();
5546     }
5547 
5548     /**
5549      * Sets the current row with its original value and marks the row as
5550      * not updated, thus undoing any changes made to the row since the
5551      * last call to the methods <code>updateRow</code> or <code>deleteRow</code>.
5552      * This method should be called only when the cursor is on a row in
5553      * this rowset.
5554      *
5555      * @throws SQLException if the cursor is on the insert row, before the
5556      *            first row, or after the last row
5557      */
5558     public void refreshRow() throws SQLException {
5559         // make sure we are on a row
5560         checkCursor();
5561 
5562         // don't want this to happen...
5563         if (onInsertRow == true) {
5564             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
5565         }
5566 
5567         Row currentRow = (Row)getCurrentRow();
5568         // just undo any changes made to this row.
5569         currentRow.clearUpdated();
5570 
5571     }
5572 
5573     /**
5574      * Rolls back any updates made to the current row of this
5575      * <code>CachedRowSetImpl</code> object and notifies listeners that
5576      * a row has changed.  To have an effect, this method
5577      * must be called after an <code>updateXXX</code> method has been
5578      * called and before the method <code>updateRow</code> has been called.
5579      * If no updates have been made or the method <code>updateRow</code>
5580      * has already been called, this method has no effect.
5581      *
5582      * @throws SQLException if the cursor is on the insert row, before the
5583      *            first row, or after the last row
5584      */
5585     public void cancelRowUpdates() throws SQLException {
5586         // make sure we are on a row
5587         checkCursor();
5588 
5589         // don't want this to happen...
5590         if (onInsertRow == true) {
5591             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
5592         }
5593 
5594         Row currentRow = (Row)getCurrentRow();
5595         if (currentRow.getUpdated() == true) {
5596             currentRow.clearUpdated();
5597             notifyRowChanged();
5598         }
5599     }
5600 
5601     /**
5602      * Moves the cursor for this <code>CachedRowSetImpl</code> object
5603      * to the insert row.  The current row in the rowset is remembered
5604      * while the cursor is on the insert row.
5605      * <P>
5606      * The insert row is a special row associated with an updatable
5607      * rowset.  It is essentially a buffer where a new row may
5608      * be constructed by calling the appropriate <code>updateXXX</code>
5609      * methods to assign a value to each column in the row.  A complete
5610      * row must be constructed; that is, every column that is not nullable
5611      * must be assigned a value.  In order for the new row to become part
5612      * of this rowset, the method <code>insertRow</code> must be called
5613      * before the cursor is moved back to the rowset.
5614      * <P>
5615      * Only certain methods may be invoked while the cursor is on the insert
5616      * row; many methods throw an exception if they are called while the
5617      * cursor is there.  In addition to the <code>updateXXX</code>
5618      * and <code>insertRow</code> methods, only the <code>getXXX</code> methods
5619      * may be called when the cursor is on the insert row.  A <code>getXXX</code>
5620      * method should be called on a column only after an <code>updateXXX</code>
5621      * method has been called on that column; otherwise, the value returned is
5622      * undetermined.
5623      *
5624      * @throws SQLException if this <code>CachedRowSetImpl</code> object is
5625      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5626      */
5627     public void moveToInsertRow() throws SQLException {
5628         if (getConcurrency() == ResultSet.CONCUR_READ_ONLY) {
5629             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins").toString());
5630         }
5631         if (insertRow == null) {
5632             if (RowSetMD == null)
5633                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins1").toString());
5634             int numCols = RowSetMD.getColumnCount();
5635             if (numCols > 0) {
5636                 insertRow = new InsertRow(numCols);
5637             } else {
5638                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins2").toString());
5639             }
5640         }
5641         onInsertRow = true;
5642         // %%% setCurrentRow called in BaseRow
5643 
5644         currentRow = cursorPos;
5645         cursorPos = -1;
5646 
5647         insertRow.initInsertRow();
5648     }
5649 
5650     /**
5651      * Moves the cursor for this <code>CachedRowSetImpl</code> object to
5652      * the current row.  The current row is the row the cursor was on
5653      * when the method <code>moveToInsertRow</code> was called.
5654      * <P>
5655      * Calling this method has no effect unless it is called while the
5656      * cursor is on the insert row.
5657      *
5658      * @throws SQLException if an error occurs
5659      */
5660     public void moveToCurrentRow() throws SQLException {
5661         if (onInsertRow == false) {
5662             return;
5663         } else {
5664             cursorPos = currentRow;
5665             onInsertRow = false;
5666         }
5667     }
5668 
5669     /**
5670      * Returns <code>null</code>.
5671      *
5672      * @return <code>null</code>
5673      * @throws SQLException if an error occurs
5674      */
5675     public Statement getStatement() throws SQLException {
5676         return null;
5677     }
5678 
5679     /**
5680      * Retrieves the value of the designated column in this
5681      * <code>CachedRowSetImpl</code> object as an <code>Object</code> in
5682      * the Java programming language, using the given
5683      * <code>java.util.Map</code> object to custom map the value if
5684      * appropriate.
5685      *
5686      * @param columnIndex the first column is <code>1</code>, the second
5687      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5688      *        and equal to or less than the number of columns in this rowset
5689      * @param map a <code>java.util.Map</code> object showing the mapping
5690      *            from SQL type names to classes in the Java programming
5691      *            language
5692      * @return an <code>Object</code> representing the SQL value
5693      * @throws SQLException if the given column index is out of bounds or
5694      *            the cursor is not on one of this rowset's rows or its
5695      *            insert row
5696      */
5697      public Object getObject(int columnIndex,
5698                              java.util.Map<String,Class<?>> map)
5699          throws SQLException
5700      {
5701         Object value;
5702 
5703         // sanity check.
5704         checkIndex(columnIndex);
5705         // make sure the cursor is on a valid row
5706         checkCursor();
5707 
5708         setLastValueNull(false);
5709         value = getCurrentRow().getColumnObject(columnIndex);
5710 
5711         // check for SQL NULL
5712         if (value == null) {
5713             setLastValueNull(true);
5714             return null;
5715         }
5716         if (value instanceof Struct) {
5717             Struct s = (Struct)value;
5718 
5719             // look up the class in the map
5720             Class<?> c = map.get(s.getSQLTypeName());
5721             if (c != null) {
5722                 // create new instance of the class
5723                 SQLData obj = null;
5724                 try {
5725                     ReflectUtil.checkPackageAccess(c);
5726                     @SuppressWarnings("deprecation")
5727                     Object tmp = c.newInstance();
5728                     obj = (SQLData) tmp;
5729                 } catch(Exception ex) {
5730                     throw new SQLException("Unable to Instantiate: ", ex);
5731                 }
5732                 // get the attributes from the struct
5733                 Object attribs[] = s.getAttributes(map);
5734                 // create the SQLInput "stream"
5735                 SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
5736                 // read the values...
5737                 obj.readSQL(sqlInput, s.getSQLTypeName());
5738                 return (Object)obj;
5739             }
5740         }
5741         return value;
5742     }
5743 
5744     /**
5745      * Retrieves the value of the designated column in this
5746      * <code>CachedRowSetImpl</code> object as a <code>Ref</code> object
5747      * in the Java programming language.
5748      *
5749      * @param columnIndex the first column is <code>1</code>, the second
5750      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5751      *        and equal to or less than the number of columns in this rowset
5752      * @return a <code>Ref</code> object representing an SQL<code> REF</code> value
5753      * @throws SQLException if (1) the given column index is out of bounds,
5754      *            (2) the cursor is not on one of this rowset's rows or its
5755      *            insert row, or (3) the designated column does not store an
5756      *            SQL <code>REF</code> value
5757      * @see #getRef(String)
5758      */
5759     public Ref getRef(int columnIndex) throws SQLException {
5760         Ref value;
5761 
5762         // sanity check.
5763         checkIndex(columnIndex);
5764         // make sure the cursor is on a valid row
5765         checkCursor();
5766 
5767         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.REF) {
5768             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5769         }
5770 
5771         setLastValueNull(false);
5772         value = (Ref)(getCurrentRow().getColumnObject(columnIndex));
5773 
5774         // check for SQL NULL
5775         if (value == null) {
5776             setLastValueNull(true);
5777             return null;
5778         }
5779 
5780         return value;
5781     }
5782 
5783     /**
5784      * Retrieves the value of the designated column in this
5785      * <code>CachedRowSetImpl</code> object as a <code>Blob</code> object
5786      * in the Java programming language.
5787      *
5788      * @param columnIndex the first column is <code>1</code>, the second
5789      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5790      *        and equal to or less than the number of columns in this rowset
5791      * @return a <code>Blob</code> object representing an SQL <code>BLOB</code> value
5792      * @throws SQLException if (1) the given column index is out of bounds,
5793      *            (2) the cursor is not on one of this rowset's rows or its
5794      *            insert row, or (3) the designated column does not store an
5795      *            SQL <code>BLOB</code> value
5796      * @see #getBlob(String)
5797      */
5798     public Blob getBlob(int columnIndex) throws SQLException {
5799         Blob value;
5800 
5801         // sanity check.
5802         checkIndex(columnIndex);
5803         // make sure the cursor is on a valid row
5804         checkCursor();
5805 
5806         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.BLOB) {
5807             System.out.println(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.type").toString(), RowSetMD.getColumnType(columnIndex)));
5808             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5809         }
5810 
5811         setLastValueNull(false);
5812         value = (Blob)(getCurrentRow().getColumnObject(columnIndex));
5813 
5814         // check for SQL NULL
5815         if (value == null) {
5816             setLastValueNull(true);
5817             return null;
5818         }
5819 
5820         return value;
5821     }
5822 
5823     /**
5824      * Retrieves the value of the designated column in this
5825      * <code>CachedRowSetImpl</code> object as a <code>Clob</code> object
5826      * in the Java programming language.
5827      *
5828      * @param columnIndex the first column is <code>1</code>, the second
5829      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5830      *        and equal to or less than the number of columns in this rowset
5831      * @return a <code>Clob</code> object representing an SQL <code>CLOB</code> value
5832      * @throws SQLException if (1) the given column index is out of bounds,
5833      *            (2) the cursor is not on one of this rowset's rows or its
5834      *            insert row, or (3) the designated column does not store an
5835      *            SQL <code>CLOB</code> value
5836      * @see #getClob(String)
5837      */
5838     public Clob getClob(int columnIndex) throws SQLException {
5839         Clob value;
5840 
5841         // sanity check.
5842         checkIndex(columnIndex);
5843         // make sure the cursor is on a valid row
5844         checkCursor();
5845 
5846         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.CLOB) {
5847             System.out.println(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.type").toString(), RowSetMD.getColumnType(columnIndex)));
5848             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5849         }
5850 
5851         setLastValueNull(false);
5852         value = (Clob)(getCurrentRow().getColumnObject(columnIndex));
5853 
5854         // check for SQL NULL
5855         if (value == null) {
5856             setLastValueNull(true);
5857             return null;
5858         }
5859 
5860         return value;
5861     }
5862 
5863     /**
5864      * Retrieves the value of the designated column in this
5865      * <code>CachedRowSetImpl</code> object as an <code>Array</code> object
5866      * in the Java programming language.
5867      *
5868      * @param columnIndex the first column is <code>1</code>, the second
5869      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5870      *        and equal to or less than the number of columns in this rowset
5871      * @return an <code>Array</code> object representing an SQL
5872      *         <code>ARRAY</code> value
5873      * @throws SQLException if (1) the given column index is out of bounds,
5874      *            (2) the cursor is not on one of this rowset's rows or its
5875      *            insert row, or (3) the designated column does not store an
5876      *            SQL <code>ARRAY</code> value
5877      * @see #getArray(String)
5878      */
5879     public Array getArray(int columnIndex) throws SQLException {
5880         java.sql.Array value;
5881 
5882         // sanity check.
5883         checkIndex(columnIndex);
5884         // make sure the cursor is on a valid row
5885         checkCursor();
5886 
5887         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.ARRAY) {
5888             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5889         }
5890 
5891         setLastValueNull(false);
5892         value = (java.sql.Array)(getCurrentRow().getColumnObject(columnIndex));
5893 
5894         // check for SQL NULL
5895         if (value == null) {
5896             setLastValueNull(true);
5897             return null;
5898         }
5899 
5900         return value;
5901     }
5902 
5903     /**
5904      * Retrieves the value of the designated column in this
5905      * <code>CachedRowSetImpl</code> object as an <code>Object</code> in
5906      * the Java programming language, using the given
5907      * <code>java.util.Map</code> object to custom map the value if
5908      * appropriate.
5909      *
5910      * @param columnName a <code>String</code> object that must match the
5911      *        SQL name of a column in this rowset, ignoring case
5912      * @param map a <code>java.util.Map</code> object showing the mapping
5913      *        from SQL type names to classes in the Java programming
5914      *        language
5915      * @return an <code>Object</code> representing the SQL value
5916      * @throws SQLException if the given column name is not the name of
5917      *         a column in this rowset or the cursor is not on one of
5918      *         this rowset's rows or its insert row
5919      */
5920     public Object getObject(String columnName,
5921                             java.util.Map<String,Class<?>> map)
5922     throws SQLException {
5923         return getObject(getColIdxByName(columnName), map);
5924     }
5925 
5926     /**
5927      * Retrieves the value of the designated column in this
5928      * <code>CachedRowSetImpl</code> object as a <code>Ref</code> object
5929      * in the Java programming language.
5930      *
5931      * @param colName a <code>String</code> object that must match the
5932      *        SQL name of a column in this rowset, ignoring case
5933      * @return a <code>Ref</code> object representing an SQL<code> REF</code> value
5934      * @throws SQLException  if (1) the given column name is not the name of
5935      *            a column in this rowset, (2) the cursor is not on one of
5936      *            this rowset's rows or its insert row, or (3) the column value
5937      *            is not an SQL <code>REF</code> value
5938      * @see #getRef(int)
5939      */
5940     public Ref getRef(String colName) throws SQLException {
5941         return getRef(getColIdxByName(colName));
5942     }
5943 
5944     /**
5945      * Retrieves the value of the designated column in this
5946      * <code>CachedRowSetImpl</code> object as a <code>Blob</code> object
5947      * in the Java programming language.
5948      *
5949      * @param colName a <code>String</code> object that must match the
5950      *        SQL name of a column in this rowset, ignoring case
5951      * @return a <code>Blob</code> object representing an SQL <code>BLOB</code> value
5952      * @throws SQLException if (1) the given column name is not the name of
5953      *            a column in this rowset, (2) the cursor is not on one of
5954      *            this rowset's rows or its insert row, or (3) the designated
5955      *            column does not store an SQL <code>BLOB</code> value
5956      * @see #getBlob(int)
5957      */
5958     public Blob getBlob(String colName) throws SQLException {
5959         return getBlob(getColIdxByName(colName));
5960     }
5961 
5962     /**
5963      * Retrieves the value of the designated column in this
5964      * <code>CachedRowSetImpl</code> object as a <code>Clob</code> object
5965      * in the Java programming language.
5966      *
5967      * @param colName a <code>String</code> object that must match the
5968      *        SQL name of a column in this rowset, ignoring case
5969      * @return a <code>Clob</code> object representing an SQL
5970      *         <code>CLOB</code> value
5971      * @throws SQLException if (1) the given column name is not the name of
5972      *            a column in this rowset, (2) the cursor is not on one of
5973      *            this rowset's rows or its insert row, or (3) the designated
5974      *            column does not store an SQL <code>CLOB</code> value
5975      * @see #getClob(int)
5976      */
5977     public Clob getClob(String colName) throws SQLException {
5978         return getClob(getColIdxByName(colName));
5979     }
5980 
5981     /**
5982      * Retrieves the value of the designated column in this
5983      * <code>CachedRowSetImpl</code> object as an <code>Array</code> object
5984      * in the Java programming langugage.
5985      *
5986      * @param colName a <code>String</code> object that must match the
5987      *        SQL name of a column in this rowset, ignoring case
5988      * @return an <code>Array</code> object representing an SQL
5989      *         <code>ARRAY</code> value
5990      * @throws SQLException if (1) the given column name is not the name of
5991      *            a column in this rowset, (2) the cursor is not on one of
5992      *            this rowset's rows or its insert row, or (3) the designated
5993      *            column does not store an SQL <code>ARRAY</code> value
5994      * @see #getArray(int)
5995      */
5996     public Array getArray(String colName) throws SQLException {
5997         return getArray(getColIdxByName(colName));
5998     }
5999 
6000     /**
6001      * Retrieves the value of the designated column in the current row
6002      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Date</code>
6003      * object, using the given <code>Calendar</code> object to construct an
6004      * appropriate millisecond value for the date.
6005      *
6006      * @param columnIndex the first column is <code>1</code>, the second
6007      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6008      *        and equal to or less than the number of columns in the rowset
6009      * @param cal the <code>java.util.Calendar</code> object to use in
6010      *            constructing the date
6011      * @return the column value; if the value is SQL <code>NULL</code>,
6012      *         the result is <code>null</code>
6013      * @throws SQLException if (1) the given column name is not the name of
6014      *            a column in this rowset, (2) the cursor is not on one of
6015      *            this rowset's rows or its insert row, or (3) the designated
6016      *            column does not store an SQL <code>DATE</code> or
6017      *            <code>TIMESTAMP</code> value
6018      */
6019     public java.sql.Date getDate(int columnIndex, Calendar cal) throws SQLException {
6020         Object value;
6021 
6022         // sanity check.
6023         checkIndex(columnIndex);
6024         // make sure the cursor is on a valid row
6025         checkCursor();
6026 
6027         setLastValueNull(false);
6028         value = getCurrentRow().getColumnObject(columnIndex);
6029 
6030         // check for SQL NULL
6031         if (value == null) {
6032             setLastValueNull(true);
6033             return null;
6034         }
6035 
6036         value = convertTemporal(value,
6037         RowSetMD.getColumnType(columnIndex),
6038         java.sql.Types.DATE);
6039 
6040         // create a default calendar
6041         Calendar defaultCal = Calendar.getInstance();
6042         // set this Calendar to the time we have
6043         defaultCal.setTime((java.util.Date)value);
6044 
6045         /*
6046          * Now we can pull the pieces of the date out
6047          * of the default calendar and put them into
6048          * the user provided calendar
6049          */
6050         cal.set(Calendar.YEAR, defaultCal.get(Calendar.YEAR));
6051         cal.set(Calendar.MONTH, defaultCal.get(Calendar.MONTH));
6052         cal.set(Calendar.DAY_OF_MONTH, defaultCal.get(Calendar.DAY_OF_MONTH));
6053 
6054         /*
6055          * This looks a little odd but it is correct -
6056          * Calendar.getTime() returns a Date...
6057          */
6058         return new java.sql.Date(cal.getTime().getTime());
6059     }
6060 
6061     /**
6062      * Retrieves the value of the designated column in the current row
6063      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Date</code>
6064      * object, using the given <code>Calendar</code> object to construct an
6065      * appropriate millisecond value for the date.
6066      *
6067      * @param columnName a <code>String</code> object that must match the
6068      *        SQL name of a column in this rowset, ignoring case
6069      * @param cal the <code>java.util.Calendar</code> object to use in
6070      *            constructing the date
6071      * @return the column value; if the value is SQL <code>NULL</code>,
6072      *         the result is <code>null</code>
6073      * @throws SQLException if (1) the given column name is not the name of
6074      *            a column in this rowset, (2) the cursor is not on one of
6075      *            this rowset's rows or its insert row, or (3) the designated
6076      *            column does not store an SQL <code>DATE</code> or
6077      *            <code>TIMESTAMP</code> value
6078      */
6079     public java.sql.Date getDate(String columnName, Calendar cal) throws SQLException {
6080         return getDate(getColIdxByName(columnName), cal);
6081     }
6082 
6083     /**
6084      * Retrieves the value of the designated column in the current row
6085      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Time</code>
6086      * object, using the given <code>Calendar</code> object to construct an
6087      * appropriate millisecond value for the date.
6088      *
6089      * @param columnIndex the first column is <code>1</code>, the second
6090      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6091      *        and equal to or less than the number of columns in the rowset
6092      * @param cal the <code>java.util.Calendar</code> object to use in
6093      *            constructing the date
6094      * @return the column value; if the value is SQL <code>NULL</code>,
6095      *         the result is <code>null</code>
6096      * @throws SQLException if (1) the given column name is not the name of
6097      *            a column in this rowset, (2) the cursor is not on one of
6098      *            this rowset's rows or its insert row, or (3) the designated
6099      *            column does not store an SQL <code>TIME</code> or
6100      *            <code>TIMESTAMP</code> value
6101      */
6102     public java.sql.Time getTime(int columnIndex, Calendar cal) throws SQLException {
6103         Object value;
6104 
6105         // sanity check.
6106         checkIndex(columnIndex);
6107         // make sure the cursor is on a valid row
6108         checkCursor();
6109 
6110         setLastValueNull(false);
6111         value = getCurrentRow().getColumnObject(columnIndex);
6112 
6113         // check for SQL NULL
6114         if (value == null) {
6115             setLastValueNull(true);
6116             return null;
6117         }
6118 
6119         value = convertTemporal(value,
6120         RowSetMD.getColumnType(columnIndex),
6121         java.sql.Types.TIME);
6122 
6123         // create a default calendar
6124         Calendar defaultCal = Calendar.getInstance();
6125         // set the time in the default calendar
6126         defaultCal.setTime((java.util.Date)value);
6127 
6128         /*
6129          * Now we can pull the pieces of the date out
6130          * of the default calendar and put them into
6131          * the user provided calendar
6132          */
6133         cal.set(Calendar.HOUR_OF_DAY, defaultCal.get(Calendar.HOUR_OF_DAY));
6134         cal.set(Calendar.MINUTE, defaultCal.get(Calendar.MINUTE));
6135         cal.set(Calendar.SECOND, defaultCal.get(Calendar.SECOND));
6136 
6137         return new java.sql.Time(cal.getTime().getTime());
6138     }
6139 
6140     /**
6141      * Retrieves the value of the designated column in the current row
6142      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Time</code>
6143      * object, using the given <code>Calendar</code> object to construct an
6144      * appropriate millisecond value for the date.
6145      *
6146      * @param columnName a <code>String</code> object that must match the
6147      *        SQL name of a column in this rowset, ignoring case
6148      * @param cal the <code>java.util.Calendar</code> object to use in
6149      *            constructing the date
6150      * @return the column value; if the value is SQL <code>NULL</code>,
6151      *         the result is <code>null</code>
6152      * @throws SQLException if (1) the given column name is not the name of
6153      *            a column in this rowset, (2) the cursor is not on one of
6154      *            this rowset's rows or its insert row, or (3) the designated
6155      *            column does not store an SQL <code>TIME</code> or
6156      *            <code>TIMESTAMP</code> value
6157      */
6158     public java.sql.Time getTime(String columnName, Calendar cal) throws SQLException {
6159         return getTime(getColIdxByName(columnName), cal);
6160     }
6161 
6162     /**
6163      * Retrieves the value of the designated column in the current row
6164      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Timestamp</code>
6165      * object, using the given <code>Calendar</code> object to construct an
6166      * appropriate millisecond value for the date.
6167      *
6168      * @param columnIndex the first column is <code>1</code>, the second
6169      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6170      *        and equal to or less than the number of columns in the rowset
6171      * @param cal the <code>java.util.Calendar</code> object to use in
6172      *            constructing the date
6173      * @return the column value; if the value is SQL <code>NULL</code>,
6174      *         the result is <code>null</code>
6175      * @throws SQLException if (1) the given column name is not the name of
6176      *            a column in this rowset, (2) the cursor is not on one of
6177      *            this rowset's rows or its insert row, or (3) the designated
6178      *            column does not store an SQL <code>TIME</code> or
6179      *            <code>TIMESTAMP</code> value
6180      */
6181     public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
6182         Object value;
6183 
6184         // sanity check.
6185         checkIndex(columnIndex);
6186         // make sure the cursor is on a valid row
6187         checkCursor();
6188 
6189         setLastValueNull(false);
6190         value = getCurrentRow().getColumnObject(columnIndex);
6191 
6192         // check for SQL NULL
6193         if (value == null) {
6194             setLastValueNull(true);
6195             return null;
6196         }
6197 
6198         value = convertTemporal(value,
6199         RowSetMD.getColumnType(columnIndex),
6200         java.sql.Types.TIMESTAMP);
6201 
6202         // create a default calendar
6203         Calendar defaultCal = Calendar.getInstance();
6204         // set the time in the default calendar
6205         defaultCal.setTime((java.util.Date)value);
6206 
6207         /*
6208          * Now we can pull the pieces of the date out
6209          * of the default calendar and put them into
6210          * the user provided calendar
6211          */
6212         cal.set(Calendar.YEAR, defaultCal.get(Calendar.YEAR));
6213         cal.set(Calendar.MONTH, defaultCal.get(Calendar.MONTH));
6214         cal.set(Calendar.DAY_OF_MONTH, defaultCal.get(Calendar.DAY_OF_MONTH));
6215         cal.set(Calendar.HOUR_OF_DAY, defaultCal.get(Calendar.HOUR_OF_DAY));
6216         cal.set(Calendar.MINUTE, defaultCal.get(Calendar.MINUTE));
6217         cal.set(Calendar.SECOND, defaultCal.get(Calendar.SECOND));
6218 
6219         return new java.sql.Timestamp(cal.getTime().getTime());
6220     }
6221 
6222     /**
6223      * Retrieves the value of the designated column in the current row
6224      * of this <code>CachedRowSetImpl</code> object as a
6225      * <code>java.sql.Timestamp</code> object, using the given
6226      * <code>Calendar</code> object to construct an appropriate
6227      * millisecond value for the date.
6228      *
6229      * @param columnName a <code>String</code> object that must match the
6230      *        SQL name of a column in this rowset, ignoring case
6231      * @param cal the <code>java.util.Calendar</code> object to use in
6232      *            constructing the date
6233      * @return the column value; if the value is SQL <code>NULL</code>,
6234      *         the result is <code>null</code>
6235      * @throws SQLException if (1) the given column name is not the name of
6236      *            a column in this rowset, (2) the cursor is not on one of
6237      *            this rowset's rows or its insert row, or (3) the designated
6238      *            column does not store an SQL <code>DATE</code>,
6239      *            <code>TIME</code>, or <code>TIMESTAMP</code> value
6240      */
6241     public java.sql.Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException {
6242         return getTimestamp(getColIdxByName(columnName), cal);
6243     }
6244 
6245     /*
6246      * RowSetInternal Interface
6247      */
6248 
6249     /**
6250      * Retrieves the <code>Connection</code> object passed to this
6251      * <code>CachedRowSetImpl</code> object.  This connection may be
6252      * used to populate this rowset with data or to write data back
6253      * to its underlying data source.
6254      *
6255      * @return the <code>Connection</code> object passed to this rowset;
6256      *         may be <code>null</code> if there is no connection
6257      * @throws SQLException if an error occurs
6258      */
6259     public Connection getConnection() throws SQLException{
6260         return conn;
6261     }
6262 
6263     /**
6264      * Sets the metadata for this <code>CachedRowSetImpl</code> object
6265      * with the given <code>RowSetMetaData</code> object.
6266      *
6267      * @param md a <code>RowSetMetaData</code> object instance containing
6268      *            metadata about the columsn in the rowset
6269      * @throws SQLException if invalid meta data is supplied to the
6270      *            rowset
6271      */
6272     public void setMetaData(RowSetMetaData md) throws SQLException {
6273         RowSetMD =(RowSetMetaDataImpl) md;
6274     }
6275 
6276     /**
6277      * Returns a result set containing the original value of the rowset. The
6278      * original value is the state of the <code>CachedRowSetImpl</code> after the
6279      * last population or synchronization (whichever occurred most recently) with
6280      * the data source.
6281      * <p>
6282      * The cursor is positioned before the first row in the result set.
6283      * Only rows contained in the result set returned by <code>getOriginal()</code>
6284      * are said to have an original value.
6285      *
6286      * @return the original result set of the rowset
6287      * @throws SQLException if an error occurs produce the
6288      *           <code>ResultSet</code> object
6289      */
6290     public ResultSet getOriginal() throws SQLException {
6291         CachedRowSetImpl crs = new CachedRowSetImpl();
6292         crs.RowSetMD = RowSetMD;
6293         crs.numRows = numRows;
6294         crs.cursorPos = 0;
6295 
6296         // make sure we don't get someone playing with these
6297         // %%% is this now necessary ???
6298         //crs.setReader(null);
6299         //crs.setWriter(null);
6300         int colCount = RowSetMD.getColumnCount();
6301         Row orig;
6302 
6303         for (Iterator<?> i = rvh.iterator(); i.hasNext();) {
6304             orig = new Row(colCount, ((Row)i.next()).getOrigRow());
6305             crs.rvh.add(orig);
6306         }
6307         return (ResultSet)crs;
6308     }
6309 
6310     /**
6311      * Returns a result set containing the original value of the current
6312      * row only.
6313      * The original value is the state of the <code>CachedRowSetImpl</code> after
6314      * the last population or synchronization (whichever occurred most recently)
6315      * with the data source.
6316      *
6317      * @return the original result set of the row
6318      * @throws SQLException if there is no current row
6319      * @see #setOriginalRow
6320      */
6321     public ResultSet getOriginalRow() throws SQLException {
6322         CachedRowSetImpl crs = new CachedRowSetImpl();
6323         crs.RowSetMD = RowSetMD;
6324         crs.numRows = 1;
6325         crs.cursorPos = 0;
6326         crs.setTypeMap(this.getTypeMap());
6327 
6328         // make sure we don't get someone playing with these
6329         // %%% is this now necessary ???
6330         //crs.setReader(null);
6331         //crs.setWriter(null);
6332 
6333         Row orig = new Row(RowSetMD.getColumnCount(),
6334         getCurrentRow().getOrigRow());
6335 
6336         crs.rvh.add(orig);
6337 
6338         return (ResultSet)crs;
6339 
6340     }
6341 
6342     /**
6343      * Marks the current row in this rowset as being an original row.
6344      *
6345      * @throws SQLException if there is no current row
6346      * @see #getOriginalRow
6347      */
6348     public void setOriginalRow() throws SQLException {
6349         if (onInsertRow == true) {
6350             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
6351         }
6352 
6353         Row row = (Row)getCurrentRow();
6354         makeRowOriginal(row);
6355 
6356         // this can happen if deleted rows are being shown
6357         if (row.getDeleted() == true) {
6358             removeCurrentRow();
6359         }
6360     }
6361 
6362     /**
6363      * Makes the given row of this rowset the original row by clearing any
6364      * settings that mark the row as having been inserted, deleted, or updated.
6365      * This method is called internally by the methods
6366      * <code>setOriginalRow</code>
6367      * and <code>setOriginal</code>.
6368      *
6369      * @param row the row to be made the original row
6370      */
6371     private void makeRowOriginal(Row row) {
6372         if (row.getInserted() == true) {
6373             row.clearInserted();
6374         }
6375 
6376         if (row.getUpdated() == true) {
6377             row.moveCurrentToOrig();
6378         }
6379     }
6380 
6381     /**
6382      * Marks all rows in this rowset as being original rows. Any updates
6383      * made to the rows become the original values for the rowset.
6384      * Calls to the method <code>setOriginal</code> connot be reversed.
6385      *
6386      * @throws SQLException if an error occurs
6387      */
6388     public void setOriginal() throws SQLException {
6389         for (Iterator<?> i = rvh.iterator(); i.hasNext();) {
6390             Row row = (Row)i.next();
6391             makeRowOriginal(row);
6392             // remove deleted rows from the collection.
6393             if (row.getDeleted() == true) {
6394                 i.remove();
6395                 --numRows;
6396             }
6397         }
6398         numDeleted = 0;
6399 
6400         // notify any listeners that the rowset has changed
6401         notifyRowSetChanged();
6402     }
6403 
6404     /**
6405      * Returns an identifier for the object (table) that was used to create this
6406      * rowset.
6407      *
6408      * @return a <code>String</code> object that identifies the table from
6409      *         which this <code>CachedRowSetImpl</code> object was derived
6410      * @throws SQLException if an error occurs
6411      */
6412     public String getTableName() throws SQLException {
6413         return tableName;
6414     }
6415 
6416     /**
6417      * Sets the identifier for the table from which this rowset was derived
6418      * to the given table name.
6419      *
6420      * @param tabName a <code>String</code> object that identifies the
6421      *          table from which this <code>CachedRowSetImpl</code> object
6422      *          was derived
6423      * @throws SQLException if an error occurs
6424      */
6425     public void setTableName(String tabName) throws SQLException {
6426         if (tabName == null)
6427             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.tablename").toString());
6428         else
6429             tableName = tabName;
6430     }
6431 
6432     /**
6433      * Returns the columns that make a key to uniquely identify a
6434      * row in this <code>CachedRowSetImpl</code> object.
6435      *
6436      * @return an array of column numbers that constitutes a primary
6437      *           key for this rowset. This array should be empty
6438      *           if no column is representitive of a primary key
6439      * @throws SQLException if the rowset is empty or no columns
6440      *           are designated as primary keys
6441      * @see #setKeyColumns
6442      */
6443     public int[] getKeyColumns() throws SQLException {
6444         int[]keyColumns  = this.keyCols;
6445         return (keyColumns == null) ? null : Arrays.copyOf(keyColumns, keyColumns.length);
6446     }
6447 
6448 
6449     /**
6450      * Sets this <code>CachedRowSetImpl</code> object's
6451      * <code>keyCols</code> field with the given array of column
6452      * numbers, which forms a key for uniquely identifying a row
6453      * in this rowset.
6454      *
6455      * @param keys an array of <code>int</code> indicating the
6456      *        columns that form a primary key for this
6457      *        <code>CachedRowSetImpl</code> object; every
6458      *        element in the array must be greater than
6459      *        <code>0</code> and less than or equal to the number
6460      *        of columns in this rowset
6461      * @throws SQLException if any of the numbers in the
6462      *            given array is not valid for this rowset
6463      * @see #getKeyColumns
6464      */
6465     public void setKeyColumns(int [] keys) throws SQLException {
6466         int numCols = 0;
6467         if (RowSetMD != null) {
6468             numCols = RowSetMD.getColumnCount();
6469             if (keys.length > numCols)
6470                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.keycols").toString());
6471         }
6472         keyCols = new int[keys.length];
6473         for (int i = 0; i < keys.length; i++) {
6474             if (RowSetMD != null && (keys[i] <= 0 ||
6475             keys[i] > numCols)) {
6476                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcol").toString() +
6477                 keys[i]);
6478             }
6479             keyCols[i] = keys[i];
6480         }
6481     }
6482 
6483     /**
6484      * Sets the designated column in either the current row or the insert
6485      * row of this <code>CachedRowSetImpl</code> object with the given
6486      * <code>Ref</code> value.
6487      *
6488      * This method updates a column value in either the current row or
6489      * the insert row of this rowset, but it does not update the
6490      * database.  If the cursor is on a row in the rowset, the
6491      * method {@link #updateRow} must be called to update the database.
6492      * If the cursor is on the insert row, the method {@link #insertRow}
6493      * must be called, which will insert the new row into both this rowset
6494      * and the database. Both of these methods must be called before the
6495      * cursor moves to another row.
6496      *
6497      * @param columnIndex the first column is <code>1</code>, the second
6498      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6499      *        and equal to or less than the number of columns in this rowset
6500      * @param ref the new column <code>java.sql.Ref</code> value
6501      * @throws SQLException if (1) the given column index is out of bounds,
6502      *        (2) the cursor is not on one of this rowset's rows or its
6503      *        insert row, or (3) this rowset is
6504      *        <code>ResultSet.CONCUR_READ_ONLY</code>
6505      */
6506     public void updateRef(int columnIndex, java.sql.Ref ref) throws SQLException {
6507         // sanity check.
6508         checkIndex(columnIndex);
6509         // make sure the cursor is on a valid row
6510         checkCursor();
6511 
6512         // SerialClob will help in getting the byte array and storing it.
6513         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6514         // or through RowSetMetaData.locatorsUpdatorCopy()
6515         getCurrentRow().setColumnObject(columnIndex, new SerialRef(ref));
6516     }
6517 
6518     /**
6519      * Sets the designated column in either the current row or the insert
6520      * row of this <code>CachedRowSetImpl</code> object with the given
6521      * <code>double</code> value.
6522      *
6523      * This method updates a column value in either the current row or
6524      * the insert row of this rowset, but it does not update the
6525      * database.  If the cursor is on a row in the rowset, the
6526      * method {@link #updateRow} must be called to update the database.
6527      * If the cursor is on the insert row, the method {@link #insertRow}
6528      * must be called, which will insert the new row into both this rowset
6529      * and the database. Both of these methods must be called before the
6530      * cursor moves to another row.
6531      *
6532      * @param columnName a <code>String</code> object that must match the
6533      *        SQL name of a column in this rowset, ignoring case
6534      * @param ref the new column <code>java.sql.Ref</code> value
6535      * @throws SQLException if (1) the given column name does not match the
6536      *        name of a column in this rowset, (2) the cursor is not on
6537      *        one of this rowset's rows or its insert row, or (3) this
6538      *        rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6539      */
6540     public void updateRef(String columnName, java.sql.Ref ref) throws SQLException {
6541         updateRef(getColIdxByName(columnName), ref);
6542     }
6543 
6544     /**
6545      * Sets the designated column in either the current row or the insert
6546      * row of this <code>CachedRowSetImpl</code> object with the given
6547      * <code>double</code> value.
6548      *
6549      * This method updates a column value in either the current row or
6550      * the insert row of this rowset, but it does not update the
6551      * database.  If the cursor is on a row in the rowset, the
6552      * method {@link #updateRow} must be called to update the database.
6553      * If the cursor is on the insert row, the method {@link #insertRow}
6554      * must be called, which will insert the new row into both this rowset
6555      * and the database. Both of these methods must be called before the
6556      * cursor moves to another row.
6557      *
6558      * @param columnIndex the first column is <code>1</code>, the second
6559      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6560      *        and equal to or less than the number of columns in this rowset
6561      * @param c the new column <code>Clob</code> value
6562      * @throws SQLException if (1) the given column index is out of bounds,
6563      *        (2) the cursor is not on one of this rowset's rows or its
6564      *        insert row, or (3) this rowset is
6565      *        <code>ResultSet.CONCUR_READ_ONLY</code>
6566      */
6567     public void updateClob(int columnIndex, Clob c) throws SQLException {
6568         // sanity check.
6569         checkIndex(columnIndex);
6570         // make sure the cursor is on a valid row
6571         checkCursor();
6572 
6573         // SerialClob will help in getting the byte array and storing it.
6574         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6575         // or through RowSetMetaData.locatorsUpdatorCopy()
6576 
6577         if(dbmslocatorsUpdateCopy){
6578            getCurrentRow().setColumnObject(columnIndex, new SerialClob(c));
6579         }
6580         else{
6581            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.opnotsupp").toString());
6582         }
6583     }
6584 
6585     /**
6586      * Sets the designated column in either the current row or the insert
6587      * row of this <code>CachedRowSetImpl</code> object with the given
6588      * <code>double</code> value.
6589      *
6590      * This method updates a column value in either the current row or
6591      * the insert row of this rowset, but it does not update the
6592      * database.  If the cursor is on a row in the rowset, the
6593      * method {@link #updateRow} must be called to update the database.
6594      * If the cursor is on the insert row, the method {@link #insertRow}
6595      * must be called, which will insert the new row into both this rowset
6596      * and the database. Both of these methods must be called before the
6597      * cursor moves to another row.
6598      *
6599      * @param columnName a <code>String</code> object that must match the
6600      *        SQL name of a column in this rowset, ignoring case
6601      * @param c the new column <code>Clob</code> value
6602      * @throws SQLException if (1) the given column name does not match the
6603      *            name of a column in this rowset, (2) the cursor is not on
6604      *            one of this rowset's rows or its insert row, or (3) this
6605      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6606      */
6607     public void updateClob(String columnName, Clob c) throws SQLException {
6608         updateClob(getColIdxByName(columnName), c);
6609     }
6610 
6611     /**
6612      * Sets the designated column in either the current row or the insert
6613      * row of this <code>CachedRowSetImpl</code> object with the given
6614      * <code>java.sql.Blob</code> value.
6615      *
6616      * This method updates a column value in either the current row or
6617      * the insert row of this rowset, but it does not update the
6618      * database.  If the cursor is on a row in the rowset, the
6619      * method {@link #updateRow} must be called to update the database.
6620      * If the cursor is on the insert row, the method {@link #insertRow}
6621      * must be called, which will insert the new row into both this rowset
6622      * and the database. Both of these methods must be called before the
6623      * cursor moves to another row.
6624      *
6625      * @param columnIndex the first column is <code>1</code>, the second
6626      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6627      *        and equal to or less than the number of columns in this rowset
6628      * @param b the new column <code>Blob</code> value
6629      * @throws SQLException if (1) the given column index is out of bounds,
6630      *            (2) the cursor is not on one of this rowset's rows or its
6631      *            insert row, or (3) this rowset is
6632      *            <code>ResultSet.CONCUR_READ_ONLY</code>
6633      */
6634     public void updateBlob(int columnIndex, Blob b) throws SQLException {
6635         // sanity check.
6636         checkIndex(columnIndex);
6637         // make sure the cursor is on a valid row
6638         checkCursor();
6639 
6640         // SerialBlob will help in getting the byte array and storing it.
6641         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6642         // or through RowSetMetaData.locatorsUpdatorCopy()
6643 
6644         if(dbmslocatorsUpdateCopy){
6645            getCurrentRow().setColumnObject(columnIndex, new SerialBlob(b));
6646         }
6647         else{
6648            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.opnotsupp").toString());
6649         }
6650     }
6651 
6652     /**
6653      * Sets the designated column in either the current row or the insert
6654      * row of this <code>CachedRowSetImpl</code> object with the given
6655      * <code>java.sql.Blob </code> value.
6656      *
6657      * This method updates a column value in either the current row or
6658      * the insert row of this rowset, but it does not update the
6659      * database.  If the cursor is on a row in the rowset, the
6660      * method {@link #updateRow} must be called to update the database.
6661      * If the cursor is on the insert row, the method {@link #insertRow}
6662      * must be called, which will insert the new row into both this rowset
6663      * and the database. Both of these methods must be called before the
6664      * cursor moves to another row.
6665      *
6666      * @param columnName a <code>String</code> object that must match the
6667      *        SQL name of a column in this rowset, ignoring case
6668      * @param b the new column <code>Blob</code> value
6669      * @throws SQLException if (1) the given column name does not match the
6670      *            name of a column in this rowset, (2) the cursor is not on
6671      *            one of this rowset's rows or its insert row, or (3) this
6672      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6673      */
6674     public void updateBlob(String columnName, Blob b) throws SQLException {
6675         updateBlob(getColIdxByName(columnName), b);
6676     }
6677 
6678     /**
6679      * Sets the designated column in either the current row or the insert
6680      * row of this <code>CachedRowSetImpl</code> object with the given
6681      * <code>java.sql.Array</code> values.
6682      *
6683      * This method updates a column value in either the current row or
6684      * the insert row of this rowset, but it does not update the
6685      * database.  If the cursor is on a row in the rowset, the
6686      * method {@link #updateRow} must be called to update the database.
6687      * If the cursor is on the insert row, the method {@link #insertRow}
6688      * must be called, which will insert the new row into both this rowset
6689      * and the database. Both of these methods must be called before the
6690      * cursor moves to another row.
6691      *
6692      * @param columnIndex the first column is <code>1</code>, the second
6693      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6694      *        and equal to or less than the number of columns in this rowset
6695      * @param a the new column <code>Array</code> value
6696      * @throws SQLException if (1) the given column index is out of bounds,
6697      *            (2) the cursor is not on one of this rowset's rows or its
6698      *            insert row, or (3) this rowset is
6699      *            <code>ResultSet.CONCUR_READ_ONLY</code>
6700      */
6701     public void updateArray(int columnIndex, Array a) throws SQLException {
6702         // sanity check.
6703         checkIndex(columnIndex);
6704         // make sure the cursor is on a valid row
6705         checkCursor();
6706 
6707         // SerialArray will help in getting the byte array and storing it.
6708         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6709         // or through RowSetMetaData.locatorsUpdatorCopy()
6710         getCurrentRow().setColumnObject(columnIndex, new SerialArray(a));
6711     }
6712 
6713     /**
6714      * Sets the designated column in either the current row or the insert
6715      * row of this <code>CachedRowSetImpl</code> object with the given
6716      * <code>java.sql.Array</code> value.
6717      *
6718      * This method updates a column value in either the current row or
6719      * the insert row of this rowset, but it does not update the
6720      * database.  If the cursor is on a row in the rowset, the
6721      * method {@link #updateRow} must be called to update the database.
6722      * If the cursor is on the insert row, the method {@link #insertRow}
6723      * must be called, which will insert the new row into both this rowset
6724      * and the database. Both of these methods must be called before the
6725      * cursor moves to another row.
6726      *
6727      * @param columnName a <code>String</code> object that must match the
6728      *        SQL name of a column in this rowset, ignoring case
6729      * @param a the new column <code>Array</code> value
6730      * @throws SQLException if (1) the given column name does not match the
6731      *            name of a column in this rowset, (2) the cursor is not on
6732      *            one of this rowset's rows or its insert row, or (3) this
6733      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6734      */
6735     public void updateArray(String columnName, Array a) throws SQLException {
6736         updateArray(getColIdxByName(columnName), a);
6737     }
6738 
6739 
6740     /**
6741      * Retrieves the value of the designated column in this
6742      * <code>CachedRowSetImpl</code> object as a <code>java.net.URL</code> object
6743      * in the Java programming language.
6744      *
6745      * @return a java.net.URL object containing the resource reference described by
6746      * the URL
6747      * @throws SQLException if (1) the given column index is out of bounds,
6748      * (2) the cursor is not on one of this rowset's rows or its
6749      * insert row, or (3) the designated column does not store an
6750      * SQL <code>DATALINK</code> value.
6751      * @see #getURL(String)
6752      */
6753     public java.net.URL getURL(int columnIndex) throws SQLException {
6754         //throw new SQLException("Operation not supported");
6755 
6756         java.net.URL value;
6757 
6758         // sanity check.
6759         checkIndex(columnIndex);
6760         // make sure the cursor is on a valid row
6761         checkCursor();
6762 
6763         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.DATALINK) {
6764             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
6765         }
6766 
6767         setLastValueNull(false);
6768         value = (java.net.URL)(getCurrentRow().getColumnObject(columnIndex));
6769 
6770         // check for SQL NULL
6771         if (value == null) {
6772             setLastValueNull(true);
6773             return null;
6774         }
6775 
6776         return value;
6777     }
6778 
6779     /**
6780      * Retrieves the value of the designated column in this
6781      * <code>CachedRowSetImpl</code> object as a <code>java.net.URL</code> object
6782      * in the Java programming language.
6783      *
6784      * @return a java.net.URL object containing the resource reference described by
6785      * the URL
6786      * @throws SQLException if (1) the given column name not the name of a column
6787      * in this rowset, or
6788      * (2) the cursor is not on one of this rowset's rows or its
6789      * insert row, or (3) the designated column does not store an
6790      * SQL <code>DATALINK</code> value.
6791      * @see #getURL(int)
6792      */
6793     public java.net.URL getURL(String columnName) throws SQLException {
6794         return getURL(getColIdxByName(columnName));
6795 
6796     }
6797 
6798     /**
6799      * The first warning reported by calls on this <code>CachedRowSetImpl</code>
6800      * object is returned. Subsequent <code>CachedRowSetImpl</code> warnings will
6801      * be chained to this <code>SQLWarning</code>. All <code>RowSetWarnings</code>
6802      * warnings are generated in the disconnected environment and remain a
6803      * seperate warning chain to that provided by the <code>getWarnings</code>
6804      * method.
6805      *
6806      * <P>The warning chain is automatically cleared each time a new
6807      * row is read.
6808      *
6809      * <P><B>Note:</B> This warning chain only covers warnings caused
6810      * by <code>CachedRowSet</code> (and their child interface)
6811      * methods. All <code>SQLWarnings</code> can be obtained using the
6812      * <code>getWarnings</code> method which tracks warnings generated
6813      * by the underlying JDBC driver.
6814      * @return the first SQLWarning or null
6815      *
6816      */
6817     public RowSetWarning getRowSetWarnings() {
6818         try {
6819             notifyCursorMoved();
6820         } catch (SQLException e) {} // mask exception
6821         return rowsetWarning;
6822     }
6823 
6824 
6825     /**
6826      * The function tries to isolate the tablename when only setCommand
6827      * is set and not setTablename is called provided there is only one table
6828      * name in the query else just leaves the setting of table name as such.
6829      * If setTablename is set later it will over ride this table name
6830      * value so retrieved.
6831      *
6832      * @return the tablename if only one table in query else return ""
6833      */
6834     private String buildTableName(String command) throws SQLException {
6835 
6836         // If we have a query from one table,
6837         // we set the table name implicitly
6838         // else user has to explicitly set the table name.
6839 
6840         int indexFrom, indexComma;
6841         String strTablename ="";
6842         command = command.trim();
6843 
6844         // Query can be a select, insert or  update
6845 
6846         if(command.toLowerCase().startsWith("select")) {
6847             // look for "from" keyword, after that look for a
6848             // comma after from. If comma is there don't set
6849             // table name else isolate table name.
6850 
6851             indexFrom = command.toLowerCase().indexOf("from");
6852             indexComma = command.indexOf(',', indexFrom);
6853 
6854             if(indexComma == -1) {
6855                 // implies only one table
6856                 strTablename = (command.substring(indexFrom+"from".length(),command.length())).trim();
6857 
6858                 String tabName = strTablename;
6859 
6860                 int idxWhere = tabName.toLowerCase().indexOf("where");
6861 
6862                 /**
6863                   * Adding the addtional check for conditions following the table name.
6864                   * If a condition is found truncate it.
6865                   **/
6866 
6867                 if(idxWhere != -1)
6868                 {
6869                    tabName = tabName.substring(0,idxWhere).trim();
6870                 }
6871 
6872                 strTablename = tabName;
6873 
6874             } else {
6875                 //strTablename="";
6876             }
6877 
6878         } else if(command.toLowerCase().startsWith("insert")) {
6879             //strTablename="";
6880         } else if(command.toLowerCase().startsWith("update")) {
6881             //strTablename="";
6882         }
6883         return strTablename;
6884     }
6885 
6886     /**
6887      * Commits all changes performed by the <code>acceptChanges()</code>
6888      * methods
6889      *
6890      * @see java.sql.Connection#commit
6891      */
6892     public void commit() throws SQLException {
6893         conn.commit();
6894     }
6895 
6896     /**
6897      * Rolls back all changes performed by the <code>acceptChanges()</code>
6898      * methods
6899      *
6900      * @see java.sql.Connection#rollback
6901      */
6902     public void rollback() throws SQLException {
6903         conn.rollback();
6904     }
6905 
6906     /**
6907      * Rolls back all changes performed by the <code>acceptChanges()</code>
6908      * to the last <code>Savepoint</code> transaction marker.
6909      *
6910      * @see java.sql.Connection#rollback(Savepoint)
6911      */
6912     public void rollback(Savepoint s) throws SQLException {
6913         conn.rollback(s);
6914     }
6915 
6916     /**
6917      * Unsets the designated parameter to the given int array.
6918      * This was set using <code>setMatchColumn</code>
6919      * as the column which will form the basis of the join.
6920      * <P>
6921      * The parameter value unset by this method should be same
6922      * as was set.
6923      *
6924      * @param columnIdxes the index into this rowset
6925      *        object's internal representation of parameter values
6926      * @throws SQLException if an error occurs or the
6927      *  parameter index is out of bounds or if the columnIdx is
6928      *  not the same as set using <code>setMatchColumn(int [])</code>
6929      */
6930     public void unsetMatchColumn(int[] columnIdxes) throws SQLException {
6931 
6932          int i_val;
6933          for( int j= 0 ;j < columnIdxes.length; j++) {
6934             i_val = (Integer.parseInt(iMatchColumns.get(j).toString()));
6935             if(columnIdxes[j] != i_val) {
6936                throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols").toString());
6937             }
6938          }
6939 
6940          for( int i = 0;i < columnIdxes.length ;i++) {
6941             iMatchColumns.set(i, -1);
6942          }
6943     }
6944 
6945    /**
6946      * Unsets the designated parameter to the given String array.
6947      * This was set using <code>setMatchColumn</code>
6948      * as the column which will form the basis of the join.
6949      * <P>
6950      * The parameter value unset by this method should be same
6951      * as was set.
6952      *
6953      * @param columnIdxes the index into this rowset
6954      *        object's internal representation of parameter values
6955      * @throws SQLException if an error occurs or the
6956      *  parameter index is out of bounds or if the columnName is
6957      *  not the same as set using <code>setMatchColumn(String [])</code>
6958      */
6959     public void unsetMatchColumn(String[] columnIdxes) throws SQLException {
6960 
6961         for(int j = 0 ;j < columnIdxes.length; j++) {
6962            if( !columnIdxes[j].equals(strMatchColumns.get(j)) ){
6963               throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols").toString());
6964            }
6965         }
6966 
6967         for(int i = 0 ; i < columnIdxes.length; i++) {
6968            strMatchColumns.set(i,null);
6969         }
6970     }
6971 
6972     /**
6973      * Retrieves the column name as <code>String</code> array
6974      * that was set using <code>setMatchColumn(String [])</code>
6975      * for this rowset.
6976      *
6977      * @return a <code>String</code> array object that contains the column names
6978      *         for the rowset which has this the match columns
6979      *
6980      * @throws SQLException if an error occurs or column name is not set
6981      */
6982     public String[] getMatchColumnNames() throws SQLException {
6983 
6984         String []str_temp = new String[strMatchColumns.size()];
6985 
6986         if( strMatchColumns.get(0) == null) {
6987            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.setmatchcols").toString());
6988         }
6989 
6990         strMatchColumns.copyInto(str_temp);
6991         return str_temp;
6992     }
6993 
6994     /**
6995      * Retrieves the column id as <code>int</code> array that was set using
6996      * <code>setMatchColumn(int [])</code> for this rowset.
6997      *
6998      * @return a <code>int</code> array object that contains the column ids
6999      *         for the rowset which has this as the match columns.
7000      *
7001      * @throws SQLException if an error occurs or column index is not set
7002      */
7003     public int[] getMatchColumnIndexes() throws SQLException {
7004 
7005         Integer []int_temp = new Integer[iMatchColumns.size()];
7006         int [] i_temp = new int[iMatchColumns.size()];
7007         int i_val;
7008 
7009         i_val = iMatchColumns.get(0);
7010 
7011         if( i_val == -1 ) {
7012            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.setmatchcols").toString());
7013         }
7014 
7015 
7016         iMatchColumns.copyInto(int_temp);
7017 
7018         for(int i = 0; i < int_temp.length; i++) {
7019            i_temp[i] = (int_temp[i]).intValue();
7020         }
7021 
7022         return i_temp;
7023     }
7024 
7025     /**
7026      * Sets the designated parameter to the given int array.
7027      * This forms the basis of the join for the
7028      * <code>JoinRowSet</code> as the column which will form the basis of the
7029      * join.
7030      * <P>
7031      * The parameter value set by this method is stored internally and
7032      * will be supplied as the appropriate parameter in this rowset's
7033      * command when the method <code>getMatchColumnIndexes</code> is called.
7034      *
7035      * @param columnIdxes the indexes into this rowset
7036      *        object's internal representation of parameter values; the
7037      *        first parameter is 0, the second is 1, and so on; must be
7038      *        <code>0</code> or greater
7039      * @throws SQLException if an error occurs or the
7040      *                         parameter index is out of bounds
7041      */
7042     public void setMatchColumn(int[] columnIdxes) throws SQLException {
7043 
7044         for(int j = 0 ; j < columnIdxes.length; j++) {
7045            if( columnIdxes[j] < 0 ) {
7046               throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols1").toString());
7047            }
7048         }
7049         for(int i = 0 ;i < columnIdxes.length; i++) {
7050            iMatchColumns.add(i,columnIdxes[i]);
7051         }
7052     }
7053 
7054     /**
7055      * Sets the designated parameter to the given String array.
7056      *  This forms the basis of the join for the
7057      * <code>JoinRowSet</code> as the column which will form the basis of the
7058      * join.
7059      * <P>
7060      * The parameter value set by this method is stored internally and
7061      * will be supplied as the appropriate parameter in this rowset's
7062      * command when the method <code>getMatchColumn</code> is called.
7063      *
7064      * @param columnNames the name of the column into this rowset
7065      *        object's internal representation of parameter values
7066      * @throws SQLException if an error occurs or the
7067      *  parameter index is out of bounds
7068      */
7069     public void setMatchColumn(String[] columnNames) throws SQLException {
7070 
7071         for(int j = 0; j < columnNames.length; j++) {
7072            if( columnNames[j] == null || columnNames[j].equals("")) {
7073               throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols2").toString());
7074            }
7075         }
7076         for( int i = 0; i < columnNames.length; i++) {
7077            strMatchColumns.add(i,columnNames[i]);
7078         }
7079     }
7080 
7081 
7082     /**
7083      * Sets the designated parameter to the given <code>int</code>
7084      * object.  This forms the basis of the join for the
7085      * <code>JoinRowSet</code> as the column which will form the basis of the
7086      * join.
7087      * <P>
7088      * The parameter value set by this method is stored internally and
7089      * will be supplied as the appropriate parameter in this rowset's
7090      * command when the method <code>getMatchColumn</code> is called.
7091      *
7092      * @param columnIdx the index into this rowset
7093      *        object's internal representation of parameter values; the
7094      *        first parameter is 0, the second is 1, and so on; must be
7095      *        <code>0</code> or greater
7096      * @throws SQLException if an error occurs or the
7097      *                         parameter index is out of bounds
7098      */
7099     public void setMatchColumn(int columnIdx) throws SQLException {
7100         // validate, if col is ok to be set
7101         if(columnIdx < 0) {
7102             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols1").toString());
7103         } else {
7104             // set iMatchColumn
7105             iMatchColumns.set(0, columnIdx);
7106             //strMatchColumn = null;
7107         }
7108     }
7109 
7110     /**
7111      * Sets the designated parameter to the given <code>String</code>
7112      * object.  This forms the basis of the join for the
7113      * <code>JoinRowSet</code> as the column which will form the basis of the
7114      * join.
7115      * <P>
7116      * The parameter value set by this method is stored internally and
7117      * will be supplied as the appropriate parameter in this rowset's
7118      * command when the method <code>getMatchColumn</code> is called.
7119      *
7120      * @param columnName the name of the column into this rowset
7121      *        object's internal representation of parameter values
7122      * @throws SQLException if an error occurs or the
7123      *  parameter index is out of bounds
7124      */
7125     public void setMatchColumn(String columnName) throws SQLException {
7126         // validate, if col is ok to be set
7127         if(columnName == null || (columnName= columnName.trim()).equals("") ) {
7128             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols2").toString());
7129         } else {
7130             // set strMatchColumn
7131             strMatchColumns.set(0, columnName);
7132             //iMatchColumn = -1;
7133         }
7134     }
7135 
7136     /**
7137      * Unsets the designated parameter to the given <code>int</code>
7138      * object.  This was set using <code>setMatchColumn</code>
7139      * as the column which will form the basis of the join.
7140      * <P>
7141      * The parameter value unset by this method should be same
7142      * as was set.
7143      *
7144      * @param columnIdx the index into this rowset
7145      *        object's internal representation of parameter values
7146      * @throws SQLException if an error occurs or the
7147      *  parameter index is out of bounds or if the columnIdx is
7148      *  not the same as set using <code>setMatchColumn(int)</code>
7149      */
7150     public void unsetMatchColumn(int columnIdx) throws SQLException {
7151         // check if we are unsetting the SAME column
7152         if(! iMatchColumns.get(0).equals(Integer.valueOf(columnIdx) )  ) {
7153             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch").toString());
7154         } else if(strMatchColumns.get(0) != null) {
7155             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch1").toString());
7156         } else {
7157                 // that is, we are unsetting it.
7158                iMatchColumns.set(0, -1);
7159         }
7160     }
7161 
7162     /**
7163      * Unsets the designated parameter to the given <code>String</code>
7164      * object.  This was set using <code>setMatchColumn</code>
7165      * as the column which will form the basis of the join.
7166      * <P>
7167      * The parameter value unset by this method should be same
7168      * as was set.
7169      *
7170      * @param columnName the index into this rowset
7171      *        object's internal representation of parameter values
7172      * @throws SQLException if an error occurs or the
7173      *  parameter index is out of bounds or if the columnName is
7174      *  not the same as set using <code>setMatchColumn(String)</code>
7175      */
7176     public void unsetMatchColumn(String columnName) throws SQLException {
7177         // check if we are unsetting the same column
7178         columnName = columnName.trim();
7179 
7180         if(!((strMatchColumns.get(0)).equals(columnName))) {
7181             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch").toString());
7182         } else if(iMatchColumns.get(0) > 0) {
7183             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch2").toString());
7184         } else {
7185             strMatchColumns.set(0, null);   // that is, we are unsetting it.
7186         }
7187     }
7188 
7189     /**
7190      * Notifies registered listeners that a RowSet object in the given RowSetEvent
7191      * object has populated a number of additional rows. The <code>numRows</code> parameter
7192      * ensures that this event will only be fired every <code>numRow</code>.
7193      * <p>
7194      * The source of the event can be retrieved with the method event.getSource.
7195      *
7196      * @param event a <code>RowSetEvent</code> object that contains the
7197      *     <code>RowSet</code> object that is the source of the events
7198      * @param numRows when populating, the number of rows interval on which the
7199      *     <code>CachedRowSet</code> populated should fire; the default value
7200      *     is zero; cannot be less than <code>fetchSize</code> or zero
7201      */
7202     public void rowSetPopulated(RowSetEvent event, int numRows) throws SQLException {
7203 
7204         if( numRows < 0 || numRows < getFetchSize()) {
7205            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.numrows").toString());
7206         }
7207 
7208         if(size() % numRows == 0) {
7209             RowSetEvent event_temp = new RowSetEvent(this);
7210             event = event_temp;
7211             notifyRowSetChanged();
7212         }
7213     }
7214 
7215     /**
7216      * Populates this <code>CachedRowSet</code> object with data from
7217      * the given <code>ResultSet</code> object. While related to the <code>populate(ResultSet)</code>
7218      * method, an additional parameter is provided to allow starting position within
7219      * the <code>ResultSet</code> from where to populate the CachedRowSet
7220      * instance.
7221      *
7222      * This method is an alternative to the method <code>execute</code>
7223      * for filling the rowset with data.  The method <code>populate</code>
7224      * does not require that the properties needed by the method
7225      * <code>execute</code>, such as the <code>command</code> property,
7226      * be set. This is true because the method <code>populate</code>
7227      * is given the <code>ResultSet</code> object from
7228      * which to get data and thus does not need to use the properties
7229      * required for setting up a connection and executing this
7230      * <code>CachedRowSetImpl</code> object's command.
7231      * <P>
7232      * After populating this rowset with data, the method
7233      * <code>populate</code> sets the rowset's metadata and
7234      * then sends a <code>RowSetChangedEvent</code> object
7235      * to all registered listeners prior to returning.
7236      *
7237      * @param data the <code>ResultSet</code> object containing the data
7238      *             to be read into this <code>CachedRowSetImpl</code> object
7239      * @param start the integer specifing the position in the
7240      *        <code>ResultSet</code> object to popultate the
7241      *        <code>CachedRowSetImpl</code> object.
7242      * @throws SQLException if an error occurs; or the max row setting is
7243      *          violated while populating the RowSet.Also id the start position
7244      *          is negative.
7245      * @see #execute
7246      */
7247      public void populate(ResultSet data, int start) throws SQLException{
7248 
7249         int rowsFetched;
7250         Row currentRow;
7251         int numCols;
7252         int i;
7253         Map<String, Class<?>> map = getTypeMap();
7254         Object obj;
7255         int mRows;
7256 
7257         cursorPos = 0;
7258         if(populatecallcount == 0){
7259             if(start < 0){
7260                throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.startpos").toString());
7261             }
7262             if(getMaxRows() == 0){
7263                data.absolute(start);
7264                while(data.next()){
7265                    totalRows++;
7266                }
7267                totalRows++;
7268             }
7269             startPos = start;
7270         }
7271         populatecallcount = populatecallcount +1;
7272         resultSet = data;
7273         if((endPos - startPos) >= getMaxRows() && (getMaxRows() > 0)){
7274             endPos = prevEndPos;
7275             pagenotend = false;
7276             return;
7277         }
7278 
7279         if((maxRowsreached != getMaxRows() || maxRowsreached != totalRows) && pagenotend) {
7280            startPrev = start - getPageSize();
7281         }
7282 
7283         if( pageSize == 0){
7284            prevEndPos = endPos;
7285            endPos = start + getMaxRows() ;
7286         }
7287         else{
7288             prevEndPos = endPos;
7289             endPos = start + getPageSize();
7290         }
7291 
7292 
7293         if (start == 1){
7294             resultSet.beforeFirst();
7295         }
7296         else {
7297             resultSet.absolute(start -1);
7298         }
7299         if( pageSize == 0) {
7300            rvh = new Vector<Object>(getMaxRows());
7301 
7302         }
7303         else{
7304             rvh = new Vector<Object>(getPageSize());
7305         }
7306 
7307         if (data == null) {
7308             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.populate").toString());
7309         }
7310 
7311         // get the meta data for this ResultSet
7312         RSMD = data.getMetaData();
7313 
7314         // set up the metadata
7315         RowSetMD = new RowSetMetaDataImpl();
7316         initMetaData(RowSetMD, RSMD);
7317 
7318         // release the meta-data so that aren't tempted to use it.
7319         RSMD = null;
7320         numCols = RowSetMD.getColumnCount();
7321         mRows = this.getMaxRows();
7322         rowsFetched = 0;
7323         currentRow = null;
7324 
7325         if(!data.next() && mRows == 0){
7326             endPos = prevEndPos;
7327             pagenotend = false;
7328             return;
7329         }
7330 
7331         data.previous();
7332 
7333         while ( data.next()) {
7334 
7335             currentRow = new Row(numCols);
7336           if(pageSize == 0){
7337             if ( rowsFetched >= mRows && mRows > 0) {
7338                 rowsetWarning.setNextException(new SQLException("Populating rows "
7339                 + "setting has exceeded max row setting"));
7340                 break;
7341             }
7342           }
7343           else {
7344               if ( (rowsFetched >= pageSize) ||( maxRowsreached >= mRows && mRows > 0)) {
7345                 rowsetWarning.setNextException(new SQLException("Populating rows "
7346                 + "setting has exceeded max row setting"));
7347                 break;
7348             }
7349           }
7350 
7351             for ( i = 1; i <= numCols; i++) {
7352                 /*
7353                  * check if the user has set a map. If no map
7354                  * is set then use plain getObject. This lets
7355                  * us work with drivers that do not support
7356                  * getObject with a map in fairly sensible way
7357                  */
7358                 if (map == null) {
7359                     obj = data.getObject(i);
7360                 } else {
7361                     obj = data.getObject(i, map);
7362                 }
7363                 /*
7364                  * the following block checks for the various
7365                  * types that we have to serialize in order to
7366                  * store - right now only structs have been tested
7367                  */
7368                 if (obj instanceof Struct) {
7369                     obj = new SerialStruct((Struct)obj, map);
7370                 } else if (obj instanceof SQLData) {
7371                     obj = new SerialStruct((SQLData)obj, map);
7372                 } else if (obj instanceof Blob) {
7373                     obj = new SerialBlob((Blob)obj);
7374                 } else if (obj instanceof Clob) {
7375                     obj = new SerialClob((Clob)obj);
7376                 } else if (obj instanceof java.sql.Array) {
7377                     obj = new SerialArray((java.sql.Array)obj, map);
7378                 }
7379 
7380                 currentRow.initColumnObject(i, obj);
7381             }
7382             rowsFetched++;
7383             maxRowsreached++;
7384             rvh.add(currentRow);
7385         }
7386         numRows = rowsFetched ;
7387         // Also rowsFetched should be equal to rvh.size()
7388         // notify any listeners that the rowset has changed
7389         notifyRowSetChanged();
7390 
7391      }
7392 
7393     /**
7394      * The nextPage gets the next page, that is a <code>CachedRowSetImpl</code> object
7395      * containing the number of rows specified by page size.
7396      * @return boolean value true indicating whether there are more pages to come and
7397      *         false indicating that this is the last page.
7398      * @throws SQLException if an error occurs or this called before calling populate.
7399      */
7400      public boolean nextPage() throws SQLException {
7401 
7402          if (populatecallcount == 0){
7403              throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.nextpage").toString());
7404          }
7405          // Fix for 6554186
7406          onFirstPage = false;
7407          if(callWithCon){
7408             crsReader.setStartPosition(endPos);
7409             crsReader.readData((RowSetInternal)this);
7410             resultSet = null;
7411          }
7412          else {
7413             populate(resultSet,endPos);
7414          }
7415          return pagenotend;
7416      }
7417 
7418     /**
7419      * This is the setter function for setting the size of the page, which specifies
7420      * how many rows have to be retrived at a time.
7421      *
7422      * @param size which is the page size
7423      * @throws SQLException if size is less than zero or greater than max rows.
7424      */
7425      public void setPageSize (int size) throws SQLException {
7426         if (size < 0) {
7427             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.pagesize").toString());
7428         }
7429         if (size > getMaxRows() && getMaxRows() != 0) {
7430             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.pagesize1").toString());
7431         }
7432         pageSize = size;
7433      }
7434 
7435     /**
7436      * This is the getter function for the size of the page.
7437      *
7438      * @return an integer that is the page size.
7439      */
7440     public int getPageSize() {
7441         return pageSize;
7442     }
7443 
7444 
7445     /**
7446      * Retrieves the data present in the page prior to the page from where it is
7447      * called.
7448      * @return boolean value true if it retrieves the previous page, flase if it
7449      *         is on the first page.
7450      * @throws SQLException if it is called before populate is called or ResultSet
7451      *         is of type <code>ResultSet.TYPE_FORWARD_ONLY</code> or if an error
7452      *         occurs.
7453      */
7454     public boolean previousPage() throws SQLException {
7455         int pS;
7456         int mR;
7457         int rem;
7458 
7459         pS = getPageSize();
7460         mR = maxRowsreached;
7461 
7462         if (populatecallcount == 0){
7463              throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.nextpage").toString());
7464          }
7465 
7466         if( !callWithCon){
7467            if(resultSet.getType() == ResultSet.TYPE_FORWARD_ONLY){
7468                throw new SQLException (resBundle.handleGetObject("cachedrowsetimpl.fwdonly").toString());
7469            }
7470         }
7471 
7472         pagenotend = true;
7473 
7474         if(startPrev < startPos ){
7475                 onFirstPage = true;
7476                return false;
7477             }
7478 
7479         if(onFirstPage){
7480             return false;
7481         }
7482 
7483         rem = mR % pS;
7484 
7485         if(rem == 0){
7486             maxRowsreached -= (2 * pS);
7487             if(callWithCon){
7488                 crsReader.setStartPosition(startPrev);
7489                 crsReader.readData((RowSetInternal)this);
7490                 resultSet = null;
7491             }
7492             else {
7493                populate(resultSet,startPrev);
7494             }
7495             return true;
7496         }
7497         else
7498         {
7499             maxRowsreached -= (pS + rem);
7500             if(callWithCon){
7501                 crsReader.setStartPosition(startPrev);
7502                 crsReader.readData((RowSetInternal)this);
7503                 resultSet = null;
7504             }
7505             else {
7506                populate(resultSet,startPrev);
7507             }
7508             return true;
7509         }
7510     }
7511 
7512     /**
7513      * Goes to the page number passed as the parameter
7514      * @param page , the page loaded on a call to this function
7515      * @return true if the page exists false otherwise
7516      * @throws SQLException if an error occurs
7517      */
7518     /*
7519     public boolean absolutePage(int page) throws SQLException{
7520 
7521         boolean isAbs = true, retVal = true;
7522         int counter;
7523 
7524         if( page <= 0 ){
7525             throw new SQLException("Absolute positoin is invalid");
7526         }
7527         counter = 0;
7528 
7529         firstPage();
7530         counter++;
7531         while((counter < page) && isAbs) {
7532             isAbs = nextPage();
7533             counter ++;
7534         }
7535 
7536         if( !isAbs && counter < page){
7537             retVal = false;
7538         }
7539         else if(counter == page){
7540             retVal = true;
7541         }
7542 
7543        return retVal;
7544     }
7545     */
7546 
7547 
7548     /**
7549      * Goes to the page number passed as the parameter  from the current page.
7550      * The parameter can take postive or negative value accordingly.
7551      * @param page , the page loaded on a call to this function
7552      * @return true if the page exists false otherwise
7553      * @throws SQLException if an error occurs
7554      */
7555     /*
7556     public boolean relativePage(int page) throws SQLException {
7557 
7558         boolean isRel = true,retVal = true;
7559         int counter;
7560 
7561         if(page > 0){
7562            counter  = 0;
7563            while((counter < page) && isRel){
7564               isRel = nextPage();
7565               counter++;
7566            }
7567 
7568            if(!isRel && counter < page){
7569                retVal = false;
7570            }
7571            else if( counter == page){
7572                retVal = true;
7573            }
7574            return retVal;
7575         }
7576         else {
7577             counter = page;
7578             isRel = true;
7579             while((counter < 0) && isRel){
7580                 isRel = previousPage();
7581                 counter++;
7582             }
7583 
7584             if( !isRel && counter < 0){
7585                 retVal = false;
7586             }
7587             else if(counter == 0){
7588                 retVal = true;
7589             }
7590             return retVal;
7591         }
7592     }
7593     */
7594 
7595      /**
7596      * Retrieves the first page of data as specified by the page size.
7597      * @return boolean value true if present on first page, false otherwise
7598      * @throws SQLException if it called before populate or ResultSet is of
7599      *         type <code>ResultSet.TYPE_FORWARD_ONLY</code> or an error occurs
7600      */
7601     /*
7602     public boolean firstPage() throws SQLException {
7603            if (populatecallcount == 0){
7604              throw new SQLException("Populate the data before calling ");
7605            }
7606            if( !callWithCon){
7607               if(resultSet.getType() == ResultSet.TYPE_FORWARD_ONLY) {
7608                   throw new SQLException("Result of type forward only");
7609               }
7610            }
7611            endPos = 0;
7612            maxRowsreached = 0;
7613            pagenotend = true;
7614            if(callWithCon){
7615                crsReader.setStartPosition(startPos);
7616                crsReader.readData((RowSetInternal)this);
7617                resultSet = null;
7618            }
7619            else {
7620               populate(resultSet,startPos);
7621            }
7622            onFirstPage = true;
7623            return onFirstPage;
7624     }
7625     */
7626 
7627     /**
7628      * Retrives the last page of data as specified by the page size.
7629      * @return boolean value tur if present on the last page, false otherwise
7630      * @throws SQLException if called before populate or if an error occurs.
7631      */
7632      /*
7633     public boolean lastPage() throws SQLException{
7634           int pS;
7635           int mR;
7636           int quo;
7637           int rem;
7638 
7639           pS = getPageSize();
7640           mR = getMaxRows();
7641 
7642           if(pS == 0){
7643               onLastPage = true;
7644               return onLastPage;
7645           }
7646 
7647           if(getMaxRows() == 0){
7648               mR = totalRows;
7649           }
7650 
7651           if (populatecallcount == 0){
7652              throw new SQLException("Populate the data before calling ");
7653          }
7654 
7655          onFirstPage = false;
7656 
7657          if((mR % pS) == 0){
7658              quo = mR / pS;
7659              int start = startPos + (pS * (quo - 1));
7660              maxRowsreached = mR - pS;
7661              if(callWithCon){
7662                  crsReader.setStartPosition(start);
7663                  crsReader.readData((RowSetInternal)this);
7664                  resultSet = null;
7665              }
7666              else {
7667                 populate(resultSet,start);
7668              }
7669              onLastPage = true;
7670              return onLastPage;
7671          }
7672         else {
7673               quo = mR /pS;
7674               rem = mR % pS;
7675               int start = startPos + (pS * quo);
7676              maxRowsreached = mR - (rem);
7677              if(callWithCon){
7678                  crsReader.setStartPosition(start);
7679                  crsReader.readData((RowSetInternal)this);
7680                  resultSet = null;
7681              }
7682              else {
7683                 populate(resultSet,start);
7684              }
7685              onLastPage = true;
7686              return onLastPage;
7687          }
7688     }
7689     */
7690 
7691    /**
7692      * Sets the status for the row on which the cursor is positioned. The insertFlag is used
7693      * to mention the toggle status for this row
7694      * @param insertFlag if it is true  - marks this row as inserted
7695      *                   if it is false - marks it as not a newly inserted row
7696      * @throws SQLException if an error occurs while doing this operation
7697      */
7698     public void setRowInserted(boolean insertFlag) throws SQLException {
7699 
7700         checkCursor();
7701 
7702         if(onInsertRow == true)
7703           throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
7704 
7705         if( insertFlag ) {
7706           ((Row)getCurrentRow()).setInserted();
7707         } else {
7708           ((Row)getCurrentRow()).clearInserted();
7709         }
7710     }
7711 
7712     /**
7713      * Retrieves the value of the designated <code>SQL XML</code> parameter as a
7714      * <code>SQLXML</code> object in the Java programming language.
7715      * @param columnIndex the first column is 1, the second is 2, ...
7716      * @return a SQLXML object that maps an SQL XML value
7717      * @throws SQLException if a database access error occurs
7718      * @since 1.6
7719      */
7720     public SQLXML getSQLXML(int columnIndex) throws SQLException {
7721         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7722     }
7723 
7724     /**
7725      * Retrieves the value of the designated <code>SQL XML</code> parameter as a
7726      * <code>SQLXML</code> object in the Java programming language.
7727      * @param colName the name of the column from which to retrieve the value
7728      * @return a SQLXML object that maps an SQL XML value
7729      * @throws SQLException if a database access error occurs
7730      */
7731     public SQLXML getSQLXML(String colName) throws SQLException {
7732         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7733     }
7734 
7735     /**
7736      * Retrieves the value of the designated column in the current row of this
7737      * <code>ResultSet</code> object as a java.sql.RowId object in the Java
7738      * programming language.
7739      *
7740      * @param columnIndex the first column is 1, the second 2, ...
7741      * @return the column value if the value is a SQL <code>NULL</code> the
7742      *     value returned is <code>null</code>
7743      * @throws SQLException if a database access error occurs
7744      * @since 1.6
7745      */
7746     public RowId getRowId(int columnIndex) throws SQLException {
7747         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7748     }
7749 
7750     /**
7751      * Retrieves the value of the designated column in the current row of this
7752      * <code>ResultSet</code> object as a java.sql.RowId object in the Java
7753      * programming language.
7754      *
7755      * @param columnName the name of the column
7756      * @return the column value if the value is a SQL <code>NULL</code> the
7757      *     value returned is <code>null</code>
7758      * @throws SQLException if a database access error occurs
7759      * @since 1.6
7760      */
7761     public RowId getRowId(String columnName) throws SQLException {
7762         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7763     }
7764 
7765     /**
7766      * Updates the designated column with a <code>RowId</code> value. The updater
7767      * methods are used to update column values in the current row or the insert
7768      * row. The updater methods do not update the underlying database; instead
7769      * the {@code updateRow} or {@code insertRow} methods are called
7770      * to update the database.
7771      *
7772      * @param columnIndex the first column is 1, the second 2, ...
7773      * @param x the column value
7774      * @throws SQLException if a database access occurs
7775      * @since 1.6
7776      */
7777     public void updateRowId(int columnIndex, RowId x) throws SQLException {
7778         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7779     }
7780 
7781     /**
7782      * Updates the designated column with a <code>RowId</code> value. The updater
7783      * methods are used to update column values in the current row or the insert
7784      * row. The updater methods do not update the underlying database; instead
7785      * the {@code updateRow} or {@code insertRow} methods are called
7786      * to update the database.
7787      *
7788      * @param columnName the name of the column
7789      * @param x the column value
7790      * @throws SQLException if a database access occurs
7791      * @since 1.6
7792      */
7793     public void updateRowId(String columnName, RowId x) throws SQLException {
7794         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7795     }
7796 
7797     /**
7798      * Retrieves the holdability of this ResultSet object
7799      * @return  either ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT
7800      * @throws SQLException if a database error occurs
7801      * @since 1.6
7802      */
7803     public int getHoldability() throws SQLException {
7804         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7805     }
7806 
7807     /**
7808      * Retrieves whether this ResultSet object has been closed. A ResultSet is closed if the
7809      * method close has been called on it, or if it is automatically closed.
7810      * @return true if this ResultSet object is closed; false if it is still open
7811      * @throws SQLException if a database access error occurs
7812      * @since 1.6
7813      */
7814     public boolean isClosed() throws SQLException {
7815         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7816     }
7817 
7818     /**
7819      * This method is used for updating columns that support National Character sets.
7820      * It can be used for updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
7821      * @param columnIndex the first column is 1, the second 2, ...
7822      * @param nString the value for the column to be updated
7823      * @throws SQLException if a database access error occurs
7824      * @since 1.6
7825      */
7826     public void updateNString(int columnIndex, String nString) throws SQLException {
7827         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7828     }
7829 
7830     /**
7831      * This method is used for updating columns that support National Character sets.
7832      * It can be used for updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
7833      * @param columnName name of the Column
7834      * @param nString the value for the column to be updated
7835      * @throws SQLException if a database access error occurs
7836      * @since 1.6
7837      */
7838     public void updateNString(String columnName, String nString) throws SQLException {
7839         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7840     }
7841 
7842 
7843     /*o
7844      * This method is used for updating SQL <code>NCLOB</code>  type that maps
7845      * to <code>java.sql.Types.NCLOB</code>
7846      * @param columnIndex the first column is 1, the second 2, ...
7847      * @param nClob the value for the column to be updated
7848      * @throws SQLException if a database access error occurs
7849      * @since 1.6
7850      */
7851     public void updateNClob(int columnIndex, NClob nClob) throws SQLException {
7852         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7853     }
7854 
7855     /**
7856      * This method is used for updating SQL <code>NCLOB</code>  type that maps
7857      * to <code>java.sql.Types.NCLOB</code>
7858      * @param columnName name of the column
7859      * @param nClob the value for the column to be updated
7860      * @throws SQLException if a database access error occurs
7861      * @since 1.6
7862      */
7863     public void updateNClob(String columnName, NClob nClob) throws SQLException {
7864        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7865     }
7866 
7867     /**
7868      * Retrieves the value of the designated column in the current row
7869      * of this <code>ResultSet</code> object as a <code>NClob</code> object
7870      * in the Java programming language.
7871      *
7872      * @param i the first column is 1, the second is 2, ...
7873      * @return a <code>NClob</code> object representing the SQL
7874      *         <code>NCLOB</code> value in the specified column
7875      * @exception SQLException if a database access error occurs
7876      * @since 1.6
7877      */
7878     public NClob getNClob(int i) throws SQLException {
7879         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7880     }
7881 
7882 
7883    /**
7884      * Retrieves the value of the designated column in the current row
7885      * of this <code>ResultSet</code> object as a <code>NClob</code> object
7886      * in the Java programming language.
7887      *
7888      * @param colName the name of the column from which to retrieve the value
7889      * @return a <code>NClob</code> object representing the SQL <code>NCLOB</code>
7890      * value in the specified column
7891      * @exception SQLException if a database access error occurs
7892      * @since 1.6
7893      */
7894     public NClob getNClob(String colName) throws SQLException {
7895         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7896     }
7897 
7898     public <T> T unwrap(java.lang.Class<T> iface) throws java.sql.SQLException {
7899         return null;
7900     }
7901 
7902     public boolean isWrapperFor(Class<?> interfaces) throws SQLException {
7903         return false;
7904     }
7905 
7906 
7907    /**
7908       * Sets the designated parameter to the given <code>java.sql.SQLXML</code> object. The driver converts this to an
7909       * SQL <code>XML</code> value when it sends it to the database.
7910       * @param parameterIndex index of the first parameter is 1, the second is 2, ...
7911       * @param xmlObject a <code>SQLXML</code> object that maps an SQL <code>XML</code> value
7912       * @throws SQLException if a database access error occurs
7913       * @since 1.6
7914       */
7915      public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
7916          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7917      }
7918 
7919    /**
7920      * Sets the designated parameter to the given <code>java.sql.SQLXML</code> object. The driver converts this to an
7921      * <code>SQL XML</code> value when it sends it to the database.
7922      * @param parameterName the name of the parameter
7923      * @param xmlObject a <code>SQLXML</code> object that maps an <code>SQL XML</code> value
7924      * @throws SQLException if a database access error occurs
7925      * @since 1.6
7926      */
7927     public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException {
7928          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7929      }
7930 
7931 
7932     /**
7933      * Sets the designated parameter to the given <code>java.sql.RowId</code> object. The
7934      * driver converts this to a SQL <code>ROWID</code> value when it sends it
7935      * to the database
7936      *
7937      * @param parameterIndex the first parameter is 1, the second is 2, ...
7938      * @param x the parameter value
7939      * @throws SQLException if a database access error occurs
7940      *
7941      * @since 1.6
7942      */
7943     public void setRowId(int parameterIndex, RowId x) throws SQLException {
7944          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7945      }
7946 
7947 
7948     /**
7949     * Sets the designated parameter to the given <code>java.sql.RowId</code> object. The
7950     * driver converts this to a SQL <code>ROWID</code> when it sends it to the
7951     * database.
7952     *
7953     * @param parameterName the name of the parameter
7954     * @param x the parameter value
7955     * @throws SQLException if a database access error occurs
7956     * @since 1.6
7957     */
7958    public void setRowId(String parameterName, RowId x) throws SQLException {
7959          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7960      }
7961 
7962 
7963     /**
7964      * Sets the designated parameter to a <code>Reader</code> object. The
7965      * <code>Reader</code> reads the data till end-of-file is reached. The
7966      * driver does the necessary conversion from Java character format to
7967      * the national character set in the database.
7968 
7969      * <P><B>Note:</B> This stream object can either be a standard
7970      * Java stream object or your own subclass that implements the
7971      * standard interface.
7972      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
7973      * it might be more efficient to use a version of
7974      * <code>setNCharacterStream</code> which takes a length parameter.
7975      *
7976      * @param parameterIndex of the first parameter is 1, the second is 2, ...
7977      * @param value the parameter value
7978      * @throws SQLException if the driver does not support national
7979      *         character sets;  if the driver can detect that a data conversion
7980      *  error could occur ; if a database access error occurs; or
7981      * this method is called on a closed <code>PreparedStatement</code>
7982      * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
7983      * @since 1.6
7984      */
7985      public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
7986         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
7987      }
7988 
7989 
7990     /**
7991     * Sets the designated parameter to a <code>java.sql.NClob</code> object. The object
7992     * implements the <code>java.sql.NClob</code> interface. This <code>NClob</code>
7993     * object maps to a SQL <code>NCLOB</code>.
7994     * @param parameterName the name of the column to be set
7995     * @param value the parameter value
7996     * @throws SQLException if the driver does not support national
7997     *         character sets;  if the driver can detect that a data conversion
7998     *  error could occur; or if a database access error occurs
7999     * @since 1.6
8000     */
8001     public void setNClob(String parameterName, NClob value) throws SQLException {
8002          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8003      }
8004 
8005 
8006   /**
8007      * Retrieves the value of the designated column in the current row
8008      * of this <code>ResultSet</code> object as a
8009      * <code>java.io.Reader</code> object.
8010      * It is intended for use when
8011      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8012      * and <code>LONGNVARCHAR</code> columns.
8013      *
8014      * @return a <code>java.io.Reader</code> object that contains the column
8015      * value; if the value is SQL <code>NULL</code>, the value returned is
8016      * <code>null</code> in the Java programming language.
8017      * @param columnIndex the first column is 1, the second is 2, ...
8018      * @exception SQLException if a database access error occurs
8019      * @since 1.6
8020      */
8021     public java.io.Reader getNCharacterStream(int columnIndex) throws SQLException {
8022        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8023      }
8024 
8025 
8026     /**
8027      * Retrieves the value of the designated column in the current row
8028      * of this <code>ResultSet</code> object as a
8029      * <code>java.io.Reader</code> object.
8030      * It is intended for use when
8031      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8032      * and <code>LONGNVARCHAR</code> columns.
8033      *
8034      * @param columnName the name of the column
8035      * @return a <code>java.io.Reader</code> object that contains the column
8036      * value; if the value is SQL <code>NULL</code>, the value returned is
8037      * <code>null</code> in the Java programming language
8038      * @exception SQLException if a database access error occurs
8039      * @since 1.6
8040      */
8041     public java.io.Reader getNCharacterStream(String columnName) throws SQLException {
8042        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8043      }
8044 
8045 
8046     /**
8047      * Updates the designated column with a <code>java.sql.SQLXML</code> value.
8048      * The updater
8049      * methods are used to update column values in the current row or the insert
8050      * row. The updater methods do not update the underlying database; instead
8051      * the <code>updateRow</code> or <code>insertRow</code> methods are called
8052      * to update the database.
8053      * @param columnIndex the first column is 1, the second 2, ...
8054      * @param xmlObject the value for the column to be updated
8055      * @throws SQLException if a database access error occurs
8056      * @since 1.6
8057      */
8058     public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException {
8059         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8060     }
8061 
8062     /**
8063      * Updates the designated column with a <code>java.sql.SQLXML</code> value.
8064      * The updater
8065      * methods are used to update column values in the current row or the insert
8066      * row. The updater methods do not update the underlying database; instead
8067      * the <code>updateRow</code> or <code>insertRow</code> methods are called
8068      * to update the database.
8069      *
8070      * @param columnName the name of the column
8071      * @param xmlObject the column value
8072      * @throws SQLException if a database access occurs
8073      * @since 1.6
8074      */
8075     public void updateSQLXML(String columnName, SQLXML xmlObject) throws SQLException {
8076         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8077     }
8078 
8079      /**
8080      * Retrieves the value of the designated column in the current row
8081      * of this <code>ResultSet</code> object as
8082      * a <code>String</code> in the Java programming language.
8083      * It is intended for use when
8084      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8085      * and <code>LONGNVARCHAR</code> columns.
8086      *
8087      * @param columnIndex the first column is 1, the second is 2, ...
8088      * @return the column value; if the value is SQL <code>NULL</code>, the
8089      * value returned is <code>null</code>
8090      * @exception SQLException if a database access error occurs
8091      * @since 1.6
8092      */
8093     public String getNString(int columnIndex) throws SQLException {
8094         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8095     }
8096 
8097     /**
8098      * Retrieves the value of the designated column in the current row
8099      * of this <code>ResultSet</code> object as
8100      * a <code>String</code> in the Java programming language.
8101      * It is intended for use when
8102      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8103      * and <code>LONGNVARCHAR</code> columns.
8104      *
8105      * @param columnName the SQL name of the column
8106      * @return the column value; if the value is SQL <code>NULL</code>, the
8107      * value returned is <code>null</code>
8108      * @exception SQLException if a database access error occurs
8109      * @since 1.6
8110      */
8111     public String getNString(String columnName) throws SQLException {
8112         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8113     }
8114 
8115      /**
8116        * Updates the designated column with a character stream value, which will
8117        * have the specified number of bytes. The driver does the necessary conversion
8118        * from Java character format to the national character set in the database.
8119        * It is intended for use when updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
8120        * The updater methods are used to update column values in the current row or
8121        * the insert row. The updater methods do not update the underlying database;
8122        * instead the updateRow or insertRow methods are called to update the database.
8123        *
8124        * @param columnIndex - the first column is 1, the second is 2, ...
8125        * @param x - the new column value
8126        * @param length - the length of the stream
8127        * @exception SQLException if a database access error occurs
8128        * @since 1.6
8129        */
8130        public void updateNCharacterStream(int columnIndex,
8131                             java.io.Reader x,
8132                             long length)
8133                             throws SQLException {
8134           throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8135        }
8136 
8137      /**
8138        * Updates the designated column with a character stream value, which will
8139        * have the specified number of bytes. The driver does the necessary conversion
8140        * from Java character format to the national character set in the database.
8141        * It is intended for use when updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
8142        * The updater methods are used to update column values in the current row or
8143        * the insert row. The updater methods do not update the underlying database;
8144        * instead the updateRow or insertRow methods are called to update the database.
8145        *
8146        * @param columnName - name of the Column
8147        * @param x - the new column value
8148        * @param length - the length of the stream
8149        * @exception SQLException if a database access error occurs
8150        * @since 1.6
8151        */
8152        public void updateNCharacterStream(String columnName,
8153                             java.io.Reader x,
8154                             long length)
8155                             throws SQLException {
8156           throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8157        }
8158 
8159      /**
8160      * Updates the designated column with a character stream value.   The
8161      * driver does the necessary conversion from Java character format to
8162      * the national character set in the database.
8163      * It is intended for use when
8164      * updating  <code>NCHAR</code>,<code>NVARCHAR</code>
8165      * and <code>LONGNVARCHAR</code> columns.
8166      *
8167      * The updater methods are used to update column values in the
8168      * current row or the insert row.  The updater methods do not
8169      * update the underlying database; instead the <code>updateRow</code> or
8170      * <code>insertRow</code> methods are called to update the database.
8171      *
8172      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8173      * it might be more efficient to use a version of
8174      * <code>updateNCharacterStream</code> which takes a length parameter.
8175      *
8176      * @param columnIndex the first column is 1, the second is 2, ...
8177      * @param x the new column value
8178      * @exception SQLException if a database access error occurs,
8179      * the result set concurrency is <code>CONCUR_READ_ONLY</code> or this method is called on a closed result set
8180      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8181      * this method
8182      * @since 1.6
8183      */
8184     public void updateNCharacterStream(int columnIndex,
8185                              java.io.Reader x) throws SQLException {
8186         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8187     }
8188 
8189     /**
8190      * Updates the designated column with a character stream value.  The
8191      * driver does the necessary conversion from Java character format to
8192      * the national character set in the database.
8193      * It is intended for use when
8194      * updating  <code>NCHAR</code>,<code>NVARCHAR</code>
8195      * and <code>LONGNVARCHAR</code> columns.
8196      *
8197      * The updater methods are used to update column values in the
8198      * current row or the insert row.  The updater methods do not
8199      * update the underlying database; instead the <code>updateRow</code> or
8200      * <code>insertRow</code> methods are called to update the database.
8201      *
8202      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8203      * it might be more efficient to use a version of
8204      * <code>updateNCharacterStream</code> which takes a length parameter.
8205      *
8206      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8207 bel is the name of the column
8208      * @param reader the <code>java.io.Reader</code> object containing
8209      *        the new column value
8210      * @exception SQLException if a database access error occurs,
8211      * the result set concurrency is <code>CONCUR_READ_ONLY</code> or this method is called on a closed result set
8212       * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8213      * this method
8214      * @since 1.6
8215      */
8216     public void updateNCharacterStream(String columnLabel,
8217                              java.io.Reader reader) throws SQLException {
8218         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8219     }
8220 
8221 //////////////////////////
8222 
8223     /**
8224      * Updates the designated column using the given input stream, which
8225      * will have the specified number of bytes.
8226      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8227      * parameter, it may be more practical to send it via a
8228      * <code>java.io.InputStream</code>. Data will be read from the stream
8229      * as needed until end-of-file is reached.  The JDBC driver will
8230      * do any necessary conversion from ASCII to the database char format.
8231      *
8232      * <P><B>Note:</B> This stream object can either be a standard
8233      * Java stream object or your own subclass that implements the
8234      * standard interface.
8235      * <p>
8236      * The updater methods are used to update column values in the
8237      * current row or the insert row.  The updater methods do not
8238      * update the underlying database; instead the <code>updateRow</code> or
8239      * <code>insertRow</code> methods are called to update the database.
8240      *
8241      * @param columnIndex the first column is 1, the second is 2, ...
8242      * @param inputStream An object that contains the data to set the parameter
8243      * value to.
8244      * @param length the number of bytes in the parameter data.
8245      * @exception SQLException if a database access error occurs,
8246      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8247      * or this method is called on a closed result set
8248      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8249      * this method
8250      * @since 1.6
8251      */
8252     public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException{
8253         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8254     }
8255 
8256     /**
8257      * Updates the designated column using the given input stream, which
8258      * will have the specified number of bytes.
8259      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8260      * parameter, it may be more practical to send it via a
8261      * <code>java.io.InputStream</code>. Data will be read from the stream
8262      * as needed until end-of-file is reached.  The JDBC driver will
8263      * do any necessary conversion from ASCII to the database char format.
8264      *
8265      * <P><B>Note:</B> This stream object can either be a standard
8266      * Java stream object or your own subclass that implements the
8267      * standard interface.
8268      * <p>
8269      * The updater methods are used to update column values in the
8270      * current row or the insert row.  The updater methods do not
8271      * update the underlying database; instead the <code>updateRow</code> or
8272      * <code>insertRow</code> methods are called to update the database.
8273      *
8274      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the label is the name of the column
8275      * @param inputStream An object that contains the data to set the parameter
8276      * value to.
8277      * @param length the number of bytes in the parameter data.
8278      * @exception SQLException if a database access error occurs,
8279      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8280      * or this method is called on a closed result set
8281      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8282      * this method
8283      * @since 1.6
8284      */
8285     public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException {
8286         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8287     }
8288 
8289     /**
8290      * Updates the designated column using the given input stream.
8291      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8292      * parameter, it may be more practical to send it via a
8293      * <code>java.io.InputStream</code>. Data will be read from the stream
8294      * as needed until end-of-file is reached.  The JDBC driver will
8295      * do any necessary conversion from ASCII to the database char format.
8296      *
8297      * <P><B>Note:</B> This stream object can either be a standard
8298      * Java stream object or your own subclass that implements the
8299      * standard interface.
8300      *
8301      *  <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8302      * it might be more efficient to use a version of
8303      * <code>updateBlob</code> which takes a length parameter.
8304      * <p>
8305      * The updater methods are used to update column values in the
8306      * current row or the insert row.  The updater methods do not
8307      * update the underlying database; instead the <code>updateRow</code> or
8308      * <code>insertRow</code> methods are called to update the database.
8309      *
8310      * @param columnIndex the first column is 1, the second is 2, ...
8311      * @param inputStream An object that contains the data to set the parameter
8312      * value to.
8313      * @exception SQLException if a database access error occurs,
8314      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8315      * or this method is called on a closed result set
8316      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8317      * this method
8318      * @since 1.6
8319      */
8320     public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException {
8321         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8322     }
8323 
8324     /**
8325      * Updates the designated column using the given input stream.
8326      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8327      * parameter, it may be more practical to send it via a
8328      * <code>java.io.InputStream</code>. Data will be read from the stream
8329      * as needed until end-of-file is reached.  The JDBC driver will
8330      * do any necessary conversion from ASCII to the database char format.
8331      *
8332      * <P><B>Note:</B> This stream object can either be a standard
8333      * Java stream object or your own subclass that implements the
8334      * standard interface.
8335      *   <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8336      * it might be more efficient to use a version of
8337      * <code>updateBlob</code> which takes a length parameter.
8338      * <p>
8339      * The updater methods are used to update column values in the
8340      * current row or the insert row.  The updater methods do not
8341      * update the underlying database; instead the <code>updateRow</code> or
8342      * <code>insertRow</code> methods are called to update the database.
8343      *
8344      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8345 bel is the name of the column
8346      * @param inputStream An object that contains the data to set the parameter
8347      * value to.
8348      * @exception SQLException if a database access error occurs,
8349      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8350      * or this method is called on a closed result set
8351      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8352      * this method
8353      * @since 1.6
8354      */
8355     public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException {
8356         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8357     }
8358 
8359     /**
8360      * Updates the designated column using the given <code>Reader</code>
8361      * object, which is the given number of characters long.
8362      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8363      * parameter, it may be more practical to send it via a
8364      * <code>java.io.Reader</code> object. The data will be read from the stream
8365      * as needed until end-of-file is reached.  The JDBC driver will
8366      * do any necessary conversion from UNICODE to the database char format.
8367      *
8368      * <P><B>Note:</B> This stream object can either be a standard
8369      * Java stream object or your own subclass that implements the
8370      * standard interface.
8371      * <p>
8372      * The updater methods are used to update column values in the
8373      * current row or the insert row.  The updater methods do not
8374      * update the underlying database; instead the <code>updateRow</code> or
8375      * <code>insertRow</code> methods are called to update the database.
8376      *
8377      * @param columnIndex the first column is 1, the second is 2, ...
8378      * @param reader An object that contains the data to set the parameter value to.
8379      * @param length the number of characters in the parameter data.
8380      * @exception SQLException if a database access error occurs,
8381      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8382      * or this method is called on a closed result set
8383      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8384      * this method
8385      * @since 1.6
8386      */
8387     public void updateClob(int columnIndex,  Reader reader, long length) throws SQLException {
8388         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8389     }
8390 
8391     /**
8392      * Updates the designated column using the given <code>Reader</code>
8393      * object, which is the given number of characters long.
8394      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8395      * parameter, it may be more practical to send it via a
8396      * <code>java.io.Reader</code> object. The data will be read from the stream
8397      * as needed until end-of-file is reached.  The JDBC driver will
8398      * do any necessary conversion from UNICODE to the database char format.
8399      *
8400      * <P><B>Note:</B> This stream object can either be a standard
8401      * Java stream object or your own subclass that implements the
8402      * standard interface.
8403      * <p>
8404      * The updater methods are used to update column values in the
8405      * current row or the insert row.  The updater methods do not
8406      * update the underlying database; instead the <code>updateRow</code> or
8407      * <code>insertRow</code> methods are called to update the database.
8408      *
8409      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the label is the name of the column
8410      * @param reader An object that contains the data to set the parameter value to.
8411      * @param length the number of characters in the parameter data.
8412      * @exception SQLException if a database access error occurs,
8413      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8414      * or this method is called on a closed result set
8415      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8416      * this method
8417      * @since 1.6
8418      */
8419     public void updateClob(String columnLabel,  Reader reader, long length) throws SQLException {
8420         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8421     }
8422 
8423    /**
8424      * Updates the designated column using the given <code>Reader</code>
8425      * object.
8426      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8427      * parameter, it may be more practical to send it via a
8428      * <code>java.io.Reader</code> object. The data will be read from the stream
8429      * as needed until end-of-file is reached.  The JDBC driver will
8430      * do any necessary conversion from UNICODE to the database char format.
8431      *
8432      * <P><B>Note:</B> This stream object can either be a standard
8433      * Java stream object or your own subclass that implements the
8434      * standard interface.
8435      *   <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8436      * it might be more efficient to use a version of
8437      * <code>updateClob</code> which takes a length parameter.
8438      * <p>
8439      * The updater methods are used to update column values in the
8440      * current row or the insert row.  The updater methods do not
8441      * update the underlying database; instead the <code>updateRow</code> or
8442      * <code>insertRow</code> methods are called to update the database.
8443      *
8444      * @param columnIndex the first column is 1, the second is 2, ...
8445      * @param reader An object that contains the data to set the parameter value to.
8446      * @exception SQLException if a database access error occurs,
8447      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8448      * or this method is called on a closed result set
8449      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8450      * this method
8451      * @since 1.6
8452      */
8453     public void updateClob(int columnIndex,  Reader reader) throws SQLException {
8454         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8455     }
8456 
8457     /**
8458      * Updates the designated column using the given <code>Reader</code>
8459      * object.
8460      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8461      * parameter, it may be more practical to send it via a
8462      * <code>java.io.Reader</code> object. The data will be read from the stream
8463      * as needed until end-of-file is reached.  The JDBC driver will
8464      * do any necessary conversion from UNICODE to the database char format.
8465      *
8466      * <P><B>Note:</B> This stream object can either be a standard
8467      * Java stream object or your own subclass that implements the
8468      * standard interface.
8469      *  <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8470      * it might be more efficient to use a version of
8471      * <code>updateClob</code> which takes a length parameter.
8472      * <p>
8473      * The updater methods are used to update column values in the
8474      * current row or the insert row.  The updater methods do not
8475      * update the underlying database; instead the <code>updateRow</code> or
8476      * <code>insertRow</code> methods are called to update the database.
8477      *
8478      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8479 bel is the name of the column
8480      * @param reader An object that contains the data to set the parameter value to.
8481      * @exception SQLException if a database access error occurs,
8482      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8483      * or this method is called on a closed result set
8484      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8485      * this method
8486      * @since 1.6
8487      */
8488     public void updateClob(String columnLabel,  Reader reader) throws SQLException {
8489         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8490     }
8491 
8492    /**
8493      * Updates the designated column using the given <code>Reader</code>
8494      * object, which is the given number of characters long.
8495      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8496      * parameter, it may be more practical to send it via a
8497      * <code>java.io.Reader</code> object. The data will be read from the stream
8498      * as needed until end-of-file is reached.  The JDBC driver will
8499      * do any necessary conversion from UNICODE to the database char format.
8500      *
8501      * <P><B>Note:</B> This stream object can either be a standard
8502      * Java stream object or your own subclass that implements the
8503      * standard interface.
8504      * <p>
8505      * The updater methods are used to update column values in the
8506      * current row or the insert row.  The updater methods do not
8507      * update the underlying database; instead the <code>updateRow</code> or
8508      * <code>insertRow</code> methods are called to update the database.
8509      *
8510      * @param columnIndex the first column is 1, the second 2, ...
8511      * @param reader An object that contains the data to set the parameter value to.
8512      * @param length the number of characters in the parameter data.
8513      * @throws SQLException if the driver does not support national
8514      *         character sets;  if the driver can detect that a data conversion
8515      *  error could occur; this method is called on a closed result set,
8516      * if a database access error occurs or
8517      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8518      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8519      * this method
8520      * @since 1.6
8521      */
8522     public void updateNClob(int columnIndex,  Reader reader, long length) throws SQLException {
8523         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8524     }
8525 
8526     /**
8527      * Updates the designated column using the given <code>Reader</code>
8528      * object, which is the given number of characters long.
8529      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8530      * parameter, it may be more practical to send it via a
8531      * <code>java.io.Reader</code> object. The data will be read from the stream
8532      * as needed until end-of-file is reached.  The JDBC driver will
8533      * do any necessary conversion from UNICODE to the database char format.
8534      *
8535      * <P><B>Note:</B> This stream object can either be a standard
8536      * Java stream object or your own subclass that implements the
8537      * standard interface.
8538      * <p>
8539      * The updater methods are used to update column values in the
8540      * current row or the insert row.  The updater methods do not
8541      * update the underlying database; instead the <code>updateRow</code> or
8542      * <code>insertRow</code> methods are called to update the database.
8543      *
8544      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the label is the name of the column
8545      * @param reader An object that contains the data to set the parameter value to.
8546      * @param length the number of characters in the parameter data.
8547      * @throws SQLException if the driver does not support national
8548      *         character sets;  if the driver can detect that a data conversion
8549      *  error could occur; this method is called on a closed result set;
8550      *  if a database access error occurs or
8551      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8552      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8553      * this method
8554      * @since 1.6
8555      */
8556     public void updateNClob(String columnLabel,  Reader reader, long length) throws SQLException {
8557         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8558     }
8559 
8560     /**
8561      * Updates the designated column using the given <code>Reader</code>
8562      * object.
8563      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8564      * parameter, it may be more practical to send it via a
8565      * <code>java.io.Reader</code> object. The data will be read from the stream
8566      * as needed until end-of-file is reached.  The JDBC driver will
8567      * do any necessary conversion from UNICODE to the database char format.
8568      *
8569      * <P><B>Note:</B> This stream object can either be a standard
8570      * Java stream object or your own subclass that implements the
8571      * standard interface.
8572      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8573      * it might be more efficient to use a version of
8574      * <code>updateNClob</code> which takes a length parameter.
8575      * <p>
8576      * The updater methods are used to update column values in the
8577      * current row or the insert row.  The updater methods do not
8578      * update the underlying database; instead the <code>updateRow</code> or
8579      * <code>insertRow</code> methods are called to update the database.
8580      *
8581      * @param columnIndex the first column is 1, the second 2, ...
8582      * @param reader An object that contains the data to set the parameter value to.
8583      * @throws SQLException if the driver does not support national
8584      *         character sets;  if the driver can detect that a data conversion
8585      *  error could occur; this method is called on a closed result set,
8586      * if a database access error occurs or
8587      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8588      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8589      * this method
8590      * @since 1.6
8591      */
8592     public void updateNClob(int columnIndex,  Reader reader) throws SQLException {
8593         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8594     }
8595 
8596     /**
8597      * Updates the designated column using the given <code>Reader</code>
8598      * object.
8599      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8600      * parameter, it may be more practical to send it via a
8601      * <code>java.io.Reader</code> object. The data will be read from the stream
8602      * as needed until end-of-file is reached.  The JDBC driver will
8603      * do any necessary conversion from UNICODE to the database char format.
8604      *
8605      * <P><B>Note:</B> This stream object can either be a standard
8606      * Java stream object or your own subclass that implements the
8607      * standard interface.
8608      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8609      * it might be more efficient to use a version of
8610      * <code>updateNClob</code> which takes a length parameter.
8611      * <p>
8612      * The updater methods are used to update column values in the
8613      * current row or the insert row.  The updater methods do not
8614      * update the underlying database; instead the <code>updateRow</code> or
8615      * <code>insertRow</code> methods are called to update the database.
8616      *
8617      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8618 bel is the name of the column
8619      * @param reader An object that contains the data to set the parameter value to.
8620      * @throws SQLException if the driver does not support national
8621      *         character sets;  if the driver can detect that a data conversion
8622      *  error could occur; this method is called on a closed result set;
8623      *  if a database access error occurs or
8624      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8625      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8626      * this method
8627      * @since 1.6
8628      */
8629     public void updateNClob(String columnLabel,  Reader reader) throws SQLException {
8630         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8631     }
8632 
8633         /**
8634      * Updates the designated column with an ascii stream value, which will have
8635      * the specified number of bytes.
8636      * The updater methods are used to update column values in the
8637      * current row or the insert row.  The updater methods do not
8638      * update the underlying database; instead the <code>updateRow</code> or
8639      * <code>insertRow</code> methods are called to update the database.
8640      *
8641      * @param columnIndex the first column is 1, the second is 2, ...
8642      * @param x the new column value
8643      * @param length the length of the stream
8644      * @exception SQLException if a database access error occurs,
8645      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8646      * or this method is called on a closed result set
8647      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8648      * this method
8649      * @since 1.6
8650      */
8651     public void updateAsciiStream(int columnIndex,
8652                            java.io.InputStream x,
8653                            long length) throws SQLException {
8654 
8655     }
8656 
8657     /**
8658      * Updates the designated column with a binary stream value, which will have
8659      * the specified number of bytes.
8660      * The updater methods are used to update column values in the
8661      * current row or the insert row.  The updater methods do not
8662      * update the underlying database; instead the <code>updateRow</code> or
8663      * <code>insertRow</code> methods are called to update the database.
8664      *
8665      * @param columnIndex the first column is 1, the second is 2, ...
8666      * @param x the new column value
8667      * @param length the length of the stream
8668      * @exception SQLException if a database access error occurs,
8669      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8670      * or this method is called on a closed result set
8671      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8672      * this method
8673      * @since 1.6
8674      */
8675     public void updateBinaryStream(int columnIndex,
8676                             java.io.InputStream x,
8677                             long length) throws SQLException {
8678     }
8679 
8680     /**
8681      * Updates the designated column with a character stream value, which will have
8682      * the specified number of bytes.
8683      * The updater methods are used to update column values in the
8684      * current row or the insert row.  The updater methods do not
8685      * update the underlying database; instead the <code>updateRow</code> or
8686      * <code>insertRow</code> methods are called to update the database.
8687      *
8688      * @param columnIndex the first column is 1, the second is 2, ...
8689      * @param x the new column value
8690      * @param length the length of the stream
8691      * @exception SQLException if a database access error occurs,
8692      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8693      * or this method is called on a closed result set
8694      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8695      * this method
8696      * @since 1.6
8697      */
8698     public void updateCharacterStream(int columnIndex,
8699                              java.io.Reader x,
8700                              long length) throws SQLException {
8701         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8702     }
8703 
8704     /**
8705      * Updates the designated column with a character stream value, which will have
8706      * the specified number of bytes.
8707      * The updater methods are used to update column values in the
8708      * current row or the insert row.  The updater methods do not
8709      * update the underlying database; instead the <code>updateRow</code> or
8710      * <code>insertRow</code> methods are called to update the database.
8711      *
8712      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8713 bel is the name of the column
8714      * @param reader the <code>java.io.Reader</code> object containing
8715      *        the new column value
8716      * @param length the length of the stream
8717      * @exception SQLException if a database access error occurs,
8718      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8719      * or this method is called on a closed result set
8720      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8721      * this method
8722      * @since 1.6
8723      */
8724     public void updateCharacterStream(String columnLabel,
8725                              java.io.Reader reader,
8726                              long length) throws SQLException {
8727         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8728     }
8729      /**
8730      * Updates the designated column with an ascii stream value, which will have
8731      * the specified number of bytes..
8732      * The updater methods are used to update column values in the
8733      * current row or the insert row.  The updater methods do not
8734      * update the underlying database; instead the <code>updateRow</code> or
8735      * <code>insertRow</code> methods are called to update the database.
8736      *
8737      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the label is the name of the column
8738      * @param x the new column value
8739      * @param length the length of the stream
8740      * @exception SQLException if a database access error occurs,
8741      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8742      * or this method is called on a closed result set
8743      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8744      * this method
8745      * @since 1.6
8746      */
8747     public void updateAsciiStream(String columnLabel,
8748                            java.io.InputStream x,
8749                            long length) throws SQLException {
8750     }
8751 
8752     /**
8753      * Updates the designated column with a binary stream value, which will have
8754      * the specified number of bytes.
8755      * The updater methods are used to update column values in the
8756      * current row or the insert row.  The updater methods do not
8757      * update the underlying database; instead the <code>updateRow</code> or
8758      * <code>insertRow</code> methods are called to update the database.
8759      *
8760      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the label is the name of the column
8761      * @param x the new column value
8762      * @param length the length of the stream
8763      * @exception SQLException if a database access error occurs,
8764      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8765      * or this method is called on a closed result set
8766      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8767      * this method
8768      * @since 1.6
8769      */
8770     public void updateBinaryStream(String columnLabel,
8771                             java.io.InputStream x,
8772                             long length) throws SQLException {
8773     }
8774 
8775     /**
8776      * Updates the designated column with a binary stream value.
8777      * The updater methods are used to update column values in the
8778      * current row or the insert row.  The updater methods do not
8779      * update the underlying database; instead the <code>updateRow</code> or
8780      * <code>insertRow</code> methods are called to update the database.
8781      *
8782      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8783      * it might be more efficient to use a version of
8784      * <code>updateBinaryStream</code> which takes a length parameter.
8785      *
8786      * @param columnIndex the first column is 1, the second is 2, ...
8787      * @param x the new column value
8788      * @exception SQLException if a database access error occurs,
8789      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8790      * or this method is called on a closed result set
8791      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8792      * this method
8793      * @since 1.6
8794      */
8795     public void updateBinaryStream(int columnIndex,
8796                             java.io.InputStream x) throws SQLException {
8797         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8798     }
8799 
8800 
8801     /**
8802      * Updates the designated column with a binary stream value.
8803      * The updater methods are used to update column values in the
8804      * current row or the insert row.  The updater methods do not
8805      * update the underlying database; instead the <code>updateRow</code> or
8806      * <code>insertRow</code> methods are called to update the database.
8807      *
8808      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8809      * it might be more efficient to use a version of
8810      * <code>updateBinaryStream</code> which takes a length parameter.
8811      *
8812      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8813 bel is the name of the column
8814      * @param x the new column value
8815      * @exception SQLException if a database access error occurs,
8816      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8817      * or this method is called on a closed result set
8818      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8819      * this method
8820      * @since 1.6
8821      */
8822     public void updateBinaryStream(String columnLabel,
8823                             java.io.InputStream x) throws SQLException {
8824         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8825     }
8826 
8827     /**
8828      * Updates the designated column with a character stream value.
8829      * The updater methods are used to update column values in the
8830      * current row or the insert row.  The updater methods do not
8831      * update the underlying database; instead the <code>updateRow</code> or
8832      * <code>insertRow</code> methods are called to update the database.
8833      *
8834      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8835      * it might be more efficient to use a version of
8836      * <code>updateCharacterStream</code> which takes a length parameter.
8837      *
8838      * @param columnIndex the first column is 1, the second is 2, ...
8839      * @param x the new column value
8840      * @exception SQLException if a database access error occurs,
8841      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8842      * or this method is called on a closed result set
8843      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8844      * this method
8845      * @since 1.6
8846      */
8847     public void updateCharacterStream(int columnIndex,
8848                              java.io.Reader x) throws SQLException {
8849         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8850     }
8851 
8852     /**
8853      * Updates the designated column with a character stream value.
8854      * The updater methods are used to update column values in the
8855      * current row or the insert row.  The updater methods do not
8856      * update the underlying database; instead the <code>updateRow</code> or
8857      * <code>insertRow</code> methods are called to update the database.
8858      *
8859      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8860      * it might be more efficient to use a version of
8861      * <code>updateCharacterStream</code> which takes a length parameter.
8862      *
8863      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8864 bel is the name of the column
8865      * @param reader the <code>java.io.Reader</code> object containing
8866      *        the new column value
8867      * @exception SQLException if a database access error occurs,
8868      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8869      * or this method is called on a closed result set
8870      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8871      * this method
8872      * @since 1.6
8873      */
8874     public void updateCharacterStream(String columnLabel,
8875                              java.io.Reader reader) throws SQLException {
8876         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8877     }
8878 
8879     /**
8880      * Updates the designated column with an ascii stream value.
8881      * The updater methods are used to update column values in the
8882      * current row or the insert row.  The updater methods do not
8883      * update the underlying database; instead the <code>updateRow</code> or
8884      * <code>insertRow</code> methods are called to update the database.
8885      *
8886      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8887      * it might be more efficient to use a version of
8888      * <code>updateAsciiStream</code> which takes a length parameter.
8889      *
8890      * @param columnIndex the first column is 1, the second is 2, ...
8891      * @param x the new column value
8892      * @exception SQLException if a database access error occurs,
8893      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8894      * or this method is called on a closed result set
8895      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8896      * this method
8897      * @since 1.6
8898      */
8899     public void updateAsciiStream(int columnIndex,
8900                            java.io.InputStream x) throws SQLException {
8901         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8902     }
8903 
8904     /**
8905      * Updates the designated column with an ascii stream value.
8906      * The updater methods are used to update column values in the
8907      * current row or the insert row.  The updater methods do not
8908      * update the underlying database; instead the <code>updateRow</code> or
8909      * <code>insertRow</code> methods are called to update the database.
8910      *
8911      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8912      * it might be more efficient to use a version of
8913      * <code>updateAsciiStream</code> which takes a length parameter.
8914      *
8915      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8916 bel is the name of the column
8917      * @param x the new column value
8918      * @exception SQLException if a database access error occurs,
8919      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8920      * or this method is called on a closed result set
8921      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8922      * this method
8923      * @since 1.6
8924      */
8925     public void updateAsciiStream(String columnLabel,
8926                            java.io.InputStream x) throws SQLException {
8927 
8928     }
8929 
8930    /**
8931   * Sets the designated parameter to the given <code>java.net.URL</code> value.
8932   * The driver converts this to an SQL <code>DATALINK</code> value
8933   * when it sends it to the database.
8934   *
8935   * @param parameterIndex the first parameter is 1, the second is 2, ...
8936   * @param x the <code>java.net.URL</code> object to be set
8937   * @exception SQLException if a database access error occurs or
8938   * this method is called on a closed <code>PreparedStatement</code>
8939   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
8940   * @since 1.4
8941   */
8942   public void setURL(int parameterIndex, java.net.URL x) throws SQLException{
8943         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8944    }
8945 
8946   /**
8947   * Sets the designated parameter to a <code>Reader</code> object.
8948   * This method differs from the <code>setCharacterStream (int, Reader)</code> method
8949   * because it informs the driver that the parameter value should be sent to
8950   * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
8951   * driver may have to do extra work to determine whether the parameter
8952   * data should be sent to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
8953   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8954   * it might be more efficient to use a version of
8955   * <code>setNClob</code> which takes a length parameter.
8956   *
8957   * @param parameterIndex index of the first parameter is 1, the second is 2, ...
8958   * @param reader An object that contains the data to set the parameter value to.
8959   * @throws SQLException if parameterIndex does not correspond to a parameter
8960   * marker in the SQL statement;
8961   * if the driver does not support national character sets;
8962   * if the driver can detect that a data conversion
8963   *  error could occur;  if a database access error occurs or
8964   * this method is called on a closed <code>PreparedStatement</code>
8965   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
8966   *
8967   * @since 1.6
8968   */
8969   public void setNClob(int parameterIndex, Reader reader)
8970     throws SQLException{
8971         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8972    }
8973 
8974   /**
8975   * Sets the designated parameter to a <code>Reader</code> object.  The <code>reader</code> must contain  the number
8976              * of characters specified by length otherwise a <code>SQLException</code> will be
8977             * generated when the <code>CallableStatement</code> is executed.
8978             * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
8979             * because it informs the driver that the parameter value should be sent to
8980             * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
8981             * driver may have to do extra work to determine whether the parameter
8982             * data should be send to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
8983             *
8984             * @param parameterName the name of the parameter to be set
8985             * @param reader An object that contains the data to set the parameter value to.
8986             * @param length the number of characters in the parameter data.
8987             * @throws SQLException if parameterIndex does not correspond to a parameter
8988             * marker in the SQL statement; if the length specified is less than zero;
8989             * if the driver does not support national
8990             *         character sets;  if the driver can detect that a data conversion
8991             *  error could occur; if a database access error occurs or
8992             * this method is called on a closed <code>CallableStatement</code>
8993             * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8994             * this method
8995             * @since 1.6
8996             */
8997             public void setNClob(String parameterName, Reader reader, long length)
8998     throws SQLException{
8999         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9000    }
9001 
9002 
9003  /**
9004   * Sets the designated parameter to a <code>Reader</code> object.
9005   * This method differs from the <code>setCharacterStream (int, Reader)</code> method
9006   * because it informs the driver that the parameter value should be sent to
9007   * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9008   * driver may have to do extra work to determine whether the parameter
9009   * data should be send to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
9010   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9011   * it might be more efficient to use a version of
9012   * <code>setNClob</code> which takes a length parameter.
9013   *
9014   * @param parameterName the name of the parameter
9015   * @param reader An object that contains the data to set the parameter value to.
9016   * @throws SQLException if the driver does not support national character sets;
9017   * if the driver can detect that a data conversion
9018   *  error could occur;  if a database access error occurs or
9019   * this method is called on a closed <code>CallableStatement</code>
9020   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9021   *
9022   * @since 1.6
9023   */
9024   public void setNClob(String parameterName, Reader reader)
9025     throws SQLException{
9026         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9027    }
9028 
9029 
9030     /**
9031      * Sets the designated parameter to a <code>Reader</code> object.  The reader must contain  the number
9032      * of characters specified by length otherwise a <code>SQLException</code> will be
9033      * generated when the <code>PreparedStatement</code> is executed.
9034      * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
9035      * because it informs the driver that the parameter value should be sent to
9036      * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9037      * driver may have to do extra work to determine whether the parameter
9038      * data should be sent to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
9039      * @param parameterIndex index of the first parameter is 1, the second is 2, ...
9040      * @param reader An object that contains the data to set the parameter value to.
9041      * @param length the number of characters in the parameter data.
9042      * @throws SQLException if parameterIndex does not correspond to a parameter
9043      * marker in the SQL statement; if the length specified is less than zero;
9044      * if the driver does not support national character sets;
9045      * if the driver can detect that a data conversion
9046      *  error could occur;  if a database access error occurs or
9047      * this method is called on a closed <code>PreparedStatement</code>
9048      * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9049      *
9050      * @since 1.6
9051      */
9052      public void setNClob(int parameterIndex, Reader reader, long length)
9053        throws SQLException{
9054         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9055    }
9056 
9057 
9058     /**
9059      * Sets the designated parameter to a <code>java.sql.NClob</code> object. The driver converts this to
9060 a
9061      * SQL <code>NCLOB</code> value when it sends it to the database.
9062      * @param parameterIndex of the first parameter is 1, the second is 2, ...
9063      * @param value the parameter value
9064      * @throws SQLException if the driver does not support national
9065      *         character sets;  if the driver can detect that a data conversion
9066      *  error could occur ; or if a database access error occurs
9067      * @since 1.6
9068      */
9069      public void setNClob(int parameterIndex, NClob value) throws SQLException{
9070         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9071    }
9072 
9073 
9074    /**
9075   * Sets the designated parameter to the given <code>String</code> object.
9076   * The driver converts this to a SQL <code>NCHAR</code> or
9077   * <code>NVARCHAR</code> or <code>LONGNVARCHAR</code> value
9078   * (depending on the argument's
9079   * size relative to the driver's limits on <code>NVARCHAR</code> values)
9080   * when it sends it to the database.
9081   *
9082   * @param parameterIndex of the first parameter is 1, the second is 2, ...
9083   * @param value the parameter value
9084   * @throws SQLException if the driver does not support national
9085   *         character sets;  if the driver can detect that a data conversion
9086   *  error could occur ; or if a database access error occurs
9087   * @since 1.6
9088   */
9089   public void setNString(int parameterIndex, String value) throws SQLException{
9090         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9091    }
9092 
9093 
9094  /**
9095   * Sets the designated parameter to the given <code>String</code> object.
9096   * The driver converts this to a SQL <code>NCHAR</code> or
9097   * <code>NVARCHAR</code> or <code>LONGNVARCHAR</code>
9098   * @param parameterName the name of the column to be set
9099   * @param value the parameter value
9100   * @throws SQLException if the driver does not support national
9101   *         character sets;  if the driver can detect that a data conversion
9102   *  error could occur; or if a database access error occurs
9103   * @since 1.6
9104   */
9105  public void setNString(String parameterName, String value)
9106          throws SQLException{
9107         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9108    }
9109 
9110 
9111  /**
9112   * Sets the designated parameter to a <code>Reader</code> object. The
9113   * <code>Reader</code> reads the data till end-of-file is reached. The
9114   * driver does the necessary conversion from Java character format to
9115   * the national character set in the database.
9116   * @param parameterIndex of the first parameter is 1, the second is 2, ...
9117   * @param value the parameter value
9118   * @param length the number of characters in the parameter data.
9119   * @throws SQLException if the driver does not support national
9120   *         character sets;  if the driver can detect that a data conversion
9121   *  error could occur ; or if a database access error occurs
9122   * @since 1.6
9123   */
9124   public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException{
9125         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9126    }
9127 
9128 
9129  /**
9130   * Sets the designated parameter to a <code>Reader</code> object. The
9131   * <code>Reader</code> reads the data till end-of-file is reached. The
9132   * driver does the necessary conversion from Java character format to
9133   * the national character set in the database.
9134   * @param parameterName the name of the column to be set
9135   * @param value the parameter value
9136   * @param length the number of characters in the parameter data.
9137   * @throws SQLException if the driver does not support national
9138   *         character sets;  if the driver can detect that a data conversion
9139   *  error could occur; or if a database access error occurs
9140   * @since 1.6
9141   */
9142  public void setNCharacterStream(String parameterName, Reader value, long length)
9143          throws SQLException{
9144         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9145    }
9146 
9147   /**
9148   * Sets the designated parameter to a <code>Reader</code> object. The
9149   * <code>Reader</code> reads the data till end-of-file is reached. The
9150   * driver does the necessary conversion from Java character format to
9151   * the national character set in the database.
9152 
9153   * <P><B>Note:</B> This stream object can either be a standard
9154   * Java stream object or your own subclass that implements the
9155   * standard interface.
9156   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9157   * it might be more efficient to use a version of
9158   * <code>setNCharacterStream</code> which takes a length parameter.
9159   *
9160   * @param parameterName the name of the parameter
9161   * @param value the parameter value
9162   * @throws SQLException if the driver does not support national
9163   *         character sets;  if the driver can detect that a data conversion
9164   *  error could occur ; if a database access error occurs; or
9165   * this method is called on a closed <code>CallableStatement</code>
9166   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9167   * @since 1.6
9168   */
9169   public void setNCharacterStream(String parameterName, Reader value) throws SQLException{
9170         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9171    }
9172 
9173   /**
9174     * Sets the designated parameter to the given <code>java.sql.Timestamp</code> value,
9175     * using the given <code>Calendar</code> object.  The driver uses
9176     * the <code>Calendar</code> object to construct an SQL <code>TIMESTAMP</code> value,
9177     * which the driver then sends to the database.  With a
9178     * a <code>Calendar</code> object, the driver can calculate the timestamp
9179     * taking into account a custom timezone.  If no
9180     * <code>Calendar</code> object is specified, the driver uses the default
9181     * timezone, which is that of the virtual machine running the application.
9182     *
9183     * @param parameterName the name of the parameter
9184     * @param x the parameter value
9185     * @param cal the <code>Calendar</code> object the driver will use
9186     *            to construct the timestamp
9187     * @exception SQLException if a database access error occurs or
9188     * this method is called on a closed <code>CallableStatement</code>
9189     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9190     * this method
9191     * @see #getTimestamp
9192     * @since 1.4
9193     */
9194     public void setTimestamp(String parameterName, java.sql.Timestamp x, Calendar cal)
9195        throws SQLException{
9196         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9197    }
9198 
9199     /**
9200     * Sets the designated parameter to a <code>Reader</code> object.  The <code>reader</code> must contain  the number
9201                * of characters specified by length otherwise a <code>SQLException</code> will be
9202                * generated when the <code>CallableStatement</code> is executed.
9203               * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
9204               * because it informs the driver that the parameter value should be sent to
9205               * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9206               * driver may have to do extra work to determine whether the parameter
9207               * data should be send to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9208               * @param parameterName the name of the parameter to be set
9209               * @param reader An object that contains the data to set the parameter value to.
9210               * @param length the number of characters in the parameter data.
9211               * @throws SQLException if parameterIndex does not correspond to a parameter
9212               * marker in the SQL statement; if the length specified is less than zero;
9213               * a database access error occurs or
9214               * this method is called on a closed <code>CallableStatement</code>
9215               * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9216               * this method
9217               *
9218               * @since 1.6
9219               */
9220       public  void setClob(String parameterName, Reader reader, long length)
9221       throws SQLException{
9222         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9223    }
9224 
9225 
9226   /**
9227     * Sets the designated parameter to the given <code>java.sql.Clob</code> object.
9228     * The driver converts this to an SQL <code>CLOB</code> value when it
9229     * sends it to the database.
9230     *
9231     * @param parameterName the name of the parameter
9232     * @param x a <code>Clob</code> object that maps an SQL <code>CLOB</code> value
9233     * @exception SQLException if a database access error occurs or
9234     * this method is called on a closed <code>CallableStatement</code>
9235     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9236     * this method
9237     * @since 1.6
9238     */
9239     public void setClob (String parameterName, Clob x) throws SQLException{
9240         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9241    }
9242 
9243 
9244  /**
9245     * Sets the designated parameter to a <code>Reader</code> object.
9246     * This method differs from the <code>setCharacterStream (int, Reader)</code> method
9247     * because it informs the driver that the parameter value should be sent to
9248     * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9249     * driver may have to do extra work to determine whether the parameter
9250     * data should be send to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9251     *
9252     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9253     * it might be more efficient to use a version of
9254     * <code>setClob</code> which takes a length parameter.
9255     *
9256     * @param parameterName the name of the parameter
9257     * @param reader An object that contains the data to set the parameter value to.
9258     * @throws SQLException if a database access error occurs or this method is called on
9259     * a closed <code>CallableStatement</code>
9260     *
9261     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9262     * @since 1.6
9263     */
9264     public void setClob(String parameterName, Reader reader)
9265       throws SQLException{
9266         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9267    }
9268 
9269 
9270  /**
9271     * Sets the designated parameter to the given <code>java.sql.Date</code> value
9272     * using the default time zone of the virtual machine that is running
9273     * the application.
9274     * The driver converts this
9275     * to an SQL <code>DATE</code> value when it sends it to the database.
9276     *
9277     * @param parameterName the name of the parameter
9278     * @param x the parameter value
9279     * @exception SQLException if a database access error occurs or
9280     * this method is called on a closed <code>CallableStatement</code>
9281     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9282     * this method
9283     * @see #getDate
9284     * @since 1.4
9285     */
9286     public void setDate(String parameterName, java.sql.Date x)
9287        throws SQLException{
9288         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9289    }
9290 
9291 
9292  /**
9293     * Sets the designated parameter to the given <code>java.sql.Date</code> value,
9294     * using the given <code>Calendar</code> object.  The driver uses
9295     * the <code>Calendar</code> object to construct an SQL <code>DATE</code> value,
9296     * which the driver then sends to the database.  With a
9297     * a <code>Calendar</code> object, the driver can calculate the date
9298     * taking into account a custom timezone.  If no
9299     * <code>Calendar</code> object is specified, the driver uses the default
9300     * timezone, which is that of the virtual machine running the application.
9301     *
9302     * @param parameterName the name of the parameter
9303     * @param x the parameter value
9304     * @param cal the <code>Calendar</code> object the driver will use
9305     *            to construct the date
9306     * @exception SQLException if a database access error occurs or
9307     * this method is called on a closed <code>CallableStatement</code>
9308     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9309     * this method
9310     * @see #getDate
9311     * @since 1.4
9312     */
9313    public void setDate(String parameterName, java.sql.Date x, Calendar cal)
9314        throws SQLException{
9315         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9316    }
9317 
9318 
9319  /**
9320     * Sets the designated parameter to the given <code>java.sql.Time</code> value.
9321     * The driver converts this
9322     * to an SQL <code>TIME</code> value when it sends it to the database.
9323     *
9324     * @param parameterName the name of the parameter
9325     * @param x the parameter value
9326     * @exception SQLException if a database access error occurs or
9327     * this method is called on a closed <code>CallableStatement</code>
9328     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9329     * this method
9330     * @see #getTime
9331     * @since 1.4
9332     */
9333    public void setTime(String parameterName, java.sql.Time x)
9334        throws SQLException{
9335         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9336    }
9337 
9338 
9339  /**
9340     * Sets the designated parameter to the given <code>java.sql.Time</code> value,
9341     * using the given <code>Calendar</code> object.  The driver uses
9342     * the <code>Calendar</code> object to construct an SQL <code>TIME</code> value,
9343     * which the driver then sends to the database.  With a
9344     * a <code>Calendar</code> object, the driver can calculate the time
9345     * taking into account a custom timezone.  If no
9346     * <code>Calendar</code> object is specified, the driver uses the default
9347     * timezone, which is that of the virtual machine running the application.
9348     *
9349     * @param parameterName the name of the parameter
9350     * @param x the parameter value
9351     * @param cal the <code>Calendar</code> object the driver will use
9352     *            to construct the time
9353     * @exception SQLException if a database access error occurs or
9354     * this method is called on a closed <code>CallableStatement</code>
9355     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9356     * this method
9357     * @see #getTime
9358     * @since 1.4
9359     */
9360    public void setTime(String parameterName, java.sql.Time x, Calendar cal)
9361        throws SQLException{
9362         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9363    }
9364 
9365    /**
9366    * Sets the designated parameter to a <code>Reader</code> object.
9367    * This method differs from the <code>setCharacterStream (int, Reader)</code> method
9368    * because it informs the driver that the parameter value should be sent to
9369    * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9370    * driver may have to do extra work to determine whether the parameter
9371    * data should be sent to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9372    *
9373    * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9374    * it might be more efficient to use a version of
9375    * <code>setClob</code> which takes a length parameter.
9376    *
9377    * @param parameterIndex index of the first parameter is 1, the second is 2, ...
9378    * @param reader An object that contains the data to set the parameter value to.
9379    * @throws SQLException if a database access error occurs, this method is called on
9380    * a closed <code>PreparedStatement</code>or if parameterIndex does not correspond to a parameter
9381    * marker in the SQL statement
9382    *
9383    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9384    * @since 1.6
9385    */
9386    public void setClob(int parameterIndex, Reader reader)
9387      throws SQLException{
9388         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9389    }
9390 
9391     /**
9392    * Sets the designated parameter to a <code>Reader</code> object.  The reader must contain  the number
9393    * of characters specified by length otherwise a <code>SQLException</code> will be
9394    * generated when the <code>PreparedStatement</code> is executed.
9395    *This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
9396    * because it informs the driver that the parameter value should be sent to
9397    * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9398    * driver may have to do extra work to determine whether the parameter
9399    * data should be sent to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9400    * @param parameterIndex index of the first parameter is 1, the second is 2, ...
9401    * @param reader An object that contains the data to set the parameter value to.
9402    * @param length the number of characters in the parameter data.
9403    * @throws SQLException if a database access error occurs, this method is called on
9404    * a closed <code>PreparedStatement</code>, if parameterIndex does not correspond to a parameter
9405    * marker in the SQL statement, or if the length specified is less than zero.
9406    *
9407    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9408    * @since 1.6
9409    */
9410    public void setClob(int parameterIndex, Reader reader, long length)
9411      throws SQLException{
9412         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9413    }
9414 
9415 
9416  /**
9417     * Sets the designated parameter to a <code>InputStream</code> object.  The inputstream must contain  the number
9418     * of characters specified by length otherwise a <code>SQLException</code> will be
9419     * generated when the <code>PreparedStatement</code> is executed.
9420     * This method differs from the <code>setBinaryStream (int, InputStream, int)</code>
9421     * method because it informs the driver that the parameter value should be
9422     * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9423     * the driver may have to do extra work to determine whether the parameter
9424     * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9425     * @param parameterIndex index of the first parameter is 1,
9426     * the second is 2, ...
9427     * @param inputStream An object that contains the data to set the parameter
9428     * value to.
9429     * @param length the number of bytes in the parameter data.
9430     * @throws SQLException if a database access error occurs,
9431     * this method is called on a closed <code>PreparedStatement</code>,
9432     * if parameterIndex does not correspond
9433     * to a parameter marker in the SQL statement,  if the length specified
9434     * is less than zero or if the number of bytes in the inputstream does not match
9435     * the specified length.
9436     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9437     *
9438     * @since 1.6
9439     */
9440     public void setBlob(int parameterIndex, InputStream inputStream, long length)
9441        throws SQLException{
9442         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9443    }
9444 
9445 
9446  /**
9447     * Sets the designated parameter to a <code>InputStream</code> object.
9448     * This method differs from the <code>setBinaryStream (int, InputStream)</code>
9449     * method because it informs the driver that the parameter value should be
9450     * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9451     * the driver may have to do extra work to determine whether the parameter
9452     * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9453     *
9454     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9455     * it might be more efficient to use a version of
9456     * <code>setBlob</code> which takes a length parameter.
9457     *
9458     * @param parameterIndex index of the first parameter is 1,
9459     * the second is 2, ...
9460     * @param inputStream An object that contains the data to set the parameter
9461     * value to.
9462     * @throws SQLException if a database access error occurs,
9463     * this method is called on a closed <code>PreparedStatement</code> or
9464     * if parameterIndex does not correspond
9465     * to a parameter marker in the SQL statement,
9466     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9467     *
9468     * @since 1.6
9469     */
9470     public void setBlob(int parameterIndex, InputStream inputStream)
9471        throws SQLException{
9472         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9473    }
9474 
9475 
9476  /**
9477     * Sets the designated parameter to a <code>InputStream</code> object.  The <code>inputstream</code> must contain  the number
9478      * of characters specified by length, otherwise a <code>SQLException</code> will be
9479      * generated when the <code>CallableStatement</code> is executed.
9480      * This method differs from the <code>setBinaryStream (int, InputStream, int)</code>
9481      * method because it informs the driver that the parameter value should be
9482      * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9483      * the driver may have to do extra work to determine whether the parameter
9484      * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9485      *
9486      * @param parameterName the name of the parameter to be set
9487      * the second is 2, ...
9488      *
9489      * @param inputStream An object that contains the data to set the parameter
9490      * value to.
9491      * @param length the number of bytes in the parameter data.
9492      * @throws SQLException  if parameterIndex does not correspond
9493      * to a parameter marker in the SQL statement,  or if the length specified
9494      * is less than zero; if the number of bytes in the inputstream does not match
9495      * the specified length; if a database access error occurs or
9496      * this method is called on a closed <code>CallableStatement</code>
9497      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9498      * this method
9499      *
9500      * @since 1.6
9501      */
9502      public void setBlob(String parameterName, InputStream inputStream, long length)
9503         throws SQLException{
9504         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9505    }
9506 
9507 
9508  /**
9509     * Sets the designated parameter to the given <code>java.sql.Blob</code> object.
9510     * The driver converts this to an SQL <code>BLOB</code> value when it
9511     * sends it to the database.
9512     *
9513     * @param parameterName the name of the parameter
9514     * @param x a <code>Blob</code> object that maps an SQL <code>BLOB</code> value
9515     * @exception SQLException if a database access error occurs or
9516     * this method is called on a closed <code>CallableStatement</code>
9517     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9518     * this method
9519     * @since 1.6
9520     */
9521    public void setBlob (String parameterName, Blob x) throws SQLException{
9522         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9523    }
9524 
9525 
9526  /**
9527     * Sets the designated parameter to a <code>InputStream</code> object.
9528     * This method differs from the <code>setBinaryStream (int, InputStream)</code>
9529     * method because it informs the driver that the parameter value should be
9530     * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9531     * the driver may have to do extra work to determine whether the parameter
9532     * data should be send to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9533     *
9534     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9535     * it might be more efficient to use a version of
9536     * <code>setBlob</code> which takes a length parameter.
9537     *
9538     * @param parameterName the name of the parameter
9539     * @param inputStream An object that contains the data to set the parameter
9540     * value to.
9541     * @throws SQLException if a database access error occurs or
9542     * this method is called on a closed <code>CallableStatement</code>
9543     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9544     *
9545     * @since 1.6
9546     */
9547     public void setBlob(String parameterName, InputStream inputStream)
9548        throws SQLException{
9549         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9550    }
9551 
9552     /**
9553     * Sets the value of the designated parameter with the given object. The second
9554     * argument must be an object type; for integral values, the
9555     * <code>java.lang</code> equivalent objects should be used.
9556     *
9557     * <p>The given Java object will be converted to the given targetSqlType
9558     * before being sent to the database.
9559     *
9560     * If the object has a custom mapping (is of a class implementing the
9561     * interface <code>SQLData</code>),
9562     * the JDBC driver should call the method <code>SQLData.writeSQL</code> to write it
9563     * to the SQL data stream.
9564     * If, on the other hand, the object is of a class implementing
9565     * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>,  <code>NClob</code>,
9566     *  <code>Struct</code>, <code>java.net.URL</code>,
9567     * or <code>Array</code>, the driver should pass it to the database as a
9568     * value of the corresponding SQL type.
9569     * <P>
9570     * Note that this method may be used to pass datatabase-
9571     * specific abstract data types.
9572     *
9573     * @param parameterName the name of the parameter
9574     * @param x the object containing the input parameter value
9575     * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
9576     * sent to the database. The scale argument may further qualify this type.
9577     * @param scale for java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types,
9578     *          this is the number of digits after the decimal point.  For all other
9579     *          types, this value will be ignored.
9580     * @exception SQLException if a database access error occurs or
9581     * this method is called on a closed <code>CallableStatement</code>
9582     * @exception SQLFeatureNotSupportedException if <code>targetSqlType</code> is
9583     * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,
9584     * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,
9585     * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,
9586     *  <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
9587     * or  <code>STRUCT</code> data type and the JDBC driver does not support
9588     * this data type
9589     * @see Types
9590     * @see #getObject
9591     * @since 1.4
9592     */
9593     public void setObject(String parameterName, Object x, int targetSqlType, int scale)
9594        throws SQLException{
9595         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9596    }
9597 
9598 
9599 
9600  /**
9601     * Sets the value of the designated parameter with the given object.
9602     * This method is like the method <code>setObject</code>
9603     * above, except that it assumes a scale of zero.
9604     *
9605     * @param parameterName the name of the parameter
9606     * @param x the object containing the input parameter value
9607     * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
9608     *                      sent to the database
9609     * @exception SQLException if a database access error occurs or
9610     * this method is called on a closed <code>CallableStatement</code>
9611     * @exception SQLFeatureNotSupportedException if <code>targetSqlType</code> is
9612     * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,
9613     * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,
9614     * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,
9615     *  <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
9616     * or  <code>STRUCT</code> data type and the JDBC driver does not support
9617     * this data type
9618     * @see #getObject
9619     * @since 1.4
9620     */
9621     public void setObject(String parameterName, Object x, int targetSqlType)
9622        throws SQLException{
9623         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9624    }
9625 
9626 
9627  /**
9628    * Sets the value of the designated parameter with the given object.
9629    * The second parameter must be of type <code>Object</code>; therefore, the
9630    * <code>java.lang</code> equivalent objects should be used for built-in types.
9631    *
9632    * <p>The JDBC specification specifies a standard mapping from
9633    * Java <code>Object</code> types to SQL types.  The given argument
9634    * will be converted to the corresponding SQL type before being
9635    * sent to the database.
9636    *
9637    * <p>Note that this method may be used to pass datatabase-
9638    * specific abstract data types, by using a driver-specific Java
9639    * type.
9640    *
9641    * If the object is of a class implementing the interface <code>SQLData</code>,
9642    * the JDBC driver should call the method <code>SQLData.writeSQL</code>
9643    * to write it to the SQL data stream.
9644    * If, on the other hand, the object is of a class implementing
9645    * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>,  <code>NClob</code>,
9646    *  <code>Struct</code>, <code>java.net.URL</code>,
9647    * or <code>Array</code>, the driver should pass it to the database as a
9648    * value of the corresponding SQL type.
9649    * <P>
9650    * This method throws an exception if there is an ambiguity, for example, if the
9651    * object is of a class implementing more than one of the interfaces named above.
9652    *
9653    * @param parameterName the name of the parameter
9654    * @param x the object containing the input parameter value
9655    * @exception SQLException if a database access error occurs,
9656    * this method is called on a closed <code>CallableStatement</code> or if the given
9657    *            <code>Object</code> parameter is ambiguous
9658    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9659    * this method
9660    * @see #getObject
9661    * @since 1.4
9662    */
9663    public void setObject(String parameterName, Object x) throws SQLException{
9664         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9665    }
9666 
9667     /**
9668     * Sets the designated parameter to the given input stream, which will have
9669     * the specified number of bytes.
9670     * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
9671     * parameter, it may be more practical to send it via a
9672     * <code>java.io.InputStream</code>. Data will be read from the stream
9673     * as needed until end-of-file is reached.  The JDBC driver will
9674     * do any necessary conversion from ASCII to the database char format.
9675     *
9676     * <P><B>Note:</B> This stream object can either be a standard
9677     * Java stream object or your own subclass that implements the
9678     * standard interface.
9679     *
9680     * @param parameterName the name of the parameter
9681     * @param x the Java input stream that contains the ASCII parameter value
9682     * @param length the number of bytes in the stream
9683     * @exception SQLException if a database access error occurs or
9684     * this method is called on a closed <code>CallableStatement</code>
9685     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9686     * this method
9687     * @since 1.4
9688     */
9689    public void setAsciiStream(String parameterName, java.io.InputStream x, int length)
9690        throws SQLException{
9691         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9692    }
9693 
9694 
9695  /**
9696     * Sets the designated parameter to the given input stream, which will have
9697     * the specified number of bytes.
9698     * When a very large binary value is input to a <code>LONGVARBINARY</code>
9699     * parameter, it may be more practical to send it via a
9700     * <code>java.io.InputStream</code> object. The data will be read from the stream
9701     * as needed until end-of-file is reached.
9702     *
9703     * <P><B>Note:</B> This stream object can either be a standard
9704     * Java stream object or your own subclass that implements the
9705     * standard interface.
9706     *
9707     * @param parameterName the name of the parameter
9708     * @param x the java input stream which contains the binary parameter value
9709     * @param length the number of bytes in the stream
9710     * @exception SQLException if a database access error occurs or
9711     * this method is called on a closed <code>CallableStatement</code>
9712     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9713     * this method
9714     * @since 1.4
9715     */
9716    public void setBinaryStream(String parameterName, java.io.InputStream x,
9717                         int length) throws SQLException{
9718         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9719    }
9720 
9721 
9722   /**
9723     * Sets the designated parameter to the given <code>Reader</code>
9724     * object, which is the given number of characters long.
9725     * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
9726     * parameter, it may be more practical to send it via a
9727     * <code>java.io.Reader</code> object. The data will be read from the stream
9728     * as needed until end-of-file is reached.  The JDBC driver will
9729     * do any necessary conversion from UNICODE to the database char format.
9730     *
9731     * <P><B>Note:</B> This stream object can either be a standard
9732     * Java stream object or your own subclass that implements the
9733     * standard interface.
9734     *
9735     * @param parameterName the name of the parameter
9736     * @param reader the <code>java.io.Reader</code> object that
9737     *        contains the UNICODE data used as the designated parameter
9738     * @param length the number of characters in the stream
9739     * @exception SQLException if a database access error occurs or
9740     * this method is called on a closed <code>CallableStatement</code>
9741     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9742     * this method
9743     * @since 1.4
9744     */
9745    public void setCharacterStream(String parameterName,
9746                            java.io.Reader reader,
9747                            int length) throws SQLException{
9748         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9749    }
9750 
9751 
9752   /**
9753    * Sets the designated parameter to the given input stream.
9754    * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
9755    * parameter, it may be more practical to send it via a
9756    * <code>java.io.InputStream</code>. Data will be read from the stream
9757    * as needed until end-of-file is reached.  The JDBC driver will
9758    * do any necessary conversion from ASCII to the database char format.
9759    *
9760    * <P><B>Note:</B> This stream object can either be a standard
9761    * Java stream object or your own subclass that implements the
9762    * standard interface.
9763    * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9764    * it might be more efficient to use a version of
9765    * <code>setAsciiStream</code> which takes a length parameter.
9766    *
9767    * @param parameterName the name of the parameter
9768    * @param x the Java input stream that contains the ASCII parameter value
9769    * @exception SQLException if a database access error occurs or
9770    * this method is called on a closed <code>CallableStatement</code>
9771    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9772      * @since 1.6
9773   */
9774   public void setAsciiStream(String parameterName, java.io.InputStream x)
9775           throws SQLException{
9776         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9777    }
9778 
9779 
9780  /**
9781     * Sets the designated parameter to the given input stream.
9782     * When a very large binary value is input to a <code>LONGVARBINARY</code>
9783     * parameter, it may be more practical to send it via a
9784     * <code>java.io.InputStream</code> object. The data will be read from the
9785     * stream as needed until end-of-file is reached.
9786     *
9787     * <P><B>Note:</B> This stream object can either be a standard
9788     * Java stream object or your own subclass that implements the
9789     * standard interface.
9790     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9791     * it might be more efficient to use a version of
9792     * <code>setBinaryStream</code> which takes a length parameter.
9793     *
9794     * @param parameterName the name of the parameter
9795     * @param x the java input stream which contains the binary parameter value
9796     * @exception SQLException if a database access error occurs or
9797     * this method is called on a closed <code>CallableStatement</code>
9798     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9799     * @since 1.6
9800     */
9801    public void setBinaryStream(String parameterName, java.io.InputStream x)
9802    throws SQLException{
9803         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9804    }
9805 
9806 
9807 
9808  /**
9809     * Sets the designated parameter to the given <code>Reader</code>
9810     * object.
9811     * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
9812     * parameter, it may be more practical to send it via a
9813     * <code>java.io.Reader</code> object. The data will be read from the stream
9814     * as needed until end-of-file is reached.  The JDBC driver will
9815     * do any necessary conversion from UNICODE to the database char format.
9816     *
9817     * <P><B>Note:</B> This stream object can either be a standard
9818     * Java stream object or your own subclass that implements the
9819     * standard interface.
9820     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9821     * it might be more efficient to use a version of
9822     * <code>setCharacterStream</code> which takes a length parameter.
9823     *
9824     * @param parameterName the name of the parameter
9825     * @param reader the <code>java.io.Reader</code> object that contains the
9826     *        Unicode data
9827     * @exception SQLException if a database access error occurs or
9828     * this method is called on a closed <code>CallableStatement</code>
9829     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9830     * @since 1.6
9831     */
9832    public void setCharacterStream(String parameterName,
9833                          java.io.Reader reader) throws SQLException{
9834         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9835    }
9836 
9837    /**
9838     * Sets the designated parameter to the given
9839     * <code>java.math.BigDecimal</code> value.
9840     * The driver converts this to an SQL <code>NUMERIC</code> value when
9841     * it sends it to the database.
9842     *
9843     * @param parameterName the name of the parameter
9844     * @param x the parameter value
9845     * @exception SQLException if a database access error occurs or
9846     * this method is called on a closed <code>CallableStatement</code>
9847     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9848     * this method
9849     * @see #getBigDecimal
9850     * @since 1.4
9851     */
9852    public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException{
9853         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9854    }
9855 
9856 
9857 
9858  /**
9859     * Sets the designated parameter to the given Java <code>String</code> value.
9860     * The driver converts this
9861     * to an SQL <code>VARCHAR</code> or <code>LONGVARCHAR</code> value
9862     * (depending on the argument's
9863     * size relative to the driver's limits on <code>VARCHAR</code> values)
9864     * when it sends it to the database.
9865     *
9866     * @param parameterName the name of the parameter
9867     * @param x the parameter value
9868     * @exception SQLException if a database access error occurs or
9869     * this method is called on a closed <code>CallableStatement</code>
9870     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9871     * this method
9872     * @see #getString
9873     * @since 1.4
9874     */
9875    public void setString(String parameterName, String x) throws SQLException{
9876         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9877    }
9878 
9879 
9880 
9881  /**
9882     * Sets the designated parameter to the given Java array of bytes.
9883     * The driver converts this to an SQL <code>VARBINARY</code> or
9884     * <code>LONGVARBINARY</code> (depending on the argument's size relative
9885     * to the driver's limits on <code>VARBINARY</code> values) when it sends
9886     * it to the database.
9887     *
9888     * @param parameterName the name of the parameter
9889     * @param x the parameter value
9890     * @exception SQLException if a database access error occurs or
9891     * this method is called on a closed <code>CallableStatement</code>
9892     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9893     * this method
9894     * @see #getBytes
9895     * @since 1.4
9896     */
9897    public void setBytes(String parameterName, byte x[]) throws SQLException{
9898         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9899    }
9900 
9901 
9902 
9903  /**
9904     * Sets the designated parameter to the given <code>java.sql.Timestamp</code> value.
9905     * The driver
9906     * converts this to an SQL <code>TIMESTAMP</code> value when it sends it to the
9907     * database.
9908     *
9909     * @param parameterName the name of the parameter
9910     * @param x the parameter value
9911     * @exception SQLException if a database access error occurs or
9912     * this method is called on a closed <code>CallableStatement</code>
9913     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9914     * this method
9915     * @see #getTimestamp
9916     * @since 1.4
9917     */
9918    public void setTimestamp(String parameterName, java.sql.Timestamp x)
9919        throws SQLException{
9920         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9921    }
9922 
9923     /**
9924     * Sets the designated parameter to SQL <code>NULL</code>.
9925     *
9926     * <P><B>Note:</B> You must specify the parameter's SQL type.
9927     *
9928     * @param parameterName the name of the parameter
9929     * @param sqlType the SQL type code defined in <code>java.sql.Types</code>
9930     * @exception SQLException if a database access error occurs or
9931     * this method is called on a closed <code>CallableStatement</code>
9932     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9933     * this method
9934     * @since 1.4
9935     */
9936    public void setNull(String parameterName, int sqlType) throws SQLException {
9937         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9938    }
9939 
9940 
9941  /**
9942     * Sets the designated parameter to SQL <code>NULL</code>.
9943     * This version of the method <code>setNull</code> should
9944     * be used for user-defined types and REF type parameters.  Examples
9945     * of user-defined types include: STRUCT, DISTINCT, JAVA_OBJECT, and
9946     * named array types.
9947     *
9948     * <P><B>Note:</B> To be portable, applications must give the
9949     * SQL type code and the fully-qualified SQL type name when specifying
9950     * a NULL user-defined or REF parameter.  In the case of a user-defined type
9951     * the name is the type name of the parameter itself.  For a REF
9952     * parameter, the name is the type name of the referenced type.  If
9953     * a JDBC driver does not need the type code or type name information,
9954     * it may ignore it.
9955     *
9956     * Although it is intended for user-defined and Ref parameters,
9957     * this method may be used to set a null parameter of any JDBC type.
9958     * If the parameter does not have a user-defined or REF type, the given
9959     * typeName is ignored.
9960     *
9961     *
9962     * @param parameterName the name of the parameter
9963     * @param sqlType a value from <code>java.sql.Types</code>
9964     * @param typeName the fully-qualified name of an SQL user-defined type;
9965     *        ignored if the parameter is not a user-defined type or
9966     *        SQL <code>REF</code> value
9967     * @exception SQLException if a database access error occurs or
9968     * this method is called on a closed <code>CallableStatement</code>
9969     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9970     * this method
9971     * @since 1.4
9972     */
9973    public void setNull (String parameterName, int sqlType, String typeName)
9974        throws SQLException{
9975         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9976    }
9977 
9978 
9979 
9980  /**
9981     * Sets the designated parameter to the given Java <code>boolean</code> value.
9982     * The driver converts this
9983     * to an SQL <code>BIT</code> or <code>BOOLEAN</code> value when it sends it to the database.
9984     *
9985     * @param parameterName the name of the parameter
9986     * @param x the parameter value
9987     * @exception SQLException if a database access error occurs or
9988     * this method is called on a closed <code>CallableStatement</code>
9989     * @see #getBoolean
9990     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9991     * this method
9992     * @since 1.4
9993     */
9994    public void setBoolean(String parameterName, boolean x) throws SQLException{
9995         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9996    }
9997 
9998 
9999 
10000  /**
10001     * Sets the designated parameter to the given Java <code>byte</code> value.
10002     * The driver converts this
10003     * to an SQL <code>TINYINT</code> value when it sends it to the database.
10004     *
10005     * @param parameterName the name of the parameter
10006     * @param x the parameter value
10007     * @exception SQLException if a database access error occurs or
10008     * this method is called on a closed <code>CallableStatement</code>
10009     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10010     * this method
10011     * @see #getByte
10012     * @since 1.4
10013     */
10014    public void setByte(String parameterName, byte x) throws SQLException{
10015         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10016    }
10017 
10018 
10019 
10020  /**
10021     * Sets the designated parameter to the given Java <code>short</code> value.
10022     * The driver converts this
10023     * to an SQL <code>SMALLINT</code> value when it sends it to the database.
10024     *
10025     * @param parameterName the name of the parameter
10026     * @param x the parameter value
10027     * @exception SQLException if a database access error occurs or
10028     * this method is called on a closed <code>CallableStatement</code>
10029     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10030     * this method
10031     * @see #getShort
10032     * @since 1.4
10033     */
10034    public void setShort(String parameterName, short x) throws SQLException{
10035         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10036    }
10037 
10038 
10039  /**
10040     * Sets the designated parameter to the given Java <code>int</code> value.
10041     * The driver converts this
10042     * to an SQL <code>INTEGER</code> value when it sends it to the database.
10043     *
10044     * @param parameterName the name of the parameter
10045     * @param x the parameter value
10046     * @exception SQLException if a database access error occurs or
10047     * this method is called on a closed <code>CallableStatement</code>
10048     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10049     * this method
10050     * @see #getInt
10051     * @since 1.4
10052     */
10053    public void setInt(String parameterName, int x) throws SQLException{
10054         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10055    }
10056 
10057 
10058  /**
10059     * Sets the designated parameter to the given Java <code>long</code> value.
10060     * The driver converts this
10061     * to an SQL <code>BIGINT</code> value when it sends it to the database.
10062     *
10063     * @param parameterName the name of the parameter
10064     * @param x the parameter value
10065     * @exception SQLException if a database access error occurs or
10066     * this method is called on a closed <code>CallableStatement</code>
10067     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10068     * this method
10069     * @see #getLong
10070     * @since 1.4
10071     */
10072    public void setLong(String parameterName, long x) throws SQLException{
10073         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10074    }
10075 
10076 
10077  /**
10078     * Sets the designated parameter to the given Java <code>float</code> value.
10079     * The driver converts this
10080     * to an SQL <code>FLOAT</code> value when it sends it to the database.
10081     *
10082     * @param parameterName the name of the parameter
10083     * @param x the parameter value
10084     * @exception SQLException if a database access error occurs or
10085     * this method is called on a closed <code>CallableStatement</code>
10086     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10087     * this method
10088     * @see #getFloat
10089     * @since 1.4
10090     */
10091    public void setFloat(String parameterName, float x) throws SQLException{
10092         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10093    }
10094 
10095 
10096  /**
10097     * Sets the designated parameter to the given Java <code>double</code> value.
10098     * The driver converts this
10099     * to an SQL <code>DOUBLE</code> value when it sends it to the database.
10100     *
10101     * @param parameterName the name of the parameter
10102     * @param x the parameter value
10103     * @exception SQLException if a database access error occurs or
10104     * this method is called on a closed <code>CallableStatement</code>
10105     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10106     * this method
10107     * @see #getDouble
10108     * @since 1.4
10109     */
10110    public void setDouble(String parameterName, double x) throws SQLException{
10111         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10112    }
10113 
10114    /**
10115      * This method re populates the resBundle
10116      * during the deserialization process
10117      *
10118      */
10119     private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
10120         // Default state initialization happens here
10121         ois.defaultReadObject();
10122         // Initialization of transient Res Bundle happens here .
10123         try {
10124            resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
10125         } catch(IOException ioe) {
10126             throw new RuntimeException(ioe);
10127         }
10128 
10129     }
10130 
10131     //------------------------- JDBC 4.1 -----------------------------------
10132     public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
10133         throw new SQLFeatureNotSupportedException("Not supported yet.");
10134     }
10135 
10136     public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
10137         throw new SQLFeatureNotSupportedException("Not supported yet.");
10138     }
10139 
10140     static final long serialVersionUID =1884577171200622428L;
10141 }