1 /*
   2  * Copyright (c) 2003, 2013, 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 import sun.reflect.misc.ReflectUtil;
  41 
  42 /**
  43  * The standard implementation of the <code>CachedRowSet</code> interface.
  44  *
  45  * See interface definition for full behavior and implementation requirements.
  46  * This reference implementation has made provision for a one-to-one write back
  47  * facility and it is curremtly be possible to change the peristence provider
  48  * during the life-time of any CachedRowSetImpl.
  49  *
  50  * @author Jonathan Bruce, Amit Handa
  51  */
  52 
  53 public class CachedRowSetImpl extends BaseRowSet implements RowSet, RowSetInternal, Serializable, Cloneable, CachedRowSet {
  54 
  55     /**
  56      * The <code>SyncProvider</code> used by the CachedRowSet
  57      */
  58     private SyncProvider provider;
  59 
  60     /**
  61      * The <code>RowSetReaderImpl</code> object that is the reader
  62      * for this rowset.  The method <code>execute</code> uses this
  63      * reader as part of its implementation.
  64      * @serial
  65      */
  66     private RowSetReader rowSetReader;
  67 
  68     /**
  69      * The <code>RowSetWriterImpl</code> object that is the writer
  70      * for this rowset.  The method <code>acceptChanges</code> uses
  71      * this writer as part of its implementation.
  72      * @serial
  73      */
  74     private RowSetWriter rowSetWriter;
  75 
  76     /**
  77      * The <code>Connection</code> object that connects with this
  78      * <code>CachedRowSetImpl</code> object's current underlying data source.
  79      */
  80     private transient Connection conn;
  81 
  82     /**
  83      * The <code>ResultSetMetaData</code> object that contains information
  84      * about the columns in the <code>ResultSet</code> object that is the
  85      * current source of data for this <code>CachedRowSetImpl</code> object.
  86      */
  87     private transient ResultSetMetaData RSMD;
  88 
  89     /**
  90      * The <code>RowSetMetaData</code> object that contains information about
  91      * the columns in this <code>CachedRowSetImpl</code> object.
  92      * @serial
  93      */
  94     private RowSetMetaDataImpl RowSetMD;
  95 
  96     // Properties of this RowSet
  97 
  98     /**
  99      * An array containing the columns in this <code>CachedRowSetImpl</code>
 100      * object that form a unique identifier for a row. This array
 101      * is used by the writer.
 102      * @serial
 103      */
 104     private int keyCols[];
 105 
 106     /**
 107      * The name of the table in the underlying database to which updates
 108      * should be written.  This name is needed because most drivers
 109      * do not return this information in a <code>ResultSetMetaData</code>
 110      * object.
 111      * @serial
 112      */
 113     private String tableName;
 114 
 115     /**
 116      * A <code>Vector</code> object containing the <code>Row</code>
 117      * objects that comprise  this <code>CachedRowSetImpl</code> object.
 118      * @serial
 119      */
 120     private Vector<Object> rvh;
 121 
 122     /**
 123      * The current position of the cursor in this <code>CachedRowSetImpl</code>
 124      * object.
 125      * @serial
 126      */
 127     private int cursorPos;
 128 
 129     /**
 130      * The current position of the cursor in this <code>CachedRowSetImpl</code>
 131      * object not counting rows that have been deleted, if any.
 132      * <P>
 133      * For example, suppose that the cursor is on the last row of a rowset
 134      * that started with five rows and subsequently had the second and third
 135      * rows deleted. The <code>absolutePos</code> would be <code>3</code>,
 136      * whereas the <code>cursorPos</code> would be <code>5</code>.
 137      * @serial
 138      */
 139     private int absolutePos;
 140 
 141     /**
 142      * The number of deleted rows currently in this <code>CachedRowSetImpl</code>
 143      * object.
 144      * @serial
 145      */
 146     private int numDeleted;
 147 
 148     /**
 149      * The total number of rows currently in this <code>CachedRowSetImpl</code>
 150      * object.
 151      * @serial
 152      */
 153     private int numRows;
 154 
 155     /**
 156      * A special row used for constructing a new row. A new
 157      * row is constructed by using <code>ResultSet.updateXXX</code>
 158      * methods to insert column values into the insert row.
 159      * @serial
 160      */
 161     private InsertRow insertRow;
 162 
 163     /**
 164      * A <code>boolean</code> indicating whether the cursor is
 165      * currently on the insert row.
 166      * @serial
 167      */
 168     private boolean onInsertRow;
 169 
 170     /**
 171      * The field that temporarily holds the last position of the
 172      * cursor before it moved to the insert row, thus preserving
 173      * the number of the current row to which the cursor may return.
 174      * @serial
 175      */
 176     private int currentRow;
 177 
 178     /**
 179      * A <code>boolean</code> indicating whether the last value
 180      * returned was an SQL <code>NULL</code>.
 181      * @serial
 182      */
 183     private boolean lastValueNull;
 184 
 185     /**
 186      * A <code>SQLWarning</code> which logs on the warnings
 187      */
 188     private SQLWarning sqlwarn;
 189 
 190     /**
 191      * Used to track match column for JoinRowSet consumption
 192      */
 193     private String strMatchColumn ="";
 194 
 195     /**
 196      * Used to track match column for JoinRowSet consumption
 197      */
 198     private int iMatchColumn = -1;
 199 
 200     /**
 201      * A <code>RowSetWarning</code> which logs on the warnings
 202      */
 203     private RowSetWarning rowsetWarning;
 204 
 205     /**
 206      * The default SyncProvider for the RI CachedRowSetImpl
 207      */
 208     private String DEFAULT_SYNC_PROVIDER = "com.sun.rowset.providers.RIOptimisticProvider";
 209 
 210     /**
 211      * The boolean variable indicating locatorsUpdateValue
 212      */
 213     private boolean dbmslocatorsUpdateCopy;
 214 
 215     /**
 216      * The <code>ResultSet</code> object that is used to maintain the data when
 217      * a ResultSet and start position are passed as parameters to the populate function
 218      */
 219     private transient ResultSet resultSet;
 220 
 221     /**
 222      * The integer value indicating the end position in the ResultSetwhere the picking
 223      * up of rows for populating a CachedRowSet object was left off.
 224      */
 225     private int endPos;
 226 
 227     /**
 228      * The integer value indicating the end position in the ResultSetwhere the picking
 229      * up of rows for populating a CachedRowSet object was left off.
 230      */
 231     private int prevEndPos;
 232 
 233     /**
 234      * The integer value indicating the position in the ResultSet, to populate the
 235      * CachedRowSet object.
 236      */
 237     private int startPos;
 238 
 239     /**
 240      * The integer value indicating the position from where the page prior to this
 241      * was populated.
 242      */
 243     private int startPrev;
 244 
 245     /**
 246      * The integer value indicating size of the page.
 247      */
 248     private int pageSize;
 249 
 250     /**
 251      * The integer value indicating number of rows that have been processed so far.
 252      * Used for checking whether maxRows has been reached or not.
 253      */
 254     private int maxRowsreached;
 255     /**
 256      * The boolean value when true signifies that pages are still to follow and a
 257      * false value indicates that this is the last page.
 258      */
 259     private boolean pagenotend = true;
 260 
 261     /**
 262      * The boolean value indicating whether this is the first page or not.
 263      */
 264     private boolean onFirstPage;
 265 
 266     /**
 267      * The boolean value indicating whether this is the last page or not.
 268      */
 269     private boolean onLastPage;
 270 
 271     /**
 272      * The integer value indicating how many times the populate function has been called.
 273      */
 274     private int populatecallcount;
 275 
 276     /**
 277      * The integer value indicating the total number of rows to be processed in the
 278      * ResultSet object passed to the populate function.
 279      */
 280     private int totalRows;
 281 
 282     /**
 283      * The boolean value indicating how the CahedRowSet object has been populated for
 284      * paging purpose. True indicates that connection parameter is passed.
 285      */
 286     private boolean callWithCon;
 287 
 288     /**
 289      * CachedRowSet reader object to read the data from the ResultSet when a connection
 290      * parameter is passed to populate the CachedRowSet object for paging.
 291      */
 292     private CachedRowSetReader crsReader;
 293 
 294     /**
 295      * The Vector holding the Match Columns
 296      */
 297     private Vector<Integer> iMatchColumns;
 298 
 299     /**
 300      * The Vector that will hold the Match Column names.
 301      */
 302     private Vector<String> strMatchColumns;
 303 
 304     /**
 305      * Trigger that indicates whether the active SyncProvider is exposes the
 306      * additional TransactionalWriter method
 307      */
 308     private boolean tXWriter = false;
 309 
 310     /**
 311      * The field object for a transactional RowSet writer
 312      */
 313     private TransactionalWriter tWriter = null;
 314 
 315     protected transient JdbcRowSetResourceBundle resBundle;
 316 
 317     private boolean updateOnInsert;
 318 
 319 
 320 
 321     /**
 322      * Constructs a new default <code>CachedRowSetImpl</code> object with
 323      * the capacity to hold 100 rows. This new object has no metadata
 324      * and has the following default values:
 325      * <pre>
 326      *     onInsertRow = false
 327      *     insertRow = null
 328      *     cursorPos = 0
 329      *     numRows = 0
 330      *     showDeleted = false
 331      *     queryTimeout = 0
 332      *     maxRows = 0
 333      *     maxFieldSize = 0
 334      *     rowSetType = ResultSet.TYPE_SCROLL_INSENSITIVE
 335      *     concurrency = ResultSet.CONCUR_UPDATABLE
 336      *     readOnly = false
 337      *     isolation = Connection.TRANSACTION_READ_COMMITTED
 338      *     escapeProcessing = true
 339      *     onInsertRow = false
 340      *     insertRow = null
 341      *     cursorPos = 0
 342      *     absolutePos = 0
 343      *     numRows = 0
 344      * </pre>
 345      * A <code>CachedRowSetImpl</code> object is configured to use the default
 346      * <code>RIOptimisticProvider</code> implementation to provide connectivity
 347      * and synchronization capabilities to the set data source.
 348      * <P>
 349      * @throws SQLException if an error occurs
 350      */
 351     public CachedRowSetImpl() throws SQLException {
 352 
 353         try {
 354            resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
 355         } catch(IOException ioe) {
 356             throw new RuntimeException(ioe);
 357         }
 358 
 359         // set the Reader, this maybe overridden latter
 360         provider =
 361         SyncFactory.getInstance(DEFAULT_SYNC_PROVIDER);
 362 
 363         if (!(provider instanceof RIOptimisticProvider)) {
 364             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidp").toString());
 365         }
 366 
 367         rowSetReader = (CachedRowSetReader)provider.getRowSetReader();
 368         rowSetWriter = (CachedRowSetWriter)provider.getRowSetWriter();
 369 
 370         // allocate the parameters collection
 371         initParams();
 372 
 373         initContainer();
 374 
 375         // set up some default values
 376         initProperties();
 377 
 378         // insert row setup
 379         onInsertRow = false;
 380         insertRow = null;
 381 
 382         // set the warninings
 383         sqlwarn = new SQLWarning();
 384         rowsetWarning = new RowSetWarning();
 385 
 386     }
 387 
 388     /**
 389      * Provides a <code>CachedRowSetImpl</code> instance with the same default properties as
 390      * as the zero parameter constructor.
 391      * <pre>
 392      *     onInsertRow = false
 393      *     insertRow = null
 394      *     cursorPos = 0
 395      *     numRows = 0
 396      *     showDeleted = false
 397      *     queryTimeout = 0
 398      *     maxRows = 0
 399      *     maxFieldSize = 0
 400      *     rowSetType = ResultSet.TYPE_SCROLL_INSENSITIVE
 401      *     concurrency = ResultSet.CONCUR_UPDATABLE
 402      *     readOnly = false
 403      *     isolation = Connection.TRANSACTION_READ_COMMITTED
 404      *     escapeProcessing = true
 405      *     onInsertRow = false
 406      *     insertRow = null
 407      *     cursorPos = 0
 408      *     absolutePos = 0
 409      *     numRows = 0
 410      * </pre>
 411      *
 412      * However, applications will have the means to specify at runtime the
 413      * desired <code>SyncProvider</code> object.
 414      * <p>
 415      * For example, creating a <code>CachedRowSetImpl</code> object as follows ensures
 416      * that a it is established with the <code>com.foo.provider.Impl</code> synchronization
 417      * implementation providing the synchronization mechanism for this disconnected
 418      * <code>RowSet</code> object.
 419      * <pre>
 420      *     Hashtable env = new Hashtable();
 421      *     env.put(javax.sql.rowset.spi.SyncFactory.ROWSET_PROVIDER_NAME,
 422      *         "com.foo.provider.Impl");
 423      *     CachedRowSetImpl crs = new CachedRowSet(env);
 424      * </pre>
 425      * <p>
 426      * Calling this constructor with a <code>null</code> parameter will
 427      * cause the <code>SyncFactory</code> to provide the reference
 428      * optimistic provider <code>com.sun.rowset.providers.RIOptimisticProvider</code>.
 429      * <p>
 430      * In addition, the following properties can be associated with the
 431      * provider to assist in determining the choice of the synchronizaton
 432      * provider such as:
 433      * <ul>
 434      * <li><code>ROWSET_SYNC_PROVIDER</code> - the property specifying the
 435      * <code>SyncProvider</code> class name to be instantiated by the
 436      * <code>SyncFacttory</code>
 437      * <li><code>ROWSET_SYNC_VENDOR</code> - the property specifying the software
 438      * vendor associated with a <code>SyncProvider</code> implementation.
 439      * <li><code>ROWSET_SYNC_PROVIDER_VER</code> - the property specifying the
 440      * version of the <code>SyncProvider</code> implementation provided by the
 441      * software vendor.
 442      * </ul>
 443      * More specific detailes are available in the <code>SyncFactory</code>
 444      * and <code>SyncProvider</code> specificiations later in this document.
 445      * <p>
 446      * @param env a <code>Hashtable</code> object with a list of desired
 447      *        synchronization providers
 448      * @throws SQLException if the requested provider cannot be found by the
 449      * synchronization factory
 450      * @see SyncProvider
 451      */
 452     public CachedRowSetImpl(@SuppressWarnings("rawtypes") 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         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, -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 || map.isEmpty()) {
 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                 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) {
 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) ) {
 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       setConnection(con);
 942       acceptChanges();
 943     }
 944 
 945     /**
 946      * Restores this <code>CachedRowSetImpl</code> object to its original state,
 947      * that is, its state before the last set of changes.
 948      * <P>
 949      * Before returning, this method moves the cursor before the first row
 950      * and sends a <code>rowSetChanged</code> event to all registered
 951      * listeners.
 952      * @throws SQLException if an error is occurs rolling back the RowSet
 953      *           state to the definied original value.
 954      * @see javax.sql.RowSetListener#rowSetChanged
 955      */
 956     public void restoreOriginal() throws SQLException {
 957         Row currentRow;
 958         for (Iterator<?> i = rvh.iterator(); i.hasNext();) {
 959             currentRow = (Row)i.next();
 960             if (currentRow.getInserted() == true) {
 961                 i.remove();
 962                 --numRows;
 963             } else {
 964                 if (currentRow.getDeleted() == true) {
 965                     currentRow.clearDeleted();
 966                 }
 967                 if (currentRow.getUpdated() == true) {
 968                     currentRow.clearUpdated();
 969                 }
 970             }
 971         }
 972         // move to before the first
 973         cursorPos = 0;
 974 
 975         // notify any listeners
 976         notifyRowSetChanged();
 977     }
 978 
 979     /**
 980      * Releases the current contents of this <code>CachedRowSetImpl</code>
 981      * object and sends a <code>rowSetChanged</code> event object to all
 982      * registered listeners.
 983      *
 984      * @throws SQLException if an error occurs flushing the contents of
 985      *           RowSet.
 986      * @see javax.sql.RowSetListener#rowSetChanged
 987      */
 988     public void release() throws SQLException {
 989         initContainer();
 990         notifyRowSetChanged();
 991     }
 992 
 993     /**
 994      * Cancels deletion of the current row and notifies listeners that
 995      * a row has changed.
 996      * <P>
 997      * Note:  This method can be ignored if deleted rows are not being shown,
 998      * which is the normal case.
 999      *
1000      * @throws SQLException if the cursor is not on a valid row
1001      */
1002     public void undoDelete() throws SQLException {
1003         if (getShowDeleted() == false) {
1004             return;
1005         }
1006         // make sure we are on a row
1007         checkCursor();
1008 
1009         // don't want this to happen...
1010         if (onInsertRow == true) {
1011             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1012         }
1013 
1014         Row currentRow = (Row)getCurrentRow();
1015         if (currentRow.getDeleted() == true) {
1016             currentRow.clearDeleted();
1017             --numDeleted;
1018             notifyRowChanged();
1019         }
1020     }
1021 
1022     /**
1023      * Immediately removes the current row from this
1024      * <code>CachedRowSetImpl</code> object if the row has been inserted, and
1025      * also notifies listeners the a row has changed.  An exception is thrown
1026      * if the row is not a row that has been inserted or the cursor is before
1027      * the first row, after the last row, or on the insert row.
1028      * <P>
1029      * This operation cannot be undone.
1030      *
1031      * @throws SQLException if an error occurs,
1032      *                         the cursor is not on a valid row,
1033      *                         or the row has not been inserted
1034      */
1035     public void undoInsert() throws SQLException {
1036         // make sure we are on a row
1037         checkCursor();
1038 
1039         // don't want this to happen...
1040         if (onInsertRow == true) {
1041             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1042         }
1043 
1044         Row currentRow = (Row)getCurrentRow();
1045         if (currentRow.getInserted() == true) {
1046             rvh.remove(cursorPos-1);
1047             --numRows;
1048             notifyRowChanged();
1049         } else {
1050             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.illegalop").toString());
1051         }
1052     }
1053 
1054     /**
1055      * Immediately reverses the last update operation if the
1056      * row has been modified. This method can be
1057      * called to reverse updates on a all columns until all updates in a row have
1058      * been rolled back to their originating state since the last synchronization
1059      * (<code>acceptChanges</code>) or population. This method may also be called
1060      * while performing updates to the insert row.
1061      * <P>
1062      * {@code undoUpdate} may be called at any time during the life-time of a
1063      * rowset, however after a synchronization has occurs this method has no
1064      * affect until further modification to the RowSet data occurs.
1065      *
1066      * @throws SQLException if cursor is before the first row, after the last
1067      *     row in rowset.
1068      * @see #undoDelete
1069      * @see #undoInsert
1070      * @see java.sql.ResultSet#cancelRowUpdates
1071      */
1072     public void undoUpdate() throws SQLException {
1073         // if on insert row, cancel the insert row
1074         // make the insert row flag,
1075         // cursorPos back to the current row
1076         moveToCurrentRow();
1077 
1078         // else if not on insert row
1079         // call undoUpdate or undoInsert
1080         undoDelete();
1081 
1082         undoInsert();
1083 
1084     }
1085 
1086     //--------------------------------------------------------------------
1087     // Views
1088     //--------------------------------------------------------------------
1089 
1090     /**
1091      * Returns a new <code>RowSet</code> object backed by the same data as
1092      * that of this <code>CachedRowSetImpl</code> object and sharing a set of cursors
1093      * with it. This allows cursors to interate over a shared set of rows, providing
1094      * multiple views of the underlying data.
1095      *
1096      * @return a <code>RowSet</code> object that is a copy of this <code>CachedRowSetImpl</code>
1097      * object and shares a set of cursors with it
1098      * @throws SQLException if an error occurs or cloning is
1099      *                         not supported
1100      * @see javax.sql.RowSetEvent
1101      * @see javax.sql.RowSetListener
1102      */
1103     public RowSet createShared() throws SQLException {
1104         RowSet clone;
1105         try {
1106             clone = (RowSet)clone();
1107         } catch (CloneNotSupportedException ex) {
1108             throw new SQLException(ex.getMessage());
1109         }
1110         return clone;
1111     }
1112 
1113     /**
1114      * Returns a new <code>RowSet</code> object containing by the same data
1115      * as this <code>CachedRowSetImpl</code> object.  This method
1116      * differs from the method <code>createCopy</code> in that it throws a
1117      * <code>CloneNotSupportedException</code> object instead of an
1118      * <code>SQLException</code> object, as the method <code>createShared</code>
1119      * does.  This <code>clone</code>
1120      * method is called internally by the method <code>createShared</code>,
1121      * which catches the <code>CloneNotSupportedException</code> object
1122      * and in turn throws a new <code>SQLException</code> object.
1123      *
1124      * @return a copy of this <code>CachedRowSetImpl</code> object
1125      * @throws CloneNotSupportedException if an error occurs when
1126      * attempting to clone this <code>CachedRowSetImpl</code> object
1127      * @see #createShared
1128      */
1129     protected Object clone() throws CloneNotSupportedException  {
1130         return (super.clone());
1131     }
1132 
1133     /**
1134      * Creates a <code>RowSet</code> object that is a deep copy of
1135      * this <code>CachedRowSetImpl</code> object's data, including
1136      * constraints.  Updates made
1137      * on a copy are not visible to the original rowset;
1138      * a copy of a rowset is completely independent from the original.
1139      * <P>
1140      * Making a copy saves the cost of creating an identical rowset
1141      * from first principles, which can be quite expensive.
1142      * For example, it can eliminate the need to query a
1143      * remote database server.
1144      * @return a new <code>CachedRowSet</code> object that is a deep copy
1145      *           of this <code>CachedRowSet</code> object and is
1146      *           completely independent from this <code>CachedRowSetImpl</code>
1147      *           object.
1148      * @throws SQLException if an error occurs in generating the copy of this
1149      *           of the <code>CachedRowSetImpl</code>
1150      * @see #createShared
1151      * @see javax.sql.RowSetEvent
1152      * @see javax.sql.RowSetListener
1153      */
1154     public CachedRowSet createCopy() throws SQLException {
1155         ObjectOutputStream out;
1156         ByteArrayOutputStream bOut = new ByteArrayOutputStream();
1157         try {
1158             out = new ObjectOutputStream(bOut);
1159             out.writeObject(this);
1160         } catch (IOException ex) {
1161             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1162         }
1163 
1164         ObjectInputStream in;
1165 
1166         try {
1167             ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
1168             in = new ObjectInputStream(bIn);
1169         } catch (StreamCorruptedException ex) {
1170             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1171         } catch (IOException ex) {
1172             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1173         }
1174 
1175         try {
1176             //return ((CachedRowSet)(in.readObject()));
1177             CachedRowSetImpl crsTemp = (CachedRowSetImpl)in.readObject();
1178             crsTemp.resBundle = this.resBundle;
1179             return ((CachedRowSet)crsTemp);
1180 
1181         } catch (ClassNotFoundException ex) {
1182             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1183         } catch (OptionalDataException ex) {
1184             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1185         } catch (IOException ex) {
1186             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1187         }
1188     }
1189 
1190     /**
1191      * Creates a <code>RowSet</code> object that is a copy of
1192      * this <code>CachedRowSetImpl</code> object's table structure
1193      * and the constraints only.
1194      * There will be no data in the object being returned.
1195      * Updates made on a copy are not visible to the original rowset.
1196      * <P>
1197      * This helps in getting the underlying XML schema which can
1198      * be used as the basis for populating a <code>WebRowSet</code>.
1199      *
1200      * @return a new <code>CachedRowSet</code> object that is a copy
1201      * of this <code>CachedRowSetImpl</code> object's schema and
1202      * retains all the constraints on the original rowset but contains
1203      * no data
1204      * @throws SQLException if an error occurs in generating the copy
1205      * of the <code>CachedRowSet</code> object
1206      * @see #createShared
1207      * @see #createCopy
1208      * @see #createCopyNoConstraints
1209      * @see javax.sql.RowSetEvent
1210      * @see javax.sql.RowSetListener
1211      */
1212     public CachedRowSet createCopySchema() throws SQLException {
1213         // Copy everything except data i.e all constraints
1214 
1215         // Store the number of rows of "this"
1216         // and make numRows equals zero.
1217         // and make data also zero.
1218         int nRows = numRows;
1219         numRows = 0;
1220 
1221         CachedRowSet crs = this.createCopy();
1222 
1223         // reset this object back to number of rows.
1224         numRows = nRows;
1225 
1226         return crs;
1227     }
1228 
1229     /**
1230      * Creates a <code>CachedRowSet</code> object that is a copy of
1231      * this <code>CachedRowSetImpl</code> object's data only.
1232      * All constraints set in this object will not be there
1233      * in the returning object.  Updates made
1234      * on a copy are not visible to the original rowset.
1235      *
1236      * @return a new <code>CachedRowSet</code> object that is a deep copy
1237      * of this <code>CachedRowSetImpl</code> object and is
1238      * completely independent from this <code>CachedRowSetImpl</code> object
1239      * @throws SQLException if an error occurs in generating the copy of the
1240      * of the <code>CachedRowSet</code>
1241      * @see #createShared
1242      * @see #createCopy
1243      * @see #createCopySchema
1244      * @see javax.sql.RowSetEvent
1245      * @see javax.sql.RowSetListener
1246      */
1247     public CachedRowSet createCopyNoConstraints() throws SQLException {
1248         // Copy the whole data ONLY without any constraints.
1249         CachedRowSetImpl crs;
1250         crs = (CachedRowSetImpl)this.createCopy();
1251 
1252         crs.initProperties();
1253         try {
1254             crs.unsetMatchColumn(crs.getMatchColumnIndexes());
1255         } catch(SQLException sqle) {
1256             //do nothing, if the setMatchColumn is not set.
1257         }
1258 
1259         try {
1260             crs.unsetMatchColumn(crs.getMatchColumnNames());
1261         } catch(SQLException sqle) {
1262             //do nothing, if the setMatchColumn is not set.
1263         }
1264 
1265         return crs;
1266     }
1267 
1268     /**
1269      * Converts this <code>CachedRowSetImpl</code> object to a collection
1270      * of tables. The sample implementation utilitizes the <code>TreeMap</code>
1271      * collection type.
1272      * This class guarantees that the map will be in ascending key order,
1273      * sorted according to the natural order for the key's class.
1274      *
1275      * @return a <code>Collection</code> object consisting of tables,
1276      *         each of which is a copy of a row in this
1277      *         <code>CachedRowSetImpl</code> object
1278      * @throws SQLException if an error occurs in generating the collection
1279      * @see #toCollection(int)
1280      * @see #toCollection(String)
1281      * @see java.util.TreeMap
1282      */
1283     public Collection<?> toCollection() throws SQLException {
1284 
1285         TreeMap<Integer, Object> tMap = new TreeMap<>();
1286 
1287         for (int i = 0; i<numRows; i++) {
1288             tMap.put(i, rvh.get(i));
1289         }
1290 
1291         return (tMap.values());
1292     }
1293 
1294     /**
1295      * Returns the specified column of this <code>CachedRowSetImpl</code> object
1296      * as a <code>Collection</code> object.  This method makes a copy of the
1297      * column's data and utilitizes the <code>Vector</code> to establish the
1298      * collection. The <code>Vector</code> class implements a growable array
1299      * objects allowing the individual components to be accessed using an
1300      * an integer index similar to that of an array.
1301      *
1302      * @return a <code>Collection</code> object that contains the value(s)
1303      *         stored in the specified column of this
1304      *         <code>CachedRowSetImpl</code>
1305      *         object
1306      * @throws SQLException if an error occurs generated the collection; or
1307      *          an invalid column is provided.
1308      * @see #toCollection()
1309      * @see #toCollection(String)
1310      * @see java.util.Vector
1311      */
1312     public Collection<?> toCollection(int column) throws SQLException {
1313 
1314         int nRows = numRows;
1315         Vector<Object> vec = new Vector<>(nRows);
1316 
1317         // create a copy
1318         CachedRowSetImpl crsTemp;
1319         crsTemp = (CachedRowSetImpl) this.createCopy();
1320 
1321         while(nRows!=0) {
1322             crsTemp.next();
1323             vec.add(crsTemp.getObject(column));
1324             nRows--;
1325         }
1326 
1327         return (Collection)vec;
1328     }
1329 
1330     /**
1331      * Returns the specified column of this <code>CachedRowSetImpl</code> object
1332      * as a <code>Collection</code> object.  This method makes a copy of the
1333      * column's data and utilitizes the <code>Vector</code> to establish the
1334      * collection. The <code>Vector</code> class implements a growable array
1335      * objects allowing the individual components to be accessed using an
1336      * an integer index similar to that of an array.
1337      *
1338      * @return a <code>Collection</code> object that contains the value(s)
1339      *         stored in the specified column of this
1340      *         <code>CachedRowSetImpl</code>
1341      *         object
1342      * @throws SQLException if an error occurs generated the collection; or
1343      *          an invalid column is provided.
1344      * @see #toCollection()
1345      * @see #toCollection(int)
1346      * @see java.util.Vector
1347      */
1348     public Collection<?> toCollection(String column) throws SQLException {
1349         return toCollection(getColIdxByName(column));
1350     }
1351 
1352     //--------------------------------------------------------------------
1353     // Advanced features
1354     //--------------------------------------------------------------------
1355 
1356 
1357     /**
1358      * Returns the <code>SyncProvider</code> implementation being used
1359      * with this <code>CachedRowSetImpl</code> implementation rowset.
1360      *
1361      * @return the SyncProvider used by the rowset. If not provider was
1362      *          set when the rowset was instantiated, the reference
1363      *          implementation (default) provider is returned.
1364      * @throws SQLException if error occurs while return the
1365      *          <code>SyncProvider</code> instance.
1366      */
1367     public SyncProvider getSyncProvider() throws SQLException {
1368         return provider;
1369     }
1370 
1371     /**
1372      * Sets the active <code>SyncProvider</code> and attempts to load
1373      * load the new provider using the <code>SyncFactory</code> SPI.
1374      *
1375      * @throws SQLException if an error occurs while resetting the
1376      *          <code>SyncProvider</code>.
1377      */
1378     public void setSyncProvider(String providerStr) throws SQLException {
1379         provider =
1380         SyncFactory.getInstance(providerStr);
1381 
1382         rowSetReader = provider.getRowSetReader();
1383         rowSetWriter = provider.getRowSetWriter();
1384     }
1385 
1386 
1387     //-----------------
1388     // methods inherited from RowSet
1389     //-----------------
1390 
1391 
1392 
1393 
1394 
1395 
1396     //---------------------------------------------------------------------
1397     // Reading and writing data
1398     //---------------------------------------------------------------------
1399 
1400     /**
1401      * Populates this <code>CachedRowSetImpl</code> object with data.
1402      * This form of the method uses the rowset's user, password, and url or
1403      * data source name properties to create a database
1404      * connection.  If properties that are needed
1405      * have not been set, this method will throw an exception.
1406      * <P>
1407      * Another form of this method uses an existing JDBC <code>Connection</code>
1408      * object instead of creating a new one; therefore, it ignores the
1409      * properties used for establishing a new connection.
1410      * <P>
1411      * The query specified by the command property is executed to create a
1412      * <code>ResultSet</code> object from which to retrieve data.
1413      * The current contents of the rowset are discarded, and the
1414      * rowset's metadata is also (re)set.  If there are outstanding updates,
1415      * they are also ignored.
1416      * <P>
1417      * The method <code>execute</code> closes any database connections that it
1418      * creates.
1419      *
1420      * @throws SQLException if an error occurs or the
1421      *                         necessary properties have not been set
1422      */
1423     public void execute() throws SQLException {
1424         execute(null);
1425     }
1426 
1427 
1428 
1429     //-----------------------------------
1430     // Methods inherited from ResultSet
1431     //-----------------------------------
1432 
1433     /**
1434      * Moves the cursor down one row from its current position and
1435      * returns <code>true</code> if the new cursor position is a
1436      * valid row.
1437      * The cursor for a new <code>ResultSet</code> object is initially
1438      * positioned before the first row. The first call to the method
1439      * <code>next</code> moves the cursor to the first row, making it
1440      * the current row; the second call makes the second row the
1441      * current row, and so on.
1442      *
1443      * <P>If an input stream from the previous row is open, it is
1444      * implicitly closed. The <code>ResultSet</code> object's warning
1445      * chain is cleared when a new row is read.
1446      *
1447      * @return <code>true</code> if the new current row is valid;
1448      *         <code>false</code> if there are no more rows
1449      * @throws SQLException if an error occurs or
1450      *            the cursor is not positioned in the rowset, before
1451      *            the first row, or after the last row
1452      */
1453     public boolean next() throws SQLException {
1454         /*
1455          * make sure things look sane. The cursor must be
1456          * positioned in the rowset or before first (0) or
1457          * after last (numRows + 1)
1458          */
1459         if (cursorPos < 0 || cursorPos >= numRows + 1) {
1460             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1461         }
1462         // now move and notify
1463         boolean ret = this.internalNext();
1464         notifyCursorMoved();
1465 
1466         return ret;
1467     }
1468 
1469     /**
1470      * Moves this <code>CachedRowSetImpl</code> object's cursor to the next
1471      * row and returns <code>true</code> if the cursor is still in the rowset;
1472      * returns <code>false</code> if the cursor has moved to the position after
1473      * the last row.
1474      * <P>
1475      * This method handles the cases where the cursor moves to a row that
1476      * has been deleted.
1477      * If this rowset shows deleted rows and the cursor moves to a row
1478      * that has been deleted, this method moves the cursor to the next
1479      * row until the cursor is on a row that has not been deleted.
1480      * <P>
1481      * The method <code>internalNext</code> is called by methods such as
1482      * <code>next</code>, <code>absolute</code>, and <code>relative</code>,
1483      * and, as its name implies, is only called internally.
1484      * <p>
1485      * This is a implementation only method and is not required as a standard
1486      * implementation of the <code>CachedRowSet</code> interface.
1487      *
1488      * @return <code>true</code> if the cursor is on a valid row in this
1489      *         rowset; <code>false</code> if it is after the last row
1490      * @throws SQLException if an error occurs
1491      */
1492     protected boolean internalNext() throws SQLException {
1493         boolean ret = false;
1494 
1495         do {
1496             if (cursorPos < numRows) {
1497                 ++cursorPos;
1498                 ret = true;
1499             } else if (cursorPos == numRows) {
1500                 // increment to after last
1501                 ++cursorPos;
1502                 ret = false;
1503                 break;
1504             }
1505         } while ((getShowDeleted() == false) && (rowDeleted() == true));
1506 
1507         /* each call to internalNext may increment cursorPos multiple
1508          * times however, the absolutePos only increments once per call.
1509          */
1510         if (ret == true)
1511             absolutePos++;
1512         else
1513             absolutePos = 0;
1514 
1515         return ret;
1516     }
1517 
1518     /**
1519      * Closes this <code>CachedRowSetImpl</code> objecy and releases any resources
1520      * it was using.
1521      *
1522      * @throws SQLException if an error occurs when releasing any resources in use
1523      * by this <code>CachedRowSetImpl</code> object
1524      */
1525     public void close() throws SQLException {
1526 
1527         // close all data structures holding
1528         // the disconnected rowset
1529 
1530         cursorPos = 0;
1531         absolutePos = 0;
1532         numRows = 0;
1533         numDeleted = 0;
1534 
1535         // set all insert(s), update(s) & delete(s),
1536         // if at all, to their initial values.
1537         initProperties();
1538 
1539         // clear the vector of it's present contents
1540         rvh.clear();
1541 
1542         // this will make it eligible for gc
1543         // rvh = null;
1544     }
1545 
1546     /**
1547      * Reports whether the last column read was SQL <code>NULL</code>.
1548      * Note that you must first call the method <code>getXXX</code>
1549      * on a column to try to read its value and then call the method
1550      * <code>wasNull</code> to determine whether the value was
1551      * SQL <code>NULL</code>.
1552      *
1553      * @return <code>true</code> if the value in the last column read
1554      *         was SQL <code>NULL</code>; <code>false</code> otherwise
1555      * @throws SQLException if an error occurs
1556      */
1557     public boolean wasNull() throws SQLException {
1558         return lastValueNull;
1559     }
1560 
1561     /**
1562      * Sets the field <code>lastValueNull</code> to the given
1563      * <code>boolean</code> value.
1564      *
1565      * @param value <code>true</code> to indicate that the value of
1566      *        the last column read was SQL <code>NULL</code>;
1567      *        <code>false</code> to indicate that it was not
1568      */
1569     private void setLastValueNull(boolean value) {
1570         lastValueNull = value;
1571     }
1572 
1573     // Methods for accessing results by column index
1574 
1575     /**
1576      * Checks to see whether the given index is a valid column number
1577      * in this <code>CachedRowSetImpl</code> object and throws
1578      * an <code>SQLException</code> if it is not. The index is out of bounds
1579      * if it is less than <code>1</code> or greater than the number of
1580      * columns in this rowset.
1581      * <P>
1582      * This method is called internally by the <code>getXXX</code> and
1583      * <code>updateXXX</code> methods.
1584      *
1585      * @param idx the number of a column in this <code>CachedRowSetImpl</code>
1586      *            object; must be between <code>1</code> and the number of
1587      *            rows in this rowset
1588      * @throws SQLException if the given index is out of bounds
1589      */
1590     private void checkIndex(int idx) throws SQLException {
1591         if (idx < 1 || idx > RowSetMD.getColumnCount()) {
1592             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcol").toString());
1593         }
1594     }
1595 
1596     /**
1597      * Checks to see whether the cursor for this <code>CachedRowSetImpl</code>
1598      * object is on a row in the rowset and throws an
1599      * <code>SQLException</code> if it is not.
1600      * <P>
1601      * This method is called internally by <code>getXXX</code> methods, by
1602      * <code>updateXXX</code> methods, and by methods that update, insert,
1603      * or delete a row or that cancel a row update, insert, or delete.
1604      *
1605      * @throws SQLException if the cursor for this <code>CachedRowSetImpl</code>
1606      *         object is not on a valid row
1607      */
1608     private void checkCursor() throws SQLException {
1609         if (isAfterLast() == true || isBeforeFirst() == true) {
1610             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1611         }
1612     }
1613 
1614     /**
1615      * Returns the column number of the column with the given name in this
1616      * <code>CachedRowSetImpl</code> object.  This method throws an
1617      * <code>SQLException</code> if the given name is not the name of
1618      * one of the columns in this rowset.
1619      *
1620      * @param name a <code>String</code> object that is the name of a column in
1621      *              this <code>CachedRowSetImpl</code> object
1622      * @throws SQLException if the given name does not match the name of one of
1623      *         the columns in this rowset
1624      */
1625     private int getColIdxByName(String name) throws SQLException {
1626         RowSetMD = (RowSetMetaDataImpl)this.getMetaData();
1627         int cols = RowSetMD.getColumnCount();
1628 
1629         for (int i=1; i <= cols; ++i) {
1630             String colName = RowSetMD.getColumnName(i);
1631             if (colName != null)
1632                 if (name.equalsIgnoreCase(colName))
1633                     return (i);
1634                 else
1635                     continue;
1636         }
1637         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalcolnm").toString());
1638 
1639     }
1640 
1641     /**
1642      * Returns the insert row or the current row of this
1643      * <code>CachedRowSetImpl</code>object.
1644      *
1645      * @return the <code>Row</code> object on which this <code>CachedRowSetImpl</code>
1646      * objects's cursor is positioned
1647      */
1648     protected BaseRow getCurrentRow() {
1649         if (onInsertRow == true) {
1650             return (BaseRow)insertRow;
1651         } else {
1652             return (BaseRow)(rvh.get(cursorPos - 1));
1653         }
1654     }
1655 
1656     /**
1657      * Removes the row on which the cursor is positioned.
1658      * <p>
1659      * This is a implementation only method and is not required as a standard
1660      * implementation of the <code>CachedRowSet</code> interface.
1661      *
1662      * @throws SQLException if the cursor is positioned on the insert
1663      *            row
1664      */
1665     protected void removeCurrentRow() {
1666         ((Row)getCurrentRow()).setDeleted();
1667         rvh.remove(cursorPos - 1);
1668         --numRows;
1669     }
1670 
1671 
1672     /**
1673      * Retrieves the value of the designated column in the current row
1674      * of this <code>CachedRowSetImpl</code> object as a
1675      * <code>String</code> object.
1676      *
1677      * @param columnIndex the first column is <code>1</code>, the second
1678      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1679      *        and equal to or less than the number of columns in the rowset
1680      * @return the column value; if the value is SQL <code>NULL</code>, the
1681      *         result is <code>null</code>
1682      * @throws SQLException if (1) the given column index is out of bounds,
1683      * (2) the cursor is not on one of this rowset's rows or its
1684      * insert row, or (3) the designated column does not store an
1685      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
1686      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, <b>CHAR</b>, <b>VARCHAR</b></code>
1687      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1688      * recommended return type.
1689      */
1690     public String getString(int columnIndex) throws SQLException {
1691         Object value;
1692 
1693         // sanity check.
1694         checkIndex(columnIndex);
1695         // make sure the cursor is on a valid row
1696         checkCursor();
1697 
1698         setLastValueNull(false);
1699         value = getCurrentRow().getColumnObject(columnIndex);
1700 
1701         // check for SQL NULL
1702         if (value == null) {
1703             setLastValueNull(true);
1704             return null;
1705         }
1706 
1707         return value.toString();
1708     }
1709 
1710     /**
1711      * Retrieves the value of the designated column in the current row
1712      * of this <code>CachedRowSetImpl</code> object as a
1713      * <code>boolean</code> value.
1714      *
1715      * @param columnIndex the first column is <code>1</code>, the second
1716      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1717      *        and equal to or less than the number of columns in the rowset
1718      * @return the column value as a <code>boolean</code> in the Java progamming language;
1719      *        if the value is SQL <code>NULL</code>, the result is <code>false</code>
1720      * @throws SQLException if (1) the given column index is out of bounds,
1721      *            (2) the cursor is not on one of this rowset's rows or its
1722      *            insert row, or (3) the designated column does not store an
1723      *            SQL <code>BOOLEAN</code> value
1724      * @see #getBoolean(String)
1725      */
1726     public boolean getBoolean(int columnIndex) throws SQLException {
1727         Object value;
1728 
1729         // sanity check.
1730         checkIndex(columnIndex);
1731         // make sure the cursor is on a valid row
1732         checkCursor();
1733 
1734         setLastValueNull(false);
1735         value = getCurrentRow().getColumnObject(columnIndex);
1736 
1737         // check for SQL NULL
1738         if (value == null) {
1739             setLastValueNull(true);
1740             return false;
1741         }
1742 
1743         // check for Boolean...
1744         if (value instanceof Boolean) {
1745             return ((Boolean)value).booleanValue();
1746         }
1747 
1748         // convert to a Double and compare to zero
1749         try {
1750             return Double.compare(Double.parseDouble(value.toString()), 0) != 0;
1751         } catch (NumberFormatException ex) {
1752             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.boolfail").toString(),
1753                   new Object[] {value.toString().trim(), columnIndex}));
1754         }
1755     }
1756 
1757     /**
1758      * Retrieves the value of the designated column in the current row
1759      * of this <code>CachedRowSetImpl</code> object as a
1760      * <code>byte</code> value.
1761      *
1762      * @param columnIndex the first column is <code>1</code>, the second
1763      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1764      *        and equal to or less than the number of columns in the rowset
1765      * @return the column value as a <code>byte</code> in the Java programming
1766      * language; if the value is SQL <code>NULL</code>, the result is <code>0</code>
1767      * @throws SQLException if (1) the given column index is out of bounds,
1768      *            (2) the cursor is not on one of this rowset's rows or its
1769      *            insert row, or (3) the designated column does not store an
1770      *            SQL <code><b>TINYINT</b>, SMALLINT, INTEGER, BIGINT, REAL,
1771      *            FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1772      *            or <code>LONGVARCHAR</code> value. The bold SQL type
1773      *            designates the recommended return type.
1774      * @see #getByte(String)
1775      */
1776     public byte getByte(int columnIndex) throws SQLException {
1777         Object value;
1778 
1779         // sanity check.
1780         checkIndex(columnIndex);
1781         // make sure the cursor is on a valid row
1782         checkCursor();
1783 
1784         setLastValueNull(false);
1785         value = getCurrentRow().getColumnObject(columnIndex);
1786 
1787         // check for SQL NULL
1788         if (value == null) {
1789             setLastValueNull(true);
1790             return (byte)0;
1791         }
1792         try {
1793             return ((Byte.valueOf(value.toString())).byteValue());
1794         } catch (NumberFormatException ex) {
1795             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.bytefail").toString(),
1796                   new Object[] {value.toString().trim(), columnIndex}));
1797         }
1798     }
1799 
1800     /**
1801      * Retrieves the value of the designated column in the current row
1802      * of this <code>CachedRowSetImpl</code> object as a
1803      * <code>short</code> value.
1804      *
1805      * @param columnIndex the first column is <code>1</code>, the second
1806      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1807      *        and equal to or less than the number of columns in the rowset
1808      * @return the column value; if the value is SQL <code>NULL</code>, the
1809      *         result is <code>0</code>
1810      * @throws SQLException if (1) the given column index is out of bounds,
1811      * (2) the cursor is not on one of this rowset's rows or its
1812      * insert row, or (3) the designated column does not store an
1813      * SQL <code>TINYINT, <b>SMALLINT</b>, INTEGER, BIGINT, REAL
1814      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1815      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1816      * recommended return type.
1817      * @see #getShort(String)
1818      */
1819     public short getShort(int columnIndex) throws SQLException {
1820         Object value;
1821 
1822         // sanity check.
1823         checkIndex(columnIndex);
1824         // make sure the cursor is on a valid row
1825         checkCursor();
1826 
1827         setLastValueNull(false);
1828         value = getCurrentRow().getColumnObject(columnIndex);
1829 
1830         // check for SQL NULL
1831         if (value == null) {
1832             setLastValueNull(true);
1833             return (short)0;
1834         }
1835 
1836         try {
1837             return ((Short.valueOf(value.toString().trim())).shortValue());
1838         } catch (NumberFormatException ex) {
1839             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.shortfail").toString(),
1840                   new Object[] {value.toString().trim(), columnIndex}));
1841         }
1842     }
1843 
1844     /**
1845      * Retrieves the value of the designated column in the current row
1846      * of this <code>CachedRowSetImpl</code> object as an
1847      * <code>int</code> value.
1848      *
1849      * @param columnIndex the first column is <code>1</code>, the second
1850      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1851      *        and equal to or less than the number of columns in the rowset
1852      * @return the column value; if the value is SQL <code>NULL</code>, the
1853      *         result is <code>0</code>
1854      * @throws SQLException if (1) the given column index is out of bounds,
1855      * (2) the cursor is not on one of this rowset's rows or its
1856      * insert row, or (3) the designated column does not store an
1857      * SQL <code>TINYINT, SMALLINT, <b>INTEGER</b>, BIGINT, REAL
1858      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1859      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1860      * recommended return type.
1861      */
1862     public int getInt(int columnIndex) throws SQLException {
1863         Object value;
1864 
1865         // sanity check.
1866         checkIndex(columnIndex);
1867         // make sure the cursor is on a valid row
1868         checkCursor();
1869 
1870         setLastValueNull(false);
1871         value = getCurrentRow().getColumnObject(columnIndex);
1872 
1873         // check for SQL NULL
1874         if (value == null) {
1875             setLastValueNull(true);
1876             return 0;
1877         }
1878 
1879         try {
1880             return ((Integer.valueOf(value.toString().trim())).intValue());
1881         } catch (NumberFormatException ex) {
1882             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.intfail").toString(),
1883                   new Object[] {value.toString().trim(), columnIndex}));
1884         }
1885     }
1886 
1887     /**
1888      * Retrieves the value of the designated column in the current row
1889      * of this <code>CachedRowSetImpl</code> object as a
1890      * <code>long</code> value.
1891      *
1892      * @param columnIndex the first column is <code>1</code>, the second
1893      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1894      *        and equal to or less than the number of columns in the rowset
1895      * @return the column value; if the value is SQL <code>NULL</code>, the
1896      *         result is <code>0</code>
1897      * @throws SQLException if (1) the given column index is out of bounds,
1898      * (2) the cursor is not on one of this rowset's rows or its
1899      * insert row, or (3) the designated column does not store an
1900      * SQL <code>TINYINT, SMALLINT, INTEGER, <b>BIGINT</b>, REAL
1901      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1902      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1903      * recommended return type.
1904      * @see #getLong(String)
1905      */
1906     public long getLong(int columnIndex) throws SQLException {
1907         Object value;
1908 
1909         // sanity check.
1910         checkIndex(columnIndex);
1911         // make sure the cursor is on a valid row
1912         checkCursor();
1913 
1914         setLastValueNull(false);
1915         value = getCurrentRow().getColumnObject(columnIndex);
1916 
1917         // check for SQL NULL
1918         if (value == null) {
1919             setLastValueNull(true);
1920             return (long)0;
1921         }
1922         try {
1923             return ((Long.valueOf(value.toString().trim())).longValue());
1924         } catch (NumberFormatException ex) {
1925             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.longfail").toString(),
1926                   new Object[] {value.toString().trim(), columnIndex}));
1927         }
1928     }
1929 
1930     /**
1931      * Retrieves the value of the designated column in the current row
1932      * of this <code>CachedRowSetImpl</code> object as a
1933      * <code>float</code> value.
1934      *
1935      * @param columnIndex the first column is <code>1</code>, the second
1936      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1937      *        and equal to or less than the number of columns in the rowset
1938      * @return the column value; if the value is SQL <code>NULL</code>, the
1939      *         result is <code>0</code>
1940      * @throws SQLException if (1) the given column index is out of bounds,
1941      * (2) the cursor is not on one of this rowset's rows or its
1942      * insert row, or (3) the designated column does not store an
1943      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, <b>REAL</b>,
1944      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1945      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1946      * recommended return type.
1947      * @see #getFloat(String)
1948      */
1949     public float getFloat(int columnIndex) throws SQLException {
1950         Object value;
1951 
1952         // sanity check.
1953         checkIndex(columnIndex);
1954         // make sure the cursor is on a valid row
1955         checkCursor();
1956 
1957         setLastValueNull(false);
1958         value = getCurrentRow().getColumnObject(columnIndex);
1959 
1960         // check for SQL NULL
1961         if (value == null) {
1962             setLastValueNull(true);
1963             return (float)0;
1964         }
1965         try {
1966             return Float.parseFloat(value.toString());
1967         } catch (NumberFormatException ex) {
1968             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.floatfail").toString(),
1969                   new Object[] {value.toString().trim(), columnIndex}));
1970         }
1971     }
1972 
1973     /**
1974      * Retrieves the value of the designated column in the current row
1975      * of this <code>CachedRowSetImpl</code> object as a
1976      * <code>double</code> value.
1977      *
1978      * @param columnIndex the first column is <code>1</code>, the second
1979      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1980      *        and equal to or less than the number of columns in the rowset
1981      * @return the column value; if the value is SQL <code>NULL</code>, the
1982      *         result is <code>0</code>
1983      * @throws SQLException if (1) the given column index is out of bounds,
1984      * (2) the cursor is not on one of this rowset's rows or its
1985      * insert row, or (3) the designated column does not store an
1986      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
1987      * <b>FLOAT</b>, <b>DOUBLE</b>, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1988      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1989      * recommended return type.
1990      * @see #getDouble(String)
1991      *
1992      */
1993     public double getDouble(int columnIndex) throws SQLException {
1994         Object value;
1995 
1996         // sanity check.
1997         checkIndex(columnIndex);
1998         // make sure the cursor is on a valid row
1999         checkCursor();
2000 
2001         setLastValueNull(false);
2002         value = getCurrentRow().getColumnObject(columnIndex);
2003 
2004         // check for SQL NULL
2005         if (value == null) {
2006             setLastValueNull(true);
2007             return (double)0;
2008         }
2009         try {
2010             return Double.parseDouble(value.toString().trim());
2011         } catch (NumberFormatException ex) {
2012             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.doublefail").toString(),
2013                   new Object[] {value.toString().trim(), columnIndex}));
2014         }
2015     }
2016 
2017     /**
2018      * Retrieves the value of the designated column in the current row
2019      * of this <code>CachedRowSetImpl</code> object as a
2020      * <code>java.math.BigDecimal</code> object.
2021      * <P>
2022      * This method is deprecated; use the version of <code>getBigDecimal</code>
2023      * that does not take a scale parameter and returns a value with full
2024      * precision.
2025      *
2026      * @param columnIndex the first column is <code>1</code>, the second
2027      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2028      *        and equal to or less than the number of columns in the rowset
2029      * @param scale the number of digits to the right of the decimal point in the
2030      *        value returned
2031      * @return the column value with the specified number of digits to the right
2032      *         of the decimal point; if the value is SQL <code>NULL</code>, the
2033      *         result is <code>null</code>
2034      * @throws SQLException if the given column index is out of bounds,
2035      *            the cursor is not on a valid row, or this method fails
2036      * @deprecated
2037      */
2038     @Deprecated
2039     public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
2040         Object value;
2041         BigDecimal bDecimal, retVal;
2042 
2043         // sanity check.
2044         checkIndex(columnIndex);
2045         // make sure the cursor is on a valid row
2046         checkCursor();
2047 
2048         setLastValueNull(false);
2049         value = getCurrentRow().getColumnObject(columnIndex);
2050 
2051         // check for SQL NULL
2052         if (value == null) {
2053             setLastValueNull(true);
2054             return (new BigDecimal(0));
2055         }
2056 
2057         bDecimal = this.getBigDecimal(columnIndex);
2058 
2059         retVal = bDecimal.setScale(scale);
2060 
2061         return retVal;
2062     }
2063 
2064     /**
2065      * Retrieves the value of the designated column in the current row
2066      * of this <code>CachedRowSetImpl</code> object as a
2067      * <code>byte</code> array value.
2068      *
2069      * @param columnIndex the first column is <code>1</code>, the second
2070      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2071      *        and equal to or less than the number of columns in the rowset
2072      * @return the column value as a <code>byte</code> array in the Java programming
2073      * language; if the value is SQL <code>NULL</code>, the
2074      * result is <code>null</code>
2075      *
2076      * @throws SQLException if (1) the given column index is out of bounds,
2077      * (2) the cursor is not on one of this rowset's rows or its
2078      * insert row, or (3) the designated column does not store an
2079      * SQL <code><b>BINARY</b>, <b>VARBINARY</b> or
2080      * LONGVARBINARY</code> value.
2081      * The bold SQL type designates the recommended return type.
2082      * @see #getBytes(String)
2083      */
2084     public byte[] getBytes(int columnIndex) throws SQLException {
2085         // sanity check.
2086         checkIndex(columnIndex);
2087         // make sure the cursor is on a valid row
2088         checkCursor();
2089 
2090         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
2091             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2092         }
2093 
2094         return (byte[])(getCurrentRow().getColumnObject(columnIndex));
2095     }
2096 
2097     /**
2098      * Retrieves the value of the designated column in the current row
2099      * of this <code>CachedRowSetImpl</code> object as a
2100      * <code>java.sql.Date</code> object.
2101      *
2102      * @param columnIndex the first column is <code>1</code>, the second
2103      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2104      *        and equal to or less than the number of columns in the rowset
2105      * @return the column value as a <code>java.sql.Data</code> object; if
2106      *        the value is SQL <code>NULL</code>, the
2107      *        result is <code>null</code>
2108      * @throws SQLException if the given column index is out of bounds,
2109      *            the cursor is not on a valid row, or this method fails
2110      */
2111     public java.sql.Date getDate(int columnIndex) throws SQLException {
2112         Object value;
2113 
2114         // sanity check.
2115         checkIndex(columnIndex);
2116         // make sure the cursor is on a valid row
2117         checkCursor();
2118 
2119         setLastValueNull(false);
2120         value = getCurrentRow().getColumnObject(columnIndex);
2121 
2122         // check for SQL NULL
2123         if (value == null) {
2124             setLastValueNull(true);
2125             return null;
2126         }
2127 
2128         /*
2129          * The object coming back from the db could be
2130          * a date, a timestamp, or a char field variety.
2131          * If it's a date type return it, a timestamp
2132          * we turn into a long and then into a date,
2133          * char strings we try to parse. Yuck.
2134          */
2135         switch (RowSetMD.getColumnType(columnIndex)) {
2136             case java.sql.Types.DATE: {
2137                 long sec = ((java.sql.Date)value).getTime();
2138                 return new java.sql.Date(sec);
2139             }
2140             case java.sql.Types.TIMESTAMP: {
2141                 long sec = ((java.sql.Timestamp)value).getTime();
2142                 return new java.sql.Date(sec);
2143             }
2144             case java.sql.Types.CHAR:
2145             case java.sql.Types.VARCHAR:
2146             case java.sql.Types.LONGVARCHAR: {
2147                 try {
2148                     DateFormat df = DateFormat.getDateInstance();
2149                     return ((java.sql.Date)(df.parse(value.toString())));
2150                 } catch (ParseException ex) {
2151                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.datefail").toString(),
2152                         new Object[] {value.toString().trim(), columnIndex}));
2153                 }
2154             }
2155             default: {
2156                 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.datefail").toString(),
2157                         new Object[] {value.toString().trim(), columnIndex}));
2158             }
2159         }
2160     }
2161 
2162     /**
2163      * Retrieves the value of the designated column in the current row
2164      * of this <code>CachedRowSetImpl</code> object as a
2165      * <code>java.sql.Time</code> object.
2166      *
2167      * @param columnIndex the first column is <code>1</code>, the second
2168      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2169      *        and equal to or less than the number of columns in the rowset
2170      * @return the column value; if the value is SQL <code>NULL</code>, the
2171      *         result is <code>null</code>
2172      * @throws SQLException if the given column index is out of bounds,
2173      *         the cursor is not on a valid row, or this method fails
2174      */
2175     public java.sql.Time getTime(int columnIndex) throws SQLException {
2176         Object value;
2177 
2178         // sanity check.
2179         checkIndex(columnIndex);
2180         // make sure the cursor is on a valid row
2181         checkCursor();
2182 
2183         setLastValueNull(false);
2184         value = getCurrentRow().getColumnObject(columnIndex);
2185 
2186         // check for SQL NULL
2187         if (value == null) {
2188             setLastValueNull(true);
2189             return null;
2190         }
2191 
2192         /*
2193          * The object coming back from the db could be
2194          * a date, a timestamp, or a char field variety.
2195          * If it's a date type return it, a timestamp
2196          * we turn into a long and then into a date,
2197          * char strings we try to parse. Yuck.
2198          */
2199         switch (RowSetMD.getColumnType(columnIndex)) {
2200             case java.sql.Types.TIME: {
2201                 return (java.sql.Time)value;
2202             }
2203             case java.sql.Types.TIMESTAMP: {
2204                 long sec = ((java.sql.Timestamp)value).getTime();
2205                 return new java.sql.Time(sec);
2206             }
2207             case java.sql.Types.CHAR:
2208             case java.sql.Types.VARCHAR:
2209             case java.sql.Types.LONGVARCHAR: {
2210                 try {
2211                     DateFormat tf = DateFormat.getTimeInstance();
2212                     return ((java.sql.Time)(tf.parse(value.toString())));
2213                 } catch (ParseException ex) {
2214                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2215                         new Object[] {value.toString().trim(), columnIndex}));
2216                 }
2217             }
2218             default: {
2219                 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2220                         new Object[] {value.toString().trim(), columnIndex}));
2221             }
2222         }
2223     }
2224 
2225     /**
2226      * Retrieves the value of the designated column in the current row
2227      * of this <code>CachedRowSetImpl</code> object as a
2228      * <code>java.sql.Timestamp</code> object.
2229      *
2230      * @param columnIndex the first column is <code>1</code>, the second
2231      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2232      *        and equal to or less than the number of columns in the rowset
2233      * @return the column value; if the value is SQL <code>NULL</code>, the
2234      *         result is <code>null</code>
2235      * @throws SQLException if the given column index is out of bounds,
2236      *            the cursor is not on a valid row, or this method fails
2237      */
2238     public java.sql.Timestamp getTimestamp(int columnIndex) throws SQLException {
2239         Object value;
2240 
2241         // sanity check.
2242         checkIndex(columnIndex);
2243         // make sure the cursor is on a valid row
2244         checkCursor();
2245 
2246         setLastValueNull(false);
2247         value = getCurrentRow().getColumnObject(columnIndex);
2248 
2249         // check for SQL NULL
2250         if (value == null) {
2251             setLastValueNull(true);
2252             return null;
2253         }
2254 
2255         /*
2256          * The object coming back from the db could be
2257          * a date, a timestamp, or a char field variety.
2258          * If it's a date type return it; a timestamp
2259          * we turn into a long and then into a date;
2260          * char strings we try to parse. Yuck.
2261          */
2262         switch (RowSetMD.getColumnType(columnIndex)) {
2263             case java.sql.Types.TIMESTAMP: {
2264                 return (java.sql.Timestamp)value;
2265             }
2266             case java.sql.Types.TIME: {
2267                 long sec = ((java.sql.Time)value).getTime();
2268                 return new java.sql.Timestamp(sec);
2269             }
2270             case java.sql.Types.DATE: {
2271                 long sec = ((java.sql.Date)value).getTime();
2272                 return new java.sql.Timestamp(sec);
2273             }
2274             case java.sql.Types.CHAR:
2275             case java.sql.Types.VARCHAR:
2276             case java.sql.Types.LONGVARCHAR: {
2277                 try {
2278                     DateFormat tf = DateFormat.getTimeInstance();
2279                     return ((java.sql.Timestamp)(tf.parse(value.toString())));
2280                 } catch (ParseException ex) {
2281                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2282                         new Object[] {value.toString().trim(), columnIndex}));
2283                 }
2284             }
2285             default: {
2286                 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2287                         new Object[] {value.toString().trim(), columnIndex}));
2288             }
2289         }
2290     }
2291 
2292     /**
2293      * Retrieves the value of the designated column in the current row of this
2294      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2295      * object.
2296      *
2297      * A column value can be retrieved as a stream of ASCII characters
2298      * and then read in chunks from the stream.  This method is particularly
2299      * suitable for retrieving large <code>LONGVARCHAR</code> values.  The JDBC
2300      * driver will do any necessary conversion from the database format into ASCII.
2301      *
2302      * <P><B>Note:</B> All the data in the returned stream must be
2303      * read prior to getting the value of any other column. The next
2304      * call to a get method implicitly closes the stream. . Also, a
2305      * stream may return <code>0</code> for <code>CachedRowSetImpl.available()</code>
2306      * whether there is data available or not.
2307      *
2308      * @param columnIndex the first column is <code>1</code>, the second
2309      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2310      *        and equal to or less than the number of columns in this rowset
2311      * @return a Java input stream that delivers the database column value
2312      *         as a stream of one-byte ASCII characters.  If the value is SQL
2313      *         <code>NULL</code>, the result is <code>null</code>.
2314      * @throws SQLException if (1) the given column index is out of bounds,
2315      * (2) the cursor is not on one of this rowset's rows or its
2316      * insert row, or (3) the designated column does not store an
2317      * SQL <code>CHAR, VARCHAR</code>, <code><b>LONGVARCHAR</b></code>
2318      * <code>BINARY, VARBINARY</code> or <code>LONGVARBINARY</code> value. The
2319      * bold SQL type designates the recommended return types that this method is
2320      * used to retrieve.
2321      * @see #getAsciiStream(String)
2322      */
2323     public java.io.InputStream getAsciiStream(int columnIndex) throws SQLException {
2324         Object value;
2325 
2326         // always free an old stream
2327         asciiStream = null;
2328 
2329         // sanity check
2330         checkIndex(columnIndex);
2331         //make sure the cursor is on a vlid row
2332         checkCursor();
2333 
2334         value =  getCurrentRow().getColumnObject(columnIndex);
2335         if (value == null) {
2336             lastValueNull = true;
2337             return null;
2338         }
2339 
2340         try {
2341             if (isString(RowSetMD.getColumnType(columnIndex))) {
2342                 asciiStream = new ByteArrayInputStream(((String)value).getBytes("ASCII"));
2343             } else {
2344                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2345             }
2346         } catch (java.io.UnsupportedEncodingException ex) {
2347             throw new SQLException(ex.getMessage());
2348         }
2349 
2350         return asciiStream;
2351     }
2352 
2353     /**
2354      * A column value can be retrieved as a stream of Unicode characters
2355      * and then read in chunks from the stream.  This method is particularly
2356      * suitable for retrieving large LONGVARCHAR values.  The JDBC driver will
2357      * do any necessary conversion from the database format into Unicode.
2358      *
2359      * <P><B>Note:</B> All the data in the returned stream must be
2360      * read prior to getting the value of any other column. The next
2361      * call to a get method implicitly closes the stream. . Also, a
2362      * stream may return 0 for available() whether there is data
2363      * available or not.
2364      *
2365      * @param columnIndex the first column is <code>1</code>, the second
2366      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2367      *        and equal to or less than the number of columns in this rowset
2368      * @return a Java input stream that delivers the database column value
2369      * as a stream of two byte Unicode characters.  If the value is SQL NULL
2370      * then the result is null.
2371      * @throws SQLException if an error occurs
2372      * @deprecated
2373      */
2374     @Deprecated
2375     public java.io.InputStream getUnicodeStream(int columnIndex) throws SQLException {
2376         // always free an old stream
2377         unicodeStream = null;
2378 
2379         // sanity check.
2380         checkIndex(columnIndex);
2381         // make sure the cursor is on a valid row
2382         checkCursor();
2383 
2384         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false &&
2385         isString(RowSetMD.getColumnType(columnIndex)) == false) {
2386             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2387         }
2388 
2389         Object value = getCurrentRow().getColumnObject(columnIndex);
2390         if (value == null) {
2391             lastValueNull = true;
2392             return null;
2393         }
2394 
2395         unicodeStream = new StringBufferInputStream(value.toString());
2396 
2397         return unicodeStream;
2398     }
2399 
2400     /**
2401      * Retrieves the value of the designated column in the current row of this
2402      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2403      * object.
2404      * <P>
2405      * A column value can be retrieved as a stream of uninterpreted bytes
2406      * and then read in chunks from the stream.  This method is particularly
2407      * suitable for retrieving large <code>LONGVARBINARY</code> values.
2408      *
2409      * <P><B>Note:</B> All the data in the returned stream must be
2410      * read prior to getting the value of any other column. The next
2411      * call to a get method implicitly closes the stream. Also, a
2412      * stream may return <code>0</code> for
2413      * <code>CachedRowSetImpl.available()</code> whether there is data
2414      * available or not.
2415      *
2416      * @param columnIndex the first column is <code>1</code>, the second
2417      * is <code>2</code>, and so on; must be <code>1</code> or larger
2418      * and equal to or less than the number of columns in the rowset
2419      * @return a Java input stream that delivers the database column value
2420      * as a stream of uninterpreted bytes.  If the value is SQL <code>NULL</code>
2421      * then the result is <code>null</code>.
2422      * @throws SQLException if (1) the given column index is out of bounds,
2423      * (2) the cursor is not on one of this rowset's rows or its
2424      * insert row, or (3) the designated column does not store an
2425      * SQL <code>BINARY, VARBINARY</code> or <code><b>LONGVARBINARY</b></code>
2426      * The bold type indicates the SQL type that this method is recommened
2427      * to retrieve.
2428      * @see #getBinaryStream(String)
2429      */
2430     public java.io.InputStream getBinaryStream(int columnIndex) throws SQLException {
2431 
2432         // always free an old stream
2433         binaryStream = null;
2434 
2435         // sanity check.
2436         checkIndex(columnIndex);
2437         // make sure the cursor is on a valid row
2438         checkCursor();
2439 
2440         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
2441             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2442         }
2443 
2444         Object value = getCurrentRow().getColumnObject(columnIndex);
2445         if (value == null) {
2446             lastValueNull = true;
2447             return null;
2448         }
2449 
2450         binaryStream = new ByteArrayInputStream((byte[])value);
2451 
2452         return binaryStream;
2453 
2454     }
2455 
2456 
2457     // Methods for accessing results by column name
2458 
2459     /**
2460      * Retrieves the value stored in the designated column
2461      * of the current row as a <code>String</code> object.
2462      *
2463      * @param columnName a <code>String</code> object giving the SQL name of
2464      *        a column in this <code>CachedRowSetImpl</code> object
2465      * @return the column value; if the value is SQL <code>NULL</code>,
2466      *         the result is <code>null</code>
2467      * @throws SQLException if (1) the given column name is not the name of
2468      * a column in this rowset, (2) the cursor is not on one of
2469      * this rowset's rows or its insert row, or (3) the designated
2470      * column does not store an SQL {@code TINYINT, SMALLINT, INTEGER
2471      * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, }
2472      * <b>{@code CHAR, VARCHAR}</b> or
2473      * <b>{@code LONGVARCHAR}</b> value.
2474      * The bold SQL type designates the recommended return type.
2475      */
2476     public String getString(String columnName) throws SQLException {
2477         return getString(getColIdxByName(columnName));
2478     }
2479 
2480     /**
2481      * Retrieves the value stored in the designated column
2482      * of the current row as a <code>boolean</code> value.
2483      *
2484      * @param columnName a <code>String</code> object giving the SQL name of
2485      *        a column in this <code>CachedRowSetImpl</code> object
2486      * @return the column value as a <code>boolean</code> in the Java programming
2487      *        language; if the value is SQL <code>NULL</code>,
2488      *        the result is <code>false</code>
2489      * @throws SQLException if (1) the given column name is not the name of
2490      *            a column in this rowset, (2) the cursor is not on one of
2491      *            this rowset's rows or its insert row, or (3) the designated
2492      *            column does not store an SQL <code>BOOLEAN</code> value
2493      * @see #getBoolean(int)
2494      */
2495     public boolean getBoolean(String columnName) throws SQLException {
2496         return getBoolean(getColIdxByName(columnName));
2497     }
2498 
2499     /**
2500      * Retrieves the value stored in the designated column
2501      * of the current row as a <code>byte</code> value.
2502      *
2503      * @param columnName a <code>String</code> object giving the SQL name of
2504      *        a column in this <code>CachedRowSetImpl</code> object
2505      * @return the column value as a <code>byte</code> in the Java programming
2506      * language; if the value is SQL <code>NULL</code>, the result is <code>0</code>
2507      * @throws SQLException if (1) the given column name is not the name of
2508      * a column in this rowset, (2) the cursor is not on one of
2509      * this rowset's rows or its insert row, or (3) the designated
2510      * column does not store an SQL <code><B>TINYINT</B>, SMALLINT, INTEGER,
2511      * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2512      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The
2513      * bold type designates the recommended return type
2514      */
2515     public byte getByte(String columnName) throws SQLException {
2516         return getByte(getColIdxByName(columnName));
2517     }
2518 
2519     /**
2520      * Retrieves the value stored in the designated column
2521      * of the current row as a <code>short</code> value.
2522      *
2523      * @param columnName a <code>String</code> object giving the SQL name of
2524      *        a column in this <code>CachedRowSetImpl</code> object
2525      * @return the column value; if the value is SQL <code>NULL</code>,
2526      *         the result is <code>0</code>
2527      * @throws SQLException if (1) the given column name is not the name of
2528      * a column in this rowset, (2) the cursor is not on one of
2529      * this rowset's rows or its insert row, or (3) the designated
2530      * column does not store an SQL <code>TINYINT, <b>SMALLINT</b>, INTEGER
2531      * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2532      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2533      * designates the recommended return type.
2534      * @see #getShort(int)
2535      */
2536     public short getShort(String columnName) throws SQLException {
2537         return getShort(getColIdxByName(columnName));
2538     }
2539 
2540     /**
2541      * Retrieves the value stored in the designated column
2542      * of the current row as an <code>int</code> value.
2543      *
2544      * @param columnName a <code>String</code> object giving the SQL name of
2545      *        a column in this <code>CachedRowSetImpl</code> object
2546      * @return the column value; if the value is SQL <code>NULL</code>,
2547      *         the result is <code>0</code>
2548      * @throws SQLException if (1) the given column name is not the name
2549      * of a column in this rowset,
2550      * (2) the cursor is not on one of this rowset's rows or its
2551      * insert row, or (3) the designated column does not store an
2552      * SQL <code>TINYINT, SMALLINT, <b>INTEGER</b>, BIGINT, REAL
2553      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
2554      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
2555      * recommended return type.
2556      */
2557     public int getInt(String columnName) throws SQLException {
2558         return getInt(getColIdxByName(columnName));
2559     }
2560 
2561     /**
2562      * Retrieves the value stored in the designated column
2563      * of the current row as a <code>long</code> value.
2564      *
2565      * @param columnName a <code>String</code> object giving the SQL name of
2566      *        a column in this <code>CachedRowSetImpl</code> object
2567      * @return the column value; if the value is SQL <code>NULL</code>,
2568      *         the result is <code>0</code>
2569      * @throws SQLException if (1) the given column name is not the name of
2570      * a column in this rowset, (2) the cursor is not on one of
2571      * this rowset's rows or its insert row, or (3) the designated
2572      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2573      * <b>BIGINT</b>, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2574      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2575      * designates the recommended return type.
2576      * @see #getLong(int)
2577      */
2578     public long getLong(String columnName) throws SQLException {
2579         return getLong(getColIdxByName(columnName));
2580     }
2581 
2582     /**
2583      * Retrieves the value stored in the designated column
2584      * of the current row as a <code>float</code> value.
2585      *
2586      * @param columnName a <code>String</code> object giving the SQL name of
2587      *        a column in this <code>CachedRowSetImpl</code> object
2588      * @return the column value; if the value is SQL <code>NULL</code>,
2589      *         the result is <code>0</code>
2590      * @throws SQLException if (1) the given column name is not the name of
2591      * a column in this rowset, (2) the cursor is not on one of
2592      * this rowset's rows or its insert row, or (3) the designated
2593      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2594      * BIGINT, <b>REAL</b>, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2595      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2596      * designates the recommended return type.
2597      * @see #getFloat(String)
2598      */
2599     public float getFloat(String columnName) throws SQLException {
2600         return getFloat(getColIdxByName(columnName));
2601     }
2602 
2603     /**
2604      * Retrieves the value stored in the designated column
2605      * of the current row of this <code>CachedRowSetImpl</code> object
2606      * as a <code>double</code> value.
2607      *
2608      * @param columnName a <code>String</code> object giving the SQL name of
2609      *        a column in this <code>CachedRowSetImpl</code> object
2610      * @return the column value; if the value is SQL <code>NULL</code>,
2611      *         the result is <code>0</code>
2612      * @throws SQLException if (1) the given column name is not the name of
2613      * a column in this rowset, (2) the cursor is not on one of
2614      * this rowset's rows or its insert row, or (3) the designated
2615      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2616      * BIGINT, REAL, <b>FLOAT</b>, <b>DOUBLE</b>, DECIMAL, NUMERIC, BIT, CHAR,
2617      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2618      * designates the recommended return types.
2619      * @see #getDouble(int)
2620      */
2621     public double getDouble(String columnName) throws SQLException {
2622         return getDouble(getColIdxByName(columnName));
2623     }
2624 
2625     /**
2626      * Retrieves the value stored in the designated column
2627      * of the current row as a <code>java.math.BigDecimal</code> object.
2628      *
2629      * @param columnName a <code>String</code> object giving the SQL name of
2630      *        a column in this <code>CachedRowSetImpl</code> object
2631      * @param scale the number of digits to the right of the decimal point
2632      * @return a java.math.BugDecimal object with <code><i>scale</i></code>
2633      * number of digits to the right of the decimal point.
2634      * @throws SQLException if (1) the given column name is not the name of
2635      * a column in this rowset, (2) the cursor is not on one of
2636      * this rowset's rows or its insert row, or (3) the designated
2637      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2638      * BIGINT, REAL, FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT CHAR,
2639      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2640      * designates the recommended return type that this method is used to
2641      * retrieve.
2642      * @deprecated Use the <code>getBigDecimal(String columnName)</code>
2643      *             method instead
2644      */
2645     @Deprecated
2646     public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {
2647         return getBigDecimal(getColIdxByName(columnName), scale);
2648     }
2649 
2650     /**
2651      * Retrieves the value stored in the designated column
2652      * of the current row as a <code>byte</code> array.
2653      * The bytes represent the raw values returned by the driver.
2654      *
2655      * @param columnName a <code>String</code> object giving the SQL name of
2656      *        a column in this <code>CachedRowSetImpl</code> object
2657      * @return the column value as a <code>byte</code> array in the Java programming
2658      * language; if the value is SQL <code>NULL</code>, the result is <code>null</code>
2659      * @throws SQLException if (1) the given column name is not the name of
2660      * a column in this rowset, (2) the cursor is not on one of
2661      * this rowset's rows or its insert row, or (3) the designated
2662      * column does not store an SQL <code><b>BINARY</b>, <b>VARBINARY</b>
2663      * </code> or <code>LONGVARBINARY</code> values
2664      * The bold SQL type designates the recommended return type.
2665      * @see #getBytes(int)
2666      */
2667     public byte[] getBytes(String columnName) throws SQLException {
2668         return getBytes(getColIdxByName(columnName));
2669     }
2670 
2671     /**
2672      * Retrieves the value stored in the designated column
2673      * of the current row as a <code>java.sql.Date</code> object.
2674      *
2675      * @param columnName a <code>String</code> object giving the SQL name of
2676      *        a column in this <code>CachedRowSetImpl</code> object
2677      * @return the column value; if the value is SQL <code>NULL</code>,
2678      *         the result is <code>null</code>
2679      * @throws SQLException if (1) the given column name is not the name of
2680      *            a column in this rowset, (2) the cursor is not on one of
2681      *            this rowset's rows or its insert row, or (3) the designated
2682      *            column does not store an SQL <code>DATE</code> or
2683      *            <code>TIMESTAMP</code> value
2684      */
2685     public java.sql.Date getDate(String columnName) throws SQLException {
2686         return getDate(getColIdxByName(columnName));
2687     }
2688 
2689     /**
2690      * Retrieves the value stored in the designated column
2691      * of the current row as a <code>java.sql.Time</code> object.
2692      *
2693      * @param columnName a <code>String</code> object giving the SQL name of
2694      *        a column in this <code>CachedRowSetImpl</code> object
2695      * @return the column value; if the value is SQL <code>NULL</code>,
2696      *         the result is <code>null</code>
2697      * @throws SQLException if the given column name does not match one of
2698      *            this rowset's column names or the cursor is not on one of
2699      *            this rowset's rows or its insert row
2700      */
2701     public java.sql.Time getTime(String columnName) throws SQLException {
2702         return getTime(getColIdxByName(columnName));
2703     }
2704 
2705     /**
2706      * Retrieves the value stored in the designated column
2707      * of the current row as a <code>java.sql.Timestamp</code> object.
2708      *
2709      * @param columnName a <code>String</code> object giving the SQL name of
2710      *        a column in this <code>CachedRowSetImpl</code> object
2711      * @return the column value; if the value is SQL <code>NULL</code>,
2712      *         the result is <code>null</code>
2713      * @throws SQLException if the given column name does not match one of
2714      *            this rowset's column names or the cursor is not on one of
2715      *            this rowset's rows or its insert row
2716      */
2717     public java.sql.Timestamp getTimestamp(String columnName) throws SQLException {
2718         return getTimestamp(getColIdxByName(columnName));
2719     }
2720 
2721     /**
2722      * Retrieves the value of the designated column in the current row of this
2723      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2724      * object.
2725      *
2726      * A column value can be retrieved as a stream of ASCII characters
2727      * and then read in chunks from the stream. This method is particularly
2728      * suitable for retrieving large <code>LONGVARCHAR</code> values. The
2729      * <code>SyncProvider</code> will rely on the JDBC driver to do any necessary
2730      * conversion from the database format into ASCII format.
2731      *
2732      * <P><B>Note:</B> All the data in the returned stream must
2733      * be read prior to getting the value of any other column. The
2734      * next call to a <code>getXXX</code> method implicitly closes the stream.
2735      *
2736      * @param columnName a <code>String</code> object giving the SQL name of
2737      *        a column in this <code>CachedRowSetImpl</code> object
2738      * @return a Java input stream that delivers the database column value
2739      *         as a stream of one-byte ASCII characters.  If the value is SQL
2740      *         <code>NULL</code>, the result is <code>null</code>.
2741      * @throws SQLException if (1) the given column name is not the name of
2742      * a column in this rowset
2743      * (2) the cursor is not on one of this rowset's rows or its
2744      * insert row, or (3) the designated column does not store an
2745      * SQL <code>CHAR, VARCHAR</code>, <code><b>LONGVARCHAR</b></code>
2746      * <code>BINARY, VARBINARY</code> or <code>LONGVARBINARY</code> value. The
2747      * bold SQL type designates the recommended return types that this method is
2748      * used to retrieve.
2749      * @see #getAsciiStream(int)
2750      */
2751     public java.io.InputStream getAsciiStream(String columnName) throws SQLException {
2752         return getAsciiStream(getColIdxByName(columnName));
2753 
2754     }
2755 
2756     /**
2757      * A column value can be retrieved as a stream of Unicode characters
2758      * and then read in chunks from the stream.  This method is particularly
2759      * suitable for retrieving large <code>LONGVARCHAR</code> values.
2760      * The JDBC driver will do any necessary conversion from the database
2761      * format into Unicode.
2762      *
2763      * <P><B>Note:</B> All the data in the returned stream must
2764      * be read prior to getting the value of any other column. The
2765      * next call to a <code>getXXX</code> method implicitly closes the stream.
2766      *
2767      * @param columnName a <code>String</code> object giving the SQL name of
2768      *        a column in this <code>CachedRowSetImpl</code> object
2769      * @return a Java input stream that delivers the database column value
2770      *         as a stream of two-byte Unicode characters.  If the value is
2771      *         SQL <code>NULL</code>, the result is <code>null</code>.
2772      * @throws SQLException if the given column name does not match one of
2773      *            this rowset's column names or the cursor is not on one of
2774      *            this rowset's rows or its insert row
2775      * @deprecated use the method <code>getCharacterStream</code> instead
2776      */
2777     @Deprecated
2778     public java.io.InputStream getUnicodeStream(String columnName) throws SQLException {
2779         return getUnicodeStream(getColIdxByName(columnName));
2780     }
2781 
2782     /**
2783      * Retrieves the value of the designated column in the current row of this
2784      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2785      * object.
2786      * <P>
2787      * A column value can be retrieved as a stream of uninterpreted bytes
2788      * and then read in chunks from the stream.  This method is particularly
2789      * suitable for retrieving large <code>LONGVARBINARY</code> values.
2790      *
2791      * <P><B>Note:</B> All the data in the returned stream must be
2792      * read prior to getting the value of any other column. The next
2793      * call to a get method implicitly closes the stream. Also, a
2794      * stream may return <code>0</code> for <code>CachedRowSetImpl.available()</code>
2795      * whether there is data available or not.
2796      *
2797      * @param columnName a <code>String</code> object giving the SQL name of
2798      *        a column in this <code>CachedRowSetImpl</code> object
2799      * @return a Java input stream that delivers the database column value
2800      *         as a stream of uninterpreted bytes.  If the value is SQL
2801      *         <code>NULL</code>, the result is <code>null</code>.
2802      * @throws SQLException if (1) the given column name is unknown,
2803      * (2) the cursor is not on one of this rowset's rows or its
2804      * insert row, or (3) the designated column does not store an
2805      * SQL <code>BINARY, VARBINARY</code> or <code><b>LONGVARBINARY</b></code>
2806      * The bold type indicates the SQL type that this method is recommened
2807      * to retrieve.
2808      * @see #getBinaryStream(int)
2809      *
2810      */
2811     public java.io.InputStream getBinaryStream(String columnName) throws SQLException {
2812         return getBinaryStream(getColIdxByName(columnName));
2813     }
2814 
2815 
2816     // Advanced features:
2817 
2818     /**
2819      * The first warning reported by calls on this <code>CachedRowSetImpl</code>
2820      * object is returned. Subsequent <code>CachedRowSetImpl</code> warnings will
2821      * be chained to this <code>SQLWarning</code>.
2822      *
2823      * <P>The warning chain is automatically cleared each time a new
2824      * row is read.
2825      *
2826      * <P><B>Note:</B> This warning chain only covers warnings caused
2827      * by <code>ResultSet</code> methods.  Any warning caused by statement
2828      * methods (such as reading OUT parameters) will be chained on the
2829      * <code>Statement</code> object.
2830      *
2831      * @return the first SQLWarning or null
2832      */
2833     public SQLWarning getWarnings() {
2834         return sqlwarn;
2835     }
2836 
2837     /**
2838      * Clears all the warnings reporeted for the <code>CachedRowSetImpl</code>
2839      * object. After a call to this method, the <code>getWarnings</code> method
2840      * returns <code>null</code> until a new warning is reported for this
2841      * <code>CachedRowSetImpl</code> object.
2842      */
2843     public void clearWarnings() {
2844         sqlwarn = null;
2845     }
2846 
2847     /**
2848      * Retrieves the name of the SQL cursor used by this
2849      * <code>CachedRowSetImpl</code> object.
2850      *
2851      * <P>In SQL, a result table is retrieved through a cursor that is
2852      * named. The current row of a <code>ResultSet</code> can be updated or deleted
2853      * using a positioned update/delete statement that references the
2854      * cursor name. To ensure that the cursor has the proper isolation
2855      * level to support an update operation, the cursor's <code>SELECT</code>
2856      * statement should be of the form <code>select for update</code>.
2857      * If the <code>for update</code> clause
2858      * is omitted, positioned updates may fail.
2859      *
2860      * <P>JDBC supports this SQL feature by providing the name of the
2861      * SQL cursor used by a <code>ResultSet</code> object. The current row
2862      * of a result set is also the current row of this SQL cursor.
2863      *
2864      * <P><B>Note:</B> If positioned updates are not supported, an
2865      * <code>SQLException</code> is thrown.
2866      *
2867      * @return the SQL cursor name for this <code>CachedRowSetImpl</code> object's
2868      *         cursor
2869      * @throws SQLException if an error occurs
2870      */
2871     public String getCursorName() throws SQLException {
2872         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.posupdate").toString());
2873     }
2874 
2875     /**
2876      * Retrieves a <code>ResultSetMetaData</code> object instance that
2877      * contains information about the <code>CachedRowSet</code> object.
2878      * However, applications should cast the returned object to a
2879      * <code>RowSetMetaData</code> interface implementation. In the
2880      * reference implementation, this cast can be done on the
2881      * <code>RowSetMetaDataImpl</code> class.
2882      * <P>
2883      * For example:
2884      * <pre>
2885      * CachedRowSet crs = new CachedRowSetImpl();
2886      * RowSetMetaDataImpl metaData =
2887      *     (RowSetMetaDataImpl)crs.getMetaData();
2888      * // Set the number of columns in the RowSet object for
2889      * // which this RowSetMetaDataImpl object was created to the
2890      * // given number.
2891      * metaData.setColumnCount(3);
2892      * crs.setMetaData(metaData);
2893      * </pre>
2894      *
2895      * @return the <code>ResultSetMetaData</code> object that describes this
2896      *         <code>CachedRowSetImpl</code> object's columns
2897      * @throws SQLException if an error occurs in generating the RowSet
2898      * meta data; or if the <code>CachedRowSetImpl</code> is empty.
2899      * @see javax.sql.RowSetMetaData
2900      */
2901     public ResultSetMetaData getMetaData() throws SQLException {
2902         return (ResultSetMetaData)RowSetMD;
2903     }
2904 
2905 
2906     /**
2907      * Retrieves the value of the designated column in the current row
2908      * of this <code>CachedRowSetImpl</code> object as an
2909      * <code>Object</code> value.
2910      * <P>
2911      * The type of the <code>Object</code> will be the default
2912      * Java object type corresponding to the column's SQL type,
2913      * following the mapping for built-in types specified in the JDBC 3.0
2914      * specification.
2915      * <P>
2916      * This method may also be used to read datatabase-specific
2917      * abstract data types.
2918      * <P>
2919      * This implementation of the method <code>getObject</code> extends its
2920      * behavior so that it gets the attributes of an SQL structured type
2921      * as an array of <code>Object</code> values.  This method also custom
2922      * maps SQL user-defined types to classes in the Java programming language.
2923      * When the specified column contains
2924      * a structured or distinct value, the behavior of this method is as
2925      * if it were a call to the method <code>getObject(columnIndex,
2926      * this.getStatement().getConnection().getTypeMap())</code>.
2927      *
2928      * @param columnIndex the first column is <code>1</code>, the second
2929      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2930      *        and equal to or less than the number of columns in the rowset
2931      * @return a <code>java.lang.Object</code> holding the column value;
2932      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
2933      * @throws SQLException if the given column index is out of bounds,
2934      *            the cursor is not on a valid row, or there is a problem getting
2935      *            the <code>Class</code> object for a custom mapping
2936      * @see #getObject(String)
2937      */
2938     public Object getObject(int columnIndex) throws SQLException {
2939         Object value;
2940         Map<String, Class<?>> map;
2941 
2942         // sanity check.
2943         checkIndex(columnIndex);
2944         // make sure the cursor is on a valid row
2945         checkCursor();
2946 
2947         setLastValueNull(false);
2948         value = getCurrentRow().getColumnObject(columnIndex);
2949 
2950         // check for SQL NULL
2951         if (value == null) {
2952             setLastValueNull(true);
2953             return null;
2954         }
2955         if (value instanceof Struct) {
2956             Struct s = (Struct)value;
2957             map = getTypeMap();
2958             // look up the class in the map
2959             Class<?> c = map.get(s.getSQLTypeName());
2960             if (c != null) {
2961                 // create new instance of the class
2962                 SQLData obj = null;
2963                 try {
2964                     ReflectUtil.checkPackageAccess(c);
2965                     obj = (SQLData) c.newInstance();
2966                 } catch(Exception ex) {
2967                     throw new SQLException("Unable to Instantiate: ", ex);
2968                 }
2969                 // get the attributes from the struct
2970                 Object attribs[] = s.getAttributes(map);
2971                 // create the SQLInput "stream"
2972                 SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
2973                 // read the values...
2974                 obj.readSQL(sqlInput, s.getSQLTypeName());
2975                 return (Object)obj;
2976             }
2977         }
2978         return value;
2979     }
2980 
2981     /**
2982      * Retrieves the value of the designated column in the current row
2983      * of this <code>CachedRowSetImpl</code> object as an
2984      * <code>Object</code> value.
2985      * <P>
2986      * The type of the <code>Object</code> will be the default
2987      * Java object type corresponding to the column's SQL type,
2988      * following the mapping for built-in types specified in the JDBC 3.0
2989      * specification.
2990      * <P>
2991      * This method may also be used to read datatabase-specific
2992      * abstract data types.
2993      * <P>
2994      * This implementation of the method <code>getObject</code> extends its
2995      * behavior so that it gets the attributes of an SQL structured type
2996      * as an array of <code>Object</code> values.  This method also custom
2997      * maps SQL user-defined types to classes
2998      * in the Java programming language. When the specified column contains
2999      * a structured or distinct value, the behavior of this method is as
3000      * if it were a call to the method <code>getObject(columnIndex,
3001      * this.getStatement().getConnection().getTypeMap())</code>.
3002      *
3003      * @param columnName a <code>String</code> object that must match the
3004      *        SQL name of a column in this rowset, ignoring case
3005      * @return a <code>java.lang.Object</code> holding the column value;
3006      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3007      * @throws SQLException if (1) the given column name does not match one of
3008      *            this rowset's column names, (2) the cursor is not
3009      *            on a valid row, or (3) there is a problem getting
3010      *            the <code>Class</code> object for a custom mapping
3011      * @see #getObject(int)
3012      */
3013     public Object getObject(String columnName) throws SQLException {
3014         return getObject(getColIdxByName(columnName));
3015     }
3016 
3017     //----------------------------------------------------------------
3018 
3019     /**
3020      * Maps the given column name for one of this <code>CachedRowSetImpl</code>
3021      * object's columns to its column number.
3022      *
3023      * @param columnName a <code>String</code> object that must match the
3024      *        SQL name of a column in this rowset, ignoring case
3025      * @return the column index of the given column name
3026      * @throws SQLException if the given column name does not match one
3027      *            of this rowset's column names
3028      */
3029     public int findColumn(String columnName) throws SQLException {
3030         return getColIdxByName(columnName);
3031     }
3032 
3033 
3034     //--------------------------JDBC 2.0-----------------------------------
3035 
3036     //---------------------------------------------------------------------
3037     // Getter's and Setter's
3038     //---------------------------------------------------------------------
3039 
3040     /**
3041      * Retrieves the value stored in the designated column
3042      * of the current row as a <code>java.io.Reader</code> object.
3043      *
3044      * <P><B>Note:</B> All the data in the returned stream must
3045      * be read prior to getting the value of any other column. The
3046      * next call to a <code>getXXX</code> method implicitly closes the stream.
3047      *
3048      * @param columnIndex the first column is <code>1</code>, the second
3049      *        is <code>2</code>, and so on; must be <code>1</code> or larger
3050      *        and equal to or less than the number of columns in the rowset
3051      * @return a Java character stream that delivers the database column value
3052      * as a stream of two-byte unicode characters in a
3053      * <code>java.io.Reader</code> object.  If the value is
3054      * SQL <code>NULL</code>, the result is <code>null</code>.
3055      * @throws SQLException if (1) the given column index is out of bounds,
3056      * (2) the cursor is not on one of this rowset's rows or its
3057      * insert row, or (3) the designated column does not store an
3058      * SQL <code>CHAR, VARCHAR, <b>LONGVARCHAR</b>, BINARY, VARBINARY</code> or
3059      * <code>LONGVARBINARY</code> value.
3060      * The bold SQL type designates the recommended return type.
3061      * @see #getCharacterStream(String)
3062      */
3063     public java.io.Reader getCharacterStream(int columnIndex) throws SQLException{
3064 
3065         // sanity check.
3066         checkIndex(columnIndex);
3067         // make sure the cursor is on a valid row
3068         checkCursor();
3069 
3070         if (isBinary(RowSetMD.getColumnType(columnIndex))) {
3071             Object value = getCurrentRow().getColumnObject(columnIndex);
3072             if (value == null) {
3073                 lastValueNull = true;
3074                 return null;
3075             }
3076             charStream = new InputStreamReader
3077             (new ByteArrayInputStream((byte[])value));
3078         } else if (isString(RowSetMD.getColumnType(columnIndex))) {
3079             Object value = getCurrentRow().getColumnObject(columnIndex);
3080             if (value == null) {
3081                 lastValueNull = true;
3082                 return null;
3083             }
3084             charStream = new StringReader(value.toString());
3085         } else {
3086             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
3087         }
3088 
3089         return charStream;
3090     }
3091 
3092     /**
3093      * Retrieves the value stored in the designated column
3094      * of the current row as a <code>java.io.Reader</code> object.
3095      *
3096      * <P><B>Note:</B> All the data in the returned stream must
3097      * be read prior to getting the value of any other column. The
3098      * next call to a <code>getXXX</code> method implicitly closes the stream.
3099      *
3100      * @param columnName a <code>String</code> object giving the SQL name of
3101      *        a column in this <code>CachedRowSetImpl</code> object
3102      * @return a Java input stream that delivers the database column value
3103      *         as a stream of two-byte Unicode characters.  If the value is
3104      *         SQL <code>NULL</code>, the result is <code>null</code>.
3105      * @throws SQLException if (1) the given column name is not the name of
3106      * a column in this rowset, (2) the cursor is not on one of
3107      * this rowset's rows or its insert row, or (3) the designated
3108      * column does not store an SQL <code>CHAR, VARCHAR, <b>LONGVARCHAR</b>,
3109      * BINARY, VARYBINARY</code> or <code>LONGVARBINARY</code> value.
3110      * The bold SQL type designates the recommended return type.
3111      */
3112     public java.io.Reader getCharacterStream(String columnName) throws SQLException {
3113         return getCharacterStream(getColIdxByName(columnName));
3114     }
3115 
3116     /**
3117      * Retrieves the value of the designated column in the current row
3118      * of this <code>CachedRowSetImpl</code> object as a
3119      * <code>java.math.BigDecimal</code> object.
3120      *
3121      * @param columnIndex the first column is <code>1</code>, the second
3122      *        is <code>2</code>, and so on; must be <code>1</code> or larger
3123      *        and equal to or less than the number of columns in the rowset
3124      * @return a <code>java.math.BigDecimal</code> value with full precision;
3125      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3126      * @throws SQLException if (1) the given column index is out of bounds,
3127      * (2) the cursor is not on one of this rowset's rows or its
3128      * insert row, or (3) the designated column does not store an
3129      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
3130      * FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT, CHAR, VARCHAR</code>
3131      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
3132      * recommended return types that this method is used to retrieve.
3133      * @see #getBigDecimal(String)
3134      */
3135     public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
3136         Object value;
3137 
3138         // sanity check.
3139         checkIndex(columnIndex);
3140         // make sure the cursor is on a valid row
3141         checkCursor();
3142 
3143         setLastValueNull(false);
3144         value = getCurrentRow().getColumnObject(columnIndex);
3145 
3146         // check for SQL NULL
3147         if (value == null) {
3148             setLastValueNull(true);
3149             return null;
3150         }
3151         try {
3152             return (new BigDecimal(value.toString().trim()));
3153         } catch (NumberFormatException ex) {
3154             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.doublefail").toString(),
3155                 new Object[] {value.toString().trim(), columnIndex}));
3156         }
3157     }
3158 
3159     /**
3160      * Retrieves the value of the designated column in the current row
3161      * of this <code>CachedRowSetImpl</code> object as a
3162      * <code>java.math.BigDecimal</code> object.
3163      *
3164      * @param columnName a <code>String</code> object that must match the
3165      *        SQL name of a column in this rowset, ignoring case
3166      * @return a <code>java.math.BigDecimal</code> value with full precision;
3167      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3168      * @throws SQLException if (1) the given column name is not the name of
3169      * a column in this rowset, (2) the cursor is not on one of
3170      * this rowset's rows or its insert row, or (3) the designated
3171      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
3172      * BIGINT, REAL, FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT CHAR,
3173      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
3174      * designates the recommended return type that this method is used to
3175      * retrieve
3176      * @see #getBigDecimal(int)
3177      */
3178     public BigDecimal getBigDecimal(String columnName) throws SQLException {
3179         return getBigDecimal(getColIdxByName(columnName));
3180     }
3181 
3182     //---------------------------------------------------------------------
3183     // Traversal/Positioning
3184     //---------------------------------------------------------------------
3185 
3186     /**
3187      * Returns the number of rows in this <code>CachedRowSetImpl</code> object.
3188      *
3189      * @return number of rows in the rowset
3190      */
3191     public int size() {
3192         return numRows;
3193     }
3194 
3195     /**
3196      * Indicates whether the cursor is before the first row in this
3197      * <code>CachedRowSetImpl</code> object.
3198      *
3199      * @return <code>true</code> if the cursor is before the first row;
3200      *         <code>false</code> otherwise or if the rowset contains no rows
3201      * @throws SQLException if an error occurs
3202      */
3203     public boolean isBeforeFirst() throws SQLException {
3204         if (cursorPos == 0 && numRows > 0) {
3205             return true;
3206         } else {
3207             return false;
3208         }
3209     }
3210 
3211     /**
3212      * Indicates whether the cursor is after the last row in this
3213      * <code>CachedRowSetImpl</code> object.
3214      *
3215      * @return <code>true</code> if the cursor is after the last row;
3216      *         <code>false</code> otherwise or if the rowset contains no rows
3217      * @throws SQLException if an error occurs
3218      */
3219     public boolean isAfterLast() throws SQLException {
3220         if (cursorPos == numRows+1 && numRows > 0) {
3221             return true;
3222         } else {
3223             return false;
3224         }
3225     }
3226 
3227     /**
3228      * Indicates whether the cursor is on the first row in this
3229      * <code>CachedRowSetImpl</code> object.
3230      *
3231      * @return <code>true</code> if the cursor is on the first row;
3232      *         <code>false</code> otherwise or if the rowset contains no rows
3233      * @throws SQLException if an error occurs
3234      */
3235     public boolean isFirst() throws SQLException {
3236         // this becomes nasty because of deletes.
3237         int saveCursorPos = cursorPos;
3238         int saveAbsoluteCursorPos = absolutePos;
3239         internalFirst();
3240         if (cursorPos == saveCursorPos) {
3241             return true;
3242         } else {
3243             cursorPos = saveCursorPos;
3244             absolutePos = saveAbsoluteCursorPos;
3245             return false;
3246         }
3247     }
3248 
3249     /**
3250      * Indicates whether the cursor is on the last row in this
3251      * <code>CachedRowSetImpl</code> object.
3252      * <P>
3253      * Note: Calling the method <code>isLast</code> may be expensive
3254      * because the JDBC driver might need to fetch ahead one row in order
3255      * to determine whether the current row is the last row in this rowset.
3256      *
3257      * @return <code>true</code> if the cursor is on the last row;
3258      *         <code>false</code> otherwise or if this rowset contains no rows
3259      * @throws SQLException if an error occurs
3260      */
3261     public boolean isLast() throws SQLException {
3262         int saveCursorPos = cursorPos;
3263         int saveAbsoluteCursorPos = absolutePos;
3264         boolean saveShowDeleted = getShowDeleted();
3265         setShowDeleted(true);
3266         internalLast();
3267         if (cursorPos == saveCursorPos) {
3268             setShowDeleted(saveShowDeleted);
3269             return true;
3270         } else {
3271             setShowDeleted(saveShowDeleted);
3272             cursorPos = saveCursorPos;
3273             absolutePos = saveAbsoluteCursorPos;
3274             return false;
3275         }
3276     }
3277 
3278     /**
3279      * Moves this <code>CachedRowSetImpl</code> object's cursor to the front of
3280      * the rowset, just before the first row. This method has no effect if
3281      * this rowset contains no rows.
3282      *
3283      * @throws SQLException if an error occurs or the type of this rowset
3284      *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3285      */
3286     public void beforeFirst() throws SQLException {
3287        if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3288             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.beforefirst").toString());
3289         }
3290         cursorPos = 0;
3291         absolutePos = 0;
3292         notifyCursorMoved();
3293     }
3294 
3295     /**
3296      * Moves this <code>CachedRowSetImpl</code> object's cursor to the end of
3297      * the rowset, just after the last row. This method has no effect if
3298      * this rowset contains no rows.
3299      *
3300      * @throws SQLException if an error occurs
3301      */
3302     public void afterLast() throws SQLException {
3303         if (numRows > 0) {
3304             cursorPos = numRows + 1;
3305             absolutePos = 0;
3306             notifyCursorMoved();
3307         }
3308     }
3309 
3310     /**
3311      * Moves this <code>CachedRowSetImpl</code> object's cursor to the first row
3312      * and returns <code>true</code> if the operation was successful.  This
3313      * method also notifies registered listeners that the cursor has moved.
3314      *
3315      * @return <code>true</code> if the cursor is on a valid row;
3316      *         <code>false</code> otherwise or if there are no rows in this
3317      *         <code>CachedRowSetImpl</code> object
3318      * @throws SQLException if the type of this rowset
3319      *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3320      */
3321     public boolean first() throws SQLException {
3322         if(getType() == ResultSet.TYPE_FORWARD_ONLY) {
3323             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.first").toString());
3324         }
3325 
3326         // move and notify
3327         boolean ret = this.internalFirst();
3328         notifyCursorMoved();
3329 
3330         return ret;
3331     }
3332 
3333     /**
3334      * Moves this <code>CachedRowSetImpl</code> object's cursor to the first
3335      * row and returns <code>true</code> if the operation is successful.
3336      * <P>
3337      * This method is called internally by the methods <code>first</code>,
3338      * <code>isFirst</code>, and <code>absolute</code>.
3339      * It in turn calls the method <code>internalNext</code> in order to
3340      * handle the case where the first row is a deleted row that is not visible.
3341      * <p>
3342      * This is a implementation only method and is not required as a standard
3343      * implementation of the <code>CachedRowSet</code> interface.
3344      *
3345      * @return <code>true</code> if the cursor moved to the first row;
3346      *         <code>false</code> otherwise
3347      * @throws SQLException if an error occurs
3348      */
3349     protected boolean internalFirst() throws SQLException {
3350         boolean ret = false;
3351 
3352         if (numRows > 0) {
3353             cursorPos = 1;
3354             if ((getShowDeleted() == false) && (rowDeleted() == true)) {
3355                 ret = internalNext();
3356             } else {
3357                 ret = true;
3358             }
3359         }
3360 
3361         if (ret == true)
3362             absolutePos = 1;
3363         else
3364             absolutePos = 0;
3365 
3366         return ret;
3367     }
3368 
3369     /**
3370      * Moves this <code>CachedRowSetImpl</code> object's cursor to the last row
3371      * and returns <code>true</code> if the operation was successful.  This
3372      * method also notifies registered listeners that the cursor has moved.
3373      *
3374      * @return <code>true</code> if the cursor is on a valid row;
3375      *         <code>false</code> otherwise or if there are no rows in this
3376      *         <code>CachedRowSetImpl</code> object
3377      * @throws SQLException if the type of this rowset
3378      *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3379      */
3380     public boolean last() throws SQLException {
3381         if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3382             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.last").toString());
3383         }
3384 
3385         // move and notify
3386         boolean ret = this.internalLast();
3387         notifyCursorMoved();
3388 
3389         return ret;
3390     }
3391 
3392     /**
3393      * Moves this <code>CachedRowSetImpl</code> object's cursor to the last
3394      * row and returns <code>true</code> if the operation is successful.
3395      * <P>
3396      * This method is called internally by the method <code>last</code>
3397      * when rows have been deleted and the deletions are not visible.
3398      * The method <code>internalLast</code> handles the case where the
3399      * last row is a deleted row that is not visible by in turn calling
3400      * the method <code>internalPrevious</code>.
3401      * <p>
3402      * This is a implementation only method and is not required as a standard
3403      * implementation of the <code>CachedRowSet</code> interface.
3404      *
3405      * @return <code>true</code> if the cursor moved to the last row;
3406      *         <code>false</code> otherwise
3407      * @throws SQLException if an error occurs
3408      */
3409     protected boolean internalLast() throws SQLException {
3410         boolean ret = false;
3411 
3412         if (numRows > 0) {
3413             cursorPos = numRows;
3414             if ((getShowDeleted() == false) && (rowDeleted() == true)) {
3415                 ret = internalPrevious();
3416             } else {
3417                 ret = true;
3418             }
3419         }
3420         if (ret == true)
3421             absolutePos = numRows - numDeleted;
3422         else
3423             absolutePos = 0;
3424         return ret;
3425     }
3426 
3427     /**
3428      * Returns the number of the current row in this <code>CachedRowSetImpl</code>
3429      * object. The first row is number 1, the second number 2, and so on.
3430      *
3431      * @return the number of the current row;  <code>0</code> if there is no
3432      *         current row
3433      * @throws SQLException if an error occurs; or if the <code>CacheRowSetImpl</code>
3434      *         is empty
3435      */
3436     public int getRow() throws SQLException {
3437         // are we on a valid row? Valid rows are between first and last
3438         if (numRows > 0 &&
3439         cursorPos > 0 &&
3440         cursorPos < (numRows + 1) &&
3441         (getShowDeleted() == false && rowDeleted() == false)) {
3442             return absolutePos;
3443         } else if (getShowDeleted() == true) {
3444             return cursorPos;
3445         } else {
3446             return 0;
3447         }
3448     }
3449 
3450     /**
3451      * Moves this <code>CachedRowSetImpl</code> object's cursor to the row number
3452      * specified.
3453      *
3454      * <p>If the number is positive, the cursor moves to an absolute row with
3455      * respect to the beginning of the rowset.  The first row is row 1, the second
3456      * is row 2, and so on.  For example, the following command, in which
3457      * <code>crs</code> is a <code>CachedRowSetImpl</code> object, moves the cursor
3458      * to the fourth row, starting from the beginning of the rowset.
3459      * <PRE><code>
3460      *
3461      *    crs.absolute(4);
3462      *
3463      * </code> </PRE>
3464      * <P>
3465      * If the number is negative, the cursor moves to an absolute row position
3466      * with respect to the end of the rowset.  For example, calling
3467      * <code>absolute(-1)</code> positions the cursor on the last row,
3468      * <code>absolute(-2)</code> moves it on the next-to-last row, and so on.
3469      * If the <code>CachedRowSetImpl</code> object <code>crs</code> has five rows,
3470      * the following command moves the cursor to the fourth-to-last row, which
3471      * in the case of a  rowset with five rows, is also the second row, counting
3472      * from the beginning.
3473      * <PRE><code>
3474      *
3475      *    crs.absolute(-4);
3476      *
3477      * </code> </PRE>
3478      *
3479      * If the number specified is larger than the number of rows, the cursor
3480      * will move to the position after the last row. If the number specified
3481      * would move the cursor one or more rows before the first row, the cursor
3482      * moves to the position before the first row.
3483      * <P>
3484      * Note: Calling <code>absolute(1)</code> is the same as calling the
3485      * method <code>first()</code>.  Calling <code>absolute(-1)</code> is the
3486      * same as calling <code>last()</code>.
3487      *
3488      * @param row a positive number to indicate the row, starting row numbering from
3489      *        the first row, which is <code>1</code>; a negative number to indicate
3490      *        the row, starting row numbering from the last row, which is
3491      *        <code>-1</code>; it must not be <code>0</code>
3492      * @return <code>true</code> if the cursor is on the rowset; <code>false</code>
3493      *         otherwise
3494      * @throws SQLException if the given cursor position is <code>0</code> or the
3495      *            type of this rowset is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3496      */
3497     public boolean absolute( int row ) throws SQLException {
3498         if (row == 0 || getType() == ResultSet.TYPE_FORWARD_ONLY) {
3499             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.absolute").toString());
3500         }
3501 
3502         if (row > 0) { // we are moving foward
3503             if (row > numRows) {
3504                 // fell off the end
3505                 afterLast();
3506                 return false;
3507             } else {
3508                 if (absolutePos <= 0)
3509                     internalFirst();
3510             }
3511         } else { // we are moving backward
3512             if (cursorPos + row < 0) {
3513                 // fell off the front
3514                 beforeFirst();
3515                 return false;
3516             } else {
3517                 if (absolutePos >= 0)
3518                     internalLast();
3519             }
3520         }
3521 
3522         // Now move towards the absolute row that we're looking for
3523         while (absolutePos != row) {
3524             if (absolutePos < row) {
3525                 if (!internalNext())
3526                     break;
3527             }
3528             else {
3529                 if (!internalPrevious())
3530                     break;
3531             }
3532         }
3533 
3534         notifyCursorMoved();
3535 
3536         if (isAfterLast() || isBeforeFirst()) {
3537             return false;
3538         } else {
3539             return true;
3540         }
3541     }
3542 
3543     /**
3544      * Moves the cursor the specified number of rows from the current
3545      * position, with a positive number moving it forward and a
3546      * negative number moving it backward.
3547      * <P>
3548      * If the number is positive, the cursor moves the specified number of
3549      * rows toward the end of the rowset, starting at the current row.
3550      * For example, the following command, in which
3551      * <code>crs</code> is a <code>CachedRowSetImpl</code> object with 100 rows,
3552      * moves the cursor forward four rows from the current row.  If the
3553      * current row is 50, the cursor would move to row 54.
3554      * <PRE><code>
3555      *
3556      *    crs.relative(4);
3557      *
3558      * </code> </PRE>
3559      * <P>
3560      * If the number is negative, the cursor moves back toward the beginning
3561      * the specified number of rows, starting at the current row.
3562      * For example, calling the method
3563      * <code>absolute(-1)</code> positions the cursor on the last row,
3564      * <code>absolute(-2)</code> moves it on the next-to-last row, and so on.
3565      * If the <code>CachedRowSetImpl</code> object <code>crs</code> has five rows,
3566      * the following command moves the cursor to the fourth-to-last row, which
3567      * in the case of a  rowset with five rows, is also the second row
3568      * from the beginning.
3569      * <PRE><code>
3570      *
3571      *    crs.absolute(-4);
3572      *
3573      * </code> </PRE>
3574      *
3575      * If the number specified is larger than the number of rows, the cursor
3576      * will move to the position after the last row. If the number specified
3577      * would move the cursor one or more rows before the first row, the cursor
3578      * moves to the position before the first row. In both cases, this method
3579      * throws an <code>SQLException</code>.
3580      * <P>
3581      * Note: Calling <code>absolute(1)</code> is the same as calling the
3582      * method <code>first()</code>.  Calling <code>absolute(-1)</code> is the
3583      * same as calling <code>last()</code>.  Calling <code>relative(0)</code>
3584      * is valid, but it does not change the cursor position.
3585      *
3586      * @param rows an <code>int</code> indicating the number of rows to move
3587      *             the cursor, starting at the current row; a positive number
3588      *             moves the cursor forward; a negative number moves the cursor
3589      *             backward; must not move the cursor past the valid
3590      *             rows
3591      * @return <code>true</code> if the cursor is on a row in this
3592      *         <code>CachedRowSetImpl</code> object; <code>false</code>
3593      *         otherwise
3594      * @throws SQLException if there are no rows in this rowset, the cursor is
3595      *         positioned either before the first row or after the last row, or
3596      *         the rowset is type <code>ResultSet.TYPE_FORWARD_ONLY</code>
3597      */
3598     public boolean relative(int rows) throws SQLException {
3599         if (numRows == 0 || isBeforeFirst() ||
3600         isAfterLast() || getType() == ResultSet.TYPE_FORWARD_ONLY) {
3601             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.relative").toString());
3602         }
3603 
3604         if (rows == 0) {
3605             return true;
3606         }
3607 
3608         if (rows > 0) { // we are moving forward
3609             if (cursorPos + rows > numRows) {
3610                 // fell off the end
3611                 afterLast();
3612             } else {
3613                 for (int i=0; i < rows; i++) {
3614                     if (!internalNext())
3615                         break;
3616                 }
3617             }
3618         } else { // we are moving backward
3619             if (cursorPos + rows < 0) {
3620                 // fell off the front
3621                 beforeFirst();
3622             } else {
3623                 for (int i=rows; i < 0; i++) {
3624                     if (!internalPrevious())
3625                         break;
3626                 }
3627             }
3628         }
3629         notifyCursorMoved();
3630 
3631         if (isAfterLast() || isBeforeFirst()) {
3632             return false;
3633         } else {
3634             return true;
3635         }
3636     }
3637 
3638     /**
3639      * Moves this <code>CachedRowSetImpl</code> object's cursor to the
3640      * previous row and returns <code>true</code> if the cursor is on
3641      * a valid row or <code>false</code> if it is not.
3642      * This method also notifies all listeners registered with this
3643      * <code>CachedRowSetImpl</code> object that its cursor has moved.
3644      * <P>
3645      * Note: calling the method <code>previous()</code> is not the same
3646      * as calling the method <code>relative(-1)</code>.  This is true
3647      * because it is possible to call <code>previous()</code> from the insert
3648      * row, from after the last row, or from the current row, whereas
3649      * <code>relative</code> may only be called from the current row.
3650      * <P>
3651      * The method <code>previous</code> may used in a <code>while</code>
3652      * loop to iterate through a rowset starting after the last row
3653      * and moving toward the beginning. The loop ends when <code>previous</code>
3654      * returns <code>false</code>, meaning that there are no more rows.
3655      * For example, the following code fragment retrieves all the data in
3656      * the <code>CachedRowSetImpl</code> object <code>crs</code>, which has
3657      * three columns.  Note that the cursor must initially be positioned
3658      * after the last row so that the first call to the method
3659      * <code>previous</code> places the cursor on the last line.
3660      * <PRE> <code>
3661      *
3662      *     crs.afterLast();
3663      *     while (previous()) {
3664      *         String name = crs.getString(1);
3665      *         int age = crs.getInt(2);
3666      *         short ssn = crs.getShort(3);
3667      *         System.out.println(name + "   " + age + "   " + ssn);
3668      *     }
3669      *
3670      * </code> </PRE>
3671      * This method throws an <code>SQLException</code> if the cursor is not
3672      * on a row in the rowset, before the first row, or after the last row.
3673      *
3674      * @return <code>true</code> if the cursor is on a valid row;
3675      *         <code>false</code> if it is before the first row or after the
3676      *         last row
3677      * @throws SQLException if the cursor is not on a valid position or the
3678      *           type of this rowset is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3679      */
3680     public boolean previous() throws SQLException {
3681         if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3682             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.last").toString());
3683         }
3684         /*
3685          * make sure things look sane. The cursor must be
3686          * positioned in the rowset or before first (0) or
3687          * after last (numRows + 1)
3688          */
3689         if (cursorPos < 0 || cursorPos > numRows + 1) {
3690             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
3691         }
3692         // move and notify
3693         boolean ret = this.internalPrevious();
3694         notifyCursorMoved();
3695 
3696         return ret;
3697     }
3698 
3699     /**
3700      * Moves the cursor to the previous row in this <code>CachedRowSetImpl</code>
3701      * object, skipping past deleted rows that are not visible; returns
3702      * <code>true</code> if the cursor is on a row in this rowset and
3703      * <code>false</code> when the cursor goes before the first row.
3704      * <P>
3705      * This method is called internally by the method <code>previous</code>.
3706      * <P>
3707      * This is a implementation only method and is not required as a standard
3708      * implementation of the <code>CachedRowSet</code> interface.
3709      *
3710      * @return <code>true</code> if the cursor is on a row in this rowset;
3711      *         <code>false</code> when the cursor reaches the position before
3712      *         the first row
3713      * @throws SQLException if an error occurs
3714      */
3715     protected boolean internalPrevious() throws SQLException {
3716         boolean ret = false;
3717 
3718         do {
3719             if (cursorPos > 1) {
3720                 --cursorPos;
3721                 ret = true;
3722             } else if (cursorPos == 1) {
3723                 // decrement to before first
3724                 --cursorPos;
3725                 ret = false;
3726                 break;
3727             }
3728         } while ((getShowDeleted() == false) && (rowDeleted() == true));
3729 
3730         /*
3731          * Each call to internalPrevious may move the cursor
3732          * over multiple rows, the absolute position moves one row
3733          */
3734         if (ret == true)
3735             --absolutePos;
3736         else
3737             absolutePos = 0;
3738 
3739         return ret;
3740     }
3741 
3742 
3743     //---------------------------------------------------------------------
3744     // Updates
3745     //---------------------------------------------------------------------
3746 
3747     /**
3748      * Indicates whether the current row of this <code>CachedRowSetImpl</code>
3749      * object has been updated.  The value returned
3750      * depends on whether this rowset can detect updates: <code>false</code>
3751      * will always be returned if it does not detect updates.
3752      *
3753      * @return <code>true</code> if the row has been visibly updated
3754      *         by the owner or another and updates are detected;
3755      *         <code>false</code> otherwise
3756      * @throws SQLException if the cursor is on the insert row or not
3757      *            not on a valid row
3758      *
3759      * @see DatabaseMetaData#updatesAreDetected
3760      */
3761     public boolean rowUpdated() throws SQLException {
3762         // make sure the cursor is on a valid row
3763         checkCursor();
3764         if (onInsertRow == true) {
3765             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3766         }
3767         return(((Row)getCurrentRow()).getUpdated());
3768     }
3769 
3770     /**
3771      * Indicates whether the designated column of the current row of
3772      * this <code>CachedRowSetImpl</code> object has been updated. The
3773      * value returned depends on whether this rowset can detcted updates:
3774      * <code>false</code> will always be returned if it does not detect updates.
3775      *
3776      * @param idx the index identifier of the column that may be have been updated.
3777      * @return <code>true</code> is the designated column has been updated
3778      * and the rowset detects updates; <code>false</code> if the rowset has not
3779      * been updated or the rowset does not detect updates
3780      * @throws SQLException if the cursor is on the insert row or not
3781      *          on a valid row
3782      * @see DatabaseMetaData#updatesAreDetected
3783      */
3784     public boolean columnUpdated(int idx) throws SQLException {
3785         // make sure the cursor is on a valid row
3786         checkCursor();
3787         if (onInsertRow == true) {
3788             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3789         }
3790         return (((Row)getCurrentRow()).getColUpdated(idx - 1));
3791     }
3792 
3793     /**
3794      * Indicates whether the designated column of the current row of
3795      * this <code>CachedRowSetImpl</code> object has been updated. The
3796      * value returned depends on whether this rowset can detcted updates:
3797      * <code>false</code> will always be returned if it does not detect updates.
3798      *
3799      * @param columnName the <code>String</code> column name column that may be have
3800      * been updated.
3801      * @return <code>true</code> is the designated column has been updated
3802      * and the rowset detects updates; <code>false</code> if the rowset has not
3803      * been updated or the rowset does not detect updates
3804      * @throws SQLException if the cursor is on the insert row or not
3805      *          on a valid row
3806      * @see DatabaseMetaData#updatesAreDetected
3807      */
3808     public boolean columnUpdated(String columnName) throws SQLException {
3809         return columnUpdated(getColIdxByName(columnName));
3810     }
3811 
3812     /**
3813      * Indicates whether the current row has been inserted.  The value returned
3814      * depends on whether or not the rowset can detect visible inserts.
3815      *
3816      * @return <code>true</code> if a row has been inserted and inserts are detected;
3817      *         <code>false</code> otherwise
3818      * @throws SQLException if the cursor is on the insert row or not
3819      *            not on a valid row
3820      *
3821      * @see DatabaseMetaData#insertsAreDetected
3822      */
3823     public boolean rowInserted() throws SQLException {
3824         // make sure the cursor is on a valid row
3825         checkCursor();
3826         if (onInsertRow == true) {
3827             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3828         }
3829         return(((Row)getCurrentRow()).getInserted());
3830     }
3831 
3832     /**
3833      * Indicates whether the current row has been deleted.  A deleted row
3834      * may leave a visible "hole" in a rowset.  This method can be used to
3835      * detect such holes if the rowset can detect deletions. This method
3836      * will always return <code>false</code> if this rowset cannot detect
3837      * deletions.
3838      *
3839      * @return <code>true</code> if (1)the current row is blank, indicating that
3840      *         the row has been deleted, and (2)deletions are detected;
3841      *         <code>false</code> otherwise
3842      * @throws SQLException if the cursor is on a valid row in this rowset
3843      * @see DatabaseMetaData#deletesAreDetected
3844      */
3845     public boolean rowDeleted() throws SQLException {
3846         // make sure the cursor is on a valid row
3847 
3848         if (isAfterLast() == true ||
3849         isBeforeFirst() == true ||
3850         onInsertRow == true) {
3851 
3852             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
3853         }
3854         return(((Row)getCurrentRow()).getDeleted());
3855     }
3856 
3857     /**
3858      * Indicates whether the given SQL data type is a numberic type.
3859      *
3860      * @param type one of the constants from <code>java.sql.Types</code>
3861      * @return <code>true</code> if the given type is <code>NUMERIC</code>,'
3862      *         <code>DECIMAL</code>, <code>BIT</code>, <code>TINYINT</code>,
3863      *         <code>SMALLINT</code>, <code>INTEGER</code>, <code>BIGINT</code>,
3864      *         <code>REAL</code>, <code>DOUBLE</code>, or <code>FLOAT</code>;
3865      *         <code>false</code> otherwise
3866      */
3867     private boolean isNumeric(int type) {
3868         switch (type) {
3869             case java.sql.Types.NUMERIC:
3870             case java.sql.Types.DECIMAL:
3871             case java.sql.Types.BIT:
3872             case java.sql.Types.TINYINT:
3873             case java.sql.Types.SMALLINT:
3874             case java.sql.Types.INTEGER:
3875             case java.sql.Types.BIGINT:
3876             case java.sql.Types.REAL:
3877             case java.sql.Types.DOUBLE:
3878             case java.sql.Types.FLOAT:
3879                 return true;
3880             default:
3881                 return false;
3882         }
3883     }
3884 
3885     /**
3886      * Indicates whether the given SQL data type is a string type.
3887      *
3888      * @param type one of the constants from <code>java.sql.Types</code>
3889      * @return <code>true</code> if the given type is <code>CHAR</code>,'
3890      *         <code>VARCHAR</code>, or <code>LONGVARCHAR</code>;
3891      *         <code>false</code> otherwise
3892      */
3893     private boolean isString(int type) {
3894         switch (type) {
3895             case java.sql.Types.CHAR:
3896             case java.sql.Types.VARCHAR:
3897             case java.sql.Types.LONGVARCHAR:
3898                 return true;
3899             default:
3900                 return false;
3901         }
3902     }
3903 
3904     /**
3905      * Indicates whether the given SQL data type is a binary type.
3906      *
3907      * @param type one of the constants from <code>java.sql.Types</code>
3908      * @return <code>true</code> if the given type is <code>BINARY</code>,'
3909      *         <code>VARBINARY</code>, or <code>LONGVARBINARY</code>;
3910      *         <code>false</code> otherwise
3911      */
3912     private boolean isBinary(int type) {
3913         switch (type) {
3914             case java.sql.Types.BINARY:
3915             case java.sql.Types.VARBINARY:
3916             case java.sql.Types.LONGVARBINARY:
3917                 return true;
3918             default:
3919                 return false;
3920         }
3921     }
3922 
3923     /**
3924      * Indicates whether the given SQL data type is a temporal type.
3925      * This method is called internally by the conversion methods
3926      * <code>convertNumeric</code> and <code>convertTemporal</code>.
3927      *
3928      * @param type one of the constants from <code>java.sql.Types</code>
3929      * @return <code>true</code> if the given type is <code>DATE</code>,
3930      *         <code>TIME</code>, or <code>TIMESTAMP</code>;
3931      *         <code>false</code> otherwise
3932      */
3933     private boolean isTemporal(int type) {
3934         switch (type) {
3935             case java.sql.Types.DATE:
3936             case java.sql.Types.TIME:
3937             case java.sql.Types.TIMESTAMP:
3938                 return true;
3939             default:
3940                 return false;
3941         }
3942     }
3943 
3944     /**
3945      * Indicates whether the given SQL data type is a boolean type.
3946      * This method is called internally by the conversion methods
3947      * <code>convertNumeric</code> and <code>convertBoolean</code>.
3948      *
3949      * @param type one of the constants from <code>java.sql.Types</code>
3950      * @return <code>true</code> if the given type is <code>BIT</code>,
3951      *         , or <code>BOOLEAN</code>;
3952      *         <code>false</code> otherwise
3953      */
3954     private boolean isBoolean(int type) {
3955         switch (type) {
3956             case java.sql.Types.BIT:
3957             case java.sql.Types.BOOLEAN:
3958                 return true;
3959             default:
3960                 return false;
3961         }
3962     }
3963 
3964 
3965     /**
3966      * Converts the given <code>Object</code> in the Java programming language
3967      * to the standard mapping for the specified SQL target data type.
3968      * The conversion must be to a string or numeric type, but there are no
3969      * restrictions on the type to be converted.  If the source type and target
3970      * type are the same, the given object is simply returned.
3971      *
3972      * @param srcObj the <code>Object</code> in the Java programming language
3973      *               that is to be converted to the target type
3974      * @param srcType the data type that is the standard mapping in SQL of the
3975      *                object to be converted; must be one of the constants in
3976      *                <code>java.sql.Types</code>
3977      * @param trgType the SQL data type to which to convert the given object;
3978      *                must be one of the following constants in
3979      *                <code>java.sql.Types</code>: <code>NUMERIC</code>,
3980      *         <code>DECIMAL</code>, <code>BIT</code>, <code>TINYINT</code>,
3981      *         <code>SMALLINT</code>, <code>INTEGER</code>, <code>BIGINT</code>,
3982      *         <code>REAL</code>, <code>DOUBLE</code>, <code>FLOAT</code>,
3983      *         <code>VARCHAR</code>, <code>LONGVARCHAR</code>, or <code>CHAR</code>
3984      * @return an <code>Object</code> value.that is
3985      *         the standard object mapping for the target SQL type
3986      * @throws SQLException if the given target type is not one of the string or
3987      *         numeric types in <code>java.sql.Types</code>
3988      */
3989     private Object convertNumeric(Object srcObj, int srcType,
3990     int trgType) throws SQLException {
3991 
3992         if (srcType == trgType) {
3993             return srcObj;
3994         }
3995 
3996         if (isNumeric(trgType) == false && isString(trgType) == false) {
3997             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
3998         }
3999 
4000         try {
4001             switch (trgType) {
4002                 case java.sql.Types.BIT:
4003                     Integer i = Integer.valueOf(srcObj.toString().trim());
4004                     return i.equals(0) ?
4005                     Boolean.valueOf(false) :
4006                         Boolean.valueOf(true);
4007                 case java.sql.Types.TINYINT:
4008                     return Byte.valueOf(srcObj.toString().trim());
4009                 case java.sql.Types.SMALLINT:
4010                     return Short.valueOf(srcObj.toString().trim());
4011                 case java.sql.Types.INTEGER:
4012                     return Integer.valueOf(srcObj.toString().trim());
4013                 case java.sql.Types.BIGINT:
4014                     return Long.valueOf(srcObj.toString().trim());
4015                 case java.sql.Types.NUMERIC:
4016                 case java.sql.Types.DECIMAL:
4017                     return new BigDecimal(srcObj.toString().trim());
4018                 case java.sql.Types.REAL:
4019                 case java.sql.Types.FLOAT:
4020                     return Float.valueOf(srcObj.toString().trim());
4021                 case java.sql.Types.DOUBLE:
4022                     return Double.valueOf(srcObj.toString().trim());
4023                 case java.sql.Types.CHAR:
4024                 case java.sql.Types.VARCHAR:
4025                 case java.sql.Types.LONGVARCHAR:
4026                     return srcObj.toString();
4027                 default:
4028                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString()+ trgType);
4029             }
4030         } catch (NumberFormatException ex) {
4031             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4032         }
4033     }
4034 
4035     /**
4036      * Converts the given <code>Object</code> in the Java programming language
4037      * to the standard object mapping for the specified SQL target data type.
4038      * The conversion must be to a string or temporal type, and there are also
4039      * restrictions on the type to be converted.
4040      * <P>
4041      * <TABLE ALIGN="CENTER" BORDER CELLPADDING=10 BORDERCOLOR="#0000FF"
4042      * <CAPTION ALIGN="CENTER"><B>Parameters and Return Values</B></CAPTION>
4043      * <TR>
4044      *   <TD><B>Source SQL Type</B>
4045      *   <TD><B>Target SQL Type</B>
4046      *   <TD><B>Object Returned</B>
4047      * </TR>
4048      * <TR>
4049      *   <TD><code>TIMESTAMP</code>
4050      *   <TD><code>DATE</code>
4051      *   <TD><code>java.sql.Date</code>
4052      * </TR>
4053      * <TR>
4054      *   <TD><code>TIMESTAMP</code>
4055      *   <TD><code>TIME</code>
4056      *   <TD><code>java.sql.Time</code>
4057      * </TR>
4058      * <TR>
4059      *   <TD><code>TIME</code>
4060      *   <TD><code>TIMESTAMP</code>
4061      *   <TD><code>java.sql.Timestamp</code>
4062      * </TR>
4063      * <TR>
4064      *   <TD><code>DATE</code>, <code>TIME</code>, or <code>TIMESTAMP</code>
4065      *   <TD><code>CHAR</code>, <code>VARCHAR</code>, or <code>LONGVARCHAR</code>
4066      *   <TD><code>java.lang.String</code>
4067      * </TR>
4068      * </TABLE>
4069      * <P>
4070      * If the source type and target type are the same,
4071      * the given object is simply returned.
4072      *
4073      * @param srcObj the <code>Object</code> in the Java programming language
4074      *               that is to be converted to the target type
4075      * @param srcType the data type that is the standard mapping in SQL of the
4076      *                object to be converted; must be one of the constants in
4077      *                <code>java.sql.Types</code>
4078      * @param trgType the SQL data type to which to convert the given object;
4079      *                must be one of the following constants in
4080      *                <code>java.sql.Types</code>: <code>DATE</code>,
4081      *         <code>TIME</code>, <code>TIMESTAMP</code>, <code>CHAR</code>,
4082      *         <code>VARCHAR</code>, or <code>LONGVARCHAR</code>
4083      * @return an <code>Object</code> value.that is
4084      *         the standard object mapping for the target SQL type
4085      * @throws SQLException if the given target type is not one of the string or
4086      *         temporal types in <code>java.sql.Types</code>
4087      */
4088     private Object convertTemporal(Object srcObj,
4089     int srcType, int trgType) throws SQLException {
4090 
4091         if (srcType == trgType) {
4092             return srcObj;
4093         }
4094 
4095         if (isNumeric(trgType) == true ||
4096         (isString(trgType) == false && isTemporal(trgType) == false)) {
4097             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4098         }
4099 
4100         try {
4101             switch (trgType) {
4102                 case java.sql.Types.DATE:
4103                     if (srcType == java.sql.Types.TIMESTAMP) {
4104                         return new java.sql.Date(((java.sql.Timestamp)srcObj).getTime());
4105                     } else {
4106                         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4107                     }
4108                 case java.sql.Types.TIMESTAMP:
4109                     if (srcType == java.sql.Types.TIME) {
4110                         return new Timestamp(((java.sql.Time)srcObj).getTime());
4111                     } else {
4112                         return new Timestamp(((java.sql.Date)srcObj).getTime());
4113                     }
4114                 case java.sql.Types.TIME:
4115                     if (srcType == java.sql.Types.TIMESTAMP) {
4116                         return new Time(((java.sql.Timestamp)srcObj).getTime());
4117                     } else {
4118                         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4119                     }
4120                 case java.sql.Types.CHAR:
4121                 case java.sql.Types.VARCHAR:
4122                 case java.sql.Types.LONGVARCHAR:
4123                     return srcObj.toString();
4124                 default:
4125                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4126             }
4127         } catch (NumberFormatException ex) {
4128             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4129         }
4130 
4131     }
4132 
4133     /**
4134      * Converts the given <code>Object</code> in the Java programming language
4135      * to the standard mapping for the specified SQL target data type.
4136      * The conversion must be to a string or numeric type, but there are no
4137      * restrictions on the type to be converted.  If the source type and target
4138      * type are the same, the given object is simply returned.
4139      *
4140      * @param srcObj the <code>Object</code> in the Java programming language
4141      *               that is to be converted to the target type
4142      * @param srcType the data type that is the standard mapping in SQL of the
4143      *                object to be converted; must be one of the constants in
4144      *                <code>java.sql.Types</code>
4145      * @param trgType the SQL data type to which to convert the given object;
4146      *                must be one of the following constants in
4147      *                <code>java.sql.Types</code>: <code>BIT</code>,
4148      *         or <code>BOOLEAN</code>
4149      * @return an <code>Object</code> value.that is
4150      *         the standard object mapping for the target SQL type
4151      * @throws SQLException if the given target type is not one of the Boolean
4152      *         types in <code>java.sql.Types</code>
4153      */
4154     private Object convertBoolean(Object srcObj, int srcType,
4155     int trgType) throws SQLException {
4156 
4157         if (srcType == trgType) {
4158             return srcObj;
4159         }
4160 
4161         if (isNumeric(trgType) == true ||
4162         (isString(trgType) == false && isBoolean(trgType) == false)) {
4163             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4164         }
4165 
4166 
4167         try {
4168             switch (trgType) {
4169                 case java.sql.Types.BIT:
4170                     Integer i = Integer.valueOf(srcObj.toString().trim());
4171                     return i.equals(0) ?
4172                     Boolean.valueOf(false) :
4173                         Boolean.valueOf(true);
4174                 case java.sql.Types.BOOLEAN:
4175                     return Boolean.valueOf(srcObj.toString().trim());
4176                 default:
4177                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString()+ trgType);
4178             }
4179         } catch (NumberFormatException ex) {
4180             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4181         }
4182     }
4183 
4184     /**
4185      * Sets the designated nullable column in the current row or the
4186      * insert row of this <code>CachedRowSetImpl</code> object with
4187      * <code>null</code> value.
4188      * <P>
4189      * This method updates a column value in the current row or the insert
4190      * row of this rowset; however, another method must be called to complete
4191      * the update process. If the cursor is on a row in the rowset, the
4192      * method {@link #updateRow} must be called to mark the row as updated
4193      * and to notify listeners that the row has changed.
4194      * If the cursor is on the insert row, the method {@link #insertRow}
4195      * must be called to insert the new row into this rowset and to notify
4196      * listeners that a row has changed.
4197      * <P>
4198      * In order to propagate updates in this rowset to the underlying
4199      * data source, an application must call the method {@link #acceptChanges}
4200      * after it calls either <code>updateRow</code> or <code>insertRow</code>.
4201      *
4202      * @param columnIndex the first column is <code>1</code>, the second
4203      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4204      *        and equal to or less than the number of columns in this rowset
4205      * @throws SQLException if (1) the given column index is out of bounds,
4206      *            (2) the cursor is not on one of this rowset's rows or its
4207      *            insert row, or (3) this rowset is
4208      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4209      */
4210     public void updateNull(int columnIndex) throws SQLException {
4211         // sanity check.
4212         checkIndex(columnIndex);
4213         // make sure the cursor is on a valid row
4214         checkCursor();
4215 
4216         BaseRow row = getCurrentRow();
4217         row.setColumnObject(columnIndex, null);
4218 
4219     }
4220 
4221     /**
4222      * Sets the designated column in either the current row or the insert
4223      * row of this <code>CachedRowSetImpl</code> object with the given
4224      * <code>boolean</code> value.
4225      * <P>
4226      * This method updates a column value in the current row or the insert
4227      * row of this rowset, but it does not update the database.
4228      * If the cursor is on a row in the rowset, the
4229      * method {@link #updateRow} must be called to update the database.
4230      * If the cursor is on the insert row, the method {@link #insertRow}
4231      * must be called, which will insert the new row into both this rowset
4232      * and the database. Both of these methods must be called before the
4233      * cursor moves to another row.
4234      *
4235      * @param columnIndex the first column is <code>1</code>, the second
4236      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4237      *        and equal to or less than the number of columns in this rowset
4238      * @param x the new column value
4239      * @throws SQLException if (1) the given column index is out of bounds,
4240      *            (2) the cursor is not on one of this rowset's rows or its
4241      *            insert row, or (3) this rowset is
4242      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4243      */
4244     public void updateBoolean(int columnIndex, boolean x) throws SQLException {
4245         // sanity check.
4246         checkIndex(columnIndex);
4247         // make sure the cursor is on a valid row
4248         checkCursor();
4249         Object obj = convertBoolean(Boolean.valueOf(x),
4250         java.sql.Types.BIT,
4251         RowSetMD.getColumnType(columnIndex));
4252 
4253         getCurrentRow().setColumnObject(columnIndex, obj);
4254     }
4255 
4256     /**
4257      * Sets the designated column in either the current row or the insert
4258      * row of this <code>CachedRowSetImpl</code> object with the given
4259      * <code>byte</code> value.
4260      * <P>
4261      * This method updates a column value in the current row or the insert
4262      * row of this rowset, but it does not update the database.
4263      * If the cursor is on a row in the rowset, the
4264      * method {@link #updateRow} must be called to update the database.
4265      * If the cursor is on the insert row, the method {@link #insertRow}
4266      * must be called, which will insert the new row into both this rowset
4267      * and the database. Both of these methods must be called before the
4268      * cursor moves to another row.
4269      *
4270      * @param columnIndex the first column is <code>1</code>, the second
4271      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4272      *        and equal to or less than the number of columns in this rowset
4273      * @param x the new column value
4274      * @throws SQLException if (1) the given column index is out of bounds,
4275      *            (2) the cursor is not on one of this rowset's rows or its
4276      *            insert row, or (3) this rowset is
4277      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4278      */
4279     public void updateByte(int columnIndex, byte x) throws SQLException {
4280         // sanity check.
4281         checkIndex(columnIndex);
4282         // make sure the cursor is on a valid row
4283         checkCursor();
4284 
4285         Object obj = convertNumeric(Byte.valueOf(x),
4286         java.sql.Types.TINYINT,
4287         RowSetMD.getColumnType(columnIndex));
4288 
4289         getCurrentRow().setColumnObject(columnIndex, obj);
4290     }
4291 
4292     /**
4293      * Sets the designated column in either the current row or the insert
4294      * row of this <code>CachedRowSetImpl</code> object with the given
4295      * <code>short</code> value.
4296      * <P>
4297      * This method updates a column value in the current row or the insert
4298      * row of this rowset, but it does not update the database.
4299      * If the cursor is on a row in the rowset, the
4300      * method {@link #updateRow} must be called to update the database.
4301      * If the cursor is on the insert row, the method {@link #insertRow}
4302      * must be called, which will insert the new row into both this rowset
4303      * and the database. Both of these methods must be called before the
4304      * cursor moves to another row.
4305      *
4306      * @param columnIndex the first column is <code>1</code>, the second
4307      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4308      *        and equal to or less than the number of columns in this rowset
4309      * @param x the new column value
4310      * @throws SQLException if (1) the given column index is out of bounds,
4311      *            (2) the cursor is not on one of this rowset's rows or its
4312      *            insert row, or (3) this rowset is
4313      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4314      */
4315     public void updateShort(int columnIndex, short x) throws SQLException {
4316         // sanity check.
4317         checkIndex(columnIndex);
4318         // make sure the cursor is on a valid row
4319         checkCursor();
4320 
4321         Object obj = convertNumeric(Short.valueOf(x),
4322         java.sql.Types.SMALLINT,
4323         RowSetMD.getColumnType(columnIndex));
4324 
4325         getCurrentRow().setColumnObject(columnIndex, obj);
4326     }
4327 
4328     /**
4329      * Sets the designated column in either the current row or the insert
4330      * row of this <code>CachedRowSetImpl</code> object with the given
4331      * <code>int</code> value.
4332      * <P>
4333      * This method updates a column value in the current row or the insert
4334      * row of this rowset, but it does not update the database.
4335      * If the cursor is on a row in the rowset, the
4336      * method {@link #updateRow} must be called to update the database.
4337      * If the cursor is on the insert row, the method {@link #insertRow}
4338      * must be called, which will insert the new row into both this rowset
4339      * and the database. Both of these methods must be called before the
4340      * cursor moves to another row.
4341      *
4342      * @param columnIndex the first column is <code>1</code>, the second
4343      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4344      *        and equal to or less than the number of columns in this rowset
4345      * @param x the new column value
4346      * @throws SQLException if (1) the given column index is out of bounds,
4347      *            (2) the cursor is not on one of this rowset's rows or its
4348      *            insert row, or (3) this rowset is
4349      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4350      */
4351     public void updateInt(int columnIndex, int x) throws SQLException {
4352         // sanity check.
4353         checkIndex(columnIndex);
4354         // make sure the cursor is on a valid row
4355         checkCursor();
4356         Object obj = convertNumeric(x,
4357         java.sql.Types.INTEGER,
4358         RowSetMD.getColumnType(columnIndex));
4359 
4360         getCurrentRow().setColumnObject(columnIndex, obj);
4361     }
4362 
4363     /**
4364      * Sets the designated column in either the current row or the insert
4365      * row of this <code>CachedRowSetImpl</code> object with the given
4366      * <code>long</code> value.
4367      * <P>
4368      * This method updates a column value in the current row or the insert
4369      * row of this rowset, but it does not update the database.
4370      * If the cursor is on a row in the rowset, the
4371      * method {@link #updateRow} must be called to update the database.
4372      * If the cursor is on the insert row, the method {@link #insertRow}
4373      * must be called, which will insert the new row into both this rowset
4374      * and the database. Both of these methods must be called before the
4375      * cursor moves to another row.
4376      *
4377      * @param columnIndex the first column is <code>1</code>, the second
4378      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4379      *        and equal to or less than the number of columns in this rowset
4380      * @param x the new column value
4381      * @throws SQLException if (1) the given column index is out of bounds,
4382      *            (2) the cursor is not on one of this rowset's rows or its
4383      *            insert row, or (3) this rowset is
4384      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4385      */
4386     public void updateLong(int columnIndex, long x) throws SQLException {
4387         // sanity check.
4388         checkIndex(columnIndex);
4389         // make sure the cursor is on a valid row
4390         checkCursor();
4391 
4392         Object obj = convertNumeric(Long.valueOf(x),
4393         java.sql.Types.BIGINT,
4394         RowSetMD.getColumnType(columnIndex));
4395 
4396         getCurrentRow().setColumnObject(columnIndex, obj);
4397 
4398     }
4399 
4400     /**
4401      * Sets the designated column in either the current row or the insert
4402      * row of this <code>CachedRowSetImpl</code> object with the given
4403      * <code>float</code> value.
4404      * <P>
4405      * This method updates a column value in the current row or the insert
4406      * row of this rowset, but it does not update the database.
4407      * If the cursor is on a row in the rowset, the
4408      * method {@link #updateRow} must be called to update the database.
4409      * If the cursor is on the insert row, the method {@link #insertRow}
4410      * must be called, which will insert the new row into both this rowset
4411      * and the database. Both of these methods must be called before the
4412      * cursor moves to another row.
4413      *
4414      * @param columnIndex the first column is <code>1</code>, the second
4415      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4416      *        and equal to or less than the number of columns in this rowset
4417      * @param x the new column value
4418      * @throws SQLException if (1) the given column index is out of bounds,
4419      *            (2) the cursor is not on one of this rowset's rows or its
4420      *            insert row, or (3) this rowset is
4421      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4422      */
4423     public void updateFloat(int columnIndex, float x) throws SQLException {
4424         // sanity check.
4425         checkIndex(columnIndex);
4426         // make sure the cursor is on a valid row
4427         checkCursor();
4428 
4429         Object obj = convertNumeric(Float.valueOf(x),
4430         java.sql.Types.REAL,
4431         RowSetMD.getColumnType(columnIndex));
4432 
4433         getCurrentRow().setColumnObject(columnIndex, obj);
4434     }
4435 
4436     /**
4437      * Sets the designated column in either the current row or the insert
4438      * row of this <code>CachedRowSetImpl</code> object with the given
4439      * <code>double</code> value.
4440      *
4441      * This method updates a column value in either the current row or
4442      * the insert row of this rowset, but it does not update the
4443      * database.  If the cursor is on a row in the rowset, the
4444      * method {@link #updateRow} must be called to update the database.
4445      * If the cursor is on the insert row, the method {@link #insertRow}
4446      * must be called, which will insert the new row into both this rowset
4447      * and the database. Both of these methods must be called before the
4448      * cursor moves to another row.
4449      *
4450      * @param columnIndex the first column is <code>1</code>, the second
4451      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4452      *        and equal to or less than the number of columns in this rowset
4453      * @param x the new column value
4454      * @throws SQLException if (1) the given column index is out of bounds,
4455      *            (2) the cursor is not on one of this rowset's rows or its
4456      *            insert row, or (3) this rowset is
4457      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4458      */
4459     public void updateDouble(int columnIndex, double x) throws SQLException {
4460         // sanity check.
4461         checkIndex(columnIndex);
4462         // make sure the cursor is on a valid row
4463         checkCursor();
4464         Object obj = convertNumeric(Double.valueOf(x),
4465         java.sql.Types.DOUBLE,
4466         RowSetMD.getColumnType(columnIndex));
4467 
4468         getCurrentRow().setColumnObject(columnIndex, obj);
4469     }
4470 
4471     /**
4472      * Sets the designated column in either the current row or the insert
4473      * row of this <code>CachedRowSetImpl</code> object with the given
4474      * <code>java.math.BigDecimal</code> object.
4475      * <P>
4476      * This method updates a column value in the current row or the insert
4477      * row of this rowset, but it does not update the database.
4478      * If the cursor is on a row in the rowset, the
4479      * method {@link #updateRow} must be called to update the database.
4480      * If the cursor is on the insert row, the method {@link #insertRow}
4481      * must be called, which will insert the new row into both this rowset
4482      * and the database. Both of these methods must be called before the
4483      * cursor moves to another row.
4484      *
4485      * @param columnIndex the first column is <code>1</code>, the second
4486      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4487      *        and equal to or less than the number of columns in this rowset
4488      * @param x the new column value
4489      * @throws SQLException if (1) the given column index is out of bounds,
4490      *            (2) the cursor is not on one of this rowset's rows or its
4491      *            insert row, or (3) this rowset is
4492      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4493      */
4494     public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {
4495         // sanity check.
4496         checkIndex(columnIndex);
4497         // make sure the cursor is on a valid row
4498         checkCursor();
4499 
4500         Object obj = convertNumeric(x,
4501         java.sql.Types.NUMERIC,
4502         RowSetMD.getColumnType(columnIndex));
4503 
4504         getCurrentRow().setColumnObject(columnIndex, obj);
4505     }
4506 
4507     /**
4508      * Sets the designated column in either the current row or the insert
4509      * row of this <code>CachedRowSetImpl</code> object with the given
4510      * <code>String</code> object.
4511      * <P>
4512      * This method updates a column value in either the current row or
4513      * the insert row of this rowset, but it does not update the
4514      * database.  If the cursor is on a row in the rowset, the
4515      * method {@link #updateRow} must be called to mark the row as updated.
4516      * If the cursor is on the insert row, the method {@link #insertRow}
4517      * must be called to insert the new row into this rowset and mark it
4518      * as inserted. Both of these methods must be called before the
4519      * cursor moves to another row.
4520      * <P>
4521      * The method <code>acceptChanges</code> must be called if the
4522      * updated values are to be written back to the underlying database.
4523      *
4524      * @param columnIndex the first column is <code>1</code>, the second
4525      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4526      *        and equal to or less than the number of columns in this rowset
4527      * @param x the new column value
4528      * @throws SQLException if (1) the given column index is out of bounds,
4529      *            (2) the cursor is not on one of this rowset's rows or its
4530      *            insert row, or (3) this rowset is
4531      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4532      */
4533     public void updateString(int columnIndex, String x) throws SQLException {
4534         // sanity check.
4535         checkIndex(columnIndex);
4536         // make sure the cursor is on a valid row
4537         checkCursor();
4538 
4539         getCurrentRow().setColumnObject(columnIndex, x);
4540     }
4541 
4542     /**
4543      * Sets the designated column in either the current row or the insert
4544      * row of this <code>CachedRowSetImpl</code> object with the given
4545      * <code>byte</code> array.
4546      *
4547      * This method updates a column value in either the current row or
4548      * the insert row of this rowset, but it does not update the
4549      * database.  If the cursor is on a row in the rowset, the
4550      * method {@link #updateRow} must be called to update the database.
4551      * If the cursor is on the insert row, the method {@link #insertRow}
4552      * must be called, which will insert the new row into both this rowset
4553      * and the database. Both of these methods must be called before the
4554      * cursor moves to another row.
4555      *
4556      * @param columnIndex the first column is <code>1</code>, the second
4557      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4558      *        and equal to or less than the number of columns in this rowset
4559      * @param x the new column value
4560      * @throws SQLException if (1) the given column index is out of bounds,
4561      *            (2) the cursor is not on one of this rowset's rows or its
4562      *            insert row, or (3) this rowset is
4563      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4564      */
4565     public void updateBytes(int columnIndex, byte x[]) throws SQLException {
4566         // sanity check.
4567         checkIndex(columnIndex);
4568         // make sure the cursor is on a valid row
4569         checkCursor();
4570 
4571         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4572             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4573         }
4574 
4575         getCurrentRow().setColumnObject(columnIndex, x);
4576     }
4577 
4578     /**
4579      * Sets the designated column in either the current row or the insert
4580      * row of this <code>CachedRowSetImpl</code> object with the given
4581      * <code>Date</code> object.
4582      *
4583      * This method updates a column value in either the current row or
4584      * the insert row of this rowset, but it does not update the
4585      * database.  If the cursor is on a row in the rowset, the
4586      * method {@link #updateRow} must be called to update the database.
4587      * If the cursor is on the insert row, the method {@link #insertRow}
4588      * must be called, which will insert the new row into both this rowset
4589      * and the database. Both of these methods must be called before the
4590      * cursor moves to another row.
4591      *
4592      * @param columnIndex the first column is <code>1</code>, the second
4593      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4594      *        and equal to or less than the number of columns in this rowset
4595      * @param x the new column value
4596      * @throws SQLException if (1) the given column index is out of bounds,
4597      *            (2) the cursor is not on one of this rowset's rows or its
4598      *            insert row, (3) the type of the designated column is not
4599      *            an SQL <code>DATE</code> or <code>TIMESTAMP</code>, or
4600      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4601      */
4602     public void updateDate(int columnIndex, java.sql.Date x) throws SQLException {
4603         // sanity check.
4604         checkIndex(columnIndex);
4605         // make sure the cursor is on a valid row
4606         checkCursor();
4607 
4608         Object obj = convertTemporal(x,
4609         java.sql.Types.DATE,
4610         RowSetMD.getColumnType(columnIndex));
4611 
4612         getCurrentRow().setColumnObject(columnIndex, obj);
4613     }
4614 
4615     /**
4616      * Sets the designated column in either the current row or the insert
4617      * row of this <code>CachedRowSetImpl</code> object with the given
4618      * <code>Time</code> object.
4619      *
4620      * This method updates a column value in either the current row or
4621      * the insert row of this rowset, but it does not update the
4622      * database.  If the cursor is on a row in the rowset, the
4623      * method {@link #updateRow} must be called to update the database.
4624      * If the cursor is on the insert row, the method {@link #insertRow}
4625      * must be called, which will insert the new row into both this rowset
4626      * and the database. Both of these methods must be called before the
4627      * cursor moves to another row.
4628      *
4629      * @param columnIndex the first column is <code>1</code>, the second
4630      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4631      *        and equal to or less than the number of columns in this rowset
4632      * @param x the new column value
4633      * @throws SQLException if (1) the given column index is out of bounds,
4634      *            (2) the cursor is not on one of this rowset's rows or its
4635      *            insert row, (3) the type of the designated column is not
4636      *            an SQL <code>TIME</code> or <code>TIMESTAMP</code>, or
4637      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4638      */
4639     public void updateTime(int columnIndex, java.sql.Time x) throws SQLException {
4640         // sanity check.
4641         checkIndex(columnIndex);
4642         // make sure the cursor is on a valid row
4643         checkCursor();
4644 
4645         Object obj = convertTemporal(x,
4646         java.sql.Types.TIME,
4647         RowSetMD.getColumnType(columnIndex));
4648 
4649         getCurrentRow().setColumnObject(columnIndex, obj);
4650     }
4651 
4652     /**
4653      * Sets the designated column in either the current row or the insert
4654      * row of this <code>CachedRowSetImpl</code> object with the given
4655      * <code>Timestamp</code> object.
4656      *
4657      * This method updates a column value in either the current row or
4658      * the insert row of this rowset, but it does not update the
4659      * database.  If the cursor is on a row in the rowset, the
4660      * method {@link #updateRow} must be called to update the database.
4661      * If the cursor is on the insert row, the method {@link #insertRow}
4662      * must be called, which will insert the new row into both this rowset
4663      * and the database. Both of these methods must be called before the
4664      * cursor moves to another row.
4665      *
4666      * @param columnIndex the first column is <code>1</code>, the second
4667      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4668      *        and equal to or less than the number of columns in this rowset
4669      * @param x the new column value
4670      * @throws SQLException if (1) the given column index is out of bounds,
4671      *            (2) the cursor is not on one of this rowset's rows or its
4672      *            insert row, (3) the type of the designated column is not
4673      *            an SQL <code>DATE</code>, <code>TIME</code>, or
4674      *            <code>TIMESTAMP</code>, or (4) this rowset is
4675      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4676      */
4677     public void updateTimestamp(int columnIndex, java.sql.Timestamp x) throws SQLException {
4678         // sanity check.
4679         checkIndex(columnIndex);
4680         // make sure the cursor is on a valid row
4681         checkCursor();
4682 
4683         Object obj = convertTemporal(x,
4684         java.sql.Types.TIMESTAMP,
4685         RowSetMD.getColumnType(columnIndex));
4686 
4687         getCurrentRow().setColumnObject(columnIndex, obj);
4688     }
4689 
4690     /**
4691      * Sets the designated column in either the current row or the insert
4692      * row of this <code>CachedRowSetImpl</code> object with the given
4693      * ASCII stream value.
4694      * <P>
4695      * This method updates a column value in either the current row or
4696      * the insert row of this rowset, but it does not update the
4697      * database.  If the cursor is on a row in the rowset, the
4698      * method {@link #updateRow} must be called to update the database.
4699      * If the cursor is on the insert row, the method {@link #insertRow}
4700      * must be called, which will insert the new row into both this rowset
4701      * and the database. Both of these methods must be called before the
4702      * cursor moves to another row.
4703      *
4704      * @param columnIndex the first column is <code>1</code>, the second
4705      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4706      *        and equal to or less than the number of columns in this rowset
4707      * @param x the new column value
4708      * @param length the number of one-byte ASCII characters in the stream
4709      * @throws SQLException if this method is invoked
4710      */
4711     public void updateAsciiStream(int columnIndex, java.io.InputStream x, int length) throws SQLException {
4712         // sanity Check
4713         checkIndex(columnIndex);
4714         // make sure the cursor is on a valid row
4715         checkCursor();
4716 
4717 
4718         if (isString(RowSetMD.getColumnType(columnIndex)) == false &&
4719         isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4720             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4721         }
4722 
4723         byte buf[] = new byte[length];
4724         try {
4725             int charsRead = 0;
4726             do {
4727                 charsRead += x.read(buf, charsRead, length - charsRead);
4728             } while (charsRead != length);
4729             //Changed the condition check to check for length instead of -1
4730         } catch (java.io.IOException ex) {
4731             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.asciistream").toString());
4732         }
4733         String str = new String(buf);
4734 
4735         getCurrentRow().setColumnObject(columnIndex, str);
4736 
4737     }
4738 
4739     /**
4740      * Sets the designated column in either the current row or the insert
4741      * row of this <code>CachedRowSetImpl</code> object with the given
4742      * <code>java.io.InputStream</code> object.
4743      * <P>
4744      * This method updates a column value in either the current row or
4745      * the insert row of this rowset, but it does not update the
4746      * database.  If the cursor is on a row in the rowset, the
4747      * method {@link #updateRow} must be called to update the database.
4748      * If the cursor is on the insert row, the method {@link #insertRow}
4749      * must be called, which will insert the new row into both this rowset
4750      * and the database. Both of these methods must be called before the
4751      * cursor moves to another row.
4752      *
4753      * @param columnIndex the first column is <code>1</code>, the second
4754      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4755      *        and equal to or less than the number of columns in this rowset
4756      * @param x the new column value; must be a <code>java.io.InputStream</code>
4757      *          containing <code>BINARY</code>, <code>VARBINARY</code>, or
4758      *          <code>LONGVARBINARY</code> data
4759      * @param length the length of the stream in bytes
4760      * @throws SQLException if (1) the given column index is out of bounds,
4761      *            (2) the cursor is not on one of this rowset's rows or its
4762      *            insert row, (3) the data in the stream is not binary, or
4763      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4764      */
4765     public void updateBinaryStream(int columnIndex, java.io.InputStream x,int length) throws SQLException {
4766         // sanity Check
4767         checkIndex(columnIndex);
4768         // make sure the cursor is on a valid row
4769         checkCursor();
4770 
4771         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4772             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4773         }
4774 
4775         byte buf[] = new byte[length];
4776         try {
4777             int bytesRead = 0;
4778             do {
4779                 bytesRead += x.read(buf, bytesRead, length - bytesRead);
4780             } while (bytesRead != -1);
4781         } catch (java.io.IOException ex) {
4782             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.binstream").toString());
4783         }
4784 
4785         getCurrentRow().setColumnObject(columnIndex, buf);
4786     }
4787 
4788     /**
4789      * Sets the designated column in either the current row or the insert
4790      * row of this <code>CachedRowSetImpl</code> object with the given
4791      * <code>java.io.Reader</code> object.
4792      * <P>
4793      * This method updates a column value in either the current row or
4794      * the insert row of this rowset, but it does not update the
4795      * database.  If the cursor is on a row in the rowset, the
4796      * method {@link #updateRow} must be called to update the database.
4797      * If the cursor is on the insert row, the method {@link #insertRow}
4798      * must be called, which will insert the new row into both this rowset
4799      * and the database. Both of these methods must be called before the
4800      * cursor moves to another row.
4801      *
4802      * @param columnIndex the first column is <code>1</code>, the second
4803      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4804      *        and equal to or less than the number of columns in this rowset
4805      * @param x the new column value; must be a <code>java.io.Reader</code>
4806      *          containing <code>BINARY</code>, <code>VARBINARY</code>,
4807      *          <code>LONGVARBINARY</code>, <code>CHAR</code>, <code>VARCHAR</code>,
4808      *          or <code>LONGVARCHAR</code> data
4809      * @param length the length of the stream in characters
4810      * @throws SQLException if (1) the given column index is out of bounds,
4811      *            (2) the cursor is not on one of this rowset's rows or its
4812      *            insert row, (3) the data in the stream is not a binary or
4813      *            character type, or (4) this rowset is
4814      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4815      */
4816     public void updateCharacterStream(int columnIndex, java.io.Reader x, int length) throws SQLException {
4817         // sanity Check
4818         checkIndex(columnIndex);
4819         // make sure the cursor is on a valid row
4820         checkCursor();
4821 
4822         if (isString(RowSetMD.getColumnType(columnIndex)) == false &&
4823         isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4824             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4825         }
4826 
4827         char buf[] = new char[length];
4828         try {
4829             int charsRead = 0;
4830             do {
4831                 charsRead += x.read(buf, charsRead, length - charsRead);
4832             } while (charsRead != length);
4833             //Changed the condition checking to check for length instead of -1
4834         } catch (java.io.IOException ex) {
4835             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.binstream").toString());
4836         }
4837         String str = new String(buf);
4838 
4839         getCurrentRow().setColumnObject(columnIndex, str);
4840     }
4841 
4842     /**
4843      * Sets the designated column in either the current row or the insert
4844      * row of this <code>CachedRowSetImpl</code> object with the given
4845      * <code>Object</code> value.  The <code>scale</code> parameter indicates
4846      * the number of digits to the right of the decimal point and is ignored
4847      * if the new column value is not a type that will be mapped to an SQL
4848      * <code>DECIMAL</code> or <code>NUMERIC</code> value.
4849      * <P>
4850      * This method updates a column value in either the current row or
4851      * the insert row of this rowset, but it does not update the
4852      * database.  If the cursor is on a row in the rowset, the
4853      * method {@link #updateRow} must be called to update the database.
4854      * If the cursor is on the insert row, the method {@link #insertRow}
4855      * must be called, which will insert the new row into both this rowset
4856      * and the database. Both of these methods must be called before the
4857      * cursor moves to another row.
4858      *
4859      * @param columnIndex the first column is <code>1</code>, the second
4860      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4861      *        and equal to or less than the number of columns in this rowset
4862      * @param x the new column value
4863      * @param scale the number of digits to the right of the decimal point (for
4864      *              <code>DECIMAL</code> and <code>NUMERIC</code> types only)
4865      * @throws SQLException if (1) the given column index is out of bounds,
4866      *            (2) the cursor is not on one of this rowset's rows or its
4867      *            insert row, or (3) this rowset is
4868      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4869      */
4870     public void updateObject(int columnIndex, Object x, int scale) throws SQLException {
4871         // sanity check.
4872         checkIndex(columnIndex);
4873         // make sure the cursor is on a valid row
4874         checkCursor();
4875 
4876         int type = RowSetMD.getColumnType(columnIndex);
4877         if (type == Types.DECIMAL || type == Types.NUMERIC) {
4878             ((java.math.BigDecimal)x).setScale(scale);
4879         }
4880         getCurrentRow().setColumnObject(columnIndex, x);
4881     }
4882 
4883     /**
4884      * Sets the designated column in either the current row or the insert
4885      * row of this <code>CachedRowSetImpl</code> object with the given
4886      * <code>Object</code> value.
4887      * <P>
4888      * This method updates a column value in either the current row or
4889      * the insert row of this rowset, but it does not update the
4890      * database.  If the cursor is on a row in the rowset, the
4891      * method {@link #updateRow} must be called to update the database.
4892      * If the cursor is on the insert row, the method {@link #insertRow}
4893      * must be called, which will insert the new row into both this rowset
4894      * and the database. Both of these methods must be called before the
4895      * cursor moves to another row.
4896      *
4897      * @param columnIndex the first column is <code>1</code>, the second
4898      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4899      *        and equal to or less than the number of columns in this rowset
4900      * @param x the new column value
4901      * @throws SQLException if (1) the given column index is out of bounds,
4902      *            (2) the cursor is not on one of this rowset's rows or its
4903      *            insert row, or (3) this rowset is
4904      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4905      */
4906     public void updateObject(int columnIndex, Object x) throws SQLException {
4907         // sanity check.
4908         checkIndex(columnIndex);
4909         // make sure the cursor is on a valid row
4910         checkCursor();
4911 
4912         getCurrentRow().setColumnObject(columnIndex, x);
4913     }
4914 
4915     /**
4916      * Sets the designated nullable column in the current row or the
4917      * insert row of this <code>CachedRowSetImpl</code> object with
4918      * <code>null</code> value.
4919      * <P>
4920      * This method updates a column value in the current row or the insert
4921      * row of this rowset, but it does not update the database.
4922      * If the cursor is on a row in the rowset, the
4923      * method {@link #updateRow} must be called to update the database.
4924      * If the cursor is on the insert row, the method {@link #insertRow}
4925      * must be called, which will insert the new row into both this rowset
4926      * and the database.
4927      *
4928      * @param columnName a <code>String</code> object that must match the
4929      *        SQL name of a column in this rowset, ignoring case
4930      * @throws SQLException if (1) the given column name does not match the
4931      *            name of a column in this rowset, (2) the cursor is not on
4932      *            one of this rowset's rows or its insert row, or (3) this
4933      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4934      */
4935     public void updateNull(String columnName) throws SQLException {
4936         updateNull(getColIdxByName(columnName));
4937     }
4938 
4939     /**
4940      * Sets the designated column in either the current row or the insert
4941      * row of this <code>CachedRowSetImpl</code> object with the given
4942      * <code>boolean</code> value.
4943      * <P>
4944      * This method updates a column value in the current row or the insert
4945      * row of this rowset, but it does not update the database.
4946      * If the cursor is on a row in the rowset, the
4947      * method {@link #updateRow} must be called to update the database.
4948      * If the cursor is on the insert row, the method {@link #insertRow}
4949      * must be called, which will insert the new row into both this rowset
4950      * and the database. Both of these methods must be called before the
4951      * cursor moves to another row.
4952      *
4953      * @param columnName a <code>String</code> object that must match the
4954      *        SQL name of a column in this rowset, ignoring case
4955      * @param x the new column value
4956      * @throws SQLException if (1) the given column name does not match the
4957      *            name of a column in this rowset, (2) the cursor is not on
4958      *            one of this rowset's rows or its insert row, or (3) this
4959      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4960      */
4961     public void updateBoolean(String columnName, boolean x) throws SQLException {
4962         updateBoolean(getColIdxByName(columnName), x);
4963     }
4964 
4965     /**
4966      * Sets the designated column in either the current row or the insert
4967      * row of this <code>CachedRowSetImpl</code> object with the given
4968      * <code>byte</code> value.
4969      * <P>
4970      * This method updates a column value in the current row or the insert
4971      * row of this rowset, but it does not update the database.
4972      * If the cursor is on a row in the rowset, the
4973      * method {@link #updateRow} must be called to update the database.
4974      * If the cursor is on the insert row, the method {@link #insertRow}
4975      * must be called, which will insert the new row into both this rowset
4976      * and the database. Both of these methods must be called before the
4977      * cursor moves to another row.
4978      *
4979      * @param columnName a <code>String</code> object that must match the
4980      *        SQL name of a column in this rowset, ignoring case
4981      * @param x the new column value
4982      * @throws SQLException if (1) the given column name does not match the
4983      *            name of a column in this rowset, (2) the cursor is not on
4984      *            one of this rowset's rows or its insert row, or (3) this
4985      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4986      */
4987     public void updateByte(String columnName, byte x) throws SQLException {
4988         updateByte(getColIdxByName(columnName), x);
4989     }
4990 
4991     /**
4992      * Sets the designated column in either the current row or the insert
4993      * row of this <code>CachedRowSetImpl</code> object with the given
4994      * <code>short</code> value.
4995      * <P>
4996      * This method updates a column value in the current row or the insert
4997      * row of this rowset, but it does not update the database.
4998      * If the cursor is on a row in the rowset, the
4999      * method {@link #updateRow} must be called to update the database.
5000      * If the cursor is on the insert row, the method {@link #insertRow}
5001      * must be called, which will insert the new row into both this rowset
5002      * and the database. Both of these methods must be called before the
5003      * cursor moves to another row.
5004      *
5005      * @param columnName a <code>String</code> object that must match the
5006      *        SQL name of a column in this rowset, ignoring case
5007      * @param x the new column value
5008      * @throws SQLException if (1) the given column name does not match the
5009      *            name of a column in this rowset, (2) the cursor is not on
5010      *            one of this rowset's rows or its insert row, or (3) this
5011      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5012      */
5013     public void updateShort(String columnName, short x) throws SQLException {
5014         updateShort(getColIdxByName(columnName), x);
5015     }
5016 
5017     /**
5018      * Sets the designated column in either the current row or the insert
5019      * row of this <code>CachedRowSetImpl</code> object with the given
5020      * <code>int</code> value.
5021      * <P>
5022      * This method updates a column value in the current row or the insert
5023      * row of this rowset, but it does not update the database.
5024      * If the cursor is on a row in the rowset, the
5025      * method {@link #updateRow} must be called to update the database.
5026      * If the cursor is on the insert row, the method {@link #insertRow}
5027      * must be called, which will insert the new row into both this rowset
5028      * and the database. Both of these methods must be called before the
5029      * cursor moves to another row.
5030      *
5031      * @param columnName a <code>String</code> object that must match the
5032      *        SQL name of a column in this rowset, ignoring case
5033      * @param x the new column value
5034      * @throws SQLException if (1) the given column name does not match the
5035      *            name of a column in this rowset, (2) the cursor is not on
5036      *            one of this rowset's rows or its insert row, or (3) this
5037      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5038      */
5039     public void updateInt(String columnName, int x) throws SQLException {
5040         updateInt(getColIdxByName(columnName), x);
5041     }
5042 
5043     /**
5044      * Sets the designated column in either the current row or the insert
5045      * row of this <code>CachedRowSetImpl</code> object with the given
5046      * <code>long</code> value.
5047      * <P>
5048      * This method updates a column value in the current row or the insert
5049      * row of this rowset, but it does not update the database.
5050      * If the cursor is on a row in the rowset, the
5051      * method {@link #updateRow} must be called to update the database.
5052      * If the cursor is on the insert row, the method {@link #insertRow}
5053      * must be called, which will insert the new row into both this rowset
5054      * and the database. Both of these methods must be called before the
5055      * cursor moves to another row.
5056      *
5057      * @param columnName a <code>String</code> object that must match the
5058      *        SQL name of a column in this rowset, ignoring case
5059      * @param x the new column value
5060      * @throws SQLException if (1) the given column name does not match the
5061      *            name of a column in this rowset, (2) the cursor is not on
5062      *            one of this rowset's rows or its insert row, or (3) this
5063      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5064      */
5065     public void updateLong(String columnName, long x) throws SQLException {
5066         updateLong(getColIdxByName(columnName), x);
5067     }
5068 
5069     /**
5070      * Sets the designated column in either the current row or the insert
5071      * row of this <code>CachedRowSetImpl</code> object with the given
5072      * <code>float</code> value.
5073      * <P>
5074      * This method updates a column value in the current row or the insert
5075      * row of this rowset, but it does not update the database.
5076      * If the cursor is on a row in the rowset, the
5077      * method {@link #updateRow} must be called to update the database.
5078      * If the cursor is on the insert row, the method {@link #insertRow}
5079      * must be called, which will insert the new row into both this rowset
5080      * and the database. Both of these methods must be called before the
5081      * cursor moves to another row.
5082      *
5083      * @param columnName a <code>String</code> object that must match the
5084      *        SQL name of a column in this rowset, ignoring case
5085      * @param x the new column value
5086      * @throws SQLException if (1) the given column name does not match the
5087      *            name of a column in this rowset, (2) the cursor is not on
5088      *            one of this rowset's rows or its insert row, or (3) this
5089      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5090      */
5091     public void updateFloat(String columnName, float x) throws SQLException {
5092         updateFloat(getColIdxByName(columnName), x);
5093     }
5094 
5095     /**
5096      * Sets the designated column in either the current row or the insert
5097      * row of this <code>CachedRowSetImpl</code> object with the given
5098      * <code>double</code> value.
5099      *
5100      * This method updates a column value in either the current row or
5101      * the insert row of this rowset, but it does not update the
5102      * database.  If the cursor is on a row in the rowset, the
5103      * method {@link #updateRow} must be called to update the database.
5104      * If the cursor is on the insert row, the method {@link #insertRow}
5105      * must be called, which will insert the new row into both this rowset
5106      * and the database. Both of these methods must be called before the
5107      * cursor moves to another row.
5108      *
5109      * @param columnName a <code>String</code> object that must match the
5110      *        SQL name of a column in this rowset, ignoring case
5111      * @param x the new column value
5112      * @throws SQLException if (1) the given column name does not match the
5113      *            name of a column in this rowset, (2) the cursor is not on
5114      *            one of this rowset's rows or its insert row, or (3) this
5115      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5116      */
5117     public void updateDouble(String columnName, double x) throws SQLException {
5118         updateDouble(getColIdxByName(columnName), x);
5119     }
5120 
5121     /**
5122      * Sets the designated column in either the current row or the insert
5123      * row of this <code>CachedRowSetImpl</code> object with the given
5124      * <code>java.math.BigDecimal</code> object.
5125      * <P>
5126      * This method updates a column value in the current row or the insert
5127      * row of this rowset, but it does not update the database.
5128      * If the cursor is on a row in the rowset, the
5129      * method {@link #updateRow} must be called to update the database.
5130      * If the cursor is on the insert row, the method {@link #insertRow}
5131      * must be called, which will insert the new row into both this rowset
5132      * and the database. Both of these methods must be called before the
5133      * cursor moves to another row.
5134      *
5135      * @param columnName a <code>String</code> object that must match the
5136      *        SQL name of a column in this rowset, ignoring case
5137      * @param x the new column value
5138      * @throws SQLException if (1) the given column name does not match the
5139      *            name of a column in this rowset, (2) the cursor is not on
5140      *            one of this rowset's rows or its insert row, or (3) this
5141      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5142      */
5143     public void updateBigDecimal(String columnName, BigDecimal x) throws SQLException {
5144         updateBigDecimal(getColIdxByName(columnName), x);
5145     }
5146 
5147     /**
5148      * Sets the designated column in either the current row or the insert
5149      * row of this <code>CachedRowSetImpl</code> object with the given
5150      * <code>String</code> object.
5151      *
5152      * This method updates a column value in either the current row or
5153      * the insert row of this rowset, but it does not update the
5154      * database.  If the cursor is on a row in the rowset, the
5155      * method {@link #updateRow} must be called to update the database.
5156      * If the cursor is on the insert row, the method {@link #insertRow}
5157      * must be called, which will insert the new row into both this rowset
5158      * and the database. Both of these methods must be called before the
5159      * cursor moves to another row.
5160      *
5161      * @param columnName a <code>String</code> object that must match the
5162      *        SQL name of a column in this rowset, ignoring case
5163      * @param x the new column value
5164      * @throws SQLException if (1) the given column name does not match the
5165      *            name of a column in this rowset, (2) the cursor is not on
5166      *            one of this rowset's rows or its insert row, or (3) this
5167      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5168      */
5169     public void updateString(String columnName, String x) throws SQLException {
5170         updateString(getColIdxByName(columnName), x);
5171     }
5172 
5173     /**
5174      * Sets the designated column in either the current row or the insert
5175      * row of this <code>CachedRowSetImpl</code> object with the given
5176      * <code>byte</code> array.
5177      *
5178      * This method updates a column value in either the current row or
5179      * the insert row of this rowset, but it does not update the
5180      * database.  If the cursor is on a row in the rowset, the
5181      * method {@link #updateRow} must be called to update the database.
5182      * If the cursor is on the insert row, the method {@link #insertRow}
5183      * must be called, which will insert the new row into both this rowset
5184      * and the database. Both of these methods must be called before the
5185      * cursor moves to another row.
5186      *
5187      * @param columnName a <code>String</code> object that must match the
5188      *        SQL name of a column in this rowset, ignoring case
5189      * @param x the new column value
5190      * @throws SQLException if (1) the given column name does not match the
5191      *            name of a column in this rowset, (2) the cursor is not on
5192      *            one of this rowset's rows or its insert row, or (3) this
5193      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5194      */
5195     public void updateBytes(String columnName, byte x[]) throws SQLException {
5196         updateBytes(getColIdxByName(columnName), x);
5197     }
5198 
5199     /**
5200      * Sets the designated column in either the current row or the insert
5201      * row of this <code>CachedRowSetImpl</code> object with the given
5202      * <code>Date</code> object.
5203      *
5204      * This method updates a column value in either the current row or
5205      * the insert row of this rowset, but it does not update the
5206      * database.  If the cursor is on a row in the rowset, the
5207      * method {@link #updateRow} must be called to update the database.
5208      * If the cursor is on the insert row, the method {@link #insertRow}
5209      * must be called, which will insert the new row into both this rowset
5210      * and the database. Both of these methods must be called before the
5211      * cursor moves to another row.
5212      *
5213      * @param columnName a <code>String</code> object that must match the
5214      *        SQL name of a column in this rowset, ignoring case
5215      * @param x the new column value
5216      * @throws SQLException if (1) the given column name does not match the
5217      *            name of a column in this rowset, (2) the cursor is not on
5218      *            one of this rowset's rows or its insert row, (3) the type
5219      *            of the designated column is not an SQL <code>DATE</code> or
5220      *            <code>TIMESTAMP</code>, or (4) this rowset is
5221      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5222      */
5223     public void updateDate(String columnName, java.sql.Date x) throws SQLException {
5224         updateDate(getColIdxByName(columnName), x);
5225     }
5226 
5227     /**
5228      * Sets the designated column in either the current row or the insert
5229      * row of this <code>CachedRowSetImpl</code> object with the given
5230      * <code>Time</code> object.
5231      *
5232      * This method updates a column value in either the current row or
5233      * the insert row of this rowset, but it does not update the
5234      * database.  If the cursor is on a row in the rowset, the
5235      * method {@link #updateRow} must be called to update the database.
5236      * If the cursor is on the insert row, the method {@link #insertRow}
5237      * must be called, which will insert the new row into both this rowset
5238      * and the database. Both of these methods must be called before the
5239      * cursor moves to another row.
5240      *
5241      * @param columnName a <code>String</code> object that must match the
5242      *        SQL name of a column in this rowset, ignoring case
5243      * @param x the new column value
5244      * @throws SQLException if (1) the given column name does not match the
5245      *            name of a column in this rowset, (2) the cursor is not on
5246      *            one of this rowset's rows or its insert row, (3) the type
5247      *            of the designated column is not an SQL <code>TIME</code> or
5248      *            <code>TIMESTAMP</code>, or (4) this rowset is
5249      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5250      */
5251     public void updateTime(String columnName, java.sql.Time x) throws SQLException {
5252         updateTime(getColIdxByName(columnName), x);
5253     }
5254 
5255     /**
5256      * Sets the designated column in either the current row or the insert
5257      * row of this <code>CachedRowSetImpl</code> object with the given
5258      * <code>Timestamp</code> object.
5259      *
5260      * This method updates a column value in either the current row or
5261      * the insert row of this rowset, but it does not update the
5262      * database.  If the cursor is on a row in the rowset, the
5263      * method {@link #updateRow} must be called to update the database.
5264      * If the cursor is on the insert row, the method {@link #insertRow}
5265      * must be called, which will insert the new row into both this rowset
5266      * and the database. Both of these methods must be called before the
5267      * cursor moves to another row.
5268      *
5269      * @param columnName a <code>String</code> object that must match the
5270      *        SQL name of a column in this rowset, ignoring case
5271      * @param x the new column value
5272      * @throws SQLException if the given column index is out of bounds or
5273      *            the cursor is not on one of this rowset's rows or its
5274      *            insert row
5275      * @throws SQLException if (1) the given column name does not match the
5276      *            name of a column in this rowset, (2) the cursor is not on
5277      *            one of this rowset's rows or its insert row, (3) the type
5278      *            of the designated column is not an SQL <code>DATE</code>,
5279      *            <code>TIME</code>, or <code>TIMESTAMP</code>, or (4) this
5280      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5281      */
5282     public void updateTimestamp(String columnName, java.sql.Timestamp x) throws SQLException {
5283         updateTimestamp(getColIdxByName(columnName), x);
5284     }
5285 
5286     /**
5287      * Sets the designated column in either the current row or the insert
5288      * row of this <code>CachedRowSetImpl</code> object with the given
5289      * ASCII stream value.
5290      * <P>
5291      * This method updates a column value in either the current row or
5292      * the insert row of this rowset, but it does not update the
5293      * database.  If the cursor is on a row in the rowset, the
5294      * method {@link #updateRow} must be called to update the database.
5295      * If the cursor is on the insert row, the method {@link #insertRow}
5296      * must be called, which will insert the new row into both this rowset
5297      * and the database. Both of these methods must be called before the
5298      * cursor moves to another row.
5299      *
5300      * @param columnName a <code>String</code> object that must match the
5301      *        SQL name of a column in this rowset, ignoring case
5302      * @param x the new column value
5303      * @param length the number of one-byte ASCII characters in the stream
5304      */
5305     public void updateAsciiStream(String columnName,
5306     java.io.InputStream x,
5307     int length) throws SQLException {
5308         updateAsciiStream(getColIdxByName(columnName), x, length);
5309     }
5310 
5311     /**
5312      * Sets the designated column in either the current row or the insert
5313      * row of this <code>CachedRowSetImpl</code> object with the given
5314      * <code>java.io.InputStream</code> object.
5315      * <P>
5316      * This method updates a column value in either the current row or
5317      * the insert row of this rowset, but it does not update the
5318      * database.  If the cursor is on a row in the rowset, the
5319      * method {@link #updateRow} must be called to update the database.
5320      * If the cursor is on the insert row, the method {@link #insertRow}
5321      * must be called, which will insert the new row into both this rowset
5322      * and the database. Both of these methods must be called before the
5323      * cursor moves to another row.
5324      *
5325      * @param columnName a <code>String</code> object that must match the
5326      *        SQL name of a column in this rowset, ignoring case
5327      * @param x the new column value; must be a <code>java.io.InputStream</code>
5328      *          containing <code>BINARY</code>, <code>VARBINARY</code>, or
5329      *          <code>LONGVARBINARY</code> data
5330      * @param length the length of the stream in bytes
5331      * @throws SQLException if (1) the given column name does not match the
5332      *            name of a column in this rowset, (2) the cursor is not on
5333      *            one of this rowset's rows or its insert row, (3) the data
5334      *            in the stream is not binary, or (4) this rowset is
5335      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5336      */
5337     public void updateBinaryStream(String columnName, java.io.InputStream x, int length) throws SQLException {
5338         updateBinaryStream(getColIdxByName(columnName), x, length);
5339     }
5340 
5341     /**
5342      * Sets the designated column in either the current row or the insert
5343      * row of this <code>CachedRowSetImpl</code> object with the given
5344      * <code>java.io.Reader</code> object.
5345      * <P>
5346      * This method updates a column value in either the current row or
5347      * the insert row of this rowset, but it does not update the
5348      * database.  If the cursor is on a row in the rowset, the
5349      * method {@link #updateRow} must be called to update the database.
5350      * If the cursor is on the insert row, the method {@link #insertRow}
5351      * must be called, which will insert the new row into both this rowset
5352      * and the database. Both of these methods must be called before the
5353      * cursor moves to another row.
5354      *
5355      * @param columnName a <code>String</code> object that must match the
5356      *        SQL name of a column in this rowset, ignoring case
5357      * @param reader the new column value; must be a
5358      * <code>java.io.Reader</code> containing <code>BINARY</code>,
5359      * <code>VARBINARY</code>, <code>LONGVARBINARY</code>, <code>CHAR</code>,
5360      * <code>VARCHAR</code>, or <code>LONGVARCHAR</code> data
5361      * @param length the length of the stream in characters
5362      * @throws SQLException if (1) the given column name does not match the
5363      *            name of a column in this rowset, (2) the cursor is not on
5364      *            one of this rowset's rows or its insert row, (3) the data
5365      *            in the stream is not a binary or character type, or (4) this
5366      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5367      */
5368     public void updateCharacterStream(String columnName,
5369     java.io.Reader reader,
5370     int length) throws SQLException {
5371         updateCharacterStream(getColIdxByName(columnName), reader, length);
5372     }
5373 
5374     /**
5375      * Sets the designated column in either the current row or the insert
5376      * row of this <code>CachedRowSetImpl</code> object with the given
5377      * <code>Object</code> value.  The <code>scale</code> parameter
5378      * indicates the number of digits to the right of the decimal point
5379      * and is ignored if the new column value is not a type that will be
5380      *  mapped to an SQL <code>DECIMAL</code> or <code>NUMERIC</code> value.
5381      * <P>
5382      * This method updates a column value in either the current row or
5383      * the insert row of this rowset, but it does not update the
5384      * database.  If the cursor is on a row in the rowset, the
5385      * method {@link #updateRow} must be called to update the database.
5386      * If the cursor is on the insert row, the method {@link #insertRow}
5387      * must be called, which will insert the new row into both this rowset
5388      * and the database. Both of these methods must be called before the
5389      * cursor moves to another row.
5390      *
5391      * @param columnName a <code>String</code> object that must match the
5392      *        SQL name of a column in this rowset, ignoring case
5393      * @param x the new column value
5394      * @param scale the number of digits to the right of the decimal point (for
5395      *              <code>DECIMAL</code> and <code>NUMERIC</code> types only)
5396      * @throws SQLException if (1) the given column name does not match the
5397      *            name of a column in this rowset, (2) the cursor is not on
5398      *            one of this rowset's rows or its insert row, or (3) this
5399      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5400      */
5401     public void updateObject(String columnName, Object x, int scale) throws SQLException {
5402         updateObject(getColIdxByName(columnName), x, scale);
5403     }
5404 
5405     /**
5406      * Sets the designated column in either the current row or the insert
5407      * row of this <code>CachedRowSetImpl</code> object with the given
5408      * <code>Object</code> value.
5409      * <P>
5410      * This method updates a column value in either the current row or
5411      * the insert row of this rowset, but it does not update the
5412      * database.  If the cursor is on a row in the rowset, the
5413      * method {@link #updateRow} must be called to update the database.
5414      * If the cursor is on the insert row, the method {@link #insertRow}
5415      * must be called, which will insert the new row into both this rowset
5416      * and the database. Both of these methods must be called before the
5417      * cursor moves to another row.
5418      *
5419      * @param columnName a <code>String</code> object that must match the
5420      *        SQL name of a column in this rowset, ignoring case
5421      * @param x the new column value
5422      * @throws SQLException if (1) the given column name does not match the
5423      *            name of a column in this rowset, (2) the cursor is not on
5424      *            one of this rowset's rows or its insert row, or (3) this
5425      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5426      */
5427     public void updateObject(String columnName, Object x) throws SQLException {
5428         updateObject(getColIdxByName(columnName), x);
5429     }
5430 
5431     /**
5432      * Inserts the contents of this <code>CachedRowSetImpl</code> object's insert
5433      * row into this rowset immediately following the current row.
5434      * If the current row is the
5435      * position after the last row or before the first row, the new row will
5436      * be inserted at the end of the rowset.  This method also notifies
5437      * listeners registered with this rowset that the row has changed.
5438      * <P>
5439      * The cursor must be on the insert row when this method is called.
5440      *
5441      * @throws SQLException if (1) the cursor is not on the insert row,
5442      *            (2) one or more of the non-nullable columns in the insert
5443      *            row has not been given a value, or (3) this rowset is
5444      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5445      */
5446     public void insertRow() throws SQLException {
5447         int pos;
5448 
5449         if (onInsertRow == false ||
5450             insertRow.isCompleteRow(RowSetMD) == false) {
5451                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.failedins").toString());
5452         }
5453         // Added the setting of parameters that are passed
5454         // to setXXX methods after an empty CRS Object is
5455         // created through RowSetMetaData object
5456         Object [] toInsert = getParams();
5457 
5458         for(int i = 0;i < toInsert.length; i++) {
5459           insertRow.setColumnObject(i+1,toInsert[i]);
5460         }
5461 
5462         Row insRow = new Row(RowSetMD.getColumnCount(),
5463         insertRow.getOrigRow());
5464         insRow.setInserted();
5465         /*
5466          * The new row is inserted into the RowSet
5467          * immediately following the current row.
5468          *
5469          * If we are afterlast then the rows are
5470          * inserted at the end.
5471          */
5472         if (currentRow >= numRows || currentRow < 0) {
5473             pos = numRows;
5474         } else {
5475             pos = currentRow;
5476         }
5477 
5478         rvh.add(pos, insRow);
5479         ++numRows;
5480         // notify the listeners that the row changed.
5481         notifyRowChanged();
5482     }
5483 
5484     /**
5485      * Marks the current row of this <code>CachedRowSetImpl</code> object as
5486      * updated and notifies listeners registered with this rowset that the
5487      * row has changed.
5488      * <P>
5489      * This method  cannot be called when the cursor is on the insert row, and
5490      * it should be called before the cursor moves to another row.  If it is
5491      * called after the cursor moves to another row, this method has no effect,
5492      * and the updates made before the cursor moved will be lost.
5493      *
5494      * @throws SQLException if the cursor is on the insert row or this
5495      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5496      */
5497     public void updateRow() throws SQLException {
5498         // make sure we aren't on the insert row
5499         if (onInsertRow == true) {
5500             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.updateins").toString());
5501         }
5502 
5503         ((Row)getCurrentRow()).setUpdated();
5504 
5505         // notify the listeners that the row changed.
5506         notifyRowChanged();
5507     }
5508 
5509     /**
5510      * Deletes the current row from this <code>CachedRowSetImpl</code> object and
5511      * notifies listeners registered with this rowset that a row has changed.
5512      * This method cannot be called when the cursor is on the insert row.
5513      * <P>
5514      * This method marks the current row as deleted, but it does not delete
5515      * the row from the underlying data source.  The method
5516      * <code>acceptChanges</code> must be called to delete the row in
5517      * the data source.
5518      *
5519      * @throws SQLException if (1) this method is called when the cursor
5520      *            is on the insert row, before the first row, or after the
5521      *            last row or (2) this rowset is
5522      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5523      */
5524     public void deleteRow() throws SQLException {
5525         // make sure the cursor is on a valid row
5526         checkCursor();
5527 
5528         ((Row)getCurrentRow()).setDeleted();
5529         ++numDeleted;
5530 
5531         // notify the listeners that the row changed.
5532         notifyRowChanged();
5533     }
5534 
5535     /**
5536      * Sets the current row with its original value and marks the row as
5537      * not updated, thus undoing any changes made to the row since the
5538      * last call to the methods <code>updateRow</code> or <code>deleteRow</code>.
5539      * This method should be called only when the cursor is on a row in
5540      * this rowset.
5541      *
5542      * @throws SQLException if the cursor is on the insert row, before the
5543      *            first row, or after the last row
5544      */
5545     public void refreshRow() throws SQLException {
5546         // make sure we are on a row
5547         checkCursor();
5548 
5549         // don't want this to happen...
5550         if (onInsertRow == true) {
5551             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
5552         }
5553 
5554         Row currentRow = (Row)getCurrentRow();
5555         // just undo any changes made to this row.
5556         currentRow.clearUpdated();
5557 
5558     }
5559 
5560     /**
5561      * Rolls back any updates made to the current row of this
5562      * <code>CachedRowSetImpl</code> object and notifies listeners that
5563      * a row has changed.  To have an effect, this method
5564      * must be called after an <code>updateXXX</code> method has been
5565      * called and before the method <code>updateRow</code> has been called.
5566      * If no updates have been made or the method <code>updateRow</code>
5567      * has already been called, this method has no effect.
5568      *
5569      * @throws SQLException if the cursor is on the insert row, before the
5570      *            first row, or after the last row
5571      */
5572     public void cancelRowUpdates() throws SQLException {
5573         // make sure we are on a row
5574         checkCursor();
5575 
5576         // don't want this to happen...
5577         if (onInsertRow == true) {
5578             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
5579         }
5580 
5581         Row currentRow = (Row)getCurrentRow();
5582         if (currentRow.getUpdated() == true) {
5583             currentRow.clearUpdated();
5584             notifyRowChanged();
5585         }
5586     }
5587 
5588     /**
5589      * Moves the cursor for this <code>CachedRowSetImpl</code> object
5590      * to the insert row.  The current row in the rowset is remembered
5591      * while the cursor is on the insert row.
5592      * <P>
5593      * The insert row is a special row associated with an updatable
5594      * rowset.  It is essentially a buffer where a new row may
5595      * be constructed by calling the appropriate <code>updateXXX</code>
5596      * methods to assign a value to each column in the row.  A complete
5597      * row must be constructed; that is, every column that is not nullable
5598      * must be assigned a value.  In order for the new row to become part
5599      * of this rowset, the method <code>insertRow</code> must be called
5600      * before the cursor is moved back to the rowset.
5601      * <P>
5602      * Only certain methods may be invoked while the cursor is on the insert
5603      * row; many methods throw an exception if they are called while the
5604      * cursor is there.  In addition to the <code>updateXXX</code>
5605      * and <code>insertRow</code> methods, only the <code>getXXX</code> methods
5606      * may be called when the cursor is on the insert row.  A <code>getXXX</code>
5607      * method should be called on a column only after an <code>updateXXX</code>
5608      * method has been called on that column; otherwise, the value returned is
5609      * undetermined.
5610      *
5611      * @throws SQLException if this <code>CachedRowSetImpl</code> object is
5612      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5613      */
5614     public void moveToInsertRow() throws SQLException {
5615         if (getConcurrency() == ResultSet.CONCUR_READ_ONLY) {
5616             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins").toString());
5617         }
5618         if (insertRow == null) {
5619             if (RowSetMD == null)
5620                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins1").toString());
5621             int numCols = RowSetMD.getColumnCount();
5622             if (numCols > 0) {
5623                 insertRow = new InsertRow(numCols);
5624             } else {
5625                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins2").toString());
5626             }
5627         }
5628         onInsertRow = true;
5629         // %%% setCurrentRow called in BaseRow
5630 
5631         currentRow = cursorPos;
5632         cursorPos = -1;
5633 
5634         insertRow.initInsertRow();
5635     }
5636 
5637     /**
5638      * Moves the cursor for this <code>CachedRowSetImpl</code> object to
5639      * the current row.  The current row is the row the cursor was on
5640      * when the method <code>moveToInsertRow</code> was called.
5641      * <P>
5642      * Calling this method has no effect unless it is called while the
5643      * cursor is on the insert row.
5644      *
5645      * @throws SQLException if an error occurs
5646      */
5647     public void moveToCurrentRow() throws SQLException {
5648         if (onInsertRow == false) {
5649             return;
5650         } else {
5651             cursorPos = currentRow;
5652             onInsertRow = false;
5653         }
5654     }
5655 
5656     /**
5657      * Returns <code>null</code>.
5658      *
5659      * @return <code>null</code>
5660      * @throws SQLException if an error occurs
5661      */
5662     public Statement getStatement() throws SQLException {
5663         return null;
5664     }
5665 
5666     /**
5667      * Retrieves the value of the designated column in this
5668      * <code>CachedRowSetImpl</code> object as an <code>Object</code> in
5669      * the Java programming language, using the given
5670      * <code>java.util.Map</code> object to custom map the value if
5671      * appropriate.
5672      *
5673      * @param columnIndex the first column is <code>1</code>, the second
5674      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5675      *        and equal to or less than the number of columns in this rowset
5676      * @param map a <code>java.util.Map</code> object showing the mapping
5677      *            from SQL type names to classes in the Java programming
5678      *            language
5679      * @return an <code>Object</code> representing the SQL value
5680      * @throws SQLException if the given column index is out of bounds or
5681      *            the cursor is not on one of this rowset's rows or its
5682      *            insert row
5683      */
5684      public Object getObject(int columnIndex,
5685                              java.util.Map<String,Class<?>> map)
5686          throws SQLException
5687      {
5688         Object value;
5689 
5690         // sanity check.
5691         checkIndex(columnIndex);
5692         // make sure the cursor is on a valid row
5693         checkCursor();
5694 
5695         setLastValueNull(false);
5696         value = getCurrentRow().getColumnObject(columnIndex);
5697 
5698         // check for SQL NULL
5699         if (value == null) {
5700             setLastValueNull(true);
5701             return null;
5702         }
5703         if (value instanceof Struct) {
5704             Struct s = (Struct)value;
5705 
5706             // look up the class in the map
5707             Class<?> c = map.get(s.getSQLTypeName());
5708             if (c != null) {
5709                 // create new instance of the class
5710                 SQLData obj = null;
5711                 try {
5712                     ReflectUtil.checkPackageAccess(c);
5713                     obj = (SQLData) c.newInstance();
5714                 } catch(Exception ex) {
5715                     throw new SQLException("Unable to Instantiate: ", ex);
5716                 }
5717                 // get the attributes from the struct
5718                 Object attribs[] = s.getAttributes(map);
5719                 // create the SQLInput "stream"
5720                 SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
5721                 // read the values...
5722                 obj.readSQL(sqlInput, s.getSQLTypeName());
5723                 return (Object)obj;
5724             }
5725         }
5726         return value;
5727     }
5728 
5729     /**
5730      * Retrieves the value of the designated column in this
5731      * <code>CachedRowSetImpl</code> object as a <code>Ref</code> object
5732      * in the Java programming language.
5733      *
5734      * @param columnIndex the first column is <code>1</code>, the second
5735      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5736      *        and equal to or less than the number of columns in this rowset
5737      * @return a <code>Ref</code> object representing an SQL<code> REF</code> value
5738      * @throws SQLException if (1) the given column index is out of bounds,
5739      *            (2) the cursor is not on one of this rowset's rows or its
5740      *            insert row, or (3) the designated column does not store an
5741      *            SQL <code>REF</code> value
5742      * @see #getRef(String)
5743      */
5744     public Ref getRef(int columnIndex) throws SQLException {
5745         Ref value;
5746 
5747         // sanity check.
5748         checkIndex(columnIndex);
5749         // make sure the cursor is on a valid row
5750         checkCursor();
5751 
5752         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.REF) {
5753             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5754         }
5755 
5756         setLastValueNull(false);
5757         value = (Ref)(getCurrentRow().getColumnObject(columnIndex));
5758 
5759         // check for SQL NULL
5760         if (value == null) {
5761             setLastValueNull(true);
5762             return null;
5763         }
5764 
5765         return value;
5766     }
5767 
5768     /**
5769      * Retrieves the value of the designated column in this
5770      * <code>CachedRowSetImpl</code> object as a <code>Blob</code> object
5771      * in the Java programming language.
5772      *
5773      * @param columnIndex the first column is <code>1</code>, the second
5774      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5775      *        and equal to or less than the number of columns in this rowset
5776      * @return a <code>Blob</code> object representing an SQL <code>BLOB</code> value
5777      * @throws SQLException if (1) the given column index is out of bounds,
5778      *            (2) the cursor is not on one of this rowset's rows or its
5779      *            insert row, or (3) the designated column does not store an
5780      *            SQL <code>BLOB</code> value
5781      * @see #getBlob(String)
5782      */
5783     public Blob getBlob(int columnIndex) throws SQLException {
5784         Blob value;
5785 
5786         // sanity check.
5787         checkIndex(columnIndex);
5788         // make sure the cursor is on a valid row
5789         checkCursor();
5790 
5791         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.BLOB) {
5792             System.out.println(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.type").toString(), RowSetMD.getColumnType(columnIndex)));
5793             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5794         }
5795 
5796         setLastValueNull(false);
5797         value = (Blob)(getCurrentRow().getColumnObject(columnIndex));
5798 
5799         // check for SQL NULL
5800         if (value == null) {
5801             setLastValueNull(true);
5802             return null;
5803         }
5804 
5805         return value;
5806     }
5807 
5808     /**
5809      * Retrieves the value of the designated column in this
5810      * <code>CachedRowSetImpl</code> object as a <code>Clob</code> object
5811      * in the Java programming language.
5812      *
5813      * @param columnIndex the first column is <code>1</code>, the second
5814      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5815      *        and equal to or less than the number of columns in this rowset
5816      * @return a <code>Clob</code> object representing an SQL <code>CLOB</code> value
5817      * @throws SQLException if (1) the given column index is out of bounds,
5818      *            (2) the cursor is not on one of this rowset's rows or its
5819      *            insert row, or (3) the designated column does not store an
5820      *            SQL <code>CLOB</code> value
5821      * @see #getClob(String)
5822      */
5823     public Clob getClob(int columnIndex) throws SQLException {
5824         Clob value;
5825 
5826         // sanity check.
5827         checkIndex(columnIndex);
5828         // make sure the cursor is on a valid row
5829         checkCursor();
5830 
5831         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.CLOB) {
5832             System.out.println(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.type").toString(), RowSetMD.getColumnType(columnIndex)));
5833             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5834         }
5835 
5836         setLastValueNull(false);
5837         value = (Clob)(getCurrentRow().getColumnObject(columnIndex));
5838 
5839         // check for SQL NULL
5840         if (value == null) {
5841             setLastValueNull(true);
5842             return null;
5843         }
5844 
5845         return value;
5846     }
5847 
5848     /**
5849      * Retrieves the value of the designated column in this
5850      * <code>CachedRowSetImpl</code> object as an <code>Array</code> object
5851      * in the Java programming language.
5852      *
5853      * @param columnIndex the first column is <code>1</code>, the second
5854      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5855      *        and equal to or less than the number of columns in this rowset
5856      * @return an <code>Array</code> object representing an SQL
5857      *         <code>ARRAY</code> value
5858      * @throws SQLException if (1) the given column index is out of bounds,
5859      *            (2) the cursor is not on one of this rowset's rows or its
5860      *            insert row, or (3) the designated column does not store an
5861      *            SQL <code>ARRAY</code> value
5862      * @see #getArray(String)
5863      */
5864     public Array getArray(int columnIndex) throws SQLException {
5865         java.sql.Array value;
5866 
5867         // sanity check.
5868         checkIndex(columnIndex);
5869         // make sure the cursor is on a valid row
5870         checkCursor();
5871 
5872         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.ARRAY) {
5873             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5874         }
5875 
5876         setLastValueNull(false);
5877         value = (java.sql.Array)(getCurrentRow().getColumnObject(columnIndex));
5878 
5879         // check for SQL NULL
5880         if (value == null) {
5881             setLastValueNull(true);
5882             return null;
5883         }
5884 
5885         return value;
5886     }
5887 
5888     /**
5889      * Retrieves the value of the designated column in this
5890      * <code>CachedRowSetImpl</code> object as an <code>Object</code> in
5891      * the Java programming language, using the given
5892      * <code>java.util.Map</code> object to custom map the value if
5893      * appropriate.
5894      *
5895      * @param columnName a <code>String</code> object that must match the
5896      *        SQL name of a column in this rowset, ignoring case
5897      * @param map a <code>java.util.Map</code> object showing the mapping
5898      *        from SQL type names to classes in the Java programming
5899      *        language
5900      * @return an <code>Object</code> representing the SQL value
5901      * @throws SQLException if the given column name is not the name of
5902      *         a column in this rowset or the cursor is not on one of
5903      *         this rowset's rows or its insert row
5904      */
5905     public Object getObject(String columnName,
5906                             java.util.Map<String,Class<?>> map)
5907     throws SQLException {
5908         return getObject(getColIdxByName(columnName), map);
5909     }
5910 
5911     /**
5912      * Retrieves the value of the designated column in this
5913      * <code>CachedRowSetImpl</code> object as a <code>Ref</code> object
5914      * in the Java programming language.
5915      *
5916      * @param colName a <code>String</code> object that must match the
5917      *        SQL name of a column in this rowset, ignoring case
5918      * @return a <code>Ref</code> object representing an SQL<code> REF</code> value
5919      * @throws SQLException  if (1) the given column name is not the name of
5920      *            a column in this rowset, (2) the cursor is not on one of
5921      *            this rowset's rows or its insert row, or (3) the column value
5922      *            is not an SQL <code>REF</code> value
5923      * @see #getRef(int)
5924      */
5925     public Ref getRef(String colName) throws SQLException {
5926         return getRef(getColIdxByName(colName));
5927     }
5928 
5929     /**
5930      * Retrieves the value of the designated column in this
5931      * <code>CachedRowSetImpl</code> object as a <code>Blob</code> object
5932      * in the Java programming language.
5933      *
5934      * @param colName a <code>String</code> object that must match the
5935      *        SQL name of a column in this rowset, ignoring case
5936      * @return a <code>Blob</code> object representing an SQL <code>BLOB</code> value
5937      * @throws SQLException if (1) the given column name is not the name of
5938      *            a column in this rowset, (2) the cursor is not on one of
5939      *            this rowset's rows or its insert row, or (3) the designated
5940      *            column does not store an SQL <code>BLOB</code> value
5941      * @see #getBlob(int)
5942      */
5943     public Blob getBlob(String colName) throws SQLException {
5944         return getBlob(getColIdxByName(colName));
5945     }
5946 
5947     /**
5948      * Retrieves the value of the designated column in this
5949      * <code>CachedRowSetImpl</code> object as a <code>Clob</code> object
5950      * in the Java programming language.
5951      *
5952      * @param colName a <code>String</code> object that must match the
5953      *        SQL name of a column in this rowset, ignoring case
5954      * @return a <code>Clob</code> object representing an SQL
5955      *         <code>CLOB</code> value
5956      * @throws SQLException if (1) the given column name is not the name of
5957      *            a column in this rowset, (2) the cursor is not on one of
5958      *            this rowset's rows or its insert row, or (3) the designated
5959      *            column does not store an SQL <code>CLOB</code> value
5960      * @see #getClob(int)
5961      */
5962     public Clob getClob(String colName) throws SQLException {
5963         return getClob(getColIdxByName(colName));
5964     }
5965 
5966     /**
5967      * Retrieves the value of the designated column in this
5968      * <code>CachedRowSetImpl</code> object as an <code>Array</code> object
5969      * in the Java programming langugage.
5970      *
5971      * @param colName a <code>String</code> object that must match the
5972      *        SQL name of a column in this rowset, ignoring case
5973      * @return an <code>Array</code> object representing an SQL
5974      *         <code>ARRAY</code> value
5975      * @throws SQLException if (1) the given column name is not the name of
5976      *            a column in this rowset, (2) the cursor is not on one of
5977      *            this rowset's rows or its insert row, or (3) the designated
5978      *            column does not store an SQL <code>ARRAY</code> value
5979      * @see #getArray(int)
5980      */
5981     public Array getArray(String colName) throws SQLException {
5982         return getArray(getColIdxByName(colName));
5983     }
5984 
5985     /**
5986      * Retrieves the value of the designated column in the current row
5987      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Date</code>
5988      * object, using the given <code>Calendar</code> object to construct an
5989      * appropriate millisecond value for the date.
5990      *
5991      * @param columnIndex the first column is <code>1</code>, the second
5992      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5993      *        and equal to or less than the number of columns in the rowset
5994      * @param cal the <code>java.util.Calendar</code> object to use in
5995      *            constructing the date
5996      * @return the column value; if the value is SQL <code>NULL</code>,
5997      *         the result is <code>null</code>
5998      * @throws SQLException if (1) the given column name is not the name of
5999      *            a column in this rowset, (2) the cursor is not on one of
6000      *            this rowset's rows or its insert row, or (3) the designated
6001      *            column does not store an SQL <code>DATE</code> or
6002      *            <code>TIMESTAMP</code> value
6003      */
6004     public java.sql.Date getDate(int columnIndex, Calendar cal) throws SQLException {
6005         Object value;
6006 
6007         // sanity check.
6008         checkIndex(columnIndex);
6009         // make sure the cursor is on a valid row
6010         checkCursor();
6011 
6012         setLastValueNull(false);
6013         value = getCurrentRow().getColumnObject(columnIndex);
6014 
6015         // check for SQL NULL
6016         if (value == null) {
6017             setLastValueNull(true);
6018             return null;
6019         }
6020 
6021         value = convertTemporal(value,
6022         RowSetMD.getColumnType(columnIndex),
6023         java.sql.Types.DATE);
6024 
6025         // create a default calendar
6026         Calendar defaultCal = Calendar.getInstance();
6027         // set this Calendar to the time we have
6028         defaultCal.setTime((java.util.Date)value);
6029 
6030         /*
6031          * Now we can pull the pieces of the date out
6032          * of the default calendar and put them into
6033          * the user provided calendar
6034          */
6035         cal.set(Calendar.YEAR, defaultCal.get(Calendar.YEAR));
6036         cal.set(Calendar.MONTH, defaultCal.get(Calendar.MONTH));
6037         cal.set(Calendar.DAY_OF_MONTH, defaultCal.get(Calendar.DAY_OF_MONTH));
6038 
6039         /*
6040          * This looks a little odd but it is correct -
6041          * Calendar.getTime() returns a Date...
6042          */
6043         return new java.sql.Date(cal.getTime().getTime());
6044     }
6045 
6046     /**
6047      * Retrieves the value of the designated column in the current row
6048      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Date</code>
6049      * object, using the given <code>Calendar</code> object to construct an
6050      * appropriate millisecond value for the date.
6051      *
6052      * @param columnName a <code>String</code> object that must match the
6053      *        SQL name of a column in this rowset, ignoring case
6054      * @param cal the <code>java.util.Calendar</code> object to use in
6055      *            constructing the date
6056      * @return the column value; if the value is SQL <code>NULL</code>,
6057      *         the result is <code>null</code>
6058      * @throws SQLException if (1) the given column name is not the name of
6059      *            a column in this rowset, (2) the cursor is not on one of
6060      *            this rowset's rows or its insert row, or (3) the designated
6061      *            column does not store an SQL <code>DATE</code> or
6062      *            <code>TIMESTAMP</code> value
6063      */
6064     public java.sql.Date getDate(String columnName, Calendar cal) throws SQLException {
6065         return getDate(getColIdxByName(columnName), cal);
6066     }
6067 
6068     /**
6069      * Retrieves the value of the designated column in the current row
6070      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Time</code>
6071      * object, using the given <code>Calendar</code> object to construct an
6072      * appropriate millisecond value for the date.
6073      *
6074      * @param columnIndex the first column is <code>1</code>, the second
6075      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6076      *        and equal to or less than the number of columns in the rowset
6077      * @param cal the <code>java.util.Calendar</code> object to use in
6078      *            constructing the date
6079      * @return the column value; if the value is SQL <code>NULL</code>,
6080      *         the result is <code>null</code>
6081      * @throws SQLException if (1) the given column name is not the name of
6082      *            a column in this rowset, (2) the cursor is not on one of
6083      *            this rowset's rows or its insert row, or (3) the designated
6084      *            column does not store an SQL <code>TIME</code> or
6085      *            <code>TIMESTAMP</code> value
6086      */
6087     public java.sql.Time getTime(int columnIndex, Calendar cal) throws SQLException {
6088         Object value;
6089 
6090         // sanity check.
6091         checkIndex(columnIndex);
6092         // make sure the cursor is on a valid row
6093         checkCursor();
6094 
6095         setLastValueNull(false);
6096         value = getCurrentRow().getColumnObject(columnIndex);
6097 
6098         // check for SQL NULL
6099         if (value == null) {
6100             setLastValueNull(true);
6101             return null;
6102         }
6103 
6104         value = convertTemporal(value,
6105         RowSetMD.getColumnType(columnIndex),
6106         java.sql.Types.TIME);
6107 
6108         // create a default calendar
6109         Calendar defaultCal = Calendar.getInstance();
6110         // set the time in the default calendar
6111         defaultCal.setTime((java.util.Date)value);
6112 
6113         /*
6114          * Now we can pull the pieces of the date out
6115          * of the default calendar and put them into
6116          * the user provided calendar
6117          */
6118         cal.set(Calendar.HOUR_OF_DAY, defaultCal.get(Calendar.HOUR_OF_DAY));
6119         cal.set(Calendar.MINUTE, defaultCal.get(Calendar.MINUTE));
6120         cal.set(Calendar.SECOND, defaultCal.get(Calendar.SECOND));
6121 
6122         return new java.sql.Time(cal.getTime().getTime());
6123     }
6124 
6125     /**
6126      * Retrieves the value of the designated column in the current row
6127      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Time</code>
6128      * object, using the given <code>Calendar</code> object to construct an
6129      * appropriate millisecond value for the date.
6130      *
6131      * @param columnName a <code>String</code> object that must match the
6132      *        SQL name of a column in this rowset, ignoring case
6133      * @param cal the <code>java.util.Calendar</code> object to use in
6134      *            constructing the date
6135      * @return the column value; if the value is SQL <code>NULL</code>,
6136      *         the result is <code>null</code>
6137      * @throws SQLException if (1) the given column name is not the name of
6138      *            a column in this rowset, (2) the cursor is not on one of
6139      *            this rowset's rows or its insert row, or (3) the designated
6140      *            column does not store an SQL <code>TIME</code> or
6141      *            <code>TIMESTAMP</code> value
6142      */
6143     public java.sql.Time getTime(String columnName, Calendar cal) throws SQLException {
6144         return getTime(getColIdxByName(columnName), cal);
6145     }
6146 
6147     /**
6148      * Retrieves the value of the designated column in the current row
6149      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Timestamp</code>
6150      * object, using the given <code>Calendar</code> object to construct an
6151      * appropriate millisecond value for the date.
6152      *
6153      * @param columnIndex the first column is <code>1</code>, the second
6154      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6155      *        and equal to or less than the number of columns in the rowset
6156      * @param cal the <code>java.util.Calendar</code> object to use in
6157      *            constructing the date
6158      * @return the column value; if the value is SQL <code>NULL</code>,
6159      *         the result is <code>null</code>
6160      * @throws SQLException if (1) the given column name is not the name of
6161      *            a column in this rowset, (2) the cursor is not on one of
6162      *            this rowset's rows or its insert row, or (3) the designated
6163      *            column does not store an SQL <code>TIME</code> or
6164      *            <code>TIMESTAMP</code> value
6165      */
6166     public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
6167         Object value;
6168 
6169         // sanity check.
6170         checkIndex(columnIndex);
6171         // make sure the cursor is on a valid row
6172         checkCursor();
6173 
6174         setLastValueNull(false);
6175         value = getCurrentRow().getColumnObject(columnIndex);
6176 
6177         // check for SQL NULL
6178         if (value == null) {
6179             setLastValueNull(true);
6180             return null;
6181         }
6182 
6183         value = convertTemporal(value,
6184         RowSetMD.getColumnType(columnIndex),
6185         java.sql.Types.TIMESTAMP);
6186 
6187         // create a default calendar
6188         Calendar defaultCal = Calendar.getInstance();
6189         // set the time in the default calendar
6190         defaultCal.setTime((java.util.Date)value);
6191 
6192         /*
6193          * Now we can pull the pieces of the date out
6194          * of the default calendar and put them into
6195          * the user provided calendar
6196          */
6197         cal.set(Calendar.YEAR, defaultCal.get(Calendar.YEAR));
6198         cal.set(Calendar.MONTH, defaultCal.get(Calendar.MONTH));
6199         cal.set(Calendar.DAY_OF_MONTH, defaultCal.get(Calendar.DAY_OF_MONTH));
6200         cal.set(Calendar.HOUR_OF_DAY, defaultCal.get(Calendar.HOUR_OF_DAY));
6201         cal.set(Calendar.MINUTE, defaultCal.get(Calendar.MINUTE));
6202         cal.set(Calendar.SECOND, defaultCal.get(Calendar.SECOND));
6203 
6204         return new java.sql.Timestamp(cal.getTime().getTime());
6205     }
6206 
6207     /**
6208      * Retrieves the value of the designated column in the current row
6209      * of this <code>CachedRowSetImpl</code> object as a
6210      * <code>java.sql.Timestamp</code> object, using the given
6211      * <code>Calendar</code> object to construct an appropriate
6212      * millisecond value for the date.
6213      *
6214      * @param columnName a <code>String</code> object that must match the
6215      *        SQL name of a column in this rowset, ignoring case
6216      * @param cal the <code>java.util.Calendar</code> object to use in
6217      *            constructing the date
6218      * @return the column value; if the value is SQL <code>NULL</code>,
6219      *         the result is <code>null</code>
6220      * @throws SQLException if (1) the given column name is not the name of
6221      *            a column in this rowset, (2) the cursor is not on one of
6222      *            this rowset's rows or its insert row, or (3) the designated
6223      *            column does not store an SQL <code>DATE</code>,
6224      *            <code>TIME</code>, or <code>TIMESTAMP</code> value
6225      */
6226     public java.sql.Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException {
6227         return getTimestamp(getColIdxByName(columnName), cal);
6228     }
6229 
6230     /*
6231      * RowSetInternal Interface
6232      */
6233 
6234     /**
6235      * Retrieves the <code>Connection</code> object passed to this
6236      * <code>CachedRowSetImpl</code> object.  This connection may be
6237      * used to populate this rowset with data or to write data back
6238      * to its underlying data source.
6239      *
6240      * @return the <code>Connection</code> object passed to this rowset;
6241      *         may be <code>null</code> if there is no connection
6242      * @throws SQLException if an error occurs
6243      */
6244     public Connection getConnection() throws SQLException{
6245         return conn;
6246     }
6247 
6248     /**
6249      * Sets the metadata for this <code>CachedRowSetImpl</code> object
6250      * with the given <code>RowSetMetaData</code> object.
6251      *
6252      * @param md a <code>RowSetMetaData</code> object instance containing
6253      *            metadata about the columsn in the rowset
6254      * @throws SQLException if invalid meta data is supplied to the
6255      *            rowset
6256      */
6257     public void setMetaData(RowSetMetaData md) throws SQLException {
6258         RowSetMD =(RowSetMetaDataImpl) md;
6259     }
6260 
6261     /**
6262      * Returns a result set containing the original value of the rowset. The
6263      * original value is the state of the <code>CachedRowSetImpl</code> after the
6264      * last population or synchronization (whichever occurred most recently) with
6265      * the data source.
6266      * <p>
6267      * The cursor is positioned before the first row in the result set.
6268      * Only rows contained in the result set returned by <code>getOriginal()</code>
6269      * are said to have an original value.
6270      *
6271      * @return the original result set of the rowset
6272      * @throws SQLException if an error occurs produce the
6273      *           <code>ResultSet</code> object
6274      */
6275     public ResultSet getOriginal() throws SQLException {
6276         CachedRowSetImpl crs = new CachedRowSetImpl();
6277         crs.RowSetMD = RowSetMD;
6278         crs.numRows = numRows;
6279         crs.cursorPos = 0;
6280 
6281         // make sure we don't get someone playing with these
6282         // %%% is this now necessary ???
6283         //crs.setReader(null);
6284         //crs.setWriter(null);
6285         int colCount = RowSetMD.getColumnCount();
6286         Row orig;
6287 
6288         for (Iterator<?> i = rvh.iterator(); i.hasNext();) {
6289             orig = new Row(colCount, ((Row)i.next()).getOrigRow());
6290             crs.rvh.add(orig);
6291         }
6292         return (ResultSet)crs;
6293     }
6294 
6295     /**
6296      * Returns a result set containing the original value of the current
6297      * row only.
6298      * The original value is the state of the <code>CachedRowSetImpl</code> after
6299      * the last population or synchronization (whichever occurred most recently)
6300      * with the data source.
6301      *
6302      * @return the original result set of the row
6303      * @throws SQLException if there is no current row
6304      * @see #setOriginalRow
6305      */
6306     public ResultSet getOriginalRow() throws SQLException {
6307         CachedRowSetImpl crs = new CachedRowSetImpl();
6308         crs.RowSetMD = RowSetMD;
6309         crs.numRows = 1;
6310         crs.cursorPos = 0;
6311         crs.setTypeMap(this.getTypeMap());
6312 
6313         // make sure we don't get someone playing with these
6314         // %%% is this now necessary ???
6315         //crs.setReader(null);
6316         //crs.setWriter(null);
6317 
6318         Row orig = new Row(RowSetMD.getColumnCount(),
6319         getCurrentRow().getOrigRow());
6320 
6321         crs.rvh.add(orig);
6322 
6323         return (ResultSet)crs;
6324 
6325     }
6326 
6327     /**
6328      * Marks the current row in this rowset as being an original row.
6329      *
6330      * @throws SQLException if there is no current row
6331      * @see #getOriginalRow
6332      */
6333     public void setOriginalRow() throws SQLException {
6334         if (onInsertRow == true) {
6335             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
6336         }
6337 
6338         Row row = (Row)getCurrentRow();
6339         makeRowOriginal(row);
6340 
6341         // this can happen if deleted rows are being shown
6342         if (row.getDeleted() == true) {
6343             removeCurrentRow();
6344         }
6345     }
6346 
6347     /**
6348      * Makes the given row of this rowset the original row by clearing any
6349      * settings that mark the row as having been inserted, deleted, or updated.
6350      * This method is called internally by the methods
6351      * <code>setOriginalRow</code>
6352      * and <code>setOriginal</code>.
6353      *
6354      * @param row the row to be made the original row
6355      */
6356     private void makeRowOriginal(Row row) {
6357         if (row.getInserted() == true) {
6358             row.clearInserted();
6359         }
6360 
6361         if (row.getUpdated() == true) {
6362             row.moveCurrentToOrig();
6363         }
6364     }
6365 
6366     /**
6367      * Marks all rows in this rowset as being original rows. Any updates
6368      * made to the rows become the original values for the rowset.
6369      * Calls to the method <code>setOriginal</code> connot be reversed.
6370      *
6371      * @throws SQLException if an error occurs
6372      */
6373     public void setOriginal() throws SQLException {
6374         for (Iterator<?> i = rvh.iterator(); i.hasNext();) {
6375             Row row = (Row)i.next();
6376             makeRowOriginal(row);
6377             // remove deleted rows from the collection.
6378             if (row.getDeleted() == true) {
6379                 i.remove();
6380                 --numRows;
6381             }
6382         }
6383         numDeleted = 0;
6384 
6385         // notify any listeners that the rowset has changed
6386         notifyRowSetChanged();
6387     }
6388 
6389     /**
6390      * Returns an identifier for the object (table) that was used to create this
6391      * rowset.
6392      *
6393      * @return a <code>String</code> object that identifies the table from
6394      *         which this <code>CachedRowSetImpl</code> object was derived
6395      * @throws SQLException if an error occurs
6396      */
6397     public String getTableName() throws SQLException {
6398         return tableName;
6399     }
6400 
6401     /**
6402      * Sets the identifier for the table from which this rowset was derived
6403      * to the given table name.
6404      *
6405      * @param tabName a <code>String</code> object that identifies the
6406      *          table from which this <code>CachedRowSetImpl</code> object
6407      *          was derived
6408      * @throws SQLException if an error occurs
6409      */
6410     public void setTableName(String tabName) throws SQLException {
6411         if (tabName == null)
6412             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.tablename").toString());
6413         else
6414             tableName = tabName;
6415     }
6416 
6417     /**
6418      * Returns the columns that make a key to uniquely identify a
6419      * row in this <code>CachedRowSetImpl</code> object.
6420      *
6421      * @return an array of column numbers that constitutes a primary
6422      *           key for this rowset. This array should be empty
6423      *           if no column is representitive of a primary key
6424      * @throws SQLException if the rowset is empty or no columns
6425      *           are designated as primary keys
6426      * @see #setKeyColumns
6427      */
6428     public int[] getKeyColumns() throws SQLException {
6429         int[]keyColumns  = this.keyCols;
6430         return (keyColumns == null) ? null : Arrays.copyOf(keyColumns, keyColumns.length);
6431     }
6432 
6433 
6434     /**
6435      * Sets this <code>CachedRowSetImpl</code> object's
6436      * <code>keyCols</code> field with the given array of column
6437      * numbers, which forms a key for uniquely identifying a row
6438      * in this rowset.
6439      *
6440      * @param keys an array of <code>int</code> indicating the
6441      *        columns that form a primary key for this
6442      *        <code>CachedRowSetImpl</code> object; every
6443      *        element in the array must be greater than
6444      *        <code>0</code> and less than or equal to the number
6445      *        of columns in this rowset
6446      * @throws SQLException if any of the numbers in the
6447      *            given array is not valid for this rowset
6448      * @see #getKeyColumns
6449      */
6450     public void setKeyColumns(int [] keys) throws SQLException {
6451         int numCols = 0;
6452         if (RowSetMD != null) {
6453             numCols = RowSetMD.getColumnCount();
6454             if (keys.length > numCols)
6455                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.keycols").toString());
6456         }
6457         keyCols = new int[keys.length];
6458         for (int i = 0; i < keys.length; i++) {
6459             if (RowSetMD != null && (keys[i] <= 0 ||
6460             keys[i] > numCols)) {
6461                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcol").toString() +
6462                 keys[i]);
6463             }
6464             keyCols[i] = keys[i];
6465         }
6466     }
6467 
6468     /**
6469      * Sets the designated column in either the current row or the insert
6470      * row of this <code>CachedRowSetImpl</code> object with the given
6471      * <code>Ref</code> value.
6472      *
6473      * This method updates a column value in either the current row or
6474      * the insert row of this rowset, but it does not update the
6475      * database.  If the cursor is on a row in the rowset, the
6476      * method {@link #updateRow} must be called to update the database.
6477      * If the cursor is on the insert row, the method {@link #insertRow}
6478      * must be called, which will insert the new row into both this rowset
6479      * and the database. Both of these methods must be called before the
6480      * cursor moves to another row.
6481      *
6482      * @param columnIndex the first column is <code>1</code>, the second
6483      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6484      *        and equal to or less than the number of columns in this rowset
6485      * @param ref the new column <code>java.sql.Ref</code> value
6486      * @throws SQLException if (1) the given column index is out of bounds,
6487      *        (2) the cursor is not on one of this rowset's rows or its
6488      *        insert row, or (3) this rowset is
6489      *        <code>ResultSet.CONCUR_READ_ONLY</code>
6490      */
6491     public void updateRef(int columnIndex, java.sql.Ref ref) throws SQLException {
6492         // sanity check.
6493         checkIndex(columnIndex);
6494         // make sure the cursor is on a valid row
6495         checkCursor();
6496 
6497         // SerialClob will help in getting the byte array and storing it.
6498         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6499         // or through RowSetMetaData.locatorsUpdatorCopy()
6500         getCurrentRow().setColumnObject(columnIndex, new SerialRef(ref));
6501     }
6502 
6503     /**
6504      * Sets the designated column in either the current row or the insert
6505      * row of this <code>CachedRowSetImpl</code> object with the given
6506      * <code>double</code> value.
6507      *
6508      * This method updates a column value in either the current row or
6509      * the insert row of this rowset, but it does not update the
6510      * database.  If the cursor is on a row in the rowset, the
6511      * method {@link #updateRow} must be called to update the database.
6512      * If the cursor is on the insert row, the method {@link #insertRow}
6513      * must be called, which will insert the new row into both this rowset
6514      * and the database. Both of these methods must be called before the
6515      * cursor moves to another row.
6516      *
6517      * @param columnName a <code>String</code> object that must match the
6518      *        SQL name of a column in this rowset, ignoring case
6519      * @param ref the new column <code>java.sql.Ref</code> value
6520      * @throws SQLException if (1) the given column name does not match the
6521      *        name of a column in this rowset, (2) the cursor is not on
6522      *        one of this rowset's rows or its insert row, or (3) this
6523      *        rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6524      */
6525     public void updateRef(String columnName, java.sql.Ref ref) throws SQLException {
6526         updateRef(getColIdxByName(columnName), ref);
6527     }
6528 
6529     /**
6530      * Sets the designated column in either the current row or the insert
6531      * row of this <code>CachedRowSetImpl</code> object with the given
6532      * <code>double</code> value.
6533      *
6534      * This method updates a column value in either the current row or
6535      * the insert row of this rowset, but it does not update the
6536      * database.  If the cursor is on a row in the rowset, the
6537      * method {@link #updateRow} must be called to update the database.
6538      * If the cursor is on the insert row, the method {@link #insertRow}
6539      * must be called, which will insert the new row into both this rowset
6540      * and the database. Both of these methods must be called before the
6541      * cursor moves to another row.
6542      *
6543      * @param columnIndex the first column is <code>1</code>, the second
6544      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6545      *        and equal to or less than the number of columns in this rowset
6546      * @param c the new column <code>Clob</code> value
6547      * @throws SQLException if (1) the given column index is out of bounds,
6548      *        (2) the cursor is not on one of this rowset's rows or its
6549      *        insert row, or (3) this rowset is
6550      *        <code>ResultSet.CONCUR_READ_ONLY</code>
6551      */
6552     public void updateClob(int columnIndex, Clob c) throws SQLException {
6553         // sanity check.
6554         checkIndex(columnIndex);
6555         // make sure the cursor is on a valid row
6556         checkCursor();
6557 
6558         // SerialClob will help in getting the byte array and storing it.
6559         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6560         // or through RowSetMetaData.locatorsUpdatorCopy()
6561 
6562         if(dbmslocatorsUpdateCopy){
6563            getCurrentRow().setColumnObject(columnIndex, new SerialClob(c));
6564         }
6565         else{
6566            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.opnotsupp").toString());
6567         }
6568     }
6569 
6570     /**
6571      * Sets the designated column in either the current row or the insert
6572      * row of this <code>CachedRowSetImpl</code> object with the given
6573      * <code>double</code> value.
6574      *
6575      * This method updates a column value in either the current row or
6576      * the insert row of this rowset, but it does not update the
6577      * database.  If the cursor is on a row in the rowset, the
6578      * method {@link #updateRow} must be called to update the database.
6579      * If the cursor is on the insert row, the method {@link #insertRow}
6580      * must be called, which will insert the new row into both this rowset
6581      * and the database. Both of these methods must be called before the
6582      * cursor moves to another row.
6583      *
6584      * @param columnName a <code>String</code> object that must match the
6585      *        SQL name of a column in this rowset, ignoring case
6586      * @param c the new column <code>Clob</code> value
6587      * @throws SQLException if (1) the given column name does not match the
6588      *            name of a column in this rowset, (2) the cursor is not on
6589      *            one of this rowset's rows or its insert row, or (3) this
6590      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6591      */
6592     public void updateClob(String columnName, Clob c) throws SQLException {
6593         updateClob(getColIdxByName(columnName), c);
6594     }
6595 
6596     /**
6597      * Sets the designated column in either the current row or the insert
6598      * row of this <code>CachedRowSetImpl</code> object with the given
6599      * <code>java.sql.Blob</code> value.
6600      *
6601      * This method updates a column value in either the current row or
6602      * the insert row of this rowset, but it does not update the
6603      * database.  If the cursor is on a row in the rowset, the
6604      * method {@link #updateRow} must be called to update the database.
6605      * If the cursor is on the insert row, the method {@link #insertRow}
6606      * must be called, which will insert the new row into both this rowset
6607      * and the database. Both of these methods must be called before the
6608      * cursor moves to another row.
6609      *
6610      * @param columnIndex the first column is <code>1</code>, the second
6611      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6612      *        and equal to or less than the number of columns in this rowset
6613      * @param b the new column <code>Blob</code> value
6614      * @throws SQLException if (1) the given column index is out of bounds,
6615      *            (2) the cursor is not on one of this rowset's rows or its
6616      *            insert row, or (3) this rowset is
6617      *            <code>ResultSet.CONCUR_READ_ONLY</code>
6618      */
6619     public void updateBlob(int columnIndex, Blob b) throws SQLException {
6620         // sanity check.
6621         checkIndex(columnIndex);
6622         // make sure the cursor is on a valid row
6623         checkCursor();
6624 
6625         // SerialBlob will help in getting the byte array and storing it.
6626         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6627         // or through RowSetMetaData.locatorsUpdatorCopy()
6628 
6629         if(dbmslocatorsUpdateCopy){
6630            getCurrentRow().setColumnObject(columnIndex, new SerialBlob(b));
6631         }
6632         else{
6633            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.opnotsupp").toString());
6634         }
6635     }
6636 
6637     /**
6638      * Sets the designated column in either the current row or the insert
6639      * row of this <code>CachedRowSetImpl</code> object with the given
6640      * <code>java.sql.Blob </code> value.
6641      *
6642      * This method updates a column value in either the current row or
6643      * the insert row of this rowset, but it does not update the
6644      * database.  If the cursor is on a row in the rowset, the
6645      * method {@link #updateRow} must be called to update the database.
6646      * If the cursor is on the insert row, the method {@link #insertRow}
6647      * must be called, which will insert the new row into both this rowset
6648      * and the database. Both of these methods must be called before the
6649      * cursor moves to another row.
6650      *
6651      * @param columnName a <code>String</code> object that must match the
6652      *        SQL name of a column in this rowset, ignoring case
6653      * @param b the new column <code>Blob</code> value
6654      * @throws SQLException if (1) the given column name does not match the
6655      *            name of a column in this rowset, (2) the cursor is not on
6656      *            one of this rowset's rows or its insert row, or (3) this
6657      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6658      */
6659     public void updateBlob(String columnName, Blob b) throws SQLException {
6660         updateBlob(getColIdxByName(columnName), b);
6661     }
6662 
6663     /**
6664      * Sets the designated column in either the current row or the insert
6665      * row of this <code>CachedRowSetImpl</code> object with the given
6666      * <code>java.sql.Array</code> values.
6667      *
6668      * This method updates a column value in either the current row or
6669      * the insert row of this rowset, but it does not update the
6670      * database.  If the cursor is on a row in the rowset, the
6671      * method {@link #updateRow} must be called to update the database.
6672      * If the cursor is on the insert row, the method {@link #insertRow}
6673      * must be called, which will insert the new row into both this rowset
6674      * and the database. Both of these methods must be called before the
6675      * cursor moves to another row.
6676      *
6677      * @param columnIndex the first column is <code>1</code>, the second
6678      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6679      *        and equal to or less than the number of columns in this rowset
6680      * @param a the new column <code>Array</code> value
6681      * @throws SQLException if (1) the given column index is out of bounds,
6682      *            (2) the cursor is not on one of this rowset's rows or its
6683      *            insert row, or (3) this rowset is
6684      *            <code>ResultSet.CONCUR_READ_ONLY</code>
6685      */
6686     public void updateArray(int columnIndex, Array a) throws SQLException {
6687         // sanity check.
6688         checkIndex(columnIndex);
6689         // make sure the cursor is on a valid row
6690         checkCursor();
6691 
6692         // SerialArray will help in getting the byte array and storing it.
6693         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6694         // or through RowSetMetaData.locatorsUpdatorCopy()
6695         getCurrentRow().setColumnObject(columnIndex, new SerialArray(a));
6696     }
6697 
6698     /**
6699      * Sets the designated column in either the current row or the insert
6700      * row of this <code>CachedRowSetImpl</code> object with the given
6701      * <code>java.sql.Array</code> value.
6702      *
6703      * This method updates a column value in either the current row or
6704      * the insert row of this rowset, but it does not update the
6705      * database.  If the cursor is on a row in the rowset, the
6706      * method {@link #updateRow} must be called to update the database.
6707      * If the cursor is on the insert row, the method {@link #insertRow}
6708      * must be called, which will insert the new row into both this rowset
6709      * and the database. Both of these methods must be called before the
6710      * cursor moves to another row.
6711      *
6712      * @param columnName a <code>String</code> object that must match the
6713      *        SQL name of a column in this rowset, ignoring case
6714      * @param a the new column <code>Array</code> value
6715      * @throws SQLException if (1) the given column name does not match the
6716      *            name of a column in this rowset, (2) the cursor is not on
6717      *            one of this rowset's rows or its insert row, or (3) this
6718      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6719      */
6720     public void updateArray(String columnName, Array a) throws SQLException {
6721         updateArray(getColIdxByName(columnName), a);
6722     }
6723 
6724 
6725     /**
6726      * Retrieves the value of the designated column in this
6727      * <code>CachedRowSetImpl</code> object as a <code>java.net.URL</code> object
6728      * in the Java programming language.
6729      *
6730      * @return a java.net.URL object containing the resource reference described by
6731      * the URL
6732      * @throws SQLException if (1) the given column index is out of bounds,
6733      * (2) the cursor is not on one of this rowset's rows or its
6734      * insert row, or (3) the designated column does not store an
6735      * SQL <code>DATALINK</code> value.
6736      * @see #getURL(String)
6737      */
6738     public java.net.URL getURL(int columnIndex) throws SQLException {
6739         //throw new SQLException("Operation not supported");
6740 
6741         java.net.URL value;
6742 
6743         // sanity check.
6744         checkIndex(columnIndex);
6745         // make sure the cursor is on a valid row
6746         checkCursor();
6747 
6748         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.DATALINK) {
6749             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
6750         }
6751 
6752         setLastValueNull(false);
6753         value = (java.net.URL)(getCurrentRow().getColumnObject(columnIndex));
6754 
6755         // check for SQL NULL
6756         if (value == null) {
6757             setLastValueNull(true);
6758             return null;
6759         }
6760 
6761         return value;
6762     }
6763 
6764     /**
6765      * Retrieves the value of the designated column in this
6766      * <code>CachedRowSetImpl</code> object as a <code>java.net.URL</code> object
6767      * in the Java programming language.
6768      *
6769      * @return a java.net.URL object containing the resource reference described by
6770      * the URL
6771      * @throws SQLException if (1) the given column name not the name of a column
6772      * in this rowset, or
6773      * (2) the cursor is not on one of this rowset's rows or its
6774      * insert row, or (3) the designated column does not store an
6775      * SQL <code>DATALINK</code> value.
6776      * @see #getURL(int)
6777      */
6778     public java.net.URL getURL(String columnName) throws SQLException {
6779         return getURL(getColIdxByName(columnName));
6780 
6781     }
6782 
6783     /**
6784      * The first warning reported by calls on this <code>CachedRowSetImpl</code>
6785      * object is returned. Subsequent <code>CachedRowSetImpl</code> warnings will
6786      * be chained to this <code>SQLWarning</code>. All <code>RowSetWarnings</code>
6787      * warnings are generated in the disconnected environment and remain a
6788      * seperate warning chain to that provided by the <code>getWarnings</code>
6789      * method.
6790      *
6791      * <P>The warning chain is automatically cleared each time a new
6792      * row is read.
6793      *
6794      * <P><B>Note:</B> This warning chain only covers warnings caused
6795      * by <code>CachedRowSet</code> (and their child interface)
6796      * methods. All <code>SQLWarnings</code> can be obtained using the
6797      * <code>getWarnings</code> method which tracks warnings generated
6798      * by the underlying JDBC driver.
6799      * @return the first SQLWarning or null
6800      *
6801      */
6802     public RowSetWarning getRowSetWarnings() {
6803         try {
6804             notifyCursorMoved();
6805         } catch (SQLException e) {} // mask exception
6806         return rowsetWarning;
6807     }
6808 
6809 
6810     /**
6811      * The function tries to isolate the tablename when only setCommand
6812      * is set and not setTablename is called provided there is only one table
6813      * name in the query else just leaves the setting of table name as such.
6814      * If setTablename is set later it will over ride this table name
6815      * value so retrieved.
6816      *
6817      * @return the tablename if only one table in query else return ""
6818      */
6819     private String buildTableName(String command) throws SQLException {
6820 
6821         // If we have a query from one table,
6822         // we set the table name implicitly
6823         // else user has to explicitly set the table name.
6824 
6825         int indexFrom, indexComma;
6826         String strTablename ="";
6827         command = command.trim();
6828 
6829         // Query can be a select, insert or  update
6830 
6831         if(command.toLowerCase().startsWith("select")) {
6832             // look for "from" keyword, after that look for a
6833             // comma after from. If comma is there don't set
6834             // table name else isolate table name.
6835 
6836             indexFrom = command.toLowerCase().indexOf("from");
6837             indexComma = command.indexOf(',', indexFrom);
6838 
6839             if(indexComma == -1) {
6840                 // implies only one table
6841                 strTablename = (command.substring(indexFrom+"from".length(),command.length())).trim();
6842 
6843                 String tabName = strTablename;
6844 
6845                 int idxWhere = tabName.toLowerCase().indexOf("where");
6846 
6847                 /**
6848                   * Adding the addtional check for conditions following the table name.
6849                   * If a condition is found truncate it.
6850                   **/
6851 
6852                 if(idxWhere != -1)
6853                 {
6854                    tabName = tabName.substring(0,idxWhere).trim();
6855                 }
6856 
6857                 strTablename = tabName;
6858 
6859             } else {
6860                 //strTablename="";
6861             }
6862 
6863         } else if(command.toLowerCase().startsWith("insert")) {
6864             //strTablename="";
6865         } else if(command.toLowerCase().startsWith("update")) {
6866             //strTablename="";
6867         }
6868         return strTablename;
6869     }
6870 
6871     /**
6872      * Commits all changes performed by the <code>acceptChanges()</code>
6873      * methods
6874      *
6875      * @see java.sql.Connection#commit
6876      */
6877     public void commit() throws SQLException {
6878         conn.commit();
6879     }
6880 
6881     /**
6882      * Rolls back all changes performed by the <code>acceptChanges()</code>
6883      * methods
6884      *
6885      * @see java.sql.Connection#rollback
6886      */
6887     public void rollback() throws SQLException {
6888         conn.rollback();
6889     }
6890 
6891     /**
6892      * Rolls back all changes performed by the <code>acceptChanges()</code>
6893      * to the last <code>Savepoint</code> transaction marker.
6894      *
6895      * @see java.sql.Connection#rollback(Savepoint)
6896      */
6897     public void rollback(Savepoint s) throws SQLException {
6898         conn.rollback(s);
6899     }
6900 
6901     /**
6902      * Unsets the designated parameter to the given int array.
6903      * This was set using <code>setMatchColumn</code>
6904      * as the column which will form the basis of the join.
6905      * <P>
6906      * The parameter value unset by this method should be same
6907      * as was set.
6908      *
6909      * @param columnIdxes the index into this rowset
6910      *        object's internal representation of parameter values
6911      * @throws SQLException if an error occurs or the
6912      *  parameter index is out of bounds or if the columnIdx is
6913      *  not the same as set using <code>setMatchColumn(int [])</code>
6914      */
6915     public void unsetMatchColumn(int[] columnIdxes) throws SQLException {
6916 
6917          int i_val;
6918          for( int j= 0 ;j < columnIdxes.length; j++) {
6919             i_val = (Integer.parseInt(iMatchColumns.get(j).toString()));
6920             if(columnIdxes[j] != i_val) {
6921                throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols").toString());
6922             }
6923          }
6924 
6925          for( int i = 0;i < columnIdxes.length ;i++) {
6926             iMatchColumns.set(i, -1);
6927          }
6928     }
6929 
6930    /**
6931      * Unsets the designated parameter to the given String array.
6932      * This was set using <code>setMatchColumn</code>
6933      * as the column which will form the basis of the join.
6934      * <P>
6935      * The parameter value unset by this method should be same
6936      * as was set.
6937      *
6938      * @param columnIdxes the index into this rowset
6939      *        object's internal representation of parameter values
6940      * @throws SQLException if an error occurs or the
6941      *  parameter index is out of bounds or if the columnName is
6942      *  not the same as set using <code>setMatchColumn(String [])</code>
6943      */
6944     public void unsetMatchColumn(String[] columnIdxes) throws SQLException {
6945 
6946         for(int j = 0 ;j < columnIdxes.length; j++) {
6947            if( !columnIdxes[j].equals(strMatchColumns.get(j)) ){
6948               throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols").toString());
6949            }
6950         }
6951 
6952         for(int i = 0 ; i < columnIdxes.length; i++) {
6953            strMatchColumns.set(i,null);
6954         }
6955     }
6956 
6957     /**
6958      * Retrieves the column name as <code>String</code> array
6959      * that was set using <code>setMatchColumn(String [])</code>
6960      * for this rowset.
6961      *
6962      * @return a <code>String</code> array object that contains the column names
6963      *         for the rowset which has this the match columns
6964      *
6965      * @throws SQLException if an error occurs or column name is not set
6966      */
6967     public String[] getMatchColumnNames() throws SQLException {
6968 
6969         String []str_temp = new String[strMatchColumns.size()];
6970 
6971         if( strMatchColumns.get(0) == null) {
6972            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.setmatchcols").toString());
6973         }
6974 
6975         strMatchColumns.copyInto(str_temp);
6976         return str_temp;
6977     }
6978 
6979     /**
6980      * Retrieves the column id as <code>int</code> array that was set using
6981      * <code>setMatchColumn(int [])</code> for this rowset.
6982      *
6983      * @return a <code>int</code> array object that contains the column ids
6984      *         for the rowset which has this as the match columns.
6985      *
6986      * @throws SQLException if an error occurs or column index is not set
6987      */
6988     public int[] getMatchColumnIndexes() throws SQLException {
6989 
6990         Integer []int_temp = new Integer[iMatchColumns.size()];
6991         int [] i_temp = new int[iMatchColumns.size()];
6992         int i_val;
6993 
6994         i_val = iMatchColumns.get(0);
6995 
6996         if( i_val == -1 ) {
6997            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.setmatchcols").toString());
6998         }
6999 
7000 
7001         iMatchColumns.copyInto(int_temp);
7002 
7003         for(int i = 0; i < int_temp.length; i++) {
7004            i_temp[i] = (int_temp[i]).intValue();
7005         }
7006 
7007         return i_temp;
7008     }
7009 
7010     /**
7011      * Sets the designated parameter to the given int array.
7012      * This forms the basis of the join for the
7013      * <code>JoinRowSet</code> as the column which will form the basis of the
7014      * join.
7015      * <P>
7016      * The parameter value set by this method is stored internally and
7017      * will be supplied as the appropriate parameter in this rowset's
7018      * command when the method <code>getMatchColumnIndexes</code> is called.
7019      *
7020      * @param columnIdxes the indexes into this rowset
7021      *        object's internal representation of parameter values; the
7022      *        first parameter is 0, the second is 1, and so on; must be
7023      *        <code>0</code> or greater
7024      * @throws SQLException if an error occurs or the
7025      *                         parameter index is out of bounds
7026      */
7027     public void setMatchColumn(int[] columnIdxes) throws SQLException {
7028 
7029         for(int j = 0 ; j < columnIdxes.length; j++) {
7030            if( columnIdxes[j] < 0 ) {
7031               throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols1").toString());
7032            }
7033         }
7034         for(int i = 0 ;i < columnIdxes.length; i++) {
7035            iMatchColumns.add(i,columnIdxes[i]);
7036         }
7037     }
7038 
7039     /**
7040      * Sets the designated parameter to the given String array.
7041      *  This forms the basis of the join for the
7042      * <code>JoinRowSet</code> as the column which will form the basis of the
7043      * join.
7044      * <P>
7045      * The parameter value set by this method is stored internally and
7046      * will be supplied as the appropriate parameter in this rowset's
7047      * command when the method <code>getMatchColumn</code> is called.
7048      *
7049      * @param columnNames the name of the column into this rowset
7050      *        object's internal representation of parameter values
7051      * @throws SQLException if an error occurs or the
7052      *  parameter index is out of bounds
7053      */
7054     public void setMatchColumn(String[] columnNames) throws SQLException {
7055 
7056         for(int j = 0; j < columnNames.length; j++) {
7057            if( columnNames[j] == null || columnNames[j].equals("")) {
7058               throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols2").toString());
7059            }
7060         }
7061         for( int i = 0; i < columnNames.length; i++) {
7062            strMatchColumns.add(i,columnNames[i]);
7063         }
7064     }
7065 
7066 
7067     /**
7068      * Sets the designated parameter to the given <code>int</code>
7069      * object.  This forms the basis of the join for the
7070      * <code>JoinRowSet</code> as the column which will form the basis of the
7071      * join.
7072      * <P>
7073      * The parameter value set by this method is stored internally and
7074      * will be supplied as the appropriate parameter in this rowset's
7075      * command when the method <code>getMatchColumn</code> is called.
7076      *
7077      * @param columnIdx the index into this rowset
7078      *        object's internal representation of parameter values; the
7079      *        first parameter is 0, the second is 1, and so on; must be
7080      *        <code>0</code> or greater
7081      * @throws SQLException if an error occurs or the
7082      *                         parameter index is out of bounds
7083      */
7084     public void setMatchColumn(int columnIdx) throws SQLException {
7085         // validate, if col is ok to be set
7086         if(columnIdx < 0) {
7087             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols1").toString());
7088         } else {
7089             // set iMatchColumn
7090             iMatchColumns.set(0, columnIdx);
7091             //strMatchColumn = null;
7092         }
7093     }
7094 
7095     /**
7096      * Sets the designated parameter to the given <code>String</code>
7097      * object.  This forms the basis of the join for the
7098      * <code>JoinRowSet</code> as the column which will form the basis of the
7099      * join.
7100      * <P>
7101      * The parameter value set by this method is stored internally and
7102      * will be supplied as the appropriate parameter in this rowset's
7103      * command when the method <code>getMatchColumn</code> is called.
7104      *
7105      * @param columnName the name of the column into this rowset
7106      *        object's internal representation of parameter values
7107      * @throws SQLException if an error occurs or the
7108      *  parameter index is out of bounds
7109      */
7110     public void setMatchColumn(String columnName) throws SQLException {
7111         // validate, if col is ok to be set
7112         if(columnName == null || (columnName= columnName.trim()).equals("") ) {
7113             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols2").toString());
7114         } else {
7115             // set strMatchColumn
7116             strMatchColumns.set(0, columnName);
7117             //iMatchColumn = -1;
7118         }
7119     }
7120 
7121     /**
7122      * Unsets the designated parameter to the given <code>int</code>
7123      * object.  This was set using <code>setMatchColumn</code>
7124      * as the column which will form the basis of the join.
7125      * <P>
7126      * The parameter value unset by this method should be same
7127      * as was set.
7128      *
7129      * @param columnIdx the index into this rowset
7130      *        object's internal representation of parameter values
7131      * @throws SQLException if an error occurs or the
7132      *  parameter index is out of bounds or if the columnIdx is
7133      *  not the same as set using <code>setMatchColumn(int)</code>
7134      */
7135     public void unsetMatchColumn(int columnIdx) throws SQLException {
7136         // check if we are unsetting the SAME column
7137         if(! iMatchColumns.get(0).equals(Integer.valueOf(columnIdx) )  ) {
7138             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch").toString());
7139         } else if(strMatchColumns.get(0) != null) {
7140             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch1").toString());
7141         } else {
7142                 // that is, we are unsetting it.
7143                iMatchColumns.set(0, -1);
7144         }
7145     }
7146 
7147     /**
7148      * Unsets the designated parameter to the given <code>String</code>
7149      * object.  This was set using <code>setMatchColumn</code>
7150      * as the column which will form the basis of the join.
7151      * <P>
7152      * The parameter value unset by this method should be same
7153      * as was set.
7154      *
7155      * @param columnName the index into this rowset
7156      *        object's internal representation of parameter values
7157      * @throws SQLException if an error occurs or the
7158      *  parameter index is out of bounds or if the columnName is
7159      *  not the same as set using <code>setMatchColumn(String)</code>
7160      */
7161     public void unsetMatchColumn(String columnName) throws SQLException {
7162         // check if we are unsetting the same column
7163         columnName = columnName.trim();
7164 
7165         if(!((strMatchColumns.get(0)).equals(columnName))) {
7166             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch").toString());
7167         } else if(iMatchColumns.get(0) > 0) {
7168             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch2").toString());
7169         } else {
7170             strMatchColumns.set(0, null);   // that is, we are unsetting it.
7171         }
7172     }
7173 
7174     /**
7175      * Notifies registered listeners that a RowSet object in the given RowSetEvent
7176      * object has populated a number of additional rows. The <code>numRows</code> parameter
7177      * ensures that this event will only be fired every <code>numRow</code>.
7178      * <p>
7179      * The source of the event can be retrieved with the method event.getSource.
7180      *
7181      * @param event a <code>RowSetEvent</code> object that contains the
7182      *     <code>RowSet</code> object that is the source of the events
7183      * @param numRows when populating, the number of rows interval on which the
7184      *     <code>CachedRowSet</code> populated should fire; the default value
7185      *     is zero; cannot be less than <code>fetchSize</code> or zero
7186      */
7187     public void rowSetPopulated(RowSetEvent event, int numRows) throws SQLException {
7188 
7189         if( numRows < 0 || numRows < getFetchSize()) {
7190            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.numrows").toString());
7191         }
7192 
7193         if(size() % numRows == 0) {
7194             RowSetEvent event_temp = new RowSetEvent(this);
7195             event = event_temp;
7196             notifyRowSetChanged();
7197         }
7198     }
7199 
7200     /**
7201      * Populates this <code>CachedRowSet</code> object with data from
7202      * the given <code>ResultSet</code> object. While related to the <code>populate(ResultSet)</code>
7203      * method, an additional parameter is provided to allow starting position within
7204      * the <code>ResultSet</code> from where to populate the CachedRowSet
7205      * instance.
7206      *
7207      * This method is an alternative to the method <code>execute</code>
7208      * for filling the rowset with data.  The method <code>populate</code>
7209      * does not require that the properties needed by the method
7210      * <code>execute</code>, such as the <code>command</code> property,
7211      * be set. This is true because the method <code>populate</code>
7212      * is given the <code>ResultSet</code> object from
7213      * which to get data and thus does not need to use the properties
7214      * required for setting up a connection and executing this
7215      * <code>CachedRowSetImpl</code> object's command.
7216      * <P>
7217      * After populating this rowset with data, the method
7218      * <code>populate</code> sets the rowset's metadata and
7219      * then sends a <code>RowSetChangedEvent</code> object
7220      * to all registered listeners prior to returning.
7221      *
7222      * @param data the <code>ResultSet</code> object containing the data
7223      *             to be read into this <code>CachedRowSetImpl</code> object
7224      * @param start the integer specifing the position in the
7225      *        <code>ResultSet</code> object to popultate the
7226      *        <code>CachedRowSetImpl</code> object.
7227      * @throws SQLException if an error occurs; or the max row setting is
7228      *          violated while populating the RowSet.Also id the start position
7229      *          is negative.
7230      * @see #execute
7231      */
7232      public void populate(ResultSet data, int start) throws SQLException{
7233 
7234         int rowsFetched;
7235         Row currentRow;
7236         int numCols;
7237         int i;
7238         Map<String, Class<?>> map = getTypeMap();
7239         Object obj;
7240         int mRows;
7241 
7242         cursorPos = 0;
7243         if(populatecallcount == 0){
7244             if(start < 0){
7245                throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.startpos").toString());
7246             }
7247             if(getMaxRows() == 0){
7248                data.absolute(start);
7249                while(data.next()){
7250                    totalRows++;
7251                }
7252                totalRows++;
7253             }
7254             startPos = start;
7255         }
7256         populatecallcount = populatecallcount +1;
7257         resultSet = data;
7258         if((endPos - startPos) >= getMaxRows() && (getMaxRows() > 0)){
7259             endPos = prevEndPos;
7260             pagenotend = false;
7261             return;
7262         }
7263 
7264         if((maxRowsreached != getMaxRows() || maxRowsreached != totalRows) && pagenotend) {
7265            startPrev = start - getPageSize();
7266         }
7267 
7268         if( pageSize == 0){
7269            prevEndPos = endPos;
7270            endPos = start + getMaxRows() ;
7271         }
7272         else{
7273             prevEndPos = endPos;
7274             endPos = start + getPageSize();
7275         }
7276 
7277 
7278         if (start == 1){
7279             resultSet.beforeFirst();
7280         }
7281         else {
7282             resultSet.absolute(start -1);
7283         }
7284         if( pageSize == 0) {
7285            rvh = new Vector<Object>(getMaxRows());
7286 
7287         }
7288         else{
7289             rvh = new Vector<Object>(getPageSize());
7290         }
7291 
7292         if (data == null) {
7293             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.populate").toString());
7294         }
7295 
7296         // get the meta data for this ResultSet
7297         RSMD = data.getMetaData();
7298 
7299         // set up the metadata
7300         RowSetMD = new RowSetMetaDataImpl();
7301         initMetaData(RowSetMD, RSMD);
7302 
7303         // release the meta-data so that aren't tempted to use it.
7304         RSMD = null;
7305         numCols = RowSetMD.getColumnCount();
7306         mRows = this.getMaxRows();
7307         rowsFetched = 0;
7308         currentRow = null;
7309 
7310         if(!data.next() && mRows == 0){
7311             endPos = prevEndPos;
7312             pagenotend = false;
7313             return;
7314         }
7315 
7316         data.previous();
7317 
7318         while ( data.next()) {
7319 
7320             currentRow = new Row(numCols);
7321           if(pageSize == 0){
7322             if ( rowsFetched >= mRows && mRows > 0) {
7323                 rowsetWarning.setNextException(new SQLException("Populating rows "
7324                 + "setting has exceeded max row setting"));
7325                 break;
7326             }
7327           }
7328           else {
7329               if ( (rowsFetched >= pageSize) ||( maxRowsreached >= mRows && mRows > 0)) {
7330                 rowsetWarning.setNextException(new SQLException("Populating rows "
7331                 + "setting has exceeded max row setting"));
7332                 break;
7333             }
7334           }
7335 
7336             for ( i = 1; i <= numCols; i++) {
7337                 /*
7338                  * check if the user has set a map. If no map
7339                  * is set then use plain getObject. This lets
7340                  * us work with drivers that do not support
7341                  * getObject with a map in fairly sensible way
7342                  */
7343                 if (map == null) {
7344                     obj = data.getObject(i);
7345                 } else {
7346                     obj = data.getObject(i, map);
7347                 }
7348                 /*
7349                  * the following block checks for the various
7350                  * types that we have to serialize in order to
7351                  * store - right now only structs have been tested
7352                  */
7353                 if (obj instanceof Struct) {
7354                     obj = new SerialStruct((Struct)obj, map);
7355                 } else if (obj instanceof SQLData) {
7356                     obj = new SerialStruct((SQLData)obj, map);
7357                 } else if (obj instanceof Blob) {
7358                     obj = new SerialBlob((Blob)obj);
7359                 } else if (obj instanceof Clob) {
7360                     obj = new SerialClob((Clob)obj);
7361                 } else if (obj instanceof java.sql.Array) {
7362                     obj = new SerialArray((java.sql.Array)obj, map);
7363                 }
7364 
7365                 currentRow.initColumnObject(i, obj);
7366             }
7367             rowsFetched++;
7368             maxRowsreached++;
7369             rvh.add(currentRow);
7370         }
7371         numRows = rowsFetched ;
7372         // Also rowsFetched should be equal to rvh.size()
7373         // notify any listeners that the rowset has changed
7374         notifyRowSetChanged();
7375 
7376      }
7377 
7378     /**
7379      * The nextPage gets the next page, that is a <code>CachedRowSetImpl</code> object
7380      * containing the number of rows specified by page size.
7381      * @return boolean value true indicating whether there are more pages to come and
7382      *         false indicating that this is the last page.
7383      * @throws SQLException if an error occurs or this called before calling populate.
7384      */
7385      public boolean nextPage() throws SQLException {
7386 
7387          if (populatecallcount == 0){
7388              throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.nextpage").toString());
7389          }
7390          // Fix for 6554186
7391          onFirstPage = false;
7392          if(callWithCon){
7393             crsReader.setStartPosition(endPos);
7394             crsReader.readData((RowSetInternal)this);
7395             resultSet = null;
7396          }
7397          else {
7398             populate(resultSet,endPos);
7399          }
7400          return pagenotend;
7401      }
7402 
7403     /**
7404      * This is the setter function for setting the size of the page, which specifies
7405      * how many rows have to be retrived at a time.
7406      *
7407      * @param size which is the page size
7408      * @throws SQLException if size is less than zero or greater than max rows.
7409      */
7410      public void setPageSize (int size) throws SQLException {
7411         if (size < 0) {
7412             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.pagesize").toString());
7413         }
7414         if (size > getMaxRows() && getMaxRows() != 0) {
7415             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.pagesize1").toString());
7416         }
7417         pageSize = size;
7418      }
7419 
7420     /**
7421      * This is the getter function for the size of the page.
7422      *
7423      * @return an integer that is the page size.
7424      */
7425     public int getPageSize() {
7426         return pageSize;
7427     }
7428 
7429 
7430     /**
7431      * Retrieves the data present in the page prior to the page from where it is
7432      * called.
7433      * @return boolean value true if it retrieves the previous page, flase if it
7434      *         is on the first page.
7435      * @throws SQLException if it is called before populate is called or ResultSet
7436      *         is of type <code>ResultSet.TYPE_FORWARD_ONLY</code> or if an error
7437      *         occurs.
7438      */
7439     public boolean previousPage() throws SQLException {
7440         int pS;
7441         int mR;
7442         int rem;
7443 
7444         pS = getPageSize();
7445         mR = maxRowsreached;
7446 
7447         if (populatecallcount == 0){
7448              throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.nextpage").toString());
7449          }
7450 
7451         if( !callWithCon){
7452            if(resultSet.getType() == ResultSet.TYPE_FORWARD_ONLY){
7453                throw new SQLException (resBundle.handleGetObject("cachedrowsetimpl.fwdonly").toString());
7454            }
7455         }
7456 
7457         pagenotend = true;
7458 
7459         if(startPrev < startPos ){
7460                 onFirstPage = true;
7461                return false;
7462             }
7463 
7464         if(onFirstPage){
7465             return false;
7466         }
7467 
7468         rem = mR % pS;
7469 
7470         if(rem == 0){
7471             maxRowsreached -= (2 * pS);
7472             if(callWithCon){
7473                 crsReader.setStartPosition(startPrev);
7474                 crsReader.readData((RowSetInternal)this);
7475                 resultSet = null;
7476             }
7477             else {
7478                populate(resultSet,startPrev);
7479             }
7480             return true;
7481         }
7482         else
7483         {
7484             maxRowsreached -= (pS + rem);
7485             if(callWithCon){
7486                 crsReader.setStartPosition(startPrev);
7487                 crsReader.readData((RowSetInternal)this);
7488                 resultSet = null;
7489             }
7490             else {
7491                populate(resultSet,startPrev);
7492             }
7493             return true;
7494         }
7495     }
7496 
7497     /**
7498      * Goes to the page number passed as the parameter
7499      * @param page , the page loaded on a call to this function
7500      * @return true if the page exists false otherwise
7501      * @throws SQLException if an error occurs
7502      */
7503     /*
7504     public boolean absolutePage(int page) throws SQLException{
7505 
7506         boolean isAbs = true, retVal = true;
7507         int counter;
7508 
7509         if( page <= 0 ){
7510             throw new SQLException("Absolute positoin is invalid");
7511         }
7512         counter = 0;
7513 
7514         firstPage();
7515         counter++;
7516         while((counter < page) && isAbs) {
7517             isAbs = nextPage();
7518             counter ++;
7519         }
7520 
7521         if( !isAbs && counter < page){
7522             retVal = false;
7523         }
7524         else if(counter == page){
7525             retVal = true;
7526         }
7527 
7528        return retVal;
7529     }
7530     */
7531 
7532 
7533     /**
7534      * Goes to the page number passed as the parameter  from the current page.
7535      * The parameter can take postive or negative value accordingly.
7536      * @param page , the page loaded on a call to this function
7537      * @return true if the page exists false otherwise
7538      * @throws SQLException if an error occurs
7539      */
7540     /*
7541     public boolean relativePage(int page) throws SQLException {
7542 
7543         boolean isRel = true,retVal = true;
7544         int counter;
7545 
7546         if(page > 0){
7547            counter  = 0;
7548            while((counter < page) && isRel){
7549               isRel = nextPage();
7550               counter++;
7551            }
7552 
7553            if(!isRel && counter < page){
7554                retVal = false;
7555            }
7556            else if( counter == page){
7557                retVal = true;
7558            }
7559            return retVal;
7560         }
7561         else {
7562             counter = page;
7563             isRel = true;
7564             while((counter < 0) && isRel){
7565                 isRel = previousPage();
7566                 counter++;
7567             }
7568 
7569             if( !isRel && counter < 0){
7570                 retVal = false;
7571             }
7572             else if(counter == 0){
7573                 retVal = true;
7574             }
7575             return retVal;
7576         }
7577     }
7578     */
7579 
7580      /**
7581      * Retrieves the first page of data as specified by the page size.
7582      * @return boolean value true if present on first page, false otherwise
7583      * @throws SQLException if it called before populate or ResultSet is of
7584      *         type <code>ResultSet.TYPE_FORWARD_ONLY</code> or an error occurs
7585      */
7586     /*
7587     public boolean firstPage() throws SQLException {
7588            if (populatecallcount == 0){
7589              throw new SQLException("Populate the data before calling ");
7590            }
7591            if( !callWithCon){
7592               if(resultSet.getType() == ResultSet.TYPE_FORWARD_ONLY) {
7593                   throw new SQLException("Result of type forward only");
7594               }
7595            }
7596            endPos = 0;
7597            maxRowsreached = 0;
7598            pagenotend = true;
7599            if(callWithCon){
7600                crsReader.setStartPosition(startPos);
7601                crsReader.readData((RowSetInternal)this);
7602                resultSet = null;
7603            }
7604            else {
7605               populate(resultSet,startPos);
7606            }
7607            onFirstPage = true;
7608            return onFirstPage;
7609     }
7610     */
7611 
7612     /**
7613      * Retrives the last page of data as specified by the page size.
7614      * @return boolean value tur if present on the last page, false otherwise
7615      * @throws SQLException if called before populate or if an error occurs.
7616      */
7617      /*
7618     public boolean lastPage() throws SQLException{
7619           int pS;
7620           int mR;
7621           int quo;
7622           int rem;
7623 
7624           pS = getPageSize();
7625           mR = getMaxRows();
7626 
7627           if(pS == 0){
7628               onLastPage = true;
7629               return onLastPage;
7630           }
7631 
7632           if(getMaxRows() == 0){
7633               mR = totalRows;
7634           }
7635 
7636           if (populatecallcount == 0){
7637              throw new SQLException("Populate the data before calling ");
7638          }
7639 
7640          onFirstPage = false;
7641 
7642          if((mR % pS) == 0){
7643              quo = mR / pS;
7644              int start = startPos + (pS * (quo - 1));
7645              maxRowsreached = mR - pS;
7646              if(callWithCon){
7647                  crsReader.setStartPosition(start);
7648                  crsReader.readData((RowSetInternal)this);
7649                  resultSet = null;
7650              }
7651              else {
7652                 populate(resultSet,start);
7653              }
7654              onLastPage = true;
7655              return onLastPage;
7656          }
7657         else {
7658               quo = mR /pS;
7659               rem = mR % pS;
7660               int start = startPos + (pS * quo);
7661              maxRowsreached = mR - (rem);
7662              if(callWithCon){
7663                  crsReader.setStartPosition(start);
7664                  crsReader.readData((RowSetInternal)this);
7665                  resultSet = null;
7666              }
7667              else {
7668                 populate(resultSet,start);
7669              }
7670              onLastPage = true;
7671              return onLastPage;
7672          }
7673     }
7674     */
7675 
7676    /**
7677      * Sets the status for the row on which the cursor is positioned. The insertFlag is used
7678      * to mention the toggle status for this row
7679      * @param insertFlag if it is true  - marks this row as inserted
7680      *                   if it is false - marks it as not a newly inserted row
7681      * @throws SQLException if an error occurs while doing this operation
7682      */
7683     public void setRowInserted(boolean insertFlag) throws SQLException {
7684 
7685         checkCursor();
7686 
7687         if(onInsertRow == true)
7688           throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
7689 
7690         if( insertFlag ) {
7691           ((Row)getCurrentRow()).setInserted();
7692         } else {
7693           ((Row)getCurrentRow()).clearInserted();
7694         }
7695     }
7696 
7697     /**
7698      * Retrieves the value of the designated <code>SQL XML</code> parameter as a
7699      * <code>SQLXML</code> object in the Java programming language.
7700      * @param columnIndex the first column is 1, the second is 2, ...
7701      * @return a SQLXML object that maps an SQL XML value
7702      * @throws SQLException if a database access error occurs
7703      * @since 1.6
7704      */
7705     public SQLXML getSQLXML(int columnIndex) throws SQLException {
7706         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7707     }
7708 
7709     /**
7710      * Retrieves the value of the designated <code>SQL XML</code> parameter as a
7711      * <code>SQLXML</code> object in the Java programming language.
7712      * @param colName the name of the column from which to retrieve the value
7713      * @return a SQLXML object that maps an SQL XML value
7714      * @throws SQLException if a database access error occurs
7715      */
7716     public SQLXML getSQLXML(String colName) throws SQLException {
7717         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7718     }
7719 
7720     /**
7721      * Retrieves the value of the designated column in the current row of this
7722      * <code>ResultSet</code> object as a java.sql.RowId object in the Java
7723      * programming language.
7724      *
7725      * @param columnIndex the first column is 1, the second 2, ...
7726      * @return the column value if the value is a SQL <code>NULL</code> the
7727      *     value returned is <code>null</code>
7728      * @throws SQLException if a database access error occurs
7729      * @since 1.6
7730      */
7731     public RowId getRowId(int columnIndex) throws SQLException {
7732         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7733     }
7734 
7735     /**
7736      * Retrieves the value of the designated column in the current row of this
7737      * <code>ResultSet</code> object as a java.sql.RowId object in the Java
7738      * programming language.
7739      *
7740      * @param columnName the name of the column
7741      * @return the column value if the value is a SQL <code>NULL</code> the
7742      *     value returned is <code>null</code>
7743      * @throws SQLException if a database access error occurs
7744      * @since 1.6
7745      */
7746     public RowId getRowId(String columnName) throws SQLException {
7747         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7748     }
7749 
7750     /**
7751      * Updates the designated column with a <code>RowId</code> value. The updater
7752      * methods are used to update column values in the current row or the insert
7753      * row. The updater methods do not update the underlying database; instead
7754      * the {@code updateRow} or {@code insertRow} methods are called
7755      * to update the database.
7756      *
7757      * @param columnIndex the first column is 1, the second 2, ...
7758      * @param x the column value
7759      * @throws SQLException if a database access occurs
7760      * @since 1.6
7761      */
7762     public void updateRowId(int columnIndex, RowId x) throws SQLException {
7763         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7764     }
7765 
7766     /**
7767      * Updates the designated column with a <code>RowId</code> value. The updater
7768      * methods are used to update column values in the current row or the insert
7769      * row. The updater methods do not update the underlying database; instead
7770      * the {@code updateRow} or {@code insertRow} methods are called
7771      * to update the database.
7772      *
7773      * @param columnName the name of the column
7774      * @param x the column value
7775      * @throws SQLException if a database access occurs
7776      * @since 1.6
7777      */
7778     public void updateRowId(String columnName, RowId x) throws SQLException {
7779         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7780     }
7781 
7782     /**
7783      * Retrieves the holdability of this ResultSet object
7784      * @return  either ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT
7785      * @throws SQLException if a database error occurs
7786      * @since 1.6
7787      */
7788     public int getHoldability() throws SQLException {
7789         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7790     }
7791 
7792     /**
7793      * Retrieves whether this ResultSet object has been closed. A ResultSet is closed if the
7794      * method close has been called on it, or if it is automatically closed.
7795      * @return true if this ResultSet object is closed; false if it is still open
7796      * @throws SQLException if a database access error occurs
7797      * @since 1.6
7798      */
7799     public boolean isClosed() throws SQLException {
7800         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7801     }
7802 
7803     /**
7804      * This method is used for updating columns that support National Character sets.
7805      * It can be used for updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
7806      * @param columnIndex the first column is 1, the second 2, ...
7807      * @param nString the value for the column to be updated
7808      * @throws SQLException if a database access error occurs
7809      * @since 1.6
7810      */
7811     public void updateNString(int columnIndex, String nString) throws SQLException {
7812         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7813     }
7814 
7815     /**
7816      * This method is used for updating columns that support National Character sets.
7817      * It can be used for updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
7818      * @param columnName name of the Column
7819      * @param nString the value for the column to be updated
7820      * @throws SQLException if a database access error occurs
7821      * @since 1.6
7822      */
7823     public void updateNString(String columnName, String nString) throws SQLException {
7824         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7825     }
7826 
7827 
7828     /*o
7829      * This method is used for updating SQL <code>NCLOB</code>  type that maps
7830      * to <code>java.sql.Types.NCLOB</code>
7831      * @param columnIndex the first column is 1, the second 2, ...
7832      * @param nClob the value for the column to be updated
7833      * @throws SQLException if a database access error occurs
7834      * @since 1.6
7835      */
7836     public void updateNClob(int columnIndex, NClob nClob) throws SQLException {
7837         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7838     }
7839 
7840     /**
7841      * This method is used for updating SQL <code>NCLOB</code>  type that maps
7842      * to <code>java.sql.Types.NCLOB</code>
7843      * @param columnName name of the column
7844      * @param nClob the value for the column to be updated
7845      * @throws SQLException if a database access error occurs
7846      * @since 1.6
7847      */
7848     public void updateNClob(String columnName, NClob nClob) throws SQLException {
7849        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7850     }
7851 
7852     /**
7853      * Retrieves the value of the designated column in the current row
7854      * of this <code>ResultSet</code> object as a <code>NClob</code> object
7855      * in the Java programming language.
7856      *
7857      * @param i the first column is 1, the second is 2, ...
7858      * @return a <code>NClob</code> object representing the SQL
7859      *         <code>NCLOB</code> value in the specified column
7860      * @exception SQLException if a database access error occurs
7861      * @since 1.6
7862      */
7863     public NClob getNClob(int i) throws SQLException {
7864         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7865     }
7866 
7867 
7868    /**
7869      * Retrieves the value of the designated column in the current row
7870      * of this <code>ResultSet</code> object as a <code>NClob</code> object
7871      * in the Java programming language.
7872      *
7873      * @param colName the name of the column from which to retrieve the value
7874      * @return a <code>NClob</code> object representing the SQL <code>NCLOB</code>
7875      * value in the specified column
7876      * @exception SQLException if a database access error occurs
7877      * @since 1.6
7878      */
7879     public NClob getNClob(String colName) throws SQLException {
7880         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7881     }
7882 
7883     public <T> T unwrap(java.lang.Class<T> iface) throws java.sql.SQLException {
7884         return null;
7885     }
7886 
7887     public boolean isWrapperFor(Class<?> interfaces) throws SQLException {
7888         return false;
7889     }
7890 
7891 
7892    /**
7893       * Sets the designated parameter to the given <code>java.sql.SQLXML</code> object. The driver converts this to an
7894       * SQL <code>XML</code> value when it sends it to the database.
7895       * @param parameterIndex index of the first parameter is 1, the second is 2, ...
7896       * @param xmlObject a <code>SQLXML</code> object that maps an SQL <code>XML</code> value
7897       * @throws SQLException if a database access error occurs
7898       * @since 1.6
7899       */
7900      public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
7901          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7902      }
7903 
7904    /**
7905      * Sets the designated parameter to the given <code>java.sql.SQLXML</code> object. The driver converts this to an
7906      * <code>SQL XML</code> value when it sends it to the database.
7907      * @param parameterName the name of the parameter
7908      * @param xmlObject a <code>SQLXML</code> object that maps an <code>SQL XML</code> value
7909      * @throws SQLException if a database access error occurs
7910      * @since 1.6
7911      */
7912     public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException {
7913          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7914      }
7915 
7916 
7917     /**
7918      * Sets the designated parameter to the given <code>java.sql.RowId</code> object. The
7919      * driver converts this to a SQL <code>ROWID</code> value when it sends it
7920      * to the database
7921      *
7922      * @param parameterIndex the first parameter is 1, the second is 2, ...
7923      * @param x the parameter value
7924      * @throws SQLException if a database access error occurs
7925      *
7926      * @since 1.6
7927      */
7928     public void setRowId(int parameterIndex, RowId x) throws SQLException {
7929          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7930      }
7931 
7932 
7933     /**
7934     * Sets the designated parameter to the given <code>java.sql.RowId</code> object. The
7935     * driver converts this to a SQL <code>ROWID</code> when it sends it to the
7936     * database.
7937     *
7938     * @param parameterName the name of the parameter
7939     * @param x the parameter value
7940     * @throws SQLException if a database access error occurs
7941     * @since 1.6
7942     */
7943    public void setRowId(String parameterName, RowId x) throws SQLException {
7944          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7945      }
7946 
7947 
7948     /**
7949      * Sets the designated parameter to a <code>Reader</code> object. The
7950      * <code>Reader</code> reads the data till end-of-file is reached. The
7951      * driver does the necessary conversion from Java character format to
7952      * the national character set in the database.
7953 
7954      * <P><B>Note:</B> This stream object can either be a standard
7955      * Java stream object or your own subclass that implements the
7956      * standard interface.
7957      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
7958      * it might be more efficient to use a version of
7959      * <code>setNCharacterStream</code> which takes a length parameter.
7960      *
7961      * @param parameterIndex of the first parameter is 1, the second is 2, ...
7962      * @param value the parameter value
7963      * @throws SQLException if the driver does not support national
7964      *         character sets;  if the driver can detect that a data conversion
7965      *  error could occur ; if a database access error occurs; or
7966      * this method is called on a closed <code>PreparedStatement</code>
7967      * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
7968      * @since 1.6
7969      */
7970      public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
7971         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
7972      }
7973 
7974 
7975     /**
7976     * Sets the designated parameter to a <code>java.sql.NClob</code> object. The object
7977     * implements the <code>java.sql.NClob</code> interface. This <code>NClob</code>
7978     * object maps to a SQL <code>NCLOB</code>.
7979     * @param parameterName the name of the column to be set
7980     * @param value the parameter value
7981     * @throws SQLException if the driver does not support national
7982     *         character sets;  if the driver can detect that a data conversion
7983     *  error could occur; or if a database access error occurs
7984     * @since 1.6
7985     */
7986     public void setNClob(String parameterName, NClob value) throws SQLException {
7987          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7988      }
7989 
7990 
7991   /**
7992      * Retrieves the value of the designated column in the current row
7993      * of this <code>ResultSet</code> object as a
7994      * <code>java.io.Reader</code> object.
7995      * It is intended for use when
7996      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
7997      * and <code>LONGNVARCHAR</code> columns.
7998      *
7999      * @return a <code>java.io.Reader</code> object that contains the column
8000      * value; if the value is SQL <code>NULL</code>, the value returned is
8001      * <code>null</code> in the Java programming language.
8002      * @param columnIndex the first column is 1, the second is 2, ...
8003      * @exception SQLException if a database access error occurs
8004      * @since 1.6
8005      */
8006     public java.io.Reader getNCharacterStream(int columnIndex) throws SQLException {
8007        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8008      }
8009 
8010 
8011     /**
8012      * Retrieves the value of the designated column in the current row
8013      * of this <code>ResultSet</code> object as a
8014      * <code>java.io.Reader</code> object.
8015      * It is intended for use when
8016      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8017      * and <code>LONGNVARCHAR</code> columns.
8018      *
8019      * @param columnName the name of the column
8020      * @return a <code>java.io.Reader</code> object that contains the column
8021      * value; if the value is SQL <code>NULL</code>, the value returned is
8022      * <code>null</code> in the Java programming language
8023      * @exception SQLException if a database access error occurs
8024      * @since 1.6
8025      */
8026     public java.io.Reader getNCharacterStream(String columnName) throws SQLException {
8027        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8028      }
8029 
8030 
8031     /**
8032      * Updates the designated column with a <code>java.sql.SQLXML</code> value.
8033      * The updater
8034      * methods are used to update column values in the current row or the insert
8035      * row. The updater methods do not update the underlying database; instead
8036      * the <code>updateRow</code> or <code>insertRow</code> methods are called
8037      * to update the database.
8038      * @param columnIndex the first column is 1, the second 2, ...
8039      * @param xmlObject the value for the column to be updated
8040      * @throws SQLException if a database access error occurs
8041      * @since 1.6
8042      */
8043     public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException {
8044         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8045     }
8046 
8047     /**
8048      * Updates the designated column with a <code>java.sql.SQLXML</code> value.
8049      * The updater
8050      * methods are used to update column values in the current row or the insert
8051      * row. The updater methods do not update the underlying database; instead
8052      * the <code>updateRow</code> or <code>insertRow</code> methods are called
8053      * to update the database.
8054      *
8055      * @param columnName the name of the column
8056      * @param xmlObject the column value
8057      * @throws SQLException if a database access occurs
8058      * @since 1.6
8059      */
8060     public void updateSQLXML(String columnName, SQLXML xmlObject) throws SQLException {
8061         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8062     }
8063 
8064      /**
8065      * Retrieves the value of the designated column in the current row
8066      * of this <code>ResultSet</code> object as
8067      * a <code>String</code> in the Java programming language.
8068      * It is intended for use when
8069      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8070      * and <code>LONGNVARCHAR</code> columns.
8071      *
8072      * @param columnIndex the first column is 1, the second is 2, ...
8073      * @return the column value; if the value is SQL <code>NULL</code>, the
8074      * value returned is <code>null</code>
8075      * @exception SQLException if a database access error occurs
8076      * @since 1.6
8077      */
8078     public String getNString(int columnIndex) throws SQLException {
8079         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8080     }
8081 
8082     /**
8083      * Retrieves the value of the designated column in the current row
8084      * of this <code>ResultSet</code> object as
8085      * a <code>String</code> in the Java programming language.
8086      * It is intended for use when
8087      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8088      * and <code>LONGNVARCHAR</code> columns.
8089      *
8090      * @param columnName the SQL name of the column
8091      * @return the column value; if the value is SQL <code>NULL</code>, the
8092      * value returned is <code>null</code>
8093      * @exception SQLException if a database access error occurs
8094      * @since 1.6
8095      */
8096     public String getNString(String columnName) throws SQLException {
8097         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8098     }
8099 
8100      /**
8101        * Updates the designated column with a character stream value, which will
8102        * have the specified number of bytes. The driver does the necessary conversion
8103        * from Java character format to the national character set in the database.
8104        * It is intended for use when updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
8105        * The updater methods are used to update column values in the current row or
8106        * the insert row. The updater methods do not update the underlying database;
8107        * instead the updateRow or insertRow methods are called to update the database.
8108        *
8109        * @param columnIndex - the first column is 1, the second is 2, ...
8110        * @param x - the new column value
8111        * @param length - the length of the stream
8112        * @exception SQLException if a database access error occurs
8113        * @since 1.6
8114        */
8115        public void updateNCharacterStream(int columnIndex,
8116                             java.io.Reader x,
8117                             long length)
8118                             throws SQLException {
8119           throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8120        }
8121 
8122      /**
8123        * Updates the designated column with a character stream value, which will
8124        * have the specified number of bytes. The driver does the necessary conversion
8125        * from Java character format to the national character set in the database.
8126        * It is intended for use when updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
8127        * The updater methods are used to update column values in the current row or
8128        * the insert row. The updater methods do not update the underlying database;
8129        * instead the updateRow or insertRow methods are called to update the database.
8130        *
8131        * @param columnName - name of the Column
8132        * @param x - the new column value
8133        * @param length - the length of the stream
8134        * @exception SQLException if a database access error occurs
8135        * @since 1.6
8136        */
8137        public void updateNCharacterStream(String columnName,
8138                             java.io.Reader x,
8139                             long length)
8140                             throws SQLException {
8141           throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8142        }
8143 
8144      /**
8145      * Updates the designated column with a character stream value.   The
8146      * driver does the necessary conversion from Java character format to
8147      * the national character set in the database.
8148      * It is intended for use when
8149      * updating  <code>NCHAR</code>,<code>NVARCHAR</code>
8150      * and <code>LONGNVARCHAR</code> columns.
8151      *
8152      * The updater methods are used to update column values in the
8153      * current row or the insert row.  The updater methods do not
8154      * update the underlying database; instead the <code>updateRow</code> or
8155      * <code>insertRow</code> methods are called to update the database.
8156      *
8157      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8158      * it might be more efficient to use a version of
8159      * <code>updateNCharacterStream</code> which takes a length parameter.
8160      *
8161      * @param columnIndex the first column is 1, the second is 2, ...
8162      * @param x the new column value
8163      * @exception SQLException if a database access error occurs,
8164      * the result set concurrency is <code>CONCUR_READ_ONLY</code> or this method is called on a closed result set
8165      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8166      * this method
8167      * @since 1.6
8168      */
8169     public void updateNCharacterStream(int columnIndex,
8170                              java.io.Reader x) throws SQLException {
8171         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8172     }
8173 
8174     /**
8175      * Updates the designated column with a character stream value.  The
8176      * driver does the necessary conversion from Java character format to
8177      * the national character set in the database.
8178      * It is intended for use when
8179      * updating  <code>NCHAR</code>,<code>NVARCHAR</code>
8180      * and <code>LONGNVARCHAR</code> columns.
8181      *
8182      * The updater methods are used to update column values in the
8183      * current row or the insert row.  The updater methods do not
8184      * update the underlying database; instead the <code>updateRow</code> or
8185      * <code>insertRow</code> methods are called to update the database.
8186      *
8187      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8188      * it might be more efficient to use a version of
8189      * <code>updateNCharacterStream</code> which takes a length parameter.
8190      *
8191      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8192 bel is the name of the column
8193      * @param reader the <code>java.io.Reader</code> object containing
8194      *        the new column value
8195      * @exception SQLException if a database access error occurs,
8196      * the result set concurrency is <code>CONCUR_READ_ONLY</code> or this method is called on a closed result set
8197       * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8198      * this method
8199      * @since 1.6
8200      */
8201     public void updateNCharacterStream(String columnLabel,
8202                              java.io.Reader reader) throws SQLException {
8203         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8204     }
8205 
8206 //////////////////////////
8207 
8208     /**
8209      * Updates the designated column using the given input stream, which
8210      * will have the specified number of bytes.
8211      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8212      * parameter, it may be more practical to send it via a
8213      * <code>java.io.InputStream</code>. Data will be read from the stream
8214      * as needed until end-of-file is reached.  The JDBC driver will
8215      * do any necessary conversion from ASCII to the database char format.
8216      *
8217      * <P><B>Note:</B> This stream object can either be a standard
8218      * Java stream object or your own subclass that implements the
8219      * standard interface.
8220      * <p>
8221      * The updater methods are used to update column values in the
8222      * current row or the insert row.  The updater methods do not
8223      * update the underlying database; instead the <code>updateRow</code> or
8224      * <code>insertRow</code> methods are called to update the database.
8225      *
8226      * @param columnIndex the first column is 1, the second is 2, ...
8227      * @param inputStream An object that contains the data to set the parameter
8228      * value to.
8229      * @param length the number of bytes in the parameter data.
8230      * @exception SQLException if a database access error occurs,
8231      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8232      * or this method is called on a closed result set
8233      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8234      * this method
8235      * @since 1.6
8236      */
8237     public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException{
8238         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8239     }
8240 
8241     /**
8242      * Updates the designated column using the given input stream, which
8243      * will have the specified number of bytes.
8244      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8245      * parameter, it may be more practical to send it via a
8246      * <code>java.io.InputStream</code>. Data will be read from the stream
8247      * as needed until end-of-file is reached.  The JDBC driver will
8248      * do any necessary conversion from ASCII to the database char format.
8249      *
8250      * <P><B>Note:</B> This stream object can either be a standard
8251      * Java stream object or your own subclass that implements the
8252      * standard interface.
8253      * <p>
8254      * The updater methods are used to update column values in the
8255      * current row or the insert row.  The updater methods do not
8256      * update the underlying database; instead the <code>updateRow</code> or
8257      * <code>insertRow</code> methods are called to update the database.
8258      *
8259      * @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
8260      * @param inputStream An object that contains the data to set the parameter
8261      * value to.
8262      * @param length the number of bytes in the parameter data.
8263      * @exception SQLException if a database access error occurs,
8264      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8265      * or this method is called on a closed result set
8266      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8267      * this method
8268      * @since 1.6
8269      */
8270     public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException {
8271         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8272     }
8273 
8274     /**
8275      * Updates the designated column using the given input stream.
8276      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8277      * parameter, it may be more practical to send it via a
8278      * <code>java.io.InputStream</code>. Data will be read from the stream
8279      * as needed until end-of-file is reached.  The JDBC driver will
8280      * do any necessary conversion from ASCII to the database char format.
8281      *
8282      * <P><B>Note:</B> This stream object can either be a standard
8283      * Java stream object or your own subclass that implements the
8284      * standard interface.
8285      *
8286      *  <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8287      * it might be more efficient to use a version of
8288      * <code>updateBlob</code> which takes a length parameter.
8289      * <p>
8290      * The updater methods are used to update column values in the
8291      * current row or the insert row.  The updater methods do not
8292      * update the underlying database; instead the <code>updateRow</code> or
8293      * <code>insertRow</code> methods are called to update the database.
8294      *
8295      * @param columnIndex the first column is 1, the second is 2, ...
8296      * @param inputStream An object that contains the data to set the parameter
8297      * value to.
8298      * @exception SQLException if a database access error occurs,
8299      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8300      * or this method is called on a closed result set
8301      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8302      * this method
8303      * @since 1.6
8304      */
8305     public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException {
8306         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8307     }
8308 
8309     /**
8310      * Updates the designated column using the given input stream.
8311      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8312      * parameter, it may be more practical to send it via a
8313      * <code>java.io.InputStream</code>. Data will be read from the stream
8314      * as needed until end-of-file is reached.  The JDBC driver will
8315      * do any necessary conversion from ASCII to the database char format.
8316      *
8317      * <P><B>Note:</B> This stream object can either be a standard
8318      * Java stream object or your own subclass that implements the
8319      * standard interface.
8320      *   <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8321      * it might be more efficient to use a version of
8322      * <code>updateBlob</code> which takes a length parameter.
8323      * <p>
8324      * The updater methods are used to update column values in the
8325      * current row or the insert row.  The updater methods do not
8326      * update the underlying database; instead the <code>updateRow</code> or
8327      * <code>insertRow</code> methods are called to update the database.
8328      *
8329      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8330 bel is the name of the column
8331      * @param inputStream An object that contains the data to set the parameter
8332      * value to.
8333      * @exception SQLException if a database access error occurs,
8334      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8335      * or this method is called on a closed result set
8336      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8337      * this method
8338      * @since 1.6
8339      */
8340     public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException {
8341         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8342     }
8343 
8344     /**
8345      * Updates the designated column using the given <code>Reader</code>
8346      * object, which is the given number of characters long.
8347      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8348      * parameter, it may be more practical to send it via a
8349      * <code>java.io.Reader</code> object. The data will be read from the stream
8350      * as needed until end-of-file is reached.  The JDBC driver will
8351      * do any necessary conversion from UNICODE to the database char format.
8352      *
8353      * <P><B>Note:</B> This stream object can either be a standard
8354      * Java stream object or your own subclass that implements the
8355      * standard interface.
8356      * <p>
8357      * The updater methods are used to update column values in the
8358      * current row or the insert row.  The updater methods do not
8359      * update the underlying database; instead the <code>updateRow</code> or
8360      * <code>insertRow</code> methods are called to update the database.
8361      *
8362      * @param columnIndex the first column is 1, the second is 2, ...
8363      * @param reader An object that contains the data to set the parameter value to.
8364      * @param length the number of characters in the parameter data.
8365      * @exception SQLException if a database access error occurs,
8366      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8367      * or this method is called on a closed result set
8368      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8369      * this method
8370      * @since 1.6
8371      */
8372     public void updateClob(int columnIndex,  Reader reader, long length) throws SQLException {
8373         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8374     }
8375 
8376     /**
8377      * Updates the designated column using the given <code>Reader</code>
8378      * object, which is the given number of characters long.
8379      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8380      * parameter, it may be more practical to send it via a
8381      * <code>java.io.Reader</code> object. The data will be read from the stream
8382      * as needed until end-of-file is reached.  The JDBC driver will
8383      * do any necessary conversion from UNICODE to the database char format.
8384      *
8385      * <P><B>Note:</B> This stream object can either be a standard
8386      * Java stream object or your own subclass that implements the
8387      * standard interface.
8388      * <p>
8389      * The updater methods are used to update column values in the
8390      * current row or the insert row.  The updater methods do not
8391      * update the underlying database; instead the <code>updateRow</code> or
8392      * <code>insertRow</code> methods are called to update the database.
8393      *
8394      * @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
8395      * @param reader An object that contains the data to set the parameter value to.
8396      * @param length the number of characters in the parameter data.
8397      * @exception SQLException if a database access error occurs,
8398      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8399      * or this method is called on a closed result set
8400      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8401      * this method
8402      * @since 1.6
8403      */
8404     public void updateClob(String columnLabel,  Reader reader, long length) throws SQLException {
8405         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8406     }
8407 
8408    /**
8409      * Updates the designated column using the given <code>Reader</code>
8410      * object.
8411      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8412      * parameter, it may be more practical to send it via a
8413      * <code>java.io.Reader</code> object. The data will be read from the stream
8414      * as needed until end-of-file is reached.  The JDBC driver will
8415      * do any necessary conversion from UNICODE to the database char format.
8416      *
8417      * <P><B>Note:</B> This stream object can either be a standard
8418      * Java stream object or your own subclass that implements the
8419      * standard interface.
8420      *   <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8421      * it might be more efficient to use a version of
8422      * <code>updateClob</code> which takes a length parameter.
8423      * <p>
8424      * The updater methods are used to update column values in the
8425      * current row or the insert row.  The updater methods do not
8426      * update the underlying database; instead the <code>updateRow</code> or
8427      * <code>insertRow</code> methods are called to update the database.
8428      *
8429      * @param columnIndex the first column is 1, the second is 2, ...
8430      * @param reader An object that contains the data to set the parameter value to.
8431      * @exception SQLException if a database access error occurs,
8432      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8433      * or this method is called on a closed result set
8434      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8435      * this method
8436      * @since 1.6
8437      */
8438     public void updateClob(int columnIndex,  Reader reader) throws SQLException {
8439         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8440     }
8441 
8442     /**
8443      * Updates the designated column using the given <code>Reader</code>
8444      * object.
8445      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8446      * parameter, it may be more practical to send it via a
8447      * <code>java.io.Reader</code> object. The data will be read from the stream
8448      * as needed until end-of-file is reached.  The JDBC driver will
8449      * do any necessary conversion from UNICODE to the database char format.
8450      *
8451      * <P><B>Note:</B> This stream object can either be a standard
8452      * Java stream object or your own subclass that implements the
8453      * standard interface.
8454      *  <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8455      * it might be more efficient to use a version of
8456      * <code>updateClob</code> which takes a length parameter.
8457      * <p>
8458      * The updater methods are used to update column values in the
8459      * current row or the insert row.  The updater methods do not
8460      * update the underlying database; instead the <code>updateRow</code> or
8461      * <code>insertRow</code> methods are called to update the database.
8462      *
8463      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8464 bel is the name of the column
8465      * @param reader An object that contains the data to set the parameter value to.
8466      * @exception SQLException if a database access error occurs,
8467      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8468      * or this method is called on a closed result set
8469      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8470      * this method
8471      * @since 1.6
8472      */
8473     public void updateClob(String columnLabel,  Reader reader) throws SQLException {
8474         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8475     }
8476 
8477    /**
8478      * Updates the designated column using the given <code>Reader</code>
8479      * object, which is the given number of characters long.
8480      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8481      * parameter, it may be more practical to send it via a
8482      * <code>java.io.Reader</code> object. The data will be read from the stream
8483      * as needed until end-of-file is reached.  The JDBC driver will
8484      * do any necessary conversion from UNICODE to the database char format.
8485      *
8486      * <P><B>Note:</B> This stream object can either be a standard
8487      * Java stream object or your own subclass that implements the
8488      * standard interface.
8489      * <p>
8490      * The updater methods are used to update column values in the
8491      * current row or the insert row.  The updater methods do not
8492      * update the underlying database; instead the <code>updateRow</code> or
8493      * <code>insertRow</code> methods are called to update the database.
8494      *
8495      * @param columnIndex the first column is 1, the second 2, ...
8496      * @param reader An object that contains the data to set the parameter value to.
8497      * @param length the number of characters in the parameter data.
8498      * @throws SQLException if the driver does not support national
8499      *         character sets;  if the driver can detect that a data conversion
8500      *  error could occur; this method is called on a closed result set,
8501      * if a database access error occurs or
8502      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8503      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8504      * this method
8505      * @since 1.6
8506      */
8507     public void updateNClob(int columnIndex,  Reader reader, long length) throws SQLException {
8508         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8509     }
8510 
8511     /**
8512      * Updates the designated column using the given <code>Reader</code>
8513      * object, which is the given number of characters long.
8514      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8515      * parameter, it may be more practical to send it via a
8516      * <code>java.io.Reader</code> object. The data will be read from the stream
8517      * as needed until end-of-file is reached.  The JDBC driver will
8518      * do any necessary conversion from UNICODE to the database char format.
8519      *
8520      * <P><B>Note:</B> This stream object can either be a standard
8521      * Java stream object or your own subclass that implements the
8522      * standard interface.
8523      * <p>
8524      * The updater methods are used to update column values in the
8525      * current row or the insert row.  The updater methods do not
8526      * update the underlying database; instead the <code>updateRow</code> or
8527      * <code>insertRow</code> methods are called to update the database.
8528      *
8529      * @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
8530      * @param reader An object that contains the data to set the parameter value to.
8531      * @param length the number of characters in the parameter data.
8532      * @throws SQLException if the driver does not support national
8533      *         character sets;  if the driver can detect that a data conversion
8534      *  error could occur; this method is called on a closed result set;
8535      *  if a database access error occurs or
8536      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8537      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8538      * this method
8539      * @since 1.6
8540      */
8541     public void updateNClob(String columnLabel,  Reader reader, long length) throws SQLException {
8542         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8543     }
8544 
8545     /**
8546      * Updates the designated column using the given <code>Reader</code>
8547      * object.
8548      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8549      * parameter, it may be more practical to send it via a
8550      * <code>java.io.Reader</code> object. The data will be read from the stream
8551      * as needed until end-of-file is reached.  The JDBC driver will
8552      * do any necessary conversion from UNICODE to the database char format.
8553      *
8554      * <P><B>Note:</B> This stream object can either be a standard
8555      * Java stream object or your own subclass that implements the
8556      * standard interface.
8557      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8558      * it might be more efficient to use a version of
8559      * <code>updateNClob</code> which takes a length parameter.
8560      * <p>
8561      * The updater methods are used to update column values in the
8562      * current row or the insert row.  The updater methods do not
8563      * update the underlying database; instead the <code>updateRow</code> or
8564      * <code>insertRow</code> methods are called to update the database.
8565      *
8566      * @param columnIndex the first column is 1, the second 2, ...
8567      * @param reader An object that contains the data to set the parameter value to.
8568      * @throws SQLException if the driver does not support national
8569      *         character sets;  if the driver can detect that a data conversion
8570      *  error could occur; this method is called on a closed result set,
8571      * if a database access error occurs or
8572      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8573      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8574      * this method
8575      * @since 1.6
8576      */
8577     public void updateNClob(int columnIndex,  Reader reader) throws SQLException {
8578         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8579     }
8580 
8581     /**
8582      * Updates the designated column using the given <code>Reader</code>
8583      * object.
8584      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8585      * parameter, it may be more practical to send it via a
8586      * <code>java.io.Reader</code> object. The data will be read from the stream
8587      * as needed until end-of-file is reached.  The JDBC driver will
8588      * do any necessary conversion from UNICODE to the database char format.
8589      *
8590      * <P><B>Note:</B> This stream object can either be a standard
8591      * Java stream object or your own subclass that implements the
8592      * standard interface.
8593      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8594      * it might be more efficient to use a version of
8595      * <code>updateNClob</code> which takes a length parameter.
8596      * <p>
8597      * The updater methods are used to update column values in the
8598      * current row or the insert row.  The updater methods do not
8599      * update the underlying database; instead the <code>updateRow</code> or
8600      * <code>insertRow</code> methods are called to update the database.
8601      *
8602      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8603 bel is the name of the column
8604      * @param reader An object that contains the data to set the parameter value to.
8605      * @throws SQLException if the driver does not support national
8606      *         character sets;  if the driver can detect that a data conversion
8607      *  error could occur; this method is called on a closed result set;
8608      *  if a database access error occurs or
8609      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8610      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8611      * this method
8612      * @since 1.6
8613      */
8614     public void updateNClob(String columnLabel,  Reader reader) throws SQLException {
8615         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8616     }
8617 
8618         /**
8619      * Updates the designated column with an ascii stream value, which will have
8620      * the specified number of bytes.
8621      * The updater methods are used to update column values in the
8622      * current row or the insert row.  The updater methods do not
8623      * update the underlying database; instead the <code>updateRow</code> or
8624      * <code>insertRow</code> methods are called to update the database.
8625      *
8626      * @param columnIndex the first column is 1, the second is 2, ...
8627      * @param x the new column value
8628      * @param length the length of the stream
8629      * @exception SQLException if a database access error occurs,
8630      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8631      * or this method is called on a closed result set
8632      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8633      * this method
8634      * @since 1.6
8635      */
8636     public void updateAsciiStream(int columnIndex,
8637                            java.io.InputStream x,
8638                            long length) throws SQLException {
8639 
8640     }
8641 
8642     /**
8643      * Updates the designated column with a binary stream value, which will have
8644      * the specified number of bytes.
8645      * The updater methods are used to update column values in the
8646      * current row or the insert row.  The updater methods do not
8647      * update the underlying database; instead the <code>updateRow</code> or
8648      * <code>insertRow</code> methods are called to update the database.
8649      *
8650      * @param columnIndex the first column is 1, the second is 2, ...
8651      * @param x the new column value
8652      * @param length the length of the stream
8653      * @exception SQLException if a database access error occurs,
8654      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8655      * or this method is called on a closed result set
8656      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8657      * this method
8658      * @since 1.6
8659      */
8660     public void updateBinaryStream(int columnIndex,
8661                             java.io.InputStream x,
8662                             long length) throws SQLException {
8663     }
8664 
8665     /**
8666      * Updates the designated column with a character stream value, which will have
8667      * the specified number of bytes.
8668      * The updater methods are used to update column values in the
8669      * current row or the insert row.  The updater methods do not
8670      * update the underlying database; instead the <code>updateRow</code> or
8671      * <code>insertRow</code> methods are called to update the database.
8672      *
8673      * @param columnIndex the first column is 1, the second is 2, ...
8674      * @param x the new column value
8675      * @param length the length of the stream
8676      * @exception SQLException if a database access error occurs,
8677      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8678      * or this method is called on a closed result set
8679      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8680      * this method
8681      * @since 1.6
8682      */
8683     public void updateCharacterStream(int columnIndex,
8684                              java.io.Reader x,
8685                              long length) throws SQLException {
8686         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8687     }
8688 
8689     /**
8690      * Updates the designated column with a character stream value, which will have
8691      * the specified number of bytes.
8692      * The updater methods are used to update column values in the
8693      * current row or the insert row.  The updater methods do not
8694      * update the underlying database; instead the <code>updateRow</code> or
8695      * <code>insertRow</code> methods are called to update the database.
8696      *
8697      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8698 bel is the name of the column
8699      * @param reader the <code>java.io.Reader</code> object containing
8700      *        the new column value
8701      * @param length the length of the stream
8702      * @exception SQLException if a database access error occurs,
8703      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8704      * or this method is called on a closed result set
8705      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8706      * this method
8707      * @since 1.6
8708      */
8709     public void updateCharacterStream(String columnLabel,
8710                              java.io.Reader reader,
8711                              long length) throws SQLException {
8712         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8713     }
8714      /**
8715      * Updates the designated column with an ascii stream value, which will have
8716      * the specified number of bytes..
8717      * The updater methods are used to update column values in the
8718      * current row or the insert row.  The updater methods do not
8719      * update the underlying database; instead the <code>updateRow</code> or
8720      * <code>insertRow</code> methods are called to update the database.
8721      *
8722      * @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
8723      * @param x the new column value
8724      * @param length the length of the stream
8725      * @exception SQLException if a database access error occurs,
8726      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8727      * or this method is called on a closed result set
8728      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8729      * this method
8730      * @since 1.6
8731      */
8732     public void updateAsciiStream(String columnLabel,
8733                            java.io.InputStream x,
8734                            long length) throws SQLException {
8735     }
8736 
8737     /**
8738      * Updates the designated column with a binary stream value, which will have
8739      * the specified number of bytes.
8740      * The updater methods are used to update column values in the
8741      * current row or the insert row.  The updater methods do not
8742      * update the underlying database; instead the <code>updateRow</code> or
8743      * <code>insertRow</code> methods are called to update the database.
8744      *
8745      * @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
8746      * @param x the new column value
8747      * @param length the length of the stream
8748      * @exception SQLException if a database access error occurs,
8749      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8750      * or this method is called on a closed result set
8751      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8752      * this method
8753      * @since 1.6
8754      */
8755     public void updateBinaryStream(String columnLabel,
8756                             java.io.InputStream x,
8757                             long length) throws SQLException {
8758     }
8759 
8760     /**
8761      * Updates the designated column with a binary stream value.
8762      * The updater methods are used to update column values in the
8763      * current row or the insert row.  The updater methods do not
8764      * update the underlying database; instead the <code>updateRow</code> or
8765      * <code>insertRow</code> methods are called to update the database.
8766      *
8767      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8768      * it might be more efficient to use a version of
8769      * <code>updateBinaryStream</code> which takes a length parameter.
8770      *
8771      * @param columnIndex the first column is 1, the second is 2, ...
8772      * @param x the new column value
8773      * @exception SQLException if a database access error occurs,
8774      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8775      * or this method is called on a closed result set
8776      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8777      * this method
8778      * @since 1.6
8779      */
8780     public void updateBinaryStream(int columnIndex,
8781                             java.io.InputStream x) throws SQLException {
8782         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8783     }
8784 
8785 
8786     /**
8787      * Updates the designated column with a binary stream value.
8788      * The updater methods are used to update column values in the
8789      * current row or the insert row.  The updater methods do not
8790      * update the underlying database; instead the <code>updateRow</code> or
8791      * <code>insertRow</code> methods are called to update the database.
8792      *
8793      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8794      * it might be more efficient to use a version of
8795      * <code>updateBinaryStream</code> which takes a length parameter.
8796      *
8797      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8798 bel is the name of the column
8799      * @param x the new column value
8800      * @exception SQLException if a database access error occurs,
8801      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8802      * or this method is called on a closed result set
8803      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8804      * this method
8805      * @since 1.6
8806      */
8807     public void updateBinaryStream(String columnLabel,
8808                             java.io.InputStream x) throws SQLException {
8809         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8810     }
8811 
8812     /**
8813      * Updates the designated column with a character stream value.
8814      * The updater methods are used to update column values in the
8815      * current row or the insert row.  The updater methods do not
8816      * update the underlying database; instead the <code>updateRow</code> or
8817      * <code>insertRow</code> methods are called to update the database.
8818      *
8819      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8820      * it might be more efficient to use a version of
8821      * <code>updateCharacterStream</code> which takes a length parameter.
8822      *
8823      * @param columnIndex the first column is 1, the second is 2, ...
8824      * @param x the new column value
8825      * @exception SQLException if a database access error occurs,
8826      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8827      * or this method is called on a closed result set
8828      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8829      * this method
8830      * @since 1.6
8831      */
8832     public void updateCharacterStream(int columnIndex,
8833                              java.io.Reader x) throws SQLException {
8834         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8835     }
8836 
8837     /**
8838      * Updates the designated column with a character stream value.
8839      * The updater methods are used to update column values in the
8840      * current row or the insert row.  The updater methods do not
8841      * update the underlying database; instead the <code>updateRow</code> or
8842      * <code>insertRow</code> methods are called to update the database.
8843      *
8844      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8845      * it might be more efficient to use a version of
8846      * <code>updateCharacterStream</code> which takes a length parameter.
8847      *
8848      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8849 bel is the name of the column
8850      * @param reader the <code>java.io.Reader</code> object containing
8851      *        the new column value
8852      * @exception SQLException if a database access error occurs,
8853      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8854      * or this method is called on a closed result set
8855      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8856      * this method
8857      * @since 1.6
8858      */
8859     public void updateCharacterStream(String columnLabel,
8860                              java.io.Reader reader) throws SQLException {
8861         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8862     }
8863 
8864     /**
8865      * Updates the designated column with an ascii stream value.
8866      * The updater methods are used to update column values in the
8867      * current row or the insert row.  The updater methods do not
8868      * update the underlying database; instead the <code>updateRow</code> or
8869      * <code>insertRow</code> methods are called to update the database.
8870      *
8871      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8872      * it might be more efficient to use a version of
8873      * <code>updateAsciiStream</code> which takes a length parameter.
8874      *
8875      * @param columnIndex the first column is 1, the second is 2, ...
8876      * @param x the new column value
8877      * @exception SQLException if a database access error occurs,
8878      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8879      * or this method is called on a closed result set
8880      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8881      * this method
8882      * @since 1.6
8883      */
8884     public void updateAsciiStream(int columnIndex,
8885                            java.io.InputStream x) throws SQLException {
8886         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8887     }
8888 
8889     /**
8890      * Updates the designated column with an ascii stream value.
8891      * The updater methods are used to update column values in the
8892      * current row or the insert row.  The updater methods do not
8893      * update the underlying database; instead the <code>updateRow</code> or
8894      * <code>insertRow</code> methods are called to update the database.
8895      *
8896      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8897      * it might be more efficient to use a version of
8898      * <code>updateAsciiStream</code> which takes a length parameter.
8899      *
8900      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8901 bel is the name of the column
8902      * @param x the new column value
8903      * @exception SQLException if a database access error occurs,
8904      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8905      * or this method is called on a closed result set
8906      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8907      * this method
8908      * @since 1.6
8909      */
8910     public void updateAsciiStream(String columnLabel,
8911                            java.io.InputStream x) throws SQLException {
8912 
8913     }
8914 
8915    /**
8916   * Sets the designated parameter to the given <code>java.net.URL</code> value.
8917   * The driver converts this to an SQL <code>DATALINK</code> value
8918   * when it sends it to the database.
8919   *
8920   * @param parameterIndex the first parameter is 1, the second is 2, ...
8921   * @param x the <code>java.net.URL</code> object to be set
8922   * @exception SQLException if a database access error occurs or
8923   * this method is called on a closed <code>PreparedStatement</code>
8924   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
8925   * @since 1.4
8926   */
8927   public void setURL(int parameterIndex, java.net.URL x) throws SQLException{
8928         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8929    }
8930 
8931   /**
8932   * Sets the designated parameter to a <code>Reader</code> object.
8933   * This method differs from the <code>setCharacterStream (int, Reader)</code> method
8934   * because it informs the driver that the parameter value should be sent to
8935   * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
8936   * driver may have to do extra work to determine whether the parameter
8937   * data should be sent to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
8938   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8939   * it might be more efficient to use a version of
8940   * <code>setNClob</code> which takes a length parameter.
8941   *
8942   * @param parameterIndex index of the first parameter is 1, the second is 2, ...
8943   * @param reader An object that contains the data to set the parameter value to.
8944   * @throws SQLException if parameterIndex does not correspond to a parameter
8945   * marker in the SQL statement;
8946   * if the driver does not support national character sets;
8947   * if the driver can detect that a data conversion
8948   *  error could occur;  if a database access error occurs or
8949   * this method is called on a closed <code>PreparedStatement</code>
8950   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
8951   *
8952   * @since 1.6
8953   */
8954   public void setNClob(int parameterIndex, Reader reader)
8955     throws SQLException{
8956         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8957    }
8958 
8959   /**
8960   * Sets the designated parameter to a <code>Reader</code> object.  The <code>reader</code> must contain  the number
8961              * of characters specified by length otherwise a <code>SQLException</code> will be
8962             * generated when the <code>CallableStatement</code> is executed.
8963             * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
8964             * because it informs the driver that the parameter value should be sent to
8965             * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
8966             * driver may have to do extra work to determine whether the parameter
8967             * data should be send to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
8968             *
8969             * @param parameterName the name of the parameter to be set
8970             * @param reader An object that contains the data to set the parameter value to.
8971             * @param length the number of characters in the parameter data.
8972             * @throws SQLException if parameterIndex does not correspond to a parameter
8973             * marker in the SQL statement; if the length specified is less than zero;
8974             * if the driver does not support national
8975             *         character sets;  if the driver can detect that a data conversion
8976             *  error could occur; if a database access error occurs or
8977             * this method is called on a closed <code>CallableStatement</code>
8978             * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8979             * this method
8980             * @since 1.6
8981             */
8982             public void setNClob(String parameterName, Reader reader, long length)
8983     throws SQLException{
8984         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8985    }
8986 
8987 
8988  /**
8989   * Sets the designated parameter to a <code>Reader</code> object.
8990   * This method differs from the <code>setCharacterStream (int, Reader)</code> method
8991   * because it informs the driver that the parameter value should be sent to
8992   * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
8993   * driver may have to do extra work to determine whether the parameter
8994   * data should be send to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
8995   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8996   * it might be more efficient to use a version of
8997   * <code>setNClob</code> which takes a length parameter.
8998   *
8999   * @param parameterName the name of the parameter
9000   * @param reader An object that contains the data to set the parameter value to.
9001   * @throws SQLException if the driver does not support national character sets;
9002   * if the driver can detect that a data conversion
9003   *  error could occur;  if a database access error occurs or
9004   * this method is called on a closed <code>CallableStatement</code>
9005   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9006   *
9007   * @since 1.6
9008   */
9009   public void setNClob(String parameterName, Reader reader)
9010     throws SQLException{
9011         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9012    }
9013 
9014 
9015     /**
9016      * Sets the designated parameter to a <code>Reader</code> object.  The reader must contain  the number
9017      * of characters specified by length otherwise a <code>SQLException</code> will be
9018      * generated when the <code>PreparedStatement</code> is executed.
9019      * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
9020      * because it informs the driver that the parameter value should be sent to
9021      * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9022      * driver may have to do extra work to determine whether the parameter
9023      * data should be sent to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
9024      * @param parameterIndex index of the first parameter is 1, the second is 2, ...
9025      * @param reader An object that contains the data to set the parameter value to.
9026      * @param length the number of characters in the parameter data.
9027      * @throws SQLException if parameterIndex does not correspond to a parameter
9028      * marker in the SQL statement; if the length specified is less than zero;
9029      * if the driver does not support national character sets;
9030      * if the driver can detect that a data conversion
9031      *  error could occur;  if a database access error occurs or
9032      * this method is called on a closed <code>PreparedStatement</code>
9033      * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9034      *
9035      * @since 1.6
9036      */
9037      public void setNClob(int parameterIndex, Reader reader, long length)
9038        throws SQLException{
9039         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9040    }
9041 
9042 
9043     /**
9044      * Sets the designated parameter to a <code>java.sql.NClob</code> object. The driver converts this to
9045 a
9046      * SQL <code>NCLOB</code> value when it sends it to the database.
9047      * @param parameterIndex of the first parameter is 1, the second is 2, ...
9048      * @param value the parameter value
9049      * @throws SQLException if the driver does not support national
9050      *         character sets;  if the driver can detect that a data conversion
9051      *  error could occur ; or if a database access error occurs
9052      * @since 1.6
9053      */
9054      public void setNClob(int parameterIndex, NClob value) throws SQLException{
9055         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9056    }
9057 
9058 
9059    /**
9060   * Sets the designated parameter to the given <code>String</code> object.
9061   * The driver converts this to a SQL <code>NCHAR</code> or
9062   * <code>NVARCHAR</code> or <code>LONGNVARCHAR</code> value
9063   * (depending on the argument's
9064   * size relative to the driver's limits on <code>NVARCHAR</code> values)
9065   * when it sends it to the database.
9066   *
9067   * @param parameterIndex of the first parameter is 1, the second is 2, ...
9068   * @param value the parameter value
9069   * @throws SQLException if the driver does not support national
9070   *         character sets;  if the driver can detect that a data conversion
9071   *  error could occur ; or if a database access error occurs
9072   * @since 1.6
9073   */
9074   public void setNString(int parameterIndex, String value) throws SQLException{
9075         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9076    }
9077 
9078 
9079  /**
9080   * Sets the designated parameter to the given <code>String</code> object.
9081   * The driver converts this to a SQL <code>NCHAR</code> or
9082   * <code>NVARCHAR</code> or <code>LONGNVARCHAR</code>
9083   * @param parameterName the name of the column to be set
9084   * @param value the parameter value
9085   * @throws SQLException if the driver does not support national
9086   *         character sets;  if the driver can detect that a data conversion
9087   *  error could occur; or if a database access error occurs
9088   * @since 1.6
9089   */
9090  public void setNString(String parameterName, String value)
9091          throws SQLException{
9092         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9093    }
9094 
9095 
9096  /**
9097   * Sets the designated parameter to a <code>Reader</code> object. The
9098   * <code>Reader</code> reads the data till end-of-file is reached. The
9099   * driver does the necessary conversion from Java character format to
9100   * the national character set in the database.
9101   * @param parameterIndex of the first parameter is 1, the second is 2, ...
9102   * @param value the parameter value
9103   * @param length the number of characters in the parameter data.
9104   * @throws SQLException if the driver does not support national
9105   *         character sets;  if the driver can detect that a data conversion
9106   *  error could occur ; or if a database access error occurs
9107   * @since 1.6
9108   */
9109   public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException{
9110         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9111    }
9112 
9113 
9114  /**
9115   * Sets the designated parameter to a <code>Reader</code> object. The
9116   * <code>Reader</code> reads the data till end-of-file is reached. The
9117   * driver does the necessary conversion from Java character format to
9118   * the national character set in the database.
9119   * @param parameterName the name of the column to be set
9120   * @param value the parameter value
9121   * @param length the number of characters in the parameter data.
9122   * @throws SQLException if the driver does not support national
9123   *         character sets;  if the driver can detect that a data conversion
9124   *  error could occur; or if a database access error occurs
9125   * @since 1.6
9126   */
9127  public void setNCharacterStream(String parameterName, Reader value, long length)
9128          throws SQLException{
9129         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9130    }
9131 
9132   /**
9133   * Sets the designated parameter to a <code>Reader</code> object. The
9134   * <code>Reader</code> reads the data till end-of-file is reached. The
9135   * driver does the necessary conversion from Java character format to
9136   * the national character set in the database.
9137 
9138   * <P><B>Note:</B> This stream object can either be a standard
9139   * Java stream object or your own subclass that implements the
9140   * standard interface.
9141   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9142   * it might be more efficient to use a version of
9143   * <code>setNCharacterStream</code> which takes a length parameter.
9144   *
9145   * @param parameterName the name of the parameter
9146   * @param value the parameter value
9147   * @throws SQLException if the driver does not support national
9148   *         character sets;  if the driver can detect that a data conversion
9149   *  error could occur ; if a database access error occurs; or
9150   * this method is called on a closed <code>CallableStatement</code>
9151   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9152   * @since 1.6
9153   */
9154   public void setNCharacterStream(String parameterName, Reader value) throws SQLException{
9155         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9156    }
9157 
9158   /**
9159     * Sets the designated parameter to the given <code>java.sql.Timestamp</code> value,
9160     * using the given <code>Calendar</code> object.  The driver uses
9161     * the <code>Calendar</code> object to construct an SQL <code>TIMESTAMP</code> value,
9162     * which the driver then sends to the database.  With a
9163     * a <code>Calendar</code> object, the driver can calculate the timestamp
9164     * taking into account a custom timezone.  If no
9165     * <code>Calendar</code> object is specified, the driver uses the default
9166     * timezone, which is that of the virtual machine running the application.
9167     *
9168     * @param parameterName the name of the parameter
9169     * @param x the parameter value
9170     * @param cal the <code>Calendar</code> object the driver will use
9171     *            to construct the timestamp
9172     * @exception SQLException if a database access error occurs or
9173     * this method is called on a closed <code>CallableStatement</code>
9174     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9175     * this method
9176     * @see #getTimestamp
9177     * @since 1.4
9178     */
9179     public void setTimestamp(String parameterName, java.sql.Timestamp x, Calendar cal)
9180        throws SQLException{
9181         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9182    }
9183 
9184     /**
9185     * Sets the designated parameter to a <code>Reader</code> object.  The <code>reader</code> must contain  the number
9186                * of characters specified by length otherwise a <code>SQLException</code> will be
9187                * generated when the <code>CallableStatement</code> is executed.
9188               * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
9189               * because it informs the driver that the parameter value should be sent to
9190               * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9191               * driver may have to do extra work to determine whether the parameter
9192               * data should be send to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9193               * @param parameterName the name of the parameter to be set
9194               * @param reader An object that contains the data to set the parameter value to.
9195               * @param length the number of characters in the parameter data.
9196               * @throws SQLException if parameterIndex does not correspond to a parameter
9197               * marker in the SQL statement; if the length specified is less than zero;
9198               * a database access error occurs or
9199               * this method is called on a closed <code>CallableStatement</code>
9200               * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9201               * this method
9202               *
9203               * @since 1.6
9204               */
9205       public  void setClob(String parameterName, Reader reader, long length)
9206       throws SQLException{
9207         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9208    }
9209 
9210 
9211   /**
9212     * Sets the designated parameter to the given <code>java.sql.Clob</code> object.
9213     * The driver converts this to an SQL <code>CLOB</code> value when it
9214     * sends it to the database.
9215     *
9216     * @param parameterName the name of the parameter
9217     * @param x a <code>Clob</code> object that maps an SQL <code>CLOB</code> value
9218     * @exception SQLException if a database access error occurs or
9219     * this method is called on a closed <code>CallableStatement</code>
9220     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9221     * this method
9222     * @since 1.6
9223     */
9224     public void setClob (String parameterName, Clob x) throws SQLException{
9225         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9226    }
9227 
9228 
9229  /**
9230     * Sets the designated parameter to a <code>Reader</code> object.
9231     * This method differs from the <code>setCharacterStream (int, Reader)</code> method
9232     * because it informs the driver that the parameter value should be sent to
9233     * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9234     * driver may have to do extra work to determine whether the parameter
9235     * data should be send to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9236     *
9237     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9238     * it might be more efficient to use a version of
9239     * <code>setClob</code> which takes a length parameter.
9240     *
9241     * @param parameterName the name of the parameter
9242     * @param reader An object that contains the data to set the parameter value to.
9243     * @throws SQLException if a database access error occurs or this method is called on
9244     * a closed <code>CallableStatement</code>
9245     *
9246     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9247     * @since 1.6
9248     */
9249     public void setClob(String parameterName, Reader reader)
9250       throws SQLException{
9251         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9252    }
9253 
9254 
9255  /**
9256     * Sets the designated parameter to the given <code>java.sql.Date</code> value
9257     * using the default time zone of the virtual machine that is running
9258     * the application.
9259     * The driver converts this
9260     * to an SQL <code>DATE</code> value when it sends it to the database.
9261     *
9262     * @param parameterName the name of the parameter
9263     * @param x the parameter value
9264     * @exception SQLException if a database access error occurs or
9265     * this method is called on a closed <code>CallableStatement</code>
9266     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9267     * this method
9268     * @see #getDate
9269     * @since 1.4
9270     */
9271     public void setDate(String parameterName, java.sql.Date x)
9272        throws SQLException{
9273         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9274    }
9275 
9276 
9277  /**
9278     * Sets the designated parameter to the given <code>java.sql.Date</code> value,
9279     * using the given <code>Calendar</code> object.  The driver uses
9280     * the <code>Calendar</code> object to construct an SQL <code>DATE</code> value,
9281     * which the driver then sends to the database.  With a
9282     * a <code>Calendar</code> object, the driver can calculate the date
9283     * taking into account a custom timezone.  If no
9284     * <code>Calendar</code> object is specified, the driver uses the default
9285     * timezone, which is that of the virtual machine running the application.
9286     *
9287     * @param parameterName the name of the parameter
9288     * @param x the parameter value
9289     * @param cal the <code>Calendar</code> object the driver will use
9290     *            to construct the date
9291     * @exception SQLException if a database access error occurs or
9292     * this method is called on a closed <code>CallableStatement</code>
9293     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9294     * this method
9295     * @see #getDate
9296     * @since 1.4
9297     */
9298    public void setDate(String parameterName, java.sql.Date x, Calendar cal)
9299        throws SQLException{
9300         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9301    }
9302 
9303 
9304  /**
9305     * Sets the designated parameter to the given <code>java.sql.Time</code> value.
9306     * The driver converts this
9307     * to an SQL <code>TIME</code> value when it sends it to the database.
9308     *
9309     * @param parameterName the name of the parameter
9310     * @param x the parameter value
9311     * @exception SQLException if a database access error occurs or
9312     * this method is called on a closed <code>CallableStatement</code>
9313     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9314     * this method
9315     * @see #getTime
9316     * @since 1.4
9317     */
9318    public void setTime(String parameterName, java.sql.Time x)
9319        throws SQLException{
9320         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9321    }
9322 
9323 
9324  /**
9325     * Sets the designated parameter to the given <code>java.sql.Time</code> value,
9326     * using the given <code>Calendar</code> object.  The driver uses
9327     * the <code>Calendar</code> object to construct an SQL <code>TIME</code> value,
9328     * which the driver then sends to the database.  With a
9329     * a <code>Calendar</code> object, the driver can calculate the time
9330     * taking into account a custom timezone.  If no
9331     * <code>Calendar</code> object is specified, the driver uses the default
9332     * timezone, which is that of the virtual machine running the application.
9333     *
9334     * @param parameterName the name of the parameter
9335     * @param x the parameter value
9336     * @param cal the <code>Calendar</code> object the driver will use
9337     *            to construct the time
9338     * @exception SQLException if a database access error occurs or
9339     * this method is called on a closed <code>CallableStatement</code>
9340     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9341     * this method
9342     * @see #getTime
9343     * @since 1.4
9344     */
9345    public void setTime(String parameterName, java.sql.Time x, Calendar cal)
9346        throws SQLException{
9347         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9348    }
9349 
9350    /**
9351    * Sets the designated parameter to a <code>Reader</code> object.
9352    * This method differs from the <code>setCharacterStream (int, Reader)</code> method
9353    * because it informs the driver that the parameter value should be sent to
9354    * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9355    * driver may have to do extra work to determine whether the parameter
9356    * data should be sent to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9357    *
9358    * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9359    * it might be more efficient to use a version of
9360    * <code>setClob</code> which takes a length parameter.
9361    *
9362    * @param parameterIndex index of the first parameter is 1, the second is 2, ...
9363    * @param reader An object that contains the data to set the parameter value to.
9364    * @throws SQLException if a database access error occurs, this method is called on
9365    * a closed <code>PreparedStatement</code>or if parameterIndex does not correspond to a parameter
9366    * marker in the SQL statement
9367    *
9368    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9369    * @since 1.6
9370    */
9371    public void setClob(int parameterIndex, Reader reader)
9372      throws SQLException{
9373         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9374    }
9375 
9376     /**
9377    * Sets the designated parameter to a <code>Reader</code> object.  The reader must contain  the number
9378    * of characters specified by length otherwise a <code>SQLException</code> will be
9379    * generated when the <code>PreparedStatement</code> is executed.
9380    *This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
9381    * because it informs the driver that the parameter value should be sent to
9382    * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9383    * driver may have to do extra work to determine whether the parameter
9384    * data should be sent to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9385    * @param parameterIndex index of the first parameter is 1, the second is 2, ...
9386    * @param reader An object that contains the data to set the parameter value to.
9387    * @param length the number of characters in the parameter data.
9388    * @throws SQLException if a database access error occurs, this method is called on
9389    * a closed <code>PreparedStatement</code>, if parameterIndex does not correspond to a parameter
9390    * marker in the SQL statement, or if the length specified is less than zero.
9391    *
9392    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9393    * @since 1.6
9394    */
9395    public void setClob(int parameterIndex, Reader reader, long length)
9396      throws SQLException{
9397         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9398    }
9399 
9400 
9401  /**
9402     * Sets the designated parameter to a <code>InputStream</code> object.  The inputstream must contain  the number
9403     * of characters specified by length otherwise a <code>SQLException</code> will be
9404     * generated when the <code>PreparedStatement</code> is executed.
9405     * This method differs from the <code>setBinaryStream (int, InputStream, int)</code>
9406     * method because it informs the driver that the parameter value should be
9407     * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9408     * the driver may have to do extra work to determine whether the parameter
9409     * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9410     * @param parameterIndex index of the first parameter is 1,
9411     * the second is 2, ...
9412     * @param inputStream An object that contains the data to set the parameter
9413     * value to.
9414     * @param length the number of bytes in the parameter data.
9415     * @throws SQLException if a database access error occurs,
9416     * this method is called on a closed <code>PreparedStatement</code>,
9417     * if parameterIndex does not correspond
9418     * to a parameter marker in the SQL statement,  if the length specified
9419     * is less than zero or if the number of bytes in the inputstream does not match
9420     * the specified length.
9421     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9422     *
9423     * @since 1.6
9424     */
9425     public void setBlob(int parameterIndex, InputStream inputStream, long length)
9426        throws SQLException{
9427         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9428    }
9429 
9430 
9431  /**
9432     * Sets the designated parameter to a <code>InputStream</code> object.
9433     * This method differs from the <code>setBinaryStream (int, InputStream)</code>
9434     * method because it informs the driver that the parameter value should be
9435     * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9436     * the driver may have to do extra work to determine whether the parameter
9437     * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9438     *
9439     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9440     * it might be more efficient to use a version of
9441     * <code>setBlob</code> which takes a length parameter.
9442     *
9443     * @param parameterIndex index of the first parameter is 1,
9444     * the second is 2, ...
9445     * @param inputStream An object that contains the data to set the parameter
9446     * value to.
9447     * @throws SQLException if a database access error occurs,
9448     * this method is called on a closed <code>PreparedStatement</code> or
9449     * if parameterIndex does not correspond
9450     * to a parameter marker in the SQL statement,
9451     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9452     *
9453     * @since 1.6
9454     */
9455     public void setBlob(int parameterIndex, InputStream inputStream)
9456        throws SQLException{
9457         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9458    }
9459 
9460 
9461  /**
9462     * Sets the designated parameter to a <code>InputStream</code> object.  The <code>inputstream</code> must contain  the number
9463      * of characters specified by length, otherwise a <code>SQLException</code> will be
9464      * generated when the <code>CallableStatement</code> is executed.
9465      * This method differs from the <code>setBinaryStream (int, InputStream, int)</code>
9466      * method because it informs the driver that the parameter value should be
9467      * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9468      * the driver may have to do extra work to determine whether the parameter
9469      * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9470      *
9471      * @param parameterName the name of the parameter to be set
9472      * the second is 2, ...
9473      *
9474      * @param inputStream An object that contains the data to set the parameter
9475      * value to.
9476      * @param length the number of bytes in the parameter data.
9477      * @throws SQLException  if parameterIndex does not correspond
9478      * to a parameter marker in the SQL statement,  or if the length specified
9479      * is less than zero; if the number of bytes in the inputstream does not match
9480      * the specified length; if a database access error occurs or
9481      * this method is called on a closed <code>CallableStatement</code>
9482      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9483      * this method
9484      *
9485      * @since 1.6
9486      */
9487      public void setBlob(String parameterName, InputStream inputStream, long length)
9488         throws SQLException{
9489         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9490    }
9491 
9492 
9493  /**
9494     * Sets the designated parameter to the given <code>java.sql.Blob</code> object.
9495     * The driver converts this to an SQL <code>BLOB</code> value when it
9496     * sends it to the database.
9497     *
9498     * @param parameterName the name of the parameter
9499     * @param x a <code>Blob</code> object that maps an SQL <code>BLOB</code> value
9500     * @exception SQLException if a database access error occurs or
9501     * this method is called on a closed <code>CallableStatement</code>
9502     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9503     * this method
9504     * @since 1.6
9505     */
9506    public void setBlob (String parameterName, Blob x) throws SQLException{
9507         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9508    }
9509 
9510 
9511  /**
9512     * Sets the designated parameter to a <code>InputStream</code> object.
9513     * This method differs from the <code>setBinaryStream (int, InputStream)</code>
9514     * method because it informs the driver that the parameter value should be
9515     * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9516     * the driver may have to do extra work to determine whether the parameter
9517     * data should be send to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9518     *
9519     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9520     * it might be more efficient to use a version of
9521     * <code>setBlob</code> which takes a length parameter.
9522     *
9523     * @param parameterName the name of the parameter
9524     * @param inputStream An object that contains the data to set the parameter
9525     * value to.
9526     * @throws SQLException if a database access error occurs or
9527     * this method is called on a closed <code>CallableStatement</code>
9528     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9529     *
9530     * @since 1.6
9531     */
9532     public void setBlob(String parameterName, InputStream inputStream)
9533        throws SQLException{
9534         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9535    }
9536 
9537     /**
9538     * Sets the value of the designated parameter with the given object. The second
9539     * argument must be an object type; for integral values, the
9540     * <code>java.lang</code> equivalent objects should be used.
9541     *
9542     * <p>The given Java object will be converted to the given targetSqlType
9543     * before being sent to the database.
9544     *
9545     * If the object has a custom mapping (is of a class implementing the
9546     * interface <code>SQLData</code>),
9547     * the JDBC driver should call the method <code>SQLData.writeSQL</code> to write it
9548     * to the SQL data stream.
9549     * If, on the other hand, the object is of a class implementing
9550     * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>,  <code>NClob</code>,
9551     *  <code>Struct</code>, <code>java.net.URL</code>,
9552     * or <code>Array</code>, the driver should pass it to the database as a
9553     * value of the corresponding SQL type.
9554     * <P>
9555     * Note that this method may be used to pass datatabase-
9556     * specific abstract data types.
9557     *
9558     * @param parameterName the name of the parameter
9559     * @param x the object containing the input parameter value
9560     * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
9561     * sent to the database. The scale argument may further qualify this type.
9562     * @param scale for java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types,
9563     *          this is the number of digits after the decimal point.  For all other
9564     *          types, this value will be ignored.
9565     * @exception SQLException if a database access error occurs or
9566     * this method is called on a closed <code>CallableStatement</code>
9567     * @exception SQLFeatureNotSupportedException if <code>targetSqlType</code> is
9568     * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,
9569     * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,
9570     * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,
9571     *  <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
9572     * or  <code>STRUCT</code> data type and the JDBC driver does not support
9573     * this data type
9574     * @see Types
9575     * @see #getObject
9576     * @since 1.4
9577     */
9578     public void setObject(String parameterName, Object x, int targetSqlType, int scale)
9579        throws SQLException{
9580         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9581    }
9582 
9583 
9584 
9585  /**
9586     * Sets the value of the designated parameter with the given object.
9587     * This method is like the method <code>setObject</code>
9588     * above, except that it assumes a scale of zero.
9589     *
9590     * @param parameterName the name of the parameter
9591     * @param x the object containing the input parameter value
9592     * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
9593     *                      sent to the database
9594     * @exception SQLException if a database access error occurs or
9595     * this method is called on a closed <code>CallableStatement</code>
9596     * @exception SQLFeatureNotSupportedException if <code>targetSqlType</code> is
9597     * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,
9598     * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,
9599     * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,
9600     *  <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
9601     * or  <code>STRUCT</code> data type and the JDBC driver does not support
9602     * this data type
9603     * @see #getObject
9604     * @since 1.4
9605     */
9606     public void setObject(String parameterName, Object x, int targetSqlType)
9607        throws SQLException{
9608         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9609    }
9610 
9611 
9612  /**
9613    * Sets the value of the designated parameter with the given object.
9614    * The second parameter must be of type <code>Object</code>; therefore, the
9615    * <code>java.lang</code> equivalent objects should be used for built-in types.
9616    *
9617    * <p>The JDBC specification specifies a standard mapping from
9618    * Java <code>Object</code> types to SQL types.  The given argument
9619    * will be converted to the corresponding SQL type before being
9620    * sent to the database.
9621    *
9622    * <p>Note that this method may be used to pass datatabase-
9623    * specific abstract data types, by using a driver-specific Java
9624    * type.
9625    *
9626    * If the object is of a class implementing the interface <code>SQLData</code>,
9627    * the JDBC driver should call the method <code>SQLData.writeSQL</code>
9628    * to write it to the SQL data stream.
9629    * If, on the other hand, the object is of a class implementing
9630    * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>,  <code>NClob</code>,
9631    *  <code>Struct</code>, <code>java.net.URL</code>,
9632    * or <code>Array</code>, the driver should pass it to the database as a
9633    * value of the corresponding SQL type.
9634    * <P>
9635    * This method throws an exception if there is an ambiguity, for example, if the
9636    * object is of a class implementing more than one of the interfaces named above.
9637    *
9638    * @param parameterName the name of the parameter
9639    * @param x the object containing the input parameter value
9640    * @exception SQLException if a database access error occurs,
9641    * this method is called on a closed <code>CallableStatement</code> or if the given
9642    *            <code>Object</code> parameter is ambiguous
9643    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9644    * this method
9645    * @see #getObject
9646    * @since 1.4
9647    */
9648    public void setObject(String parameterName, Object x) throws SQLException{
9649         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9650    }
9651 
9652     /**
9653     * Sets the designated parameter to the given input stream, which will have
9654     * the specified number of bytes.
9655     * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
9656     * parameter, it may be more practical to send it via a
9657     * <code>java.io.InputStream</code>. Data will be read from the stream
9658     * as needed until end-of-file is reached.  The JDBC driver will
9659     * do any necessary conversion from ASCII to the database char format.
9660     *
9661     * <P><B>Note:</B> This stream object can either be a standard
9662     * Java stream object or your own subclass that implements the
9663     * standard interface.
9664     *
9665     * @param parameterName the name of the parameter
9666     * @param x the Java input stream that contains the ASCII parameter value
9667     * @param length the number of bytes in the stream
9668     * @exception SQLException if a database access error occurs or
9669     * this method is called on a closed <code>CallableStatement</code>
9670     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9671     * this method
9672     * @since 1.4
9673     */
9674    public void setAsciiStream(String parameterName, java.io.InputStream x, int length)
9675        throws SQLException{
9676         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9677    }
9678 
9679 
9680  /**
9681     * Sets the designated parameter to the given input stream, which will have
9682     * the specified number of bytes.
9683     * When a very large binary value is input to a <code>LONGVARBINARY</code>
9684     * parameter, it may be more practical to send it via a
9685     * <code>java.io.InputStream</code> object. The data will be read from the stream
9686     * as needed until end-of-file is reached.
9687     *
9688     * <P><B>Note:</B> This stream object can either be a standard
9689     * Java stream object or your own subclass that implements the
9690     * standard interface.
9691     *
9692     * @param parameterName the name of the parameter
9693     * @param x the java input stream which contains the binary parameter value
9694     * @param length the number of bytes in the stream
9695     * @exception SQLException if a database access error occurs or
9696     * this method is called on a closed <code>CallableStatement</code>
9697     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9698     * this method
9699     * @since 1.4
9700     */
9701    public void setBinaryStream(String parameterName, java.io.InputStream x,
9702                         int length) throws SQLException{
9703         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9704    }
9705 
9706 
9707   /**
9708     * Sets the designated parameter to the given <code>Reader</code>
9709     * object, which is the given number of characters long.
9710     * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
9711     * parameter, it may be more practical to send it via a
9712     * <code>java.io.Reader</code> object. The data will be read from the stream
9713     * as needed until end-of-file is reached.  The JDBC driver will
9714     * do any necessary conversion from UNICODE to the database char format.
9715     *
9716     * <P><B>Note:</B> This stream object can either be a standard
9717     * Java stream object or your own subclass that implements the
9718     * standard interface.
9719     *
9720     * @param parameterName the name of the parameter
9721     * @param reader the <code>java.io.Reader</code> object that
9722     *        contains the UNICODE data used as the designated parameter
9723     * @param length the number of characters in the stream
9724     * @exception SQLException if a database access error occurs or
9725     * this method is called on a closed <code>CallableStatement</code>
9726     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9727     * this method
9728     * @since 1.4
9729     */
9730    public void setCharacterStream(String parameterName,
9731                            java.io.Reader reader,
9732                            int length) throws SQLException{
9733         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9734    }
9735 
9736 
9737   /**
9738    * Sets the designated parameter to the given input stream.
9739    * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
9740    * parameter, it may be more practical to send it via a
9741    * <code>java.io.InputStream</code>. Data will be read from the stream
9742    * as needed until end-of-file is reached.  The JDBC driver will
9743    * do any necessary conversion from ASCII to the database char format.
9744    *
9745    * <P><B>Note:</B> This stream object can either be a standard
9746    * Java stream object or your own subclass that implements the
9747    * standard interface.
9748    * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9749    * it might be more efficient to use a version of
9750    * <code>setAsciiStream</code> which takes a length parameter.
9751    *
9752    * @param parameterName the name of the parameter
9753    * @param x the Java input stream that contains the ASCII parameter value
9754    * @exception SQLException if a database access error occurs or
9755    * this method is called on a closed <code>CallableStatement</code>
9756    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9757      * @since 1.6
9758   */
9759   public void setAsciiStream(String parameterName, java.io.InputStream x)
9760           throws SQLException{
9761         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9762    }
9763 
9764 
9765  /**
9766     * Sets the designated parameter to the given input stream.
9767     * When a very large binary value is input to a <code>LONGVARBINARY</code>
9768     * parameter, it may be more practical to send it via a
9769     * <code>java.io.InputStream</code> object. The data will be read from the
9770     * stream as needed until end-of-file is reached.
9771     *
9772     * <P><B>Note:</B> This stream object can either be a standard
9773     * Java stream object or your own subclass that implements the
9774     * standard interface.
9775     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9776     * it might be more efficient to use a version of
9777     * <code>setBinaryStream</code> which takes a length parameter.
9778     *
9779     * @param parameterName the name of the parameter
9780     * @param x the java input stream which contains the binary parameter value
9781     * @exception SQLException if a database access error occurs or
9782     * this method is called on a closed <code>CallableStatement</code>
9783     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9784     * @since 1.6
9785     */
9786    public void setBinaryStream(String parameterName, java.io.InputStream x)
9787    throws SQLException{
9788         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9789    }
9790 
9791 
9792 
9793  /**
9794     * Sets the designated parameter to the given <code>Reader</code>
9795     * object.
9796     * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
9797     * parameter, it may be more practical to send it via a
9798     * <code>java.io.Reader</code> object. The data will be read from the stream
9799     * as needed until end-of-file is reached.  The JDBC driver will
9800     * do any necessary conversion from UNICODE to the database char format.
9801     *
9802     * <P><B>Note:</B> This stream object can either be a standard
9803     * Java stream object or your own subclass that implements the
9804     * standard interface.
9805     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9806     * it might be more efficient to use a version of
9807     * <code>setCharacterStream</code> which takes a length parameter.
9808     *
9809     * @param parameterName the name of the parameter
9810     * @param reader the <code>java.io.Reader</code> object that contains the
9811     *        Unicode data
9812     * @exception SQLException if a database access error occurs or
9813     * this method is called on a closed <code>CallableStatement</code>
9814     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9815     * @since 1.6
9816     */
9817    public void setCharacterStream(String parameterName,
9818                          java.io.Reader reader) throws SQLException{
9819         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9820    }
9821 
9822    /**
9823     * Sets the designated parameter to the given
9824     * <code>java.math.BigDecimal</code> value.
9825     * The driver converts this to an SQL <code>NUMERIC</code> value when
9826     * it sends it to the database.
9827     *
9828     * @param parameterName the name of the parameter
9829     * @param x the parameter value
9830     * @exception SQLException if a database access error occurs or
9831     * this method is called on a closed <code>CallableStatement</code>
9832     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9833     * this method
9834     * @see #getBigDecimal
9835     * @since 1.4
9836     */
9837    public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException{
9838         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9839    }
9840 
9841 
9842 
9843  /**
9844     * Sets the designated parameter to the given Java <code>String</code> value.
9845     * The driver converts this
9846     * to an SQL <code>VARCHAR</code> or <code>LONGVARCHAR</code> value
9847     * (depending on the argument's
9848     * size relative to the driver's limits on <code>VARCHAR</code> values)
9849     * when it sends it to the database.
9850     *
9851     * @param parameterName the name of the parameter
9852     * @param x the parameter value
9853     * @exception SQLException if a database access error occurs or
9854     * this method is called on a closed <code>CallableStatement</code>
9855     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9856     * this method
9857     * @see #getString
9858     * @since 1.4
9859     */
9860    public void setString(String parameterName, String x) throws SQLException{
9861         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9862    }
9863 
9864 
9865 
9866  /**
9867     * Sets the designated parameter to the given Java array of bytes.
9868     * The driver converts this to an SQL <code>VARBINARY</code> or
9869     * <code>LONGVARBINARY</code> (depending on the argument's size relative
9870     * to the driver's limits on <code>VARBINARY</code> values) when it sends
9871     * it to the database.
9872     *
9873     * @param parameterName the name of the parameter
9874     * @param x the parameter value
9875     * @exception SQLException if a database access error occurs or
9876     * this method is called on a closed <code>CallableStatement</code>
9877     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9878     * this method
9879     * @see #getBytes
9880     * @since 1.4
9881     */
9882    public void setBytes(String parameterName, byte x[]) throws SQLException{
9883         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9884    }
9885 
9886 
9887 
9888  /**
9889     * Sets the designated parameter to the given <code>java.sql.Timestamp</code> value.
9890     * The driver
9891     * converts this to an SQL <code>TIMESTAMP</code> value when it sends it to the
9892     * database.
9893     *
9894     * @param parameterName the name of the parameter
9895     * @param x the parameter value
9896     * @exception SQLException if a database access error occurs or
9897     * this method is called on a closed <code>CallableStatement</code>
9898     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9899     * this method
9900     * @see #getTimestamp
9901     * @since 1.4
9902     */
9903    public void setTimestamp(String parameterName, java.sql.Timestamp x)
9904        throws SQLException{
9905         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9906    }
9907 
9908     /**
9909     * Sets the designated parameter to SQL <code>NULL</code>.
9910     *
9911     * <P><B>Note:</B> You must specify the parameter's SQL type.
9912     *
9913     * @param parameterName the name of the parameter
9914     * @param sqlType the SQL type code defined in <code>java.sql.Types</code>
9915     * @exception SQLException if a database access error occurs or
9916     * this method is called on a closed <code>CallableStatement</code>
9917     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9918     * this method
9919     * @since 1.4
9920     */
9921    public void setNull(String parameterName, int sqlType) throws SQLException {
9922         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9923    }
9924 
9925 
9926  /**
9927     * Sets the designated parameter to SQL <code>NULL</code>.
9928     * This version of the method <code>setNull</code> should
9929     * be used for user-defined types and REF type parameters.  Examples
9930     * of user-defined types include: STRUCT, DISTINCT, JAVA_OBJECT, and
9931     * named array types.
9932     *
9933     * <P><B>Note:</B> To be portable, applications must give the
9934     * SQL type code and the fully-qualified SQL type name when specifying
9935     * a NULL user-defined or REF parameter.  In the case of a user-defined type
9936     * the name is the type name of the parameter itself.  For a REF
9937     * parameter, the name is the type name of the referenced type.  If
9938     * a JDBC driver does not need the type code or type name information,
9939     * it may ignore it.
9940     *
9941     * Although it is intended for user-defined and Ref parameters,
9942     * this method may be used to set a null parameter of any JDBC type.
9943     * If the parameter does not have a user-defined or REF type, the given
9944     * typeName is ignored.
9945     *
9946     *
9947     * @param parameterName the name of the parameter
9948     * @param sqlType a value from <code>java.sql.Types</code>
9949     * @param typeName the fully-qualified name of an SQL user-defined type;
9950     *        ignored if the parameter is not a user-defined type or
9951     *        SQL <code>REF</code> value
9952     * @exception SQLException if a database access error occurs or
9953     * this method is called on a closed <code>CallableStatement</code>
9954     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9955     * this method
9956     * @since 1.4
9957     */
9958    public void setNull (String parameterName, int sqlType, String typeName)
9959        throws SQLException{
9960         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9961    }
9962 
9963 
9964 
9965  /**
9966     * Sets the designated parameter to the given Java <code>boolean</code> value.
9967     * The driver converts this
9968     * to an SQL <code>BIT</code> or <code>BOOLEAN</code> value when it sends it to the database.
9969     *
9970     * @param parameterName the name of the parameter
9971     * @param x the parameter value
9972     * @exception SQLException if a database access error occurs or
9973     * this method is called on a closed <code>CallableStatement</code>
9974     * @see #getBoolean
9975     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9976     * this method
9977     * @since 1.4
9978     */
9979    public void setBoolean(String parameterName, boolean x) throws SQLException{
9980         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9981    }
9982 
9983 
9984 
9985  /**
9986     * Sets the designated parameter to the given Java <code>byte</code> value.
9987     * The driver converts this
9988     * to an SQL <code>TINYINT</code> value when it sends it to the database.
9989     *
9990     * @param parameterName the name of the parameter
9991     * @param x the parameter value
9992     * @exception SQLException if a database access error occurs or
9993     * this method is called on a closed <code>CallableStatement</code>
9994     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9995     * this method
9996     * @see #getByte
9997     * @since 1.4
9998     */
9999    public void setByte(String parameterName, byte x) throws SQLException{
10000         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10001    }
10002 
10003 
10004 
10005  /**
10006     * Sets the designated parameter to the given Java <code>short</code> value.
10007     * The driver converts this
10008     * to an SQL <code>SMALLINT</code> value when it sends it to the database.
10009     *
10010     * @param parameterName the name of the parameter
10011     * @param x the parameter value
10012     * @exception SQLException if a database access error occurs or
10013     * this method is called on a closed <code>CallableStatement</code>
10014     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10015     * this method
10016     * @see #getShort
10017     * @since 1.4
10018     */
10019    public void setShort(String parameterName, short x) throws SQLException{
10020         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10021    }
10022 
10023 
10024  /**
10025     * Sets the designated parameter to the given Java <code>int</code> value.
10026     * The driver converts this
10027     * to an SQL <code>INTEGER</code> value when it sends it to the database.
10028     *
10029     * @param parameterName the name of the parameter
10030     * @param x the parameter value
10031     * @exception SQLException if a database access error occurs or
10032     * this method is called on a closed <code>CallableStatement</code>
10033     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10034     * this method
10035     * @see #getInt
10036     * @since 1.4
10037     */
10038    public void setInt(String parameterName, int x) throws SQLException{
10039         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10040    }
10041 
10042 
10043  /**
10044     * Sets the designated parameter to the given Java <code>long</code> value.
10045     * The driver converts this
10046     * to an SQL <code>BIGINT</code> value when it sends it to the database.
10047     *
10048     * @param parameterName the name of the parameter
10049     * @param x the parameter value
10050     * @exception SQLException if a database access error occurs or
10051     * this method is called on a closed <code>CallableStatement</code>
10052     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10053     * this method
10054     * @see #getLong
10055     * @since 1.4
10056     */
10057    public void setLong(String parameterName, long x) throws SQLException{
10058         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10059    }
10060 
10061 
10062  /**
10063     * Sets the designated parameter to the given Java <code>float</code> value.
10064     * The driver converts this
10065     * to an SQL <code>FLOAT</code> value when it sends it to the database.
10066     *
10067     * @param parameterName the name of the parameter
10068     * @param x the parameter value
10069     * @exception SQLException if a database access error occurs or
10070     * this method is called on a closed <code>CallableStatement</code>
10071     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10072     * this method
10073     * @see #getFloat
10074     * @since 1.4
10075     */
10076    public void setFloat(String parameterName, float x) throws SQLException{
10077         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10078    }
10079 
10080 
10081  /**
10082     * Sets the designated parameter to the given Java <code>double</code> value.
10083     * The driver converts this
10084     * to an SQL <code>DOUBLE</code> value when it sends it to the database.
10085     *
10086     * @param parameterName the name of the parameter
10087     * @param x the parameter value
10088     * @exception SQLException if a database access error occurs or
10089     * this method is called on a closed <code>CallableStatement</code>
10090     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10091     * this method
10092     * @see #getDouble
10093     * @since 1.4
10094     */
10095    public void setDouble(String parameterName, double x) throws SQLException{
10096         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10097    }
10098 
10099    /**
10100      * This method re populates the resBundle
10101      * during the deserialization process
10102      *
10103      */
10104     private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
10105         // Default state initialization happens here
10106         ois.defaultReadObject();
10107         // Initialization of transient Res Bundle happens here .
10108         try {
10109            resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
10110         } catch(IOException ioe) {
10111             throw new RuntimeException(ioe);
10112         }
10113 
10114     }
10115 
10116     //------------------------- JDBC 4.1 -----------------------------------
10117     public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
10118         throw new SQLFeatureNotSupportedException("Not supported yet.");
10119     }
10120 
10121     public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
10122         throw new SQLFeatureNotSupportedException("Not supported yet.");
10123     }
10124 
10125     static final long serialVersionUID =1884577171200622428L;
10126 }