1 /*
   2  * Copyright (c) 2003, 2011, 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 
  35 import javax.sql.rowset.*;
  36 import javax.sql.rowset.spi.*;
  37 import javax.sql.rowset.serial.*;
  38 import com.sun.rowset.internal.*;
  39 import com.sun.rowset.providers.*;
  40 
  41 /**
  42  * The standard implementation of the <code>CachedRowSet</code> interface.
  43  *
  44  * See interface defintion for full behaviour and implementation requirements.
  45  * This reference implementation has made provision for a one-to-one write back
  46  * facility and it is curremtly be possible to change the peristence provider
  47  * during the life-time of any CachedRowSetImpl.
  48  *
  49  * @author Jonathan Bruce, Amit Handa
  50  */
  51 
  52 public class CachedRowSetImpl extends BaseRowSet implements RowSet, RowSetInternal, Serializable, Cloneable, CachedRowSet {
  53 
  54     /**
  55      * The <code>SyncProvider</code> used by the CachedRowSet
  56      */
  57     private SyncProvider provider;
  58 
  59     /**
  60      * The <code>RowSetReaderImpl</code> object that is the reader
  61      * for this rowset.  The method <code>execute</code> uses this
  62      * reader as part of its implementation.
  63      * @serial
  64      */
  65     private RowSetReader rowSetReader;
  66 
  67     /**
  68      * The <code>RowSetWriterImpl</code> object that is the writer
  69      * for this rowset.  The method <code>acceptChanges</code> uses
  70      * this writer as part of its implementation.
  71      * @serial
  72      */
  73     private RowSetWriter rowSetWriter;
  74 
  75     /**
  76      * The <code>Connection</code> object that connects with this
  77      * <code>CachedRowSetImpl</code> object's current underlying data source.
  78      */
  79     private transient Connection conn;
  80 
  81     /**
  82      * The <code>ResultSetMetaData</code> object that contains information
  83      * about the columns in the <code>ResultSet</code> object that is the
  84      * current source of data for this <code>CachedRowSetImpl</code> object.
  85      */
  86     private transient ResultSetMetaData RSMD;
  87 
  88     /**
  89      * The <code>RowSetMetaData</code> object that contains information about
  90      * the columns in this <code>CachedRowSetImpl</code> object.
  91      * @serial
  92      */
  93     private RowSetMetaDataImpl RowSetMD;
  94 
  95     // Properties of this RowSet
  96 
  97     /**
  98      * An array containing the columns in this <code>CachedRowSetImpl</code>
  99      * object that form a unique identifier for a row. This array
 100      * is used by the writer.
 101      * @serial
 102      */
 103     private int keyCols[];
 104 
 105     /**
 106      * The name of the table in the underlying database to which updates
 107      * should be written.  This name is needed because most drivers
 108      * do not return this information in a <code>ResultSetMetaData</code>
 109      * object.
 110      * @serial
 111      */
 112     private String tableName;
 113 
 114     /**
 115      * A <code>Vector</code> object containing the <code>Row</code>
 116      * objects that comprise  this <code>CachedRowSetImpl</code> object.
 117      * @serial
 118      */
 119     private Vector<Object> rvh;
 120 
 121     /**
 122      * The current postion of the cursor in this <code>CachedRowSetImpl</code>
 123      * object.
 124      * @serial
 125      */
 126     private int cursorPos;
 127 
 128     /**
 129      * The current postion of the cursor in this <code>CachedRowSetImpl</code>
 130      * object not counting rows that have been deleted, if any.
 131      * <P>
 132      * For example, suppose that the cursor is on the last row of a rowset
 133      * that started with five rows and subsequently had the second and third
 134      * rows deleted. The <code>absolutePos</code> would be <code>3</code>,
 135      * whereas the <code>cursorPos</code> would be <code>5</code>.
 136      * @serial
 137      */
 138     private int absolutePos;
 139 
 140     /**
 141      * The number of deleted rows currently in this <code>CachedRowSetImpl</code>
 142      * object.
 143      * @serial
 144      */
 145     private int numDeleted;
 146 
 147     /**
 148      * The total number of rows currently in this <code>CachedRowSetImpl</code>
 149      * object.
 150      * @serial
 151      */
 152     private int numRows;
 153 
 154     /**
 155      * A special row used for constructing a new row. A new
 156      * row is constructed by using <code>ResultSet.updateXXX</code>
 157      * methods to insert column values into the insert row.
 158      * @serial
 159      */
 160     private InsertRow insertRow;
 161 
 162     /**
 163      * A <code>boolean</code> indicating whether the cursor is
 164      * currently on the insert row.
 165      * @serial
 166      */
 167     private boolean onInsertRow;
 168 
 169     /**
 170      * The field that temporarily holds the last position of the
 171      * cursor before it moved to the insert row, thus preserving
 172      * the number of the current row to which the cursor may return.
 173      * @serial
 174      */
 175     private int currentRow;
 176 
 177     /**
 178      * A <code>boolean</code> indicating whether the last value
 179      * returned was an SQL <code>NULL</code>.
 180      * @serial
 181      */
 182     private boolean lastValueNull;
 183 
 184     /**
 185      * A <code>SQLWarning</code> which logs on the warnings
 186      */
 187     private SQLWarning sqlwarn;
 188 
 189     /**
 190      * Used to track match column for JoinRowSet consumption
 191      */
 192     private String strMatchColumn ="";
 193 
 194     /**
 195      * Used to track match column for JoinRowSet consumption
 196      */
 197     private int iMatchColumn = -1;
 198 
 199     /**
 200      * A <code>RowSetWarning</code> which logs on the warnings
 201      */
 202     private RowSetWarning rowsetWarning;
 203 
 204     /**
 205      * The default SyncProvider for the RI CachedRowSetImpl
 206      */
 207     private String DEFAULT_SYNC_PROVIDER = "com.sun.rowset.providers.RIOptimisticProvider";
 208 
 209     /**
 210      * The boolean variable indicating locatorsUpdateValue
 211      */
 212     private boolean dbmslocatorsUpdateCopy;
 213 
 214     /**
 215      * The <code>ResultSet</code> object that is used to maintain the data when
 216      * a ResultSet and start position are passed as parameters to the populate function
 217      */
 218     private transient ResultSet resultSet;
 219 
 220     /**
 221      * The integer value indicating the end position in the ResultSetwhere the picking
 222      * up of rows for populating a CachedRowSet object was left off.
 223      */
 224     private int endPos;
 225 
 226     /**
 227      * The integer value indicating the end position in the ResultSetwhere the picking
 228      * up of rows for populating a CachedRowSet object was left off.
 229      */
 230     private int prevEndPos;
 231 
 232     /**
 233      * The integer value indicating the position in the ResultSet, to populate the
 234      * CachedRowSet object.
 235      */
 236     private int startPos;
 237 
 238     /**
 239      * The integer value indicating the positon from where the page prior to this
 240      * was populated.
 241      */
 242     private int startPrev;
 243 
 244     /**
 245      * The integer value indicating size of the page.
 246      */
 247     private int pageSize;
 248 
 249     /**
 250      * The integer value indicating number of rows that have been processed so far.
 251      * Used for checking whether maxRows has been reached or not.
 252      */
 253     private int maxRowsreached;
 254     /**
 255      * The boolean value when true signifies that pages are still to follow and a
 256      * false value indicates that this is the last page.
 257      */
 258     private boolean pagenotend = true;
 259 
 260     /**
 261      * The boolean value indicating whether this is the first page or not.
 262      */
 263     private boolean onFirstPage;
 264 
 265     /**
 266      * The boolean value indicating whether this is the last page or not.
 267      */
 268     private boolean onLastPage;
 269 
 270     /**
 271      * The integer value indicating how many times the populate function has been called.
 272      */
 273     private int populatecallcount;
 274 
 275     /**
 276      * The integer value indicating the total number of rows to be processed in the
 277      * ResultSet object passed to the populate function.
 278      */
 279     private int totalRows;
 280 
 281     /**
 282      * The boolean value indicating how the CahedRowSet object has been populated for
 283      * paging purpose. True indicates that connection parameter is passed.
 284      */
 285     private boolean callWithCon;
 286 
 287     /**
 288      * CachedRowSet reader object to read the data from the ResultSet when a connection
 289      * parameter is passed to populate the CachedRowSet object for paging.
 290      */
 291     private CachedRowSetReader crsReader;
 292 
 293     /**
 294      * The Vector holding the Match Columns
 295      */
 296     private Vector<Integer> iMatchColumns;
 297 
 298     /**
 299      * The Vector that will hold the Match Column names.
 300      */
 301     private Vector<String> strMatchColumns;
 302 
 303     /**
 304      * Trigger that indicates whether the active SyncProvider is exposes the
 305      * additional TransactionalWriter method
 306      */
 307     private boolean tXWriter = false;
 308 
 309     /**
 310      * The field object for a transactional RowSet writer
 311      */
 312     private TransactionalWriter tWriter = null;
 313 
 314     protected transient JdbcRowSetResourceBundle resBundle;
 315 
 316     private boolean updateOnInsert;
 317 
 318 
 319 
 320     /**
 321      * Constructs a new default <code>CachedRowSetImpl</code> object with
 322      * the capacity to hold 100 rows. This new object has no metadata
 323      * and has the following default values:
 324      * <pre>
 325      *     onInsertRow = false
 326      *     insertRow = null
 327      *     cursorPos = 0
 328      *     numRows = 0
 329      *     showDeleted = false
 330      *     queryTimeout = 0
 331      *     maxRows = 0
 332      *     maxFieldSize = 0
 333      *     rowSetType = ResultSet.TYPE_SCROLL_INSENSITIVE
 334      *     concurrency = ResultSet.CONCUR_UPDATABLE
 335      *     readOnly = false
 336      *     isolation = Connection.TRANSACTION_READ_COMMITTED
 337      *     escapeProcessing = true
 338      *     onInsertRow = false
 339      *     insertRow = null
 340      *     cursorPos = 0
 341      *     absolutePos = 0
 342      *     numRows = 0
 343      * </pre>
 344      * A <code>CachedRowSetImpl</code> object is configured to use the default
 345      * <code>RIOptimisticProvider</code> implementation to provide connectivity
 346      * and synchronization capabilities to the set data source.
 347      * <P>
 348      * @throws SQLException if an error occurs
 349      */
 350     public CachedRowSetImpl() throws SQLException {
 351 
 352         try {
 353            resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
 354         } catch(IOException ioe) {
 355             throw new RuntimeException(ioe);
 356         }
 357 
 358         // set the Reader, this maybe overridden latter
 359         provider =
 360         (SyncProvider)SyncFactory.getInstance(DEFAULT_SYNC_PROVIDER);
 361 
 362         if (!(provider instanceof RIOptimisticProvider)) {
 363             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidp").toString());
 364         }
 365 
 366         rowSetReader = (CachedRowSetReader)provider.getRowSetReader();
 367         rowSetWriter = (CachedRowSetWriter)provider.getRowSetWriter();
 368 
 369         // allocate the parameters collection
 370         initParams();
 371 
 372         initContainer();
 373 
 374         // set up some default values
 375         initProperties();
 376 
 377         // insert row setup
 378         onInsertRow = false;
 379         insertRow = null;
 380 
 381         // set the warninings
 382         sqlwarn = new SQLWarning();
 383         rowsetWarning = new RowSetWarning();
 384 
 385     }
 386 
 387     /**
 388      * Provides a <code>CachedRowSetImpl</code> instance with the same default properties as
 389      * as the zero parameter constructor.
 390      * <pre>
 391      *     onInsertRow = false
 392      *     insertRow = null
 393      *     cursorPos = 0
 394      *     numRows = 0
 395      *     showDeleted = false
 396      *     queryTimeout = 0
 397      *     maxRows = 0
 398      *     maxFieldSize = 0
 399      *     rowSetType = ResultSet.TYPE_SCROLL_INSENSITIVE
 400      *     concurrency = ResultSet.CONCUR_UPDATABLE
 401      *     readOnly = false
 402      *     isolation = Connection.TRANSACTION_READ_COMMITTED
 403      *     escapeProcessing = true
 404      *     onInsertRow = false
 405      *     insertRow = null
 406      *     cursorPos = 0
 407      *     absolutePos = 0
 408      *     numRows = 0
 409      * </pre>
 410      *
 411      * However, applications will have the means to specify at runtime the
 412      * desired <code>SyncProvider</code> object.
 413      * <p>
 414      * For example, creating a <code>CachedRowSetImpl</code> object as follows ensures
 415      * that a it is established with the <code>com.foo.provider.Impl</code> synchronization
 416      * implementation providing the synchronization mechanism for this disconnected
 417      * <code>RowSet</code> object.
 418      * <pre>
 419      *     Hashtable env = new Hashtable();
 420      *     env.put(javax.sql.rowset.spi.SyncFactory.ROWSET_PROVIDER_NAME,
 421      *         "com.foo.provider.Impl");
 422      *     CachedRowSetImpl crs = new CachedRowSet(env);
 423      * </pre>
 424      * <p>
 425      * Calling this constructor with a <code>null</code> parameter will
 426      * cause the <code>SyncFactory</code> to provide the reference
 427      * optimistic provider <code>com.sun.rowset.providers.RIOptimisticProvider</code>.
 428      * <p>
 429      * In addition, the following properties can be associated with the
 430      * provider to assist in determining the choice of the synchronizaton
 431      * provider such as:
 432      * <ul>
 433      * <li><code>ROWSET_SYNC_PROVIDER</code> - the property specifying the the
 434      * <code>SyncProvider</code> class name to be instantiated by the
 435      * <code>SyncFacttory</code>
 436      * <li><code>ROWSET_SYNC_VENDOR</code> - the property specifying the software
 437      * vendor associated with a <code>SyncProvider</code> implementation.
 438      * <li><code>ROWSET_SYNC_PROVIDER_VER</code> - the property specifying the
 439      * version of the <code>SyncProvider</code> implementation provided by the
 440      * software vendor.
 441      * </ul>
 442      * More specific detailes are available in the <code>SyncFactory</code>
 443      * and <code>SyncProvider</code> specificiations later in this document.
 444      * <p>
 445      * @param env a <code>Hashtable</code> object with a list of desired
 446      *        synchronization providers
 447      * @throws SQLException if the requested provider cannot be found by the
 448      * synchonization factory
 449      * @see SyncProvider
 450      */
 451 
 452     public CachedRowSetImpl(Hashtable env) throws SQLException {
 453 
 454 
 455         try {
 456            resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
 457         } catch(IOException ioe) {
 458             throw new RuntimeException(ioe);
 459         }
 460 
 461         if (env == null) {
 462             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.nullhash").toString());
 463         }
 464 
 465         String providerName = (String)env.get(
 466         javax.sql.rowset.spi.SyncFactory.ROWSET_SYNC_PROVIDER);
 467 
 468         // set the Reader, this maybe overridden latter
 469         provider =
 470         (SyncProvider)SyncFactory.getInstance(providerName);
 471 
 472         rowSetReader = provider.getRowSetReader();
 473         rowSetWriter = provider.getRowSetWriter();
 474 
 475         initParams(); // allocate the parameters collection
 476         initContainer();
 477         initProperties(); // set up some default values
 478     }
 479 
 480     /**
 481      * Sets the <code>rvh</code> field to a new <code>Vector</code>
 482      * object with a capacity of 100 and sets the
 483      * <code>cursorPos</code> and <code>numRows</code> fields to zero.
 484      */
 485     private void initContainer() {
 486 
 487         rvh = new Vector<Object>(100);
 488         cursorPos = 0;
 489         absolutePos = 0;
 490         numRows = 0;
 491         numDeleted = 0;
 492     }
 493 
 494     /**
 495      * Sets the properties for this <code>CachedRowSetImpl</code> object to
 496      * their default values. This method is called internally by the
 497      * default constructor.
 498      */
 499 
 500     private void initProperties() throws SQLException {
 501 
 502         if(resBundle == null) {
 503             try {
 504                resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
 505             } catch(IOException ioe) {
 506                 throw new RuntimeException(ioe);
 507             }
 508         }
 509         setShowDeleted(false);
 510         setQueryTimeout(0);
 511         setMaxRows(0);
 512         setMaxFieldSize(0);
 513         setType(ResultSet.TYPE_SCROLL_INSENSITIVE);
 514         setConcurrency(ResultSet.CONCUR_UPDATABLE);
 515         if((rvh.size() > 0) && (isReadOnly() == false))
 516             setReadOnly(false);
 517         else
 518             setReadOnly(true);
 519         setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
 520         setEscapeProcessing(true);
 521         //setTypeMap(null);
 522         checkTransactionalWriter();
 523 
 524         //Instantiating the vector for MatchColumns
 525 
 526         iMatchColumns = new Vector<Integer>(10);
 527         for(int i = 0; i < 10 ; i++) {
 528            iMatchColumns.add(i,Integer.valueOf(-1));
 529         }
 530 
 531         strMatchColumns = new Vector<String>(10);
 532         for(int j = 0; j < 10; j++) {
 533            strMatchColumns.add(j,null);
 534         }
 535     }
 536 
 537     /**
 538      * Determine whether the SyncProvider's writer implements the
 539      * <code>TransactionalWriter<code> interface
 540      */
 541     private void checkTransactionalWriter() {
 542         if (rowSetWriter != null) {
 543             Class c = rowSetWriter.getClass();
 544             if (c != null) {
 545                 Class[] theInterfaces = c.getInterfaces();
 546                 for (int i = 0; i < theInterfaces.length; i++) {
 547                     if ((theInterfaces[i].getName()).indexOf("TransactionalWriter") > 0) {
 548                         tXWriter = true;
 549                         establishTransactionalWriter();
 550                     }
 551                 }
 552             }
 553         }
 554     }
 555 
 556     /**
 557      * Sets an private field to all transaction bounddaries to be set
 558      */
 559     private void establishTransactionalWriter() {
 560         tWriter = (TransactionalWriter)provider.getRowSetWriter();
 561     }
 562 
 563     //-----------------------------------------------------------------------
 564     // Properties
 565     //-----------------------------------------------------------------------
 566 
 567     /**
 568      * Sets this <code>CachedRowSetImpl</code> object's command property
 569      * to the given <code>String</code> object and clears the parameters,
 570      * if any, that were set for the previous command.
 571      * <P>
 572      * The command property may not be needed
 573      * if the rowset is produced by a data source, such as a spreadsheet,
 574      * that does not support commands. Thus, this property is optional
 575      * and may be <code>null</code>.
 576      *
 577      * @param cmd a <code>String</code> object containing an SQL query
 578      *            that will be set as the command; may be <code>null</code>
 579      * @throws SQLException if an error occurs
 580      */
 581     public void setCommand(String cmd) throws SQLException {
 582 
 583         super.setCommand(cmd);
 584 
 585         if(!buildTableName(cmd).equals("")) {
 586             this.setTableName(buildTableName(cmd));
 587         }
 588     }
 589 
 590 
 591     //---------------------------------------------------------------------
 592     // Reading and writing data
 593     //---------------------------------------------------------------------
 594 
 595     /**
 596      * Populates this <code>CachedRowSetImpl</code> object with data from
 597      * the given <code>ResultSet</code> object.  This
 598      * method is an alternative to the method <code>execute</code>
 599      * for filling the rowset with data.  The method <code>populate</code>
 600      * does not require that the properties needed by the method
 601      * <code>execute</code>, such as the <code>command</code> property,
 602      * be set. This is true because the method <code>populate</code>
 603      * is given the <code>ResultSet</code> object from
 604      * which to get data and thus does not need to use the properties
 605      * required for setting up a connection and executing this
 606      * <code>CachedRowSetImpl</code> object's command.
 607      * <P>
 608      * After populating this rowset with data, the method
 609      * <code>populate</code> sets the rowset's metadata and
 610      * then sends a <code>RowSetChangedEvent</code> object
 611      * to all registered listeners prior to returning.
 612      *
 613      * @param data the <code>ResultSet</code> object containing the data
 614      *             to be read into this <code>CachedRowSetImpl</code> object
 615      * @throws SQLException if an error occurs; or the max row setting is
 616      *          violated while populating the RowSet
 617      * @see #execute
 618      */
 619 
 620      public void populate(ResultSet data) throws SQLException {
 621         int rowsFetched;
 622         Row currentRow;
 623         int numCols;
 624         int i;
 625         Map<String, Class<?>> map = getTypeMap();
 626         Object obj;
 627         int mRows;
 628 
 629         if (data == null) {
 630             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.populate").toString());
 631         }
 632         this.resultSet = data;
 633 
 634         // get the meta data for this ResultSet
 635         RSMD = data.getMetaData();
 636 
 637         // set up the metadata
 638         RowSetMD = new RowSetMetaDataImpl();
 639         initMetaData(RowSetMD, RSMD);
 640 
 641         // release the meta-data so that aren't tempted to use it.
 642         RSMD = null;
 643         numCols = RowSetMD.getColumnCount();
 644         mRows = this.getMaxRows();
 645         rowsFetched = 0;
 646         currentRow = null;
 647 
 648         while ( data.next()) {
 649 
 650             currentRow = new Row(numCols);
 651 
 652             if ( rowsFetched > mRows && mRows > 0) {
 653                 rowsetWarning.setNextWarning(new RowSetWarning("Populating rows "
 654                 + "setting has exceeded max row setting"));
 655             }
 656             for ( i = 1; i <= numCols; i++) {
 657                 /*
 658                  * check if the user has set a map. If no map
 659                  * is set then use plain getObject. This lets
 660                  * us work with drivers that do not support
 661                  * getObject with a map in fairly sensible way
 662                  */
 663                 if (map == null) {
 664                     obj = data.getObject(i);
 665                 } else {
 666                     obj = data.getObject(i, map);
 667                 }
 668                 /*
 669                  * the following block checks for the various
 670                  * types that we have to serialize in order to
 671                  * store - right now only structs have been tested
 672                  */
 673                 if (obj instanceof Struct) {
 674                     obj = new SerialStruct((Struct)obj, map);
 675                 } else if (obj instanceof SQLData) {
 676                     obj = new SerialStruct((SQLData)obj, map);
 677                 } else if (obj instanceof Blob) {
 678                     obj = new SerialBlob((Blob)obj);
 679                 } else if (obj instanceof Clob) {
 680                     obj = new SerialClob((Clob)obj);
 681                 } else if (obj instanceof java.sql.Array) {
 682                     if(map != null)
 683                         obj = new SerialArray((java.sql.Array)obj, map);
 684                     else
 685                         obj = new SerialArray((java.sql.Array)obj);
 686                 }
 687 
 688                 ((Row)currentRow).initColumnObject(i, obj);
 689             }
 690             rowsFetched++;
 691             rvh.add(currentRow);
 692         }
 693 
 694         numRows = rowsFetched ;
 695         // Also rowsFetched should be equal to rvh.size()
 696 
 697         // notify any listeners that the rowset has changed
 698         notifyRowSetChanged();
 699 
 700 
 701     }
 702 
 703     /**
 704      * Initializes the given <code>RowSetMetaData</code> object with the values
 705      * in the given <code>ResultSetMetaData</code> object.
 706      *
 707      * @param md the <code>RowSetMetaData</code> object for this
 708      *           <code>CachedRowSetImpl</code> object, which will be set with
 709      *           values from rsmd
 710      * @param rsmd the <code>ResultSetMetaData</code> object from which new
 711      *             values for md will be read
 712      * @throws SQLException if an error occurs
 713      */
 714     private void initMetaData(RowSetMetaDataImpl md, ResultSetMetaData rsmd) throws SQLException {
 715         int numCols = rsmd.getColumnCount();
 716 
 717         md.setColumnCount(numCols);
 718         for (int col=1; col <= numCols; col++) {
 719             md.setAutoIncrement(col, rsmd.isAutoIncrement(col));
 720             if(rsmd.isAutoIncrement(col))
 721                 updateOnInsert = true;
 722             md.setCaseSensitive(col, rsmd.isCaseSensitive(col));
 723             md.setCurrency(col, rsmd.isCurrency(col));
 724             md.setNullable(col, rsmd.isNullable(col));
 725             md.setSigned(col, rsmd.isSigned(col));
 726             md.setSearchable(col, rsmd.isSearchable(col));
 727              /*
 728              * The PostgreSQL drivers sometimes return negative columnDisplaySize,
 729              * which causes an exception to be thrown.  Check for it.
 730              */
 731             int size = rsmd.getColumnDisplaySize(col);
 732             if (size < 0) {
 733                 size = 0;
 734             }
 735             md.setColumnDisplaySize(col, size);
 736             md.setColumnLabel(col, rsmd.getColumnLabel(col));
 737             md.setColumnName(col, rsmd.getColumnName(col));
 738             md.setSchemaName(col, rsmd.getSchemaName(col));
 739             /*
 740              * Drivers return some strange values for precision, for non-numeric data, including reports of
 741              * non-integer values; maybe we should check type, & set to 0 for non-numeric types.
 742              */
 743             int precision = rsmd.getPrecision(col);
 744             if (precision < 0) {
 745                 precision = 0;
 746             }
 747             md.setPrecision(col, precision);
 748 
 749             /*
 750              * It seems, from a bug report, that a driver can sometimes return a negative
 751              * value for scale.  javax.sql.rowset.RowSetMetaDataImpl will throw an exception
 752              * if we attempt to set a negative value.  As such, we'll check for this case.
 753              */
 754             int scale = rsmd.getScale(col);
 755             if (scale < 0) {
 756                 scale = 0;
 757             }
 758             md.setScale(col, scale);
 759             md.setTableName(col, rsmd.getTableName(col));
 760             md.setCatalogName(col, rsmd.getCatalogName(col));
 761             md.setColumnType(col, rsmd.getColumnType(col));
 762             md.setColumnTypeName(col, rsmd.getColumnTypeName(col));
 763         }
 764 
 765         if( conn != null){
 766            // JDBC 4.0 mandates as does the Java EE spec that all DataBaseMetaData methods
 767            // must be implemented, therefore, the previous fix for 5055528 is being backed out
 768             dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy();
 769         }
 770     }
 771 
 772     /**
 773      * Populates this <code>CachedRowSetImpl</code> object with data,
 774      * using the given connection to produce the result set from
 775      * which data will be read.  A second form of this method,
 776      * which takes no arguments, uses the values from this rowset's
 777      * user, password, and either url or data source properties to
 778      * create a new database connection. The form of <code>execute</code>
 779      * that is given a connection ignores these properties.
 780      *
 781      * @param conn A standard JDBC <code>Connection</code> object that this
 782      * <code>CachedRowSet</code> object can pass to a synchronization provider
 783      * to establish a connection to the data source
 784      * @throws SQLException if an invalid <code>Connection</code> is supplied
 785      *           or an error occurs in establishing the connection to the
 786      *           data source
 787      * @see #populate
 788      * @see java.sql.Connection
 789      */
 790     public void execute(Connection conn) throws SQLException {
 791         // store the connection so the reader can find it.
 792         setConnection(conn);
 793 
 794         if(getPageSize() != 0){
 795             crsReader = (CachedRowSetReader)provider.getRowSetReader();
 796             crsReader.setStartPosition(1);
 797             callWithCon = true;
 798             crsReader.readData((RowSetInternal)this);
 799         }
 800 
 801         // Now call the current reader's readData method
 802         else {
 803            rowSetReader.readData((RowSetInternal)this);
 804         }
 805         RowSetMD = (RowSetMetaDataImpl)this.getMetaData();
 806 
 807         if(conn != null){
 808             // JDBC 4.0 mandates as does the Java EE spec that all DataBaseMetaData methods
 809             // must be implemented, therefore, the previous fix for 5055528 is being backed out
 810             dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy();
 811         }
 812 
 813     }
 814 
 815     /**
 816      * Sets this <code>CachedRowSetImpl</code> object's connection property
 817      * to the given <code>Connection</code> object.  This method is called
 818      * internally by the version of the method <code>execute</code> that takes a
 819      * <code>Connection</code> object as an argument. The reader for this
 820      * <code>CachedRowSetImpl</code> object can retrieve the connection stored
 821      * in the rowset's connection property by calling its
 822      * <code>getConnection</code> method.
 823      *
 824      * @param connection the <code>Connection</code> object that was passed in
 825      *                   to the method <code>execute</code> and is to be stored
 826      *                   in this <code>CachedRowSetImpl</code> object's connection
 827      *                   property
 828      */
 829     private void setConnection (Connection connection) {
 830         conn = connection;
 831     }
 832 
 833 
 834     /**
 835      * Propagates all row update, insert, and delete changes to the
 836      * underlying data source backing this <code>CachedRowSetImpl</code>
 837      * object.
 838      * <P>
 839      * <b>Note</b>In the reference implementation an optimistic concurrency implementation
 840      * is provided as a sample implementation of a the <code>SyncProvider</code>
 841      * abstract class.
 842      * <P>
 843      * This method fails if any of the updates cannot be propagated back
 844      * to the data source.  When it fails, the caller can assume that
 845      * none of the updates are reflected in the data source.
 846      * When an exception is thrown, the current row
 847      * is set to the first "updated" row that resulted in an exception
 848      * unless the row that caused the exception is a "deleted" row.
 849      * In that case, when deleted rows are not shown, which is usually true,
 850      * the current row is not affected.
 851      * <P>
 852      * If no <code>SyncProvider</code> is configured, the reference implementation
 853      * leverages the <code>RIOptimisticProvider</code> available which provides the
 854      * default and reference synchronization capabilities for disconnected
 855      * <code>RowSets</code>.
 856      *
 857      * @throws SQLException if the cursor is on the insert row or the underlying
 858      *          reference synchronization provider fails to commit the updates
 859      *          to the datasource
 860      * @throws SyncProviderException if an internal error occurs within the
 861      *          <code>SyncProvider</code> instance during either during the
 862      *          process or at any time when the <code>SyncProvider</code>
 863      *          instance touches the data source.
 864      * @see #acceptChanges(java.sql.Connection)
 865      * @see javax.sql.RowSetWriter
 866      * @see javax.sql.rowset.spi.SyncProvider
 867      */
 868     public void acceptChanges() throws SyncProviderException {
 869         if (onInsertRow == true) {
 870             throw new SyncProviderException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
 871         }
 872 
 873         int saveCursorPos = cursorPos;
 874         boolean success = false;
 875         boolean conflict = false;
 876 
 877         try {
 878             if (rowSetWriter != null) {
 879                 saveCursorPos = cursorPos;
 880                 conflict = rowSetWriter.writeData((RowSetInternal)this);
 881                 cursorPos = saveCursorPos;
 882             }
 883 
 884             if ((tXWriter) && this.COMMIT_ON_ACCEPT_CHANGES) {
 885                 // do commit/rollback's here
 886                 if (!conflict) {
 887                     tWriter = (TransactionalWriter)rowSetWriter;
 888                     tWriter.rollback();
 889                     success = false;
 890                 } else {
 891                     tWriter = (TransactionalWriter)rowSetWriter;
 892                     if (tWriter instanceof CachedRowSetWriter) {
 893                         ((CachedRowSetWriter)tWriter).commit(this, updateOnInsert);
 894                     } else {
 895                         tWriter.commit();
 896                     }
 897 
 898                     success = true;
 899                 }
 900             }
 901 
 902             if (success == true) {
 903                 setOriginal();
 904             } else if (!(success) && !(this.COMMIT_ON_ACCEPT_CHANGES)) {
 905                 throw new SyncProviderException(resBundle.handleGetObject("cachedrowsetimpl.accfailed").toString());
 906             }
 907 
 908         } catch (SyncProviderException spe) {
 909                throw spe;
 910         } catch (SQLException e) {
 911             e.printStackTrace();
 912             throw new SyncProviderException(e.getMessage());
 913         } catch (SecurityException e) {
 914             throw new SyncProviderException(e.getMessage());
 915         }
 916     }
 917 
 918     /**
 919      * Propagates all row update, insert, and delete changes to the
 920      * data source backing this <code>CachedRowSetImpl</code> object
 921      * using the given <code>Connection</code> object.
 922      * <P>
 923      * The reference implementation <code>RIOptimisticProvider</code>
 924      * modifies its synchronization to a write back function given
 925      * the updated connection
 926      * The reference implementation modifies its synchronization behaviour
 927      * via the <code>SyncProvider</code> to ensure the synchronization
 928      * occurs according to the updated JDBC <code>Connection</code>
 929      * properties.
 930      *
 931      * @param con a standard JDBC <code>Connection</code> object
 932      * @throws SQLException if the cursor is on the insert row or the underlying
 933      *                   synchronization provider fails to commit the updates
 934      *                   back to the data source
 935      * @see #acceptChanges
 936      * @see javax.sql.RowSetWriter
 937      * @see javax.sql.rowset.spi.SyncFactory
 938      * @see javax.sql.rowset.spi.SyncProvider
 939      */
 940     public void acceptChanges(Connection con) throws SyncProviderException{
 941 
 942       setConnection(con);
 943       acceptChanges();
 944 
 945     }
 946 
 947     /**
 948      * Restores this <code>CachedRowSetImpl</code> object to its original state,
 949      * that is, its state before the last set of changes.
 950      * <P>
 951      * Before returning, this method moves the cursor before the first row
 952      * and sends a <code>rowSetChanged</code> event to all registered
 953      * listeners.
 954      * @throws SQLException if an error is occurs rolling back the RowSet
 955      *           state to the definied original value.
 956      * @see javax.sql.RowSetListener#rowSetChanged
 957      */
 958     public void restoreOriginal() throws SQLException {
 959         Row currentRow;
 960         for (Iterator i = rvh.iterator(); i.hasNext();) {
 961             currentRow = (Row)i.next();
 962             if (currentRow.getInserted() == true) {
 963                 i.remove();
 964                 --numRows;
 965             } else {
 966                 if (currentRow.getDeleted() == true) {
 967                     currentRow.clearDeleted();
 968                 }
 969                 if (currentRow.getUpdated() == true) {
 970                     currentRow.clearUpdated();
 971                 }
 972             }
 973         }
 974         // move to before the first
 975         cursorPos = 0;
 976 
 977         // notify any listeners
 978         notifyRowSetChanged();
 979     }
 980 
 981     /**
 982      * Releases the current contents of this <code>CachedRowSetImpl</code>
 983      * object and sends a <code>rowSetChanged</code> event object to all
 984      * registered listeners.
 985      *
 986      * @throws SQLException if an error occurs flushing the contents of
 987      *           RowSet.
 988      * @see javax.sql.RowSetListener#rowSetChanged
 989      */
 990     public void release() throws SQLException {
 991         initContainer();
 992         notifyRowSetChanged();
 993     }
 994 
 995     /**
 996      * Cancels deletion of the current row and notifies listeners that
 997      * a row has changed.
 998      * <P>
 999      * Note:  This method can be ignored if deleted rows are not being shown,
1000      * which is the normal case.
1001      *
1002      * @throws SQLException if the cursor is not on a valid row
1003      */
1004     public void undoDelete() throws SQLException {
1005         if (getShowDeleted() == false) {
1006             return;
1007         }
1008         // make sure we are on a row
1009         checkCursor();
1010 
1011         // don't want this to happen...
1012         if (onInsertRow == true) {
1013             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1014         }
1015 
1016         Row currentRow = (Row)getCurrentRow();
1017         if (currentRow.getDeleted() == true) {
1018             currentRow.clearDeleted();
1019             --numDeleted;
1020             notifyRowChanged();
1021         }
1022     }
1023 
1024     /**
1025      * Immediately removes the current row from this
1026      * <code>CachedRowSetImpl</code> object if the row has been inserted, and
1027      * also notifies listeners the a row has changed.  An exception is thrown
1028      * if the row is not a row that has been inserted or the cursor is before
1029      * the first row, after the last row, or on the insert row.
1030      * <P>
1031      * This operation cannot be undone.
1032      *
1033      * @throws SQLException if an error occurs,
1034      *                         the cursor is not on a valid row,
1035      *                         or the row has not been inserted
1036      */
1037     public void undoInsert() throws SQLException {
1038         // make sure we are on a row
1039         checkCursor();
1040 
1041         // don't want this to happen...
1042         if (onInsertRow == true) {
1043             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1044         }
1045 
1046         Row currentRow = (Row)getCurrentRow();
1047         if (currentRow.getInserted() == true) {
1048             rvh.remove(cursorPos-1);
1049             --numRows;
1050             notifyRowChanged();
1051         } else {
1052             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.illegalop").toString());
1053         }
1054     }
1055 
1056     /**
1057      * Immediately reverses the last update operation if the
1058      * row has been modified. This method can be
1059      * called to reverse updates on a all columns until all updates in a row have
1060      * been rolled back to their originating state since the last synchronization
1061      * (<code>acceptChanges</code>) or population. This method may also be called
1062      * while performing updates to the insert row.
1063      * <P>
1064      * <code>undoUpdate</code may be called at any time during the life-time of a
1065      * rowset, however after a synchronization has occurs this method has no
1066      * affect until further modification to the RowSet data occurs.
1067      *
1068      * @throws SQLException if cursor is before the first row, after the last
1069      *     row in rowset.
1070      * @see #undoDelete
1071      * @see #undoInsert
1072      * @see java.sql.ResultSet#cancelRowUpdates
1073      */
1074     public void undoUpdate() throws SQLException {
1075         // if on insert row, cancel the insert row
1076         // make the insert row flag,
1077         // cursorPos back to the current row
1078         moveToCurrentRow();
1079 
1080         // else if not on insert row
1081         // call undoUpdate or undoInsert
1082         undoDelete();
1083 
1084         undoInsert();
1085 
1086     }
1087 
1088     //--------------------------------------------------------------------
1089     // Views
1090     //--------------------------------------------------------------------
1091 
1092     /**
1093      * Returns a new <code>RowSet</code> object backed by the same data as
1094      * that of this <code>CachedRowSetImpl</code> object and sharing a set of cursors
1095      * with it. This allows cursors to interate over a shared set of rows, providing
1096      * multiple views of the underlying data.
1097      *
1098      * @return a <code>RowSet</code> object that is a copy of this <code>CachedRowSetImpl</code>
1099      * object and shares a set of cursors with it
1100      * @throws SQLException if an error occurs or cloning is
1101      *                         not supported
1102      * @see javax.sql.RowSetEvent
1103      * @see javax.sql.RowSetListener
1104      */
1105     public RowSet createShared() throws SQLException {
1106         RowSet clone;
1107         try {
1108             clone = (RowSet)clone();
1109         } catch (CloneNotSupportedException ex) {
1110             throw new SQLException(ex.getMessage());
1111         }
1112         return clone;
1113     }
1114 
1115     /**
1116      * Returns a new <code>RowSet</code> object containing by the same data
1117      * as this <code>CachedRowSetImpl</code> object.  This method
1118      * differs from the method <code>createCopy</code> in that it throws a
1119      * <code>CloneNotSupportedException</code> object instead of an
1120      * <code>SQLException</code> object, as the method <code>createShared</code>
1121      * does.  This <code>clone</code>
1122      * method is called internally by the method <code>createShared</code>,
1123      * which catches the <code>CloneNotSupportedException</code> object
1124      * and in turn throws a new <code>SQLException</code> object.
1125      *
1126      * @return a copy of this <code>CachedRowSetImpl</code> object
1127      * @throws CloneNotSupportedException if an error occurs when
1128      * attempting to clone this <code>CachedRowSetImpl</code> object
1129      * @see #createShared
1130      */
1131     protected Object clone() throws CloneNotSupportedException  {
1132         return (super.clone());
1133     }
1134 
1135     /**
1136      * Creates a <code>RowSet</code> object that is a deep copy of
1137      * this <code>CachedRowSetImpl</code> object's data, including
1138      * constraints.  Updates made
1139      * on a copy are not visible to the original rowset;
1140      * a copy of a rowset is completely independent from the original.
1141      * <P>
1142      * Making a copy saves the cost of creating an identical rowset
1143      * from first principles, which can be quite expensive.
1144      * For example, it can eliminate the need to query a
1145      * remote database server.
1146      * @return a new <code>CachedRowSet</code> object that is a deep copy
1147      *           of this <code>CachedRowSet</code> object and is
1148      *           completely independent from this <code>CachedRowSetImpl</code>
1149      *           object.
1150      * @throws SQLException if an error occurs in generating the copy of this
1151      *           of the <code>CachedRowSetImpl</code>
1152      * @see #createShared
1153      * @see javax.sql.RowSetEvent
1154      * @see javax.sql.RowSetListener
1155      */
1156     public CachedRowSet createCopy() throws SQLException {
1157         ObjectOutputStream out;
1158         ByteArrayOutputStream bOut = new ByteArrayOutputStream();
1159         try {
1160             out = new ObjectOutputStream(bOut);
1161             out.writeObject(this);
1162         } catch (IOException ex) {
1163             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1164         }
1165 
1166         ObjectInputStream in;
1167 
1168         try {
1169             ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
1170             in = new ObjectInputStream(bIn);
1171         } catch (StreamCorruptedException ex) {
1172             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1173         } catch (IOException ex) {
1174             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1175         }
1176 
1177         try {
1178             //return ((CachedRowSet)(in.readObject()));
1179             CachedRowSetImpl crsTemp = (CachedRowSetImpl)in.readObject();
1180             crsTemp.resBundle = this.resBundle;
1181             return ((CachedRowSet)crsTemp);
1182 
1183         } catch (ClassNotFoundException ex) {
1184             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1185         } catch (OptionalDataException ex) {
1186             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1187         } catch (IOException ex) {
1188             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1189         }
1190     }
1191 
1192     /**
1193      * Creates a <code>RowSet</code> object that is a copy of
1194      * this <code>CachedRowSetImpl</code> object's table structure
1195      * and the constraints only.
1196      * There will be no data in the object being returned.
1197      * Updates made on a copy are not visible to the original rowset.
1198      * <P>
1199      * This helps in getting the underlying XML schema which can
1200      * be used as the basis for populating a <code>WebRowSet</code>.
1201      *
1202      * @return a new <code>CachedRowSet</code> object that is a copy
1203      * of this <code>CachedRowSetImpl</code> object's schema and
1204      * retains all the constraints on the original rowset but contains
1205      * no data
1206      * @throws SQLException if an error occurs in generating the copy
1207      * of the <code>CachedRowSet</code> object
1208      * @see #createShared
1209      * @see #createCopy
1210      * @see #createCopyNoConstraints
1211      * @see javax.sql.RowSetEvent
1212      * @see javax.sql.RowSetListener
1213      */
1214     public CachedRowSet createCopySchema() throws SQLException {
1215         // Copy everything except data i.e all constraints
1216 
1217         // Store the number of rows of "this"
1218         // and make numRows equals zero.
1219         // and make data also zero.
1220         int nRows = numRows;
1221         numRows = 0;
1222 
1223         CachedRowSet crs = this.createCopy();
1224 
1225         // reset this object back to number of rows.
1226         numRows = nRows;
1227 
1228         return crs;
1229     }
1230 
1231     /**
1232      * Creates a <code>CachedRowSet</code> object that is a copy of
1233      * this <code>CachedRowSetImpl</code> object's data only.
1234      * All constraints set in this object will not be there
1235      * in the returning object.  Updates made
1236      * on a copy are not visible to the original rowset.
1237      *
1238      * @return a new <code>CachedRowSet</code> object that is a deep copy
1239      * of this <code>CachedRowSetImpl</code> object and is
1240      * completely independent from this <code>CachedRowSetImpl</code> object
1241      * @throws SQLException if an error occurs in generating the copy of the
1242      * of the <code>CachedRowSet</code>
1243      * @see #createShared
1244      * @see #createCopy
1245      * @see #createCopySchema
1246      * @see javax.sql.RowSetEvent
1247      * @see javax.sql.RowSetListener
1248      */
1249     public CachedRowSet createCopyNoConstraints() throws SQLException {
1250         // Copy the whole data ONLY without any constraints.
1251         CachedRowSetImpl crs;
1252         crs = (CachedRowSetImpl)this.createCopy();
1253 
1254         crs.initProperties();
1255         try {
1256             crs.unsetMatchColumn(crs.getMatchColumnIndexes());
1257         } catch(SQLException sqle) {
1258             //do nothing, if the setMatchColumn is not set.
1259         }
1260 
1261         try {
1262             crs.unsetMatchColumn(crs.getMatchColumnNames());
1263         } catch(SQLException sqle) {
1264             //do nothing, if the setMatchColumn is not set.
1265         }
1266 
1267         return crs;
1268     }
1269 
1270     /**
1271      * Converts this <code>CachedRowSetImpl</code> object to a collection
1272      * of tables. The sample implementation utilitizes the <code>TreeMap</code>
1273      * collection type.
1274      * This class guarantees that the map will be in ascending key order,
1275      * sorted according to the natural order for the key's class.
1276      *
1277      * @return a <code>Collection</code> object consisting of tables,
1278      *         each of which is a copy of a row in this
1279      *         <code>CachedRowSetImpl</code> object
1280      * @throws SQLException if an error occurs in generating the collection
1281      * @see #toCollection(int)
1282      * @see #toCollection(String)
1283      * @see java.util.TreeMap
1284      */
1285     public Collection<?> toCollection() throws SQLException {
1286 
1287         TreeMap<Integer, Object> tMap = new TreeMap<>();
1288 
1289         for (int i = 0; i<numRows; i++) {
1290             tMap.put(Integer.valueOf(i), rvh.get(i));
1291         }
1292 
1293         return (tMap.values());
1294     }
1295 
1296     /**
1297      * Returns the specified column of this <code>CachedRowSetImpl</code> object
1298      * as a <code>Collection</code> object.  This method makes a copy of the
1299      * column's data and utilitizes the <code>Vector</code> to establish the
1300      * collection. The <code>Vector</code> class implements a growable array
1301      * objects allowing the individual components to be accessed using an
1302      * an integer index similar to that of an array.
1303      *
1304      * @return a <code>Collection</code> object that contains the value(s)
1305      *         stored in the specified column of this
1306      *         <code>CachedRowSetImpl</code>
1307      *         object
1308      * @throws SQLException if an error occurs generated the collection; or
1309      *          an invalid column is provided.
1310      * @see #toCollection()
1311      * @see #toCollection(String)
1312      * @see java.util.Vector
1313      */
1314     public Collection<?> toCollection(int column) throws SQLException {
1315 
1316         int nRows = numRows;
1317         Vector<Object> vec = new Vector<>(nRows);
1318 
1319         // create a copy
1320         CachedRowSetImpl crsTemp;
1321         crsTemp = (CachedRowSetImpl) this.createCopy();
1322 
1323         while(nRows!=0) {
1324             crsTemp.next();
1325             vec.add(crsTemp.getObject(column));
1326             nRows--;
1327         }
1328 
1329         return (Collection)vec;
1330     }
1331 
1332     /**
1333      * Returns the specified column of this <code>CachedRowSetImpl</code> object
1334      * as a <code>Collection</code> object.  This method makes a copy of the
1335      * column's data and utilitizes the <code>Vector</code> to establish the
1336      * collection. The <code>Vector</code> class implements a growable array
1337      * objects allowing the individual components to be accessed using an
1338      * an integer index similar to that of an array.
1339      *
1340      * @return a <code>Collection</code> object that contains the value(s)
1341      *         stored in the specified column of this
1342      *         <code>CachedRowSetImpl</code>
1343      *         object
1344      * @throws SQLException if an error occurs generated the collection; or
1345      *          an invalid column is provided.
1346      * @see #toCollection()
1347      * @see #toCollection(int)
1348      * @see java.util.Vector
1349      */
1350     public Collection<?> toCollection(String column) throws SQLException {
1351         return toCollection(getColIdxByName(column));
1352     }
1353 
1354     //--------------------------------------------------------------------
1355     // Advanced features
1356     //--------------------------------------------------------------------
1357 
1358 
1359     /**
1360      * Returns the <code>SyncProvider</code> implementation being used
1361      * with this <code>CachedRowSetImpl</code> implementation rowset.
1362      *
1363      * @return the SyncProvider used by the rowset. If not provider was
1364      *          set when the rowset was instantiated, the reference
1365      *          implementation (default) provider is returned.
1366      * @throws SQLException if error occurs while return the
1367      *          <code>SyncProvider</code> instance.
1368      */
1369     public SyncProvider getSyncProvider() throws SQLException {
1370         return provider;
1371     }
1372 
1373     /**
1374      * Sets the active <code>SyncProvider</code> and attempts to load
1375      * load the new provider using the <code>SyncFactory</code> SPI.
1376      *
1377      * @throws SQLException if an error occurs while resetting the
1378      *          <code>SyncProvider</code>.
1379      */
1380     public void setSyncProvider(String providerStr) throws SQLException {
1381         provider =
1382         (SyncProvider)SyncFactory.getInstance(providerStr);
1383 
1384         rowSetReader = provider.getRowSetReader();
1385         rowSetWriter = provider.getRowSetWriter();
1386     }
1387 
1388 
1389     //-----------------
1390     // methods inherited from RowSet
1391     //-----------------
1392 
1393 
1394 
1395 
1396 
1397 
1398     //---------------------------------------------------------------------
1399     // Reading and writing data
1400     //---------------------------------------------------------------------
1401 
1402     /**
1403      * Populates this <code>CachedRowSetImpl</code> object with data.
1404      * This form of the method uses the rowset's user, password, and url or
1405      * data source name properties to create a database
1406      * connection.  If properties that are needed
1407      * have not been set, this method will throw an exception.
1408      * <P>
1409      * Another form of this method uses an existing JDBC <code>Connection</code>
1410      * object instead of creating a new one; therefore, it ignores the
1411      * properties used for establishing a new connection.
1412      * <P>
1413      * The query specified by the command property is executed to create a
1414      * <code>ResultSet</code> object from which to retrieve data.
1415      * The current contents of the rowset are discarded, and the
1416      * rowset's metadata is also (re)set.  If there are outstanding updates,
1417      * they are also ignored.
1418      * <P>
1419      * The method <code>execute</code> closes any database connections that it
1420      * creates.
1421      *
1422      * @throws SQLException if an error occurs or the
1423      *                         necessary properties have not been set
1424      */
1425     public void execute() throws SQLException {
1426         execute(null);
1427     }
1428 
1429 
1430 
1431     //-----------------------------------
1432     // Methods inherited from ResultSet
1433     //-----------------------------------
1434 
1435     /**
1436      * Moves the cursor down one row from its current position and
1437      * returns <code>true</code> if the new cursor position is a
1438      * valid row.
1439      * The cursor for a new <code>ResultSet</code> object is initially
1440      * positioned before the first row. The first call to the method
1441      * <code>next</code> moves the cursor to the first row, making it
1442      * the current row; the second call makes the second row the
1443      * current row, and so on.
1444      *
1445      * <P>If an input stream from the previous row is open, it is
1446      * implicitly closed. The <code>ResultSet</code> object's warning
1447      * chain is cleared when a new row is read.
1448      *
1449      * @return <code>true</code> if the new current row is valid;
1450      *         <code>false</code> if there are no more rows
1451      * @throws SQLException if an error occurs or
1452      *            the cursor is not positioned in the rowset, before
1453      *            the first row, or after the last row
1454      */
1455     public boolean next() throws SQLException {
1456         /*
1457          * make sure things look sane. The cursor must be
1458          * positioned in the rowset or before first (0) or
1459          * after last (numRows + 1)
1460          */
1461         if (cursorPos < 0 || cursorPos >= numRows + 1) {
1462             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1463         }
1464         // now move and notify
1465         boolean ret = this.internalNext();
1466         notifyCursorMoved();
1467 
1468         return ret;
1469     }
1470 
1471     /**
1472      * Moves this <code>CachedRowSetImpl</code> object's cursor to the next
1473      * row and returns <code>true</code> if the cursor is still in the rowset;
1474      * returns <code>false</code> if the cursor has moved to the position after
1475      * the last row.
1476      * <P>
1477      * This method handles the cases where the cursor moves to a row that
1478      * has been deleted.
1479      * If this rowset shows deleted rows and the cursor moves to a row
1480      * that has been deleted, this method moves the cursor to the next
1481      * row until the cursor is on a row that has not been deleted.
1482      * <P>
1483      * The method <code>internalNext</code> is called by methods such as
1484      * <code>next</code>, <code>absolute</code>, and <code>relative</code>,
1485      * and, as its name implies, is only called internally.
1486      * <p>
1487      * This is a implementation only method and is not required as a standard
1488      * implementation of the <code>CachedRowSet</code> interface.
1489      *
1490      * @return <code>true</code> if the cursor is on a valid row in this
1491      *         rowset; <code>false</code> if it is after the last row
1492      * @throws SQLException if an error occurs
1493      */
1494     protected boolean internalNext() throws SQLException {
1495         boolean ret = false;
1496 
1497         do {
1498             if (cursorPos < numRows) {
1499                 ++cursorPos;
1500                 ret = true;
1501             } else if (cursorPos == numRows) {
1502                 // increment to after last
1503                 ++cursorPos;
1504                 ret = false;
1505                 break;
1506             }
1507         } while ((getShowDeleted() == false) && (rowDeleted() == true));
1508 
1509         /* each call to internalNext may increment cursorPos multiple
1510          * times however, the absolutePos only increments once per call.
1511          */
1512         if (ret == true)
1513             absolutePos++;
1514         else
1515             absolutePos = 0;
1516 
1517         return ret;
1518     }
1519 
1520     /**
1521      * Closes this <code>CachedRowSetImpl</code> objecy and releases any resources
1522      * it was using.
1523      *
1524      * @throws SQLException if an error occurs when releasing any resources in use
1525      * by this <code>CachedRowSetImpl</code> object
1526      */
1527     public void close() throws SQLException {
1528 
1529         // close all data structures holding
1530         // the disconnected rowset
1531 
1532         cursorPos = 0;
1533         absolutePos = 0;
1534         numRows = 0;
1535         numDeleted = 0;
1536 
1537         // set all insert(s), update(s) & delete(s),
1538         // if at all, to their initial values.
1539         initProperties();
1540 
1541         // clear the vector of it's present contents
1542         rvh.clear();
1543 
1544         // this will make it eligible for gc
1545         // rvh = null;
1546     }
1547 
1548     /**
1549      * Reports whether the last column read was SQL <code>NULL</code>.
1550      * Note that you must first call the method <code>getXXX</code>
1551      * on a column to try to read its value and then call the method
1552      * <code>wasNull</code> to determine whether the value was
1553      * SQL <code>NULL</code>.
1554      *
1555      * @return <code>true</code> if the value in the last column read
1556      *         was SQL <code>NULL</code>; <code>false</code> otherwise
1557      * @throws SQLException if an error occurs
1558      */
1559     public boolean wasNull() throws SQLException {
1560         return lastValueNull;
1561     }
1562 
1563     /**
1564      * Sets the field <code>lastValueNull</code> to the given
1565      * <code>boolean</code> value.
1566      *
1567      * @param value <code>true</code> to indicate that the value of
1568      *        the last column read was SQL <code>NULL</code>;
1569      *        <code>false</code> to indicate that it was not
1570      */
1571     private void setLastValueNull(boolean value) {
1572         lastValueNull = value;
1573     }
1574 
1575     // Methods for accessing results by column index
1576 
1577     /**
1578      * Checks to see whether the given index is a valid column number
1579      * in this <code>CachedRowSetImpl</code> object and throws
1580      * an <code>SQLException</code> if it is not. The index is out of bounds
1581      * if it is less than <code>1</code> or greater than the number of
1582      * columns in this rowset.
1583      * <P>
1584      * This method is called internally by the <code>getXXX</code> and
1585      * <code>updateXXX</code> methods.
1586      *
1587      * @param idx the number of a column in this <code>CachedRowSetImpl</code>
1588      *            object; must be between <code>1</code> and the number of
1589      *            rows in this rowset
1590      * @throws SQLException if the given index is out of bounds
1591      */
1592     private void checkIndex(int idx) throws SQLException {
1593         if (idx < 1 || idx > RowSetMD.getColumnCount()) {
1594             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcol").toString());
1595         }
1596     }
1597 
1598     /**
1599      * Checks to see whether the cursor for this <code>CachedRowSetImpl</code>
1600      * object is on a row in the rowset and throws an
1601      * <code>SQLException</code> if it is not.
1602      * <P>
1603      * This method is called internally by <code>getXXX</code> methods, by
1604      * <code>updateXXX</code> methods, and by methods that update, insert,
1605      * or delete a row or that cancel a row update, insert, or delete.
1606      *
1607      * @throws SQLException if the cursor for this <code>CachedRowSetImpl</code>
1608      *         object is not on a valid row
1609      */
1610     private void checkCursor() throws SQLException {
1611         if (isAfterLast() == true || isBeforeFirst() == true) {
1612             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1613         }
1614     }
1615 
1616     /**
1617      * Returns the column number of the column with the given name in this
1618      * <code>CachedRowSetImpl</code> object.  This method throws an
1619      * <code>SQLException</code> if the given name is not the name of
1620      * one of the columns in this rowset.
1621      *
1622      * @param name a <code>String</code> object that is the name of a column in
1623      *              this <code>CachedRowSetImpl</code> object
1624      * @throws SQLException if the given name does not match the name of one of
1625      *         the columns in this rowset
1626      */
1627     private int getColIdxByName(String name) throws SQLException {
1628         RowSetMD = (RowSetMetaDataImpl)this.getMetaData();
1629         int cols = RowSetMD.getColumnCount();
1630 
1631         for (int i=1; i <= cols; ++i) {
1632             String colName = RowSetMD.getColumnName(i);
1633             if (colName != null)
1634                 if (name.equalsIgnoreCase(colName))
1635                     return (i);
1636                 else
1637                     continue;
1638         }
1639         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalcolnm").toString());
1640 
1641     }
1642 
1643     /**
1644      * Returns the insert row or the current row of this
1645      * <code>CachedRowSetImpl</code>object.
1646      *
1647      * @return the <code>Row</code> object on which this <code>CachedRowSetImpl</code>
1648      * objects's cursor is positioned
1649      */
1650     protected BaseRow getCurrentRow() {
1651         if (onInsertRow == true) {
1652             return (BaseRow)insertRow;
1653         } else {
1654             return (BaseRow)(rvh.get(cursorPos - 1));
1655         }
1656     }
1657 
1658     /**
1659      * Removes the row on which the cursor is positioned.
1660      * <p>
1661      * This is a implementation only method and is not required as a standard
1662      * implementation of the <code>CachedRowSet</code> interface.
1663      *
1664      * @throws SQLException if the cursor is positioned on the insert
1665      *            row
1666      */
1667     protected void removeCurrentRow() {
1668         ((Row)getCurrentRow()).setDeleted();
1669         rvh.remove(cursorPos - 1);
1670         --numRows;
1671     }
1672 
1673 
1674     /**
1675      * Retrieves the value of the designated column in the current row
1676      * of this <code>CachedRowSetImpl</code> object as a
1677      * <code>String</code> object.
1678      *
1679      * @param columnIndex the first column is <code>1</code>, the second
1680      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1681      *        and equal to or less than the number of columns in the rowset
1682      * @return the column value; if the value is SQL <code>NULL</code>, the
1683      *         result is <code>null</code>
1684      * @throws SQLException if (1) the given column index is out of bounds,
1685      * (2) the cursor is not on one of this rowset's rows or its
1686      * insert row, or (3) the designated column does not store an
1687      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
1688      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, <b>CHAR</b>, <b>VARCHAR</b></code>
1689      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1690      * recommended return type.
1691      */
1692     public String getString(int columnIndex) throws SQLException {
1693         Object value;
1694 
1695         // sanity check.
1696         checkIndex(columnIndex);
1697         // make sure the cursor is on a valid row
1698         checkCursor();
1699 
1700         setLastValueNull(false);
1701         value = getCurrentRow().getColumnObject(columnIndex);
1702 
1703         // check for SQL NULL
1704         if (value == null) {
1705             setLastValueNull(true);
1706             return null;
1707         }
1708 
1709         return value.toString();
1710     }
1711 
1712     /**
1713      * Retrieves the value of the designated column in the current row
1714      * of this <code>CachedRowSetImpl</code> object as a
1715      * <code>boolean</code> value.
1716      *
1717      * @param columnIndex the first column is <code>1</code>, the second
1718      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1719      *        and equal to or less than the number of columns in the rowset
1720      * @return the column value as a <code>boolean</code> in the Java progamming language;
1721      *        if the value is SQL <code>NULL</code>, the result is <code>false</code>
1722      * @throws SQLException if (1) the given column index is out of bounds,
1723      *            (2) the cursor is not on one of this rowset's rows or its
1724      *            insert row, or (3) the designated column does not store an
1725      *            SQL <code>BOOLEAN</code> value
1726      * @see #getBoolean(String)
1727      */
1728     public boolean getBoolean(int columnIndex) throws SQLException {
1729         Object value;
1730 
1731         // sanity check.
1732         checkIndex(columnIndex);
1733         // make sure the cursor is on a valid row
1734         checkCursor();
1735 
1736         setLastValueNull(false);
1737         value = getCurrentRow().getColumnObject(columnIndex);
1738 
1739         // check for SQL NULL
1740         if (value == null) {
1741             setLastValueNull(true);
1742             return false;
1743         }
1744 
1745         // check for Boolean...
1746         if (value instanceof Boolean) {
1747             return ((Boolean)value).booleanValue();
1748         }
1749 
1750         // convert to a Double and compare to zero
1751         try {
1752             Double d = new Double(value.toString());
1753             if (d.compareTo(new Double((double)0)) == 0) {
1754                 return false;
1755             } else {
1756                 return true;
1757             }
1758         } catch (NumberFormatException ex) {
1759             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.boolfail").toString(),
1760                   new Object[] {value.toString().trim(), columnIndex}));
1761         }
1762     }
1763 
1764     /**
1765      * Retrieves the value of the designated column in the current row
1766      * of this <code>CachedRowSetImpl</code> object as a
1767      * <code>byte</code> value.
1768      *
1769      * @param columnIndex the first column is <code>1</code>, the second
1770      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1771      *        and equal to or less than the number of columns in the rowset
1772      * @return the column value as a <code>byte</code> in the Java programming
1773      * language; if the value is SQL <code>NULL</code>, the result is <code>0</code>
1774      * @throws SQLException if (1) the given column index is out of bounds,
1775      *            (2) the cursor is not on one of this rowset's rows or its
1776      *            insert row, or (3) the designated column does not store an
1777      *            SQL <code><b>TINYINT</b>, SMALLINT, INTEGER, BIGINT, REAL,
1778      *            FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1779      *            or <code>LONGVARCHAR</code> value. The bold SQL type
1780      *            designates the recommended return type.
1781      * @see #getByte(String)
1782      */
1783     public byte getByte(int columnIndex) throws SQLException {
1784         Object value;
1785 
1786         // sanity check.
1787         checkIndex(columnIndex);
1788         // make sure the cursor is on a valid row
1789         checkCursor();
1790 
1791         setLastValueNull(false);
1792         value = getCurrentRow().getColumnObject(columnIndex);
1793 
1794         // check for SQL NULL
1795         if (value == null) {
1796             setLastValueNull(true);
1797             return (byte)0;
1798         }
1799         try {
1800             return ((Byte.valueOf(value.toString())).byteValue());
1801         } catch (NumberFormatException ex) {
1802             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.bytefail").toString(),
1803                   new Object[] {value.toString().trim(), columnIndex}));
1804         }
1805     }
1806 
1807     /**
1808      * Retrieves the value of the designated column in the current row
1809      * of this <code>CachedRowSetImpl</code> object as a
1810      * <code>short</code> value.
1811      *
1812      * @param columnIndex the first column is <code>1</code>, the second
1813      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1814      *        and equal to or less than the number of columns in the rowset
1815      * @return the column value; if the value is SQL <code>NULL</code>, the
1816      *         result is <code>0</code>
1817      * @throws SQLException if (1) the given column index is out of bounds,
1818      * (2) the cursor is not on one of this rowset's rows or its
1819      * insert row, or (3) the designated column does not store an
1820      * SQL <code>TINYINT, <b>SMALLINT</b>, INTEGER, BIGINT, REAL
1821      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1822      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1823      * recommended return type.
1824      * @see #getShort(String)
1825      */
1826     public short getShort(int columnIndex) throws SQLException {
1827         Object value;
1828 
1829         // sanity check.
1830         checkIndex(columnIndex);
1831         // make sure the cursor is on a valid row
1832         checkCursor();
1833 
1834         setLastValueNull(false);
1835         value = getCurrentRow().getColumnObject(columnIndex);
1836 
1837         // check for SQL NULL
1838         if (value == null) {
1839             setLastValueNull(true);
1840             return (short)0;
1841         }
1842 
1843         try {
1844             return ((Short.valueOf(value.toString().trim())).shortValue());
1845         } catch (NumberFormatException ex) {
1846             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.shortfail").toString(),
1847                   new Object[] {value.toString().trim(), columnIndex}));
1848         }
1849     }
1850 
1851     /**
1852      * Retrieves the value of the designated column in the current row
1853      * of this <code>CachedRowSetImpl</code> object as an
1854      * <code>int</code> value.
1855      *
1856      * @param columnIndex the first column is <code>1</code>, the second
1857      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1858      *        and equal to or less than the number of columns in the rowset
1859      * @return the column value; if the value is SQL <code>NULL</code>, the
1860      *         result is <code>0</code>
1861      * @throws SQLException if (1) the given column index is out of bounds,
1862      * (2) the cursor is not on one of this rowset's rows or its
1863      * insert row, or (3) the designated column does not store an
1864      * SQL <code>TINYINT, SMALLINT, <b>INTEGER</b>, BIGINT, REAL
1865      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1866      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1867      * recommended return type.
1868      */
1869     public int getInt(int columnIndex) throws SQLException {
1870         Object value;
1871 
1872         // sanity check.
1873         checkIndex(columnIndex);
1874         // make sure the cursor is on a valid row
1875         checkCursor();
1876 
1877         setLastValueNull(false);
1878         value = getCurrentRow().getColumnObject(columnIndex);
1879 
1880         // check for SQL NULL
1881         if (value == null) {
1882             setLastValueNull(true);
1883             return (int)0;
1884         }
1885 
1886         try {
1887             return ((Integer.valueOf(value.toString().trim())).intValue());
1888         } catch (NumberFormatException ex) {
1889             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.intfail").toString(),
1890                   new Object[] {value.toString().trim(), columnIndex}));
1891         }
1892     }
1893 
1894     /**
1895      * Retrieves the value of the designated column in the current row
1896      * of this <code>CachedRowSetImpl</code> object as a
1897      * <code>long</code> value.
1898      *
1899      * @param columnIndex the first column is <code>1</code>, the second
1900      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1901      *        and equal to or less than the number of columns in the rowset
1902      * @return the column value; if the value is SQL <code>NULL</code>, the
1903      *         result is <code>0</code>
1904      * @throws SQLException if (1) the given column index is out of bounds,
1905      * (2) the cursor is not on one of this rowset's rows or its
1906      * insert row, or (3) the designated column does not store an
1907      * SQL <code>TINYINT, SMALLINT, INTEGER, <b>BIGINT</b>, REAL
1908      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1909      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1910      * recommended return type.
1911      * @see #getLong(String)
1912      */
1913     public long getLong(int columnIndex) throws SQLException {
1914         Object value;
1915 
1916         // sanity check.
1917         checkIndex(columnIndex);
1918         // make sure the cursor is on a valid row
1919         checkCursor();
1920 
1921         setLastValueNull(false);
1922         value = getCurrentRow().getColumnObject(columnIndex);
1923 
1924         // check for SQL NULL
1925         if (value == null) {
1926             setLastValueNull(true);
1927             return (long)0;
1928         }
1929         try {
1930             return ((Long.valueOf(value.toString().trim())).longValue());
1931         } catch (NumberFormatException ex) {
1932             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.longfail").toString(),
1933                   new Object[] {value.toString().trim(), columnIndex}));
1934         }
1935     }
1936 
1937     /**
1938      * Retrieves the value of the designated column in the current row
1939      * of this <code>CachedRowSetImpl</code> object as a
1940      * <code>float</code> value.
1941      *
1942      * @param columnIndex the first column is <code>1</code>, the second
1943      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1944      *        and equal to or less than the number of columns in the rowset
1945      * @return the column value; if the value is SQL <code>NULL</code>, the
1946      *         result is <code>0</code>
1947      * @throws SQLException if (1) the given column index is out of bounds,
1948      * (2) the cursor is not on one of this rowset's rows or its
1949      * insert row, or (3) the designated column does not store an
1950      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, <b>REAL</b>,
1951      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1952      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1953      * recommended return type.
1954      * @see #getFloat(String)
1955      */
1956     public float getFloat(int columnIndex) throws SQLException {
1957         Object value;
1958 
1959         // sanity check.
1960         checkIndex(columnIndex);
1961         // make sure the cursor is on a valid row
1962         checkCursor();
1963 
1964         setLastValueNull(false);
1965         value = getCurrentRow().getColumnObject(columnIndex);
1966 
1967         // check for SQL NULL
1968         if (value == null) {
1969             setLastValueNull(true);
1970             return (float)0;
1971         }
1972         try {
1973             return ((new Float(value.toString())).floatValue());
1974         } catch (NumberFormatException ex) {
1975             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.floatfail").toString(),
1976                   new Object[] {value.toString().trim(), columnIndex}));
1977         }
1978     }
1979 
1980     /**
1981      * Retrieves the value of the designated column in the current row
1982      * of this <code>CachedRowSetImpl</code> object as a
1983      * <code>double</code> value.
1984      *
1985      * @param columnIndex the first column is <code>1</code>, the second
1986      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1987      *        and equal to or less than the number of columns in the rowset
1988      * @return the column value; if the value is SQL <code>NULL</code>, the
1989      *         result is <code>0</code>
1990      * @throws SQLException if (1) the given column index is out of bounds,
1991      * (2) the cursor is not on one of this rowset's rows or its
1992      * insert row, or (3) the designated column does not store an
1993      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
1994      * <b>FLOAT</b>, <b>DOUBLE</b>, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1995      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1996      * recommended return type.
1997      * @see #getDouble(String)
1998      *
1999      */
2000     public double getDouble(int columnIndex) throws SQLException {
2001         Object value;
2002 
2003         // sanity check.
2004         checkIndex(columnIndex);
2005         // make sure the cursor is on a valid row
2006         checkCursor();
2007 
2008         setLastValueNull(false);
2009         value = getCurrentRow().getColumnObject(columnIndex);
2010 
2011         // check for SQL NULL
2012         if (value == null) {
2013             setLastValueNull(true);
2014             return (double)0;
2015         }
2016         try {
2017             return ((new Double(value.toString().trim())).doubleValue());
2018         } catch (NumberFormatException ex) {
2019             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.doublefail").toString(),
2020                   new Object[] {value.toString().trim(), columnIndex}));
2021         }
2022     }
2023 
2024     /**
2025      * Retrieves the value of the designated column in the current row
2026      * of this <code>CachedRowSetImpl</code> object as a
2027      * <code>java.math.BigDecimal</code> object.
2028      * <P>
2029      * This method is deprecated; use the version of <code>getBigDecimal</code>
2030      * that does not take a scale parameter and returns a value with full
2031      * precision.
2032      *
2033      * @param columnIndex the first column is <code>1</code>, the second
2034      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2035      *        and equal to or less than the number of columns in the rowset
2036      * @param scale the number of digits to the right of the decimal point in the
2037      *        value returned
2038      * @return the column value with the specified number of digits to the right
2039      *         of the decimal point; if the value is SQL <code>NULL</code>, the
2040      *         result is <code>null</code>
2041      * @throws SQLException if the given column index is out of bounds,
2042      *            the cursor is not on a valid row, or this method fails
2043      * @deprecated
2044      */
2045     public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
2046         Object value;
2047         BigDecimal bDecimal, retVal;
2048 
2049         // sanity check.
2050         checkIndex(columnIndex);
2051         // make sure the cursor is on a valid row
2052         checkCursor();
2053 
2054         setLastValueNull(false);
2055         value = getCurrentRow().getColumnObject(columnIndex);
2056 
2057         // check for SQL NULL
2058         if (value == null) {
2059             setLastValueNull(true);
2060             return (new BigDecimal(0));
2061         }
2062 
2063         bDecimal = this.getBigDecimal(columnIndex);
2064 
2065         retVal = bDecimal.setScale(scale);
2066 
2067         return retVal;
2068     }
2069 
2070     /**
2071      * Retrieves the value of the designated column in the current row
2072      * of this <code>CachedRowSetImpl</code> object as a
2073      * <code>byte</code> array value.
2074      *
2075      * @param columnIndex the first column is <code>1</code>, the second
2076      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2077      *        and equal to or less than the number of columns in the rowset
2078      * @return the column value as a <code>byte</code> array in the Java programming
2079      * language; if the value is SQL <code>NULL</code>, the
2080      * result is <code>null</code>
2081      *
2082      * @throws SQLException if (1) the given column index is out of bounds,
2083      * (2) the cursor is not on one of this rowset's rows or its
2084      * insert row, or (3) the designated column does not store an
2085      * SQL <code><b>BINARY</b>, <b>VARBINARY</b> or
2086      * LONGVARBINARY</code> value.
2087      * The bold SQL type designates the recommended return type.
2088      * @see #getBytes(String)
2089      */
2090     public byte[] getBytes(int columnIndex) throws SQLException {
2091         // sanity check.
2092         checkIndex(columnIndex);
2093         // make sure the cursor is on a valid row
2094         checkCursor();
2095 
2096         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
2097             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2098         }
2099 
2100         return (byte[])(getCurrentRow().getColumnObject(columnIndex));
2101     }
2102 
2103     /**
2104      * Retrieves the value of the designated column in the current row
2105      * of this <code>CachedRowSetImpl</code> object as a
2106      * <code>java.sql.Date</code> object.
2107      *
2108      * @param columnIndex the first column is <code>1</code>, the second
2109      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2110      *        and equal to or less than the number of columns in the rowset
2111      * @return the column value as a <code>java.sql.Data</code> object; if
2112      *        the value is SQL <code>NULL</code>, the
2113      *        result is <code>null</code>
2114      * @throws SQLException if the given column index is out of bounds,
2115      *            the cursor is not on a valid row, or this method fails
2116      */
2117     public java.sql.Date getDate(int columnIndex) throws SQLException {
2118         Object value;
2119 
2120         // sanity check.
2121         checkIndex(columnIndex);
2122         // make sure the cursor is on a valid row
2123         checkCursor();
2124 
2125         setLastValueNull(false);
2126         value = getCurrentRow().getColumnObject(columnIndex);
2127 
2128         // check for SQL NULL
2129         if (value == null) {
2130             setLastValueNull(true);
2131             return null;
2132         }
2133 
2134         /*
2135          * The object coming back from the db could be
2136          * a date, a timestamp, or a char field variety.
2137          * If it's a date type return it, a timestamp
2138          * we turn into a long and then into a date,
2139          * char strings we try to parse. Yuck.
2140          */
2141         switch (RowSetMD.getColumnType(columnIndex)) {
2142             case java.sql.Types.DATE: {
2143                 long sec = ((java.sql.Date)value).getTime();
2144                 return new java.sql.Date(sec);
2145             }
2146             case java.sql.Types.TIMESTAMP: {
2147                 long sec = ((java.sql.Timestamp)value).getTime();
2148                 return new java.sql.Date(sec);
2149             }
2150             case java.sql.Types.CHAR:
2151             case java.sql.Types.VARCHAR:
2152             case java.sql.Types.LONGVARCHAR: {
2153                 try {
2154                     DateFormat df = DateFormat.getDateInstance();
2155                     return ((java.sql.Date)(df.parse(value.toString())));
2156                 } catch (ParseException ex) {
2157                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.datefail").toString(),
2158                         new Object[] {value.toString().trim(), columnIndex}));
2159                 }
2160             }
2161             default: {
2162                 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.datefail").toString(),
2163                         new Object[] {value.toString().trim(), columnIndex}));
2164             }
2165         }
2166     }
2167 
2168     /**
2169      * Retrieves the value of the designated column in the current row
2170      * of this <code>CachedRowSetImpl</code> object as a
2171      * <code>java.sql.Time</code> object.
2172      *
2173      * @param columnIndex the first column is <code>1</code>, the second
2174      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2175      *        and equal to or less than the number of columns in the rowset
2176      * @return the column value; if the value is SQL <code>NULL</code>, the
2177      *         result is <code>null</code>
2178      * @throws SQLException if the given column index is out of bounds,
2179      *         the cursor is not on a valid row, or this method fails
2180      */
2181     public java.sql.Time getTime(int columnIndex) throws SQLException {
2182         Object value;
2183 
2184         // sanity check.
2185         checkIndex(columnIndex);
2186         // make sure the cursor is on a valid row
2187         checkCursor();
2188 
2189         setLastValueNull(false);
2190         value = getCurrentRow().getColumnObject(columnIndex);
2191 
2192         // check for SQL NULL
2193         if (value == null) {
2194             setLastValueNull(true);
2195             return null;
2196         }
2197 
2198         /*
2199          * The object coming back from the db could be
2200          * a date, a timestamp, or a char field variety.
2201          * If it's a date type return it, a timestamp
2202          * we turn into a long and then into a date,
2203          * char strings we try to parse. Yuck.
2204          */
2205         switch (RowSetMD.getColumnType(columnIndex)) {
2206             case java.sql.Types.TIME: {
2207                 return (java.sql.Time)value;
2208             }
2209             case java.sql.Types.TIMESTAMP: {
2210                 long sec = ((java.sql.Timestamp)value).getTime();
2211                 return new java.sql.Time(sec);
2212             }
2213             case java.sql.Types.CHAR:
2214             case java.sql.Types.VARCHAR:
2215             case java.sql.Types.LONGVARCHAR: {
2216                 try {
2217                     DateFormat tf = DateFormat.getTimeInstance();
2218                     return ((java.sql.Time)(tf.parse(value.toString())));
2219                 } catch (ParseException ex) {
2220                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2221                         new Object[] {value.toString().trim(), columnIndex}));
2222                 }
2223             }
2224             default: {
2225                 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2226                         new Object[] {value.toString().trim(), columnIndex}));
2227             }
2228         }
2229     }
2230 
2231     /**
2232      * Retrieves the value of the designated column in the current row
2233      * of this <code>CachedRowSetImpl</code> object as a
2234      * <code>java.sql.Timestamp</code> object.
2235      *
2236      * @param columnIndex the first column is <code>1</code>, the second
2237      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2238      *        and equal to or less than the number of columns in the rowset
2239      * @return the column value; if the value is SQL <code>NULL</code>, the
2240      *         result is <code>null</code>
2241      * @throws SQLException if the given column index is out of bounds,
2242      *            the cursor is not on a valid row, or this method fails
2243      */
2244     public java.sql.Timestamp getTimestamp(int columnIndex) throws SQLException {
2245         Object value;
2246 
2247         // sanity check.
2248         checkIndex(columnIndex);
2249         // make sure the cursor is on a valid row
2250         checkCursor();
2251 
2252         setLastValueNull(false);
2253         value = getCurrentRow().getColumnObject(columnIndex);
2254 
2255         // check for SQL NULL
2256         if (value == null) {
2257             setLastValueNull(true);
2258             return null;
2259         }
2260 
2261         /*
2262          * The object coming back from the db could be
2263          * a date, a timestamp, or a char field variety.
2264          * If it's a date type return it; a timestamp
2265          * we turn into a long and then into a date;
2266          * char strings we try to parse. Yuck.
2267          */
2268         switch (RowSetMD.getColumnType(columnIndex)) {
2269             case java.sql.Types.TIMESTAMP: {
2270                 return (java.sql.Timestamp)value;
2271             }
2272             case java.sql.Types.TIME: {
2273                 long sec = ((java.sql.Time)value).getTime();
2274                 return new java.sql.Timestamp(sec);
2275             }
2276             case java.sql.Types.DATE: {
2277                 long sec = ((java.sql.Date)value).getTime();
2278                 return new java.sql.Timestamp(sec);
2279             }
2280             case java.sql.Types.CHAR:
2281             case java.sql.Types.VARCHAR:
2282             case java.sql.Types.LONGVARCHAR: {
2283                 try {
2284                     DateFormat tf = DateFormat.getTimeInstance();
2285                     return ((java.sql.Timestamp)(tf.parse(value.toString())));
2286                 } catch (ParseException ex) {
2287                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2288                         new Object[] {value.toString().trim(), columnIndex}));
2289                 }
2290             }
2291             default: {
2292                 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2293                         new Object[] {value.toString().trim(), columnIndex}));
2294             }
2295         }
2296     }
2297 
2298     /**
2299      * Retrieves the value of the designated column in the current row of this
2300      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2301      * object.
2302      *
2303      * A column value can be retrieved as a stream of ASCII characters
2304      * and then read in chunks from the stream.  This method is particularly
2305      * suitable for retrieving large <code>LONGVARCHAR</code> values.  The JDBC
2306      * driver will do any necessary conversion from the database format into ASCII.
2307      *
2308      * <P><B>Note:</B> All the data in the returned stream must be
2309      * read prior to getting the value of any other column. The next
2310      * call to a get method implicitly closes the stream. . Also, a
2311      * stream may return <code>0</code> for <code>CachedRowSetImpl.available()</code>
2312      * whether there is data available or not.
2313      *
2314      * @param columnIndex the first column is <code>1</code>, the second
2315      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2316      *        and equal to or less than the number of columns in this rowset
2317      * @return a Java input stream that delivers the database column value
2318      *         as a stream of one-byte ASCII characters.  If the value is SQL
2319      *         <code>NULL</code>, the result is <code>null</code>.
2320      * @throws SQLException if (1) the given column index is out of bounds,
2321      * (2) the cursor is not on one of this rowset's rows or its
2322      * insert row, or (3) the designated column does not store an
2323      * SQL <code>CHAR, VARCHAR</code>, <code><b>LONGVARCHAR</b></code>
2324      * <code>BINARY, VARBINARY</code> or <code>LONGVARBINARY</code> value. The
2325      * bold SQL type designates the recommended return types that this method is
2326      * used to retrieve.
2327      * @see #getAsciiStream(String)
2328      */
2329     public java.io.InputStream getAsciiStream(int columnIndex) throws SQLException {
2330         Object value;
2331 
2332         // always free an old stream
2333         asciiStream = null;
2334 
2335         // sanity check
2336         checkIndex(columnIndex);
2337         //make sure the cursor is on a vlid row
2338         checkCursor();
2339 
2340         value =  getCurrentRow().getColumnObject(columnIndex);
2341         if (value == null) {
2342             lastValueNull = true;
2343             return null;
2344         }
2345 
2346         try {
2347             if (isString(RowSetMD.getColumnType(columnIndex))) {
2348                 asciiStream = new ByteArrayInputStream(((String)value).getBytes("ASCII"));
2349             } else {
2350                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2351             }
2352         } catch (java.io.UnsupportedEncodingException ex) {
2353             throw new SQLException(ex.getMessage());
2354         }
2355 
2356         return (java.io.InputStream)asciiStream;
2357     }
2358 
2359     /**
2360      * A column value can be retrieved as a stream of Unicode characters
2361      * and then read in chunks from the stream.  This method is particularly
2362      * suitable for retrieving large LONGVARCHAR values.  The JDBC driver will
2363      * do any necessary conversion from the database format into Unicode.
2364      *
2365      * <P><B>Note:</B> All the data in the returned stream must be
2366      * read prior to getting the value of any other column. The next
2367      * call to a get method implicitly closes the stream. . Also, a
2368      * stream may return 0 for available() whether there is data
2369      * available or not.
2370      *
2371      * @param columnIndex the first column is <code>1</code>, the second
2372      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2373      *        and equal to or less than the number of columns in this rowset
2374      * @return a Java input stream that delivers the database column value
2375      * as a stream of two byte Unicode characters.  If the value is SQL NULL
2376      * then the result is null.
2377      * @throws SQLException if an error occurs
2378      * @deprecated
2379      */
2380     public java.io.InputStream getUnicodeStream(int columnIndex) throws SQLException {
2381         // always free an old stream
2382         unicodeStream = null;
2383 
2384         // sanity check.
2385         checkIndex(columnIndex);
2386         // make sure the cursor is on a valid row
2387         checkCursor();
2388 
2389         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false &&
2390         isString(RowSetMD.getColumnType(columnIndex)) == false) {
2391             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2392         }
2393 
2394         Object value = getCurrentRow().getColumnObject(columnIndex);
2395         if (value == null) {
2396             lastValueNull = true;
2397             return null;
2398         }
2399 
2400         unicodeStream = new StringBufferInputStream(value.toString());
2401 
2402         return (java.io.InputStream)unicodeStream;
2403     }
2404 
2405     /**
2406      * Retrieves the value of the designated column in the current row of this
2407      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2408      * object.
2409      * <P>
2410      * A column value can be retrieved as a stream of uninterpreted bytes
2411      * and then read in chunks from the stream.  This method is particularly
2412      * suitable for retrieving large <code>LONGVARBINARY</code> values.
2413      *
2414      * <P><B>Note:</B> All the data in the returned stream must be
2415      * read prior to getting the value of any other column. The next
2416      * call to a get method implicitly closes the stream. Also, a
2417      * stream may return <code>0</code> for
2418      * <code>CachedRowSetImpl.available()</code> whether there is data
2419      * available or not.
2420      *
2421      * @param columnIndex the first column is <code>1</code>, the second
2422      * is <code>2</code>, and so on; must be <code>1</code> or larger
2423      * and equal to or less than the number of columns in the rowset
2424      * @return a Java input stream that delivers the database column value
2425      * as a stream of uninterpreted bytes.  If the value is SQL <code>NULL</code>
2426      * then the result is <code>null</code>.
2427      * @throws SQLException if (1) the given column index is out of bounds,
2428      * (2) the cursor is not on one of this rowset's rows or its
2429      * insert row, or (3) the designated column does not store an
2430      * SQL <code>BINARY, VARBINARY</code> or <code><b>LONGVARBINARY</b></code>
2431      * The bold type indicates the SQL type that this method is recommened
2432      * to retrieve.
2433      * @see #getBinaryStream(String)
2434      */
2435     public java.io.InputStream getBinaryStream(int columnIndex) throws SQLException {
2436 
2437         // always free an old stream
2438         binaryStream = null;
2439 
2440         // sanity check.
2441         checkIndex(columnIndex);
2442         // make sure the cursor is on a valid row
2443         checkCursor();
2444 
2445         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
2446             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2447         }
2448 
2449         Object value = getCurrentRow().getColumnObject(columnIndex);
2450         if (value == null) {
2451             lastValueNull = true;
2452             return null;
2453         }
2454 
2455         binaryStream = new ByteArrayInputStream((byte[])value);
2456 
2457         return (java.io.InputStream)binaryStream;
2458 
2459     }
2460 
2461 
2462     // Methods for accessing results by column name
2463 
2464     /**
2465      * Retrieves the value stored in the designated column
2466      * of the current row as a <code>String</code> object.
2467      *
2468      * @param columnName a <code>String</code> object giving the SQL name of
2469      *        a column in this <code>CachedRowSetImpl</code> object
2470      * @return the column value; if the value is SQL <code>NULL</code>,
2471      *         the result is <code>null</code>
2472      * @throws SQLException if (1) the given column name is not the name of
2473      * a column in this rowset, (2) the cursor is not on one of
2474      * this rowset's rows or its insert row, or (3) the designated
2475      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2476      * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, <b>CHAR</b>,
2477      * <b>VARCHAR</b></code> or <code>LONGVARCHAR<</code> value. The bold SQL type
2478      * designates the recommended return type.
2479      */
2480     public String getString(String columnName) throws SQLException {
2481         return getString(getColIdxByName(columnName));
2482     }
2483 
2484     /**
2485      * Retrieves the value stored in the designated column
2486      * of the current row as a <code>boolean</code> value.
2487      *
2488      * @param columnName a <code>String</code> object giving the SQL name of
2489      *        a column in this <code>CachedRowSetImpl</code> object
2490      * @return the column value as a <code>boolean</code> in the Java programming
2491      *        language; if the value is SQL <code>NULL</code>,
2492      *        the result is <code>false</code>
2493      * @throws SQLException if (1) the given column name is not the name of
2494      *            a column in this rowset, (2) the cursor is not on one of
2495      *            this rowset's rows or its insert row, or (3) the designated
2496      *            column does not store an SQL <code>BOOLEAN</code> value
2497      * @see #getBoolean(int)
2498      */
2499     public boolean getBoolean(String columnName) throws SQLException {
2500         return getBoolean(getColIdxByName(columnName));
2501     }
2502 
2503     /**
2504      * Retrieves the value stored in the designated column
2505      * of the current row as a <code>byte</code> value.
2506      *
2507      * @param columnName a <code>String</code> object giving the SQL name of
2508      *        a column in this <code>CachedRowSetImpl</code> object
2509      * @return the column value as a <code>byte</code> in the Java programming
2510      * language; if the value is SQL <code>NULL</code>, the result is <code>0</code>
2511      * @throws SQLException if (1) the given column name is not the name of
2512      * a column in this rowset, (2) the cursor is not on one of
2513      * this rowset's rows or its insert row, or (3) the designated
2514      * column does not store an SQL <code><B>TINYINT</B>, SMALLINT, INTEGER,
2515      * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2516      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The
2517      * bold type designates the recommended return type
2518      */
2519     public byte getByte(String columnName) throws SQLException {
2520         return getByte(getColIdxByName(columnName));
2521     }
2522 
2523     /**
2524      * Retrieves the value stored in the designated column
2525      * of the current row as a <code>short</code> value.
2526      *
2527      * @param columnName a <code>String</code> object giving the SQL name of
2528      *        a column in this <code>CachedRowSetImpl</code> object
2529      * @return the column value; if the value is SQL <code>NULL</code>,
2530      *         the result is <code>0</code>
2531      * @throws SQLException if (1) the given column name is not the name of
2532      * a column in this rowset, (2) the cursor is not on one of
2533      * this rowset's rows or its insert row, or (3) the designated
2534      * column does not store an SQL <code>TINYINT, <b>SMALLINT</b>, INTEGER
2535      * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2536      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2537      * designates the recommended return type.
2538      * @see #getShort(int)
2539      */
2540     public short getShort(String columnName) throws SQLException {
2541         return getShort(getColIdxByName(columnName));
2542     }
2543 
2544     /**
2545      * Retrieves the value stored in the designated column
2546      * of the current row as an <code>int</code> value.
2547      *
2548      * @param columnName a <code>String</code> object giving the SQL name of
2549      *        a column in this <code>CachedRowSetImpl</code> object
2550      * @return the column value; if the value is SQL <code>NULL</code>,
2551      *         the result is <code>0</code>
2552      * @throws SQLException if (1) the given column name is not the name
2553      * of a column in this rowset,
2554      * (2) the cursor is not on one of this rowset's rows or its
2555      * insert row, or (3) the designated column does not store an
2556      * SQL <code>TINYINT, SMALLINT, <b>INTEGER</b>, BIGINT, REAL
2557      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
2558      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
2559      * recommended return type.
2560      */
2561     public int getInt(String columnName) throws SQLException {
2562         return getInt(getColIdxByName(columnName));
2563     }
2564 
2565     /**
2566      * Retrieves the value stored in the designated column
2567      * of the current row as a <code>long</code> value.
2568      *
2569      * @param columnName a <code>String</code> object giving the SQL name of
2570      *        a column in this <code>CachedRowSetImpl</code> object
2571      * @return the column value; if the value is SQL <code>NULL</code>,
2572      *         the result is <code>0</code>
2573      * @throws SQLException if (1) the given column name is not the name of
2574      * a column in this rowset, (2) the cursor is not on one of
2575      * this rowset's rows or its insert row, or (3) the designated
2576      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2577      * <b>BIGINT</b>, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2578      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2579      * designates the recommended return type.
2580      * @see #getLong(int)
2581      */
2582     public long getLong(String columnName) throws SQLException {
2583         return getLong(getColIdxByName(columnName));
2584     }
2585 
2586     /**
2587      * Retrieves the value stored in the designated column
2588      * of the current row as a <code>float</code> value.
2589      *
2590      * @param columnName a <code>String</code> object giving the SQL name of
2591      *        a column in this <code>CachedRowSetImpl</code> object
2592      * @return the column value; if the value is SQL <code>NULL</code>,
2593      *         the result is <code>0</code>
2594      * @throws SQLException if (1) the given column name is not the name of
2595      * a column in this rowset, (2) the cursor is not on one of
2596      * this rowset's rows or its insert row, or (3) the designated
2597      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2598      * BIGINT, <b>REAL</b>, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2599      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2600      * designates the recommended return type.
2601      * @see #getFloat(String)
2602      */
2603     public float getFloat(String columnName) throws SQLException {
2604         return getFloat(getColIdxByName(columnName));
2605     }
2606 
2607     /**
2608      * Retrieves the value stored in the designated column
2609      * of the current row of this <code>CachedRowSetImpl</code> object
2610      * as a <code>double</code> value.
2611      *
2612      * @param columnName a <code>String</code> object giving the SQL name of
2613      *        a column in this <code>CachedRowSetImpl</code> object
2614      * @return the column value; if the value is SQL <code>NULL</code>,
2615      *         the result is <code>0</code>
2616      * @throws SQLException if (1) the given column name is not the name of
2617      * a column in this rowset, (2) the cursor is not on one of
2618      * this rowset's rows or its insert row, or (3) the designated
2619      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2620      * BIGINT, REAL, <b>FLOAT</b>, <b>DOUBLE</b>, DECIMAL, NUMERIC, BIT, CHAR,
2621      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2622      * designates the recommended return types.
2623      * @see #getDouble(int)
2624      */
2625     public double getDouble(String columnName) throws SQLException {
2626         return getDouble(getColIdxByName(columnName));
2627     }
2628 
2629     /**
2630      * Retrieves the value stored in the designated column
2631      * of the current row as a <code>java.math.BigDecimal</code> object.
2632      *
2633      * @param columnName a <code>String</code> object giving the SQL name of
2634      *        a column in this <code>CachedRowSetImpl</code> object
2635      * @param scale the number of digits to the right of the decimal point
2636      * @return a java.math.BugDecimal object with <code><i>scale</i></code>
2637      * number of digits to the right of the decimal point.
2638      * @throws SQLException if (1) the given column name is not the name of
2639      * a column in this rowset, (2) the cursor is not on one of
2640      * this rowset's rows or its insert row, or (3) the designated
2641      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2642      * BIGINT, REAL, FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT CHAR,
2643      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2644      * designates the recommended return type that this method is used to
2645      * retrieve.
2646      * @deprecated Use the <code>getBigDecimal(String columnName)</code>
2647      *             method instead
2648      */
2649     public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {
2650         return getBigDecimal(getColIdxByName(columnName), scale);
2651     }
2652 
2653     /**
2654      * Retrieves the value stored in the designated column
2655      * of the current row as a <code>byte</code> array.
2656      * The bytes represent the raw values returned by the driver.
2657      *
2658      * @param columnName a <code>String</code> object giving the SQL name of
2659      *        a column in this <code>CachedRowSetImpl</code> object
2660      * @return the column value as a <code>byte</code> array in the Java programming
2661      * language; if the value is SQL <code>NULL</code>, the result is <code>null</code>
2662      * @throws SQLException if (1) the given column name is not the name of
2663      * a column in this rowset, (2) the cursor is not on one of
2664      * this rowset's rows or its insert row, or (3) the designated
2665      * column does not store an SQL <code><b>BINARY</b>, <b>VARBINARY</b>
2666      * </code> or <code>LONGVARBINARY</code> values
2667      * The bold SQL type designates the recommended return type.
2668      * @see #getBytes(int)
2669      */
2670     public byte[] getBytes(String columnName) throws SQLException {
2671         return getBytes(getColIdxByName(columnName));
2672     }
2673 
2674     /**
2675      * Retrieves the value stored in the designated column
2676      * of the current row as a <code>java.sql.Date</code> object.
2677      *
2678      * @param columnName a <code>String</code> object giving the SQL name of
2679      *        a column in this <code>CachedRowSetImpl</code> object
2680      * @return the column value; if the value is SQL <code>NULL</code>,
2681      *         the result is <code>null</code>
2682      * @throws SQLException if (1) the given column name is not the name of
2683      *            a column in this rowset, (2) the cursor is not on one of
2684      *            this rowset's rows or its insert row, or (3) the designated
2685      *            column does not store an SQL <code>DATE</code> or
2686      *            <code>TIMESTAMP</code> value
2687      */
2688     public java.sql.Date getDate(String columnName) throws SQLException {
2689         return getDate(getColIdxByName(columnName));
2690     }
2691 
2692     /**
2693      * Retrieves the value stored in the designated column
2694      * of the current row as a <code>java.sql.Time</code> object.
2695      *
2696      * @param columnName a <code>String</code> object giving the SQL name of
2697      *        a column in this <code>CachedRowSetImpl</code> object
2698      * @return the column value; if the value is SQL <code>NULL</code>,
2699      *         the result is <code>null</code>
2700      * @throws SQLException if the given column name does not match one of
2701      *            this rowset's column names or the cursor is not on one of
2702      *            this rowset's rows or its insert row
2703      */
2704     public java.sql.Time getTime(String columnName) throws SQLException {
2705         return getTime(getColIdxByName(columnName));
2706     }
2707 
2708     /**
2709      * Retrieves the value stored in the designated column
2710      * of the current row as a <code>java.sql.Timestamp</code> object.
2711      *
2712      * @param columnName a <code>String</code> object giving the SQL name of
2713      *        a column in this <code>CachedRowSetImpl</code> object
2714      * @return the column value; if the value is SQL <code>NULL</code>,
2715      *         the result is <code>null</code>
2716      * @throws SQLException if the given column name does not match one of
2717      *            this rowset's column names or the cursor is not on one of
2718      *            this rowset's rows or its insert row
2719      */
2720     public java.sql.Timestamp getTimestamp(String columnName) throws SQLException {
2721         return getTimestamp(getColIdxByName(columnName));
2722     }
2723 
2724     /**
2725      * Retrieves the value of the designated column in the current row of this
2726      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2727      * object.
2728      *
2729      * A column value can be retrieved as a stream of ASCII characters
2730      * and then read in chunks from the stream. This method is particularly
2731      * suitable for retrieving large <code>LONGVARCHAR</code> values. The
2732      * <code>SyncProvider</code> will rely on the JDBC driver to do any necessary
2733      * conversion from the database format into ASCII format.
2734      *
2735      * <P><B>Note:</B> All the data in the returned stream must
2736      * be read prior to getting the value of any other column. The
2737      * next call to a <code>getXXX</code> method implicitly closes the stream.
2738      *
2739      * @param columnName a <code>String</code> object giving the SQL name of
2740      *        a column in this <code>CachedRowSetImpl</code> object
2741      * @return a Java input stream that delivers the database column value
2742      *         as a stream of one-byte ASCII characters.  If the value is SQL
2743      *         <code>NULL</code>, the result is <code>null</code>.
2744      * @throws SQLException if (1) the given column name is not the name of
2745      * a column in this rowset
2746      * (2) the cursor is not on one of this rowset's rows or its
2747      * insert row, or (3) the designated column does not store an
2748      * SQL <code>CHAR, VARCHAR</code>, <code><b>LONGVARCHAR</b></code>
2749      * <code>BINARY, VARBINARY</code> or <code>LONGVARBINARY</code> value. The
2750      * bold SQL type designates the recommended return types that this method is
2751      * used to retrieve.
2752      * @see #getAsciiStream(int)
2753      */
2754     public java.io.InputStream getAsciiStream(String columnName) throws SQLException {
2755         return getAsciiStream(getColIdxByName(columnName));
2756 
2757     }
2758 
2759     /**
2760      * A column value can be retrieved as a stream of Unicode characters
2761      * and then read in chunks from the stream.  This method is particularly
2762      * suitable for retrieving large <code>LONGVARCHAR</code> values.
2763      * The JDBC driver will do any necessary conversion from the database
2764      * format into Unicode.
2765      *
2766      * <P><B>Note:</B> All the data in the returned stream must
2767      * be read prior to getting the value of any other column. The
2768      * next call to a <code>getXXX</code> method implicitly closes the stream.
2769      *
2770      * @param columnName a <code>String</code> object giving the SQL name of
2771      *        a column in this <code>CachedRowSetImpl</code> object
2772      * @return a Java input stream that delivers the database column value
2773      *         as a stream of two-byte Unicode characters.  If the value is
2774      *         SQL <code>NULL</code>, the result is <code>null</code>.
2775      * @throws SQLException if the given column name does not match one of
2776      *            this rowset's column names or the cursor is not on one of
2777      *            this rowset's rows or its insert row
2778      * @deprecated use the method <code>getCharacterStream</code> instead
2779      */
2780     public java.io.InputStream getUnicodeStream(String columnName) throws SQLException {
2781         return getUnicodeStream(getColIdxByName(columnName));
2782     }
2783 
2784     /**
2785      * Retrieves the value of the designated column in the current row of this
2786      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2787      * object.
2788      * <P>
2789      * A column value can be retrieved as a stream of uninterpreted bytes
2790      * and then read in chunks from the stream.  This method is particularly
2791      * suitable for retrieving large <code>LONGVARBINARY</code> values.
2792      *
2793      * <P><B>Note:</B> All the data in the returned stream must be
2794      * read prior to getting the value of any other column. The next
2795      * call to a get method implicitly closes the stream. Also, a
2796      * stream may return <code>0</code> for <code>CachedRowSetImpl.available()</code>
2797      * whether there is data available or not.
2798      *
2799      * @param columnName a <code>String</code> object giving the SQL name of
2800      *        a column in this <code>CachedRowSetImpl</code> object
2801      * @return a Java input stream that delivers the database column value
2802      *         as a stream of uninterpreted bytes.  If the value is SQL
2803      *         <code>NULL</code>, the result is <code>null</code>.
2804      * @throws SQLException if (1) the given column name is unknown,
2805      * (2) the cursor is not on one of this rowset's rows or its
2806      * insert row, or (3) the designated column does not store an
2807      * SQL <code>BINARY, VARBINARY</code> or <code><b>LONGVARBINARY</b></code>
2808      * The bold type indicates the SQL type that this method is recommened
2809      * to retrieve.
2810      * @see #getBinaryStream(int)
2811      *
2812      */
2813     public java.io.InputStream getBinaryStream(String columnName) throws SQLException {
2814         return getBinaryStream(getColIdxByName(columnName));
2815     }
2816 
2817 
2818     // Advanced features:
2819 
2820     /**
2821      * The first warning reported by calls on this <code>CachedRowSetImpl</code>
2822      * object is returned. Subsequent <code>CachedRowSetImpl</code> warnings will
2823      * be chained to this <code>SQLWarning</code>.
2824      *
2825      * <P>The warning chain is automatically cleared each time a new
2826      * row is read.
2827      *
2828      * <P><B>Note:</B> This warning chain only covers warnings caused
2829      * by <code>ResultSet</code> methods.  Any warning caused by statement
2830      * methods (such as reading OUT parameters) will be chained on the
2831      * <code>Statement</code> object.
2832      *
2833      * @return the first SQLWarning or null
2834      */
2835     public SQLWarning getWarnings() {
2836         return sqlwarn;
2837     }
2838 
2839     /**
2840      * Clears all the warnings reporeted for the <code>CachedRowSetImpl</code>
2841      * object. After a call to this method, the <code>getWarnings</code> method
2842      * returns <code>null</code> until a new warning is reported for this
2843      * <code>CachedRowSetImpl</code> object.
2844      */
2845     public void clearWarnings() {
2846         sqlwarn = null;
2847     }
2848 
2849     /**
2850      * Retrieves the name of the SQL cursor used by this
2851      * <code>CachedRowSetImpl</code> object.
2852      *
2853      * <P>In SQL, a result table is retrieved through a cursor that is
2854      * named. The current row of a <code>ResultSet</code> can be updated or deleted
2855      * using a positioned update/delete statement that references the
2856      * cursor name. To ensure that the cursor has the proper isolation
2857      * level to support an update operation, the cursor's <code>SELECT</code>
2858      * statement should be of the form <code>select for update</code>.
2859      * If the <code>for update</code> clause
2860      * is omitted, positioned updates may fail.
2861      *
2862      * <P>JDBC supports this SQL feature by providing the name of the
2863      * SQL cursor used by a <code>ResultSet</code> object. The current row
2864      * of a result set is also the current row of this SQL cursor.
2865      *
2866      * <P><B>Note:</B> If positioned updates are not supported, an
2867      * <code>SQLException</code> is thrown.
2868      *
2869      * @return the SQL cursor name for this <code>CachedRowSetImpl</code> object's
2870      *         cursor
2871      * @throws SQLException if an error occurs
2872      */
2873     public String getCursorName() throws SQLException {
2874         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.posupdate").toString());
2875     }
2876 
2877     /**
2878      * Retrieves a <code>ResultSetMetaData</code> object instance that
2879      * contains information about the <code>CachedRowSet</code> object.
2880      * However, applications should cast the returned object to a
2881      * <code>RowSetMetaData</code> interface implementation. In the
2882      * reference implementation, this cast can be done on the
2883      * <code>RowSetMetaDataImpl</code> class.
2884      * <P>
2885      * For example:
2886      * <pre>
2887      * CachedRowSet crs = new CachedRowSetImpl();
2888      * RowSetMetaDataImpl metaData =
2889      *     (RowSetMetaDataImpl)crs.getMetaData();
2890      * // Set the number of columns in the RowSet object for
2891      * // which this RowSetMetaDataImpl object was created to the
2892      * // given number.
2893      * metaData.setColumnCount(3);
2894      * crs.setMetaData(metaData);
2895      * </pre>
2896      *
2897      * @return the <code>ResultSetMetaData</code> object that describes this
2898      *         <code>CachedRowSetImpl</code> object's columns
2899      * @throws SQLException if an error occurs in generating the RowSet
2900      * meta data; or if the <code>CachedRowSetImpl</code> is empty.
2901      * @see javax.sql.RowSetMetaData
2902      */
2903     public ResultSetMetaData getMetaData() throws SQLException {
2904         return (ResultSetMetaData)RowSetMD;
2905     }
2906 
2907 
2908     /**
2909      * Retrieves the value of the designated column in the current row
2910      * of this <code>CachedRowSetImpl</code> object as an
2911      * <code>Object</code> value.
2912      * <P>
2913      * The type of the <code>Object</code> will be the default
2914      * Java object type corresponding to the column's SQL type,
2915      * following the mapping for built-in types specified in the JDBC 3.0
2916      * specification.
2917      * <P>
2918      * This method may also be used to read datatabase-specific
2919      * abstract data types.
2920      * <P>
2921      * This implementation of the method <code>getObject</code> extends its
2922      * behavior so that it gets the attributes of an SQL structured type
2923      * as an array of <code>Object</code> values.  This method also custom
2924      * maps SQL user-defined types to classes in the Java programming language.
2925      * When the specified column contains
2926      * a structured or distinct value, the behavior of this method is as
2927      * if it were a call to the method <code>getObject(columnIndex,
2928      * this.getStatement().getConnection().getTypeMap())</code>.
2929      *
2930      * @param columnIndex the first column is <code>1</code>, the second
2931      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2932      *        and equal to or less than the number of columns in the rowset
2933      * @return a <code>java.lang.Object</code> holding the column value;
2934      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
2935      * @throws SQLException if the given column index is out of bounds,
2936      *            the cursor is not on a valid row, or there is a problem getting
2937      *            the <code>Class</code> object for a custom mapping
2938      * @see #getObject(String)
2939      */
2940     public Object getObject(int columnIndex) throws SQLException {
2941         Object value;
2942         Map<String, Class<?>> map;
2943 
2944         // sanity check.
2945         checkIndex(columnIndex);
2946         // make sure the cursor is on a valid row
2947         checkCursor();
2948 
2949         setLastValueNull(false);
2950         value = getCurrentRow().getColumnObject(columnIndex);
2951 
2952         // check for SQL NULL
2953         if (value == null) {
2954             setLastValueNull(true);
2955             return null;
2956         }
2957         if (value instanceof Struct) {
2958             Struct s = (Struct)value;
2959             map = getTypeMap();
2960             // look up the class in the map
2961             Class c = (Class)map.get(s.getSQLTypeName());
2962             if (c != null) {
2963                 // create new instance of the class
2964                 SQLData obj = null;
2965                 try {
2966                     obj = (SQLData)c.newInstance();
2967                 } catch (java.lang.InstantiationException ex) {
2968                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
2969                     ex.getMessage()));
2970                 } catch (java.lang.IllegalAccessException ex) {
2971                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
2972                     ex.getMessage()));
2973                 }
2974                 // get the attributes from the struct
2975                 Object attribs[] = s.getAttributes(map);
2976                 // create the SQLInput "stream"
2977                 SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
2978                 // read the values...
2979                 obj.readSQL(sqlInput, s.getSQLTypeName());
2980                 return (Object)obj;
2981             }
2982         }
2983         return value;
2984     }
2985 
2986     /**
2987      * Retrieves the value of the designated column in the current row
2988      * of this <code>CachedRowSetImpl</code> object as an
2989      * <code>Object</code> value.
2990      * <P>
2991      * The type of the <code>Object</code> will be the default
2992      * Java object type corresponding to the column's SQL type,
2993      * following the mapping for built-in types specified in the JDBC 3.0
2994      * specification.
2995      * <P>
2996      * This method may also be used to read datatabase-specific
2997      * abstract data types.
2998      * <P>
2999      * This implementation of the method <code>getObject</code> extends its
3000      * behavior so that it gets the attributes of an SQL structured type
3001      * as an array of <code>Object</code> values.  This method also custom
3002      * maps SQL user-defined types to classes
3003      * in the Java programming language. When the specified column contains
3004      * a structured or distinct value, the behavior of this method is as
3005      * if it were a call to the method <code>getObject(columnIndex,
3006      * this.getStatement().getConnection().getTypeMap())</code>.
3007      *
3008      * @param columnName a <code>String</code> object that must match the
3009      *        SQL name of a column in this rowset, ignoring case
3010      * @return a <code>java.lang.Object</code> holding the column value;
3011      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3012      * @throws SQLException if (1) the given column name does not match one of
3013      *            this rowset's column names, (2) the cursor is not
3014      *            on a valid row, or (3) there is a problem getting
3015      *            the <code>Class</code> object for a custom mapping
3016      * @see #getObject(int)
3017      */
3018     public Object getObject(String columnName) throws SQLException {
3019         return getObject(getColIdxByName(columnName));
3020     }
3021 
3022     //----------------------------------------------------------------
3023 
3024     /**
3025      * Maps the given column name for one of this <code>CachedRowSetImpl</code>
3026      * object's columns to its column number.
3027      *
3028      * @param columnName a <code>String</code> object that must match the
3029      *        SQL name of a column in this rowset, ignoring case
3030      * @return the column index of the given column name
3031      * @throws SQLException if the given column name does not match one
3032      *            of this rowset's column names
3033      */
3034     public int findColumn(String columnName) throws SQLException {
3035         return getColIdxByName(columnName);
3036     }
3037 
3038 
3039     //--------------------------JDBC 2.0-----------------------------------
3040 
3041     //---------------------------------------------------------------------
3042     // Getter's and Setter's
3043     //---------------------------------------------------------------------
3044 
3045     /**
3046      * Retrieves the value stored in the designated column
3047      * of the current row as a <code>java.io.Reader</code> object.
3048      *
3049      * <P><B>Note:</B> All the data in the returned stream must
3050      * be read prior to getting the value of any other column. The
3051      * next call to a <code>getXXX</code> method implicitly closes the stream.
3052      *
3053      * @param columnIndex the first column is <code>1</code>, the second
3054      *        is <code>2</code>, and so on; must be <code>1</code> or larger
3055      *        and equal to or less than the number of columns in the rowset
3056      * @return a Java character stream that delivers the database column value
3057      * as a stream of two-byte unicode characters in a
3058      * <code>java.io.Reader</code> object.  If the value is
3059      * SQL <code>NULL</code>, the result is <code>null</code>.
3060      * @throws SQLException if (1) the given column index is out of bounds,
3061      * (2) the cursor is not on one of this rowset's rows or its
3062      * insert row, or (3) the designated column does not store an
3063      * SQL <code>CHAR, VARCHAR, <b>LONGVARCHAR</b>, BINARY, VARBINARY</code> or
3064      * <code>LONGVARBINARY</code> value.
3065      * The bold SQL type designates the recommended return type.
3066      * @see #getCharacterStream(String)
3067      */
3068     public java.io.Reader getCharacterStream(int columnIndex) throws SQLException{
3069 
3070         // sanity check.
3071         checkIndex(columnIndex);
3072         // make sure the cursor is on a valid row
3073         checkCursor();
3074 
3075         if (isBinary(RowSetMD.getColumnType(columnIndex))) {
3076             Object value = getCurrentRow().getColumnObject(columnIndex);
3077             if (value == null) {
3078                 lastValueNull = true;
3079                 return null;
3080             }
3081             charStream = new InputStreamReader
3082             (new ByteArrayInputStream((byte[])value));
3083         } else if (isString(RowSetMD.getColumnType(columnIndex))) {
3084             Object value = getCurrentRow().getColumnObject(columnIndex);
3085             if (value == null) {
3086                 lastValueNull = true;
3087                 return null;
3088             }
3089             charStream = new StringReader(value.toString());
3090         } else {
3091             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
3092         }
3093 
3094         return (java.io.Reader)charStream;
3095     }
3096 
3097     /**
3098      * Retrieves the value stored in the designated column
3099      * of the current row as a <code>java.io.Reader</code> object.
3100      *
3101      * <P><B>Note:</B> All the data in the returned stream must
3102      * be read prior to getting the value of any other column. The
3103      * next call to a <code>getXXX</code> method implicitly closes the stream.
3104      *
3105      * @param columnName a <code>String</code> object giving the SQL name of
3106      *        a column in this <code>CachedRowSetImpl</code> object
3107      * @return a Java input stream that delivers the database column value
3108      *         as a stream of two-byte Unicode characters.  If the value is
3109      *         SQL <code>NULL</code>, the result is <code>null</code>.
3110      * @throws SQLException if (1) the given column name is not the name of
3111      * a column in this rowset, (2) the cursor is not on one of
3112      * this rowset's rows or its insert row, or (3) the designated
3113      * column does not store an SQL <code>CHAR, VARCHAR, <b>LONGVARCHAR</b>,
3114      * BINARY, VARYBINARY</code> or <code>LONGVARBINARY</code> value.
3115      * The bold SQL type designates the recommended return type.
3116      */
3117     public java.io.Reader getCharacterStream(String columnName) throws SQLException {
3118         return getCharacterStream(getColIdxByName(columnName));
3119     }
3120 
3121     /**
3122      * Retrieves the value of the designated column in the current row
3123      * of this <code>CachedRowSetImpl</code> object as a
3124      * <code>java.math.BigDecimal</code> object.
3125      *
3126      * @param columnIndex the first column is <code>1</code>, the second
3127      *        is <code>2</code>, and so on; must be <code>1</code> or larger
3128      *        and equal to or less than the number of columns in the rowset
3129      * @return a <code>java.math.BigDecimal</code> value with full precision;
3130      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3131      * @throws SQLException if (1) the given column index is out of bounds,
3132      * (2) the cursor is not on one of this rowset's rows or its
3133      * insert row, or (3) the designated column does not store an
3134      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
3135      * FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT, CHAR, VARCHAR</code>
3136      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
3137      * recommended return types that this method is used to retrieve.
3138      * @see #getBigDecimal(String)
3139      */
3140     public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
3141         Object value;
3142 
3143         // sanity check.
3144         checkIndex(columnIndex);
3145         // make sure the cursor is on a valid row
3146         checkCursor();
3147 
3148         setLastValueNull(false);
3149         value = getCurrentRow().getColumnObject(columnIndex);
3150 
3151         // check for SQL NULL
3152         if (value == null) {
3153             setLastValueNull(true);
3154             return null;
3155         }
3156         try {
3157             return (new BigDecimal(value.toString().trim()));
3158         } catch (NumberFormatException ex) {
3159             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.doublefail").toString(),
3160                 new Object[] {value.toString().trim(), columnIndex}));
3161         }
3162     }
3163 
3164     /**
3165      * Retrieves the value of the designated column in the current row
3166      * of this <code>CachedRowSetImpl</code> object as a
3167      * <code>java.math.BigDecimal</code> object.
3168      *
3169      * @param columnName a <code>String</code> object that must match the
3170      *        SQL name of a column in this rowset, ignoring case
3171      * @return a <code>java.math.BigDecimal</code> value with full precision;
3172      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3173      * @throws SQLException if (1) the given column name is not the name of
3174      * a column in this rowset, (2) the cursor is not on one of
3175      * this rowset's rows or its insert row, or (3) the designated
3176      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
3177      * BIGINT, REAL, FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT CHAR,
3178      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
3179      * designates the recommended return type that this method is used to
3180      * retrieve
3181      * @see #getBigDecimal(int)
3182      */
3183     public BigDecimal getBigDecimal(String columnName) throws SQLException {
3184         return getBigDecimal(getColIdxByName(columnName));
3185     }
3186 
3187     //---------------------------------------------------------------------
3188     // Traversal/Positioning
3189     //---------------------------------------------------------------------
3190 
3191     /**
3192      * Returns the number of rows in this <code>CachedRowSetImpl</code> object.
3193      *
3194      * @return number of rows in the rowset
3195      */
3196     public int size() {
3197         return numRows;
3198     }
3199 
3200     /**
3201      * Indicates whether the cursor is before the first row in this
3202      * <code>CachedRowSetImpl</code> object.
3203      *
3204      * @return <code>true</code> if the cursor is before the first row;
3205      *         <code>false</code> otherwise or if the rowset contains no rows
3206      * @throws SQLException if an error occurs
3207      */
3208     public boolean isBeforeFirst() throws SQLException {
3209         if (cursorPos == 0 && numRows > 0) {
3210             return true;
3211         } else {
3212             return false;
3213         }
3214     }
3215 
3216     /**
3217      * Indicates whether the cursor is after the last row in this
3218      * <code>CachedRowSetImpl</code> object.
3219      *
3220      * @return <code>true</code> if the cursor is after the last row;
3221      *         <code>false</code> otherwise or if the rowset contains no rows
3222      * @throws SQLException if an error occurs
3223      */
3224     public boolean isAfterLast() throws SQLException {
3225         if (cursorPos == numRows+1 && numRows > 0) {
3226             return true;
3227         } else {
3228             return false;
3229         }
3230     }
3231 
3232     /**
3233      * Indicates whether the cursor is on the first row in this
3234      * <code>CachedRowSetImpl</code> object.
3235      *
3236      * @return <code>true</code> if the cursor is on the first row;
3237      *         <code>false</code> otherwise or if the rowset contains no rows
3238      * @throws SQLException if an error occurs
3239      */
3240     public boolean isFirst() throws SQLException {
3241         // this becomes nasty because of deletes.
3242         int saveCursorPos = cursorPos;
3243         int saveAbsoluteCursorPos = absolutePos;
3244         internalFirst();
3245         if (cursorPos == saveCursorPos) {
3246             return true;
3247         } else {
3248             cursorPos = saveCursorPos;
3249             absolutePos = saveAbsoluteCursorPos;
3250             return false;
3251         }
3252     }
3253 
3254     /**
3255      * Indicates whether the cursor is on the last row in this
3256      * <code>CachedRowSetImpl</code> object.
3257      * <P>
3258      * Note: Calling the method <code>isLast</code> may be expensive
3259      * because the JDBC driver might need to fetch ahead one row in order
3260      * to determine whether the current row is the last row in this rowset.
3261      *
3262      * @return <code>true</code> if the cursor is on the last row;
3263      *         <code>false</code> otherwise or if this rowset contains no rows
3264      * @throws SQLException if an error occurs
3265      */
3266     public boolean isLast() throws SQLException {
3267         int saveCursorPos = cursorPos;
3268         int saveAbsoluteCursorPos = absolutePos;
3269         boolean saveShowDeleted = getShowDeleted();
3270         setShowDeleted(true);
3271         internalLast();
3272         if (cursorPos == saveCursorPos) {
3273             setShowDeleted(saveShowDeleted);
3274             return true;
3275         } else {
3276             setShowDeleted(saveShowDeleted);
3277             cursorPos = saveCursorPos;
3278             absolutePos = saveAbsoluteCursorPos;
3279             return false;
3280         }
3281     }
3282 
3283     /**
3284      * Moves this <code>CachedRowSetImpl</code> object's cursor to the front of
3285      * the rowset, just before the first row. This method has no effect if
3286      * this rowset contains no rows.
3287      *
3288      * @throws SQLException if an error occurs or the type of this rowset
3289      *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3290      */
3291     public void beforeFirst() throws SQLException {
3292        if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3293             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.beforefirst").toString());
3294         }
3295         cursorPos = 0;
3296         absolutePos = 0;
3297         notifyCursorMoved();
3298     }
3299 
3300     /**
3301      * Moves this <code>CachedRowSetImpl</code> object's cursor to the end of
3302      * the rowset, just after the last row. This method has no effect if
3303      * this rowset contains no rows.
3304      *
3305      * @throws SQLException if an error occurs
3306      */
3307     public void afterLast() throws SQLException {
3308         if (numRows > 0) {
3309             cursorPos = numRows + 1;
3310             absolutePos = 0;
3311             notifyCursorMoved();
3312         }
3313     }
3314 
3315     /**
3316      * Moves this <code>CachedRowSetImpl</code> object's cursor to the first row
3317      * and returns <code>true</code> if the operation was successful.  This
3318      * method also notifies registered listeners that the cursor has moved.
3319      *
3320      * @return <code>true</code> if the cursor is on a valid row;
3321      *         <code>false</code> otherwise or if there are no rows in this
3322      *         <code>CachedRowSetImpl</code> object
3323      * @throws SQLException if the type of this rowset
3324      *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3325      */
3326     public boolean first() throws SQLException {
3327         if(getType() == ResultSet.TYPE_FORWARD_ONLY) {
3328             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.first").toString());
3329         }
3330 
3331         // move and notify
3332         boolean ret = this.internalFirst();
3333         notifyCursorMoved();
3334 
3335         return ret;
3336     }
3337 
3338     /**
3339      * Moves this <code>CachedRowSetImpl</code> object's cursor to the first
3340      * row and returns <code>true</code> if the operation is successful.
3341      * <P>
3342      * This method is called internally by the methods <code>first</code>,
3343      * <code>isFirst</code>, and <code>absolute</code>.
3344      * It in turn calls the method <code>internalNext</code> in order to
3345      * handle the case where the first row is a deleted row that is not visible.
3346      * <p>
3347      * This is a implementation only method and is not required as a standard
3348      * implementation of the <code>CachedRowSet</code> interface.
3349      *
3350      * @return <code>true</code> if the cursor moved to the first row;
3351      *         <code>false</code> otherwise
3352      * @throws SQLException if an error occurs
3353      */
3354     protected boolean internalFirst() throws SQLException {
3355         boolean ret = false;
3356 
3357         if (numRows > 0) {
3358             cursorPos = 1;
3359             if ((getShowDeleted() == false) && (rowDeleted() == true)) {
3360                 ret = internalNext();
3361             } else {
3362                 ret = true;
3363             }
3364         }
3365 
3366         if (ret == true)
3367             absolutePos = 1;
3368         else
3369             absolutePos = 0;
3370 
3371         return ret;
3372     }
3373 
3374     /**
3375      * Moves this <code>CachedRowSetImpl</code> object's cursor to the last row
3376      * and returns <code>true</code> if the operation was successful.  This
3377      * method also notifies registered listeners that the cursor has moved.
3378      *
3379      * @return <code>true</code> if the cursor is on a valid row;
3380      *         <code>false</code> otherwise or if there are no rows in this
3381      *         <code>CachedRowSetImpl</code> object
3382      * @throws SQLException if the type of this rowset
3383      *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3384      */
3385     public boolean last() throws SQLException {
3386         if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3387             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.last").toString());
3388         }
3389 
3390         // move and notify
3391         boolean ret = this.internalLast();
3392         notifyCursorMoved();
3393 
3394         return ret;
3395     }
3396 
3397     /**
3398      * Moves this <code>CachedRowSetImpl</code> object's cursor to the last
3399      * row and returns <code>true</code> if the operation is successful.
3400      * <P>
3401      * This method is called internally by the method <code>last</code>
3402      * when rows have been deleted and the deletions are not visible.
3403      * The method <code>internalLast</code> handles the case where the
3404      * last row is a deleted row that is not visible by in turn calling
3405      * the method <code>internalPrevious</code>.
3406      * <p>
3407      * This is a implementation only method and is not required as a standard
3408      * implementation of the <code>CachedRowSet</code> interface.
3409      *
3410      * @return <code>true</code> if the cursor moved to the last row;
3411      *         <code>false</code> otherwise
3412      * @throws SQLException if an error occurs
3413      */
3414     protected boolean internalLast() throws SQLException {
3415         boolean ret = false;
3416 
3417         if (numRows > 0) {
3418             cursorPos = numRows;
3419             if ((getShowDeleted() == false) && (rowDeleted() == true)) {
3420                 ret = internalPrevious();
3421             } else {
3422                 ret = true;
3423             }
3424         }
3425         if (ret == true)
3426             absolutePos = numRows - numDeleted;
3427         else
3428             absolutePos = 0;
3429         return ret;
3430     }
3431 
3432     /**
3433      * Returns the number of the current row in this <code>CachedRowSetImpl</code>
3434      * object. The first row is number 1, the second number 2, and so on.
3435      *
3436      * @return the number of the current row;  <code>0</code> if there is no
3437      *         current row
3438      * @throws SQLException if an error occurs; or if the <code>CacheRowSetImpl</code>
3439      *         is empty
3440      */
3441     public int getRow() throws SQLException {
3442         // are we on a valid row? Valid rows are between first and last
3443         if (numRows > 0 &&
3444         cursorPos > 0 &&
3445         cursorPos < (numRows + 1) &&
3446         (getShowDeleted() == false && rowDeleted() == false)) {
3447             return absolutePos;
3448         } else if (getShowDeleted() == true) {
3449             return cursorPos;
3450         } else {
3451             return 0;
3452         }
3453     }
3454 
3455     /**
3456      * Moves this <code>CachedRowSetImpl</code> object's cursor to the row number
3457      * specified.
3458      *
3459      * <p>If the number is positive, the cursor moves to an absolute row with
3460      * respect to the beginning of the rowset.  The first row is row 1, the second
3461      * is row 2, and so on.  For example, the following command, in which
3462      * <code>crs</code> is a <code>CachedRowSetImpl</code> object, moves the cursor
3463      * to the fourth row, starting from the beginning of the rowset.
3464      * <PRE><code>
3465      *
3466      *    crs.absolute(4);
3467      *
3468      * </code> </PRE>
3469      * <P>
3470      * If the number is negative, the cursor moves to an absolute row position
3471      * with respect to the end of the rowset.  For example, calling
3472      * <code>absolute(-1)</code> positions the cursor on the last row,
3473      * <code>absolute(-2)</code> moves it on the next-to-last row, and so on.
3474      * If the <code>CachedRowSetImpl</code> object <code>crs</code> has five rows,
3475      * the following command moves the cursor to the fourth-to-last row, which
3476      * in the case of a  rowset with five rows, is also the second row, counting
3477      * from the beginning.
3478      * <PRE><code>
3479      *
3480      *    crs.absolute(-4);
3481      *
3482      * </code> </PRE>
3483      *
3484      * If the number specified is larger than the number of rows, the cursor
3485      * will move to the position after the last row. If the number specified
3486      * would move the cursor one or more rows before the first row, the cursor
3487      * moves to the position before the first row.
3488      * <P>
3489      * Note: Calling <code>absolute(1)</code> is the same as calling the
3490      * method <code>first()</code>.  Calling <code>absolute(-1)</code> is the
3491      * same as calling <code>last()</code>.
3492      *
3493      * @param row a positive number to indicate the row, starting row numbering from
3494      *        the first row, which is <code>1</code>; a negative number to indicate
3495      *        the row, starting row numbering from the last row, which is
3496      *        <code>-1</code>; it must not be <code>0</code>
3497      * @return <code>true</code> if the cursor is on the rowset; <code>false</code>
3498      *         otherwise
3499      * @throws SQLException if the given cursor position is <code>0</code> or the
3500      *            type of this rowset is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3501      */
3502     public boolean absolute( int row ) throws SQLException {
3503         if (row == 0 || getType() == ResultSet.TYPE_FORWARD_ONLY) {
3504             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.absolute").toString());
3505         }
3506 
3507         if (row > 0) { // we are moving foward
3508             if (row > numRows) {
3509                 // fell off the end
3510                 afterLast();
3511                 return false;
3512             } else {
3513                 if (absolutePos <= 0)
3514                     internalFirst();
3515             }
3516         } else { // we are moving backward
3517             if (cursorPos + row < 0) {
3518                 // fell off the front
3519                 beforeFirst();
3520                 return false;
3521             } else {
3522                 if (absolutePos >= 0)
3523                     internalLast();
3524             }
3525         }
3526 
3527         // Now move towards the absolute row that we're looking for
3528         while (absolutePos != row) {
3529             if (absolutePos < row) {
3530                 if (!internalNext())
3531                     break;
3532             }
3533             else {
3534                 if (!internalPrevious())
3535                     break;
3536             }
3537         }
3538 
3539         notifyCursorMoved();
3540 
3541         if (isAfterLast() || isBeforeFirst()) {
3542             return false;
3543         } else {
3544             return true;
3545         }
3546     }
3547 
3548     /**
3549      * Moves the cursor the specified number of rows from the current
3550      * position, with a positive number moving it forward and a
3551      * negative number moving it backward.
3552      * <P>
3553      * If the number is positive, the cursor moves the specified number of
3554      * rows toward the end of the rowset, starting at the current row.
3555      * For example, the following command, in which
3556      * <code>crs</code> is a <code>CachedRowSetImpl</code> object with 100 rows,
3557      * moves the cursor forward four rows from the current row.  If the
3558      * current row is 50, the cursor would move to row 54.
3559      * <PRE><code>
3560      *
3561      *    crs.relative(4);
3562      *
3563      * </code> </PRE>
3564      * <P>
3565      * If the number is negative, the cursor moves back toward the beginning
3566      * the specified number of rows, starting at the current row.
3567      * For example, calling the method
3568      * <code>absolute(-1)</code> positions the cursor on the last row,
3569      * <code>absolute(-2)</code> moves it on the next-to-last row, and so on.
3570      * If the <code>CachedRowSetImpl</code> object <code>crs</code> has five rows,
3571      * the following command moves the cursor to the fourth-to-last row, which
3572      * in the case of a  rowset with five rows, is also the second row
3573      * from the beginning.
3574      * <PRE><code>
3575      *
3576      *    crs.absolute(-4);
3577      *
3578      * </code> </PRE>
3579      *
3580      * If the number specified is larger than the number of rows, the cursor
3581      * will move to the position after the last row. If the number specified
3582      * would move the cursor one or more rows before the first row, the cursor
3583      * moves to the position before the first row. In both cases, this method
3584      * throws an <code>SQLException</code>.
3585      * <P>
3586      * Note: Calling <code>absolute(1)</code> is the same as calling the
3587      * method <code>first()</code>.  Calling <code>absolute(-1)</code> is the
3588      * same as calling <code>last()</code>.  Calling <code>relative(0)</code>
3589      * is valid, but it does not change the cursor position.
3590      *
3591      * @param rows an <code>int</code> indicating the number of rows to move
3592      *             the cursor, starting at the current row; a positive number
3593      *             moves the cursor forward; a negative number moves the cursor
3594      *             backward; must not move the cursor past the valid
3595      *             rows
3596      * @return <code>true</code> if the cursor is on a row in this
3597      *         <code>CachedRowSetImpl</code> object; <code>false</code>
3598      *         otherwise
3599      * @throws SQLException if there are no rows in this rowset, the cursor is
3600      *         positioned either before the first row or after the last row, or
3601      *         the rowset is type <code>ResultSet.TYPE_FORWARD_ONLY</code>
3602      */
3603     public boolean relative(int rows) throws SQLException {
3604         if (numRows == 0 || isBeforeFirst() ||
3605         isAfterLast() || getType() == ResultSet.TYPE_FORWARD_ONLY) {
3606             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.relative").toString());
3607         }
3608 
3609         if (rows == 0) {
3610             return true;
3611         }
3612 
3613         if (rows > 0) { // we are moving forward
3614             if (cursorPos + rows > numRows) {
3615                 // fell off the end
3616                 afterLast();
3617             } else {
3618                 for (int i=0; i < rows; i++) {
3619                     if (!internalNext())
3620                         break;
3621                 }
3622             }
3623         } else { // we are moving backward
3624             if (cursorPos + rows < 0) {
3625                 // fell off the front
3626                 beforeFirst();
3627             } else {
3628                 for (int i=rows; i < 0; i++) {
3629                     if (!internalPrevious())
3630                         break;
3631                 }
3632             }
3633         }
3634         notifyCursorMoved();
3635 
3636         if (isAfterLast() || isBeforeFirst()) {
3637             return false;
3638         } else {
3639             return true;
3640         }
3641     }
3642 
3643     /**
3644      * Moves this <code>CachedRowSetImpl</code> object's cursor to the
3645      * previous row and returns <code>true</code> if the cursor is on
3646      * a valid row or <code>false</code> if it is not.
3647      * This method also notifies all listeners registered with this
3648      * <code>CachedRowSetImpl</code> object that its cursor has moved.
3649      * <P>
3650      * Note: calling the method <code>previous()</code> is not the same
3651      * as calling the method <code>relative(-1)</code>.  This is true
3652      * because it is possible to call <code>previous()</code> from the insert
3653      * row, from after the last row, or from the current row, whereas
3654      * <code>relative</code> may only be called from the current row.
3655      * <P>
3656      * The method <code>previous</code> may used in a <code>while</code>
3657      * loop to iterate through a rowset starting after the last row
3658      * and moving toward the beginning. The loop ends when <code>previous</code>
3659      * returns <code>false</code>, meaning that there are no more rows.
3660      * For example, the following code fragment retrieves all the data in
3661      * the <code>CachedRowSetImpl</code> object <code>crs</code>, which has
3662      * three columns.  Note that the cursor must initially be positioned
3663      * after the last row so that the first call to the method
3664      * <code>previous</code> places the cursor on the last line.
3665      * <PRE> <code>
3666      *
3667      *     crs.afterLast();
3668      *     while (previous()) {
3669      *         String name = crs.getString(1);
3670      *         int age = crs.getInt(2);
3671      *         short ssn = crs.getShort(3);
3672      *         System.out.println(name + "   " + age + "   " + ssn);
3673      *     }
3674      *
3675      * </code> </PRE>
3676      * This method throws an <code>SQLException</code> if the cursor is not
3677      * on a row in the rowset, before the first row, or after the last row.
3678      *
3679      * @return <code>true</code> if the cursor is on a valid row;
3680      *         <code>false</code> if it is before the first row or after the
3681      *         last row
3682      * @throws SQLException if the cursor is not on a valid position or the
3683      *           type of this rowset is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3684      */
3685     public boolean previous() throws SQLException {
3686         if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3687             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.last").toString());
3688         }
3689         /*
3690          * make sure things look sane. The cursor must be
3691          * positioned in the rowset or before first (0) or
3692          * after last (numRows + 1)
3693          */
3694         if (cursorPos < 0 || cursorPos > numRows + 1) {
3695             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
3696         }
3697         // move and notify
3698         boolean ret = this.internalPrevious();
3699         notifyCursorMoved();
3700 
3701         return ret;
3702     }
3703 
3704     /**
3705      * Moves the cursor to the previous row in this <code>CachedRowSetImpl</code>
3706      * object, skipping past deleted rows that are not visible; returns
3707      * <code>true</code> if the cursor is on a row in this rowset and
3708      * <code>false</code> when the cursor goes before the first row.
3709      * <P>
3710      * This method is called internally by the method <code>previous</code>.
3711      * <P>
3712      * This is a implementation only method and is not required as a standard
3713      * implementation of the <code>CachedRowSet</code> interface.
3714      *
3715      * @return <code>true</code> if the cursor is on a row in this rowset;
3716      *         <code>false</code> when the cursor reaches the position before
3717      *         the first row
3718      * @throws SQLException if an error occurs
3719      */
3720     protected boolean internalPrevious() throws SQLException {
3721         boolean ret = false;
3722 
3723         do {
3724             if (cursorPos > 1) {
3725                 --cursorPos;
3726                 ret = true;
3727             } else if (cursorPos == 1) {
3728                 // decrement to before first
3729                 --cursorPos;
3730                 ret = false;
3731                 break;
3732             }
3733         } while ((getShowDeleted() == false) && (rowDeleted() == true));
3734 
3735         /*
3736          * Each call to internalPrevious may move the cursor
3737          * over multiple rows, the absolute postion moves one one row
3738          */
3739         if (ret == true)
3740             --absolutePos;
3741         else
3742             absolutePos = 0;
3743 
3744         return ret;
3745     }
3746 
3747 
3748     //---------------------------------------------------------------------
3749     // Updates
3750     //---------------------------------------------------------------------
3751 
3752     /**
3753      * Indicates whether the current row of this <code>CachedRowSetImpl</code>
3754      * object has been updated.  The value returned
3755      * depends on whether this rowset can detect updates: <code>false</code>
3756      * will always be returned if it does not detect updates.
3757      *
3758      * @return <code>true</code> if the row has been visibly updated
3759      *         by the owner or another and updates are detected;
3760      *         <code>false</code> otherwise
3761      * @throws SQLException if the cursor is on the insert row or not
3762      *            not on a valid row
3763      *
3764      * @see DatabaseMetaData#updatesAreDetected
3765      */
3766     public boolean rowUpdated() throws SQLException {
3767         // make sure the cursor is on a valid row
3768         checkCursor();
3769         if (onInsertRow == true) {
3770             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3771         }
3772         return(((Row)getCurrentRow()).getUpdated());
3773     }
3774 
3775     /**
3776      * Indicates whether the designated column of the current row of
3777      * this <code>CachedRowSetImpl</code> object has been updated. The
3778      * value returned depends on whether this rowset can detcted updates:
3779      * <code>false</code> will always be returned if it does not detect updates.
3780      *
3781      * @param idx the index identifier of the column that may be have been updated.
3782      * @return <code>true</code> is the designated column has been updated
3783      * and the rowset detects updates; <code>false</code> if the rowset has not
3784      * been updated or the rowset does not detect updates
3785      * @throws SQLException if the cursor is on the insert row or not
3786      *          on a valid row
3787      * @see DatabaseMetaData#updatesAreDetected
3788      */
3789     public boolean columnUpdated(int idx) throws SQLException {
3790         // make sure the cursor is on a valid row
3791         checkCursor();
3792         if (onInsertRow == true) {
3793             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3794         }
3795         return (((Row)getCurrentRow()).getColUpdated(idx - 1));
3796     }
3797 
3798     /**
3799      * Indicates whether the designated column of the current row of
3800      * this <code>CachedRowSetImpl</code> object has been updated. The
3801      * value returned depends on whether this rowset can detcted updates:
3802      * <code>false</code> will always be returned if it does not detect updates.
3803      *
3804      * @param columnName the <code>String</code> column name column that may be have
3805      * been updated.
3806      * @return <code>true</code> is the designated column has been updated
3807      * and the rowset detects updates; <code>false</code> if the rowset has not
3808      * been updated or the rowset does not detect updates
3809      * @throws SQLException if the cursor is on the insert row or not
3810      *          on a valid row
3811      * @see DatabaseMetaData#updatesAreDetected
3812      */
3813     public boolean columnUpdated(String columnName) throws SQLException {
3814         return columnUpdated(getColIdxByName(columnName));
3815     }
3816 
3817     /**
3818      * Indicates whether the current row has been inserted.  The value returned
3819      * depends on whether or not the rowset can detect visible inserts.
3820      *
3821      * @return <code>true</code> if a row has been inserted and inserts are detected;
3822      *         <code>false</code> otherwise
3823      * @throws SQLException if the cursor is on the insert row or not
3824      *            not on a valid row
3825      *
3826      * @see DatabaseMetaData#insertsAreDetected
3827      */
3828     public boolean rowInserted() throws SQLException {
3829         // make sure the cursor is on a valid row
3830         checkCursor();
3831         if (onInsertRow == true) {
3832             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3833         }
3834         return(((Row)getCurrentRow()).getInserted());
3835     }
3836 
3837     /**
3838      * Indicates whether the current row has been deleted.  A deleted row
3839      * may leave a visible "hole" in a rowset.  This method can be used to
3840      * detect such holes if the rowset can detect deletions. This method
3841      * will always return <code>false</code> if this rowset cannot detect
3842      * deletions.
3843      *
3844      * @return <code>true</code> if (1)the current row is blank, indicating that
3845      *         the row has been deleted, and (2)deletions are detected;
3846      *         <code>false</code> otherwise
3847      * @throws SQLException if the cursor is on a valid row in this rowset
3848      * @see DatabaseMetaData#deletesAreDetected
3849      */
3850     public boolean rowDeleted() throws SQLException {
3851         // make sure the cursor is on a valid row
3852 
3853         if (isAfterLast() == true ||
3854         isBeforeFirst() == true ||
3855         onInsertRow == true) {
3856 
3857             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
3858         }
3859         return(((Row)getCurrentRow()).getDeleted());
3860     }
3861 
3862     /**
3863      * Indicates whether the given SQL data type is a numberic type.
3864      *
3865      * @param type one of the constants from <code>java.sql.Types</code>
3866      * @return <code>true</code> if the given type is <code>NUMERIC</code>,'
3867      *         <code>DECIMAL</code>, <code>BIT</code>, <code>TINYINT</code>,
3868      *         <code>SMALLINT</code>, <code>INTEGER</code>, <code>BIGINT</code>,
3869      *         <code>REAL</code>, <code>DOUBLE</code>, or <code>FLOAT</code>;
3870      *         <code>false</code> otherwise
3871      */
3872     private boolean isNumeric(int type) {
3873         switch (type) {
3874             case java.sql.Types.NUMERIC:
3875             case java.sql.Types.DECIMAL:
3876             case java.sql.Types.BIT:
3877             case java.sql.Types.TINYINT:
3878             case java.sql.Types.SMALLINT:
3879             case java.sql.Types.INTEGER:
3880             case java.sql.Types.BIGINT:
3881             case java.sql.Types.REAL:
3882             case java.sql.Types.DOUBLE:
3883             case java.sql.Types.FLOAT:
3884                 return true;
3885             default:
3886                 return false;
3887         }
3888     }
3889 
3890     /**
3891      * Indicates whether the given SQL data type is a string type.
3892      *
3893      * @param type one of the constants from <code>java.sql.Types</code>
3894      * @return <code>true</code> if the given type is <code>CHAR</code>,'
3895      *         <code>VARCHAR</code>, or <code>LONGVARCHAR</code>;
3896      *         <code>false</code> otherwise
3897      */
3898     private boolean isString(int type) {
3899         switch (type) {
3900             case java.sql.Types.CHAR:
3901             case java.sql.Types.VARCHAR:
3902             case java.sql.Types.LONGVARCHAR:
3903                 return true;
3904             default:
3905                 return false;
3906         }
3907     }
3908 
3909     /**
3910      * Indicates whether the given SQL data type is a binary type.
3911      *
3912      * @param type one of the constants from <code>java.sql.Types</code>
3913      * @return <code>true</code> if the given type is <code>BINARY</code>,'
3914      *         <code>VARBINARY</code>, or <code>LONGVARBINARY</code>;
3915      *         <code>false</code> otherwise
3916      */
3917     private boolean isBinary(int type) {
3918         switch (type) {
3919             case java.sql.Types.BINARY:
3920             case java.sql.Types.VARBINARY:
3921             case java.sql.Types.LONGVARBINARY:
3922                 return true;
3923             default:
3924                 return false;
3925         }
3926     }
3927 
3928     /**
3929      * Indicates whether the given SQL data type is a temporal type.
3930      * This method is called internally by the conversion methods
3931      * <code>convertNumeric</code> and <code>convertTemporal</code>.
3932      *
3933      * @param type one of the constants from <code>java.sql.Types</code>
3934      * @return <code>true</code> if the given type is <code>DATE</code>,
3935      *         <code>TIME</code>, or <code>TIMESTAMP</code>;
3936      *         <code>false</code> otherwise
3937      */
3938     private boolean isTemporal(int type) {
3939         switch (type) {
3940             case java.sql.Types.DATE:
3941             case java.sql.Types.TIME:
3942             case java.sql.Types.TIMESTAMP:
3943                 return true;
3944             default:
3945                 return false;
3946         }
3947     }
3948 
3949     /**
3950      * Indicates whether the given SQL data type is a boolean type.
3951      * This method is called internally by the conversion methods
3952      * <code>convertNumeric</code> and <code>convertBoolean</code>.
3953      *
3954      * @param type one of the constants from <code>java.sql.Types</code>
3955      * @return <code>true</code> if the given type is <code>BIT</code>,
3956      *         , or <code>BOOLEAN</code>;
3957      *         <code>false</code> otherwise
3958      */
3959     private boolean isBoolean(int type) {
3960         switch (type) {
3961             case java.sql.Types.BIT:
3962             case java.sql.Types.BOOLEAN:
3963                 return true;
3964             default:
3965                 return false;
3966         }
3967     }
3968 
3969 
3970     /**
3971      * Converts the given <code>Object</code> in the Java programming language
3972      * to the standard mapping for the specified SQL target data type.
3973      * The conversion must be to a string or numeric type, but there are no
3974      * restrictions on the type to be converted.  If the source type and target
3975      * type are the same, the given object is simply returned.
3976      *
3977      * @param srcObj the <code>Object</code> in the Java programming language
3978      *               that is to be converted to the target type
3979      * @param srcType the data type that is the standard mapping in SQL of the
3980      *                object to be converted; must be one of the constants in
3981      *                <code>java.sql.Types</code>
3982      * @param trgType the SQL data type to which to convert the given object;
3983      *                must be one of the following constants in
3984      *                <code>java.sql.Types</code>: <code>NUMERIC</code>,
3985      *         <code>DECIMAL</code>, <code>BIT</code>, <code>TINYINT</code>,
3986      *         <code>SMALLINT</code>, <code>INTEGER</code>, <code>BIGINT</code>,
3987      *         <code>REAL</code>, <code>DOUBLE</code>, <code>FLOAT</code>,
3988      *         <code>VARCHAR</code>, <code>LONGVARCHAR</code>, or <code>CHAR</code>
3989      * @return an <code>Object</code> value.that is
3990      *         the standard object mapping for the target SQL type
3991      * @throws SQLException if the given target type is not one of the string or
3992      *         numeric types in <code>java.sql.Types</code>
3993      */
3994     private Object convertNumeric(Object srcObj, int srcType,
3995     int trgType) throws SQLException {
3996 
3997         if (srcType == trgType) {
3998             return srcObj;
3999         }
4000 
4001         if (isNumeric(trgType) == false && isString(trgType) == false) {
4002             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4003         }
4004 
4005         try {
4006             switch (trgType) {
4007                 case java.sql.Types.BIT:
4008                     Integer i = Integer.valueOf(srcObj.toString().trim());
4009                     return i.equals(Integer.valueOf((int)0)) ?
4010                     Boolean.valueOf(false) :
4011                         Boolean.valueOf(true);
4012                 case java.sql.Types.TINYINT:
4013                     return Byte.valueOf(srcObj.toString().trim());
4014                 case java.sql.Types.SMALLINT:
4015                     return Short.valueOf(srcObj.toString().trim());
4016                 case java.sql.Types.INTEGER:
4017                     return Integer.valueOf(srcObj.toString().trim());
4018                 case java.sql.Types.BIGINT:
4019                     return Long.valueOf(srcObj.toString().trim());
4020                 case java.sql.Types.NUMERIC:
4021                 case java.sql.Types.DECIMAL:
4022                     return new BigDecimal(srcObj.toString().trim());
4023                 case java.sql.Types.REAL:
4024                 case java.sql.Types.FLOAT:
4025                     return new Float(srcObj.toString().trim());
4026                 case java.sql.Types.DOUBLE:
4027                     return new Double(srcObj.toString().trim());
4028                 case java.sql.Types.CHAR:
4029                 case java.sql.Types.VARCHAR:
4030                 case java.sql.Types.LONGVARCHAR:
4031                     return srcObj.toString();
4032                 default:
4033                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString()+ trgType);
4034             }
4035         } catch (NumberFormatException ex) {
4036             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4037         }
4038     }
4039 
4040     /**
4041      * Converts the given <code>Object</code> in the Java programming language
4042      * to the standard object mapping for the specified SQL target data type.
4043      * The conversion must be to a string or temporal type, and there are also
4044      * restrictions on the type to be converted.
4045      * <P>
4046      * <TABLE ALIGN="CENTER" BORDER CELLPADDING=10 BORDERCOLOR="#0000FF"
4047      * <CAPTION ALIGN="CENTER"><B>Parameters and Return Values</B></CAPTION>
4048      * <TR>
4049      *   <TD><B>Source SQL Type</B>
4050      *   <TD><B>Target SQL Type</B>
4051      *   <TD><B>Object Returned</B>
4052      * </TR>
4053      * <TR>
4054      *   <TD><code>TIMESTAMP</code>
4055      *   <TD><code>DATE</code>
4056      *   <TD><code>java.sql.Date</code>
4057      * </TR>
4058      * <TR>
4059      *   <TD><code>TIMESTAMP</code>
4060      *   <TD><code>TIME</code>
4061      *   <TD><code>java.sql.Time</code>
4062      * </TR>
4063      * <TR>
4064      *   <TD><code>TIME</code>
4065      *   <TD><code>TIMESTAMP</code>
4066      *   <TD><code>java.sql.Timestamp</code>
4067      * </TR>
4068      * <TR>
4069      *   <TD><code>DATE</code>, <code>TIME</code>, or <code>TIMESTAMP</code>
4070      *   <TD><code>CHAR</code>, <code>VARCHAR</code>, or <code>LONGVARCHAR</code>
4071      *   <TD><code>java.lang.String</code>
4072      * </TR>
4073      * </TABLE>
4074      * <P>
4075      * If the source type and target type are the same,
4076      * the given object is simply returned.
4077      *
4078      * @param srcObj the <code>Object</code> in the Java programming language
4079      *               that is to be converted to the target type
4080      * @param srcType the data type that is the standard mapping in SQL of the
4081      *                object to be converted; must be one of the constants in
4082      *                <code>java.sql.Types</code>
4083      * @param trgType the SQL data type to which to convert the given object;
4084      *                must be one of the following constants in
4085      *                <code>java.sql.Types</code>: <code>DATE</code>,
4086      *         <code>TIME</code>, <code>TIMESTAMP</code>, <code>CHAR</code>,
4087      *         <code>VARCHAR</code>, or <code>LONGVARCHAR</code>
4088      * @return an <code>Object</code> value.that is
4089      *         the standard object mapping for the target SQL type
4090      * @throws SQLException if the given target type is not one of the string or
4091      *         temporal types in <code>java.sql.Types</code>
4092      */
4093     private Object convertTemporal(Object srcObj,
4094     int srcType, int trgType) throws SQLException {
4095 
4096         if (srcType == trgType) {
4097             return srcObj;
4098         }
4099 
4100         if (isNumeric(trgType) == true ||
4101         (isString(trgType) == false && isTemporal(trgType) == false)) {
4102             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4103         }
4104 
4105         try {
4106             switch (trgType) {
4107                 case java.sql.Types.DATE:
4108                     if (srcType == java.sql.Types.TIMESTAMP) {
4109                         return new java.sql.Date(((java.sql.Timestamp)srcObj).getTime());
4110                     } else {
4111                         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4112                     }
4113                 case java.sql.Types.TIMESTAMP:
4114                     if (srcType == java.sql.Types.TIME) {
4115                         return new Timestamp(((java.sql.Time)srcObj).getTime());
4116                     } else {
4117                         return new Timestamp(((java.sql.Date)srcObj).getTime());
4118                     }
4119                 case java.sql.Types.TIME:
4120                     if (srcType == java.sql.Types.TIMESTAMP) {
4121                         return new Time(((java.sql.Timestamp)srcObj).getTime());
4122                     } else {
4123                         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4124                     }
4125                 case java.sql.Types.CHAR:
4126                 case java.sql.Types.VARCHAR:
4127                 case java.sql.Types.LONGVARCHAR:
4128                     return srcObj.toString();
4129                 default:
4130                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4131             }
4132         } catch (NumberFormatException ex) {
4133             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4134         }
4135 
4136     }
4137 
4138     /**
4139      * Converts the given <code>Object</code> in the Java programming language
4140      * to the standard mapping for the specified SQL target data type.
4141      * The conversion must be to a string or numeric type, but there are no
4142      * restrictions on the type to be converted.  If the source type and target
4143      * type are the same, the given object is simply returned.
4144      *
4145      * @param srcObj the <code>Object</code> in the Java programming language
4146      *               that is to be converted to the target type
4147      * @param srcType the data type that is the standard mapping in SQL of the
4148      *                object to be converted; must be one of the constants in
4149      *                <code>java.sql.Types</code>
4150      * @param trgType the SQL data type to which to convert the given object;
4151      *                must be one of the following constants in
4152      *                <code>java.sql.Types</code>: <code>BIT</code>,
4153      *         or <code>BOOLEAN</code>
4154      * @return an <code>Object</code> value.that is
4155      *         the standard object mapping for the target SQL type
4156      * @throws SQLException if the given target type is not one of the Boolean
4157      *         types in <code>java.sql.Types</code>
4158      */
4159     private Object convertBoolean(Object srcObj, int srcType,
4160     int trgType) throws SQLException {
4161 
4162         if (srcType == trgType) {
4163             return srcObj;
4164         }
4165 
4166         if (isNumeric(trgType) == true ||
4167         (isString(trgType) == false && isBoolean(trgType) == false)) {
4168             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4169         }
4170 
4171 
4172         try {
4173             switch (trgType) {
4174                 case java.sql.Types.BIT:
4175                     Integer i = Integer.valueOf(srcObj.toString().trim());
4176                     return i.equals(Integer.valueOf((int)0)) ?
4177                     Boolean.valueOf(false) :
4178                         Boolean.valueOf(true);
4179                 case java.sql.Types.BOOLEAN:
4180                     return Boolean.valueOf(srcObj.toString().trim());
4181                 default:
4182                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString()+ trgType);
4183             }
4184         } catch (NumberFormatException ex) {
4185             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4186         }
4187     }
4188 
4189     /**
4190      * Sets the designated nullable column in the current row or the
4191      * insert row of this <code>CachedRowSetImpl</code> object with
4192      * <code>null</code> value.
4193      * <P>
4194      * This method updates a column value in the current row or the insert
4195      * row of this rowset; however, another method must be called to complete
4196      * the update process. If the cursor is on a row in the rowset, the
4197      * method {@link #updateRow} must be called to mark the row as updated
4198      * and to notify listeners that the row has changed.
4199      * If the cursor is on the insert row, the method {@link #insertRow}
4200      * must be called to insert the new row into this rowset and to notify
4201      * listeners that a row has changed.
4202      * <P>
4203      * In order to propagate updates in this rowset to the underlying
4204      * data source, an application must call the method {@link #acceptChanges}
4205      * after it calls either <code>updateRow</code> or <code>insertRow</code>.
4206      *
4207      * @param columnIndex the first column is <code>1</code>, the second
4208      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4209      *        and equal to or less than the number of columns in this rowset
4210      * @throws SQLException if (1) the given column index is out of bounds,
4211      *            (2) the cursor is not on one of this rowset's rows or its
4212      *            insert row, or (3) this rowset is
4213      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4214      */
4215     public void updateNull(int columnIndex) throws SQLException {
4216         // sanity check.
4217         checkIndex(columnIndex);
4218         // make sure the cursor is on a valid row
4219         checkCursor();
4220 
4221         BaseRow row = getCurrentRow();
4222         row.setColumnObject(columnIndex, null);
4223 
4224     }
4225 
4226     /**
4227      * Sets the designated column in either the current row or the insert
4228      * row of this <code>CachedRowSetImpl</code> object with the given
4229      * <code>boolean</code> value.
4230      * <P>
4231      * This method updates a column value in the current row or the insert
4232      * row of this rowset, but it does not update the database.
4233      * If the cursor is on a row in the rowset, the
4234      * method {@link #updateRow} must be called to update the database.
4235      * If the cursor is on the insert row, the method {@link #insertRow}
4236      * must be called, which will insert the new row into both this rowset
4237      * and the database. Both of these methods must be called before the
4238      * cursor moves to another row.
4239      *
4240      * @param columnIndex the first column is <code>1</code>, the second
4241      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4242      *        and equal to or less than the number of columns in this rowset
4243      * @param x the new column value
4244      * @throws SQLException if (1) the given column index is out of bounds,
4245      *            (2) the cursor is not on one of this rowset's rows or its
4246      *            insert row, or (3) this rowset is
4247      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4248      */
4249     public void updateBoolean(int columnIndex, boolean x) throws SQLException {
4250         // sanity check.
4251         checkIndex(columnIndex);
4252         // make sure the cursor is on a valid row
4253         checkCursor();
4254         Object obj = convertBoolean(Boolean.valueOf(x),
4255         java.sql.Types.BIT,
4256         RowSetMD.getColumnType(columnIndex));
4257 
4258         getCurrentRow().setColumnObject(columnIndex, obj);
4259     }
4260 
4261     /**
4262      * Sets the designated column in either the current row or the insert
4263      * row of this <code>CachedRowSetImpl</code> object with the given
4264      * <code>byte</code> value.
4265      * <P>
4266      * This method updates a column value in the current row or the insert
4267      * row of this rowset, but it does not update the database.
4268      * If the cursor is on a row in the rowset, the
4269      * method {@link #updateRow} must be called to update the database.
4270      * If the cursor is on the insert row, the method {@link #insertRow}
4271      * must be called, which will insert the new row into both this rowset
4272      * and the database. Both of these methods must be called before the
4273      * cursor moves to another row.
4274      *
4275      * @param columnIndex the first column is <code>1</code>, the second
4276      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4277      *        and equal to or less than the number of columns in this rowset
4278      * @param x the new column value
4279      * @throws SQLException if (1) the given column index is out of bounds,
4280      *            (2) the cursor is not on one of this rowset's rows or its
4281      *            insert row, or (3) this rowset is
4282      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4283      */
4284     public void updateByte(int columnIndex, byte x) throws SQLException {
4285         // sanity check.
4286         checkIndex(columnIndex);
4287         // make sure the cursor is on a valid row
4288         checkCursor();
4289 
4290         Object obj = convertNumeric(Byte.valueOf(x),
4291         java.sql.Types.TINYINT,
4292         RowSetMD.getColumnType(columnIndex));
4293 
4294         getCurrentRow().setColumnObject(columnIndex, obj);
4295     }
4296 
4297     /**
4298      * Sets the designated column in either the current row or the insert
4299      * row of this <code>CachedRowSetImpl</code> object with the given
4300      * <code>short</code> value.
4301      * <P>
4302      * This method updates a column value in the current row or the insert
4303      * row of this rowset, but it does not update the database.
4304      * If the cursor is on a row in the rowset, the
4305      * method {@link #updateRow} must be called to update the database.
4306      * If the cursor is on the insert row, the method {@link #insertRow}
4307      * must be called, which will insert the new row into both this rowset
4308      * and the database. Both of these methods must be called before the
4309      * cursor moves to another row.
4310      *
4311      * @param columnIndex the first column is <code>1</code>, the second
4312      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4313      *        and equal to or less than the number of columns in this rowset
4314      * @param x the new column value
4315      * @throws SQLException if (1) the given column index is out of bounds,
4316      *            (2) the cursor is not on one of this rowset's rows or its
4317      *            insert row, or (3) this rowset is
4318      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4319      */
4320     public void updateShort(int columnIndex, short x) throws SQLException {
4321         // sanity check.
4322         checkIndex(columnIndex);
4323         // make sure the cursor is on a valid row
4324         checkCursor();
4325 
4326         Object obj = convertNumeric(Short.valueOf(x),
4327         java.sql.Types.SMALLINT,
4328         RowSetMD.getColumnType(columnIndex));
4329 
4330         getCurrentRow().setColumnObject(columnIndex, obj);
4331     }
4332 
4333     /**
4334      * Sets the designated column in either the current row or the insert
4335      * row of this <code>CachedRowSetImpl</code> object with the given
4336      * <code>int</code> value.
4337      * <P>
4338      * This method updates a column value in the current row or the insert
4339      * row of this rowset, but it does not update the database.
4340      * If the cursor is on a row in the rowset, the
4341      * method {@link #updateRow} must be called to update the database.
4342      * If the cursor is on the insert row, the method {@link #insertRow}
4343      * must be called, which will insert the new row into both this rowset
4344      * and the database. Both of these methods must be called before the
4345      * cursor moves to another row.
4346      *
4347      * @param columnIndex the first column is <code>1</code>, the second
4348      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4349      *        and equal to or less than the number of columns in this rowset
4350      * @param x the new column value
4351      * @throws SQLException if (1) the given column index is out of bounds,
4352      *            (2) the cursor is not on one of this rowset's rows or its
4353      *            insert row, or (3) this rowset is
4354      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4355      */
4356     public void updateInt(int columnIndex, int x) throws SQLException {
4357         // sanity check.
4358         checkIndex(columnIndex);
4359         // make sure the cursor is on a valid row
4360         checkCursor();
4361         Object obj = convertNumeric(Integer.valueOf(x),
4362         java.sql.Types.INTEGER,
4363         RowSetMD.getColumnType(columnIndex));
4364 
4365         getCurrentRow().setColumnObject(columnIndex, obj);
4366     }
4367 
4368     /**
4369      * Sets the designated column in either the current row or the insert
4370      * row of this <code>CachedRowSetImpl</code> object with the given
4371      * <code>long</code> value.
4372      * <P>
4373      * This method updates a column value in the current row or the insert
4374      * row of this rowset, but it does not update the database.
4375      * If the cursor is on a row in the rowset, the
4376      * method {@link #updateRow} must be called to update the database.
4377      * If the cursor is on the insert row, the method {@link #insertRow}
4378      * must be called, which will insert the new row into both this rowset
4379      * and the database. Both of these methods must be called before the
4380      * cursor moves to another row.
4381      *
4382      * @param columnIndex the first column is <code>1</code>, the second
4383      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4384      *        and equal to or less than the number of columns in this rowset
4385      * @param x the new column value
4386      * @throws SQLException if (1) the given column index is out of bounds,
4387      *            (2) the cursor is not on one of this rowset's rows or its
4388      *            insert row, or (3) this rowset is
4389      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4390      */
4391     public void updateLong(int columnIndex, long x) throws SQLException {
4392         // sanity check.
4393         checkIndex(columnIndex);
4394         // make sure the cursor is on a valid row
4395         checkCursor();
4396 
4397         Object obj = convertNumeric(Long.valueOf(x),
4398         java.sql.Types.BIGINT,
4399         RowSetMD.getColumnType(columnIndex));
4400 
4401         getCurrentRow().setColumnObject(columnIndex, obj);
4402 
4403     }
4404 
4405     /**
4406      * Sets the designated column in either the current row or the insert
4407      * row of this <code>CachedRowSetImpl</code> object with the given
4408      * <code>float</code> value.
4409      * <P>
4410      * This method updates a column value in the current row or the insert
4411      * row of this rowset, but it does not update the database.
4412      * If the cursor is on a row in the rowset, the
4413      * method {@link #updateRow} must be called to update the database.
4414      * If the cursor is on the insert row, the method {@link #insertRow}
4415      * must be called, which will insert the new row into both this rowset
4416      * and the database. Both of these methods must be called before the
4417      * cursor moves to another row.
4418      *
4419      * @param columnIndex the first column is <code>1</code>, the second
4420      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4421      *        and equal to or less than the number of columns in this rowset
4422      * @param x the new column value
4423      * @throws SQLException if (1) the given column index is out of bounds,
4424      *            (2) the cursor is not on one of this rowset's rows or its
4425      *            insert row, or (3) this rowset is
4426      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4427      */
4428     public void updateFloat(int columnIndex, float x) throws SQLException {
4429         // sanity check.
4430         checkIndex(columnIndex);
4431         // make sure the cursor is on a valid row
4432         checkCursor();
4433 
4434         Object obj = convertNumeric(new Float(x),
4435         java.sql.Types.REAL,
4436         RowSetMD.getColumnType(columnIndex));
4437 
4438         getCurrentRow().setColumnObject(columnIndex, obj);
4439     }
4440 
4441     /**
4442      * Sets the designated column in either the current row or the insert
4443      * row of this <code>CachedRowSetImpl</code> object with the given
4444      * <code>double</code> value.
4445      *
4446      * This method updates a column value in either the current row or
4447      * the insert row of this rowset, but it does not update the
4448      * database.  If the cursor is on a row in the rowset, the
4449      * method {@link #updateRow} must be called to update the database.
4450      * If the cursor is on the insert row, the method {@link #insertRow}
4451      * must be called, which will insert the new row into both this rowset
4452      * and the database. Both of these methods must be called before the
4453      * cursor moves to another row.
4454      *
4455      * @param columnIndex the first column is <code>1</code>, the second
4456      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4457      *        and equal to or less than the number of columns in this rowset
4458      * @param x the new column value
4459      * @throws SQLException if (1) the given column index is out of bounds,
4460      *            (2) the cursor is not on one of this rowset's rows or its
4461      *            insert row, or (3) this rowset is
4462      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4463      */
4464     public void updateDouble(int columnIndex, double x) throws SQLException {
4465         // sanity check.
4466         checkIndex(columnIndex);
4467         // make sure the cursor is on a valid row
4468         checkCursor();
4469         Object obj = convertNumeric(new Double(x),
4470         java.sql.Types.DOUBLE,
4471         RowSetMD.getColumnType(columnIndex));
4472 
4473         getCurrentRow().setColumnObject(columnIndex, obj);
4474     }
4475 
4476     /**
4477      * Sets the designated column in either the current row or the insert
4478      * row of this <code>CachedRowSetImpl</code> object with the given
4479      * <code>java.math.BigDecimal</code> object.
4480      * <P>
4481      * This method updates a column value in the current row or the insert
4482      * row of this rowset, but it does not update the database.
4483      * If the cursor is on a row in the rowset, the
4484      * method {@link #updateRow} must be called to update the database.
4485      * If the cursor is on the insert row, the method {@link #insertRow}
4486      * must be called, which will insert the new row into both this rowset
4487      * and the database. Both of these methods must be called before the
4488      * cursor moves to another row.
4489      *
4490      * @param columnIndex the first column is <code>1</code>, the second
4491      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4492      *        and equal to or less than the number of columns in this rowset
4493      * @param x the new column value
4494      * @throws SQLException if (1) the given column index is out of bounds,
4495      *            (2) the cursor is not on one of this rowset's rows or its
4496      *            insert row, or (3) this rowset is
4497      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4498      */
4499     public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {
4500         // sanity check.
4501         checkIndex(columnIndex);
4502         // make sure the cursor is on a valid row
4503         checkCursor();
4504 
4505         Object obj = convertNumeric(x,
4506         java.sql.Types.NUMERIC,
4507         RowSetMD.getColumnType(columnIndex));
4508 
4509         getCurrentRow().setColumnObject(columnIndex, obj);
4510     }
4511 
4512     /**
4513      * Sets the designated column in either the current row or the insert
4514      * row of this <code>CachedRowSetImpl</code> object with the given
4515      * <code>String</code> object.
4516      * <P>
4517      * This method updates a column value in either the current row or
4518      * the insert row of this rowset, but it does not update the
4519      * database.  If the cursor is on a row in the rowset, the
4520      * method {@link #updateRow} must be called to mark the row as updated.
4521      * If the cursor is on the insert row, the method {@link #insertRow}
4522      * must be called to insert the new row into this rowset and mark it
4523      * as inserted. Both of these methods must be called before the
4524      * cursor moves to another row.
4525      * <P>
4526      * The method <code>acceptChanges</code> must be called if the
4527      * updated values are to be written back to the underlying database.
4528      *
4529      * @param columnIndex the first column is <code>1</code>, the second
4530      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4531      *        and equal to or less than the number of columns in this rowset
4532      * @param x the new column value
4533      * @throws SQLException if (1) the given column index is out of bounds,
4534      *            (2) the cursor is not on one of this rowset's rows or its
4535      *            insert row, or (3) this rowset is
4536      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4537      */
4538     public void updateString(int columnIndex, String x) throws SQLException {
4539         // sanity check.
4540         checkIndex(columnIndex);
4541         // make sure the cursor is on a valid row
4542         checkCursor();
4543 
4544         getCurrentRow().setColumnObject(columnIndex, x);
4545     }
4546 
4547     /**
4548      * Sets the designated column in either the current row or the insert
4549      * row of this <code>CachedRowSetImpl</code> object with the given
4550      * <code>byte</code> array.
4551      *
4552      * This method updates a column value in either the current row or
4553      * the insert row of this rowset, but it does not update the
4554      * database.  If the cursor is on a row in the rowset, the
4555      * method {@link #updateRow} must be called to update the database.
4556      * If the cursor is on the insert row, the method {@link #insertRow}
4557      * must be called, which will insert the new row into both this rowset
4558      * and the database. Both of these methods must be called before the
4559      * cursor moves to another row.
4560      *
4561      * @param columnIndex the first column is <code>1</code>, the second
4562      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4563      *        and equal to or less than the number of columns in this rowset
4564      * @param x the new column value
4565      * @throws SQLException if (1) the given column index is out of bounds,
4566      *            (2) the cursor is not on one of this rowset's rows or its
4567      *            insert row, or (3) this rowset is
4568      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4569      */
4570     public void updateBytes(int columnIndex, byte x[]) throws SQLException {
4571         // sanity check.
4572         checkIndex(columnIndex);
4573         // make sure the cursor is on a valid row
4574         checkCursor();
4575 
4576         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4577             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4578         }
4579 
4580         getCurrentRow().setColumnObject(columnIndex, x);
4581     }
4582 
4583     /**
4584      * Sets the designated column in either the current row or the insert
4585      * row of this <code>CachedRowSetImpl</code> object with the given
4586      * <code>Date</code> object.
4587      *
4588      * This method updates a column value in either the current row or
4589      * the insert row of this rowset, but it does not update the
4590      * database.  If the cursor is on a row in the rowset, the
4591      * method {@link #updateRow} must be called to update the database.
4592      * If the cursor is on the insert row, the method {@link #insertRow}
4593      * must be called, which will insert the new row into both this rowset
4594      * and the database. Both of these methods must be called before the
4595      * cursor moves to another row.
4596      *
4597      * @param columnIndex the first column is <code>1</code>, the second
4598      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4599      *        and equal to or less than the number of columns in this rowset
4600      * @param x the new column value
4601      * @throws SQLException if (1) the given column index is out of bounds,
4602      *            (2) the cursor is not on one of this rowset's rows or its
4603      *            insert row, (3) the type of the designated column is not
4604      *            an SQL <code>DATE</code> or <code>TIMESTAMP</code>, or
4605      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4606      */
4607     public void updateDate(int columnIndex, java.sql.Date x) throws SQLException {
4608         // sanity check.
4609         checkIndex(columnIndex);
4610         // make sure the cursor is on a valid row
4611         checkCursor();
4612 
4613         Object obj = convertTemporal(x,
4614         java.sql.Types.DATE,
4615         RowSetMD.getColumnType(columnIndex));
4616 
4617         getCurrentRow().setColumnObject(columnIndex, obj);
4618     }
4619 
4620     /**
4621      * Sets the designated column in either the current row or the insert
4622      * row of this <code>CachedRowSetImpl</code> object with the given
4623      * <code>Time</code> object.
4624      *
4625      * This method updates a column value in either the current row or
4626      * the insert row of this rowset, but it does not update the
4627      * database.  If the cursor is on a row in the rowset, the
4628      * method {@link #updateRow} must be called to update the database.
4629      * If the cursor is on the insert row, the method {@link #insertRow}
4630      * must be called, which will insert the new row into both this rowset
4631      * and the database. Both of these methods must be called before the
4632      * cursor moves to another row.
4633      *
4634      * @param columnIndex the first column is <code>1</code>, the second
4635      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4636      *        and equal to or less than the number of columns in this rowset
4637      * @param x the new column value
4638      * @throws SQLException if (1) the given column index is out of bounds,
4639      *            (2) the cursor is not on one of this rowset's rows or its
4640      *            insert row, (3) the type of the designated column is not
4641      *            an SQL <code>TIME</code> or <code>TIMESTAMP</code>, or
4642      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4643      */
4644     public void updateTime(int columnIndex, java.sql.Time x) throws SQLException {
4645         // sanity check.
4646         checkIndex(columnIndex);
4647         // make sure the cursor is on a valid row
4648         checkCursor();
4649 
4650         Object obj = convertTemporal(x,
4651         java.sql.Types.TIME,
4652         RowSetMD.getColumnType(columnIndex));
4653 
4654         getCurrentRow().setColumnObject(columnIndex, obj);
4655     }
4656 
4657     /**
4658      * Sets the designated column in either the current row or the insert
4659      * row of this <code>CachedRowSetImpl</code> object with the given
4660      * <code>Timestamp</code> object.
4661      *
4662      * This method updates a column value in either the current row or
4663      * the insert row of this rowset, but it does not update the
4664      * database.  If the cursor is on a row in the rowset, the
4665      * method {@link #updateRow} must be called to update the database.
4666      * If the cursor is on the insert row, the method {@link #insertRow}
4667      * must be called, which will insert the new row into both this rowset
4668      * and the database. Both of these methods must be called before the
4669      * cursor moves to another row.
4670      *
4671      * @param columnIndex the first column is <code>1</code>, the second
4672      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4673      *        and equal to or less than the number of columns in this rowset
4674      * @param x the new column value
4675      * @throws SQLException if (1) the given column index is out of bounds,
4676      *            (2) the cursor is not on one of this rowset's rows or its
4677      *            insert row, (3) the type of the designated column is not
4678      *            an SQL <code>DATE</code>, <code>TIME</code>, or
4679      *            <code>TIMESTAMP</code>, or (4) this rowset is
4680      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4681      */
4682     public void updateTimestamp(int columnIndex, java.sql.Timestamp x) throws SQLException {
4683         // sanity check.
4684         checkIndex(columnIndex);
4685         // make sure the cursor is on a valid row
4686         checkCursor();
4687 
4688         Object obj = convertTemporal(x,
4689         java.sql.Types.TIMESTAMP,
4690         RowSetMD.getColumnType(columnIndex));
4691 
4692         getCurrentRow().setColumnObject(columnIndex, obj);
4693     }
4694 
4695     /**
4696      * Sets the designated column in either the current row or the insert
4697      * row of this <code>CachedRowSetImpl</code> object with the given
4698      * ASCII stream value.
4699      * <P>
4700      * This method updates a column value in either the current row or
4701      * the insert row of this rowset, but it does not update the
4702      * database.  If the cursor is on a row in the rowset, the
4703      * method {@link #updateRow} must be called to update the database.
4704      * If the cursor is on the insert row, the method {@link #insertRow}
4705      * must be called, which will insert the new row into both this rowset
4706      * and the database. Both of these methods must be called before the
4707      * cursor moves to another row.
4708      *
4709      * @param columnIndex the first column is <code>1</code>, the second
4710      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4711      *        and equal to or less than the number of columns in this rowset
4712      * @param x the new column value
4713      * @param length the number of one-byte ASCII characters in the stream
4714      * @throws SQLException if this method is invoked
4715      */
4716     public void updateAsciiStream(int columnIndex, java.io.InputStream x, int length) throws SQLException {
4717         // sanity Check
4718         checkIndex(columnIndex);
4719         // make sure the cursor is on a valid row
4720         checkCursor();
4721 
4722 
4723         if (isString(RowSetMD.getColumnType(columnIndex)) == false &&
4724         isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4725             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4726         }
4727 
4728         byte buf[] = new byte[length];
4729         try {
4730             int charsRead = 0;
4731             do {
4732                 charsRead += x.read(buf, charsRead, length - charsRead);
4733             } while (charsRead != length);
4734             //Changed the condition check to check for length instead of -1
4735         } catch (java.io.IOException ex) {
4736             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.asciistream").toString());
4737         }
4738         String str = new String(buf);
4739 
4740         getCurrentRow().setColumnObject(columnIndex, str);
4741 
4742     }
4743 
4744     /**
4745      * Sets the designated column in either the current row or the insert
4746      * row of this <code>CachedRowSetImpl</code> object with the given
4747      * <code>java.io.InputStream</code> object.
4748      * <P>
4749      * This method updates a column value in either the current row or
4750      * the insert row of this rowset, but it does not update the
4751      * database.  If the cursor is on a row in the rowset, the
4752      * method {@link #updateRow} must be called to update the database.
4753      * If the cursor is on the insert row, the method {@link #insertRow}
4754      * must be called, which will insert the new row into both this rowset
4755      * and the database. Both of these methods must be called before the
4756      * cursor moves to another row.
4757      *
4758      * @param columnIndex the first column is <code>1</code>, the second
4759      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4760      *        and equal to or less than the number of columns in this rowset
4761      * @param x the new column value; must be a <code>java.io.InputStream</code>
4762      *          containing <code>BINARY</code>, <code>VARBINARY</code>, or
4763      *          <code>LONGVARBINARY</code> data
4764      * @param length the length of the stream in bytes
4765      * @throws SQLException if (1) the given column index is out of bounds,
4766      *            (2) the cursor is not on one of this rowset's rows or its
4767      *            insert row, (3) the data in the stream is not binary, or
4768      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4769      */
4770     public void updateBinaryStream(int columnIndex, java.io.InputStream x,int length) throws SQLException {
4771         // sanity Check
4772         checkIndex(columnIndex);
4773         // make sure the cursor is on a valid row
4774         checkCursor();
4775 
4776         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4777             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4778         }
4779 
4780         byte buf[] = new byte[length];
4781         try {
4782             int bytesRead = 0;
4783             do {
4784                 bytesRead += x.read(buf, bytesRead, length - bytesRead);
4785             } while (bytesRead != -1);
4786         } catch (java.io.IOException ex) {
4787             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.binstream").toString());
4788         }
4789 
4790         getCurrentRow().setColumnObject(columnIndex, buf);
4791     }
4792 
4793     /**
4794      * Sets the designated column in either the current row or the insert
4795      * row of this <code>CachedRowSetImpl</code> object with the given
4796      * <code>java.io.Reader</code> object.
4797      * <P>
4798      * This method updates a column value in either the current row or
4799      * the insert row of this rowset, but it does not update the
4800      * database.  If the cursor is on a row in the rowset, the
4801      * method {@link #updateRow} must be called to update the database.
4802      * If the cursor is on the insert row, the method {@link #insertRow}
4803      * must be called, which will insert the new row into both this rowset
4804      * and the database. Both of these methods must be called before the
4805      * cursor moves to another row.
4806      *
4807      * @param columnIndex the first column is <code>1</code>, the second
4808      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4809      *        and equal to or less than the number of columns in this rowset
4810      * @param x the new column value; must be a <code>java.io.Reader</code>
4811      *          containing <code>BINARY</code>, <code>VARBINARY</code>,
4812      *          <code>LONGVARBINARY</code>, <code>CHAR</code>, <code>VARCHAR</code>,
4813      *          or <code>LONGVARCHAR</code> data
4814      * @param length the length of the stream in characters
4815      * @throws SQLException if (1) the given column index is out of bounds,
4816      *            (2) the cursor is not on one of this rowset's rows or its
4817      *            insert row, (3) the data in the stream is not a binary or
4818      *            character type, or (4) this rowset is
4819      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4820      */
4821     public void updateCharacterStream(int columnIndex, java.io.Reader x, int length) throws SQLException {
4822         // sanity Check
4823         checkIndex(columnIndex);
4824         // make sure the cursor is on a valid row
4825         checkCursor();
4826 
4827         if (isString(RowSetMD.getColumnType(columnIndex)) == false &&
4828         isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4829             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4830         }
4831 
4832         char buf[] = new char[length];
4833         try {
4834             int charsRead = 0;
4835             do {
4836                 charsRead += x.read(buf, charsRead, length - charsRead);
4837             } while (charsRead != length);
4838             //Changed the condition checking to check for length instead of -1
4839         } catch (java.io.IOException ex) {
4840             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.binstream").toString());
4841         }
4842         String str = new String(buf);
4843 
4844         getCurrentRow().setColumnObject(columnIndex, str);
4845     }
4846 
4847     /**
4848      * Sets the designated column in either the current row or the insert
4849      * row of this <code>CachedRowSetImpl</code> object with the given
4850      * <code>Object</code> value.  The <code>scale</code> parameter indicates
4851      * the number of digits to the right of the decimal point and is ignored
4852      * if the new column value is not a type that will be mapped to an SQL
4853      * <code>DECIMAL</code> or <code>NUMERIC</code> value.
4854      * <P>
4855      * This method updates a column value in either the current row or
4856      * the insert row of this rowset, but it does not update the
4857      * database.  If the cursor is on a row in the rowset, the
4858      * method {@link #updateRow} must be called to update the database.
4859      * If the cursor is on the insert row, the method {@link #insertRow}
4860      * must be called, which will insert the new row into both this rowset
4861      * and the database. Both of these methods must be called before the
4862      * cursor moves to another row.
4863      *
4864      * @param columnIndex the first column is <code>1</code>, the second
4865      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4866      *        and equal to or less than the number of columns in this rowset
4867      * @param x the new column value
4868      * @param scale the number of digits to the right of the decimal point (for
4869      *              <code>DECIMAL</code> and <code>NUMERIC</code> types only)
4870      * @throws SQLException if (1) the given column index is out of bounds,
4871      *            (2) the cursor is not on one of this rowset's rows or its
4872      *            insert row, or (3) this rowset is
4873      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4874      */
4875     public void updateObject(int columnIndex, Object x, int scale) throws SQLException {
4876         // sanity check.
4877         checkIndex(columnIndex);
4878         // make sure the cursor is on a valid row
4879         checkCursor();
4880 
4881         int type = RowSetMD.getColumnType(columnIndex);
4882         if (type == Types.DECIMAL || type == Types.NUMERIC) {
4883             ((java.math.BigDecimal)x).setScale(scale);
4884         }
4885         getCurrentRow().setColumnObject(columnIndex, x);
4886     }
4887 
4888     /**
4889      * Sets the designated column in either the current row or the insert
4890      * row of this <code>CachedRowSetImpl</code> object with the given
4891      * <code>Object</code> value.
4892      * <P>
4893      * This method updates a column value in either the current row or
4894      * the insert row of this rowset, but it does not update the
4895      * database.  If the cursor is on a row in the rowset, the
4896      * method {@link #updateRow} must be called to update the database.
4897      * If the cursor is on the insert row, the method {@link #insertRow}
4898      * must be called, which will insert the new row into both this rowset
4899      * and the database. Both of these methods must be called before the
4900      * cursor moves to another row.
4901      *
4902      * @param columnIndex the first column is <code>1</code>, the second
4903      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4904      *        and equal to or less than the number of columns in this rowset
4905      * @param x the new column value
4906      * @throws SQLException if (1) the given column index is out of bounds,
4907      *            (2) the cursor is not on one of this rowset's rows or its
4908      *            insert row, or (3) this rowset is
4909      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4910      */
4911     public void updateObject(int columnIndex, Object x) throws SQLException {
4912         // sanity check.
4913         checkIndex(columnIndex);
4914         // make sure the cursor is on a valid row
4915         checkCursor();
4916 
4917         getCurrentRow().setColumnObject(columnIndex, x);
4918     }
4919 
4920     /**
4921      * Sets the designated nullable column in the current row or the
4922      * insert row of this <code>CachedRowSetImpl</code> object with
4923      * <code>null</code> value.
4924      * <P>
4925      * This method updates a column value in the current row or the insert
4926      * row of this rowset, but it does not update the database.
4927      * If the cursor is on a row in the rowset, the
4928      * method {@link #updateRow} must be called to update the database.
4929      * If the cursor is on the insert row, the method {@link #insertRow}
4930      * must be called, which will insert the new row into both this rowset
4931      * and the database.
4932      *
4933      * @param columnName a <code>String</code> object that must match the
4934      *        SQL name of a column in this rowset, ignoring case
4935      * @throws SQLException if (1) the given column name does not match the
4936      *            name of a column in this rowset, (2) the cursor is not on
4937      *            one of this rowset's rows or its insert row, or (3) this
4938      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4939      */
4940     public void updateNull(String columnName) throws SQLException {
4941         updateNull(getColIdxByName(columnName));
4942     }
4943 
4944     /**
4945      * Sets the designated column in either the current row or the insert
4946      * row of this <code>CachedRowSetImpl</code> object with the given
4947      * <code>boolean</code> value.
4948      * <P>
4949      * This method updates a column value in the current row or the insert
4950      * row of this rowset, but it does not update the database.
4951      * If the cursor is on a row in the rowset, the
4952      * method {@link #updateRow} must be called to update the database.
4953      * If the cursor is on the insert row, the method {@link #insertRow}
4954      * must be called, which will insert the new row into both this rowset
4955      * and the database. Both of these methods must be called before the
4956      * cursor moves to another row.
4957      *
4958      * @param columnName a <code>String</code> object that must match the
4959      *        SQL name of a column in this rowset, ignoring case
4960      * @param x the new column value
4961      * @throws SQLException if (1) the given column name does not match the
4962      *            name of a column in this rowset, (2) the cursor is not on
4963      *            one of this rowset's rows or its insert row, or (3) this
4964      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4965      */
4966     public void updateBoolean(String columnName, boolean x) throws SQLException {
4967         updateBoolean(getColIdxByName(columnName), x);
4968     }
4969 
4970     /**
4971      * Sets the designated column in either the current row or the insert
4972      * row of this <code>CachedRowSetImpl</code> object with the given
4973      * <code>byte</code> value.
4974      * <P>
4975      * This method updates a column value in the current row or the insert
4976      * row of this rowset, but it does not update the database.
4977      * If the cursor is on a row in the rowset, the
4978      * method {@link #updateRow} must be called to update the database.
4979      * If the cursor is on the insert row, the method {@link #insertRow}
4980      * must be called, which will insert the new row into both this rowset
4981      * and the database. Both of these methods must be called before the
4982      * cursor moves to another row.
4983      *
4984      * @param columnName a <code>String</code> object that must match the
4985      *        SQL name of a column in this rowset, ignoring case
4986      * @param x the new column value
4987      * @throws SQLException if (1) the given column name does not match the
4988      *            name of a column in this rowset, (2) the cursor is not on
4989      *            one of this rowset's rows or its insert row, or (3) this
4990      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4991      */
4992     public void updateByte(String columnName, byte x) throws SQLException {
4993         updateByte(getColIdxByName(columnName), x);
4994     }
4995 
4996     /**
4997      * Sets the designated column in either the current row or the insert
4998      * row of this <code>CachedRowSetImpl</code> object with the given
4999      * <code>short</code> value.
5000      * <P>
5001      * This method updates a column value in the current row or the insert
5002      * row of this rowset, but it does not update the database.
5003      * If the cursor is on a row in the rowset, the
5004      * method {@link #updateRow} must be called to update the database.
5005      * If the cursor is on the insert row, the method {@link #insertRow}
5006      * must be called, which will insert the new row into both this rowset
5007      * and the database. Both of these methods must be called before the
5008      * cursor moves to another row.
5009      *
5010      * @param columnName a <code>String</code> object that must match the
5011      *        SQL name of a column in this rowset, ignoring case
5012      * @param x the new column value
5013      * @throws SQLException if (1) the given column name does not match the
5014      *            name of a column in this rowset, (2) the cursor is not on
5015      *            one of this rowset's rows or its insert row, or (3) this
5016      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5017      */
5018     public void updateShort(String columnName, short x) throws SQLException {
5019         updateShort(getColIdxByName(columnName), x);
5020     }
5021 
5022     /**
5023      * Sets the designated column in either the current row or the insert
5024      * row of this <code>CachedRowSetImpl</code> object with the given
5025      * <code>int</code> value.
5026      * <P>
5027      * This method updates a column value in the current row or the insert
5028      * row of this rowset, but it does not update the database.
5029      * If the cursor is on a row in the rowset, the
5030      * method {@link #updateRow} must be called to update the database.
5031      * If the cursor is on the insert row, the method {@link #insertRow}
5032      * must be called, which will insert the new row into both this rowset
5033      * and the database. Both of these methods must be called before the
5034      * cursor moves to another row.
5035      *
5036      * @param columnName a <code>String</code> object that must match the
5037      *        SQL name of a column in this rowset, ignoring case
5038      * @param x the new column value
5039      * @throws SQLException if (1) the given column name does not match the
5040      *            name of a column in this rowset, (2) the cursor is not on
5041      *            one of this rowset's rows or its insert row, or (3) this
5042      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5043      */
5044     public void updateInt(String columnName, int x) throws SQLException {
5045         updateInt(getColIdxByName(columnName), x);
5046     }
5047 
5048     /**
5049      * Sets the designated column in either the current row or the insert
5050      * row of this <code>CachedRowSetImpl</code> object with the given
5051      * <code>long</code> value.
5052      * <P>
5053      * This method updates a column value in the current row or the insert
5054      * row of this rowset, but it does not update the database.
5055      * If the cursor is on a row in the rowset, the
5056      * method {@link #updateRow} must be called to update the database.
5057      * If the cursor is on the insert row, the method {@link #insertRow}
5058      * must be called, which will insert the new row into both this rowset
5059      * and the database. Both of these methods must be called before the
5060      * cursor moves to another row.
5061      *
5062      * @param columnName a <code>String</code> object that must match the
5063      *        SQL name of a column in this rowset, ignoring case
5064      * @param x the new column value
5065      * @throws SQLException if (1) the given column name does not match the
5066      *            name of a column in this rowset, (2) the cursor is not on
5067      *            one of this rowset's rows or its insert row, or (3) this
5068      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5069      */
5070     public void updateLong(String columnName, long x) throws SQLException {
5071         updateLong(getColIdxByName(columnName), x);
5072     }
5073 
5074     /**
5075      * Sets the designated column in either the current row or the insert
5076      * row of this <code>CachedRowSetImpl</code> object with the given
5077      * <code>float</code> value.
5078      * <P>
5079      * This method updates a column value in the current row or the insert
5080      * row of this rowset, but it does not update the database.
5081      * If the cursor is on a row in the rowset, the
5082      * method {@link #updateRow} must be called to update the database.
5083      * If the cursor is on the insert row, the method {@link #insertRow}
5084      * must be called, which will insert the new row into both this rowset
5085      * and the database. Both of these methods must be called before the
5086      * cursor moves to another row.
5087      *
5088      * @param columnName a <code>String</code> object that must match the
5089      *        SQL name of a column in this rowset, ignoring case
5090      * @param x the new column value
5091      * @throws SQLException if (1) the given column name does not match the
5092      *            name of a column in this rowset, (2) the cursor is not on
5093      *            one of this rowset's rows or its insert row, or (3) this
5094      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5095      */
5096     public void updateFloat(String columnName, float x) throws SQLException {
5097         updateFloat(getColIdxByName(columnName), x);
5098     }
5099 
5100     /**
5101      * Sets the designated column in either the current row or the insert
5102      * row of this <code>CachedRowSetImpl</code> object with the given
5103      * <code>double</code> value.
5104      *
5105      * This method updates a column value in either the current row or
5106      * the insert row of this rowset, but it does not update the
5107      * database.  If the cursor is on a row in the rowset, the
5108      * method {@link #updateRow} must be called to update the database.
5109      * If the cursor is on the insert row, the method {@link #insertRow}
5110      * must be called, which will insert the new row into both this rowset
5111      * and the database. Both of these methods must be called before the
5112      * cursor moves to another row.
5113      *
5114      * @param columnName a <code>String</code> object that must match the
5115      *        SQL name of a column in this rowset, ignoring case
5116      * @param x the new column value
5117      * @throws SQLException if (1) the given column name does not match the
5118      *            name of a column in this rowset, (2) the cursor is not on
5119      *            one of this rowset's rows or its insert row, or (3) this
5120      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5121      */
5122     public void updateDouble(String columnName, double x) throws SQLException {
5123         updateDouble(getColIdxByName(columnName), x);
5124     }
5125 
5126     /**
5127      * Sets the designated column in either the current row or the insert
5128      * row of this <code>CachedRowSetImpl</code> object with the given
5129      * <code>java.math.BigDecimal</code> object.
5130      * <P>
5131      * This method updates a column value in the current row or the insert
5132      * row of this rowset, but it does not update the database.
5133      * If the cursor is on a row in the rowset, the
5134      * method {@link #updateRow} must be called to update the database.
5135      * If the cursor is on the insert row, the method {@link #insertRow}
5136      * must be called, which will insert the new row into both this rowset
5137      * and the database. Both of these methods must be called before the
5138      * cursor moves to another row.
5139      *
5140      * @param columnName a <code>String</code> object that must match the
5141      *        SQL name of a column in this rowset, ignoring case
5142      * @param x the new column value
5143      * @throws SQLException if (1) the given column name does not match the
5144      *            name of a column in this rowset, (2) the cursor is not on
5145      *            one of this rowset's rows or its insert row, or (3) this
5146      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5147      */
5148     public void updateBigDecimal(String columnName, BigDecimal x) throws SQLException {
5149         updateBigDecimal(getColIdxByName(columnName), x);
5150     }
5151 
5152     /**
5153      * Sets the designated column in either the current row or the insert
5154      * row of this <code>CachedRowSetImpl</code> object with the given
5155      * <code>String</code> object.
5156      *
5157      * This method updates a column value in either the current row or
5158      * the insert row of this rowset, but it does not update the
5159      * database.  If the cursor is on a row in the rowset, the
5160      * method {@link #updateRow} must be called to update the database.
5161      * If the cursor is on the insert row, the method {@link #insertRow}
5162      * must be called, which will insert the new row into both this rowset
5163      * and the database. Both of these methods must be called before the
5164      * cursor moves to another row.
5165      *
5166      * @param columnName a <code>String</code> object that must match the
5167      *        SQL name of a column in this rowset, ignoring case
5168      * @param x the new column value
5169      * @throws SQLException if (1) the given column name does not match the
5170      *            name of a column in this rowset, (2) the cursor is not on
5171      *            one of this rowset's rows or its insert row, or (3) this
5172      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5173      */
5174     public void updateString(String columnName, String x) throws SQLException {
5175         updateString(getColIdxByName(columnName), x);
5176     }
5177 
5178     /**
5179      * Sets the designated column in either the current row or the insert
5180      * row of this <code>CachedRowSetImpl</code> object with the given
5181      * <code>byte</code> array.
5182      *
5183      * This method updates a column value in either the current row or
5184      * the insert row of this rowset, but it does not update the
5185      * database.  If the cursor is on a row in the rowset, the
5186      * method {@link #updateRow} must be called to update the database.
5187      * If the cursor is on the insert row, the method {@link #insertRow}
5188      * must be called, which will insert the new row into both this rowset
5189      * and the database. Both of these methods must be called before the
5190      * cursor moves to another row.
5191      *
5192      * @param columnName a <code>String</code> object that must match the
5193      *        SQL name of a column in this rowset, ignoring case
5194      * @param x the new column value
5195      * @throws SQLException if (1) the given column name does not match the
5196      *            name of a column in this rowset, (2) the cursor is not on
5197      *            one of this rowset's rows or its insert row, or (3) this
5198      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5199      */
5200     public void updateBytes(String columnName, byte x[]) throws SQLException {
5201         updateBytes(getColIdxByName(columnName), x);
5202     }
5203 
5204     /**
5205      * Sets the designated column in either the current row or the insert
5206      * row of this <code>CachedRowSetImpl</code> object with the given
5207      * <code>Date</code> object.
5208      *
5209      * This method updates a column value in either the current row or
5210      * the insert row of this rowset, but it does not update the
5211      * database.  If the cursor is on a row in the rowset, the
5212      * method {@link #updateRow} must be called to update the database.
5213      * If the cursor is on the insert row, the method {@link #insertRow}
5214      * must be called, which will insert the new row into both this rowset
5215      * and the database. Both of these methods must be called before the
5216      * cursor moves to another row.
5217      *
5218      * @param columnName a <code>String</code> object that must match the
5219      *        SQL name of a column in this rowset, ignoring case
5220      * @param x the new column value
5221      * @throws SQLException if (1) the given column name does not match the
5222      *            name of a column in this rowset, (2) the cursor is not on
5223      *            one of this rowset's rows or its insert row, (3) the type
5224      *            of the designated column is not an SQL <code>DATE</code> or
5225      *            <code>TIMESTAMP</code>, or (4) this rowset is
5226      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5227      */
5228     public void updateDate(String columnName, java.sql.Date x) throws SQLException {
5229         updateDate(getColIdxByName(columnName), x);
5230     }
5231 
5232     /**
5233      * Sets the designated column in either the current row or the insert
5234      * row of this <code>CachedRowSetImpl</code> object with the given
5235      * <code>Time</code> object.
5236      *
5237      * This method updates a column value in either the current row or
5238      * the insert row of this rowset, but it does not update the
5239      * database.  If the cursor is on a row in the rowset, the
5240      * method {@link #updateRow} must be called to update the database.
5241      * If the cursor is on the insert row, the method {@link #insertRow}
5242      * must be called, which will insert the new row into both this rowset
5243      * and the database. Both of these methods must be called before the
5244      * cursor moves to another row.
5245      *
5246      * @param columnName a <code>String</code> object that must match the
5247      *        SQL name of a column in this rowset, ignoring case
5248      * @param x the new column value
5249      * @throws SQLException if (1) the given column name does not match the
5250      *            name of a column in this rowset, (2) the cursor is not on
5251      *            one of this rowset's rows or its insert row, (3) the type
5252      *            of the designated column is not an SQL <code>TIME</code> or
5253      *            <code>TIMESTAMP</code>, or (4) this rowset is
5254      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5255      */
5256     public void updateTime(String columnName, java.sql.Time x) throws SQLException {
5257         updateTime(getColIdxByName(columnName), x);
5258     }
5259 
5260     /**
5261      * Sets the designated column in either the current row or the insert
5262      * row of this <code>CachedRowSetImpl</code> object with the given
5263      * <code>Timestamp</code> object.
5264      *
5265      * This method updates a column value in either the current row or
5266      * the insert row of this rowset, but it does not update the
5267      * database.  If the cursor is on a row in the rowset, the
5268      * method {@link #updateRow} must be called to update the database.
5269      * If the cursor is on the insert row, the method {@link #insertRow}
5270      * must be called, which will insert the new row into both this rowset
5271      * and the database. Both of these methods must be called before the
5272      * cursor moves to another row.
5273      *
5274      * @param columnName a <code>String</code> object that must match the
5275      *        SQL name of a column in this rowset, ignoring case
5276      * @param x the new column value
5277      * @throws SQLException if the given column index is out of bounds or
5278      *            the cursor is not on one of this rowset's rows or its
5279      *            insert row
5280      * @throws SQLException if (1) the given column name does not match the
5281      *            name of a column in this rowset, (2) the cursor is not on
5282      *            one of this rowset's rows or its insert row, (3) the type
5283      *            of the designated column is not an SQL <code>DATE</code>,
5284      *            <code>TIME</code>, or <code>TIMESTAMP</code>, or (4) this
5285      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5286      */
5287     public void updateTimestamp(String columnName, java.sql.Timestamp x) throws SQLException {
5288         updateTimestamp(getColIdxByName(columnName), x);
5289     }
5290 
5291     /**
5292      * Sets the designated column in either the current row or the insert
5293      * row of this <code>CachedRowSetImpl</code> object with the given
5294      * ASCII stream value.
5295      * <P>
5296      * This method updates a column value in either the current row or
5297      * the insert row of this rowset, but it does not update the
5298      * database.  If the cursor is on a row in the rowset, the
5299      * method {@link #updateRow} must be called to update the database.
5300      * If the cursor is on the insert row, the method {@link #insertRow}
5301      * must be called, which will insert the new row into both this rowset
5302      * and the database. Both of these methods must be called before the
5303      * cursor moves to another row.
5304      *
5305      * @param columnName a <code>String</code> object that must match the
5306      *        SQL name of a column in this rowset, ignoring case
5307      * @param x the new column value
5308      * @param length the number of one-byte ASCII characters in the stream
5309      */
5310     public void updateAsciiStream(String columnName,
5311     java.io.InputStream x,
5312     int length) throws SQLException {
5313         updateAsciiStream(getColIdxByName(columnName), x, length);
5314     }
5315 
5316     /**
5317      * Sets the designated column in either the current row or the insert
5318      * row of this <code>CachedRowSetImpl</code> object with the given
5319      * <code>java.io.InputStream</code> object.
5320      * <P>
5321      * This method updates a column value in either the current row or
5322      * the insert row of this rowset, but it does not update the
5323      * database.  If the cursor is on a row in the rowset, the
5324      * method {@link #updateRow} must be called to update the database.
5325      * If the cursor is on the insert row, the method {@link #insertRow}
5326      * must be called, which will insert the new row into both this rowset
5327      * and the database. Both of these methods must be called before the
5328      * cursor moves to another row.
5329      *
5330      * @param columnName a <code>String</code> object that must match the
5331      *        SQL name of a column in this rowset, ignoring case
5332      * @param x the new column value; must be a <code>java.io.InputStream</code>
5333      *          containing <code>BINARY</code>, <code>VARBINARY</code>, or
5334      *          <code>LONGVARBINARY</code> data
5335      * @param length the length of the stream in bytes
5336      * @throws SQLException if (1) the given column name does not match the
5337      *            name of a column in this rowset, (2) the cursor is not on
5338      *            one of this rowset's rows or its insert row, (3) the data
5339      *            in the stream is not binary, or (4) this rowset is
5340      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5341      */
5342     public void updateBinaryStream(String columnName, java.io.InputStream x, int length) throws SQLException {
5343         updateBinaryStream(getColIdxByName(columnName), x, length);
5344     }
5345 
5346     /**
5347      * Sets the designated column in either the current row or the insert
5348      * row of this <code>CachedRowSetImpl</code> object with the given
5349      * <code>java.io.Reader</code> object.
5350      * <P>
5351      * This method updates a column value in either the current row or
5352      * the insert row of this rowset, but it does not update the
5353      * database.  If the cursor is on a row in the rowset, the
5354      * method {@link #updateRow} must be called to update the database.
5355      * If the cursor is on the insert row, the method {@link #insertRow}
5356      * must be called, which will insert the new row into both this rowset
5357      * and the database. Both of these methods must be called before the
5358      * cursor moves to another row.
5359      *
5360      * @param columnName a <code>String</code> object that must match the
5361      *        SQL name of a column in this rowset, ignoring case
5362      * @param reader the new column value; must be a
5363      * <code>java.io.Reader</code> containing <code>BINARY</code>,
5364      * <code>VARBINARY</code>, <code>LONGVARBINARY</code>, <code>CHAR</code>,
5365      * <code>VARCHAR</code>, or <code>LONGVARCHAR</code> data
5366      * @param length the length of the stream in characters
5367      * @throws SQLException if (1) the given column name does not match the
5368      *            name of a column in this rowset, (2) the cursor is not on
5369      *            one of this rowset's rows or its insert row, (3) the data
5370      *            in the stream is not a binary or character type, or (4) this
5371      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5372      */
5373     public void updateCharacterStream(String columnName,
5374     java.io.Reader reader,
5375     int length) throws SQLException {
5376         updateCharacterStream(getColIdxByName(columnName), reader, length);
5377     }
5378 
5379     /**
5380      * Sets the designated column in either the current row or the insert
5381      * row of this <code>CachedRowSetImpl</code> object with the given
5382      * <code>Object</code> value.  The <code>scale</code> parameter
5383      * indicates the number of digits to the right of the decimal point
5384      * and is ignored if the new column value is not a type that will be
5385      *  mapped to an SQL <code>DECIMAL</code> or <code>NUMERIC</code> value.
5386      * <P>
5387      * This method updates a column value in either the current row or
5388      * the insert row of this rowset, but it does not update the
5389      * database.  If the cursor is on a row in the rowset, the
5390      * method {@link #updateRow} must be called to update the database.
5391      * If the cursor is on the insert row, the method {@link #insertRow}
5392      * must be called, which will insert the new row into both this rowset
5393      * and the database. Both of these methods must be called before the
5394      * cursor moves to another row.
5395      *
5396      * @param columnName a <code>String</code> object that must match the
5397      *        SQL name of a column in this rowset, ignoring case
5398      * @param x the new column value
5399      * @param scale the number of digits to the right of the decimal point (for
5400      *              <code>DECIMAL</code> and <code>NUMERIC</code> types only)
5401      * @throws SQLException if (1) the given column name does not match the
5402      *            name of a column in this rowset, (2) the cursor is not on
5403      *            one of this rowset's rows or its insert row, or (3) this
5404      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5405      */
5406     public void updateObject(String columnName, Object x, int scale) throws SQLException {
5407         updateObject(getColIdxByName(columnName), x, scale);
5408     }
5409 
5410     /**
5411      * Sets the designated column in either the current row or the insert
5412      * row of this <code>CachedRowSetImpl</code> object with the given
5413      * <code>Object</code> value.
5414      * <P>
5415      * This method updates a column value in either the current row or
5416      * the insert row of this rowset, but it does not update the
5417      * database.  If the cursor is on a row in the rowset, the
5418      * method {@link #updateRow} must be called to update the database.
5419      * If the cursor is on the insert row, the method {@link #insertRow}
5420      * must be called, which will insert the new row into both this rowset
5421      * and the database. Both of these methods must be called before the
5422      * cursor moves to another row.
5423      *
5424      * @param columnName a <code>String</code> object that must match the
5425      *        SQL name of a column in this rowset, ignoring case
5426      * @param x the new column value
5427      * @throws SQLException if (1) the given column name does not match the
5428      *            name of a column in this rowset, (2) the cursor is not on
5429      *            one of this rowset's rows or its insert row, or (3) this
5430      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5431      */
5432     public void updateObject(String columnName, Object x) throws SQLException {
5433         updateObject(getColIdxByName(columnName), x);
5434     }
5435 
5436     /**
5437      * Inserts the contents of this <code>CachedRowSetImpl</code> object's insert
5438      * row into this rowset immediately following the current row.
5439      * If the current row is the
5440      * position after the last row or before the first row, the new row will
5441      * be inserted at the end of the rowset.  This method also notifies
5442      * listeners registered with this rowset that the row has changed.
5443      * <P>
5444      * The cursor must be on the insert row when this method is called.
5445      *
5446      * @throws SQLException if (1) the cursor is not on the insert row,
5447      *            (2) one or more of the non-nullable columns in the insert
5448      *            row has not been given a value, or (3) this rowset is
5449      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5450      */
5451     public void insertRow() throws SQLException {
5452         int pos;
5453 
5454         if (onInsertRow == false ||
5455             insertRow.isCompleteRow(RowSetMD) == false) {
5456                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.failedins").toString());
5457         }
5458         // Added the setting of parameters that are passed
5459         // to setXXX methods after an empty CRS Object is
5460         // created through RowSetMetaData object
5461         Object [] toInsert = getParams();
5462 
5463         for(int i = 0;i < toInsert.length; i++) {
5464           insertRow.setColumnObject(i+1,toInsert[i]);
5465         }
5466 
5467         Row insRow = new Row(RowSetMD.getColumnCount(),
5468         insertRow.getOrigRow());
5469         insRow.setInserted();
5470         /*
5471          * The new row is inserted into the RowSet
5472          * immediately following the current row.
5473          *
5474          * If we are afterlast then the rows are
5475          * inserted at the end.
5476          */
5477         if (currentRow >= numRows || currentRow < 0) {
5478             pos = numRows;
5479         } else {
5480             pos = currentRow;
5481         }
5482 
5483         rvh.add(pos, insRow);
5484         ++numRows;
5485         // notify the listeners that the row changed.
5486         notifyRowChanged();
5487     }
5488 
5489     /**
5490      * Marks the current row of this <code>CachedRowSetImpl</code> object as
5491      * updated and notifies listeners registered with this rowset that the
5492      * row has changed.
5493      * <P>
5494      * This method  cannot be called when the cursor is on the insert row, and
5495      * it should be called before the cursor moves to another row.  If it is
5496      * called after the cursor moves to another row, this method has no effect,
5497      * and the updates made before the cursor moved will be lost.
5498      *
5499      * @throws SQLException if the cursor is on the insert row or this
5500      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5501      */
5502     public void updateRow() throws SQLException {
5503         // make sure we aren't on the insert row
5504         if (onInsertRow == true) {
5505             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.updateins").toString());
5506         }
5507 
5508         ((Row)getCurrentRow()).setUpdated();
5509 
5510         // notify the listeners that the row changed.
5511         notifyRowChanged();
5512     }
5513 
5514     /**
5515      * Deletes the current row from this <code>CachedRowSetImpl</code> object and
5516      * notifies listeners registered with this rowset that a row has changed.
5517      * This method cannot be called when the cursor is on the insert row.
5518      * <P>
5519      * This method marks the current row as deleted, but it does not delete
5520      * the row from the underlying data source.  The method
5521      * <code>acceptChanges</code> must be called to delete the row in
5522      * the data source.
5523      *
5524      * @throws SQLException if (1) this method is called when the cursor
5525      *            is on the insert row, before the first row, or after the
5526      *            last row or (2) this rowset is
5527      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5528      */
5529     public void deleteRow() throws SQLException {
5530         // make sure the cursor is on a valid row
5531         checkCursor();
5532 
5533         ((Row)getCurrentRow()).setDeleted();
5534         ++numDeleted;
5535 
5536         // notify the listeners that the row changed.
5537         notifyRowChanged();
5538     }
5539 
5540     /**
5541      * Sets the current row with its original value and marks the row as
5542      * not updated, thus undoing any changes made to the row since the
5543      * last call to the methods <code>updateRow</code> or <code>deleteRow</code>.
5544      * This method should be called only when the cursor is on a row in
5545      * this rowset.
5546      *
5547      * @throws SQLException if the cursor is on the insert row, before the
5548      *            first row, or after the last row
5549      */
5550     public void refreshRow() throws SQLException {
5551         // make sure we are on a row
5552         checkCursor();
5553 
5554         // don't want this to happen...
5555         if (onInsertRow == true) {
5556             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
5557         }
5558 
5559         Row currentRow = (Row)getCurrentRow();
5560         // just undo any changes made to this row.
5561         currentRow.clearUpdated();
5562 
5563     }
5564 
5565     /**
5566      * Rolls back any updates made to the current row of this
5567      * <code>CachedRowSetImpl</code> object and notifies listeners that
5568      * a row has changed.  To have an effect, this method
5569      * must be called after an <code>updateXXX</code> method has been
5570      * called and before the method <code>updateRow</code> has been called.
5571      * If no updates have been made or the method <code>updateRow</code>
5572      * has already been called, this method has no effect.
5573      *
5574      * @throws SQLException if the cursor is on the insert row, before the
5575      *            first row, or after the last row
5576      */
5577     public void cancelRowUpdates() throws SQLException {
5578         // make sure we are on a row
5579         checkCursor();
5580 
5581         // don't want this to happen...
5582         if (onInsertRow == true) {
5583             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
5584         }
5585 
5586         Row currentRow = (Row)getCurrentRow();
5587         if (currentRow.getUpdated() == true) {
5588             currentRow.clearUpdated();
5589             notifyRowChanged();
5590         }
5591     }
5592 
5593     /**
5594      * Moves the cursor for this <code>CachedRowSetImpl</code> object
5595      * to the insert row.  The current row in the rowset is remembered
5596      * while the cursor is on the insert row.
5597      * <P>
5598      * The insert row is a special row associated with an updatable
5599      * rowset.  It is essentially a buffer where a new row may
5600      * be constructed by calling the appropriate <code>updateXXX</code>
5601      * methods to assign a value to each column in the row.  A complete
5602      * row must be constructed; that is, every column that is not nullable
5603      * must be assigned a value.  In order for the new row to become part
5604      * of this rowset, the method <code>insertRow</code> must be called
5605      * before the cursor is moved back to the rowset.
5606      * <P>
5607      * Only certain methods may be invoked while the cursor is on the insert
5608      * row; many methods throw an exception if they are called while the
5609      * cursor is there.  In addition to the <code>updateXXX</code>
5610      * and <code>insertRow</code> methods, only the <code>getXXX</code> methods
5611      * may be called when the cursor is on the insert row.  A <code>getXXX</code>
5612      * method should be called on a column only after an <code>updateXXX</code>
5613      * method has been called on that column; otherwise, the value returned is
5614      * undetermined.
5615      *
5616      * @throws SQLException if this <code>CachedRowSetImpl</code> object is
5617      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5618      */
5619     public void moveToInsertRow() throws SQLException {
5620         if (getConcurrency() == ResultSet.CONCUR_READ_ONLY) {
5621             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins").toString());
5622         }
5623         if (insertRow == null) {
5624             if (RowSetMD == null)
5625                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins1").toString());
5626             int numCols = RowSetMD.getColumnCount();
5627             if (numCols > 0) {
5628                 insertRow = new InsertRow(numCols);
5629             } else {
5630                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins2").toString());
5631             }
5632         }
5633         onInsertRow = true;
5634         // %%% setCurrentRow called in BaseRow
5635 
5636         currentRow = cursorPos;
5637         cursorPos = -1;
5638 
5639         insertRow.initInsertRow();
5640     }
5641 
5642     /**
5643      * Moves the cursor for this <code>CachedRowSetImpl</code> object to
5644      * the current row.  The current row is the row the cursor was on
5645      * when the method <code>moveToInsertRow</code> was called.
5646      * <P>
5647      * Calling this method has no effect unless it is called while the
5648      * cursor is on the insert row.
5649      *
5650      * @throws SQLException if an error occurs
5651      */
5652     public void moveToCurrentRow() throws SQLException {
5653         if (onInsertRow == false) {
5654             return;
5655         } else {
5656             cursorPos = currentRow;
5657             onInsertRow = false;
5658         }
5659     }
5660 
5661     /**
5662      * Returns <code>null</code>.
5663      *
5664      * @return <code>null</code>
5665      * @throws SQLException if an error occurs
5666      */
5667     public Statement getStatement() throws SQLException {
5668         return null;
5669     }
5670 
5671     /**
5672      * Retrieves the value of the designated column in this
5673      * <code>CachedRowSetImpl</code> object as an <code>Object</code> in
5674      * the Java programming language, using the given
5675      * <code>java.util.Map</code> object to custom map the value if
5676      * appropriate.
5677      *
5678      * @param columnIndex the first column is <code>1</code>, the second
5679      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5680      *        and equal to or less than the number of columns in this rowset
5681      * @param map a <code>java.util.Map</code> object showing the mapping
5682      *            from SQL type names to classes in the Java programming
5683      *            language
5684      * @return an <code>Object</code> representing the SQL value
5685      * @throws SQLException if the given column index is out of bounds or
5686      *            the cursor is not on one of this rowset's rows or its
5687      *            insert row
5688      */
5689      public Object getObject(int columnIndex,
5690                              java.util.Map<String,Class<?>> map)
5691          throws SQLException
5692      {
5693         Object value;
5694 
5695         // sanity check.
5696         checkIndex(columnIndex);
5697         // make sure the cursor is on a valid row
5698         checkCursor();
5699 
5700         setLastValueNull(false);
5701         value = getCurrentRow().getColumnObject(columnIndex);
5702 
5703         // check for SQL NULL
5704         if (value == null) {
5705             setLastValueNull(true);
5706             return null;
5707         }
5708         if (value instanceof Struct) {
5709             Struct s = (Struct)value;
5710 
5711             // look up the class in the map
5712             Class c = (Class)map.get(s.getSQLTypeName());
5713             if (c != null) {
5714                 // create new instance of the class
5715                 SQLData obj = null;
5716                 try {
5717                     obj = (SQLData)c.newInstance();
5718                 } catch (java.lang.InstantiationException ex) {
5719                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
5720                     ex.getMessage()));
5721                 } catch (java.lang.IllegalAccessException ex) {
5722                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
5723                     ex.getMessage()));
5724                 }
5725                 // get the attributes from the struct
5726                 Object attribs[] = s.getAttributes(map);
5727                 // create the SQLInput "stream"
5728                 SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
5729                 // read the values...
5730                 obj.readSQL(sqlInput, s.getSQLTypeName());
5731                 return (Object)obj;
5732             }
5733         }
5734         return value;
5735     }
5736 
5737     /**
5738      * Retrieves the value of the designated column in this
5739      * <code>CachedRowSetImpl</code> object as a <code>Ref</code> object
5740      * in the Java programming language.
5741      *
5742      * @param columnIndex the first column is <code>1</code>, the second
5743      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5744      *        and equal to or less than the number of columns in this rowset
5745      * @return a <code>Ref</code> object representing an SQL<code> REF</code> value
5746      * @throws SQLException if (1) the given column index is out of bounds,
5747      *            (2) the cursor is not on one of this rowset's rows or its
5748      *            insert row, or (3) the designated column does not store an
5749      *            SQL <code>REF</code> value
5750      * @see #getRef(String)
5751      */
5752     public Ref getRef(int columnIndex) throws SQLException {
5753         Ref value;
5754 
5755         // sanity check.
5756         checkIndex(columnIndex);
5757         // make sure the cursor is on a valid row
5758         checkCursor();
5759 
5760         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.REF) {
5761             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5762         }
5763 
5764         setLastValueNull(false);
5765         value = (Ref)(getCurrentRow().getColumnObject(columnIndex));
5766 
5767         // check for SQL NULL
5768         if (value == null) {
5769             setLastValueNull(true);
5770             return null;
5771         }
5772 
5773         return value;
5774     }
5775 
5776     /**
5777      * Retrieves the value of the designated column in this
5778      * <code>CachedRowSetImpl</code> object as a <code>Blob</code> object
5779      * in the Java programming language.
5780      *
5781      * @param columnIndex the first column is <code>1</code>, the second
5782      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5783      *        and equal to or less than the number of columns in this rowset
5784      * @return a <code>Blob</code> object representing an SQL <code>BLOB</code> value
5785      * @throws SQLException if (1) the given column index is out of bounds,
5786      *            (2) the cursor is not on one of this rowset's rows or its
5787      *            insert row, or (3) the designated column does not store an
5788      *            SQL <code>BLOB</code> value
5789      * @see #getBlob(String)
5790      */
5791     public Blob getBlob(int columnIndex) throws SQLException {
5792         Blob value;
5793 
5794         // sanity check.
5795         checkIndex(columnIndex);
5796         // make sure the cursor is on a valid row
5797         checkCursor();
5798 
5799         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.BLOB) {
5800             System.out.println(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.type").toString(), RowSetMD.getColumnType(columnIndex)));
5801             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5802         }
5803 
5804         setLastValueNull(false);
5805         value = (Blob)(getCurrentRow().getColumnObject(columnIndex));
5806 
5807         // check for SQL NULL
5808         if (value == null) {
5809             setLastValueNull(true);
5810             return null;
5811         }
5812 
5813         return value;
5814     }
5815 
5816     /**
5817      * Retrieves the value of the designated column in this
5818      * <code>CachedRowSetImpl</code> object as a <code>Clob</code> object
5819      * in the Java programming language.
5820      *
5821      * @param columnIndex the first column is <code>1</code>, the second
5822      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5823      *        and equal to or less than the number of columns in this rowset
5824      * @return a <code>Clob</code> object representing an SQL <code>CLOB</code> value
5825      * @throws SQLException if (1) the given column index is out of bounds,
5826      *            (2) the cursor is not on one of this rowset's rows or its
5827      *            insert row, or (3) the designated column does not store an
5828      *            SQL <code>CLOB</code> value
5829      * @see #getClob(String)
5830      */
5831     public Clob getClob(int columnIndex) throws SQLException {
5832         Clob value;
5833 
5834         // sanity check.
5835         checkIndex(columnIndex);
5836         // make sure the cursor is on a valid row
5837         checkCursor();
5838 
5839         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.CLOB) {
5840             System.out.println(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.type").toString(), RowSetMD.getColumnType(columnIndex)));
5841             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5842         }
5843 
5844         setLastValueNull(false);
5845         value = (Clob)(getCurrentRow().getColumnObject(columnIndex));
5846 
5847         // check for SQL NULL
5848         if (value == null) {
5849             setLastValueNull(true);
5850             return null;
5851         }
5852 
5853         return value;
5854     }
5855 
5856     /**
5857      * Retrieves the value of the designated column in this
5858      * <code>CachedRowSetImpl</code> object as an <code>Array</code> object
5859      * in the Java programming language.
5860      *
5861      * @param columnIndex the first column is <code>1</code>, the second
5862      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5863      *        and equal to or less than the number of columns in this rowset
5864      * @return an <code>Array</code> object representing an SQL
5865      *         <code>ARRAY</code> value
5866      * @throws SQLException if (1) the given column index is out of bounds,
5867      *            (2) the cursor is not on one of this rowset's rows or its
5868      *            insert row, or (3) the designated column does not store an
5869      *            SQL <code>ARRAY</code> value
5870      * @see #getArray(String)
5871      */
5872     public Array getArray(int columnIndex) throws SQLException {
5873         java.sql.Array value;
5874 
5875         // sanity check.
5876         checkIndex(columnIndex);
5877         // make sure the cursor is on a valid row
5878         checkCursor();
5879 
5880         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.ARRAY) {
5881             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5882         }
5883 
5884         setLastValueNull(false);
5885         value = (java.sql.Array)(getCurrentRow().getColumnObject(columnIndex));
5886 
5887         // check for SQL NULL
5888         if (value == null) {
5889             setLastValueNull(true);
5890             return null;
5891         }
5892 
5893         return value;
5894     }
5895 
5896     /**
5897      * Retrieves the value of the designated column in this
5898      * <code>CachedRowSetImpl</code> object as an <code>Object</code> in
5899      * the Java programming language, using the given
5900      * <code>java.util.Map</code> object to custom map the value if
5901      * appropriate.
5902      *
5903      * @param columnName a <code>String</code> object that must match the
5904      *        SQL name of a column in this rowset, ignoring case
5905      * @param map a <code>java.util.Map</code> object showing the mapping
5906      *        from SQL type names to classes in the Java programming
5907      *        language
5908      * @return an <code>Object</code> representing the SQL value
5909      * @throws SQLException if the given column name is not the name of
5910      *         a column in this rowset or the cursor is not on one of
5911      *         this rowset's rows or its insert row
5912      */
5913     public Object getObject(String columnName,
5914                             java.util.Map<String,Class<?>> map)
5915     throws SQLException {
5916         return getObject(getColIdxByName(columnName), map);
5917     }
5918 
5919     /**
5920      * Retrieves the value of the designated column in this
5921      * <code>CachedRowSetImpl</code> object as a <code>Ref</code> object
5922      * in the Java programming language.
5923      *
5924      * @param colName a <code>String</code> object that must match the
5925      *        SQL name of a column in this rowset, ignoring case
5926      * @return a <code>Ref</code> object representing an SQL<code> REF</code> value
5927      * @throws SQLException  if (1) the given column name is not the name of
5928      *            a column in this rowset, (2) the cursor is not on one of
5929      *            this rowset's rows or its insert row, or (3) the column value
5930      *            is not an SQL <code>REF</code> value
5931      * @see #getRef(int)
5932      */
5933     public Ref getRef(String colName) throws SQLException {
5934         return getRef(getColIdxByName(colName));
5935     }
5936 
5937     /**
5938      * Retrieves the value of the designated column in this
5939      * <code>CachedRowSetImpl</code> object as a <code>Blob</code> object
5940      * in the Java programming language.
5941      *
5942      * @param colName a <code>String</code> object that must match the
5943      *        SQL name of a column in this rowset, ignoring case
5944      * @return a <code>Blob</code> object representing an SQL <code>BLOB</code> value
5945      * @throws SQLException if (1) the given column name is not the name of
5946      *            a column in this rowset, (2) the cursor is not on one of
5947      *            this rowset's rows or its insert row, or (3) the designated
5948      *            column does not store an SQL <code>BLOB</code> value
5949      * @see #getBlob(int)
5950      */
5951     public Blob getBlob(String colName) throws SQLException {
5952         return getBlob(getColIdxByName(colName));
5953     }
5954 
5955     /**
5956      * Retrieves the value of the designated column in this
5957      * <code>CachedRowSetImpl</code> object as a <code>Clob</code> object
5958      * in the Java programming language.
5959      *
5960      * @param colName a <code>String</code> object that must match the
5961      *        SQL name of a column in this rowset, ignoring case
5962      * @return a <code>Clob</code> object representing an SQL
5963      *         <code>CLOB</code> value
5964      * @throws SQLException if (1) the given column name is not the name of
5965      *            a column in this rowset, (2) the cursor is not on one of
5966      *            this rowset's rows or its insert row, or (3) the designated
5967      *            column does not store an SQL <code>CLOB</code> value
5968      * @see #getClob(int)
5969      */
5970     public Clob getClob(String colName) throws SQLException {
5971         return getClob(getColIdxByName(colName));
5972     }
5973 
5974     /**
5975      * Retrieves the value of the designated column in this
5976      * <code>CachedRowSetImpl</code> object as an <code>Array</code> object
5977      * in the Java programming langugage.
5978      *
5979      * @param colName a <code>String</code> object that must match the
5980      *        SQL name of a column in this rowset, ignoring case
5981      * @return an <code>Array</code> object representing an SQL
5982      *         <code>ARRAY</code> value
5983      * @throws SQLException if (1) the given column name is not the name of
5984      *            a column in this rowset, (2) the cursor is not on one of
5985      *            this rowset's rows or its insert row, or (3) the designated
5986      *            column does not store an SQL <code>ARRAY</code> value
5987      * @see #getArray(int)
5988      */
5989     public Array getArray(String colName) throws SQLException {
5990         return getArray(getColIdxByName(colName));
5991     }
5992 
5993     /**
5994      * Retrieves the value of the designated column in the current row
5995      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Date</code>
5996      * object, using the given <code>Calendar</code> object to construct an
5997      * appropriate millisecond value for the date.
5998      *
5999      * @param columnIndex the first column is <code>1</code>, the second
6000      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6001      *        and equal to or less than the number of columns in the rowset
6002      * @param cal the <code>java.util.Calendar</code> object to use in
6003      *            constructing the date
6004      * @return the column value; if the value is SQL <code>NULL</code>,
6005      *         the result is <code>null</code>
6006      * @throws SQLException if (1) the given column name is not the name of
6007      *            a column in this rowset, (2) the cursor is not on one of
6008      *            this rowset's rows or its insert row, or (3) the designated
6009      *            column does not store an SQL <code>DATE</code> or
6010      *            <code>TIMESTAMP</code> value
6011      */
6012     public java.sql.Date getDate(int columnIndex, Calendar cal) throws SQLException {
6013         Object value;
6014 
6015         // sanity check.
6016         checkIndex(columnIndex);
6017         // make sure the cursor is on a valid row
6018         checkCursor();
6019 
6020         setLastValueNull(false);
6021         value = getCurrentRow().getColumnObject(columnIndex);
6022 
6023         // check for SQL NULL
6024         if (value == null) {
6025             setLastValueNull(true);
6026             return null;
6027         }
6028 
6029         value = convertTemporal(value,
6030         RowSetMD.getColumnType(columnIndex),
6031         java.sql.Types.DATE);
6032 
6033         // create a default calendar
6034         Calendar defaultCal = Calendar.getInstance();
6035         // set this Calendar to the time we have
6036         defaultCal.setTime((java.util.Date)value);
6037 
6038         /*
6039          * Now we can pull the pieces of the date out
6040          * of the default calendar and put them into
6041          * the user provided calendar
6042          */
6043         cal.set(Calendar.YEAR, defaultCal.get(Calendar.YEAR));
6044         cal.set(Calendar.MONTH, defaultCal.get(Calendar.MONTH));
6045         cal.set(Calendar.DAY_OF_MONTH, defaultCal.get(Calendar.DAY_OF_MONTH));
6046 
6047         /*
6048          * This looks a little odd but it is correct -
6049          * Calendar.getTime() returns a Date...
6050          */
6051         return new java.sql.Date(cal.getTime().getTime());
6052     }
6053 
6054     /**
6055      * Retrieves the value of the designated column in the current row
6056      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Date</code>
6057      * object, using the given <code>Calendar</code> object to construct an
6058      * appropriate millisecond value for the date.
6059      *
6060      * @param columnName a <code>String</code> object that must match the
6061      *        SQL name of a column in this rowset, ignoring case
6062      * @param cal the <code>java.util.Calendar</code> object to use in
6063      *            constructing the date
6064      * @return the column value; if the value is SQL <code>NULL</code>,
6065      *         the result is <code>null</code>
6066      * @throws SQLException if (1) the given column name is not the name of
6067      *            a column in this rowset, (2) the cursor is not on one of
6068      *            this rowset's rows or its insert row, or (3) the designated
6069      *            column does not store an SQL <code>DATE</code> or
6070      *            <code>TIMESTAMP</code> value
6071      */
6072     public java.sql.Date getDate(String columnName, Calendar cal) throws SQLException {
6073         return getDate(getColIdxByName(columnName), cal);
6074     }
6075 
6076     /**
6077      * Retrieves the value of the designated column in the current row
6078      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Time</code>
6079      * object, using the given <code>Calendar</code> object to construct an
6080      * appropriate millisecond value for the date.
6081      *
6082      * @param columnIndex the first column is <code>1</code>, the second
6083      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6084      *        and equal to or less than the number of columns in the rowset
6085      * @param cal the <code>java.util.Calendar</code> object to use in
6086      *            constructing the date
6087      * @return the column value; if the value is SQL <code>NULL</code>,
6088      *         the result is <code>null</code>
6089      * @throws SQLException if (1) the given column name is not the name of
6090      *            a column in this rowset, (2) the cursor is not on one of
6091      *            this rowset's rows or its insert row, or (3) the designated
6092      *            column does not store an SQL <code>TIME</code> or
6093      *            <code>TIMESTAMP</code> value
6094      */
6095     public java.sql.Time getTime(int columnIndex, Calendar cal) throws SQLException {
6096         Object value;
6097 
6098         // sanity check.
6099         checkIndex(columnIndex);
6100         // make sure the cursor is on a valid row
6101         checkCursor();
6102 
6103         setLastValueNull(false);
6104         value = getCurrentRow().getColumnObject(columnIndex);
6105 
6106         // check for SQL NULL
6107         if (value == null) {
6108             setLastValueNull(true);
6109             return null;
6110         }
6111 
6112         value = convertTemporal(value,
6113         RowSetMD.getColumnType(columnIndex),
6114         java.sql.Types.TIME);
6115 
6116         // create a default calendar
6117         Calendar defaultCal = Calendar.getInstance();
6118         // set the time in the default calendar
6119         defaultCal.setTime((java.util.Date)value);
6120 
6121         /*
6122          * Now we can pull the pieces of the date out
6123          * of the default calendar and put them into
6124          * the user provided calendar
6125          */
6126         cal.set(Calendar.HOUR_OF_DAY, defaultCal.get(Calendar.HOUR_OF_DAY));
6127         cal.set(Calendar.MINUTE, defaultCal.get(Calendar.MINUTE));
6128         cal.set(Calendar.SECOND, defaultCal.get(Calendar.SECOND));
6129 
6130         return new java.sql.Time(cal.getTime().getTime());
6131     }
6132 
6133     /**
6134      * Retrieves the value of the designated column in the current row
6135      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Time</code>
6136      * object, using the given <code>Calendar</code> object to construct an
6137      * appropriate millisecond value for the date.
6138      *
6139      * @param columnName a <code>String</code> object that must match the
6140      *        SQL name of a column in this rowset, ignoring case
6141      * @param cal the <code>java.util.Calendar</code> object to use in
6142      *            constructing the date
6143      * @return the column value; if the value is SQL <code>NULL</code>,
6144      *         the result is <code>null</code>
6145      * @throws SQLException if (1) the given column name is not the name of
6146      *            a column in this rowset, (2) the cursor is not on one of
6147      *            this rowset's rows or its insert row, or (3) the designated
6148      *            column does not store an SQL <code>TIME</code> or
6149      *            <code>TIMESTAMP</code> value
6150      */
6151     public java.sql.Time getTime(String columnName, Calendar cal) throws SQLException {
6152         return getTime(getColIdxByName(columnName), cal);
6153     }
6154 
6155     /**
6156      * Retrieves the value of the designated column in the current row
6157      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Timestamp</code>
6158      * object, using the given <code>Calendar</code> object to construct an
6159      * appropriate millisecond value for the date.
6160      *
6161      * @param columnIndex the first column is <code>1</code>, the second
6162      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6163      *        and equal to or less than the number of columns in the rowset
6164      * @param cal the <code>java.util.Calendar</code> object to use in
6165      *            constructing the date
6166      * @return the column value; if the value is SQL <code>NULL</code>,
6167      *         the result is <code>null</code>
6168      * @throws SQLException if (1) the given column name is not the name of
6169      *            a column in this rowset, (2) the cursor is not on one of
6170      *            this rowset's rows or its insert row, or (3) the designated
6171      *            column does not store an SQL <code>TIME</code> or
6172      *            <code>TIMESTAMP</code> value
6173      */
6174     public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
6175         Object value;
6176 
6177         // sanity check.
6178         checkIndex(columnIndex);
6179         // make sure the cursor is on a valid row
6180         checkCursor();
6181 
6182         setLastValueNull(false);
6183         value = getCurrentRow().getColumnObject(columnIndex);
6184 
6185         // check for SQL NULL
6186         if (value == null) {
6187             setLastValueNull(true);
6188             return null;
6189         }
6190 
6191         value = convertTemporal(value,
6192         RowSetMD.getColumnType(columnIndex),
6193         java.sql.Types.TIMESTAMP);
6194 
6195         // create a default calendar
6196         Calendar defaultCal = Calendar.getInstance();
6197         // set the time in the default calendar
6198         defaultCal.setTime((java.util.Date)value);
6199 
6200         /*
6201          * Now we can pull the pieces of the date out
6202          * of the default calendar and put them into
6203          * the user provided calendar
6204          */
6205         cal.set(Calendar.YEAR, defaultCal.get(Calendar.YEAR));
6206         cal.set(Calendar.MONTH, defaultCal.get(Calendar.MONTH));
6207         cal.set(Calendar.DAY_OF_MONTH, defaultCal.get(Calendar.DAY_OF_MONTH));
6208         cal.set(Calendar.HOUR_OF_DAY, defaultCal.get(Calendar.HOUR_OF_DAY));
6209         cal.set(Calendar.MINUTE, defaultCal.get(Calendar.MINUTE));
6210         cal.set(Calendar.SECOND, defaultCal.get(Calendar.SECOND));
6211 
6212         return new java.sql.Timestamp(cal.getTime().getTime());
6213     }
6214 
6215     /**
6216      * Retrieves the value of the designated column in the current row
6217      * of this <code>CachedRowSetImpl</code> object as a
6218      * <code>java.sql.Timestamp</code> object, using the given
6219      * <code>Calendar</code> object to construct an appropriate
6220      * millisecond value for the date.
6221      *
6222      * @param columnName a <code>String</code> object that must match the
6223      *        SQL name of a column in this rowset, ignoring case
6224      * @param cal the <code>java.util.Calendar</code> object to use in
6225      *            constructing the date
6226      * @return the column value; if the value is SQL <code>NULL</code>,
6227      *         the result is <code>null</code>
6228      * @throws SQLException if (1) the given column name is not the name of
6229      *            a column in this rowset, (2) the cursor is not on one of
6230      *            this rowset's rows or its insert row, or (3) the designated
6231      *            column does not store an SQL <code>DATE</code>,
6232      *            <code>TIME</code>, or <code>TIMESTAMP</code> value
6233      */
6234     public java.sql.Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException {
6235         return getTimestamp(getColIdxByName(columnName), cal);
6236     }
6237 
6238     /*
6239      * RowSetInternal Interface
6240      */
6241 
6242     /**
6243      * Retrieves the <code>Connection</code> object passed to this
6244      * <code>CachedRowSetImpl</code> object.  This connection may be
6245      * used to populate this rowset with data or to write data back
6246      * to its underlying data source.
6247      *
6248      * @return the <code>Connection</code> object passed to this rowset;
6249      *         may be <code>null</code> if there is no connection
6250      * @throws SQLException if an error occurs
6251      */
6252     public Connection getConnection() throws SQLException{
6253         return conn;
6254     }
6255 
6256     /**
6257      * Sets the metadata for this <code>CachedRowSetImpl</code> object
6258      * with the given <code>RowSetMetaData</code> object.
6259      *
6260      * @param md a <code>RowSetMetaData</code> object instance containing
6261      *            metadata about the columsn in the rowset
6262      * @throws SQLException if invalid meta data is supplied to the
6263      *            rowset
6264      */
6265     public void setMetaData(RowSetMetaData md) throws SQLException {
6266         RowSetMD =(RowSetMetaDataImpl) md;
6267     }
6268 
6269     /**
6270      * Returns a result set containing the original value of the rowset. The
6271      * original value is the state of the <code>CachedRowSetImpl</code> after the
6272      * last population or synchronization (whichever occured most recently) with
6273      * the data source.
6274      * <p>
6275      * The cursor is positioned before the first row in the result set.
6276      * Only rows contained in the result set returned by <code>getOriginal()</code>
6277      * are said to have an original value.
6278      *
6279      * @return the original result set of the rowset
6280      * @throws SQLException if an error occurs produce the
6281      *           <code>ResultSet</code> object
6282      */
6283     public ResultSet getOriginal() throws SQLException {
6284         CachedRowSetImpl crs = new CachedRowSetImpl();
6285         crs.RowSetMD = RowSetMD;
6286         crs.numRows = numRows;
6287         crs.cursorPos = 0;
6288 
6289         // make sure we don't get someone playing with these
6290         // %%% is this now necessary ???
6291         //crs.setReader(null);
6292         //crs.setWriter(null);
6293         int colCount = RowSetMD.getColumnCount();
6294         Row orig;
6295 
6296         for (Iterator i = rvh.iterator(); i.hasNext();) {
6297             orig = new Row(colCount, ((Row)i.next()).getOrigRow());
6298             crs.rvh.add(orig);
6299         }
6300         return (ResultSet)crs;
6301     }
6302 
6303     /**
6304      * Returns a result set containing the original value of the current
6305      * row only.
6306      * The original value is the state of the <code>CachedRowSetImpl</code> after
6307      * the last population or synchronization (whichever occured most recently)
6308      * with the data source.
6309      *
6310      * @return the original result set of the row
6311      * @throws SQLException if there is no current row
6312      * @see #setOriginalRow
6313      */
6314     public ResultSet getOriginalRow() throws SQLException {
6315         CachedRowSetImpl crs = new CachedRowSetImpl();
6316         crs.RowSetMD = RowSetMD;
6317         crs.numRows = 1;
6318         crs.cursorPos = 0;
6319         crs.setTypeMap(this.getTypeMap());
6320 
6321         // make sure we don't get someone playing with these
6322         // %%% is this now necessary ???
6323         //crs.setReader(null);
6324         //crs.setWriter(null);
6325 
6326         Row orig = new Row(RowSetMD.getColumnCount(),
6327         getCurrentRow().getOrigRow());
6328 
6329         crs.rvh.add(orig);
6330 
6331         return (ResultSet)crs;
6332 
6333     }
6334 
6335     /**
6336      * Marks the current row in this rowset as being an original row.
6337      *
6338      * @throws SQLException if there is no current row
6339      * @see #getOriginalRow
6340      */
6341     public void setOriginalRow() throws SQLException {
6342         if (onInsertRow == true) {
6343             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
6344         }
6345 
6346         Row row = (Row)getCurrentRow();
6347         makeRowOriginal(row);
6348 
6349         // this can happen if deleted rows are being shown
6350         if (row.getDeleted() == true) {
6351             removeCurrentRow();
6352         }
6353     }
6354 
6355     /**
6356      * Makes the given row of this rowset the original row by clearing any
6357      * settings that mark the row as having been inserted, deleted, or updated.
6358      * This method is called internally by the methods
6359      * <code>setOriginalRow</code>
6360      * and <code>setOriginal</code>.
6361      *
6362      * @param row the row to be made the original row
6363      */
6364     private void makeRowOriginal(Row row) {
6365         if (row.getInserted() == true) {
6366             row.clearInserted();
6367         }
6368 
6369         if (row.getUpdated() == true) {
6370             row.moveCurrentToOrig();
6371         }
6372     }
6373 
6374     /**
6375      * Marks all rows in this rowset as being original rows. Any updates
6376      * made to the rows become the original values for the rowset.
6377      * Calls to the method <code>setOriginal</code> connot be reversed.
6378      *
6379      * @throws SQLException if an error occurs
6380      */
6381     public void setOriginal() throws SQLException {
6382         for (Iterator i = rvh.iterator(); i.hasNext();) {
6383             Row row = (Row)i.next();
6384             makeRowOriginal(row);
6385             // remove deleted rows from the collection.
6386             if (row.getDeleted() == true) {
6387                 i.remove();
6388                 --numRows;
6389             }
6390         }
6391         numDeleted = 0;
6392 
6393         // notify any listeners that the rowset has changed
6394         notifyRowSetChanged();
6395     }
6396 
6397     /**
6398      * Returns an identifier for the object (table) that was used to create this
6399      * rowset.
6400      *
6401      * @return a <code>String</code> object that identifies the table from
6402      *         which this <code>CachedRowSetImpl</code> object was derived
6403      * @throws SQLException if an error occurs
6404      */
6405     public String getTableName() throws SQLException {
6406         return tableName;
6407     }
6408 
6409     /**
6410      * Sets the identifier for the table from which this rowset was derived
6411      * to the given table name.
6412      *
6413      * @param tabName a <code>String</code> object that identifies the
6414      *          table from which this <code>CachedRowSetImpl</code> object
6415      *          was derived
6416      * @throws SQLException if an error occurs
6417      */
6418     public void setTableName(String tabName) throws SQLException {
6419         if (tabName == null)
6420             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.tablename").toString());
6421         else
6422             tableName = tabName;
6423     }
6424 
6425     /**
6426      * Returns the columns that make a key to uniquely identify a
6427      * row in this <code>CachedRowSetImpl</code> object.
6428      *
6429      * @return an array of column numbers that constitutes a primary
6430      *           key for this rowset. This array should be empty
6431      *           if no column is representitive of a primary key
6432      * @throws SQLException if the rowset is empty or no columns
6433      *           are designated as primary keys
6434      * @see #setKeyColumns
6435      */
6436     public int[] getKeyColumns() throws SQLException {
6437         return keyCols;
6438     }
6439 
6440 
6441     /**
6442      * Sets this <code>CachedRowSetImpl</code> object's
6443      * <code>keyCols</code> field with the given array of column
6444      * numbers, which forms a key for uniquely identifying a row
6445      * in this rowset.
6446      *
6447      * @param keys an array of <code>int</code> indicating the
6448      *        columns that form a primary key for this
6449      *        <code>CachedRowSetImpl</code> object; every
6450      *        element in the array must be greater than
6451      *        <code>0</code> and less than or equal to the number
6452      *        of columns in this rowset
6453      * @throws SQLException if any of the numbers in the
6454      *            given array is not valid for this rowset
6455      * @see #getKeyColumns
6456      */
6457     public void setKeyColumns(int [] keys) throws SQLException {
6458         int numCols = 0;
6459         if (RowSetMD != null) {
6460             numCols = RowSetMD.getColumnCount();
6461             if (keys.length > numCols)
6462                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.keycols").toString());
6463         }
6464         keyCols = new int[keys.length];
6465         for (int i = 0; i < keys.length; i++) {
6466             if (RowSetMD != null && (keys[i] <= 0 ||
6467             keys[i] > numCols)) {
6468                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcol").toString() +
6469                 keys[i]);
6470             }
6471             keyCols[i] = keys[i];
6472         }
6473     }
6474 
6475     /**
6476      * Sets the designated column in either the current row or the insert
6477      * row of this <code>CachedRowSetImpl</code> object with the given
6478      * <code>Ref</code> value.
6479      *
6480      * This method updates a column value in either the current row or
6481      * the insert row of this rowset, but it does not update the
6482      * database.  If the cursor is on a row in the rowset, the
6483      * method {@link #updateRow} must be called to update the database.
6484      * If the cursor is on the insert row, the method {@link #insertRow}
6485      * must be called, which will insert the new row into both this rowset
6486      * and the database. Both of these methods must be called before the
6487      * cursor moves to another row.
6488      *
6489      * @param columnIndex the first column is <code>1</code>, the second
6490      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6491      *        and equal to or less than the number of columns in this rowset
6492      * @param ref the new column <code>java.sql.Ref</code> value
6493      * @throws SQLException if (1) the given column index is out of bounds,
6494      *        (2) the cursor is not on one of this rowset's rows or its
6495      *        insert row, or (3) this rowset is
6496      *        <code>ResultSet.CONCUR_READ_ONLY</code>
6497      */
6498     public void updateRef(int columnIndex, java.sql.Ref ref) throws SQLException {
6499         // sanity check.
6500         checkIndex(columnIndex);
6501         // make sure the cursor is on a valid row
6502         checkCursor();
6503 
6504         // SerialClob will help in getting the byte array and storing it.
6505         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6506         // or through RowSetMetaData.locatorsUpdatorCopy()
6507         getCurrentRow().setColumnObject(columnIndex, new SerialRef(ref));
6508     }
6509 
6510     /**
6511      * Sets the designated column in either the current row or the insert
6512      * row of this <code>CachedRowSetImpl</code> object with the given
6513      * <code>double</code> value.
6514      *
6515      * This method updates a column value in either the current row or
6516      * the insert row of this rowset, but it does not update the
6517      * database.  If the cursor is on a row in the rowset, the
6518      * method {@link #updateRow} must be called to update the database.
6519      * If the cursor is on the insert row, the method {@link #insertRow}
6520      * must be called, which will insert the new row into both this rowset
6521      * and the database. Both of these methods must be called before the
6522      * cursor moves to another row.
6523      *
6524      * @param columnName a <code>String</code> object that must match the
6525      *        SQL name of a column in this rowset, ignoring case
6526      * @param ref the new column <code>java.sql.Ref</code> value
6527      * @throws SQLException if (1) the given column name does not match the
6528      *        name of a column in this rowset, (2) the cursor is not on
6529      *        one of this rowset's rows or its insert row, or (3) this
6530      *        rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6531      */
6532     public void updateRef(String columnName, java.sql.Ref ref) throws SQLException {
6533         updateRef(getColIdxByName(columnName), ref);
6534     }
6535 
6536     /**
6537      * Sets the designated column in either the current row or the insert
6538      * row of this <code>CachedRowSetImpl</code> object with the given
6539      * <code>double</code> value.
6540      *
6541      * This method updates a column value in either the current row or
6542      * the insert row of this rowset, but it does not update the
6543      * database.  If the cursor is on a row in the rowset, the
6544      * method {@link #updateRow} must be called to update the database.
6545      * If the cursor is on the insert row, the method {@link #insertRow}
6546      * must be called, which will insert the new row into both this rowset
6547      * and the database. Both of these methods must be called before the
6548      * cursor moves to another row.
6549      *
6550      * @param columnIndex the first column is <code>1</code>, the second
6551      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6552      *        and equal to or less than the number of columns in this rowset
6553      * @param c the new column <code>Clob</code> value
6554      * @throws SQLException if (1) the given column index is out of bounds,
6555      *        (2) the cursor is not on one of this rowset's rows or its
6556      *        insert row, or (3) this rowset is
6557      *        <code>ResultSet.CONCUR_READ_ONLY</code>
6558      */
6559     public void updateClob(int columnIndex, Clob c) throws SQLException {
6560         // sanity check.
6561         checkIndex(columnIndex);
6562         // make sure the cursor is on a valid row
6563         checkCursor();
6564 
6565         // SerialClob will help in getting the byte array and storing it.
6566         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6567         // or through RowSetMetaData.locatorsUpdatorCopy()
6568 
6569         if(dbmslocatorsUpdateCopy){
6570            getCurrentRow().setColumnObject(columnIndex, new SerialClob(c));
6571         }
6572         else{
6573            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.opnotsupp").toString());
6574         }
6575     }
6576 
6577     /**
6578      * Sets the designated column in either the current row or the insert
6579      * row of this <code>CachedRowSetImpl</code> object with the given
6580      * <code>double</code> value.
6581      *
6582      * This method updates a column value in either the current row or
6583      * the insert row of this rowset, but it does not update the
6584      * database.  If the cursor is on a row in the rowset, the
6585      * method {@link #updateRow} must be called to update the database.
6586      * If the cursor is on the insert row, the method {@link #insertRow}
6587      * must be called, which will insert the new row into both this rowset
6588      * and the database. Both of these methods must be called before the
6589      * cursor moves to another row.
6590      *
6591      * @param columnName a <code>String</code> object that must match the
6592      *        SQL name of a column in this rowset, ignoring case
6593      * @param c the new column <code>Clob</code> value
6594      * @throws SQLException if (1) the given column name does not match the
6595      *            name of a column in this rowset, (2) the cursor is not on
6596      *            one of this rowset's rows or its insert row, or (3) this
6597      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6598      */
6599     public void updateClob(String columnName, Clob c) throws SQLException {
6600         updateClob(getColIdxByName(columnName), c);
6601     }
6602 
6603     /**
6604      * Sets the designated column in either the current row or the insert
6605      * row of this <code>CachedRowSetImpl</code> object with the given
6606      * <code>java.sql.Blob</code> value.
6607      *
6608      * This method updates a column value in either the current row or
6609      * the insert row of this rowset, but it does not update the
6610      * database.  If the cursor is on a row in the rowset, the
6611      * method {@link #updateRow} must be called to update the database.
6612      * If the cursor is on the insert row, the method {@link #insertRow}
6613      * must be called, which will insert the new row into both this rowset
6614      * and the database. Both of these methods must be called before the
6615      * cursor moves to another row.
6616      *
6617      * @param columnIndex the first column is <code>1</code>, the second
6618      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6619      *        and equal to or less than the number of columns in this rowset
6620      * @param b the new column <code>Blob</code> value
6621      * @throws SQLException if (1) the given column index is out of bounds,
6622      *            (2) the cursor is not on one of this rowset's rows or its
6623      *            insert row, or (3) this rowset is
6624      *            <code>ResultSet.CONCUR_READ_ONLY</code>
6625      */
6626     public void updateBlob(int columnIndex, Blob b) throws SQLException {
6627         // sanity check.
6628         checkIndex(columnIndex);
6629         // make sure the cursor is on a valid row
6630         checkCursor();
6631 
6632         // SerialBlob will help in getting the byte array and storing it.
6633         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6634         // or through RowSetMetaData.locatorsUpdatorCopy()
6635 
6636         if(dbmslocatorsUpdateCopy){
6637            getCurrentRow().setColumnObject(columnIndex, new SerialBlob(b));
6638         }
6639         else{
6640            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.opnotsupp").toString());
6641         }
6642     }
6643 
6644     /**
6645      * Sets the designated column in either the current row or the insert
6646      * row of this <code>CachedRowSetImpl</code> object with the given
6647      * <code>java.sql.Blob </code> value.
6648      *
6649      * This method updates a column value in either the current row or
6650      * the insert row of this rowset, but it does not update the
6651      * database.  If the cursor is on a row in the rowset, the
6652      * method {@link #updateRow} must be called to update the database.
6653      * If the cursor is on the insert row, the method {@link #insertRow}
6654      * must be called, which will insert the new row into both this rowset
6655      * and the database. Both of these methods must be called before the
6656      * cursor moves to another row.
6657      *
6658      * @param columnName a <code>String</code> object that must match the
6659      *        SQL name of a column in this rowset, ignoring case
6660      * @param b the new column <code>Blob</code> value
6661      * @throws SQLException if (1) the given column name does not match the
6662      *            name of a column in this rowset, (2) the cursor is not on
6663      *            one of this rowset's rows or its insert row, or (3) this
6664      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6665      */
6666     public void updateBlob(String columnName, Blob b) throws SQLException {
6667         updateBlob(getColIdxByName(columnName), b);
6668     }
6669 
6670     /**
6671      * Sets the designated column in either the current row or the insert
6672      * row of this <code>CachedRowSetImpl</code> object with the given
6673      * <code>java.sql.Array</code> values.
6674      *
6675      * This method updates a column value in either the current row or
6676      * the insert row of this rowset, but it does not update the
6677      * database.  If the cursor is on a row in the rowset, the
6678      * method {@link #updateRow} must be called to update the database.
6679      * If the cursor is on the insert row, the method {@link #insertRow}
6680      * must be called, which will insert the new row into both this rowset
6681      * and the database. Both of these methods must be called before the
6682      * cursor moves to another row.
6683      *
6684      * @param columnIndex the first column is <code>1</code>, the second
6685      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6686      *        and equal to or less than the number of columns in this rowset
6687      * @param a the new column <code>Array</code> value
6688      * @throws SQLException if (1) the given column index is out of bounds,
6689      *            (2) the cursor is not on one of this rowset's rows or its
6690      *            insert row, or (3) this rowset is
6691      *            <code>ResultSet.CONCUR_READ_ONLY</code>
6692      */
6693     public void updateArray(int columnIndex, Array a) throws SQLException {
6694         // sanity check.
6695         checkIndex(columnIndex);
6696         // make sure the cursor is on a valid row
6697         checkCursor();
6698 
6699         // SerialArray will help in getting the byte array and storing it.
6700         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6701         // or through RowSetMetaData.locatorsUpdatorCopy()
6702         getCurrentRow().setColumnObject(columnIndex, new SerialArray(a));
6703     }
6704 
6705     /**
6706      * Sets the designated column in either the current row or the insert
6707      * row of this <code>CachedRowSetImpl</code> object with the given
6708      * <code>java.sql.Array</code> value.
6709      *
6710      * This method updates a column value in either the current row or
6711      * the insert row of this rowset, but it does not update the
6712      * database.  If the cursor is on a row in the rowset, the
6713      * method {@link #updateRow} must be called to update the database.
6714      * If the cursor is on the insert row, the method {@link #insertRow}
6715      * must be called, which will insert the new row into both this rowset
6716      * and the database. Both of these methods must be called before the
6717      * cursor moves to another row.
6718      *
6719      * @param columnName a <code>String</code> object that must match the
6720      *        SQL name of a column in this rowset, ignoring case
6721      * @param a the new column <code>Array</code> value
6722      * @throws SQLException if (1) the given column name does not match the
6723      *            name of a column in this rowset, (2) the cursor is not on
6724      *            one of this rowset's rows or its insert row, or (3) this
6725      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6726      */
6727     public void updateArray(String columnName, Array a) throws SQLException {
6728         updateArray(getColIdxByName(columnName), a);
6729     }
6730 
6731 
6732     /**
6733      * Retrieves the value of the designated column in this
6734      * <code>CachedRowSetImpl</code> object as a <code>java.net.URL</code> object
6735      * in the Java programming language.
6736      *
6737      * @return a java.net.URL object containing the resource reference described by
6738      * the URL
6739      * @throws SQLException if (1) the given column index is out of bounds,
6740      * (2) the cursor is not on one of this rowset's rows or its
6741      * insert row, or (3) the designated column does not store an
6742      * SQL <code>DATALINK</code> value.
6743      * @see #getURL(String)
6744      */
6745     public java.net.URL getURL(int columnIndex) throws SQLException {
6746         //throw new SQLException("Operation not supported");
6747 
6748         java.net.URL value;
6749 
6750         // sanity check.
6751         checkIndex(columnIndex);
6752         // make sure the cursor is on a valid row
6753         checkCursor();
6754 
6755         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.DATALINK) {
6756             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
6757         }
6758 
6759         setLastValueNull(false);
6760         value = (java.net.URL)(getCurrentRow().getColumnObject(columnIndex));
6761 
6762         // check for SQL NULL
6763         if (value == null) {
6764             setLastValueNull(true);
6765             return null;
6766         }
6767 
6768         return value;
6769     }
6770 
6771     /**
6772      * Retrieves the value of the designated column in this
6773      * <code>CachedRowSetImpl</code> object as a <code>java.net.URL</code> object
6774      * in the Java programming language.
6775      *
6776      * @return a java.net.URL object containing the resource reference described by
6777      * the URL
6778      * @throws SQLException if (1) the given column name not the name of a column
6779      * in this rowset, or
6780      * (2) the cursor is not on one of this rowset's rows or its
6781      * insert row, or (3) the designated column does not store an
6782      * SQL <code>DATALINK</code> value.
6783      * @see #getURL(int)
6784      */
6785     public java.net.URL getURL(String columnName) throws SQLException {
6786         return getURL(getColIdxByName(columnName));
6787 
6788     }
6789 
6790     /**
6791      * The first warning reported by calls on this <code>CachedRowSetImpl</code>
6792      * object is returned. Subsequent <code>CachedRowSetImpl</code> warnings will
6793      * be chained to this <code>SQLWarning</code>. All <code>RowSetWarnings</code>
6794      * warnings are generated in the disconnected environment and remain a
6795      * seperate warning chain to that provided by the <code>getWarnings</code>
6796      * method.
6797      *
6798      * <P>The warning chain is automatically cleared each time a new
6799      * row is read.
6800      *
6801      * <P><B>Note:</B> This warning chain only covers warnings caused
6802      * by <code>CachedRowSet</code> (and their child interface)
6803      * methods. All <code>SQLWarnings</code> can be obtained using the
6804      * <code>getWarnings</code> method which tracks warnings generated
6805      * by the underlying JDBC driver.
6806      * @return the first SQLWarning or null
6807      *
6808      */
6809     public RowSetWarning getRowSetWarnings() {
6810         try {
6811             notifyCursorMoved();
6812         } catch (SQLException e) {} // mask exception
6813         return rowsetWarning;
6814     }
6815 
6816 
6817     /**
6818      * The function tries to isolate the tablename when only setCommand
6819      * is set and not setTablename is called provided there is only one table
6820      * name in the query else just leaves the setting of table name as such.
6821      * If setTablename is set later it will over ride this table name
6822      * value so retrieved.
6823      *
6824      * @return the tablename if only one table in query else return ""
6825      */
6826     private String buildTableName(String command) throws SQLException {
6827 
6828         // If we have a query from one table,
6829         // we set the table name implicitly
6830         // else user has to explicitly set the table name.
6831 
6832         int indexFrom, indexComma;
6833         String strTablename ="";
6834         command = command.trim();
6835 
6836         // Query can be a select, insert or  update
6837 
6838         if(command.toLowerCase().startsWith("select")) {
6839             // look for "from" keyword, after that look for a
6840             // comma after from. If comma is there don't set
6841             // table name else isolate table name.
6842 
6843             indexFrom = command.toLowerCase().indexOf("from");
6844             indexComma = command.indexOf(",", indexFrom);
6845 
6846             if(indexComma == -1) {
6847                 // implies only one table
6848                 strTablename = (command.substring(indexFrom+"from".length(),command.length())).trim();
6849 
6850                 String tabName = strTablename;
6851 
6852                 int idxWhere = tabName.toLowerCase().indexOf("where");
6853 
6854                 /**
6855                   * Adding the addtional check for conditions following the table name.
6856                   * If a condition is found truncate it.
6857                   **/
6858 
6859                 if(idxWhere != -1)
6860                 {
6861                    tabName = tabName.substring(0,idxWhere).trim();
6862                 }
6863 
6864                 strTablename = tabName;
6865 
6866             } else {
6867                 //strTablename="";
6868             }
6869 
6870         } else if(command.toLowerCase().startsWith("insert")) {
6871             //strTablename="";
6872         } else if(command.toLowerCase().startsWith("update")) {
6873             //strTablename="";
6874         }
6875         return strTablename;
6876     }
6877 
6878     /**
6879      * Commits all changes performed by the <code>acceptChanges()</code>
6880      * methods
6881      *
6882      * @see java.sql.Connection#commit
6883      */
6884     public void commit() throws SQLException {
6885         conn.commit();
6886     }
6887 
6888     /**
6889      * Rolls back all changes performed by the <code>acceptChanges()</code>
6890      * methods
6891      *
6892      * @see java.sql.Connection#rollback
6893      */
6894     public void rollback() throws SQLException {
6895         conn.rollback();
6896     }
6897 
6898     /**
6899      * Rolls back all changes performed by the <code>acceptChanges()</code>
6900      * to the last <code>Savepoint</code> transaction marker.
6901      *
6902      * @see java.sql.Connection#rollback(Savepoint)
6903      */
6904     public void rollback(Savepoint s) throws SQLException {
6905         conn.rollback(s);
6906     }
6907 
6908     /**
6909      * Unsets the designated parameter to the given int array.
6910      * This was set using <code>setMatchColumn</code>
6911      * as the column which will form the basis of the join.
6912      * <P>
6913      * The parameter value unset by this method should be same
6914      * as was set.
6915      *
6916      * @param columnIdxes the index into this rowset
6917      *        object's internal representation of parameter values
6918      * @throws SQLException if an error occurs or the
6919      *  parameter index is out of bounds or if the columnIdx is
6920      *  not the same as set using <code>setMatchColumn(int [])</code>
6921      */
6922     public void unsetMatchColumn(int[] columnIdxes) throws SQLException {
6923 
6924          int i_val;
6925          for( int j= 0 ;j < columnIdxes.length; j++) {
6926             i_val = (Integer.parseInt(iMatchColumns.get(j).toString()));
6927             if(columnIdxes[j] != i_val) {
6928                throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols").toString());
6929             }
6930          }
6931 
6932          for( int i = 0;i < columnIdxes.length ;i++) {
6933             iMatchColumns.set(i,Integer.valueOf(-1));
6934          }
6935     }
6936 
6937    /**
6938      * Unsets the designated parameter to the given String array.
6939      * This was set using <code>setMatchColumn</code>
6940      * as the column which will form the basis of the join.
6941      * <P>
6942      * The parameter value unset by this method should be same
6943      * as was set.
6944      *
6945      * @param columnIdxes the index into this rowset
6946      *        object's internal representation of parameter values
6947      * @throws SQLException if an error occurs or the
6948      *  parameter index is out of bounds or if the columnName is
6949      *  not the same as set using <code>setMatchColumn(String [])</code>
6950      */
6951     public void unsetMatchColumn(String[] columnIdxes) throws SQLException {
6952 
6953         for(int j = 0 ;j < columnIdxes.length; j++) {
6954            if( !columnIdxes[j].equals(strMatchColumns.get(j)) ){
6955               throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols").toString());
6956            }
6957         }
6958 
6959         for(int i = 0 ; i < columnIdxes.length; i++) {
6960            strMatchColumns.set(i,null);
6961         }
6962     }
6963 
6964     /**
6965      * Retrieves the column name as <code>String</code> array
6966      * that was set using <code>setMatchColumn(String [])</code>
6967      * for this rowset.
6968      *
6969      * @return a <code>String</code> array object that contains the column names
6970      *         for the rowset which has this the match columns
6971      *
6972      * @throws SQLException if an error occurs or column name is not set
6973      */
6974     public String[] getMatchColumnNames() throws SQLException {
6975 
6976         String []str_temp = new String[strMatchColumns.size()];
6977 
6978         if( strMatchColumns.get(0) == null) {
6979            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.setmatchcols").toString());
6980         }
6981 
6982         strMatchColumns.copyInto(str_temp);
6983         return str_temp;
6984     }
6985 
6986     /**
6987      * Retrieves the column id as <code>int</code> array that was set using
6988      * <code>setMatchColumn(int [])</code> for this rowset.
6989      *
6990      * @return a <code>int</code> array object that contains the column ids
6991      *         for the rowset which has this as the match columns.
6992      *
6993      * @throws SQLException if an error occurs or column index is not set
6994      */
6995     public int[] getMatchColumnIndexes() throws SQLException {
6996 
6997         Integer []int_temp = new Integer[iMatchColumns.size()];
6998         int [] i_temp = new int[iMatchColumns.size()];
6999         int i_val;
7000 
7001         i_val = ((Integer)iMatchColumns.get(0)).intValue();
7002 
7003         if( i_val == -1 ) {
7004            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.setmatchcols").toString());
7005         }
7006 
7007 
7008         iMatchColumns.copyInto(int_temp);
7009 
7010         for(int i = 0; i < int_temp.length; i++) {
7011            i_temp[i] = (int_temp[i]).intValue();
7012         }
7013 
7014         return i_temp;
7015     }
7016 
7017     /**
7018      * Sets the designated parameter to the given int array.
7019      * This forms the basis of the join for the
7020      * <code>JoinRowSet</code> as the column which will form the basis of the
7021      * join.
7022      * <P>
7023      * The parameter value set by this method is stored internally and
7024      * will be supplied as the appropriate parameter in this rowset's
7025      * command when the method <code>getMatchColumnIndexes</code> is called.
7026      *
7027      * @param columnIdxes the indexes into this rowset
7028      *        object's internal representation of parameter values; the
7029      *        first parameter is 0, the second is 1, and so on; must be
7030      *        <code>0</code> or greater
7031      * @throws SQLException if an error occurs or the
7032      *                         parameter index is out of bounds
7033      */
7034     public void setMatchColumn(int[] columnIdxes) throws SQLException {
7035 
7036         for(int j = 0 ; j < columnIdxes.length; j++) {
7037            if( columnIdxes[j] < 0 ) {
7038               throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols1").toString());
7039            }
7040         }
7041         for(int i = 0 ;i < columnIdxes.length; i++) {
7042            iMatchColumns.add(i,Integer.valueOf(columnIdxes[i]));
7043         }
7044     }
7045 
7046     /**
7047      * Sets the designated parameter to the given String array.
7048      *  This forms the basis of the join for the
7049      * <code>JoinRowSet</code> as the column which will form the basis of the
7050      * join.
7051      * <P>
7052      * The parameter value set by this method is stored internally and
7053      * will be supplied as the appropriate parameter in this rowset's
7054      * command when the method <code>getMatchColumn</code> is called.
7055      *
7056      * @param columnNames the name of the column into this rowset
7057      *        object's internal representation of parameter values
7058      * @throws SQLException if an error occurs or the
7059      *  parameter index is out of bounds
7060      */
7061     public void setMatchColumn(String[] columnNames) throws SQLException {
7062 
7063         for(int j = 0; j < columnNames.length; j++) {
7064            if( columnNames[j] == null || columnNames[j].equals("")) {
7065               throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols2").toString());
7066            }
7067         }
7068         for( int i = 0; i < columnNames.length; i++) {
7069            strMatchColumns.add(i,columnNames[i]);
7070         }
7071     }
7072 
7073 
7074     /**
7075      * Sets the designated parameter to the given <code>int</code>
7076      * object.  This forms the basis of the join for the
7077      * <code>JoinRowSet</code> as the column which will form the basis of the
7078      * join.
7079      * <P>
7080      * The parameter value set by this method is stored internally and
7081      * will be supplied as the appropriate parameter in this rowset's
7082      * command when the method <code>getMatchColumn</code> is called.
7083      *
7084      * @param columnIdx the index into this rowset
7085      *        object's internal representation of parameter values; the
7086      *        first parameter is 0, the second is 1, and so on; must be
7087      *        <code>0</code> or greater
7088      * @throws SQLException if an error occurs or the
7089      *                         parameter index is out of bounds
7090      */
7091     public void setMatchColumn(int columnIdx) throws SQLException {
7092         // validate, if col is ok to be set
7093         if(columnIdx < 0) {
7094             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols1").toString());
7095         } else {
7096             // set iMatchColumn
7097             iMatchColumns.set(0, Integer.valueOf(columnIdx));
7098             //strMatchColumn = null;
7099         }
7100     }
7101 
7102     /**
7103      * Sets the designated parameter to the given <code>String</code>
7104      * object.  This forms the basis of the join for the
7105      * <code>JoinRowSet</code> as the column which will form the basis of the
7106      * join.
7107      * <P>
7108      * The parameter value set by this method is stored internally and
7109      * will be supplied as the appropriate parameter in this rowset's
7110      * command when the method <code>getMatchColumn</code> is called.
7111      *
7112      * @param columnName the name of the column into this rowset
7113      *        object's internal representation of parameter values
7114      * @throws SQLException if an error occurs or the
7115      *  parameter index is out of bounds
7116      */
7117     public void setMatchColumn(String columnName) throws SQLException {
7118         // validate, if col is ok to be set
7119         if(columnName == null || (columnName= columnName.trim()).equals("") ) {
7120             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols2").toString());
7121         } else {
7122             // set strMatchColumn
7123             strMatchColumns.set(0, columnName);
7124             //iMatchColumn = -1;
7125         }
7126     }
7127 
7128     /**
7129      * Unsets the designated parameter to the given <code>int</code>
7130      * object.  This was set using <code>setMatchColumn</code>
7131      * as the column which will form the basis of the join.
7132      * <P>
7133      * The parameter value unset by this method should be same
7134      * as was set.
7135      *
7136      * @param columnIdx the index into this rowset
7137      *        object's internal representation of parameter values
7138      * @throws SQLException if an error occurs or the
7139      *  parameter index is out of bounds or if the columnIdx is
7140      *  not the same as set using <code>setMatchColumn(int)</code>
7141      */
7142     public void unsetMatchColumn(int columnIdx) throws SQLException {
7143         // check if we are unsetting the SAME column
7144         if(! iMatchColumns.get(0).equals(Integer.valueOf(columnIdx) )  ) {
7145             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch").toString());
7146         } else if(strMatchColumns.get(0) != null) {
7147             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch1").toString());
7148         } else {
7149                 // that is, we are unsetting it.
7150                iMatchColumns.set(0, Integer.valueOf(-1));
7151         }
7152     }
7153 
7154     /**
7155      * Unsets the designated parameter to the given <code>String</code>
7156      * object.  This was set using <code>setMatchColumn</code>
7157      * as the column which will form the basis of the join.
7158      * <P>
7159      * The parameter value unset by this method should be same
7160      * as was set.
7161      *
7162      * @param columnName the index into this rowset
7163      *        object's internal representation of parameter values
7164      * @throws SQLException if an error occurs or the
7165      *  parameter index is out of bounds or if the columnName is
7166      *  not the same as set using <code>setMatchColumn(String)</code>
7167      */
7168     public void unsetMatchColumn(String columnName) throws SQLException {
7169         // check if we are unsetting the same column
7170         columnName = columnName.trim();
7171 
7172         if(!((strMatchColumns.get(0)).equals(columnName))) {
7173             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch").toString());
7174         } else if( ((Integer)(iMatchColumns.get(0))).intValue() > 0) {
7175             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch2").toString());
7176         } else {
7177             strMatchColumns.set(0, null);   // that is, we are unsetting it.
7178         }
7179     }
7180 
7181     /**
7182      * Notifies registered listeners that a RowSet object in the given RowSetEvent
7183      * object has populated a number of additional rows. The <code>numRows</code> parameter
7184      * ensures that this event will only be fired every <code>numRow</code>.
7185      * <p>
7186      * The source of the event can be retrieved with the method event.getSource.
7187      *
7188      * @param event a <code>RowSetEvent</code> object that contains the
7189      *     <code>RowSet</code> object that is the source of the events
7190      * @param numRows when populating, the number of rows interval on which the
7191      *     <code>CachedRowSet</code> populated should fire; the default value
7192      *     is zero; cannot be less than <code>fetchSize</code> or zero
7193      */
7194     public void rowSetPopulated(RowSetEvent event, int numRows) throws SQLException {
7195 
7196         if( numRows < 0 || numRows < getFetchSize()) {
7197            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.numrows").toString());
7198         }
7199 
7200         if(size() % numRows == 0) {
7201             RowSetEvent event_temp = new RowSetEvent(this);
7202             event = event_temp;
7203             notifyRowSetChanged();
7204         }
7205     }
7206 
7207     /**
7208      * Populates this <code>CachedRowSet</code> object with data from
7209      * the given <code>ResultSet</code> object. While related to the <code>populate(ResultSet)</code>
7210      * method, an additional parameter is provided to allow starting position within
7211      * the <code>ResultSet</code> from where to populate the CachedRowSet
7212      * instance.
7213      *
7214      * This method is an alternative to the method <code>execute</code>
7215      * for filling the rowset with data.  The method <code>populate</code>
7216      * does not require that the properties needed by the method
7217      * <code>execute</code>, such as the <code>command</code> property,
7218      * be set. This is true because the method <code>populate</code>
7219      * is given the <code>ResultSet</code> object from
7220      * which to get data and thus does not need to use the properties
7221      * required for setting up a connection and executing this
7222      * <code>CachedRowSetImpl</code> object's command.
7223      * <P>
7224      * After populating this rowset with data, the method
7225      * <code>populate</code> sets the rowset's metadata and
7226      * then sends a <code>RowSetChangedEvent</code> object
7227      * to all registered listeners prior to returning.
7228      *
7229      * @param data the <code>ResultSet</code> object containing the data
7230      *             to be read into this <code>CachedRowSetImpl</code> object
7231      * @param start the integer specifing the position in the
7232      *        <code>ResultSet</code> object to popultate the
7233      *        <code>CachedRowSetImpl</code> object.
7234      * @throws SQLException if an error occurs; or the max row setting is
7235      *          violated while populating the RowSet.Also id the start position
7236      *          is negative.
7237      * @see #execute
7238      */
7239      public void populate(ResultSet data, int start) throws SQLException{
7240 
7241         int rowsFetched;
7242         Row currentRow;
7243         int numCols;
7244         int i;
7245         Map<String, Class<?>> map = getTypeMap();
7246         Object obj;
7247         int mRows;
7248 
7249         cursorPos = 0;
7250         if(populatecallcount == 0){
7251             if(start < 0){
7252                throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.startpos").toString());
7253             }
7254             if(getMaxRows() == 0){
7255                data.absolute(start);
7256                while(data.next()){
7257                    totalRows++;
7258                }
7259                totalRows++;
7260             }
7261             startPos = start;
7262         }
7263         populatecallcount = populatecallcount +1;
7264         resultSet = data;
7265         if((endPos - startPos) >= getMaxRows() && (getMaxRows() > 0)){
7266             endPos = prevEndPos;
7267             pagenotend = false;
7268             return;
7269         }
7270 
7271         if((maxRowsreached != getMaxRows() || maxRowsreached != totalRows) && pagenotend) {
7272            startPrev = start - getPageSize();
7273         }
7274 
7275         if( pageSize == 0){
7276            prevEndPos = endPos;
7277            endPos = start + getMaxRows() ;
7278         }
7279         else{
7280             prevEndPos = endPos;
7281             endPos = start + getPageSize();
7282         }
7283 
7284 
7285         if (start == 1){
7286             resultSet.beforeFirst();
7287         }
7288         else {
7289             resultSet.absolute(start -1);
7290         }
7291         if( pageSize == 0) {
7292            rvh = new Vector<Object>(getMaxRows());
7293 
7294         }
7295         else{
7296             rvh = new Vector<Object>(getPageSize());
7297         }
7298 
7299         if (data == null) {
7300             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.populate").toString());
7301         }
7302 
7303         // get the meta data for this ResultSet
7304         RSMD = data.getMetaData();
7305 
7306         // set up the metadata
7307         RowSetMD = new RowSetMetaDataImpl();
7308         initMetaData(RowSetMD, RSMD);
7309 
7310         // release the meta-data so that aren't tempted to use it.
7311         RSMD = null;
7312         numCols = RowSetMD.getColumnCount();
7313         mRows = this.getMaxRows();
7314         rowsFetched = 0;
7315         currentRow = null;
7316 
7317         if(!data.next() && mRows == 0){
7318             endPos = prevEndPos;
7319             pagenotend = false;
7320             return;
7321         }
7322 
7323         data.previous();
7324 
7325         while ( data.next()) {
7326 
7327             currentRow = new Row(numCols);
7328           if(pageSize == 0){
7329             if ( rowsFetched >= mRows && mRows > 0) {
7330                 rowsetWarning.setNextException(new SQLException("Populating rows "
7331                 + "setting has exceeded max row setting"));
7332                 break;
7333             }
7334           }
7335           else {
7336               if ( (rowsFetched >= pageSize) ||( maxRowsreached >= mRows && mRows > 0)) {
7337                 rowsetWarning.setNextException(new SQLException("Populating rows "
7338                 + "setting has exceeded max row setting"));
7339                 break;
7340             }
7341           }
7342 
7343             for ( i = 1; i <= numCols; i++) {
7344                 /*
7345                  * check if the user has set a map. If no map
7346                  * is set then use plain getObject. This lets
7347                  * us work with drivers that do not support
7348                  * getObject with a map in fairly sensible way
7349                  */
7350                 if (map == null) {
7351                     obj = data.getObject(i);
7352                 } else {
7353                     obj = data.getObject(i, map);
7354                 }
7355                 /*
7356                  * the following block checks for the various
7357                  * types that we have to serialize in order to
7358                  * store - right now only structs have been tested
7359                  */
7360                 if (obj instanceof Struct) {
7361                     obj = new SerialStruct((Struct)obj, map);
7362                 } else if (obj instanceof SQLData) {
7363                     obj = new SerialStruct((SQLData)obj, map);
7364                 } else if (obj instanceof Blob) {
7365                     obj = new SerialBlob((Blob)obj);
7366                 } else if (obj instanceof Clob) {
7367                     obj = new SerialClob((Clob)obj);
7368                 } else if (obj instanceof java.sql.Array) {
7369                     obj = new SerialArray((java.sql.Array)obj, map);
7370                 }
7371 
7372                 ((Row)currentRow).initColumnObject(i, obj);
7373             }
7374             rowsFetched++;
7375             maxRowsreached++;
7376             rvh.add(currentRow);
7377         }
7378         numRows = rowsFetched ;
7379         // Also rowsFetched should be equal to rvh.size()
7380         // notify any listeners that the rowset has changed
7381         notifyRowSetChanged();
7382 
7383      }
7384 
7385     /**
7386      * The nextPage gets the next page, that is a <code>CachedRowSetImpl</code> object
7387      * containing the number of rows specified by page size.
7388      * @return boolean value true indicating whether there are more pages to come and
7389      *         false indicating that this is the last page.
7390      * @throws SQLException if an error occurs or this called before calling populate.
7391      */
7392      public boolean nextPage() throws SQLException {
7393 
7394          if (populatecallcount == 0){
7395              throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.nextpage").toString());
7396          }
7397          // Fix for 6554186
7398          onFirstPage = false;
7399          if(callWithCon){
7400             crsReader.setStartPosition(endPos);
7401             crsReader.readData((RowSetInternal)this);
7402             resultSet = null;
7403          }
7404          else {
7405             populate(resultSet,endPos);
7406          }
7407          return pagenotend;
7408      }
7409 
7410     /**
7411      * This is the setter function for setting the size of the page, which specifies
7412      * how many rows have to be retrived at a time.
7413      *
7414      * @param size which is the page size
7415      * @throws SQLException if size is less than zero or greater than max rows.
7416      */
7417      public void setPageSize (int size) throws SQLException {
7418         if (size < 0) {
7419             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.pagesize").toString());
7420         }
7421         if (size > getMaxRows() && getMaxRows() != 0) {
7422             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.pagesize1").toString());
7423         }
7424         pageSize = size;
7425      }
7426 
7427     /**
7428      * This is the getter function for the size of the page.
7429      *
7430      * @return an integer that is the page size.
7431      */
7432     public int getPageSize() {
7433         return pageSize;
7434     }
7435 
7436 
7437     /**
7438      * Retrieves the data present in the page prior to the page from where it is
7439      * called.
7440      * @return boolean value true if it retrieves the previous page, flase if it
7441      *         is on the first page.
7442      * @throws SQLException if it is called before populate is called or ResultSet
7443      *         is of type <code>ResultSet.TYPE_FORWARD_ONLY</code> or if an error
7444      *         occurs.
7445      */
7446     public boolean previousPage() throws SQLException {
7447         int pS;
7448         int mR;
7449         int rem;
7450 
7451         pS = getPageSize();
7452         mR = maxRowsreached;
7453 
7454         if (populatecallcount == 0){
7455              throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.nextpage").toString());
7456          }
7457 
7458         if( !callWithCon){
7459            if(resultSet.getType() == ResultSet.TYPE_FORWARD_ONLY){
7460                throw new SQLException (resBundle.handleGetObject("cachedrowsetimpl.fwdonly").toString());
7461            }
7462         }
7463 
7464         pagenotend = true;
7465 
7466         if(startPrev < startPos ){
7467                 onFirstPage = true;
7468                return false;
7469             }
7470 
7471         if(onFirstPage){
7472             return false;
7473         }
7474 
7475         rem = mR % pS;
7476 
7477         if(rem == 0){
7478             maxRowsreached -= (2 * pS);
7479             if(callWithCon){
7480                 crsReader.setStartPosition(startPrev);
7481                 crsReader.readData((RowSetInternal)this);
7482                 resultSet = null;
7483             }
7484             else {
7485                populate(resultSet,startPrev);
7486             }
7487             return true;
7488         }
7489         else
7490         {
7491             maxRowsreached -= (pS + rem);
7492             if(callWithCon){
7493                 crsReader.setStartPosition(startPrev);
7494                 crsReader.readData((RowSetInternal)this);
7495                 resultSet = null;
7496             }
7497             else {
7498                populate(resultSet,startPrev);
7499             }
7500             return true;
7501         }
7502     }
7503 
7504     /**
7505      * Goes to the page number passed as the parameter
7506      * @param page , the page loaded on a call to this function
7507      * @return true if the page exists false otherwise
7508      * @throws SQLException if an error occurs
7509      */
7510     /*
7511     public boolean absolutePage(int page) throws SQLException{
7512 
7513         boolean isAbs = true, retVal = true;
7514         int counter;
7515 
7516         if( page <= 0 ){
7517             throw new SQLException("Absolute positoin is invalid");
7518         }
7519         counter = 0;
7520 
7521         firstPage();
7522         counter++;
7523         while((counter < page) && isAbs) {
7524             isAbs = nextPage();
7525             counter ++;
7526         }
7527 
7528         if( !isAbs && counter < page){
7529             retVal = false;
7530         }
7531         else if(counter == page){
7532             retVal = true;
7533         }
7534 
7535        return retVal;
7536     }
7537     */
7538 
7539 
7540     /**
7541      * Goes to the page number passed as the parameter  from the current page.
7542      * The parameter can take postive or negative value accordingly.
7543      * @param page , the page loaded on a call to this function
7544      * @return true if the page exists false otherwise
7545      * @throws SQLException if an error occurs
7546      */
7547     /*
7548     public boolean relativePage(int page) throws SQLException {
7549 
7550         boolean isRel = true,retVal = true;
7551         int counter;
7552 
7553         if(page > 0){
7554            counter  = 0;
7555            while((counter < page) && isRel){
7556               isRel = nextPage();
7557               counter++;
7558            }
7559 
7560            if(!isRel && counter < page){
7561                retVal = false;
7562            }
7563            else if( counter == page){
7564                retVal = true;
7565            }
7566            return retVal;
7567         }
7568         else {
7569             counter = page;
7570             isRel = true;
7571             while((counter < 0) && isRel){
7572                 isRel = previousPage();
7573                 counter++;
7574             }
7575 
7576             if( !isRel && counter < 0){
7577                 retVal = false;
7578             }
7579             else if(counter == 0){
7580                 retVal = true;
7581             }
7582             return retVal;
7583         }
7584     }
7585     */
7586 
7587      /**
7588      * Retrieves the first page of data as specified by the page size.
7589      * @return boolean value true if present on first page, false otherwise
7590      * @throws SQLException if it called before populate or ResultSet is of
7591      *         type <code>ResultSet.TYPE_FORWARD_ONLY</code> or an error occurs
7592      */
7593     /*
7594     public boolean firstPage() throws SQLException {
7595            if (populatecallcount == 0){
7596              throw new SQLException("Populate the data before calling ");
7597            }
7598            if( !callWithCon){
7599               if(resultSet.getType() == ResultSet.TYPE_FORWARD_ONLY) {
7600                   throw new SQLException("Result of type forward only");
7601               }
7602            }
7603            endPos = 0;
7604            maxRowsreached = 0;
7605            pagenotend = true;
7606            if(callWithCon){
7607                crsReader.setStartPosition(startPos);
7608                crsReader.readData((RowSetInternal)this);
7609                resultSet = null;
7610            }
7611            else {
7612               populate(resultSet,startPos);
7613            }
7614            onFirstPage = true;
7615            return onFirstPage;
7616     }
7617     */
7618 
7619     /**
7620      * Retrives the last page of data as specified by the page size.
7621      * @return boolean value tur if present on the last page, false otherwise
7622      * @throws SQLException if called before populate or if an error occurs.
7623      */
7624      /*
7625     public boolean lastPage() throws SQLException{
7626           int pS;
7627           int mR;
7628           int quo;
7629           int rem;
7630 
7631           pS = getPageSize();
7632           mR = getMaxRows();
7633 
7634           if(pS == 0){
7635               onLastPage = true;
7636               return onLastPage;
7637           }
7638 
7639           if(getMaxRows() == 0){
7640               mR = totalRows;
7641           }
7642 
7643           if (populatecallcount == 0){
7644              throw new SQLException("Populate the data before calling ");
7645          }
7646 
7647          onFirstPage = false;
7648 
7649          if((mR % pS) == 0){
7650              quo = mR / pS;
7651              int start = startPos + (pS * (quo - 1));
7652              maxRowsreached = mR - pS;
7653              if(callWithCon){
7654                  crsReader.setStartPosition(start);
7655                  crsReader.readData((RowSetInternal)this);
7656                  resultSet = null;
7657              }
7658              else {
7659                 populate(resultSet,start);
7660              }
7661              onLastPage = true;
7662              return onLastPage;
7663          }
7664         else {
7665               quo = mR /pS;
7666               rem = mR % pS;
7667               int start = startPos + (pS * quo);
7668              maxRowsreached = mR - (rem);
7669              if(callWithCon){
7670                  crsReader.setStartPosition(start);
7671                  crsReader.readData((RowSetInternal)this);
7672                  resultSet = null;
7673              }
7674              else {
7675                 populate(resultSet,start);
7676              }
7677              onLastPage = true;
7678              return onLastPage;
7679          }
7680     }
7681     */
7682 
7683    /**
7684      * Sets the status for the row on which the cursor is positioned. The insertFlag is used
7685      * to mention the toggle status for this row
7686      * @param insertFlag if it is true  - marks this row as inserted
7687      *                   if it is false - marks it as not a newly inserted row
7688      * @throws SQLException if an error occurs while doing this operation
7689      */
7690     public void setRowInserted(boolean insertFlag) throws SQLException {
7691 
7692         checkCursor();
7693 
7694         if(onInsertRow == true)
7695           throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
7696 
7697         if( insertFlag ) {
7698           ((Row)getCurrentRow()).setInserted();
7699         } else {
7700           ((Row)getCurrentRow()).clearInserted();
7701         }
7702     }
7703 
7704     /**
7705      * Retrieves the value of the designated <code>SQL XML</code> parameter as a
7706      * <code>SQLXML</code> object in the Java programming language.
7707      * @param columnIndex the first column is 1, the second is 2, ...
7708      * @return a SQLXML object that maps an SQL XML value
7709      * @throws SQLException if a database access error occurs
7710      * @since 6.0
7711      */
7712     public SQLXML getSQLXML(int columnIndex) throws SQLException {
7713         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7714     }
7715 
7716     /**
7717      * Retrieves the value of the designated <code>SQL XML</code> parameter as a
7718      * <code>SQLXML</code> object in the Java programming language.
7719      * @param colName the name of the column from which to retrieve the value
7720      * @return a SQLXML object that maps an SQL XML value
7721      * @throws SQLException if a database access error occurs
7722      */
7723     public SQLXML getSQLXML(String colName) throws SQLException {
7724         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7725     }
7726 
7727     /**
7728      * Retrieves the value of the designated column in the current row of this
7729      * <code>ResultSet</code> object as a java.sql.RowId object in the Java
7730      * programming language.
7731      *
7732      * @param columnIndex the first column is 1, the second 2, ...
7733      * @return the column value if the value is a SQL <code>NULL</code> the
7734      *     value returned is <code>null</code>
7735      * @throws SQLException if a database access error occurs
7736      * @since 6.0
7737      */
7738     public RowId getRowId(int columnIndex) throws SQLException {
7739         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7740     }
7741 
7742     /**
7743      * Retrieves the value of the designated column in the current row of this
7744      * <code>ResultSet</code> object as a java.sql.RowId object in the Java
7745      * programming language.
7746      *
7747      * @param columnName the name of the column
7748      * @return the column value if the value is a SQL <code>NULL</code> the
7749      *     value returned is <code>null</code>
7750      * @throws SQLException if a database access error occurs
7751      * @since 6.0
7752      */
7753     public RowId getRowId(String columnName) throws SQLException {
7754         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7755     }
7756 
7757     /**
7758      * Updates the designated column with a <code>RowId</code> value. The updater
7759      * methods are used to update column values in the current row or the insert
7760      * row. The updater methods do not update the underlying database; instead
7761      * the <code>updateRow<code> or <code>insertRow</code> methods are called
7762      * to update the database.
7763      *
7764      * @param columnIndex the first column is 1, the second 2, ...
7765      * @param x the column value
7766      * @throws SQLException if a database access occurs
7767      * @since 6.0
7768      */
7769     public void updateRowId(int columnIndex, RowId x) throws SQLException {
7770         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7771     }
7772 
7773     /**
7774      * Updates the designated column with a <code>RowId</code> value. The updater
7775      * methods are used to update column values in the current row or the insert
7776      * row. The updater methods do not update the underlying database; instead
7777      * the <code>updateRow<code> or <code>insertRow</code> methods are called
7778      * to update the database.
7779      *
7780      * @param columnName the name of the column
7781      * @param x the column value
7782      * @throws SQLException if a database access occurs
7783      * @since 6.0
7784      */
7785     public void updateRowId(String columnName, RowId x) throws SQLException {
7786         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7787     }
7788 
7789     /**
7790      * Retrieves the holdability of this ResultSet object
7791      * @return  either ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT
7792      * @throws SQLException if a database error occurs
7793      * @since 6.0
7794      */
7795     public int getHoldability() throws SQLException {
7796         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7797     }
7798 
7799     /**
7800      * Retrieves whether this ResultSet object has been closed. A ResultSet is closed if the
7801      * method close has been called on it, or if it is automatically closed.
7802      * @return true if this ResultSet object is closed; false if it is still open
7803      * @throws SQLException if a database access error occurs
7804      * @since 6.0
7805      */
7806     public boolean isClosed() throws SQLException {
7807         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7808     }
7809 
7810     /**
7811      * This method is used for updating columns that support National Character sets.
7812      * It can be used for updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
7813      * @param columnIndex the first column is 1, the second 2, ...
7814      * @param nString the value for the column to be updated
7815      * @throws SQLException if a database access error occurs
7816      * @since 6.0
7817      */
7818     public void updateNString(int columnIndex, String nString) throws SQLException {
7819         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7820     }
7821 
7822     /**
7823      * This method is used for updating columns that support National Character sets.
7824      * It can be used for updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
7825      * @param columnName name of the Column
7826      * @param nString the value for the column to be updated
7827      * @throws SQLException if a database access error occurs
7828      * @since 6.0
7829      */
7830     public void updateNString(String columnName, String nString) throws SQLException {
7831         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7832     }
7833 
7834 
7835     /*o
7836      * This method is used for updating SQL <code>NCLOB</code>  type that maps
7837      * to <code>java.sql.Types.NCLOB</code>
7838      * @param columnIndex the first column is 1, the second 2, ...
7839      * @param nClob the value for the column to be updated
7840      * @throws SQLException if a database access error occurs
7841      * @since 6.0
7842      */
7843     public void updateNClob(int columnIndex, NClob nClob) throws SQLException {
7844         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7845     }
7846 
7847     /**
7848      * This method is used for updating SQL <code>NCLOB</code>  type that maps
7849      * to <code>java.sql.Types.NCLOB</code>
7850      * @param columnName name of the column
7851      * @param nClob the value for the column to be updated
7852      * @throws SQLException if a database access error occurs
7853      * @since 6.0
7854      */
7855     public void updateNClob(String columnName, NClob nClob) throws SQLException {
7856        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7857     }
7858 
7859     /**
7860      * Retrieves the value of the designated column in the current row
7861      * of this <code>ResultSet</code> object as a <code>NClob</code> object
7862      * in the Java programming language.
7863      *
7864      * @param i the first column is 1, the second is 2, ...
7865      * @return a <code>NClob</code> object representing the SQL
7866      *         <code>NCLOB</code> value in the specified column
7867      * @exception SQLException if a database access error occurs
7868      * @since 6.0
7869      */
7870     public NClob getNClob(int i) throws SQLException {
7871         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7872     }
7873 
7874 
7875    /**
7876      * Retrieves the value of the designated column in the current row
7877      * of this <code>ResultSet</code> object as a <code>NClob</code> object
7878      * in the Java programming language.
7879      *
7880      * @param colName the name of the column from which to retrieve the value
7881      * @return a <code>NClob</code> object representing the SQL <code>NCLOB</code>
7882      * value in the specified column
7883      * @exception SQLException if a database access error occurs
7884      * @since 6.0
7885      */
7886     public NClob getNClob(String colName) throws SQLException {
7887         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7888     }
7889 
7890     public <T> T unwrap(java.lang.Class<T> iface) throws java.sql.SQLException {
7891         return null;
7892     }
7893 
7894     public boolean isWrapperFor(Class<?> interfaces) throws SQLException {
7895         return false;
7896     }
7897 
7898 
7899    /**
7900       * Sets the designated parameter to the given <code>java.sql.SQLXML</code> object. The driver converts this to an
7901       * SQL <code>XML</code> value when it sends it to the database.
7902       * @param parameterIndex index of the first parameter is 1, the second is 2, ...
7903       * @param xmlObject a <code>SQLXML</code> object that maps an SQL <code>XML</code> value
7904       * @throws SQLException if a database access error occurs
7905       * @since 1.6
7906       */
7907      public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
7908          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7909      }
7910 
7911    /**
7912      * Sets the designated parameter to the given <code>java.sql.SQLXML</code> object. The driver converts this to an
7913      * <code>SQL XML</code> value when it sends it to the database.
7914      * @param parameterName the name of the parameter
7915      * @param xmlObject a <code>SQLXML</code> object that maps an <code>SQL XML</code> value
7916      * @throws SQLException if a database access error occurs
7917      * @since 1.6
7918      */
7919     public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException {
7920          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7921      }
7922 
7923 
7924     /**
7925      * Sets the designated parameter to the given <code>java.sql.RowId</code> object. The
7926      * driver converts this to a SQL <code>ROWID</code> value when it sends it
7927      * to the database
7928      *
7929      * @param parameterIndex the first parameter is 1, the second is 2, ...
7930      * @param x the parameter value
7931      * @throws SQLException if a database access error occurs
7932      *
7933      * @since 1.6
7934      */
7935     public void setRowId(int parameterIndex, RowId x) throws SQLException {
7936          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7937      }
7938 
7939 
7940     /**
7941     * Sets the designated parameter to the given <code>java.sql.RowId</code> object. The
7942     * driver converts this to a SQL <code>ROWID</code> when it sends it to the
7943     * database.
7944     *
7945     * @param parameterName the name of the parameter
7946     * @param x the parameter value
7947     * @throws SQLException if a database access error occurs
7948     * @since 1.6
7949     */
7950    public void setRowId(String parameterName, RowId x) throws SQLException {
7951          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7952      }
7953 
7954 
7955     /**
7956      * Sets the designated parameter to a <code>Reader</code> object. The
7957      * <code>Reader</code> reads the data till end-of-file is reached. The
7958      * driver does the necessary conversion from Java character format to
7959      * the national character set in the database.
7960 
7961      * <P><B>Note:</B> This stream object can either be a standard
7962      * Java stream object or your own subclass that implements the
7963      * standard interface.
7964      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
7965      * it might be more efficient to use a version of
7966      * <code>setNCharacterStream</code> which takes a length parameter.
7967      *
7968      * @param parameterIndex of the first parameter is 1, the second is 2, ...
7969      * @param value the parameter value
7970      * @throws SQLException if the driver does not support national
7971      *         character sets;  if the driver can detect that a data conversion
7972      *  error could occur ; if a database access error occurs; or
7973      * this method is called on a closed <code>PreparedStatement</code>
7974      * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
7975      * @since 1.6
7976      */
7977      public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
7978         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
7979      }
7980 
7981 
7982     /**
7983     * Sets the designated parameter to a <code>java.sql.NClob</code> object. The object
7984     * implements the <code>java.sql.NClob</code> interface. This <code>NClob</code>
7985     * object maps to a SQL <code>NCLOB</code>.
7986     * @param parameterName the name of the column to be set
7987     * @param value the parameter value
7988     * @throws SQLException if the driver does not support national
7989     *         character sets;  if the driver can detect that a data conversion
7990     *  error could occur; or if a database access error occurs
7991     * @since 1.6
7992     */
7993     public void setNClob(String parameterName, NClob value) throws SQLException {
7994          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7995      }
7996 
7997 
7998   /**
7999      * Retrieves the value of the designated column in the current row
8000      * of this <code>ResultSet</code> object as a
8001      * <code>java.io.Reader</code> object.
8002      * It is intended for use when
8003      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8004      * and <code>LONGNVARCHAR</code> columns.
8005      *
8006      * @return a <code>java.io.Reader</code> object that contains the column
8007      * value; if the value is SQL <code>NULL</code>, the value returned is
8008      * <code>null</code> in the Java programming language.
8009      * @param columnIndex the first column is 1, the second is 2, ...
8010      * @exception SQLException if a database access error occurs
8011      * @since 1.6
8012      */
8013     public java.io.Reader getNCharacterStream(int columnIndex) throws SQLException {
8014        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8015      }
8016 
8017 
8018     /**
8019      * Retrieves the value of the designated column in the current row
8020      * of this <code>ResultSet</code> object as a
8021      * <code>java.io.Reader</code> object.
8022      * It is intended for use when
8023      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8024      * and <code>LONGNVARCHAR</code> columns.
8025      *
8026      * @param columnName the name of the column
8027      * @return a <code>java.io.Reader</code> object that contains the column
8028      * value; if the value is SQL <code>NULL</code>, the value returned is
8029      * <code>null</code> in the Java programming language
8030      * @exception SQLException if a database access error occurs
8031      * @since 1.6
8032      */
8033     public java.io.Reader getNCharacterStream(String columnName) throws SQLException {
8034        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8035      }
8036 
8037 
8038     /**
8039      * Updates the designated column with a <code>java.sql.SQLXML</code> value.
8040      * The updater
8041      * methods are used to update column values in the current row or the insert
8042      * row. The updater methods do not update the underlying database; instead
8043      * the <code>updateRow</code> or <code>insertRow</code> methods are called
8044      * to update the database.
8045      * @param columnIndex the first column is 1, the second 2, ...
8046      * @param xmlObject the value for the column to be updated
8047      * @throws SQLException if a database access error occurs
8048      * @since 1.6
8049      */
8050     public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException {
8051         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8052     }
8053 
8054     /**
8055      * Updates the designated column with a <code>java.sql.SQLXML</code> value.
8056      * The updater
8057      * methods are used to update column values in the current row or the insert
8058      * row. The updater methods do not update the underlying database; instead
8059      * the <code>updateRow</code> or <code>insertRow</code> methods are called
8060      * to update the database.
8061      *
8062      * @param columnName the name of the column
8063      * @param xmlObject the column value
8064      * @throws SQLException if a database access occurs
8065      * @since 1.6
8066      */
8067     public void updateSQLXML(String columnName, SQLXML xmlObject) throws SQLException {
8068         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8069     }
8070 
8071      /**
8072      * Retrieves the value of the designated column in the current row
8073      * of this <code>ResultSet</code> object as
8074      * a <code>String</code> in the Java programming language.
8075      * It is intended for use when
8076      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8077      * and <code>LONGNVARCHAR</code> columns.
8078      *
8079      * @param columnIndex the first column is 1, the second is 2, ...
8080      * @return the column value; if the value is SQL <code>NULL</code>, the
8081      * value returned is <code>null</code>
8082      * @exception SQLException if a database access error occurs
8083      * @since 1.6
8084      */
8085     public String getNString(int columnIndex) throws SQLException {
8086         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8087     }
8088 
8089     /**
8090      * Retrieves the value of the designated column in the current row
8091      * of this <code>ResultSet</code> object as
8092      * a <code>String</code> in the Java programming language.
8093      * It is intended for use when
8094      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8095      * and <code>LONGNVARCHAR</code> columns.
8096      *
8097      * @param columnName the SQL name of the column
8098      * @return the column value; if the value is SQL <code>NULL</code>, the
8099      * value returned is <code>null</code>
8100      * @exception SQLException if a database access error occurs
8101      * @since 1.6
8102      */
8103     public String getNString(String columnName) throws SQLException {
8104         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8105     }
8106 
8107      /**
8108        * Updates the designated column with a character stream value, which will
8109        * have the specified number of bytes. The driver does the necessary conversion
8110        * from Java character format to the national character set in the database.
8111        * It is intended for use when updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
8112        * The updater methods are used to update column values in the current row or
8113        * the insert row. The updater methods do not update the underlying database;
8114        * instead the updateRow or insertRow methods are called to update the database.
8115        *
8116        * @param columnIndex - the first column is 1, the second is 2, ...
8117        * @param x - the new column value
8118        * @param length - the length of the stream
8119        * @exception SQLException if a database access error occurs
8120        * @since 1.6
8121        */
8122        public void updateNCharacterStream(int columnIndex,
8123                             java.io.Reader x,
8124                             long length)
8125                             throws SQLException {
8126           throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8127        }
8128 
8129      /**
8130        * Updates the designated column with a character stream value, which will
8131        * have the specified number of bytes. The driver does the necessary conversion
8132        * from Java character format to the national character set in the database.
8133        * It is intended for use when updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
8134        * The updater methods are used to update column values in the current row or
8135        * the insert row. The updater methods do not update the underlying database;
8136        * instead the updateRow or insertRow methods are called to update the database.
8137        *
8138        * @param columnName - name of the Column
8139        * @param x - the new column value
8140        * @param length - the length of the stream
8141        * @exception SQLException if a database access error occurs
8142        * @since 1.6
8143        */
8144        public void updateNCharacterStream(String columnName,
8145                             java.io.Reader x,
8146                             long length)
8147                             throws SQLException {
8148           throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8149        }
8150 
8151      /**
8152      * Updates the designated column with a character stream value.   The
8153      * driver does the necessary conversion from Java character format to
8154      * the national character set in the database.
8155      * It is intended for use when
8156      * updating  <code>NCHAR</code>,<code>NVARCHAR</code>
8157      * and <code>LONGNVARCHAR</code> columns.
8158      *
8159      * The updater methods are used to update column values in the
8160      * current row or the insert row.  The updater methods do not
8161      * update the underlying database; instead the <code>updateRow</code> or
8162      * <code>insertRow</code> methods are called to update the database.
8163      *
8164      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8165      * it might be more efficient to use a version of
8166      * <code>updateNCharacterStream</code> which takes a length parameter.
8167      *
8168      * @param columnIndex the first column is 1, the second is 2, ...
8169      * @param x the new column value
8170      * @exception SQLException if a database access error occurs,
8171      * the result set concurrency is <code>CONCUR_READ_ONLY</code> or this method is called on a closed result set
8172      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8173      * this method
8174      * @since 1.6
8175      */
8176     public void updateNCharacterStream(int columnIndex,
8177                              java.io.Reader x) throws SQLException {
8178         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8179     }
8180 
8181     /**
8182      * Updates the designated column with a character stream value.  The
8183      * driver does the necessary conversion from Java character format to
8184      * the national character set in the database.
8185      * It is intended for use when
8186      * updating  <code>NCHAR</code>,<code>NVARCHAR</code>
8187      * and <code>LONGNVARCHAR</code> columns.
8188      *
8189      * The updater methods are used to update column values in the
8190      * current row or the insert row.  The updater methods do not
8191      * update the underlying database; instead the <code>updateRow</code> or
8192      * <code>insertRow</code> methods are called to update the database.
8193      *
8194      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8195      * it might be more efficient to use a version of
8196      * <code>updateNCharacterStream</code> which takes a length parameter.
8197      *
8198      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8199 bel is the name of the column
8200      * @param reader the <code>java.io.Reader</code> object containing
8201      *        the new column value
8202      * @exception SQLException if a database access error occurs,
8203      * the result set concurrency is <code>CONCUR_READ_ONLY</code> or this method is called on a closed result set
8204       * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8205      * this method
8206      * @since 1.6
8207      */
8208     public void updateNCharacterStream(String columnLabel,
8209                              java.io.Reader reader) throws SQLException {
8210         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8211     }
8212 
8213 //////////////////////////
8214 
8215     /**
8216      * Updates the designated column using the given input stream, which
8217      * will have the specified number of bytes.
8218      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8219      * parameter, it may be more practical to send it via a
8220      * <code>java.io.InputStream</code>. Data will be read from the stream
8221      * as needed until end-of-file is reached.  The JDBC driver will
8222      * do any necessary conversion from ASCII to the database char format.
8223      *
8224      * <P><B>Note:</B> This stream object can either be a standard
8225      * Java stream object or your own subclass that implements the
8226      * standard interface.
8227      * <p>
8228      * The updater methods are used to update column values in the
8229      * current row or the insert row.  The updater methods do not
8230      * update the underlying database; instead the <code>updateRow</code> or
8231      * <code>insertRow</code> methods are called to update the database.
8232      *
8233      * @param columnIndex the first column is 1, the second is 2, ...
8234      * @param inputStream An object that contains the data to set the parameter
8235      * value to.
8236      * @param length the number of bytes in the parameter data.
8237      * @exception SQLException if a database access error occurs,
8238      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8239      * or this method is called on a closed result set
8240      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8241      * this method
8242      * @since 1.6
8243      */
8244     public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException{
8245         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8246     }
8247 
8248     /**
8249      * Updates the designated column using the given input stream, which
8250      * will have the specified number of bytes.
8251      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8252      * parameter, it may be more practical to send it via a
8253      * <code>java.io.InputStream</code>. Data will be read from the stream
8254      * as needed until end-of-file is reached.  The JDBC driver will
8255      * do any necessary conversion from ASCII to the database char format.
8256      *
8257      * <P><B>Note:</B> This stream object can either be a standard
8258      * Java stream object or your own subclass that implements the
8259      * standard interface.
8260      * <p>
8261      * The updater methods are used to update column values in the
8262      * current row or the insert row.  The updater methods do not
8263      * update the underlying database; instead the <code>updateRow</code> or
8264      * <code>insertRow</code> methods are called to update the database.
8265      *
8266      * @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
8267      * @param inputStream An object that contains the data to set the parameter
8268      * value to.
8269      * @param length the number of bytes in the parameter data.
8270      * @exception SQLException if a database access error occurs,
8271      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8272      * or this method is called on a closed result set
8273      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8274      * this method
8275      * @since 1.6
8276      */
8277     public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException {
8278         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8279     }
8280 
8281     /**
8282      * Updates the designated column using the given input stream.
8283      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8284      * parameter, it may be more practical to send it via a
8285      * <code>java.io.InputStream</code>. Data will be read from the stream
8286      * as needed until end-of-file is reached.  The JDBC driver will
8287      * do any necessary conversion from ASCII to the database char format.
8288      *
8289      * <P><B>Note:</B> This stream object can either be a standard
8290      * Java stream object or your own subclass that implements the
8291      * standard interface.
8292      *
8293      *  <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8294      * it might be more efficient to use a version of
8295      * <code>updateBlob</code> which takes a length parameter.
8296      * <p>
8297      * The updater methods are used to update column values in the
8298      * current row or the insert row.  The updater methods do not
8299      * update the underlying database; instead the <code>updateRow</code> or
8300      * <code>insertRow</code> methods are called to update the database.
8301      *
8302      * @param columnIndex the first column is 1, the second is 2, ...
8303      * @param inputStream An object that contains the data to set the parameter
8304      * value to.
8305      * @exception SQLException if a database access error occurs,
8306      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8307      * or this method is called on a closed result set
8308      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8309      * this method
8310      * @since 1.6
8311      */
8312     public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException {
8313         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8314     }
8315 
8316     /**
8317      * Updates the designated column using the given input stream.
8318      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8319      * parameter, it may be more practical to send it via a
8320      * <code>java.io.InputStream</code>. Data will be read from the stream
8321      * as needed until end-of-file is reached.  The JDBC driver will
8322      * do any necessary conversion from ASCII to the database char format.
8323      *
8324      * <P><B>Note:</B> This stream object can either be a standard
8325      * Java stream object or your own subclass that implements the
8326      * standard interface.
8327      *   <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8328      * it might be more efficient to use a version of
8329      * <code>updateBlob</code> which takes a length parameter.
8330      * <p>
8331      * The updater methods are used to update column values in the
8332      * current row or the insert row.  The updater methods do not
8333      * update the underlying database; instead the <code>updateRow</code> or
8334      * <code>insertRow</code> methods are called to update the database.
8335      *
8336      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8337 bel is the name of the column
8338      * @param inputStream An object that contains the data to set the parameter
8339      * value to.
8340      * @exception SQLException if a database access error occurs,
8341      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8342      * or this method is called on a closed result set
8343      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8344      * this method
8345      * @since 1.6
8346      */
8347     public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException {
8348         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8349     }
8350 
8351     /**
8352      * Updates the designated column using the given <code>Reader</code>
8353      * object, which is the given number of characters long.
8354      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8355      * parameter, it may be more practical to send it via a
8356      * <code>java.io.Reader</code> object. The data will be read from the stream
8357      * as needed until end-of-file is reached.  The JDBC driver will
8358      * do any necessary conversion from UNICODE to the database char format.
8359      *
8360      * <P><B>Note:</B> This stream object can either be a standard
8361      * Java stream object or your own subclass that implements the
8362      * standard interface.
8363      * <p>
8364      * The updater methods are used to update column values in the
8365      * current row or the insert row.  The updater methods do not
8366      * update the underlying database; instead the <code>updateRow</code> or
8367      * <code>insertRow</code> methods are called to update the database.
8368      *
8369      * @param columnIndex the first column is 1, the second is 2, ...
8370      * @param reader An object that contains the data to set the parameter value to.
8371      * @param length the number of characters in the parameter data.
8372      * @exception SQLException if a database access error occurs,
8373      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8374      * or this method is called on a closed result set
8375      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8376      * this method
8377      * @since 1.6
8378      */
8379     public void updateClob(int columnIndex,  Reader reader, long length) throws SQLException {
8380         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8381     }
8382 
8383     /**
8384      * Updates the designated column using the given <code>Reader</code>
8385      * object, which is the given number of characters long.
8386      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8387      * parameter, it may be more practical to send it via a
8388      * <code>java.io.Reader</code> object. The data will be read from the stream
8389      * as needed until end-of-file is reached.  The JDBC driver will
8390      * do any necessary conversion from UNICODE to the database char format.
8391      *
8392      * <P><B>Note:</B> This stream object can either be a standard
8393      * Java stream object or your own subclass that implements the
8394      * standard interface.
8395      * <p>
8396      * The updater methods are used to update column values in the
8397      * current row or the insert row.  The updater methods do not
8398      * update the underlying database; instead the <code>updateRow</code> or
8399      * <code>insertRow</code> methods are called to update the database.
8400      *
8401      * @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
8402      * @param reader An object that contains the data to set the parameter value to.
8403      * @param length the number of characters in the parameter data.
8404      * @exception SQLException if a database access error occurs,
8405      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8406      * or this method is called on a closed result set
8407      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8408      * this method
8409      * @since 1.6
8410      */
8411     public void updateClob(String columnLabel,  Reader reader, long length) throws SQLException {
8412         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8413     }
8414 
8415    /**
8416      * Updates the designated column using the given <code>Reader</code>
8417      * object.
8418      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8419      * parameter, it may be more practical to send it via a
8420      * <code>java.io.Reader</code> object. The data will be read from the stream
8421      * as needed until end-of-file is reached.  The JDBC driver will
8422      * do any necessary conversion from UNICODE to the database char format.
8423      *
8424      * <P><B>Note:</B> This stream object can either be a standard
8425      * Java stream object or your own subclass that implements the
8426      * standard interface.
8427      *   <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8428      * it might be more efficient to use a version of
8429      * <code>updateClob</code> which takes a length parameter.
8430      * <p>
8431      * The updater methods are used to update column values in the
8432      * current row or the insert row.  The updater methods do not
8433      * update the underlying database; instead the <code>updateRow</code> or
8434      * <code>insertRow</code> methods are called to update the database.
8435      *
8436      * @param columnIndex the first column is 1, the second is 2, ...
8437      * @param reader An object that contains the data to set the parameter value to.
8438      * @exception SQLException if a database access error occurs,
8439      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8440      * or this method is called on a closed result set
8441      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8442      * this method
8443      * @since 1.6
8444      */
8445     public void updateClob(int columnIndex,  Reader reader) throws SQLException {
8446         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8447     }
8448 
8449     /**
8450      * Updates the designated column using the given <code>Reader</code>
8451      * object.
8452      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8453      * parameter, it may be more practical to send it via a
8454      * <code>java.io.Reader</code> object. The data will be read from the stream
8455      * as needed until end-of-file is reached.  The JDBC driver will
8456      * do any necessary conversion from UNICODE to the database char format.
8457      *
8458      * <P><B>Note:</B> This stream object can either be a standard
8459      * Java stream object or your own subclass that implements the
8460      * standard interface.
8461      *  <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8462      * it might be more efficient to use a version of
8463      * <code>updateClob</code> which takes a length parameter.
8464      * <p>
8465      * The updater methods are used to update column values in the
8466      * current row or the insert row.  The updater methods do not
8467      * update the underlying database; instead the <code>updateRow</code> or
8468      * <code>insertRow</code> methods are called to update the database.
8469      *
8470      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8471 bel is the name of the column
8472      * @param reader An object that contains the data to set the parameter value to.
8473      * @exception SQLException if a database access error occurs,
8474      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8475      * or this method is called on a closed result set
8476      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8477      * this method
8478      * @since 1.6
8479      */
8480     public void updateClob(String columnLabel,  Reader reader) throws SQLException {
8481         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8482     }
8483 
8484    /**
8485      * Updates the designated column using the given <code>Reader</code>
8486      * object, which is the given number of characters long.
8487      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8488      * parameter, it may be more practical to send it via a
8489      * <code>java.io.Reader</code> object. The data will be read from the stream
8490      * as needed until end-of-file is reached.  The JDBC driver will
8491      * do any necessary conversion from UNICODE to the database char format.
8492      *
8493      * <P><B>Note:</B> This stream object can either be a standard
8494      * Java stream object or your own subclass that implements the
8495      * standard interface.
8496      * <p>
8497      * The updater methods are used to update column values in the
8498      * current row or the insert row.  The updater methods do not
8499      * update the underlying database; instead the <code>updateRow</code> or
8500      * <code>insertRow</code> methods are called to update the database.
8501      *
8502      * @param columnIndex the first column is 1, the second 2, ...
8503      * @param reader An object that contains the data to set the parameter value to.
8504      * @param length the number of characters in the parameter data.
8505      * @throws SQLException if the driver does not support national
8506      *         character sets;  if the driver can detect that a data conversion
8507      *  error could occur; this method is called on a closed result set,
8508      * if a database access error occurs or
8509      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8510      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8511      * this method
8512      * @since 1.6
8513      */
8514     public void updateNClob(int columnIndex,  Reader reader, long length) throws SQLException {
8515         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8516     }
8517 
8518     /**
8519      * Updates the designated column using the given <code>Reader</code>
8520      * object, which is the given number of characters long.
8521      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8522      * parameter, it may be more practical to send it via a
8523      * <code>java.io.Reader</code> object. The data will be read from the stream
8524      * as needed until end-of-file is reached.  The JDBC driver will
8525      * do any necessary conversion from UNICODE to the database char format.
8526      *
8527      * <P><B>Note:</B> This stream object can either be a standard
8528      * Java stream object or your own subclass that implements the
8529      * standard interface.
8530      * <p>
8531      * The updater methods are used to update column values in the
8532      * current row or the insert row.  The updater methods do not
8533      * update the underlying database; instead the <code>updateRow</code> or
8534      * <code>insertRow</code> methods are called to update the database.
8535      *
8536      * @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
8537      * @param reader An object that contains the data to set the parameter value to.
8538      * @param length the number of characters in the parameter data.
8539      * @throws SQLException if the driver does not support national
8540      *         character sets;  if the driver can detect that a data conversion
8541      *  error could occur; this method is called on a closed result set;
8542      *  if a database access error occurs or
8543      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8544      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8545      * this method
8546      * @since 1.6
8547      */
8548     public void updateNClob(String columnLabel,  Reader reader, long length) throws SQLException {
8549         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8550     }
8551 
8552     /**
8553      * Updates the designated column using the given <code>Reader</code>
8554      * object.
8555      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8556      * parameter, it may be more practical to send it via a
8557      * <code>java.io.Reader</code> object. The data will be read from the stream
8558      * as needed until end-of-file is reached.  The JDBC driver will
8559      * do any necessary conversion from UNICODE to the database char format.
8560      *
8561      * <P><B>Note:</B> This stream object can either be a standard
8562      * Java stream object or your own subclass that implements the
8563      * standard interface.
8564      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8565      * it might be more efficient to use a version of
8566      * <code>updateNClob</code> which takes a length parameter.
8567      * <p>
8568      * The updater methods are used to update column values in the
8569      * current row or the insert row.  The updater methods do not
8570      * update the underlying database; instead the <code>updateRow</code> or
8571      * <code>insertRow</code> methods are called to update the database.
8572      *
8573      * @param columnIndex the first column is 1, the second 2, ...
8574      * @param reader An object that contains the data to set the parameter value to.
8575      * @throws SQLException if the driver does not support national
8576      *         character sets;  if the driver can detect that a data conversion
8577      *  error could occur; this method is called on a closed result set,
8578      * if a database access error occurs or
8579      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8580      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8581      * this method
8582      * @since 1.6
8583      */
8584     public void updateNClob(int columnIndex,  Reader reader) throws SQLException {
8585         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8586     }
8587 
8588     /**
8589      * Updates the designated column using the given <code>Reader</code>
8590      * object.
8591      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8592      * parameter, it may be more practical to send it via a
8593      * <code>java.io.Reader</code> object. The data will be read from the stream
8594      * as needed until end-of-file is reached.  The JDBC driver will
8595      * do any necessary conversion from UNICODE to the database char format.
8596      *
8597      * <P><B>Note:</B> This stream object can either be a standard
8598      * Java stream object or your own subclass that implements the
8599      * standard interface.
8600      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8601      * it might be more efficient to use a version of
8602      * <code>updateNClob</code> which takes a length parameter.
8603      * <p>
8604      * The updater methods are used to update column values in the
8605      * current row or the insert row.  The updater methods do not
8606      * update the underlying database; instead the <code>updateRow</code> or
8607      * <code>insertRow</code> methods are called to update the database.
8608      *
8609      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8610 bel is the name of the column
8611      * @param reader An object that contains the data to set the parameter value to.
8612      * @throws SQLException if the driver does not support national
8613      *         character sets;  if the driver can detect that a data conversion
8614      *  error could occur; this method is called on a closed result set;
8615      *  if a database access error occurs or
8616      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8617      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8618      * this method
8619      * @since 1.6
8620      */
8621     public void updateNClob(String columnLabel,  Reader reader) throws SQLException {
8622         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8623     }
8624 
8625         /**
8626      * Updates the designated column with an ascii stream value, which will have
8627      * the specified number of bytes.
8628      * The updater methods are used to update column values in the
8629      * current row or the insert row.  The updater methods do not
8630      * update the underlying database; instead the <code>updateRow</code> or
8631      * <code>insertRow</code> methods are called to update the database.
8632      *
8633      * @param columnIndex the first column is 1, the second is 2, ...
8634      * @param x the new column value
8635      * @param length the length of the stream
8636      * @exception SQLException if a database access error occurs,
8637      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8638      * or this method is called on a closed result set
8639      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8640      * this method
8641      * @since 1.6
8642      */
8643     public void updateAsciiStream(int columnIndex,
8644                            java.io.InputStream x,
8645                            long length) throws SQLException {
8646 
8647     }
8648 
8649     /**
8650      * Updates the designated column with a binary stream value, which will have
8651      * the specified number of bytes.
8652      * The updater methods are used to update column values in the
8653      * current row or the insert row.  The updater methods do not
8654      * update the underlying database; instead the <code>updateRow</code> or
8655      * <code>insertRow</code> methods are called to update the database.
8656      *
8657      * @param columnIndex the first column is 1, the second is 2, ...
8658      * @param x the new column value
8659      * @param length the length of the stream
8660      * @exception SQLException if a database access error occurs,
8661      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8662      * or this method is called on a closed result set
8663      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8664      * this method
8665      * @since 1.6
8666      */
8667     public void updateBinaryStream(int columnIndex,
8668                             java.io.InputStream x,
8669                             long length) throws SQLException {
8670     }
8671 
8672     /**
8673      * Updates the designated column with a character stream value, which will have
8674      * the specified number of bytes.
8675      * The updater methods are used to update column values in the
8676      * current row or the insert row.  The updater methods do not
8677      * update the underlying database; instead the <code>updateRow</code> or
8678      * <code>insertRow</code> methods are called to update the database.
8679      *
8680      * @param columnIndex the first column is 1, the second is 2, ...
8681      * @param x the new column value
8682      * @param length the length of the stream
8683      * @exception SQLException if a database access error occurs,
8684      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8685      * or this method is called on a closed result set
8686      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8687      * this method
8688      * @since 1.6
8689      */
8690     public void updateCharacterStream(int columnIndex,
8691                              java.io.Reader x,
8692                              long length) throws SQLException {
8693         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8694     }
8695 
8696     /**
8697      * Updates the designated column with a character stream value, which will have
8698      * the specified number of bytes.
8699      * The updater methods are used to update column values in the
8700      * current row or the insert row.  The updater methods do not
8701      * update the underlying database; instead the <code>updateRow</code> or
8702      * <code>insertRow</code> methods are called to update the database.
8703      *
8704      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8705 bel is the name of the column
8706      * @param reader the <code>java.io.Reader</code> object containing
8707      *        the new column value
8708      * @param length the length of the stream
8709      * @exception SQLException if a database access error occurs,
8710      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8711      * or this method is called on a closed result set
8712      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8713      * this method
8714      * @since 1.6
8715      */
8716     public void updateCharacterStream(String columnLabel,
8717                              java.io.Reader reader,
8718                              long length) throws SQLException {
8719         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8720     }
8721      /**
8722      * Updates the designated column with an ascii stream value, which will have
8723      * the specified number of bytes..
8724      * The updater methods are used to update column values in the
8725      * current row or the insert row.  The updater methods do not
8726      * update the underlying database; instead the <code>updateRow</code> or
8727      * <code>insertRow</code> methods are called to update the database.
8728      *
8729      * @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
8730      * @param x the new column value
8731      * @param length the length of the stream
8732      * @exception SQLException if a database access error occurs,
8733      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8734      * or this method is called on a closed result set
8735      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8736      * this method
8737      * @since 1.6
8738      */
8739     public void updateAsciiStream(String columnLabel,
8740                            java.io.InputStream x,
8741                            long length) throws SQLException {
8742     }
8743 
8744     /**
8745      * Updates the designated column with a binary stream value, which will have
8746      * the specified number of bytes.
8747      * The updater methods are used to update column values in the
8748      * current row or the insert row.  The updater methods do not
8749      * update the underlying database; instead the <code>updateRow</code> or
8750      * <code>insertRow</code> methods are called to update the database.
8751      *
8752      * @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
8753      * @param x the new column value
8754      * @param length the length of the stream
8755      * @exception SQLException if a database access error occurs,
8756      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8757      * or this method is called on a closed result set
8758      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8759      * this method
8760      * @since 1.6
8761      */
8762     public void updateBinaryStream(String columnLabel,
8763                             java.io.InputStream x,
8764                             long length) throws SQLException {
8765     }
8766 
8767     /**
8768      * Updates the designated column with a binary stream value.
8769      * The updater methods are used to update column values in the
8770      * current row or the insert row.  The updater methods do not
8771      * update the underlying database; instead the <code>updateRow</code> or
8772      * <code>insertRow</code> methods are called to update the database.
8773      *
8774      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8775      * it might be more efficient to use a version of
8776      * <code>updateBinaryStream</code> which takes a length parameter.
8777      *
8778      * @param columnIndex the first column is 1, the second is 2, ...
8779      * @param x the new column value
8780      * @exception SQLException if a database access error occurs,
8781      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8782      * or this method is called on a closed result set
8783      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8784      * this method
8785      * @since 1.6
8786      */
8787     public void updateBinaryStream(int columnIndex,
8788                             java.io.InputStream x) throws SQLException {
8789         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8790     }
8791 
8792 
8793     /**
8794      * Updates the designated column with a binary stream value.
8795      * The updater methods are used to update column values in the
8796      * current row or the insert row.  The updater methods do not
8797      * update the underlying database; instead the <code>updateRow</code> or
8798      * <code>insertRow</code> methods are called to update the database.
8799      *
8800      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8801      * it might be more efficient to use a version of
8802      * <code>updateBinaryStream</code> which takes a length parameter.
8803      *
8804      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8805 bel is the name of the column
8806      * @param x the new column value
8807      * @exception SQLException if a database access error occurs,
8808      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8809      * or this method is called on a closed result set
8810      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8811      * this method
8812      * @since 1.6
8813      */
8814     public void updateBinaryStream(String columnLabel,
8815                             java.io.InputStream x) throws SQLException {
8816         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8817     }
8818 
8819     /**
8820      * Updates the designated column with a character stream value.
8821      * The updater methods are used to update column values in the
8822      * current row or the insert row.  The updater methods do not
8823      * update the underlying database; instead the <code>updateRow</code> or
8824      * <code>insertRow</code> methods are called to update the database.
8825      *
8826      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8827      * it might be more efficient to use a version of
8828      * <code>updateCharacterStream</code> which takes a length parameter.
8829      *
8830      * @param columnIndex the first column is 1, the second is 2, ...
8831      * @param x the new column value
8832      * @exception SQLException if a database access error occurs,
8833      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8834      * or this method is called on a closed result set
8835      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8836      * this method
8837      * @since 1.6
8838      */
8839     public void updateCharacterStream(int columnIndex,
8840                              java.io.Reader x) throws SQLException {
8841         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8842     }
8843 
8844     /**
8845      * Updates the designated column with a character stream value.
8846      * The updater methods are used to update column values in the
8847      * current row or the insert row.  The updater methods do not
8848      * update the underlying database; instead the <code>updateRow</code> or
8849      * <code>insertRow</code> methods are called to update the database.
8850      *
8851      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8852      * it might be more efficient to use a version of
8853      * <code>updateCharacterStream</code> which takes a length parameter.
8854      *
8855      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8856 bel is the name of the column
8857      * @param reader the <code>java.io.Reader</code> object containing
8858      *        the new column value
8859      * @exception SQLException if a database access error occurs,
8860      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8861      * or this method is called on a closed result set
8862      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8863      * this method
8864      * @since 1.6
8865      */
8866     public void updateCharacterStream(String columnLabel,
8867                              java.io.Reader reader) throws SQLException {
8868         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8869     }
8870 
8871     /**
8872      * Updates the designated column with an ascii stream value.
8873      * The updater methods are used to update column values in the
8874      * current row or the insert row.  The updater methods do not
8875      * update the underlying database; instead the <code>updateRow</code> or
8876      * <code>insertRow</code> methods are called to update the database.
8877      *
8878      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8879      * it might be more efficient to use a version of
8880      * <code>updateAsciiStream</code> which takes a length parameter.
8881      *
8882      * @param columnIndex the first column is 1, the second is 2, ...
8883      * @param x the new column value
8884      * @exception SQLException if a database access error occurs,
8885      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8886      * or this method is called on a closed result set
8887      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8888      * this method
8889      * @since 1.6
8890      */
8891     public void updateAsciiStream(int columnIndex,
8892                            java.io.InputStream x) throws SQLException {
8893         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8894     }
8895 
8896     /**
8897      * Updates the designated column with an ascii stream value.
8898      * The updater methods are used to update column values in the
8899      * current row or the insert row.  The updater methods do not
8900      * update the underlying database; instead the <code>updateRow</code> or
8901      * <code>insertRow</code> methods are called to update the database.
8902      *
8903      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8904      * it might be more efficient to use a version of
8905      * <code>updateAsciiStream</code> which takes a length parameter.
8906      *
8907      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8908 bel is the name of the column
8909      * @param x the new column value
8910      * @exception SQLException if a database access error occurs,
8911      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8912      * or this method is called on a closed result set
8913      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8914      * this method
8915      * @since 1.6
8916      */
8917     public void updateAsciiStream(String columnLabel,
8918                            java.io.InputStream x) throws SQLException {
8919 
8920     }
8921 
8922    /**
8923   * Sets the designated parameter to the given <code>java.net.URL</code> value.
8924   * The driver converts this to an SQL <code>DATALINK</code> value
8925   * when it sends it to the database.
8926   *
8927   * @param parameterIndex the first parameter is 1, the second is 2, ...
8928   * @param x the <code>java.net.URL</code> object to be set
8929   * @exception SQLException if a database access error occurs or
8930   * this method is called on a closed <code>PreparedStatement</code>
8931   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
8932   * @since 1.4
8933   */
8934   public void setURL(int parameterIndex, java.net.URL x) throws SQLException{
8935         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8936    }
8937 
8938   /**
8939   * Sets the designated parameter to a <code>Reader</code> object.
8940   * This method differs from the <code>setCharacterStream (int, Reader)</code> method
8941   * because it informs the driver that the parameter value should be sent to
8942   * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
8943   * driver may have to do extra work to determine whether the parameter
8944   * data should be sent to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
8945   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8946   * it might be more efficient to use a version of
8947   * <code>setNClob</code> which takes a length parameter.
8948   *
8949   * @param parameterIndex index of the first parameter is 1, the second is 2, ...
8950   * @param reader An object that contains the data to set the parameter value to.
8951   * @throws SQLException if parameterIndex does not correspond to a parameter
8952   * marker in the SQL statement;
8953   * if the driver does not support national character sets;
8954   * if the driver can detect that a data conversion
8955   *  error could occur;  if a database access error occurs or
8956   * this method is called on a closed <code>PreparedStatement</code>
8957   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
8958   *
8959   * @since 1.6
8960   */
8961   public void setNClob(int parameterIndex, Reader reader)
8962     throws SQLException{
8963         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8964    }
8965 
8966   /**
8967   * Sets the designated parameter to a <code>Reader</code> object.  The <code>reader</code> must contain  the number
8968              * of characters specified by length otherwise a <code>SQLException</code> will be
8969             * generated when the <code>CallableStatement</code> is executed.
8970             * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
8971             * because it informs the driver that the parameter value should be sent to
8972             * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
8973             * driver may have to do extra work to determine whether the parameter
8974             * data should be send to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
8975             *
8976             * @param parameterName the name of the parameter to be set
8977             * @param reader An object that contains the data to set the parameter value to.
8978             * @param length the number of characters in the parameter data.
8979             * @throws SQLException if parameterIndex does not correspond to a parameter
8980             * marker in the SQL statement; if the length specified is less than zero;
8981             * if the driver does not support national
8982             *         character sets;  if the driver can detect that a data conversion
8983             *  error could occur; if a database access error occurs or
8984             * this method is called on a closed <code>CallableStatement</code>
8985             * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8986             * this method
8987             * @since 1.6
8988             */
8989             public void setNClob(String parameterName, Reader reader, long length)
8990     throws SQLException{
8991         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8992    }
8993 
8994 
8995  /**
8996   * Sets the designated parameter to a <code>Reader</code> object.
8997   * This method differs from the <code>setCharacterStream (int, Reader)</code> method
8998   * because it informs the driver that the parameter value should be sent to
8999   * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9000   * driver may have to do extra work to determine whether the parameter
9001   * data should be send to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
9002   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9003   * it might be more efficient to use a version of
9004   * <code>setNClob</code> which takes a length parameter.
9005   *
9006   * @param parameterName the name of the parameter
9007   * @param reader An object that contains the data to set the parameter value to.
9008   * @throws SQLException if the driver does not support national character sets;
9009   * if the driver can detect that a data conversion
9010   *  error could occur;  if a database access error occurs or
9011   * this method is called on a closed <code>CallableStatement</code>
9012   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9013   *
9014   * @since 1.6
9015   */
9016   public void setNClob(String parameterName, Reader reader)
9017     throws SQLException{
9018         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9019    }
9020 
9021 
9022     /**
9023      * Sets the designated parameter to a <code>Reader</code> object.  The reader must contain  the number
9024      * of characters specified by length otherwise a <code>SQLException</code> will be
9025      * generated when the <code>PreparedStatement</code> is executed.
9026      * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
9027      * because it informs the driver that the parameter value should be sent to
9028      * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9029      * driver may have to do extra work to determine whether the parameter
9030      * data should be sent to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
9031      * @param parameterIndex index of the first parameter is 1, the second is 2, ...
9032      * @param reader An object that contains the data to set the parameter value to.
9033      * @param length the number of characters in the parameter data.
9034      * @throws SQLException if parameterIndex does not correspond to a parameter
9035      * marker in the SQL statement; if the length specified is less than zero;
9036      * if the driver does not support national character sets;
9037      * if the driver can detect that a data conversion
9038      *  error could occur;  if a database access error occurs or
9039      * this method is called on a closed <code>PreparedStatement</code>
9040      * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9041      *
9042      * @since 1.6
9043      */
9044      public void setNClob(int parameterIndex, Reader reader, long length)
9045        throws SQLException{
9046         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9047    }
9048 
9049 
9050     /**
9051      * Sets the designated parameter to a <code>java.sql.NClob</code> object. The driver converts this to
9052 a
9053      * SQL <code>NCLOB</code> value when it sends it to the database.
9054      * @param parameterIndex of the first parameter is 1, the second is 2, ...
9055      * @param value the parameter value
9056      * @throws SQLException if the driver does not support national
9057      *         character sets;  if the driver can detect that a data conversion
9058      *  error could occur ; or if a database access error occurs
9059      * @since 1.6
9060      */
9061      public void setNClob(int parameterIndex, NClob value) throws SQLException{
9062         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9063    }
9064 
9065 
9066    /**
9067   * Sets the designated paramter to the given <code>String</code> object.
9068   * The driver converts this to a SQL <code>NCHAR</code> or
9069   * <code>NVARCHAR</code> or <code>LONGNVARCHAR</code> value
9070   * (depending on the argument's
9071   * size relative to the driver's limits on <code>NVARCHAR</code> values)
9072   * when it sends it to the database.
9073   *
9074   * @param parameterIndex of the first parameter is 1, the second is 2, ...
9075   * @param value the parameter value
9076   * @throws SQLException if the driver does not support national
9077   *         character sets;  if the driver can detect that a data conversion
9078   *  error could occur ; or if a database access error occurs
9079   * @since 1.6
9080   */
9081   public void setNString(int parameterIndex, String value) throws SQLException{
9082         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9083    }
9084 
9085 
9086  /**
9087   * Sets the designated paramter to the given <code>String</code> object.
9088   * The driver converts this to a SQL <code>NCHAR</code> or
9089   * <code>NVARCHAR</code> or <code>LONGNVARCHAR</code>
9090   * @param parameterName the name of the column to be set
9091   * @param value the parameter value
9092   * @throws SQLException if the driver does not support national
9093   *         character sets;  if the driver can detect that a data conversion
9094   *  error could occur; or if a database access error occurs
9095   * @since 1.6
9096   */
9097  public void setNString(String parameterName, String value)
9098          throws SQLException{
9099         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9100    }
9101 
9102 
9103  /**
9104   * Sets the designated parameter to a <code>Reader</code> object. The
9105   * <code>Reader</code> reads the data till end-of-file is reached. The
9106   * driver does the necessary conversion from Java character format to
9107   * the national character set in the database.
9108   * @param parameterIndex of the first parameter is 1, the second is 2, ...
9109   * @param value the parameter value
9110   * @param length the number of characters in the parameter data.
9111   * @throws SQLException if the driver does not support national
9112   *         character sets;  if the driver can detect that a data conversion
9113   *  error could occur ; or if a database access error occurs
9114   * @since 1.6
9115   */
9116   public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException{
9117         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9118    }
9119 
9120 
9121  /**
9122   * Sets the designated parameter to a <code>Reader</code> object. The
9123   * <code>Reader</code> reads the data till end-of-file is reached. The
9124   * driver does the necessary conversion from Java character format to
9125   * the national character set in the database.
9126   * @param parameterName the name of the column to be set
9127   * @param value the parameter value
9128   * @param length the number of characters in the parameter data.
9129   * @throws SQLException if the driver does not support national
9130   *         character sets;  if the driver can detect that a data conversion
9131   *  error could occur; or if a database access error occurs
9132   * @since 1.6
9133   */
9134  public void setNCharacterStream(String parameterName, Reader value, long length)
9135          throws SQLException{
9136         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9137    }
9138 
9139   /**
9140   * Sets the designated parameter to a <code>Reader</code> object. The
9141   * <code>Reader</code> reads the data till end-of-file is reached. The
9142   * driver does the necessary conversion from Java character format to
9143   * the national character set in the database.
9144 
9145   * <P><B>Note:</B> This stream object can either be a standard
9146   * Java stream object or your own subclass that implements the
9147   * standard interface.
9148   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9149   * it might be more efficient to use a version of
9150   * <code>setNCharacterStream</code> which takes a length parameter.
9151   *
9152   * @param parameterName the name of the parameter
9153   * @param value the parameter value
9154   * @throws SQLException if the driver does not support national
9155   *         character sets;  if the driver can detect that a data conversion
9156   *  error could occur ; if a database access error occurs; or
9157   * this method is called on a closed <code>CallableStatement</code>
9158   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9159   * @since 1.6
9160   */
9161   public void setNCharacterStream(String parameterName, Reader value) throws SQLException{
9162         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9163    }
9164 
9165   /**
9166     * Sets the designated parameter to the given <code>java.sql.Timestamp</code> value,
9167     * using the given <code>Calendar</code> object.  The driver uses
9168     * the <code>Calendar</code> object to construct an SQL <code>TIMESTAMP</code> value,
9169     * which the driver then sends to the database.  With a
9170     * a <code>Calendar</code> object, the driver can calculate the timestamp
9171     * taking into account a custom timezone.  If no
9172     * <code>Calendar</code> object is specified, the driver uses the default
9173     * timezone, which is that of the virtual machine running the application.
9174     *
9175     * @param parameterName the name of the parameter
9176     * @param x the parameter value
9177     * @param cal the <code>Calendar</code> object the driver will use
9178     *            to construct the timestamp
9179     * @exception SQLException if a database access error occurs or
9180     * this method is called on a closed <code>CallableStatement</code>
9181     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9182     * this method
9183     * @see #getTimestamp
9184     * @since 1.4
9185     */
9186     public void setTimestamp(String parameterName, java.sql.Timestamp x, Calendar cal)
9187        throws SQLException{
9188         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9189    }
9190 
9191     /**
9192     * Sets the designated parameter to a <code>Reader</code> object.  The <code>reader</code> must contain  the number
9193                * of characters specified by length otherwise a <code>SQLException</code> will be
9194                * generated when the <code>CallableStatement</code> is executed.
9195               * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
9196               * because it informs the driver that the parameter value should be sent to
9197               * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9198               * driver may have to do extra work to determine whether the parameter
9199               * data should be send to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9200               * @param parameterName the name of the parameter to be set
9201               * @param reader An object that contains the data to set the parameter value to.
9202               * @param length the number of characters in the parameter data.
9203               * @throws SQLException if parameterIndex does not correspond to a parameter
9204               * marker in the SQL statement; if the length specified is less than zero;
9205               * a database access error occurs or
9206               * this method is called on a closed <code>CallableStatement</code>
9207               * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9208               * this method
9209               *
9210               * @since 1.6
9211               */
9212       public  void setClob(String parameterName, Reader reader, long length)
9213       throws SQLException{
9214         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9215    }
9216 
9217 
9218   /**
9219     * Sets the designated parameter to the given <code>java.sql.Clob</code> object.
9220     * The driver converts this to an SQL <code>CLOB</code> value when it
9221     * sends it to the database.
9222     *
9223     * @param parameterName the name of the parameter
9224     * @param x a <code>Clob</code> object that maps an SQL <code>CLOB</code> value
9225     * @exception SQLException if a database access error occurs or
9226     * this method is called on a closed <code>CallableStatement</code>
9227     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9228     * this method
9229     * @since 1.6
9230     */
9231     public void setClob (String parameterName, Clob x) throws SQLException{
9232         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9233    }
9234 
9235 
9236  /**
9237     * Sets the designated parameter to a <code>Reader</code> object.
9238     * This method differs from the <code>setCharacterStream (int, Reader)</code> method
9239     * because it informs the driver that the parameter value should be sent to
9240     * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9241     * driver may have to do extra work to determine whether the parameter
9242     * data should be send to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9243     *
9244     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9245     * it might be more efficient to use a version of
9246     * <code>setClob</code> which takes a length parameter.
9247     *
9248     * @param parameterName the name of the parameter
9249     * @param reader An object that contains the data to set the parameter value to.
9250     * @throws SQLException if a database access error occurs or this method is called on
9251     * a closed <code>CallableStatement</code>
9252     *
9253     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9254     * @since 1.6
9255     */
9256     public void setClob(String parameterName, Reader reader)
9257       throws SQLException{
9258         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9259    }
9260 
9261 
9262  /**
9263     * Sets the designated parameter to the given <code>java.sql.Date</code> value
9264     * using the default time zone of the virtual machine that is running
9265     * the application.
9266     * The driver converts this
9267     * to an SQL <code>DATE</code> value when it sends it to the database.
9268     *
9269     * @param parameterName the name of the parameter
9270     * @param x the parameter value
9271     * @exception SQLException if a database access error occurs or
9272     * this method is called on a closed <code>CallableStatement</code>
9273     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9274     * this method
9275     * @see #getDate
9276     * @since 1.4
9277     */
9278     public void setDate(String parameterName, java.sql.Date x)
9279        throws SQLException{
9280         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9281    }
9282 
9283 
9284  /**
9285     * Sets the designated parameter to the given <code>java.sql.Date</code> value,
9286     * using the given <code>Calendar</code> object.  The driver uses
9287     * the <code>Calendar</code> object to construct an SQL <code>DATE</code> value,
9288     * which the driver then sends to the database.  With a
9289     * a <code>Calendar</code> object, the driver can calculate the date
9290     * taking into account a custom timezone.  If no
9291     * <code>Calendar</code> object is specified, the driver uses the default
9292     * timezone, which is that of the virtual machine running the application.
9293     *
9294     * @param parameterName the name of the parameter
9295     * @param x the parameter value
9296     * @param cal the <code>Calendar</code> object the driver will use
9297     *            to construct the date
9298     * @exception SQLException if a database access error occurs or
9299     * this method is called on a closed <code>CallableStatement</code>
9300     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9301     * this method
9302     * @see #getDate
9303     * @since 1.4
9304     */
9305    public void setDate(String parameterName, java.sql.Date x, Calendar cal)
9306        throws SQLException{
9307         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9308    }
9309 
9310 
9311  /**
9312     * Sets the designated parameter to the given <code>java.sql.Time</code> value.
9313     * The driver converts this
9314     * to an SQL <code>TIME</code> value when it sends it to the database.
9315     *
9316     * @param parameterName the name of the parameter
9317     * @param x the parameter value
9318     * @exception SQLException if a database access error occurs or
9319     * this method is called on a closed <code>CallableStatement</code>
9320     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9321     * this method
9322     * @see #getTime
9323     * @since 1.4
9324     */
9325    public void setTime(String parameterName, java.sql.Time x)
9326        throws SQLException{
9327         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9328    }
9329 
9330 
9331  /**
9332     * Sets the designated parameter to the given <code>java.sql.Time</code> value,
9333     * using the given <code>Calendar</code> object.  The driver uses
9334     * the <code>Calendar</code> object to construct an SQL <code>TIME</code> value,
9335     * which the driver then sends to the database.  With a
9336     * a <code>Calendar</code> object, the driver can calculate the time
9337     * taking into account a custom timezone.  If no
9338     * <code>Calendar</code> object is specified, the driver uses the default
9339     * timezone, which is that of the virtual machine running the application.
9340     *
9341     * @param parameterName the name of the parameter
9342     * @param x the parameter value
9343     * @param cal the <code>Calendar</code> object the driver will use
9344     *            to construct the time
9345     * @exception SQLException if a database access error occurs or
9346     * this method is called on a closed <code>CallableStatement</code>
9347     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9348     * this method
9349     * @see #getTime
9350     * @since 1.4
9351     */
9352    public void setTime(String parameterName, java.sql.Time x, Calendar cal)
9353        throws SQLException{
9354         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9355    }
9356 
9357    /**
9358    * Sets the designated parameter to a <code>Reader</code> object.
9359    * This method differs from the <code>setCharacterStream (int, Reader)</code> method
9360    * because it informs the driver that the parameter value should be sent to
9361    * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9362    * driver may have to do extra work to determine whether the parameter
9363    * data should be sent to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9364    *
9365    * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9366    * it might be more efficient to use a version of
9367    * <code>setClob</code> which takes a length parameter.
9368    *
9369    * @param parameterIndex index of the first parameter is 1, the second is 2, ...
9370    * @param reader An object that contains the data to set the parameter value to.
9371    * @throws SQLException if a database access error occurs, this method is called on
9372    * a closed <code>PreparedStatement</code>or if parameterIndex does not correspond to a parameter
9373    * marker in the SQL statement
9374    *
9375    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9376    * @since 1.6
9377    */
9378    public void setClob(int parameterIndex, Reader reader)
9379      throws SQLException{
9380         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9381    }
9382 
9383     /**
9384    * Sets the designated parameter to a <code>Reader</code> object.  The reader must contain  the number
9385    * of characters specified by length otherwise a <code>SQLException</code> will be
9386    * generated when the <code>PreparedStatement</code> is executed.
9387    *This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
9388    * because it informs the driver that the parameter value should be sent to
9389    * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9390    * driver may have to do extra work to determine whether the parameter
9391    * data should be sent to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9392    * @param parameterIndex index of the first parameter is 1, the second is 2, ...
9393    * @param reader An object that contains the data to set the parameter value to.
9394    * @param length the number of characters in the parameter data.
9395    * @throws SQLException if a database access error occurs, this method is called on
9396    * a closed <code>PreparedStatement</code>, if parameterIndex does not correspond to a parameter
9397    * marker in the SQL statement, or if the length specified is less than zero.
9398    *
9399    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9400    * @since 1.6
9401    */
9402    public void setClob(int parameterIndex, Reader reader, long length)
9403      throws SQLException{
9404         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9405    }
9406 
9407 
9408  /**
9409     * Sets the designated parameter to a <code>InputStream</code> object.  The inputstream must contain  the number
9410     * of characters specified by length otherwise a <code>SQLException</code> will be
9411     * generated when the <code>PreparedStatement</code> is executed.
9412     * This method differs from the <code>setBinaryStream (int, InputStream, int)</code>
9413     * method because it informs the driver that the parameter value should be
9414     * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9415     * the driver may have to do extra work to determine whether the parameter
9416     * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9417     * @param parameterIndex index of the first parameter is 1,
9418     * the second is 2, ...
9419     * @param inputStream An object that contains the data to set the parameter
9420     * value to.
9421     * @param length the number of bytes in the parameter data.
9422     * @throws SQLException if a database access error occurs,
9423     * this method is called on a closed <code>PreparedStatement</code>,
9424     * if parameterIndex does not correspond
9425     * to a parameter marker in the SQL statement,  if the length specified
9426     * is less than zero or if the number of bytes in the inputstream does not match
9427     * the specfied length.
9428     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9429     *
9430     * @since 1.6
9431     */
9432     public void setBlob(int parameterIndex, InputStream inputStream, long length)
9433        throws SQLException{
9434         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9435    }
9436 
9437 
9438  /**
9439     * Sets the designated parameter to a <code>InputStream</code> object.
9440     * This method differs from the <code>setBinaryStream (int, InputStream)</code>
9441     * method because it informs the driver that the parameter value should be
9442     * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9443     * the driver may have to do extra work to determine whether the parameter
9444     * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9445     *
9446     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9447     * it might be more efficient to use a version of
9448     * <code>setBlob</code> which takes a length parameter.
9449     *
9450     * @param parameterIndex index of the first parameter is 1,
9451     * the second is 2, ...
9452     * @param inputStream An object that contains the data to set the parameter
9453     * value to.
9454     * @throws SQLException if a database access error occurs,
9455     * this method is called on a closed <code>PreparedStatement</code> or
9456     * if parameterIndex does not correspond
9457     * to a parameter marker in the SQL statement,
9458     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9459     *
9460     * @since 1.6
9461     */
9462     public void setBlob(int parameterIndex, InputStream inputStream)
9463        throws SQLException{
9464         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9465    }
9466 
9467 
9468  /**
9469     * Sets the designated parameter to a <code>InputStream</code> object.  The <code>inputstream</code> must contain  the number
9470      * of characters specified by length, otherwise a <code>SQLException</code> will be
9471      * generated when the <code>CallableStatement</code> is executed.
9472      * This method differs from the <code>setBinaryStream (int, InputStream, int)</code>
9473      * method because it informs the driver that the parameter value should be
9474      * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9475      * the driver may have to do extra work to determine whether the parameter
9476      * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9477      *
9478      * @param parameterName the name of the parameter to be set
9479      * the second is 2, ...
9480      *
9481      * @param inputStream An object that contains the data to set the parameter
9482      * value to.
9483      * @param length the number of bytes in the parameter data.
9484      * @throws SQLException  if parameterIndex does not correspond
9485      * to a parameter marker in the SQL statement,  or if the length specified
9486      * is less than zero; if the number of bytes in the inputstream does not match
9487      * the specfied length; if a database access error occurs or
9488      * this method is called on a closed <code>CallableStatement</code>
9489      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9490      * this method
9491      *
9492      * @since 1.6
9493      */
9494      public void setBlob(String parameterName, InputStream inputStream, long length)
9495         throws SQLException{
9496         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9497    }
9498 
9499 
9500  /**
9501     * Sets the designated parameter to the given <code>java.sql.Blob</code> object.
9502     * The driver converts this to an SQL <code>BLOB</code> value when it
9503     * sends it to the database.
9504     *
9505     * @param parameterName the name of the parameter
9506     * @param x a <code>Blob</code> object that maps an SQL <code>BLOB</code> value
9507     * @exception SQLException if a database access error occurs or
9508     * this method is called on a closed <code>CallableStatement</code>
9509     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9510     * this method
9511     * @since 1.6
9512     */
9513    public void setBlob (String parameterName, Blob x) throws SQLException{
9514         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9515    }
9516 
9517 
9518  /**
9519     * Sets the designated parameter to a <code>InputStream</code> object.
9520     * This method differs from the <code>setBinaryStream (int, InputStream)</code>
9521     * method because it informs the driver that the parameter value should be
9522     * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9523     * the driver may have to do extra work to determine whether the parameter
9524     * data should be send to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9525     *
9526     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9527     * it might be more efficient to use a version of
9528     * <code>setBlob</code> which takes a length parameter.
9529     *
9530     * @param parameterName the name of the parameter
9531     * @param inputStream An object that contains the data to set the parameter
9532     * value to.
9533     * @throws SQLException if a database access error occurs or
9534     * this method is called on a closed <code>CallableStatement</code>
9535     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9536     *
9537     * @since 1.6
9538     */
9539     public void setBlob(String parameterName, InputStream inputStream)
9540        throws SQLException{
9541         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9542    }
9543 
9544     /**
9545     * Sets the value of the designated parameter with the given object. The second
9546     * argument must be an object type; for integral values, the
9547     * <code>java.lang</code> equivalent objects should be used.
9548     *
9549     * <p>The given Java object will be converted to the given targetSqlType
9550     * before being sent to the database.
9551     *
9552     * If the object has a custom mapping (is of a class implementing the
9553     * interface <code>SQLData</code>),
9554     * the JDBC driver should call the method <code>SQLData.writeSQL</code> to write it
9555     * to the SQL data stream.
9556     * If, on the other hand, the object is of a class implementing
9557     * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>,  <code>NClob</code>,
9558     *  <code>Struct</code>, <code>java.net.URL</code>,
9559     * or <code>Array</code>, the driver should pass it to the database as a
9560     * value of the corresponding SQL type.
9561     * <P>
9562     * Note that this method may be used to pass datatabase-
9563     * specific abstract data types.
9564     *
9565     * @param parameterName the name of the parameter
9566     * @param x the object containing the input parameter value
9567     * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
9568     * sent to the database. The scale argument may further qualify this type.
9569     * @param scale for java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types,
9570     *          this is the number of digits after the decimal point.  For all other
9571     *          types, this value will be ignored.
9572     * @exception SQLException if a database access error occurs or
9573     * this method is called on a closed <code>CallableStatement</code>
9574     * @exception SQLFeatureNotSupportedException if <code>targetSqlType</code> is
9575     * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,
9576     * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,
9577     * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,
9578     *  <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
9579     * or  <code>STRUCT</code> data type and the JDBC driver does not support
9580     * this data type
9581     * @see Types
9582     * @see #getObject
9583     * @since 1.4
9584     */
9585     public void setObject(String parameterName, Object x, int targetSqlType, int scale)
9586        throws SQLException{
9587         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9588    }
9589 
9590 
9591 
9592  /**
9593     * Sets the value of the designated parameter with the given object.
9594     * This method is like the method <code>setObject</code>
9595     * above, except that it assumes a scale of zero.
9596     *
9597     * @param parameterName the name of the parameter
9598     * @param x the object containing the input parameter value
9599     * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
9600     *                      sent to the database
9601     * @exception SQLException if a database access error occurs or
9602     * this method is called on a closed <code>CallableStatement</code>
9603     * @exception SQLFeatureNotSupportedException if <code>targetSqlType</code> is
9604     * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,
9605     * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,
9606     * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,
9607     *  <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
9608     * or  <code>STRUCT</code> data type and the JDBC driver does not support
9609     * this data type
9610     * @see #getObject
9611     * @since 1.4
9612     */
9613     public void setObject(String parameterName, Object x, int targetSqlType)
9614        throws SQLException{
9615         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9616    }
9617 
9618 
9619  /**
9620    * Sets the value of the designated parameter with the given object.
9621    * The second parameter must be of type <code>Object</code>; therefore, the
9622    * <code>java.lang</code> equivalent objects should be used for built-in types.
9623    *
9624    * <p>The JDBC specification specifies a standard mapping from
9625    * Java <code>Object</code> types to SQL types.  The given argument
9626    * will be converted to the corresponding SQL type before being
9627    * sent to the database.
9628    *
9629    * <p>Note that this method may be used to pass datatabase-
9630    * specific abstract data types, by using a driver-specific Java
9631    * type.
9632    *
9633    * If the object is of a class implementing the interface <code>SQLData</code>,
9634    * the JDBC driver should call the method <code>SQLData.writeSQL</code>
9635    * to write it to the SQL data stream.
9636    * If, on the other hand, the object is of a class implementing
9637    * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>,  <code>NClob</code>,
9638    *  <code>Struct</code>, <code>java.net.URL</code>,
9639    * or <code>Array</code>, the driver should pass it to the database as a
9640    * value of the corresponding SQL type.
9641    * <P>
9642    * This method throws an exception if there is an ambiguity, for example, if the
9643    * object is of a class implementing more than one of the interfaces named above.
9644    *
9645    * @param parameterName the name of the parameter
9646    * @param x the object containing the input parameter value
9647    * @exception SQLException if a database access error occurs,
9648    * this method is called on a closed <code>CallableStatement</code> or if the given
9649    *            <code>Object</code> parameter is ambiguous
9650    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9651    * this method
9652    * @see #getObject
9653    * @since 1.4
9654    */
9655    public void setObject(String parameterName, Object x) throws SQLException{
9656         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9657    }
9658 
9659     /**
9660     * Sets the designated parameter to the given input stream, which will have
9661     * the specified number of bytes.
9662     * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
9663     * parameter, it may be more practical to send it via a
9664     * <code>java.io.InputStream</code>. Data will be read from the stream
9665     * as needed until end-of-file is reached.  The JDBC driver will
9666     * do any necessary conversion from ASCII to the database char format.
9667     *
9668     * <P><B>Note:</B> This stream object can either be a standard
9669     * Java stream object or your own subclass that implements the
9670     * standard interface.
9671     *
9672     * @param parameterName the name of the parameter
9673     * @param x the Java input stream that contains the ASCII parameter value
9674     * @param length the number of bytes in the stream
9675     * @exception SQLException if a database access error occurs or
9676     * this method is called on a closed <code>CallableStatement</code>
9677     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9678     * this method
9679     * @since 1.4
9680     */
9681    public void setAsciiStream(String parameterName, java.io.InputStream x, int length)
9682        throws SQLException{
9683         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9684    }
9685 
9686 
9687  /**
9688     * Sets the designated parameter to the given input stream, which will have
9689     * the specified number of bytes.
9690     * When a very large binary value is input to a <code>LONGVARBINARY</code>
9691     * parameter, it may be more practical to send it via a
9692     * <code>java.io.InputStream</code> object. The data will be read from the stream
9693     * as needed until end-of-file is reached.
9694     *
9695     * <P><B>Note:</B> This stream object can either be a standard
9696     * Java stream object or your own subclass that implements the
9697     * standard interface.
9698     *
9699     * @param parameterName the name of the parameter
9700     * @param x the java input stream which contains the binary parameter value
9701     * @param length the number of bytes in the stream
9702     * @exception SQLException if a database access error occurs or
9703     * this method is called on a closed <code>CallableStatement</code>
9704     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9705     * this method
9706     * @since 1.4
9707     */
9708    public void setBinaryStream(String parameterName, java.io.InputStream x,
9709                         int length) throws SQLException{
9710         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9711    }
9712 
9713 
9714   /**
9715     * Sets the designated parameter to the given <code>Reader</code>
9716     * object, which is the given number of characters long.
9717     * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
9718     * parameter, it may be more practical to send it via a
9719     * <code>java.io.Reader</code> object. The data will be read from the stream
9720     * as needed until end-of-file is reached.  The JDBC driver will
9721     * do any necessary conversion from UNICODE to the database char format.
9722     *
9723     * <P><B>Note:</B> This stream object can either be a standard
9724     * Java stream object or your own subclass that implements the
9725     * standard interface.
9726     *
9727     * @param parameterName the name of the parameter
9728     * @param reader the <code>java.io.Reader</code> object that
9729     *        contains the UNICODE data used as the designated parameter
9730     * @param length the number of characters in the stream
9731     * @exception SQLException if a database access error occurs or
9732     * this method is called on a closed <code>CallableStatement</code>
9733     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9734     * this method
9735     * @since 1.4
9736     */
9737    public void setCharacterStream(String parameterName,
9738                            java.io.Reader reader,
9739                            int length) throws SQLException{
9740         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9741    }
9742 
9743 
9744   /**
9745    * Sets the designated parameter to the given input stream.
9746    * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
9747    * parameter, it may be more practical to send it via a
9748    * <code>java.io.InputStream</code>. Data will be read from the stream
9749    * as needed until end-of-file is reached.  The JDBC driver will
9750    * do any necessary conversion from ASCII to the database char format.
9751    *
9752    * <P><B>Note:</B> This stream object can either be a standard
9753    * Java stream object or your own subclass that implements the
9754    * standard interface.
9755    * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9756    * it might be more efficient to use a version of
9757    * <code>setAsciiStream</code> which takes a length parameter.
9758    *
9759    * @param parameterName the name of the parameter
9760    * @param x the Java input stream that contains the ASCII parameter value
9761    * @exception SQLException if a database access error occurs or
9762    * this method is called on a closed <code>CallableStatement</code>
9763    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9764      * @since 1.6
9765   */
9766   public void setAsciiStream(String parameterName, java.io.InputStream x)
9767           throws SQLException{
9768         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9769    }
9770 
9771 
9772  /**
9773     * Sets the designated parameter to the given input stream.
9774     * When a very large binary value is input to a <code>LONGVARBINARY</code>
9775     * parameter, it may be more practical to send it via a
9776     * <code>java.io.InputStream</code> object. The data will be read from the
9777     * stream as needed until end-of-file is reached.
9778     *
9779     * <P><B>Note:</B> This stream object can either be a standard
9780     * Java stream object or your own subclass that implements the
9781     * standard interface.
9782     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9783     * it might be more efficient to use a version of
9784     * <code>setBinaryStream</code> which takes a length parameter.
9785     *
9786     * @param parameterName the name of the parameter
9787     * @param x the java input stream which contains the binary parameter value
9788     * @exception SQLException if a database access error occurs or
9789     * this method is called on a closed <code>CallableStatement</code>
9790     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9791     * @since 1.6
9792     */
9793    public void setBinaryStream(String parameterName, java.io.InputStream x)
9794    throws SQLException{
9795         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9796    }
9797 
9798 
9799 
9800  /**
9801     * Sets the designated parameter to the given <code>Reader</code>
9802     * object.
9803     * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
9804     * parameter, it may be more practical to send it via a
9805     * <code>java.io.Reader</code> object. The data will be read from the stream
9806     * as needed until end-of-file is reached.  The JDBC driver will
9807     * do any necessary conversion from UNICODE to the database char format.
9808     *
9809     * <P><B>Note:</B> This stream object can either be a standard
9810     * Java stream object or your own subclass that implements the
9811     * standard interface.
9812     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9813     * it might be more efficient to use a version of
9814     * <code>setCharacterStream</code> which takes a length parameter.
9815     *
9816     * @param parameterName the name of the parameter
9817     * @param reader the <code>java.io.Reader</code> object that contains the
9818     *        Unicode data
9819     * @exception SQLException if a database access error occurs or
9820     * this method is called on a closed <code>CallableStatement</code>
9821     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9822     * @since 1.6
9823     */
9824    public void setCharacterStream(String parameterName,
9825                          java.io.Reader reader) throws SQLException{
9826         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9827    }
9828 
9829    /**
9830     * Sets the designated parameter to the given
9831     * <code>java.math.BigDecimal</code> value.
9832     * The driver converts this to an SQL <code>NUMERIC</code> value when
9833     * it sends it to the database.
9834     *
9835     * @param parameterName the name of the parameter
9836     * @param x the parameter value
9837     * @exception SQLException if a database access error occurs or
9838     * this method is called on a closed <code>CallableStatement</code>
9839     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9840     * this method
9841     * @see #getBigDecimal
9842     * @since 1.4
9843     */
9844    public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException{
9845         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9846    }
9847 
9848 
9849 
9850  /**
9851     * Sets the designated parameter to the given Java <code>String</code> value.
9852     * The driver converts this
9853     * to an SQL <code>VARCHAR</code> or <code>LONGVARCHAR</code> value
9854     * (depending on the argument's
9855     * size relative to the driver's limits on <code>VARCHAR</code> values)
9856     * when it sends it to the database.
9857     *
9858     * @param parameterName the name of the parameter
9859     * @param x the parameter value
9860     * @exception SQLException if a database access error occurs or
9861     * this method is called on a closed <code>CallableStatement</code>
9862     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9863     * this method
9864     * @see #getString
9865     * @since 1.4
9866     */
9867    public void setString(String parameterName, String x) throws SQLException{
9868         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9869    }
9870 
9871 
9872 
9873  /**
9874     * Sets the designated parameter to the given Java array of bytes.
9875     * The driver converts this to an SQL <code>VARBINARY</code> or
9876     * <code>LONGVARBINARY</code> (depending on the argument's size relative
9877     * to the driver's limits on <code>VARBINARY</code> values) when it sends
9878     * it to the database.
9879     *
9880     * @param parameterName the name of the parameter
9881     * @param x the parameter value
9882     * @exception SQLException if a database access error occurs or
9883     * this method is called on a closed <code>CallableStatement</code>
9884     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9885     * this method
9886     * @see #getBytes
9887     * @since 1.4
9888     */
9889    public void setBytes(String parameterName, byte x[]) throws SQLException{
9890         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9891    }
9892 
9893 
9894 
9895  /**
9896     * Sets the designated parameter to the given <code>java.sql.Timestamp</code> value.
9897     * The driver
9898     * converts this to an SQL <code>TIMESTAMP</code> value when it sends it to the
9899     * database.
9900     *
9901     * @param parameterName the name of the parameter
9902     * @param x the parameter value
9903     * @exception SQLException if a database access error occurs or
9904     * this method is called on a closed <code>CallableStatement</code>
9905     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9906     * this method
9907     * @see #getTimestamp
9908     * @since 1.4
9909     */
9910    public void setTimestamp(String parameterName, java.sql.Timestamp x)
9911        throws SQLException{
9912         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9913    }
9914 
9915     /**
9916     * Sets the designated parameter to SQL <code>NULL</code>.
9917     *
9918     * <P><B>Note:</B> You must specify the parameter's SQL type.
9919     *
9920     * @param parameterName the name of the parameter
9921     * @param sqlType the SQL type code defined in <code>java.sql.Types</code>
9922     * @exception SQLException if a database access error occurs or
9923     * this method is called on a closed <code>CallableStatement</code>
9924     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9925     * this method
9926     * @since 1.4
9927     */
9928    public void setNull(String parameterName, int sqlType) throws SQLException {
9929         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9930    }
9931 
9932 
9933  /**
9934     * Sets the designated parameter to SQL <code>NULL</code>.
9935     * This version of the method <code>setNull</code> should
9936     * be used for user-defined types and REF type parameters.  Examples
9937     * of user-defined types include: STRUCT, DISTINCT, JAVA_OBJECT, and
9938     * named array types.
9939     *
9940     * <P><B>Note:</B> To be portable, applications must give the
9941     * SQL type code and the fully-qualified SQL type name when specifying
9942     * a NULL user-defined or REF parameter.  In the case of a user-defined type
9943     * the name is the type name of the parameter itself.  For a REF
9944     * parameter, the name is the type name of the referenced type.  If
9945     * a JDBC driver does not need the type code or type name information,
9946     * it may ignore it.
9947     *
9948     * Although it is intended for user-defined and Ref parameters,
9949     * this method may be used to set a null parameter of any JDBC type.
9950     * If the parameter does not have a user-defined or REF type, the given
9951     * typeName is ignored.
9952     *
9953     *
9954     * @param parameterName the name of the parameter
9955     * @param sqlType a value from <code>java.sql.Types</code>
9956     * @param typeName the fully-qualified name of an SQL user-defined type;
9957     *        ignored if the parameter is not a user-defined type or
9958     *        SQL <code>REF</code> value
9959     * @exception SQLException if a database access error occurs or
9960     * this method is called on a closed <code>CallableStatement</code>
9961     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9962     * this method
9963     * @since 1.4
9964     */
9965    public void setNull (String parameterName, int sqlType, String typeName)
9966        throws SQLException{
9967         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9968    }
9969 
9970 
9971 
9972  /**
9973     * Sets the designated parameter to the given Java <code>boolean</code> value.
9974     * The driver converts this
9975     * to an SQL <code>BIT</code> or <code>BOOLEAN</code> value when it sends it to the database.
9976     *
9977     * @param parameterName the name of the parameter
9978     * @param x the parameter value
9979     * @exception SQLException if a database access error occurs or
9980     * this method is called on a closed <code>CallableStatement</code>
9981     * @see #getBoolean
9982     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9983     * this method
9984     * @since 1.4
9985     */
9986    public void setBoolean(String parameterName, boolean x) throws SQLException{
9987         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9988    }
9989 
9990 
9991 
9992  /**
9993     * Sets the designated parameter to the given Java <code>byte</code> value.
9994     * The driver converts this
9995     * to an SQL <code>TINYINT</code> value when it sends it to the database.
9996     *
9997     * @param parameterName the name of the parameter
9998     * @param x the parameter value
9999     * @exception SQLException if a database access error occurs or
10000     * this method is called on a closed <code>CallableStatement</code>
10001     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10002     * this method
10003     * @see #getByte
10004     * @since 1.4
10005     */
10006    public void setByte(String parameterName, byte x) throws SQLException{
10007         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10008    }
10009 
10010 
10011 
10012  /**
10013     * Sets the designated parameter to the given Java <code>short</code> value.
10014     * The driver converts this
10015     * to an SQL <code>SMALLINT</code> value when it sends it to the database.
10016     *
10017     * @param parameterName the name of the parameter
10018     * @param x the parameter value
10019     * @exception SQLException if a database access error occurs or
10020     * this method is called on a closed <code>CallableStatement</code>
10021     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10022     * this method
10023     * @see #getShort
10024     * @since 1.4
10025     */
10026    public void setShort(String parameterName, short x) throws SQLException{
10027         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10028    }
10029 
10030 
10031  /**
10032     * Sets the designated parameter to the given Java <code>int</code> value.
10033     * The driver converts this
10034     * to an SQL <code>INTEGER</code> value when it sends it to the database.
10035     *
10036     * @param parameterName the name of the parameter
10037     * @param x the parameter value
10038     * @exception SQLException if a database access error occurs or
10039     * this method is called on a closed <code>CallableStatement</code>
10040     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10041     * this method
10042     * @see #getInt
10043     * @since 1.4
10044     */
10045    public void setInt(String parameterName, int x) throws SQLException{
10046         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10047    }
10048 
10049 
10050  /**
10051     * Sets the designated parameter to the given Java <code>long</code> value.
10052     * The driver converts this
10053     * to an SQL <code>BIGINT</code> value when it sends it to the database.
10054     *
10055     * @param parameterName the name of the parameter
10056     * @param x the parameter value
10057     * @exception SQLException if a database access error occurs or
10058     * this method is called on a closed <code>CallableStatement</code>
10059     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10060     * this method
10061     * @see #getLong
10062     * @since 1.4
10063     */
10064    public void setLong(String parameterName, long x) throws SQLException{
10065         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10066    }
10067 
10068 
10069  /**
10070     * Sets the designated parameter to the given Java <code>float</code> value.
10071     * The driver converts this
10072     * to an SQL <code>FLOAT</code> value when it sends it to the database.
10073     *
10074     * @param parameterName the name of the parameter
10075     * @param x the parameter value
10076     * @exception SQLException if a database access error occurs or
10077     * this method is called on a closed <code>CallableStatement</code>
10078     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10079     * this method
10080     * @see #getFloat
10081     * @since 1.4
10082     */
10083    public void setFloat(String parameterName, float x) throws SQLException{
10084         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10085    }
10086 
10087 
10088  /**
10089     * Sets the designated parameter to the given Java <code>double</code> value.
10090     * The driver converts this
10091     * to an SQL <code>DOUBLE</code> value when it sends it to the database.
10092     *
10093     * @param parameterName the name of the parameter
10094     * @param x the parameter value
10095     * @exception SQLException if a database access error occurs or
10096     * this method is called on a closed <code>CallableStatement</code>
10097     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10098     * this method
10099     * @see #getDouble
10100     * @since 1.4
10101     */
10102    public void setDouble(String parameterName, double x) throws SQLException{
10103         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10104    }
10105 
10106    /**
10107      * This method re populates the resBundle
10108      * during the deserialization process
10109      *
10110      */
10111     private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
10112         // Default state initialization happens here
10113         ois.defaultReadObject();
10114         // Initialization of transient Res Bundle happens here .
10115         try {
10116            resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
10117         } catch(IOException ioe) {
10118             throw new RuntimeException(ioe);
10119         }
10120 
10121     }
10122 
10123     //------------------------- JDBC 4.1 -----------------------------------
10124     public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
10125         throw new SQLFeatureNotSupportedException("Not supported yet.");
10126     }
10127 
10128     public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
10129         throw new SQLFeatureNotSupportedException("Not supported yet.");
10130     }
10131 
10132     static final long serialVersionUID =1884577171200622428L;
10133 }