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</code 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 ((new Float(value.toString())).floatValue());
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 ((new Double(value.toString().trim())).doubleValue());
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, <b>CHAR</b>,
2472      * <b>VARCHAR</b></code> or <code>LONGVARCHAR<</code> value. The bold SQL type
2473      * designates the recommended return type.
2474      */
2475     public String getString(String columnName) throws SQLException {
2476         return getString(getColIdxByName(columnName));
2477     }
2478 
2479     /**
2480      * Retrieves the value stored in the designated column
2481      * of the current row as a <code>boolean</code> value.
2482      *
2483      * @param columnName a <code>String</code> object giving the SQL name of
2484      *        a column in this <code>CachedRowSetImpl</code> object
2485      * @return the column value as a <code>boolean</code> in the Java programming
2486      *        language; if the value is SQL <code>NULL</code>,
2487      *        the result is <code>false</code>
2488      * @throws SQLException if (1) the given column name is not the name of
2489      *            a column in this rowset, (2) the cursor is not on one of
2490      *            this rowset's rows or its insert row, or (3) the designated
2491      *            column does not store an SQL <code>BOOLEAN</code> value
2492      * @see #getBoolean(int)
2493      */
2494     public boolean getBoolean(String columnName) throws SQLException {
2495         return getBoolean(getColIdxByName(columnName));
2496     }
2497 
2498     /**
2499      * Retrieves the value stored in the designated column
2500      * of the current row as a <code>byte</code> value.
2501      *
2502      * @param columnName a <code>String</code> object giving the SQL name of
2503      *        a column in this <code>CachedRowSetImpl</code> object
2504      * @return the column value as a <code>byte</code> in the Java programming
2505      * language; if the value is SQL <code>NULL</code>, the result is <code>0</code>
2506      * @throws SQLException if (1) the given column name is not the name of
2507      * a column in this rowset, (2) the cursor is not on one of
2508      * this rowset's rows or its insert row, or (3) the designated
2509      * column does not store an SQL <code><B>TINYINT</B>, SMALLINT, INTEGER,
2510      * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2511      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The
2512      * bold type designates the recommended return type
2513      */
2514     public byte getByte(String columnName) throws SQLException {
2515         return getByte(getColIdxByName(columnName));
2516     }
2517 
2518     /**
2519      * Retrieves the value stored in the designated column
2520      * of the current row as a <code>short</code> value.
2521      *
2522      * @param columnName a <code>String</code> object giving the SQL name of
2523      *        a column in this <code>CachedRowSetImpl</code> object
2524      * @return the column value; if the value is SQL <code>NULL</code>,
2525      *         the result is <code>0</code>
2526      * @throws SQLException if (1) the given column name is not the name of
2527      * a column in this rowset, (2) the cursor is not on one of
2528      * this rowset's rows or its insert row, or (3) the designated
2529      * column does not store an SQL <code>TINYINT, <b>SMALLINT</b>, INTEGER
2530      * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2531      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2532      * designates the recommended return type.
2533      * @see #getShort(int)
2534      */
2535     public short getShort(String columnName) throws SQLException {
2536         return getShort(getColIdxByName(columnName));
2537     }
2538 
2539     /**
2540      * Retrieves the value stored in the designated column
2541      * of the current row as an <code>int</code> value.
2542      *
2543      * @param columnName a <code>String</code> object giving the SQL name of
2544      *        a column in this <code>CachedRowSetImpl</code> object
2545      * @return the column value; if the value is SQL <code>NULL</code>,
2546      *         the result is <code>0</code>
2547      * @throws SQLException if (1) the given column name is not the name
2548      * of a column in this rowset,
2549      * (2) the cursor is not on one of this rowset's rows or its
2550      * insert row, or (3) the designated column does not store an
2551      * SQL <code>TINYINT, SMALLINT, <b>INTEGER</b>, BIGINT, REAL
2552      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
2553      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
2554      * recommended return type.
2555      */
2556     public int getInt(String columnName) throws SQLException {
2557         return getInt(getColIdxByName(columnName));
2558     }
2559 
2560     /**
2561      * Retrieves the value stored in the designated column
2562      * of the current row as a <code>long</code> value.
2563      *
2564      * @param columnName a <code>String</code> object giving the SQL name of
2565      *        a column in this <code>CachedRowSetImpl</code> object
2566      * @return the column value; if the value is SQL <code>NULL</code>,
2567      *         the result is <code>0</code>
2568      * @throws SQLException if (1) the given column name is not the name of
2569      * a column in this rowset, (2) the cursor is not on one of
2570      * this rowset's rows or its insert row, or (3) the designated
2571      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2572      * <b>BIGINT</b>, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2573      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2574      * designates the recommended return type.
2575      * @see #getLong(int)
2576      */
2577     public long getLong(String columnName) throws SQLException {
2578         return getLong(getColIdxByName(columnName));
2579     }
2580 
2581     /**
2582      * Retrieves the value stored in the designated column
2583      * of the current row as a <code>float</code> value.
2584      *
2585      * @param columnName a <code>String</code> object giving the SQL name of
2586      *        a column in this <code>CachedRowSetImpl</code> object
2587      * @return the column value; if the value is SQL <code>NULL</code>,
2588      *         the result is <code>0</code>
2589      * @throws SQLException if (1) the given column name is not the name of
2590      * a column in this rowset, (2) the cursor is not on one of
2591      * this rowset's rows or its insert row, or (3) the designated
2592      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2593      * BIGINT, <b>REAL</b>, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2594      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2595      * designates the recommended return type.
2596      * @see #getFloat(String)
2597      */
2598     public float getFloat(String columnName) throws SQLException {
2599         return getFloat(getColIdxByName(columnName));
2600     }
2601 
2602     /**
2603      * Retrieves the value stored in the designated column
2604      * of the current row of this <code>CachedRowSetImpl</code> object
2605      * as a <code>double</code> value.
2606      *
2607      * @param columnName a <code>String</code> object giving the SQL name of
2608      *        a column in this <code>CachedRowSetImpl</code> object
2609      * @return the column value; if the value is SQL <code>NULL</code>,
2610      *         the result is <code>0</code>
2611      * @throws SQLException if (1) the given column name is not the name of
2612      * a column in this rowset, (2) the cursor is not on one of
2613      * this rowset's rows or its insert row, or (3) the designated
2614      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2615      * BIGINT, REAL, <b>FLOAT</b>, <b>DOUBLE</b>, DECIMAL, NUMERIC, BIT, CHAR,
2616      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2617      * designates the recommended return types.
2618      * @see #getDouble(int)
2619      */
2620     public double getDouble(String columnName) throws SQLException {
2621         return getDouble(getColIdxByName(columnName));
2622     }
2623 
2624     /**
2625      * Retrieves the value stored in the designated column
2626      * of the current row as a <code>java.math.BigDecimal</code> object.
2627      *
2628      * @param columnName a <code>String</code> object giving the SQL name of
2629      *        a column in this <code>CachedRowSetImpl</code> object
2630      * @param scale the number of digits to the right of the decimal point
2631      * @return a java.math.BugDecimal object with <code><i>scale</i></code>
2632      * number of digits to the right of the decimal point.
2633      * @throws SQLException if (1) the given column name is not the name of
2634      * a column in this rowset, (2) the cursor is not on one of
2635      * this rowset's rows or its insert row, or (3) the designated
2636      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2637      * BIGINT, REAL, FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT CHAR,
2638      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2639      * designates the recommended return type that this method is used to
2640      * retrieve.
2641      * @deprecated Use the <code>getBigDecimal(String columnName)</code>
2642      *             method instead
2643      */
2644     @Deprecated
2645     public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {
2646         return getBigDecimal(getColIdxByName(columnName), scale);
2647     }
2648 
2649     /**
2650      * Retrieves the value stored in the designated column
2651      * of the current row as a <code>byte</code> array.
2652      * The bytes represent the raw values returned by the driver.
2653      *
2654      * @param columnName a <code>String</code> object giving the SQL name of
2655      *        a column in this <code>CachedRowSetImpl</code> object
2656      * @return the column value as a <code>byte</code> array in the Java programming
2657      * language; if the value is SQL <code>NULL</code>, the result is <code>null</code>
2658      * @throws SQLException if (1) the given column name is not the name of
2659      * a column in this rowset, (2) the cursor is not on one of
2660      * this rowset's rows or its insert row, or (3) the designated
2661      * column does not store an SQL <code><b>BINARY</b>, <b>VARBINARY</b>
2662      * </code> or <code>LONGVARBINARY</code> values
2663      * The bold SQL type designates the recommended return type.
2664      * @see #getBytes(int)
2665      */
2666     public byte[] getBytes(String columnName) throws SQLException {
2667         return getBytes(getColIdxByName(columnName));
2668     }
2669 
2670     /**
2671      * Retrieves the value stored in the designated column
2672      * of the current row as a <code>java.sql.Date</code> object.
2673      *
2674      * @param columnName a <code>String</code> object giving the SQL name of
2675      *        a column in this <code>CachedRowSetImpl</code> object
2676      * @return the column value; if the value is SQL <code>NULL</code>,
2677      *         the result is <code>null</code>
2678      * @throws SQLException if (1) the given column name is not the name of
2679      *            a column in this rowset, (2) the cursor is not on one of
2680      *            this rowset's rows or its insert row, or (3) the designated
2681      *            column does not store an SQL <code>DATE</code> or
2682      *            <code>TIMESTAMP</code> value
2683      */
2684     public java.sql.Date getDate(String columnName) throws SQLException {
2685         return getDate(getColIdxByName(columnName));
2686     }
2687 
2688     /**
2689      * Retrieves the value stored in the designated column
2690      * of the current row as a <code>java.sql.Time</code> object.
2691      *
2692      * @param columnName a <code>String</code> object giving the SQL name of
2693      *        a column in this <code>CachedRowSetImpl</code> object
2694      * @return the column value; if the value is SQL <code>NULL</code>,
2695      *         the result is <code>null</code>
2696      * @throws SQLException if the given column name does not match one of
2697      *            this rowset's column names or the cursor is not on one of
2698      *            this rowset's rows or its insert row
2699      */
2700     public java.sql.Time getTime(String columnName) throws SQLException {
2701         return getTime(getColIdxByName(columnName));
2702     }
2703 
2704     /**
2705      * Retrieves the value stored in the designated column
2706      * of the current row as a <code>java.sql.Timestamp</code> object.
2707      *
2708      * @param columnName a <code>String</code> object giving the SQL name of
2709      *        a column in this <code>CachedRowSetImpl</code> object
2710      * @return the column value; if the value is SQL <code>NULL</code>,
2711      *         the result is <code>null</code>
2712      * @throws SQLException if the given column name does not match one of
2713      *            this rowset's column names or the cursor is not on one of
2714      *            this rowset's rows or its insert row
2715      */
2716     public java.sql.Timestamp getTimestamp(String columnName) throws SQLException {
2717         return getTimestamp(getColIdxByName(columnName));
2718     }
2719 
2720     /**
2721      * Retrieves the value of the designated column in the current row of this
2722      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2723      * object.
2724      *
2725      * A column value can be retrieved as a stream of ASCII characters
2726      * and then read in chunks from the stream. This method is particularly
2727      * suitable for retrieving large <code>LONGVARCHAR</code> values. The
2728      * <code>SyncProvider</code> will rely on the JDBC driver to do any necessary
2729      * conversion from the database format into ASCII format.
2730      *
2731      * <P><B>Note:</B> All the data in the returned stream must
2732      * be read prior to getting the value of any other column. The
2733      * next call to a <code>getXXX</code> method implicitly closes the stream.
2734      *
2735      * @param columnName a <code>String</code> object giving the SQL name of
2736      *        a column in this <code>CachedRowSetImpl</code> object
2737      * @return a Java input stream that delivers the database column value
2738      *         as a stream of one-byte ASCII characters.  If the value is SQL
2739      *         <code>NULL</code>, the result is <code>null</code>.
2740      * @throws SQLException if (1) the given column name is not the name of
2741      * a column in this rowset
2742      * (2) the cursor is not on one of this rowset's rows or its
2743      * insert row, or (3) the designated column does not store an
2744      * SQL <code>CHAR, VARCHAR</code>, <code><b>LONGVARCHAR</b></code>
2745      * <code>BINARY, VARBINARY</code> or <code>LONGVARBINARY</code> value. The
2746      * bold SQL type designates the recommended return types that this method is
2747      * used to retrieve.
2748      * @see #getAsciiStream(int)
2749      */
2750     public java.io.InputStream getAsciiStream(String columnName) throws SQLException {
2751         return getAsciiStream(getColIdxByName(columnName));
2752 
2753     }
2754 
2755     /**
2756      * A column value can be retrieved as a stream of Unicode characters
2757      * and then read in chunks from the stream.  This method is particularly
2758      * suitable for retrieving large <code>LONGVARCHAR</code> values.
2759      * The JDBC driver will do any necessary conversion from the database
2760      * format into Unicode.
2761      *
2762      * <P><B>Note:</B> All the data in the returned stream must
2763      * be read prior to getting the value of any other column. The
2764      * next call to a <code>getXXX</code> method implicitly closes the stream.
2765      *
2766      * @param columnName a <code>String</code> object giving the SQL name of
2767      *        a column in this <code>CachedRowSetImpl</code> object
2768      * @return a Java input stream that delivers the database column value
2769      *         as a stream of two-byte Unicode characters.  If the value is
2770      *         SQL <code>NULL</code>, the result is <code>null</code>.
2771      * @throws SQLException if the given column name does not match one of
2772      *            this rowset's column names or the cursor is not on one of
2773      *            this rowset's rows or its insert row
2774      * @deprecated use the method <code>getCharacterStream</code> instead
2775      */
2776     @Deprecated
2777     public java.io.InputStream getUnicodeStream(String columnName) throws SQLException {
2778         return getUnicodeStream(getColIdxByName(columnName));
2779     }
2780 
2781     /**
2782      * Retrieves the value of the designated column in the current row of this
2783      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2784      * object.
2785      * <P>
2786      * A column value can be retrieved as a stream of uninterpreted bytes
2787      * and then read in chunks from the stream.  This method is particularly
2788      * suitable for retrieving large <code>LONGVARBINARY</code> values.
2789      *
2790      * <P><B>Note:</B> All the data in the returned stream must be
2791      * read prior to getting the value of any other column. The next
2792      * call to a get method implicitly closes the stream. Also, a
2793      * stream may return <code>0</code> for <code>CachedRowSetImpl.available()</code>
2794      * whether there is data available or not.
2795      *
2796      * @param columnName a <code>String</code> object giving the SQL name of
2797      *        a column in this <code>CachedRowSetImpl</code> object
2798      * @return a Java input stream that delivers the database column value
2799      *         as a stream of uninterpreted bytes.  If the value is SQL
2800      *         <code>NULL</code>, the result is <code>null</code>.
2801      * @throws SQLException if (1) the given column name is unknown,
2802      * (2) the cursor is not on one of this rowset's rows or its
2803      * insert row, or (3) the designated column does not store an
2804      * SQL <code>BINARY, VARBINARY</code> or <code><b>LONGVARBINARY</b></code>
2805      * The bold type indicates the SQL type that this method is recommened
2806      * to retrieve.
2807      * @see #getBinaryStream(int)
2808      *
2809      */
2810     public java.io.InputStream getBinaryStream(String columnName) throws SQLException {
2811         return getBinaryStream(getColIdxByName(columnName));
2812     }
2813 
2814 
2815     // Advanced features:
2816 
2817     /**
2818      * The first warning reported by calls on this <code>CachedRowSetImpl</code>
2819      * object is returned. Subsequent <code>CachedRowSetImpl</code> warnings will
2820      * be chained to this <code>SQLWarning</code>.
2821      *
2822      * <P>The warning chain is automatically cleared each time a new
2823      * row is read.
2824      *
2825      * <P><B>Note:</B> This warning chain only covers warnings caused
2826      * by <code>ResultSet</code> methods.  Any warning caused by statement
2827      * methods (such as reading OUT parameters) will be chained on the
2828      * <code>Statement</code> object.
2829      *
2830      * @return the first SQLWarning or null
2831      */
2832     public SQLWarning getWarnings() {
2833         return sqlwarn;
2834     }
2835 
2836     /**
2837      * Clears all the warnings reporeted for the <code>CachedRowSetImpl</code>
2838      * object. After a call to this method, the <code>getWarnings</code> method
2839      * returns <code>null</code> until a new warning is reported for this
2840      * <code>CachedRowSetImpl</code> object.
2841      */
2842     public void clearWarnings() {
2843         sqlwarn = null;
2844     }
2845 
2846     /**
2847      * Retrieves the name of the SQL cursor used by this
2848      * <code>CachedRowSetImpl</code> object.
2849      *
2850      * <P>In SQL, a result table is retrieved through a cursor that is
2851      * named. The current row of a <code>ResultSet</code> can be updated or deleted
2852      * using a positioned update/delete statement that references the
2853      * cursor name. To ensure that the cursor has the proper isolation
2854      * level to support an update operation, the cursor's <code>SELECT</code>
2855      * statement should be of the form <code>select for update</code>.
2856      * If the <code>for update</code> clause
2857      * is omitted, positioned updates may fail.
2858      *
2859      * <P>JDBC supports this SQL feature by providing the name of the
2860      * SQL cursor used by a <code>ResultSet</code> object. The current row
2861      * of a result set is also the current row of this SQL cursor.
2862      *
2863      * <P><B>Note:</B> If positioned updates are not supported, an
2864      * <code>SQLException</code> is thrown.
2865      *
2866      * @return the SQL cursor name for this <code>CachedRowSetImpl</code> object's
2867      *         cursor
2868      * @throws SQLException if an error occurs
2869      */
2870     public String getCursorName() throws SQLException {
2871         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.posupdate").toString());
2872     }
2873 
2874     /**
2875      * Retrieves a <code>ResultSetMetaData</code> object instance that
2876      * contains information about the <code>CachedRowSet</code> object.
2877      * However, applications should cast the returned object to a
2878      * <code>RowSetMetaData</code> interface implementation. In the
2879      * reference implementation, this cast can be done on the
2880      * <code>RowSetMetaDataImpl</code> class.
2881      * <P>
2882      * For example:
2883      * <pre>
2884      * CachedRowSet crs = new CachedRowSetImpl();
2885      * RowSetMetaDataImpl metaData =
2886      *     (RowSetMetaDataImpl)crs.getMetaData();
2887      * // Set the number of columns in the RowSet object for
2888      * // which this RowSetMetaDataImpl object was created to the
2889      * // given number.
2890      * metaData.setColumnCount(3);
2891      * crs.setMetaData(metaData);
2892      * </pre>
2893      *
2894      * @return the <code>ResultSetMetaData</code> object that describes this
2895      *         <code>CachedRowSetImpl</code> object's columns
2896      * @throws SQLException if an error occurs in generating the RowSet
2897      * meta data; or if the <code>CachedRowSetImpl</code> is empty.
2898      * @see javax.sql.RowSetMetaData
2899      */
2900     public ResultSetMetaData getMetaData() throws SQLException {
2901         return (ResultSetMetaData)RowSetMD;
2902     }
2903 
2904 
2905     /**
2906      * Retrieves the value of the designated column in the current row
2907      * of this <code>CachedRowSetImpl</code> object as an
2908      * <code>Object</code> value.
2909      * <P>
2910      * The type of the <code>Object</code> will be the default
2911      * Java object type corresponding to the column's SQL type,
2912      * following the mapping for built-in types specified in the JDBC 3.0
2913      * specification.
2914      * <P>
2915      * This method may also be used to read datatabase-specific
2916      * abstract data types.
2917      * <P>
2918      * This implementation of the method <code>getObject</code> extends its
2919      * behavior so that it gets the attributes of an SQL structured type
2920      * as an array of <code>Object</code> values.  This method also custom
2921      * maps SQL user-defined types to classes in the Java programming language.
2922      * When the specified column contains
2923      * a structured or distinct value, the behavior of this method is as
2924      * if it were a call to the method <code>getObject(columnIndex,
2925      * this.getStatement().getConnection().getTypeMap())</code>.
2926      *
2927      * @param columnIndex the first column is <code>1</code>, the second
2928      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2929      *        and equal to or less than the number of columns in the rowset
2930      * @return a <code>java.lang.Object</code> holding the column value;
2931      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
2932      * @throws SQLException if the given column index is out of bounds,
2933      *            the cursor is not on a valid row, or there is a problem getting
2934      *            the <code>Class</code> object for a custom mapping
2935      * @see #getObject(String)
2936      */
2937     public Object getObject(int columnIndex) throws SQLException {
2938         Object value;
2939         Map<String, Class<?>> map;
2940 
2941         // sanity check.
2942         checkIndex(columnIndex);
2943         // make sure the cursor is on a valid row
2944         checkCursor();
2945 
2946         setLastValueNull(false);
2947         value = getCurrentRow().getColumnObject(columnIndex);
2948 
2949         // check for SQL NULL
2950         if (value == null) {
2951             setLastValueNull(true);
2952             return null;
2953         }
2954         if (value instanceof Struct) {
2955             Struct s = (Struct)value;
2956             map = getTypeMap();
2957             // look up the class in the map
2958             Class<?> c = map.get(s.getSQLTypeName());
2959             if (c != null) {
2960                 // create new instance of the class
2961                 SQLData obj = null;
2962                 try {
2963                     obj = (SQLData) ReflectUtil.newInstance(c);
2964                 } catch(Exception ex) {
2965                     throw new SQLException("Unable to Instantiate: ", ex);
2966                 }
2967                 // get the attributes from the struct
2968                 Object attribs[] = s.getAttributes(map);
2969                 // create the SQLInput "stream"
2970                 SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
2971                 // read the values...
2972                 obj.readSQL(sqlInput, s.getSQLTypeName());
2973                 return (Object)obj;
2974             }
2975         }
2976         return value;
2977     }
2978 
2979     /**
2980      * Retrieves the value of the designated column in the current row
2981      * of this <code>CachedRowSetImpl</code> object as an
2982      * <code>Object</code> value.
2983      * <P>
2984      * The type of the <code>Object</code> will be the default
2985      * Java object type corresponding to the column's SQL type,
2986      * following the mapping for built-in types specified in the JDBC 3.0
2987      * specification.
2988      * <P>
2989      * This method may also be used to read datatabase-specific
2990      * abstract data types.
2991      * <P>
2992      * This implementation of the method <code>getObject</code> extends its
2993      * behavior so that it gets the attributes of an SQL structured type
2994      * as an array of <code>Object</code> values.  This method also custom
2995      * maps SQL user-defined types to classes
2996      * in the Java programming language. When the specified column contains
2997      * a structured or distinct value, the behavior of this method is as
2998      * if it were a call to the method <code>getObject(columnIndex,
2999      * this.getStatement().getConnection().getTypeMap())</code>.
3000      *
3001      * @param columnName a <code>String</code> object that must match the
3002      *        SQL name of a column in this rowset, ignoring case
3003      * @return a <code>java.lang.Object</code> holding the column value;
3004      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3005      * @throws SQLException if (1) the given column name does not match one of
3006      *            this rowset's column names, (2) the cursor is not
3007      *            on a valid row, or (3) there is a problem getting
3008      *            the <code>Class</code> object for a custom mapping
3009      * @see #getObject(int)
3010      */
3011     public Object getObject(String columnName) throws SQLException {
3012         return getObject(getColIdxByName(columnName));
3013     }
3014 
3015     //----------------------------------------------------------------
3016 
3017     /**
3018      * Maps the given column name for one of this <code>CachedRowSetImpl</code>
3019      * object's columns to its column number.
3020      *
3021      * @param columnName a <code>String</code> object that must match the
3022      *        SQL name of a column in this rowset, ignoring case
3023      * @return the column index of the given column name
3024      * @throws SQLException if the given column name does not match one
3025      *            of this rowset's column names
3026      */
3027     public int findColumn(String columnName) throws SQLException {
3028         return getColIdxByName(columnName);
3029     }
3030 
3031 
3032     //--------------------------JDBC 2.0-----------------------------------
3033 
3034     //---------------------------------------------------------------------
3035     // Getter's and Setter's
3036     //---------------------------------------------------------------------
3037 
3038     /**
3039      * Retrieves the value stored in the designated column
3040      * of the current row as a <code>java.io.Reader</code> object.
3041      *
3042      * <P><B>Note:</B> All the data in the returned stream must
3043      * be read prior to getting the value of any other column. The
3044      * next call to a <code>getXXX</code> method implicitly closes the stream.
3045      *
3046      * @param columnIndex the first column is <code>1</code>, the second
3047      *        is <code>2</code>, and so on; must be <code>1</code> or larger
3048      *        and equal to or less than the number of columns in the rowset
3049      * @return a Java character stream that delivers the database column value
3050      * as a stream of two-byte unicode characters in a
3051      * <code>java.io.Reader</code> object.  If the value is
3052      * SQL <code>NULL</code>, the result is <code>null</code>.
3053      * @throws SQLException if (1) the given column index is out of bounds,
3054      * (2) the cursor is not on one of this rowset's rows or its
3055      * insert row, or (3) the designated column does not store an
3056      * SQL <code>CHAR, VARCHAR, <b>LONGVARCHAR</b>, BINARY, VARBINARY</code> or
3057      * <code>LONGVARBINARY</code> value.
3058      * The bold SQL type designates the recommended return type.
3059      * @see #getCharacterStream(String)
3060      */
3061     public java.io.Reader getCharacterStream(int columnIndex) throws SQLException{
3062 
3063         // sanity check.
3064         checkIndex(columnIndex);
3065         // make sure the cursor is on a valid row
3066         checkCursor();
3067 
3068         if (isBinary(RowSetMD.getColumnType(columnIndex))) {
3069             Object value = getCurrentRow().getColumnObject(columnIndex);
3070             if (value == null) {
3071                 lastValueNull = true;
3072                 return null;
3073             }
3074             charStream = new InputStreamReader
3075             (new ByteArrayInputStream((byte[])value));
3076         } else if (isString(RowSetMD.getColumnType(columnIndex))) {
3077             Object value = getCurrentRow().getColumnObject(columnIndex);
3078             if (value == null) {
3079                 lastValueNull = true;
3080                 return null;
3081             }
3082             charStream = new StringReader(value.toString());
3083         } else {
3084             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
3085         }
3086 
3087         return charStream;
3088     }
3089 
3090     /**
3091      * Retrieves the value stored in the designated column
3092      * of the current row as a <code>java.io.Reader</code> object.
3093      *
3094      * <P><B>Note:</B> All the data in the returned stream must
3095      * be read prior to getting the value of any other column. The
3096      * next call to a <code>getXXX</code> method implicitly closes the stream.
3097      *
3098      * @param columnName a <code>String</code> object giving the SQL name of
3099      *        a column in this <code>CachedRowSetImpl</code> object
3100      * @return a Java input stream that delivers the database column value
3101      *         as a stream of two-byte Unicode characters.  If the value is
3102      *         SQL <code>NULL</code>, the result is <code>null</code>.
3103      * @throws SQLException if (1) the given column name is not the name of
3104      * a column in this rowset, (2) the cursor is not on one of
3105      * this rowset's rows or its insert row, or (3) the designated
3106      * column does not store an SQL <code>CHAR, VARCHAR, <b>LONGVARCHAR</b>,
3107      * BINARY, VARYBINARY</code> or <code>LONGVARBINARY</code> value.
3108      * The bold SQL type designates the recommended return type.
3109      */
3110     public java.io.Reader getCharacterStream(String columnName) throws SQLException {
3111         return getCharacterStream(getColIdxByName(columnName));
3112     }
3113 
3114     /**
3115      * Retrieves the value of the designated column in the current row
3116      * of this <code>CachedRowSetImpl</code> object as a
3117      * <code>java.math.BigDecimal</code> object.
3118      *
3119      * @param columnIndex the first column is <code>1</code>, the second
3120      *        is <code>2</code>, and so on; must be <code>1</code> or larger
3121      *        and equal to or less than the number of columns in the rowset
3122      * @return a <code>java.math.BigDecimal</code> value with full precision;
3123      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3124      * @throws SQLException if (1) the given column index is out of bounds,
3125      * (2) the cursor is not on one of this rowset's rows or its
3126      * insert row, or (3) the designated column does not store an
3127      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
3128      * FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT, CHAR, VARCHAR</code>
3129      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
3130      * recommended return types that this method is used to retrieve.
3131      * @see #getBigDecimal(String)
3132      */
3133     public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
3134         Object value;
3135 
3136         // sanity check.
3137         checkIndex(columnIndex);
3138         // make sure the cursor is on a valid row
3139         checkCursor();
3140 
3141         setLastValueNull(false);
3142         value = getCurrentRow().getColumnObject(columnIndex);
3143 
3144         // check for SQL NULL
3145         if (value == null) {
3146             setLastValueNull(true);
3147             return null;
3148         }
3149         try {
3150             return (new BigDecimal(value.toString().trim()));
3151         } catch (NumberFormatException ex) {
3152             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.doublefail").toString(),
3153                 new Object[] {value.toString().trim(), columnIndex}));
3154         }
3155     }
3156 
3157     /**
3158      * Retrieves the value of the designated column in the current row
3159      * of this <code>CachedRowSetImpl</code> object as a
3160      * <code>java.math.BigDecimal</code> object.
3161      *
3162      * @param columnName a <code>String</code> object that must match the
3163      *        SQL name of a column in this rowset, ignoring case
3164      * @return a <code>java.math.BigDecimal</code> value with full precision;
3165      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3166      * @throws SQLException if (1) the given column name is not the name of
3167      * a column in this rowset, (2) the cursor is not on one of
3168      * this rowset's rows or its insert row, or (3) the designated
3169      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
3170      * BIGINT, REAL, FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT CHAR,
3171      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
3172      * designates the recommended return type that this method is used to
3173      * retrieve
3174      * @see #getBigDecimal(int)
3175      */
3176     public BigDecimal getBigDecimal(String columnName) throws SQLException {
3177         return getBigDecimal(getColIdxByName(columnName));
3178     }
3179 
3180     //---------------------------------------------------------------------
3181     // Traversal/Positioning
3182     //---------------------------------------------------------------------
3183 
3184     /**
3185      * Returns the number of rows in this <code>CachedRowSetImpl</code> object.
3186      *
3187      * @return number of rows in the rowset
3188      */
3189     public int size() {
3190         return numRows;
3191     }
3192 
3193     /**
3194      * Indicates whether the cursor is before the first row in this
3195      * <code>CachedRowSetImpl</code> object.
3196      *
3197      * @return <code>true</code> if the cursor is before the first row;
3198      *         <code>false</code> otherwise or if the rowset contains no rows
3199      * @throws SQLException if an error occurs
3200      */
3201     public boolean isBeforeFirst() throws SQLException {
3202         if (cursorPos == 0 && numRows > 0) {
3203             return true;
3204         } else {
3205             return false;
3206         }
3207     }
3208 
3209     /**
3210      * Indicates whether the cursor is after the last row in this
3211      * <code>CachedRowSetImpl</code> object.
3212      *
3213      * @return <code>true</code> if the cursor is after the last row;
3214      *         <code>false</code> otherwise or if the rowset contains no rows
3215      * @throws SQLException if an error occurs
3216      */
3217     public boolean isAfterLast() throws SQLException {
3218         if (cursorPos == numRows+1 && numRows > 0) {
3219             return true;
3220         } else {
3221             return false;
3222         }
3223     }
3224 
3225     /**
3226      * Indicates whether the cursor is on the first row in this
3227      * <code>CachedRowSetImpl</code> object.
3228      *
3229      * @return <code>true</code> if the cursor is on the first row;
3230      *         <code>false</code> otherwise or if the rowset contains no rows
3231      * @throws SQLException if an error occurs
3232      */
3233     public boolean isFirst() throws SQLException {
3234         // this becomes nasty because of deletes.
3235         int saveCursorPos = cursorPos;
3236         int saveAbsoluteCursorPos = absolutePos;
3237         internalFirst();
3238         if (cursorPos == saveCursorPos) {
3239             return true;
3240         } else {
3241             cursorPos = saveCursorPos;
3242             absolutePos = saveAbsoluteCursorPos;
3243             return false;
3244         }
3245     }
3246 
3247     /**
3248      * Indicates whether the cursor is on the last row in this
3249      * <code>CachedRowSetImpl</code> object.
3250      * <P>
3251      * Note: Calling the method <code>isLast</code> may be expensive
3252      * because the JDBC driver might need to fetch ahead one row in order
3253      * to determine whether the current row is the last row in this rowset.
3254      *
3255      * @return <code>true</code> if the cursor is on the last row;
3256      *         <code>false</code> otherwise or if this rowset contains no rows
3257      * @throws SQLException if an error occurs
3258      */
3259     public boolean isLast() throws SQLException {
3260         int saveCursorPos = cursorPos;
3261         int saveAbsoluteCursorPos = absolutePos;
3262         boolean saveShowDeleted = getShowDeleted();
3263         setShowDeleted(true);
3264         internalLast();
3265         if (cursorPos == saveCursorPos) {
3266             setShowDeleted(saveShowDeleted);
3267             return true;
3268         } else {
3269             setShowDeleted(saveShowDeleted);
3270             cursorPos = saveCursorPos;
3271             absolutePos = saveAbsoluteCursorPos;
3272             return false;
3273         }
3274     }
3275 
3276     /**
3277      * Moves this <code>CachedRowSetImpl</code> object's cursor to the front of
3278      * the rowset, just before the first row. This method has no effect if
3279      * this rowset contains no rows.
3280      *
3281      * @throws SQLException if an error occurs or the type of this rowset
3282      *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3283      */
3284     public void beforeFirst() throws SQLException {
3285        if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3286             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.beforefirst").toString());
3287         }
3288         cursorPos = 0;
3289         absolutePos = 0;
3290         notifyCursorMoved();
3291     }
3292 
3293     /**
3294      * Moves this <code>CachedRowSetImpl</code> object's cursor to the end of
3295      * the rowset, just after the last row. This method has no effect if
3296      * this rowset contains no rows.
3297      *
3298      * @throws SQLException if an error occurs
3299      */
3300     public void afterLast() throws SQLException {
3301         if (numRows > 0) {
3302             cursorPos = numRows + 1;
3303             absolutePos = 0;
3304             notifyCursorMoved();
3305         }
3306     }
3307 
3308     /**
3309      * Moves this <code>CachedRowSetImpl</code> object's cursor to the first row
3310      * and returns <code>true</code> if the operation was successful.  This
3311      * method also notifies registered listeners that the cursor has moved.
3312      *
3313      * @return <code>true</code> if the cursor is on a valid row;
3314      *         <code>false</code> otherwise or if there are no rows in this
3315      *         <code>CachedRowSetImpl</code> object
3316      * @throws SQLException if the type of this rowset
3317      *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3318      */
3319     public boolean first() throws SQLException {
3320         if(getType() == ResultSet.TYPE_FORWARD_ONLY) {
3321             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.first").toString());
3322         }
3323 
3324         // move and notify
3325         boolean ret = this.internalFirst();
3326         notifyCursorMoved();
3327 
3328         return ret;
3329     }
3330 
3331     /**
3332      * Moves this <code>CachedRowSetImpl</code> object's cursor to the first
3333      * row and returns <code>true</code> if the operation is successful.
3334      * <P>
3335      * This method is called internally by the methods <code>first</code>,
3336      * <code>isFirst</code>, and <code>absolute</code>.
3337      * It in turn calls the method <code>internalNext</code> in order to
3338      * handle the case where the first row is a deleted row that is not visible.
3339      * <p>
3340      * This is a implementation only method and is not required as a standard
3341      * implementation of the <code>CachedRowSet</code> interface.
3342      *
3343      * @return <code>true</code> if the cursor moved to the first row;
3344      *         <code>false</code> otherwise
3345      * @throws SQLException if an error occurs
3346      */
3347     protected boolean internalFirst() throws SQLException {
3348         boolean ret = false;
3349 
3350         if (numRows > 0) {
3351             cursorPos = 1;
3352             if ((getShowDeleted() == false) && (rowDeleted() == true)) {
3353                 ret = internalNext();
3354             } else {
3355                 ret = true;
3356             }
3357         }
3358 
3359         if (ret == true)
3360             absolutePos = 1;
3361         else
3362             absolutePos = 0;
3363 
3364         return ret;
3365     }
3366 
3367     /**
3368      * Moves this <code>CachedRowSetImpl</code> object's cursor to the last row
3369      * and returns <code>true</code> if the operation was successful.  This
3370      * method also notifies registered listeners that the cursor has moved.
3371      *
3372      * @return <code>true</code> if the cursor is on a valid row;
3373      *         <code>false</code> otherwise or if there are no rows in this
3374      *         <code>CachedRowSetImpl</code> object
3375      * @throws SQLException if the type of this rowset
3376      *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3377      */
3378     public boolean last() throws SQLException {
3379         if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3380             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.last").toString());
3381         }
3382 
3383         // move and notify
3384         boolean ret = this.internalLast();
3385         notifyCursorMoved();
3386 
3387         return ret;
3388     }
3389 
3390     /**
3391      * Moves this <code>CachedRowSetImpl</code> object's cursor to the last
3392      * row and returns <code>true</code> if the operation is successful.
3393      * <P>
3394      * This method is called internally by the method <code>last</code>
3395      * when rows have been deleted and the deletions are not visible.
3396      * The method <code>internalLast</code> handles the case where the
3397      * last row is a deleted row that is not visible by in turn calling
3398      * the method <code>internalPrevious</code>.
3399      * <p>
3400      * This is a implementation only method and is not required as a standard
3401      * implementation of the <code>CachedRowSet</code> interface.
3402      *
3403      * @return <code>true</code> if the cursor moved to the last row;
3404      *         <code>false</code> otherwise
3405      * @throws SQLException if an error occurs
3406      */
3407     protected boolean internalLast() throws SQLException {
3408         boolean ret = false;
3409 
3410         if (numRows > 0) {
3411             cursorPos = numRows;
3412             if ((getShowDeleted() == false) && (rowDeleted() == true)) {
3413                 ret = internalPrevious();
3414             } else {
3415                 ret = true;
3416             }
3417         }
3418         if (ret == true)
3419             absolutePos = numRows - numDeleted;
3420         else
3421             absolutePos = 0;
3422         return ret;
3423     }
3424 
3425     /**
3426      * Returns the number of the current row in this <code>CachedRowSetImpl</code>
3427      * object. The first row is number 1, the second number 2, and so on.
3428      *
3429      * @return the number of the current row;  <code>0</code> if there is no
3430      *         current row
3431      * @throws SQLException if an error occurs; or if the <code>CacheRowSetImpl</code>
3432      *         is empty
3433      */
3434     public int getRow() throws SQLException {
3435         // are we on a valid row? Valid rows are between first and last
3436         if (numRows > 0 &&
3437         cursorPos > 0 &&
3438         cursorPos < (numRows + 1) &&
3439         (getShowDeleted() == false && rowDeleted() == false)) {
3440             return absolutePos;
3441         } else if (getShowDeleted() == true) {
3442             return cursorPos;
3443         } else {
3444             return 0;
3445         }
3446     }
3447 
3448     /**
3449      * Moves this <code>CachedRowSetImpl</code> object's cursor to the row number
3450      * specified.
3451      *
3452      * <p>If the number is positive, the cursor moves to an absolute row with
3453      * respect to the beginning of the rowset.  The first row is row 1, the second
3454      * is row 2, and so on.  For example, the following command, in which
3455      * <code>crs</code> is a <code>CachedRowSetImpl</code> object, moves the cursor
3456      * to the fourth row, starting from the beginning of the rowset.
3457      * <PRE><code>
3458      *
3459      *    crs.absolute(4);
3460      *
3461      * </code> </PRE>
3462      * <P>
3463      * If the number is negative, the cursor moves to an absolute row position
3464      * with respect to the end of the rowset.  For example, calling
3465      * <code>absolute(-1)</code> positions the cursor on the last row,
3466      * <code>absolute(-2)</code> moves it on the next-to-last row, and so on.
3467      * If the <code>CachedRowSetImpl</code> object <code>crs</code> has five rows,
3468      * the following command moves the cursor to the fourth-to-last row, which
3469      * in the case of a  rowset with five rows, is also the second row, counting
3470      * from the beginning.
3471      * <PRE><code>
3472      *
3473      *    crs.absolute(-4);
3474      *
3475      * </code> </PRE>
3476      *
3477      * If the number specified is larger than the number of rows, the cursor
3478      * will move to the position after the last row. If the number specified
3479      * would move the cursor one or more rows before the first row, the cursor
3480      * moves to the position before the first row.
3481      * <P>
3482      * Note: Calling <code>absolute(1)</code> is the same as calling the
3483      * method <code>first()</code>.  Calling <code>absolute(-1)</code> is the
3484      * same as calling <code>last()</code>.
3485      *
3486      * @param row a positive number to indicate the row, starting row numbering from
3487      *        the first row, which is <code>1</code>; a negative number to indicate
3488      *        the row, starting row numbering from the last row, which is
3489      *        <code>-1</code>; it must not be <code>0</code>
3490      * @return <code>true</code> if the cursor is on the rowset; <code>false</code>
3491      *         otherwise
3492      * @throws SQLException if the given cursor position is <code>0</code> or the
3493      *            type of this rowset is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3494      */
3495     public boolean absolute( int row ) throws SQLException {
3496         if (row == 0 || getType() == ResultSet.TYPE_FORWARD_ONLY) {
3497             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.absolute").toString());
3498         }
3499 
3500         if (row > 0) { // we are moving foward
3501             if (row > numRows) {
3502                 // fell off the end
3503                 afterLast();
3504                 return false;
3505             } else {
3506                 if (absolutePos <= 0)
3507                     internalFirst();
3508             }
3509         } else { // we are moving backward
3510             if (cursorPos + row < 0) {
3511                 // fell off the front
3512                 beforeFirst();
3513                 return false;
3514             } else {
3515                 if (absolutePos >= 0)
3516                     internalLast();
3517             }
3518         }
3519 
3520         // Now move towards the absolute row that we're looking for
3521         while (absolutePos != row) {
3522             if (absolutePos < row) {
3523                 if (!internalNext())
3524                     break;
3525             }
3526             else {
3527                 if (!internalPrevious())
3528                     break;
3529             }
3530         }
3531 
3532         notifyCursorMoved();
3533 
3534         if (isAfterLast() || isBeforeFirst()) {
3535             return false;
3536         } else {
3537             return true;
3538         }
3539     }
3540 
3541     /**
3542      * Moves the cursor the specified number of rows from the current
3543      * position, with a positive number moving it forward and a
3544      * negative number moving it backward.
3545      * <P>
3546      * If the number is positive, the cursor moves the specified number of
3547      * rows toward the end of the rowset, starting at the current row.
3548      * For example, the following command, in which
3549      * <code>crs</code> is a <code>CachedRowSetImpl</code> object with 100 rows,
3550      * moves the cursor forward four rows from the current row.  If the
3551      * current row is 50, the cursor would move to row 54.
3552      * <PRE><code>
3553      *
3554      *    crs.relative(4);
3555      *
3556      * </code> </PRE>
3557      * <P>
3558      * If the number is negative, the cursor moves back toward the beginning
3559      * the specified number of rows, starting at the current row.
3560      * For example, calling the method
3561      * <code>absolute(-1)</code> positions the cursor on the last row,
3562      * <code>absolute(-2)</code> moves it on the next-to-last row, and so on.
3563      * If the <code>CachedRowSetImpl</code> object <code>crs</code> has five rows,
3564      * the following command moves the cursor to the fourth-to-last row, which
3565      * in the case of a  rowset with five rows, is also the second row
3566      * from the beginning.
3567      * <PRE><code>
3568      *
3569      *    crs.absolute(-4);
3570      *
3571      * </code> </PRE>
3572      *
3573      * If the number specified is larger than the number of rows, the cursor
3574      * will move to the position after the last row. If the number specified
3575      * would move the cursor one or more rows before the first row, the cursor
3576      * moves to the position before the first row. In both cases, this method
3577      * throws an <code>SQLException</code>.
3578      * <P>
3579      * Note: Calling <code>absolute(1)</code> is the same as calling the
3580      * method <code>first()</code>.  Calling <code>absolute(-1)</code> is the
3581      * same as calling <code>last()</code>.  Calling <code>relative(0)</code>
3582      * is valid, but it does not change the cursor position.
3583      *
3584      * @param rows an <code>int</code> indicating the number of rows to move
3585      *             the cursor, starting at the current row; a positive number
3586      *             moves the cursor forward; a negative number moves the cursor
3587      *             backward; must not move the cursor past the valid
3588      *             rows
3589      * @return <code>true</code> if the cursor is on a row in this
3590      *         <code>CachedRowSetImpl</code> object; <code>false</code>
3591      *         otherwise
3592      * @throws SQLException if there are no rows in this rowset, the cursor is
3593      *         positioned either before the first row or after the last row, or
3594      *         the rowset is type <code>ResultSet.TYPE_FORWARD_ONLY</code>
3595      */
3596     public boolean relative(int rows) throws SQLException {
3597         if (numRows == 0 || isBeforeFirst() ||
3598         isAfterLast() || getType() == ResultSet.TYPE_FORWARD_ONLY) {
3599             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.relative").toString());
3600         }
3601 
3602         if (rows == 0) {
3603             return true;
3604         }
3605 
3606         if (rows > 0) { // we are moving forward
3607             if (cursorPos + rows > numRows) {
3608                 // fell off the end
3609                 afterLast();
3610             } else {
3611                 for (int i=0; i < rows; i++) {
3612                     if (!internalNext())
3613                         break;
3614                 }
3615             }
3616         } else { // we are moving backward
3617             if (cursorPos + rows < 0) {
3618                 // fell off the front
3619                 beforeFirst();
3620             } else {
3621                 for (int i=rows; i < 0; i++) {
3622                     if (!internalPrevious())
3623                         break;
3624                 }
3625             }
3626         }
3627         notifyCursorMoved();
3628 
3629         if (isAfterLast() || isBeforeFirst()) {
3630             return false;
3631         } else {
3632             return true;
3633         }
3634     }
3635 
3636     /**
3637      * Moves this <code>CachedRowSetImpl</code> object's cursor to the
3638      * previous row and returns <code>true</code> if the cursor is on
3639      * a valid row or <code>false</code> if it is not.
3640      * This method also notifies all listeners registered with this
3641      * <code>CachedRowSetImpl</code> object that its cursor has moved.
3642      * <P>
3643      * Note: calling the method <code>previous()</code> is not the same
3644      * as calling the method <code>relative(-1)</code>.  This is true
3645      * because it is possible to call <code>previous()</code> from the insert
3646      * row, from after the last row, or from the current row, whereas
3647      * <code>relative</code> may only be called from the current row.
3648      * <P>
3649      * The method <code>previous</code> may used in a <code>while</code>
3650      * loop to iterate through a rowset starting after the last row
3651      * and moving toward the beginning. The loop ends when <code>previous</code>
3652      * returns <code>false</code>, meaning that there are no more rows.
3653      * For example, the following code fragment retrieves all the data in
3654      * the <code>CachedRowSetImpl</code> object <code>crs</code>, which has
3655      * three columns.  Note that the cursor must initially be positioned
3656      * after the last row so that the first call to the method
3657      * <code>previous</code> places the cursor on the last line.
3658      * <PRE> <code>
3659      *
3660      *     crs.afterLast();
3661      *     while (previous()) {
3662      *         String name = crs.getString(1);
3663      *         int age = crs.getInt(2);
3664      *         short ssn = crs.getShort(3);
3665      *         System.out.println(name + "   " + age + "   " + ssn);
3666      *     }
3667      *
3668      * </code> </PRE>
3669      * This method throws an <code>SQLException</code> if the cursor is not
3670      * on a row in the rowset, before the first row, or after the last row.
3671      *
3672      * @return <code>true</code> if the cursor is on a valid row;
3673      *         <code>false</code> if it is before the first row or after the
3674      *         last row
3675      * @throws SQLException if the cursor is not on a valid position or the
3676      *           type of this rowset is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3677      */
3678     public boolean previous() throws SQLException {
3679         if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3680             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.last").toString());
3681         }
3682         /*
3683          * make sure things look sane. The cursor must be
3684          * positioned in the rowset or before first (0) or
3685          * after last (numRows + 1)
3686          */
3687         if (cursorPos < 0 || cursorPos > numRows + 1) {
3688             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
3689         }
3690         // move and notify
3691         boolean ret = this.internalPrevious();
3692         notifyCursorMoved();
3693 
3694         return ret;
3695     }
3696 
3697     /**
3698      * Moves the cursor to the previous row in this <code>CachedRowSetImpl</code>
3699      * object, skipping past deleted rows that are not visible; returns
3700      * <code>true</code> if the cursor is on a row in this rowset and
3701      * <code>false</code> when the cursor goes before the first row.
3702      * <P>
3703      * This method is called internally by the method <code>previous</code>.
3704      * <P>
3705      * This is a implementation only method and is not required as a standard
3706      * implementation of the <code>CachedRowSet</code> interface.
3707      *
3708      * @return <code>true</code> if the cursor is on a row in this rowset;
3709      *         <code>false</code> when the cursor reaches the position before
3710      *         the first row
3711      * @throws SQLException if an error occurs
3712      */
3713     protected boolean internalPrevious() throws SQLException {
3714         boolean ret = false;
3715 
3716         do {
3717             if (cursorPos > 1) {
3718                 --cursorPos;
3719                 ret = true;
3720             } else if (cursorPos == 1) {
3721                 // decrement to before first
3722                 --cursorPos;
3723                 ret = false;
3724                 break;
3725             }
3726         } while ((getShowDeleted() == false) && (rowDeleted() == true));
3727 
3728         /*
3729          * Each call to internalPrevious may move the cursor
3730          * over multiple rows, the absolute position moves one row
3731          */
3732         if (ret == true)
3733             --absolutePos;
3734         else
3735             absolutePos = 0;
3736 
3737         return ret;
3738     }
3739 
3740 
3741     //---------------------------------------------------------------------
3742     // Updates
3743     //---------------------------------------------------------------------
3744 
3745     /**
3746      * Indicates whether the current row of this <code>CachedRowSetImpl</code>
3747      * object has been updated.  The value returned
3748      * depends on whether this rowset can detect updates: <code>false</code>
3749      * will always be returned if it does not detect updates.
3750      *
3751      * @return <code>true</code> if the row has been visibly updated
3752      *         by the owner or another and updates are detected;
3753      *         <code>false</code> otherwise
3754      * @throws SQLException if the cursor is on the insert row or not
3755      *            not on a valid row
3756      *
3757      * @see DatabaseMetaData#updatesAreDetected
3758      */
3759     public boolean rowUpdated() throws SQLException {
3760         // make sure the cursor is on a valid row
3761         checkCursor();
3762         if (onInsertRow == true) {
3763             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3764         }
3765         return(((Row)getCurrentRow()).getUpdated());
3766     }
3767 
3768     /**
3769      * Indicates whether the designated column of the current row of
3770      * this <code>CachedRowSetImpl</code> object has been updated. The
3771      * value returned depends on whether this rowset can detcted updates:
3772      * <code>false</code> will always be returned if it does not detect updates.
3773      *
3774      * @param idx the index identifier of the column that may be have been updated.
3775      * @return <code>true</code> is the designated column has been updated
3776      * and the rowset detects updates; <code>false</code> if the rowset has not
3777      * been updated or the rowset does not detect updates
3778      * @throws SQLException if the cursor is on the insert row or not
3779      *          on a valid row
3780      * @see DatabaseMetaData#updatesAreDetected
3781      */
3782     public boolean columnUpdated(int idx) throws SQLException {
3783         // make sure the cursor is on a valid row
3784         checkCursor();
3785         if (onInsertRow == true) {
3786             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3787         }
3788         return (((Row)getCurrentRow()).getColUpdated(idx - 1));
3789     }
3790 
3791     /**
3792      * Indicates whether the designated column of the current row of
3793      * this <code>CachedRowSetImpl</code> object has been updated. The
3794      * value returned depends on whether this rowset can detcted updates:
3795      * <code>false</code> will always be returned if it does not detect updates.
3796      *
3797      * @param columnName the <code>String</code> column name column that may be have
3798      * been updated.
3799      * @return <code>true</code> is the designated column has been updated
3800      * and the rowset detects updates; <code>false</code> if the rowset has not
3801      * been updated or the rowset does not detect updates
3802      * @throws SQLException if the cursor is on the insert row or not
3803      *          on a valid row
3804      * @see DatabaseMetaData#updatesAreDetected
3805      */
3806     public boolean columnUpdated(String columnName) throws SQLException {
3807         return columnUpdated(getColIdxByName(columnName));
3808     }
3809 
3810     /**
3811      * Indicates whether the current row has been inserted.  The value returned
3812      * depends on whether or not the rowset can detect visible inserts.
3813      *
3814      * @return <code>true</code> if a row has been inserted and inserts are detected;
3815      *         <code>false</code> otherwise
3816      * @throws SQLException if the cursor is on the insert row or not
3817      *            not on a valid row
3818      *
3819      * @see DatabaseMetaData#insertsAreDetected
3820      */
3821     public boolean rowInserted() throws SQLException {
3822         // make sure the cursor is on a valid row
3823         checkCursor();
3824         if (onInsertRow == true) {
3825             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3826         }
3827         return(((Row)getCurrentRow()).getInserted());
3828     }
3829 
3830     /**
3831      * Indicates whether the current row has been deleted.  A deleted row
3832      * may leave a visible "hole" in a rowset.  This method can be used to
3833      * detect such holes if the rowset can detect deletions. This method
3834      * will always return <code>false</code> if this rowset cannot detect
3835      * deletions.
3836      *
3837      * @return <code>true</code> if (1)the current row is blank, indicating that
3838      *         the row has been deleted, and (2)deletions are detected;
3839      *         <code>false</code> otherwise
3840      * @throws SQLException if the cursor is on a valid row in this rowset
3841      * @see DatabaseMetaData#deletesAreDetected
3842      */
3843     public boolean rowDeleted() throws SQLException {
3844         // make sure the cursor is on a valid row
3845 
3846         if (isAfterLast() == true ||
3847         isBeforeFirst() == true ||
3848         onInsertRow == true) {
3849 
3850             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
3851         }
3852         return(((Row)getCurrentRow()).getDeleted());
3853     }
3854 
3855     /**
3856      * Indicates whether the given SQL data type is a numberic type.
3857      *
3858      * @param type one of the constants from <code>java.sql.Types</code>
3859      * @return <code>true</code> if the given type is <code>NUMERIC</code>,'
3860      *         <code>DECIMAL</code>, <code>BIT</code>, <code>TINYINT</code>,
3861      *         <code>SMALLINT</code>, <code>INTEGER</code>, <code>BIGINT</code>,
3862      *         <code>REAL</code>, <code>DOUBLE</code>, or <code>FLOAT</code>;
3863      *         <code>false</code> otherwise
3864      */
3865     private boolean isNumeric(int type) {
3866         switch (type) {
3867             case java.sql.Types.NUMERIC:
3868             case java.sql.Types.DECIMAL:
3869             case java.sql.Types.BIT:
3870             case java.sql.Types.TINYINT:
3871             case java.sql.Types.SMALLINT:
3872             case java.sql.Types.INTEGER:
3873             case java.sql.Types.BIGINT:
3874             case java.sql.Types.REAL:
3875             case java.sql.Types.DOUBLE:
3876             case java.sql.Types.FLOAT:
3877                 return true;
3878             default:
3879                 return false;
3880         }
3881     }
3882 
3883     /**
3884      * Indicates whether the given SQL data type is a string type.
3885      *
3886      * @param type one of the constants from <code>java.sql.Types</code>
3887      * @return <code>true</code> if the given type is <code>CHAR</code>,'
3888      *         <code>VARCHAR</code>, or <code>LONGVARCHAR</code>;
3889      *         <code>false</code> otherwise
3890      */
3891     private boolean isString(int type) {
3892         switch (type) {
3893             case java.sql.Types.CHAR:
3894             case java.sql.Types.VARCHAR:
3895             case java.sql.Types.LONGVARCHAR:
3896                 return true;
3897             default:
3898                 return false;
3899         }
3900     }
3901 
3902     /**
3903      * Indicates whether the given SQL data type is a binary type.
3904      *
3905      * @param type one of the constants from <code>java.sql.Types</code>
3906      * @return <code>true</code> if the given type is <code>BINARY</code>,'
3907      *         <code>VARBINARY</code>, or <code>LONGVARBINARY</code>;
3908      *         <code>false</code> otherwise
3909      */
3910     private boolean isBinary(int type) {
3911         switch (type) {
3912             case java.sql.Types.BINARY:
3913             case java.sql.Types.VARBINARY:
3914             case java.sql.Types.LONGVARBINARY:
3915                 return true;
3916             default:
3917                 return false;
3918         }
3919     }
3920 
3921     /**
3922      * Indicates whether the given SQL data type is a temporal type.
3923      * This method is called internally by the conversion methods
3924      * <code>convertNumeric</code> and <code>convertTemporal</code>.
3925      *
3926      * @param type one of the constants from <code>java.sql.Types</code>
3927      * @return <code>true</code> if the given type is <code>DATE</code>,
3928      *         <code>TIME</code>, or <code>TIMESTAMP</code>;
3929      *         <code>false</code> otherwise
3930      */
3931     private boolean isTemporal(int type) {
3932         switch (type) {
3933             case java.sql.Types.DATE:
3934             case java.sql.Types.TIME:
3935             case java.sql.Types.TIMESTAMP:
3936                 return true;
3937             default:
3938                 return false;
3939         }
3940     }
3941 
3942     /**
3943      * Indicates whether the given SQL data type is a boolean type.
3944      * This method is called internally by the conversion methods
3945      * <code>convertNumeric</code> and <code>convertBoolean</code>.
3946      *
3947      * @param type one of the constants from <code>java.sql.Types</code>
3948      * @return <code>true</code> if the given type is <code>BIT</code>,
3949      *         , or <code>BOOLEAN</code>;
3950      *         <code>false</code> otherwise
3951      */
3952     private boolean isBoolean(int type) {
3953         switch (type) {
3954             case java.sql.Types.BIT:
3955             case java.sql.Types.BOOLEAN:
3956                 return true;
3957             default:
3958                 return false;
3959         }
3960     }
3961 
3962 
3963     /**
3964      * Converts the given <code>Object</code> in the Java programming language
3965      * to the standard mapping for the specified SQL target data type.
3966      * The conversion must be to a string or numeric type, but there are no
3967      * restrictions on the type to be converted.  If the source type and target
3968      * type are the same, the given object is simply returned.
3969      *
3970      * @param srcObj the <code>Object</code> in the Java programming language
3971      *               that is to be converted to the target type
3972      * @param srcType the data type that is the standard mapping in SQL of the
3973      *                object to be converted; must be one of the constants in
3974      *                <code>java.sql.Types</code>
3975      * @param trgType the SQL data type to which to convert the given object;
3976      *                must be one of the following constants in
3977      *                <code>java.sql.Types</code>: <code>NUMERIC</code>,
3978      *         <code>DECIMAL</code>, <code>BIT</code>, <code>TINYINT</code>,
3979      *         <code>SMALLINT</code>, <code>INTEGER</code>, <code>BIGINT</code>,
3980      *         <code>REAL</code>, <code>DOUBLE</code>, <code>FLOAT</code>,
3981      *         <code>VARCHAR</code>, <code>LONGVARCHAR</code>, or <code>CHAR</code>
3982      * @return an <code>Object</code> value.that is
3983      *         the standard object mapping for the target SQL type
3984      * @throws SQLException if the given target type is not one of the string or
3985      *         numeric types in <code>java.sql.Types</code>
3986      */
3987     private Object convertNumeric(Object srcObj, int srcType,
3988     int trgType) throws SQLException {
3989 
3990         if (srcType == trgType) {
3991             return srcObj;
3992         }
3993 
3994         if (isNumeric(trgType) == false && isString(trgType) == false) {
3995             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
3996         }
3997 
3998         try {
3999             switch (trgType) {
4000                 case java.sql.Types.BIT:
4001                     Integer i = Integer.valueOf(srcObj.toString().trim());
4002                     return i.equals(0) ?
4003                     Boolean.valueOf(false) :
4004                         Boolean.valueOf(true);
4005                 case java.sql.Types.TINYINT:
4006                     return Byte.valueOf(srcObj.toString().trim());
4007                 case java.sql.Types.SMALLINT:
4008                     return Short.valueOf(srcObj.toString().trim());
4009                 case java.sql.Types.INTEGER:
4010                     return Integer.valueOf(srcObj.toString().trim());
4011                 case java.sql.Types.BIGINT:
4012                     return Long.valueOf(srcObj.toString().trim());
4013                 case java.sql.Types.NUMERIC:
4014                 case java.sql.Types.DECIMAL:
4015                     return new BigDecimal(srcObj.toString().trim());
4016                 case java.sql.Types.REAL:
4017                 case java.sql.Types.FLOAT:
4018                     return new Float(srcObj.toString().trim());
4019                 case java.sql.Types.DOUBLE:
4020                     return new Double(srcObj.toString().trim());
4021                 case java.sql.Types.CHAR:
4022                 case java.sql.Types.VARCHAR:
4023                 case java.sql.Types.LONGVARCHAR:
4024                     return srcObj.toString();
4025                 default:
4026                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString()+ trgType);
4027             }
4028         } catch (NumberFormatException ex) {
4029             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4030         }
4031     }
4032 
4033     /**
4034      * Converts the given <code>Object</code> in the Java programming language
4035      * to the standard object mapping for the specified SQL target data type.
4036      * The conversion must be to a string or temporal type, and there are also
4037      * restrictions on the type to be converted.
4038      * <P>
4039      * <TABLE ALIGN="CENTER" BORDER CELLPADDING=10 BORDERCOLOR="#0000FF"
4040      * <CAPTION ALIGN="CENTER"><B>Parameters and Return Values</B></CAPTION>
4041      * <TR>
4042      *   <TD><B>Source SQL Type</B>
4043      *   <TD><B>Target SQL Type</B>
4044      *   <TD><B>Object Returned</B>
4045      * </TR>
4046      * <TR>
4047      *   <TD><code>TIMESTAMP</code>
4048      *   <TD><code>DATE</code>
4049      *   <TD><code>java.sql.Date</code>
4050      * </TR>
4051      * <TR>
4052      *   <TD><code>TIMESTAMP</code>
4053      *   <TD><code>TIME</code>
4054      *   <TD><code>java.sql.Time</code>
4055      * </TR>
4056      * <TR>
4057      *   <TD><code>TIME</code>
4058      *   <TD><code>TIMESTAMP</code>
4059      *   <TD><code>java.sql.Timestamp</code>
4060      * </TR>
4061      * <TR>
4062      *   <TD><code>DATE</code>, <code>TIME</code>, or <code>TIMESTAMP</code>
4063      *   <TD><code>CHAR</code>, <code>VARCHAR</code>, or <code>LONGVARCHAR</code>
4064      *   <TD><code>java.lang.String</code>
4065      * </TR>
4066      * </TABLE>
4067      * <P>
4068      * If the source type and target type are the same,
4069      * the given object is simply returned.
4070      *
4071      * @param srcObj the <code>Object</code> in the Java programming language
4072      *               that is to be converted to the target type
4073      * @param srcType the data type that is the standard mapping in SQL of the
4074      *                object to be converted; must be one of the constants in
4075      *                <code>java.sql.Types</code>
4076      * @param trgType the SQL data type to which to convert the given object;
4077      *                must be one of the following constants in
4078      *                <code>java.sql.Types</code>: <code>DATE</code>,
4079      *         <code>TIME</code>, <code>TIMESTAMP</code>, <code>CHAR</code>,
4080      *         <code>VARCHAR</code>, or <code>LONGVARCHAR</code>
4081      * @return an <code>Object</code> value.that is
4082      *         the standard object mapping for the target SQL type
4083      * @throws SQLException if the given target type is not one of the string or
4084      *         temporal types in <code>java.sql.Types</code>
4085      */
4086     private Object convertTemporal(Object srcObj,
4087     int srcType, int trgType) throws SQLException {
4088 
4089         if (srcType == trgType) {
4090             return srcObj;
4091         }
4092 
4093         if (isNumeric(trgType) == true ||
4094         (isString(trgType) == false && isTemporal(trgType) == false)) {
4095             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4096         }
4097 
4098         try {
4099             switch (trgType) {
4100                 case java.sql.Types.DATE:
4101                     if (srcType == java.sql.Types.TIMESTAMP) {
4102                         return new java.sql.Date(((java.sql.Timestamp)srcObj).getTime());
4103                     } else {
4104                         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4105                     }
4106                 case java.sql.Types.TIMESTAMP:
4107                     if (srcType == java.sql.Types.TIME) {
4108                         return new Timestamp(((java.sql.Time)srcObj).getTime());
4109                     } else {
4110                         return new Timestamp(((java.sql.Date)srcObj).getTime());
4111                     }
4112                 case java.sql.Types.TIME:
4113                     if (srcType == java.sql.Types.TIMESTAMP) {
4114                         return new Time(((java.sql.Timestamp)srcObj).getTime());
4115                     } else {
4116                         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4117                     }
4118                 case java.sql.Types.CHAR:
4119                 case java.sql.Types.VARCHAR:
4120                 case java.sql.Types.LONGVARCHAR:
4121                     return srcObj.toString();
4122                 default:
4123                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4124             }
4125         } catch (NumberFormatException ex) {
4126             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4127         }
4128 
4129     }
4130 
4131     /**
4132      * Converts the given <code>Object</code> in the Java programming language
4133      * to the standard mapping for the specified SQL target data type.
4134      * The conversion must be to a string or numeric type, but there are no
4135      * restrictions on the type to be converted.  If the source type and target
4136      * type are the same, the given object is simply returned.
4137      *
4138      * @param srcObj the <code>Object</code> in the Java programming language
4139      *               that is to be converted to the target type
4140      * @param srcType the data type that is the standard mapping in SQL of the
4141      *                object to be converted; must be one of the constants in
4142      *                <code>java.sql.Types</code>
4143      * @param trgType the SQL data type to which to convert the given object;
4144      *                must be one of the following constants in
4145      *                <code>java.sql.Types</code>: <code>BIT</code>,
4146      *         or <code>BOOLEAN</code>
4147      * @return an <code>Object</code> value.that is
4148      *         the standard object mapping for the target SQL type
4149      * @throws SQLException if the given target type is not one of the Boolean
4150      *         types in <code>java.sql.Types</code>
4151      */
4152     private Object convertBoolean(Object srcObj, int srcType,
4153     int trgType) throws SQLException {
4154 
4155         if (srcType == trgType) {
4156             return srcObj;
4157         }
4158 
4159         if (isNumeric(trgType) == true ||
4160         (isString(trgType) == false && isBoolean(trgType) == false)) {
4161             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4162         }
4163 
4164 
4165         try {
4166             switch (trgType) {
4167                 case java.sql.Types.BIT:
4168                     Integer i = Integer.valueOf(srcObj.toString().trim());
4169                     return i.equals(0) ?
4170                     Boolean.valueOf(false) :
4171                         Boolean.valueOf(true);
4172                 case java.sql.Types.BOOLEAN:
4173                     return Boolean.valueOf(srcObj.toString().trim());
4174                 default:
4175                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString()+ trgType);
4176             }
4177         } catch (NumberFormatException ex) {
4178             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4179         }
4180     }
4181 
4182     /**
4183      * Sets the designated nullable column in the current row or the
4184      * insert row of this <code>CachedRowSetImpl</code> object with
4185      * <code>null</code> value.
4186      * <P>
4187      * This method updates a column value in the current row or the insert
4188      * row of this rowset; however, another method must be called to complete
4189      * the update process. If the cursor is on a row in the rowset, the
4190      * method {@link #updateRow} must be called to mark the row as updated
4191      * and to notify listeners that the row has changed.
4192      * If the cursor is on the insert row, the method {@link #insertRow}
4193      * must be called to insert the new row into this rowset and to notify
4194      * listeners that a row has changed.
4195      * <P>
4196      * In order to propagate updates in this rowset to the underlying
4197      * data source, an application must call the method {@link #acceptChanges}
4198      * after it calls either <code>updateRow</code> or <code>insertRow</code>.
4199      *
4200      * @param columnIndex the first column is <code>1</code>, the second
4201      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4202      *        and equal to or less than the number of columns in this rowset
4203      * @throws SQLException if (1) the given column index is out of bounds,
4204      *            (2) the cursor is not on one of this rowset's rows or its
4205      *            insert row, or (3) this rowset is
4206      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4207      */
4208     public void updateNull(int columnIndex) throws SQLException {
4209         // sanity check.
4210         checkIndex(columnIndex);
4211         // make sure the cursor is on a valid row
4212         checkCursor();
4213 
4214         BaseRow row = getCurrentRow();
4215         row.setColumnObject(columnIndex, null);
4216 
4217     }
4218 
4219     /**
4220      * Sets the designated column in either the current row or the insert
4221      * row of this <code>CachedRowSetImpl</code> object with the given
4222      * <code>boolean</code> value.
4223      * <P>
4224      * This method updates a column value in the current row or the insert
4225      * row of this rowset, but it does not update the database.
4226      * If the cursor is on a row in the rowset, the
4227      * method {@link #updateRow} must be called to update the database.
4228      * If the cursor is on the insert row, the method {@link #insertRow}
4229      * must be called, which will insert the new row into both this rowset
4230      * and the database. Both of these methods must be called before the
4231      * cursor moves to another row.
4232      *
4233      * @param columnIndex the first column is <code>1</code>, the second
4234      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4235      *        and equal to or less than the number of columns in this rowset
4236      * @param x the new column value
4237      * @throws SQLException if (1) the given column index is out of bounds,
4238      *            (2) the cursor is not on one of this rowset's rows or its
4239      *            insert row, or (3) this rowset is
4240      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4241      */
4242     public void updateBoolean(int columnIndex, boolean x) throws SQLException {
4243         // sanity check.
4244         checkIndex(columnIndex);
4245         // make sure the cursor is on a valid row
4246         checkCursor();
4247         Object obj = convertBoolean(Boolean.valueOf(x),
4248         java.sql.Types.BIT,
4249         RowSetMD.getColumnType(columnIndex));
4250 
4251         getCurrentRow().setColumnObject(columnIndex, obj);
4252     }
4253 
4254     /**
4255      * Sets the designated column in either the current row or the insert
4256      * row of this <code>CachedRowSetImpl</code> object with the given
4257      * <code>byte</code> value.
4258      * <P>
4259      * This method updates a column value in the current row or the insert
4260      * row of this rowset, but it does not update the database.
4261      * If the cursor is on a row in the rowset, the
4262      * method {@link #updateRow} must be called to update the database.
4263      * If the cursor is on the insert row, the method {@link #insertRow}
4264      * must be called, which will insert the new row into both this rowset
4265      * and the database. Both of these methods must be called before the
4266      * cursor moves to another row.
4267      *
4268      * @param columnIndex the first column is <code>1</code>, the second
4269      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4270      *        and equal to or less than the number of columns in this rowset
4271      * @param x the new column value
4272      * @throws SQLException if (1) the given column index is out of bounds,
4273      *            (2) the cursor is not on one of this rowset's rows or its
4274      *            insert row, or (3) this rowset is
4275      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4276      */
4277     public void updateByte(int columnIndex, byte x) throws SQLException {
4278         // sanity check.
4279         checkIndex(columnIndex);
4280         // make sure the cursor is on a valid row
4281         checkCursor();
4282 
4283         Object obj = convertNumeric(Byte.valueOf(x),
4284         java.sql.Types.TINYINT,
4285         RowSetMD.getColumnType(columnIndex));
4286 
4287         getCurrentRow().setColumnObject(columnIndex, obj);
4288     }
4289 
4290     /**
4291      * Sets the designated column in either the current row or the insert
4292      * row of this <code>CachedRowSetImpl</code> object with the given
4293      * <code>short</code> value.
4294      * <P>
4295      * This method updates a column value in the current row or the insert
4296      * row of this rowset, but it does not update the database.
4297      * If the cursor is on a row in the rowset, the
4298      * method {@link #updateRow} must be called to update the database.
4299      * If the cursor is on the insert row, the method {@link #insertRow}
4300      * must be called, which will insert the new row into both this rowset
4301      * and the database. Both of these methods must be called before the
4302      * cursor moves to another row.
4303      *
4304      * @param columnIndex the first column is <code>1</code>, the second
4305      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4306      *        and equal to or less than the number of columns in this rowset
4307      * @param x the new column value
4308      * @throws SQLException if (1) the given column index is out of bounds,
4309      *            (2) the cursor is not on one of this rowset's rows or its
4310      *            insert row, or (3) this rowset is
4311      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4312      */
4313     public void updateShort(int columnIndex, short x) throws SQLException {
4314         // sanity check.
4315         checkIndex(columnIndex);
4316         // make sure the cursor is on a valid row
4317         checkCursor();
4318 
4319         Object obj = convertNumeric(Short.valueOf(x),
4320         java.sql.Types.SMALLINT,
4321         RowSetMD.getColumnType(columnIndex));
4322 
4323         getCurrentRow().setColumnObject(columnIndex, obj);
4324     }
4325 
4326     /**
4327      * Sets the designated column in either the current row or the insert
4328      * row of this <code>CachedRowSetImpl</code> object with the given
4329      * <code>int</code> value.
4330      * <P>
4331      * This method updates a column value in the current row or the insert
4332      * row of this rowset, but it does not update the database.
4333      * If the cursor is on a row in the rowset, the
4334      * method {@link #updateRow} must be called to update the database.
4335      * If the cursor is on the insert row, the method {@link #insertRow}
4336      * must be called, which will insert the new row into both this rowset
4337      * and the database. Both of these methods must be called before the
4338      * cursor moves to another row.
4339      *
4340      * @param columnIndex the first column is <code>1</code>, the second
4341      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4342      *        and equal to or less than the number of columns in this rowset
4343      * @param x the new column value
4344      * @throws SQLException if (1) the given column index is out of bounds,
4345      *            (2) the cursor is not on one of this rowset's rows or its
4346      *            insert row, or (3) this rowset is
4347      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4348      */
4349     public void updateInt(int columnIndex, int x) throws SQLException {
4350         // sanity check.
4351         checkIndex(columnIndex);
4352         // make sure the cursor is on a valid row
4353         checkCursor();
4354         Object obj = convertNumeric(x,
4355         java.sql.Types.INTEGER,
4356         RowSetMD.getColumnType(columnIndex));
4357 
4358         getCurrentRow().setColumnObject(columnIndex, obj);
4359     }
4360 
4361     /**
4362      * Sets the designated column in either the current row or the insert
4363      * row of this <code>CachedRowSetImpl</code> object with the given
4364      * <code>long</code> value.
4365      * <P>
4366      * This method updates a column value in the current row or the insert
4367      * row of this rowset, but it does not update the database.
4368      * If the cursor is on a row in the rowset, the
4369      * method {@link #updateRow} must be called to update the database.
4370      * If the cursor is on the insert row, the method {@link #insertRow}
4371      * must be called, which will insert the new row into both this rowset
4372      * and the database. Both of these methods must be called before the
4373      * cursor moves to another row.
4374      *
4375      * @param columnIndex the first column is <code>1</code>, the second
4376      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4377      *        and equal to or less than the number of columns in this rowset
4378      * @param x the new column value
4379      * @throws SQLException if (1) the given column index is out of bounds,
4380      *            (2) the cursor is not on one of this rowset's rows or its
4381      *            insert row, or (3) this rowset is
4382      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4383      */
4384     public void updateLong(int columnIndex, long x) throws SQLException {
4385         // sanity check.
4386         checkIndex(columnIndex);
4387         // make sure the cursor is on a valid row
4388         checkCursor();
4389 
4390         Object obj = convertNumeric(Long.valueOf(x),
4391         java.sql.Types.BIGINT,
4392         RowSetMD.getColumnType(columnIndex));
4393 
4394         getCurrentRow().setColumnObject(columnIndex, obj);
4395 
4396     }
4397 
4398     /**
4399      * Sets the designated column in either the current row or the insert
4400      * row of this <code>CachedRowSetImpl</code> object with the given
4401      * <code>float</code> value.
4402      * <P>
4403      * This method updates a column value in the current row or the insert
4404      * row of this rowset, but it does not update the database.
4405      * If the cursor is on a row in the rowset, the
4406      * method {@link #updateRow} must be called to update the database.
4407      * If the cursor is on the insert row, the method {@link #insertRow}
4408      * must be called, which will insert the new row into both this rowset
4409      * and the database. Both of these methods must be called before the
4410      * cursor moves to another row.
4411      *
4412      * @param columnIndex the first column is <code>1</code>, the second
4413      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4414      *        and equal to or less than the number of columns in this rowset
4415      * @param x the new column value
4416      * @throws SQLException if (1) the given column index is out of bounds,
4417      *            (2) the cursor is not on one of this rowset's rows or its
4418      *            insert row, or (3) this rowset is
4419      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4420      */
4421     public void updateFloat(int columnIndex, float x) throws SQLException {
4422         // sanity check.
4423         checkIndex(columnIndex);
4424         // make sure the cursor is on a valid row
4425         checkCursor();
4426 
4427         Object obj = convertNumeric(Float.valueOf(x),
4428         java.sql.Types.REAL,
4429         RowSetMD.getColumnType(columnIndex));
4430 
4431         getCurrentRow().setColumnObject(columnIndex, obj);
4432     }
4433 
4434     /**
4435      * Sets the designated column in either the current row or the insert
4436      * row of this <code>CachedRowSetImpl</code> object with the given
4437      * <code>double</code> value.
4438      *
4439      * This method updates a column value in either the current row or
4440      * the insert row of this rowset, but it does not update the
4441      * database.  If the cursor is on a row in the rowset, the
4442      * method {@link #updateRow} must be called to update the database.
4443      * If the cursor is on the insert row, the method {@link #insertRow}
4444      * must be called, which will insert the new row into both this rowset
4445      * and the database. Both of these methods must be called before the
4446      * cursor moves to another row.
4447      *
4448      * @param columnIndex the first column is <code>1</code>, the second
4449      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4450      *        and equal to or less than the number of columns in this rowset
4451      * @param x the new column value
4452      * @throws SQLException if (1) the given column index is out of bounds,
4453      *            (2) the cursor is not on one of this rowset's rows or its
4454      *            insert row, or (3) this rowset is
4455      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4456      */
4457     public void updateDouble(int columnIndex, double x) throws SQLException {
4458         // sanity check.
4459         checkIndex(columnIndex);
4460         // make sure the cursor is on a valid row
4461         checkCursor();
4462         Object obj = convertNumeric(Double.valueOf(x),
4463         java.sql.Types.DOUBLE,
4464         RowSetMD.getColumnType(columnIndex));
4465 
4466         getCurrentRow().setColumnObject(columnIndex, obj);
4467     }
4468 
4469     /**
4470      * Sets the designated column in either the current row or the insert
4471      * row of this <code>CachedRowSetImpl</code> object with the given
4472      * <code>java.math.BigDecimal</code> object.
4473      * <P>
4474      * This method updates a column value in the current row or the insert
4475      * row of this rowset, but it does not update the database.
4476      * If the cursor is on a row in the rowset, the
4477      * method {@link #updateRow} must be called to update the database.
4478      * If the cursor is on the insert row, the method {@link #insertRow}
4479      * must be called, which will insert the new row into both this rowset
4480      * and the database. Both of these methods must be called before the
4481      * cursor moves to another row.
4482      *
4483      * @param columnIndex the first column is <code>1</code>, the second
4484      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4485      *        and equal to or less than the number of columns in this rowset
4486      * @param x the new column value
4487      * @throws SQLException if (1) the given column index is out of bounds,
4488      *            (2) the cursor is not on one of this rowset's rows or its
4489      *            insert row, or (3) this rowset is
4490      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4491      */
4492     public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {
4493         // sanity check.
4494         checkIndex(columnIndex);
4495         // make sure the cursor is on a valid row
4496         checkCursor();
4497 
4498         Object obj = convertNumeric(x,
4499         java.sql.Types.NUMERIC,
4500         RowSetMD.getColumnType(columnIndex));
4501 
4502         getCurrentRow().setColumnObject(columnIndex, obj);
4503     }
4504 
4505     /**
4506      * Sets the designated column in either the current row or the insert
4507      * row of this <code>CachedRowSetImpl</code> object with the given
4508      * <code>String</code> object.
4509      * <P>
4510      * This method updates a column value in either the current row or
4511      * the insert row of this rowset, but it does not update the
4512      * database.  If the cursor is on a row in the rowset, the
4513      * method {@link #updateRow} must be called to mark the row as updated.
4514      * If the cursor is on the insert row, the method {@link #insertRow}
4515      * must be called to insert the new row into this rowset and mark it
4516      * as inserted. Both of these methods must be called before the
4517      * cursor moves to another row.
4518      * <P>
4519      * The method <code>acceptChanges</code> must be called if the
4520      * updated values are to be written back to the underlying database.
4521      *
4522      * @param columnIndex the first column is <code>1</code>, the second
4523      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4524      *        and equal to or less than the number of columns in this rowset
4525      * @param x the new column value
4526      * @throws SQLException if (1) the given column index is out of bounds,
4527      *            (2) the cursor is not on one of this rowset's rows or its
4528      *            insert row, or (3) this rowset is
4529      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4530      */
4531     public void updateString(int columnIndex, String x) throws SQLException {
4532         // sanity check.
4533         checkIndex(columnIndex);
4534         // make sure the cursor is on a valid row
4535         checkCursor();
4536 
4537         getCurrentRow().setColumnObject(columnIndex, x);
4538     }
4539 
4540     /**
4541      * Sets the designated column in either the current row or the insert
4542      * row of this <code>CachedRowSetImpl</code> object with the given
4543      * <code>byte</code> array.
4544      *
4545      * This method updates a column value in either the current row or
4546      * the insert row of this rowset, but it does not update the
4547      * database.  If the cursor is on a row in the rowset, the
4548      * method {@link #updateRow} must be called to update the database.
4549      * If the cursor is on the insert row, the method {@link #insertRow}
4550      * must be called, which will insert the new row into both this rowset
4551      * and the database. Both of these methods must be called before the
4552      * cursor moves to another row.
4553      *
4554      * @param columnIndex the first column is <code>1</code>, the second
4555      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4556      *        and equal to or less than the number of columns in this rowset
4557      * @param x the new column value
4558      * @throws SQLException if (1) the given column index is out of bounds,
4559      *            (2) the cursor is not on one of this rowset's rows or its
4560      *            insert row, or (3) this rowset is
4561      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4562      */
4563     public void updateBytes(int columnIndex, byte x[]) throws SQLException {
4564         // sanity check.
4565         checkIndex(columnIndex);
4566         // make sure the cursor is on a valid row
4567         checkCursor();
4568 
4569         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4570             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4571         }
4572 
4573         getCurrentRow().setColumnObject(columnIndex, x);
4574     }
4575 
4576     /**
4577      * Sets the designated column in either the current row or the insert
4578      * row of this <code>CachedRowSetImpl</code> object with the given
4579      * <code>Date</code> object.
4580      *
4581      * This method updates a column value in either the current row or
4582      * the insert row of this rowset, but it does not update the
4583      * database.  If the cursor is on a row in the rowset, the
4584      * method {@link #updateRow} must be called to update the database.
4585      * If the cursor is on the insert row, the method {@link #insertRow}
4586      * must be called, which will insert the new row into both this rowset
4587      * and the database. Both of these methods must be called before the
4588      * cursor moves to another row.
4589      *
4590      * @param columnIndex the first column is <code>1</code>, the second
4591      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4592      *        and equal to or less than the number of columns in this rowset
4593      * @param x the new column value
4594      * @throws SQLException if (1) the given column index is out of bounds,
4595      *            (2) the cursor is not on one of this rowset's rows or its
4596      *            insert row, (3) the type of the designated column is not
4597      *            an SQL <code>DATE</code> or <code>TIMESTAMP</code>, or
4598      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4599      */
4600     public void updateDate(int columnIndex, java.sql.Date x) throws SQLException {
4601         // sanity check.
4602         checkIndex(columnIndex);
4603         // make sure the cursor is on a valid row
4604         checkCursor();
4605 
4606         Object obj = convertTemporal(x,
4607         java.sql.Types.DATE,
4608         RowSetMD.getColumnType(columnIndex));
4609 
4610         getCurrentRow().setColumnObject(columnIndex, obj);
4611     }
4612 
4613     /**
4614      * Sets the designated column in either the current row or the insert
4615      * row of this <code>CachedRowSetImpl</code> object with the given
4616      * <code>Time</code> object.
4617      *
4618      * This method updates a column value in either the current row or
4619      * the insert row of this rowset, but it does not update the
4620      * database.  If the cursor is on a row in the rowset, the
4621      * method {@link #updateRow} must be called to update the database.
4622      * If the cursor is on the insert row, the method {@link #insertRow}
4623      * must be called, which will insert the new row into both this rowset
4624      * and the database. Both of these methods must be called before the
4625      * cursor moves to another row.
4626      *
4627      * @param columnIndex the first column is <code>1</code>, the second
4628      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4629      *        and equal to or less than the number of columns in this rowset
4630      * @param x the new column value
4631      * @throws SQLException if (1) the given column index is out of bounds,
4632      *            (2) the cursor is not on one of this rowset's rows or its
4633      *            insert row, (3) the type of the designated column is not
4634      *            an SQL <code>TIME</code> or <code>TIMESTAMP</code>, or
4635      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4636      */
4637     public void updateTime(int columnIndex, java.sql.Time x) throws SQLException {
4638         // sanity check.
4639         checkIndex(columnIndex);
4640         // make sure the cursor is on a valid row
4641         checkCursor();
4642 
4643         Object obj = convertTemporal(x,
4644         java.sql.Types.TIME,
4645         RowSetMD.getColumnType(columnIndex));
4646 
4647         getCurrentRow().setColumnObject(columnIndex, obj);
4648     }
4649 
4650     /**
4651      * Sets the designated column in either the current row or the insert
4652      * row of this <code>CachedRowSetImpl</code> object with the given
4653      * <code>Timestamp</code> object.
4654      *
4655      * This method updates a column value in either the current row or
4656      * the insert row of this rowset, but it does not update the
4657      * database.  If the cursor is on a row in the rowset, the
4658      * method {@link #updateRow} must be called to update the database.
4659      * If the cursor is on the insert row, the method {@link #insertRow}
4660      * must be called, which will insert the new row into both this rowset
4661      * and the database. Both of these methods must be called before the
4662      * cursor moves to another row.
4663      *
4664      * @param columnIndex the first column is <code>1</code>, the second
4665      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4666      *        and equal to or less than the number of columns in this rowset
4667      * @param x the new column value
4668      * @throws SQLException if (1) the given column index is out of bounds,
4669      *            (2) the cursor is not on one of this rowset's rows or its
4670      *            insert row, (3) the type of the designated column is not
4671      *            an SQL <code>DATE</code>, <code>TIME</code>, or
4672      *            <code>TIMESTAMP</code>, or (4) this rowset is
4673      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4674      */
4675     public void updateTimestamp(int columnIndex, java.sql.Timestamp x) throws SQLException {
4676         // sanity check.
4677         checkIndex(columnIndex);
4678         // make sure the cursor is on a valid row
4679         checkCursor();
4680 
4681         Object obj = convertTemporal(x,
4682         java.sql.Types.TIMESTAMP,
4683         RowSetMD.getColumnType(columnIndex));
4684 
4685         getCurrentRow().setColumnObject(columnIndex, obj);
4686     }
4687 
4688     /**
4689      * Sets the designated column in either the current row or the insert
4690      * row of this <code>CachedRowSetImpl</code> object with the given
4691      * ASCII stream value.
4692      * <P>
4693      * This method updates a column value in either the current row or
4694      * the insert row of this rowset, but it does not update the
4695      * database.  If the cursor is on a row in the rowset, the
4696      * method {@link #updateRow} must be called to update the database.
4697      * If the cursor is on the insert row, the method {@link #insertRow}
4698      * must be called, which will insert the new row into both this rowset
4699      * and the database. Both of these methods must be called before the
4700      * cursor moves to another row.
4701      *
4702      * @param columnIndex the first column is <code>1</code>, the second
4703      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4704      *        and equal to or less than the number of columns in this rowset
4705      * @param x the new column value
4706      * @param length the number of one-byte ASCII characters in the stream
4707      * @throws SQLException if this method is invoked
4708      */
4709     public void updateAsciiStream(int columnIndex, java.io.InputStream x, int length) throws SQLException {
4710         // sanity Check
4711         checkIndex(columnIndex);
4712         // make sure the cursor is on a valid row
4713         checkCursor();
4714 
4715 
4716         if (isString(RowSetMD.getColumnType(columnIndex)) == false &&
4717         isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4718             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4719         }
4720 
4721         byte buf[] = new byte[length];
4722         try {
4723             int charsRead = 0;
4724             do {
4725                 charsRead += x.read(buf, charsRead, length - charsRead);
4726             } while (charsRead != length);
4727             //Changed the condition check to check for length instead of -1
4728         } catch (java.io.IOException ex) {
4729             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.asciistream").toString());
4730         }
4731         String str = new String(buf);
4732 
4733         getCurrentRow().setColumnObject(columnIndex, str);
4734 
4735     }
4736 
4737     /**
4738      * Sets the designated column in either the current row or the insert
4739      * row of this <code>CachedRowSetImpl</code> object with the given
4740      * <code>java.io.InputStream</code> object.
4741      * <P>
4742      * This method updates a column value in either the current row or
4743      * the insert row of this rowset, but it does not update the
4744      * database.  If the cursor is on a row in the rowset, the
4745      * method {@link #updateRow} must be called to update the database.
4746      * If the cursor is on the insert row, the method {@link #insertRow}
4747      * must be called, which will insert the new row into both this rowset
4748      * and the database. Both of these methods must be called before the
4749      * cursor moves to another row.
4750      *
4751      * @param columnIndex the first column is <code>1</code>, the second
4752      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4753      *        and equal to or less than the number of columns in this rowset
4754      * @param x the new column value; must be a <code>java.io.InputStream</code>
4755      *          containing <code>BINARY</code>, <code>VARBINARY</code>, or
4756      *          <code>LONGVARBINARY</code> data
4757      * @param length the length of the stream in bytes
4758      * @throws SQLException if (1) the given column index is out of bounds,
4759      *            (2) the cursor is not on one of this rowset's rows or its
4760      *            insert row, (3) the data in the stream is not binary, or
4761      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4762      */
4763     public void updateBinaryStream(int columnIndex, java.io.InputStream x,int length) throws SQLException {
4764         // sanity Check
4765         checkIndex(columnIndex);
4766         // make sure the cursor is on a valid row
4767         checkCursor();
4768 
4769         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4770             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4771         }
4772 
4773         byte buf[] = new byte[length];
4774         try {
4775             int bytesRead = 0;
4776             do {
4777                 bytesRead += x.read(buf, bytesRead, length - bytesRead);
4778             } while (bytesRead != -1);
4779         } catch (java.io.IOException ex) {
4780             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.binstream").toString());
4781         }
4782 
4783         getCurrentRow().setColumnObject(columnIndex, buf);
4784     }
4785 
4786     /**
4787      * Sets the designated column in either the current row or the insert
4788      * row of this <code>CachedRowSetImpl</code> object with the given
4789      * <code>java.io.Reader</code> object.
4790      * <P>
4791      * This method updates a column value in either the current row or
4792      * the insert row of this rowset, but it does not update the
4793      * database.  If the cursor is on a row in the rowset, the
4794      * method {@link #updateRow} must be called to update the database.
4795      * If the cursor is on the insert row, the method {@link #insertRow}
4796      * must be called, which will insert the new row into both this rowset
4797      * and the database. Both of these methods must be called before the
4798      * cursor moves to another row.
4799      *
4800      * @param columnIndex the first column is <code>1</code>, the second
4801      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4802      *        and equal to or less than the number of columns in this rowset
4803      * @param x the new column value; must be a <code>java.io.Reader</code>
4804      *          containing <code>BINARY</code>, <code>VARBINARY</code>,
4805      *          <code>LONGVARBINARY</code>, <code>CHAR</code>, <code>VARCHAR</code>,
4806      *          or <code>LONGVARCHAR</code> data
4807      * @param length the length of the stream in characters
4808      * @throws SQLException if (1) the given column index is out of bounds,
4809      *            (2) the cursor is not on one of this rowset's rows or its
4810      *            insert row, (3) the data in the stream is not a binary or
4811      *            character type, or (4) this rowset is
4812      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4813      */
4814     public void updateCharacterStream(int columnIndex, java.io.Reader x, int length) throws SQLException {
4815         // sanity Check
4816         checkIndex(columnIndex);
4817         // make sure the cursor is on a valid row
4818         checkCursor();
4819 
4820         if (isString(RowSetMD.getColumnType(columnIndex)) == false &&
4821         isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4822             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4823         }
4824 
4825         char buf[] = new char[length];
4826         try {
4827             int charsRead = 0;
4828             do {
4829                 charsRead += x.read(buf, charsRead, length - charsRead);
4830             } while (charsRead != length);
4831             //Changed the condition checking to check for length instead of -1
4832         } catch (java.io.IOException ex) {
4833             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.binstream").toString());
4834         }
4835         String str = new String(buf);
4836 
4837         getCurrentRow().setColumnObject(columnIndex, str);
4838     }
4839 
4840     /**
4841      * Sets the designated column in either the current row or the insert
4842      * row of this <code>CachedRowSetImpl</code> object with the given
4843      * <code>Object</code> value.  The <code>scale</code> parameter indicates
4844      * the number of digits to the right of the decimal point and is ignored
4845      * if the new column value is not a type that will be mapped to an SQL
4846      * <code>DECIMAL</code> or <code>NUMERIC</code> value.
4847      * <P>
4848      * This method updates a column value in either the current row or
4849      * the insert row of this rowset, but it does not update the
4850      * database.  If the cursor is on a row in the rowset, the
4851      * method {@link #updateRow} must be called to update the database.
4852      * If the cursor is on the insert row, the method {@link #insertRow}
4853      * must be called, which will insert the new row into both this rowset
4854      * and the database. Both of these methods must be called before the
4855      * cursor moves to another row.
4856      *
4857      * @param columnIndex the first column is <code>1</code>, the second
4858      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4859      *        and equal to or less than the number of columns in this rowset
4860      * @param x the new column value
4861      * @param scale the number of digits to the right of the decimal point (for
4862      *              <code>DECIMAL</code> and <code>NUMERIC</code> types only)
4863      * @throws SQLException if (1) the given column index is out of bounds,
4864      *            (2) the cursor is not on one of this rowset's rows or its
4865      *            insert row, or (3) this rowset is
4866      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4867      */
4868     public void updateObject(int columnIndex, Object x, int scale) throws SQLException {
4869         // sanity check.
4870         checkIndex(columnIndex);
4871         // make sure the cursor is on a valid row
4872         checkCursor();
4873 
4874         int type = RowSetMD.getColumnType(columnIndex);
4875         if (type == Types.DECIMAL || type == Types.NUMERIC) {
4876             ((java.math.BigDecimal)x).setScale(scale);
4877         }
4878         getCurrentRow().setColumnObject(columnIndex, x);
4879     }
4880 
4881     /**
4882      * Sets the designated column in either the current row or the insert
4883      * row of this <code>CachedRowSetImpl</code> object with the given
4884      * <code>Object</code> value.
4885      * <P>
4886      * This method updates a column value in either the current row or
4887      * the insert row of this rowset, but it does not update the
4888      * database.  If the cursor is on a row in the rowset, the
4889      * method {@link #updateRow} must be called to update the database.
4890      * If the cursor is on the insert row, the method {@link #insertRow}
4891      * must be called, which will insert the new row into both this rowset
4892      * and the database. Both of these methods must be called before the
4893      * cursor moves to another row.
4894      *
4895      * @param columnIndex the first column is <code>1</code>, the second
4896      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4897      *        and equal to or less than the number of columns in this rowset
4898      * @param x the new column value
4899      * @throws SQLException if (1) the given column index is out of bounds,
4900      *            (2) the cursor is not on one of this rowset's rows or its
4901      *            insert row, or (3) this rowset is
4902      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4903      */
4904     public void updateObject(int columnIndex, Object x) throws SQLException {
4905         // sanity check.
4906         checkIndex(columnIndex);
4907         // make sure the cursor is on a valid row
4908         checkCursor();
4909 
4910         getCurrentRow().setColumnObject(columnIndex, x);
4911     }
4912 
4913     /**
4914      * Sets the designated nullable column in the current row or the
4915      * insert row of this <code>CachedRowSetImpl</code> object with
4916      * <code>null</code> value.
4917      * <P>
4918      * This method updates a column value in the current row or the insert
4919      * row of this rowset, but it does not update the database.
4920      * If the cursor is on a row in the rowset, the
4921      * method {@link #updateRow} must be called to update the database.
4922      * If the cursor is on the insert row, the method {@link #insertRow}
4923      * must be called, which will insert the new row into both this rowset
4924      * and the database.
4925      *
4926      * @param columnName a <code>String</code> object that must match the
4927      *        SQL name of a column in this rowset, ignoring case
4928      * @throws SQLException if (1) the given column name does not match the
4929      *            name of a column in this rowset, (2) the cursor is not on
4930      *            one of this rowset's rows or its insert row, or (3) this
4931      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4932      */
4933     public void updateNull(String columnName) throws SQLException {
4934         updateNull(getColIdxByName(columnName));
4935     }
4936 
4937     /**
4938      * Sets the designated column in either the current row or the insert
4939      * row of this <code>CachedRowSetImpl</code> object with the given
4940      * <code>boolean</code> value.
4941      * <P>
4942      * This method updates a column value in the current row or the insert
4943      * row of this rowset, but it does not update the database.
4944      * If the cursor is on a row in the rowset, the
4945      * method {@link #updateRow} must be called to update the database.
4946      * If the cursor is on the insert row, the method {@link #insertRow}
4947      * must be called, which will insert the new row into both this rowset
4948      * and the database. Both of these methods must be called before the
4949      * cursor moves to another row.
4950      *
4951      * @param columnName a <code>String</code> object that must match the
4952      *        SQL name of a column in this rowset, ignoring case
4953      * @param x the new column value
4954      * @throws SQLException if (1) the given column name does not match the
4955      *            name of a column in this rowset, (2) the cursor is not on
4956      *            one of this rowset's rows or its insert row, or (3) this
4957      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4958      */
4959     public void updateBoolean(String columnName, boolean x) throws SQLException {
4960         updateBoolean(getColIdxByName(columnName), x);
4961     }
4962 
4963     /**
4964      * Sets the designated column in either the current row or the insert
4965      * row of this <code>CachedRowSetImpl</code> object with the given
4966      * <code>byte</code> value.
4967      * <P>
4968      * This method updates a column value in the current row or the insert
4969      * row of this rowset, but it does not update the database.
4970      * If the cursor is on a row in the rowset, the
4971      * method {@link #updateRow} must be called to update the database.
4972      * If the cursor is on the insert row, the method {@link #insertRow}
4973      * must be called, which will insert the new row into both this rowset
4974      * and the database. Both of these methods must be called before the
4975      * cursor moves to another row.
4976      *
4977      * @param columnName a <code>String</code> object that must match the
4978      *        SQL name of a column in this rowset, ignoring case
4979      * @param x the new column value
4980      * @throws SQLException if (1) the given column name does not match the
4981      *            name of a column in this rowset, (2) the cursor is not on
4982      *            one of this rowset's rows or its insert row, or (3) this
4983      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4984      */
4985     public void updateByte(String columnName, byte x) throws SQLException {
4986         updateByte(getColIdxByName(columnName), x);
4987     }
4988 
4989     /**
4990      * Sets the designated column in either the current row or the insert
4991      * row of this <code>CachedRowSetImpl</code> object with the given
4992      * <code>short</code> value.
4993      * <P>
4994      * This method updates a column value in the current row or the insert
4995      * row of this rowset, but it does not update the database.
4996      * If the cursor is on a row in the rowset, the
4997      * method {@link #updateRow} must be called to update the database.
4998      * If the cursor is on the insert row, the method {@link #insertRow}
4999      * must be called, which will insert the new row into both this rowset
5000      * and the database. Both of these methods must be called before the
5001      * cursor moves to another row.
5002      *
5003      * @param columnName a <code>String</code> object that must match the
5004      *        SQL name of a column in this rowset, ignoring case
5005      * @param x the new column value
5006      * @throws SQLException if (1) the given column name does not match the
5007      *            name of a column in this rowset, (2) the cursor is not on
5008      *            one of this rowset's rows or its insert row, or (3) this
5009      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5010      */
5011     public void updateShort(String columnName, short x) throws SQLException {
5012         updateShort(getColIdxByName(columnName), x);
5013     }
5014 
5015     /**
5016      * Sets the designated column in either the current row or the insert
5017      * row of this <code>CachedRowSetImpl</code> object with the given
5018      * <code>int</code> value.
5019      * <P>
5020      * This method updates a column value in the current row or the insert
5021      * row of this rowset, but it does not update the database.
5022      * If the cursor is on a row in the rowset, the
5023      * method {@link #updateRow} must be called to update the database.
5024      * If the cursor is on the insert row, the method {@link #insertRow}
5025      * must be called, which will insert the new row into both this rowset
5026      * and the database. Both of these methods must be called before the
5027      * cursor moves to another row.
5028      *
5029      * @param columnName a <code>String</code> object that must match the
5030      *        SQL name of a column in this rowset, ignoring case
5031      * @param x the new column value
5032      * @throws SQLException if (1) the given column name does not match the
5033      *            name of a column in this rowset, (2) the cursor is not on
5034      *            one of this rowset's rows or its insert row, or (3) this
5035      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5036      */
5037     public void updateInt(String columnName, int x) throws SQLException {
5038         updateInt(getColIdxByName(columnName), x);
5039     }
5040 
5041     /**
5042      * Sets the designated column in either the current row or the insert
5043      * row of this <code>CachedRowSetImpl</code> object with the given
5044      * <code>long</code> value.
5045      * <P>
5046      * This method updates a column value in the current row or the insert
5047      * row of this rowset, but it does not update the database.
5048      * If the cursor is on a row in the rowset, the
5049      * method {@link #updateRow} must be called to update the database.
5050      * If the cursor is on the insert row, the method {@link #insertRow}
5051      * must be called, which will insert the new row into both this rowset
5052      * and the database. Both of these methods must be called before the
5053      * cursor moves to another row.
5054      *
5055      * @param columnName a <code>String</code> object that must match the
5056      *        SQL name of a column in this rowset, ignoring case
5057      * @param x the new column value
5058      * @throws SQLException if (1) the given column name does not match the
5059      *            name of a column in this rowset, (2) the cursor is not on
5060      *            one of this rowset's rows or its insert row, or (3) this
5061      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5062      */
5063     public void updateLong(String columnName, long x) throws SQLException {
5064         updateLong(getColIdxByName(columnName), x);
5065     }
5066 
5067     /**
5068      * Sets the designated column in either the current row or the insert
5069      * row of this <code>CachedRowSetImpl</code> object with the given
5070      * <code>float</code> value.
5071      * <P>
5072      * This method updates a column value in the current row or the insert
5073      * row of this rowset, but it does not update the database.
5074      * If the cursor is on a row in the rowset, the
5075      * method {@link #updateRow} must be called to update the database.
5076      * If the cursor is on the insert row, the method {@link #insertRow}
5077      * must be called, which will insert the new row into both this rowset
5078      * and the database. Both of these methods must be called before the
5079      * cursor moves to another row.
5080      *
5081      * @param columnName a <code>String</code> object that must match the
5082      *        SQL name of a column in this rowset, ignoring case
5083      * @param x the new column value
5084      * @throws SQLException if (1) the given column name does not match the
5085      *            name of a column in this rowset, (2) the cursor is not on
5086      *            one of this rowset's rows or its insert row, or (3) this
5087      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5088      */
5089     public void updateFloat(String columnName, float x) throws SQLException {
5090         updateFloat(getColIdxByName(columnName), x);
5091     }
5092 
5093     /**
5094      * Sets the designated column in either the current row or the insert
5095      * row of this <code>CachedRowSetImpl</code> object with the given
5096      * <code>double</code> value.
5097      *
5098      * This method updates a column value in either the current row or
5099      * the insert row of this rowset, but it does not update the
5100      * database.  If the cursor is on a row in the rowset, the
5101      * method {@link #updateRow} must be called to update the database.
5102      * If the cursor is on the insert row, the method {@link #insertRow}
5103      * must be called, which will insert the new row into both this rowset
5104      * and the database. Both of these methods must be called before the
5105      * cursor moves to another row.
5106      *
5107      * @param columnName a <code>String</code> object that must match the
5108      *        SQL name of a column in this rowset, ignoring case
5109      * @param x the new column value
5110      * @throws SQLException if (1) the given column name does not match the
5111      *            name of a column in this rowset, (2) the cursor is not on
5112      *            one of this rowset's rows or its insert row, or (3) this
5113      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5114      */
5115     public void updateDouble(String columnName, double x) throws SQLException {
5116         updateDouble(getColIdxByName(columnName), x);
5117     }
5118 
5119     /**
5120      * Sets the designated column in either the current row or the insert
5121      * row of this <code>CachedRowSetImpl</code> object with the given
5122      * <code>java.math.BigDecimal</code> object.
5123      * <P>
5124      * This method updates a column value in the current row or the insert
5125      * row of this rowset, but it does not update the database.
5126      * If the cursor is on a row in the rowset, the
5127      * method {@link #updateRow} must be called to update the database.
5128      * If the cursor is on the insert row, the method {@link #insertRow}
5129      * must be called, which will insert the new row into both this rowset
5130      * and the database. Both of these methods must be called before the
5131      * cursor moves to another row.
5132      *
5133      * @param columnName a <code>String</code> object that must match the
5134      *        SQL name of a column in this rowset, ignoring case
5135      * @param x the new column value
5136      * @throws SQLException if (1) the given column name does not match the
5137      *            name of a column in this rowset, (2) the cursor is not on
5138      *            one of this rowset's rows or its insert row, or (3) this
5139      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5140      */
5141     public void updateBigDecimal(String columnName, BigDecimal x) throws SQLException {
5142         updateBigDecimal(getColIdxByName(columnName), x);
5143     }
5144 
5145     /**
5146      * Sets the designated column in either the current row or the insert
5147      * row of this <code>CachedRowSetImpl</code> object with the given
5148      * <code>String</code> object.
5149      *
5150      * This method updates a column value in either the current row or
5151      * the insert row of this rowset, but it does not update the
5152      * database.  If the cursor is on a row in the rowset, the
5153      * method {@link #updateRow} must be called to update the database.
5154      * If the cursor is on the insert row, the method {@link #insertRow}
5155      * must be called, which will insert the new row into both this rowset
5156      * and the database. Both of these methods must be called before the
5157      * cursor moves to another row.
5158      *
5159      * @param columnName a <code>String</code> object that must match the
5160      *        SQL name of a column in this rowset, ignoring case
5161      * @param x the new column value
5162      * @throws SQLException if (1) the given column name does not match the
5163      *            name of a column in this rowset, (2) the cursor is not on
5164      *            one of this rowset's rows or its insert row, or (3) this
5165      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5166      */
5167     public void updateString(String columnName, String x) throws SQLException {
5168         updateString(getColIdxByName(columnName), x);
5169     }
5170 
5171     /**
5172      * Sets the designated column in either the current row or the insert
5173      * row of this <code>CachedRowSetImpl</code> object with the given
5174      * <code>byte</code> array.
5175      *
5176      * This method updates a column value in either the current row or
5177      * the insert row of this rowset, but it does not update the
5178      * database.  If the cursor is on a row in the rowset, the
5179      * method {@link #updateRow} must be called to update the database.
5180      * If the cursor is on the insert row, the method {@link #insertRow}
5181      * must be called, which will insert the new row into both this rowset
5182      * and the database. Both of these methods must be called before the
5183      * cursor moves to another row.
5184      *
5185      * @param columnName a <code>String</code> object that must match the
5186      *        SQL name of a column in this rowset, ignoring case
5187      * @param x the new column value
5188      * @throws SQLException if (1) the given column name does not match the
5189      *            name of a column in this rowset, (2) the cursor is not on
5190      *            one of this rowset's rows or its insert row, or (3) this
5191      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5192      */
5193     public void updateBytes(String columnName, byte x[]) throws SQLException {
5194         updateBytes(getColIdxByName(columnName), x);
5195     }
5196 
5197     /**
5198      * Sets the designated column in either the current row or the insert
5199      * row of this <code>CachedRowSetImpl</code> object with the given
5200      * <code>Date</code> object.
5201      *
5202      * This method updates a column value in either the current row or
5203      * the insert row of this rowset, but it does not update the
5204      * database.  If the cursor is on a row in the rowset, the
5205      * method {@link #updateRow} must be called to update the database.
5206      * If the cursor is on the insert row, the method {@link #insertRow}
5207      * must be called, which will insert the new row into both this rowset
5208      * and the database. Both of these methods must be called before the
5209      * cursor moves to another row.
5210      *
5211      * @param columnName a <code>String</code> object that must match the
5212      *        SQL name of a column in this rowset, ignoring case
5213      * @param x the new column value
5214      * @throws SQLException if (1) the given column name does not match the
5215      *            name of a column in this rowset, (2) the cursor is not on
5216      *            one of this rowset's rows or its insert row, (3) the type
5217      *            of the designated column is not an SQL <code>DATE</code> or
5218      *            <code>TIMESTAMP</code>, or (4) this rowset is
5219      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5220      */
5221     public void updateDate(String columnName, java.sql.Date x) throws SQLException {
5222         updateDate(getColIdxByName(columnName), x);
5223     }
5224 
5225     /**
5226      * Sets the designated column in either the current row or the insert
5227      * row of this <code>CachedRowSetImpl</code> object with the given
5228      * <code>Time</code> object.
5229      *
5230      * This method updates a column value in either the current row or
5231      * the insert row of this rowset, but it does not update the
5232      * database.  If the cursor is on a row in the rowset, the
5233      * method {@link #updateRow} must be called to update the database.
5234      * If the cursor is on the insert row, the method {@link #insertRow}
5235      * must be called, which will insert the new row into both this rowset
5236      * and the database. Both of these methods must be called before the
5237      * cursor moves to another row.
5238      *
5239      * @param columnName a <code>String</code> object that must match the
5240      *        SQL name of a column in this rowset, ignoring case
5241      * @param x the new column value
5242      * @throws SQLException if (1) the given column name does not match the
5243      *            name of a column in this rowset, (2) the cursor is not on
5244      *            one of this rowset's rows or its insert row, (3) the type
5245      *            of the designated column is not an SQL <code>TIME</code> or
5246      *            <code>TIMESTAMP</code>, or (4) this rowset is
5247      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5248      */
5249     public void updateTime(String columnName, java.sql.Time x) throws SQLException {
5250         updateTime(getColIdxByName(columnName), x);
5251     }
5252 
5253     /**
5254      * Sets the designated column in either the current row or the insert
5255      * row of this <code>CachedRowSetImpl</code> object with the given
5256      * <code>Timestamp</code> object.
5257      *
5258      * This method updates a column value in either the current row or
5259      * the insert row of this rowset, but it does not update the
5260      * database.  If the cursor is on a row in the rowset, the
5261      * method {@link #updateRow} must be called to update the database.
5262      * If the cursor is on the insert row, the method {@link #insertRow}
5263      * must be called, which will insert the new row into both this rowset
5264      * and the database. Both of these methods must be called before the
5265      * cursor moves to another row.
5266      *
5267      * @param columnName a <code>String</code> object that must match the
5268      *        SQL name of a column in this rowset, ignoring case
5269      * @param x the new column value
5270      * @throws SQLException if the given column index is out of bounds or
5271      *            the cursor is not on one of this rowset's rows or its
5272      *            insert row
5273      * @throws SQLException if (1) the given column name does not match the
5274      *            name of a column in this rowset, (2) the cursor is not on
5275      *            one of this rowset's rows or its insert row, (3) the type
5276      *            of the designated column is not an SQL <code>DATE</code>,
5277      *            <code>TIME</code>, or <code>TIMESTAMP</code>, or (4) this
5278      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5279      */
5280     public void updateTimestamp(String columnName, java.sql.Timestamp x) throws SQLException {
5281         updateTimestamp(getColIdxByName(columnName), x);
5282     }
5283 
5284     /**
5285      * Sets the designated column in either the current row or the insert
5286      * row of this <code>CachedRowSetImpl</code> object with the given
5287      * ASCII stream value.
5288      * <P>
5289      * This method updates a column value in either the current row or
5290      * the insert row of this rowset, but it does not update the
5291      * database.  If the cursor is on a row in the rowset, the
5292      * method {@link #updateRow} must be called to update the database.
5293      * If the cursor is on the insert row, the method {@link #insertRow}
5294      * must be called, which will insert the new row into both this rowset
5295      * and the database. Both of these methods must be called before the
5296      * cursor moves to another row.
5297      *
5298      * @param columnName a <code>String</code> object that must match the
5299      *        SQL name of a column in this rowset, ignoring case
5300      * @param x the new column value
5301      * @param length the number of one-byte ASCII characters in the stream
5302      */
5303     public void updateAsciiStream(String columnName,
5304     java.io.InputStream x,
5305     int length) throws SQLException {
5306         updateAsciiStream(getColIdxByName(columnName), x, length);
5307     }
5308 
5309     /**
5310      * Sets the designated column in either the current row or the insert
5311      * row of this <code>CachedRowSetImpl</code> object with the given
5312      * <code>java.io.InputStream</code> object.
5313      * <P>
5314      * This method updates a column value in either the current row or
5315      * the insert row of this rowset, but it does not update the
5316      * database.  If the cursor is on a row in the rowset, the
5317      * method {@link #updateRow} must be called to update the database.
5318      * If the cursor is on the insert row, the method {@link #insertRow}
5319      * must be called, which will insert the new row into both this rowset
5320      * and the database. Both of these methods must be called before the
5321      * cursor moves to another row.
5322      *
5323      * @param columnName a <code>String</code> object that must match the
5324      *        SQL name of a column in this rowset, ignoring case
5325      * @param x the new column value; must be a <code>java.io.InputStream</code>
5326      *          containing <code>BINARY</code>, <code>VARBINARY</code>, or
5327      *          <code>LONGVARBINARY</code> data
5328      * @param length the length of the stream in bytes
5329      * @throws SQLException if (1) the given column name does not match the
5330      *            name of a column in this rowset, (2) the cursor is not on
5331      *            one of this rowset's rows or its insert row, (3) the data
5332      *            in the stream is not binary, or (4) this rowset is
5333      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5334      */
5335     public void updateBinaryStream(String columnName, java.io.InputStream x, int length) throws SQLException {
5336         updateBinaryStream(getColIdxByName(columnName), x, length);
5337     }
5338 
5339     /**
5340      * Sets the designated column in either the current row or the insert
5341      * row of this <code>CachedRowSetImpl</code> object with the given
5342      * <code>java.io.Reader</code> object.
5343      * <P>
5344      * This method updates a column value in either the current row or
5345      * the insert row of this rowset, but it does not update the
5346      * database.  If the cursor is on a row in the rowset, the
5347      * method {@link #updateRow} must be called to update the database.
5348      * If the cursor is on the insert row, the method {@link #insertRow}
5349      * must be called, which will insert the new row into both this rowset
5350      * and the database. Both of these methods must be called before the
5351      * cursor moves to another row.
5352      *
5353      * @param columnName a <code>String</code> object that must match the
5354      *        SQL name of a column in this rowset, ignoring case
5355      * @param reader the new column value; must be a
5356      * <code>java.io.Reader</code> containing <code>BINARY</code>,
5357      * <code>VARBINARY</code>, <code>LONGVARBINARY</code>, <code>CHAR</code>,
5358      * <code>VARCHAR</code>, or <code>LONGVARCHAR</code> data
5359      * @param length the length of the stream in characters
5360      * @throws SQLException if (1) the given column name does not match the
5361      *            name of a column in this rowset, (2) the cursor is not on
5362      *            one of this rowset's rows or its insert row, (3) the data
5363      *            in the stream is not a binary or character type, or (4) this
5364      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5365      */
5366     public void updateCharacterStream(String columnName,
5367     java.io.Reader reader,
5368     int length) throws SQLException {
5369         updateCharacterStream(getColIdxByName(columnName), reader, length);
5370     }
5371 
5372     /**
5373      * Sets the designated column in either the current row or the insert
5374      * row of this <code>CachedRowSetImpl</code> object with the given
5375      * <code>Object</code> value.  The <code>scale</code> parameter
5376      * indicates the number of digits to the right of the decimal point
5377      * and is ignored if the new column value is not a type that will be
5378      *  mapped to an SQL <code>DECIMAL</code> or <code>NUMERIC</code> value.
5379      * <P>
5380      * This method updates a column value in either the current row or
5381      * the insert row of this rowset, but it does not update the
5382      * database.  If the cursor is on a row in the rowset, the
5383      * method {@link #updateRow} must be called to update the database.
5384      * If the cursor is on the insert row, the method {@link #insertRow}
5385      * must be called, which will insert the new row into both this rowset
5386      * and the database. Both of these methods must be called before the
5387      * cursor moves to another row.
5388      *
5389      * @param columnName a <code>String</code> object that must match the
5390      *        SQL name of a column in this rowset, ignoring case
5391      * @param x the new column value
5392      * @param scale the number of digits to the right of the decimal point (for
5393      *              <code>DECIMAL</code> and <code>NUMERIC</code> types only)
5394      * @throws SQLException if (1) the given column name does not match the
5395      *            name of a column in this rowset, (2) the cursor is not on
5396      *            one of this rowset's rows or its insert row, or (3) this
5397      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5398      */
5399     public void updateObject(String columnName, Object x, int scale) throws SQLException {
5400         updateObject(getColIdxByName(columnName), x, scale);
5401     }
5402 
5403     /**
5404      * Sets the designated column in either the current row or the insert
5405      * row of this <code>CachedRowSetImpl</code> object with the given
5406      * <code>Object</code> value.
5407      * <P>
5408      * This method updates a column value in either the current row or
5409      * the insert row of this rowset, but it does not update the
5410      * database.  If the cursor is on a row in the rowset, the
5411      * method {@link #updateRow} must be called to update the database.
5412      * If the cursor is on the insert row, the method {@link #insertRow}
5413      * must be called, which will insert the new row into both this rowset
5414      * and the database. Both of these methods must be called before the
5415      * cursor moves to another row.
5416      *
5417      * @param columnName a <code>String</code> object that must match the
5418      *        SQL name of a column in this rowset, ignoring case
5419      * @param x the new column value
5420      * @throws SQLException if (1) the given column name does not match the
5421      *            name of a column in this rowset, (2) the cursor is not on
5422      *            one of this rowset's rows or its insert row, or (3) this
5423      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5424      */
5425     public void updateObject(String columnName, Object x) throws SQLException {
5426         updateObject(getColIdxByName(columnName), x);
5427     }
5428 
5429     /**
5430      * Inserts the contents of this <code>CachedRowSetImpl</code> object's insert
5431      * row into this rowset immediately following the current row.
5432      * If the current row is the
5433      * position after the last row or before the first row, the new row will
5434      * be inserted at the end of the rowset.  This method also notifies
5435      * listeners registered with this rowset that the row has changed.
5436      * <P>
5437      * The cursor must be on the insert row when this method is called.
5438      *
5439      * @throws SQLException if (1) the cursor is not on the insert row,
5440      *            (2) one or more of the non-nullable columns in the insert
5441      *            row has not been given a value, or (3) this rowset is
5442      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5443      */
5444     public void insertRow() throws SQLException {
5445         int pos;
5446 
5447         if (onInsertRow == false ||
5448             insertRow.isCompleteRow(RowSetMD) == false) {
5449                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.failedins").toString());
5450         }
5451         // Added the setting of parameters that are passed
5452         // to setXXX methods after an empty CRS Object is
5453         // created through RowSetMetaData object
5454         Object [] toInsert = getParams();
5455 
5456         for(int i = 0;i < toInsert.length; i++) {
5457           insertRow.setColumnObject(i+1,toInsert[i]);
5458         }
5459 
5460         Row insRow = new Row(RowSetMD.getColumnCount(),
5461         insertRow.getOrigRow());
5462         insRow.setInserted();
5463         /*
5464          * The new row is inserted into the RowSet
5465          * immediately following the current row.
5466          *
5467          * If we are afterlast then the rows are
5468          * inserted at the end.
5469          */
5470         if (currentRow >= numRows || currentRow < 0) {
5471             pos = numRows;
5472         } else {
5473             pos = currentRow;
5474         }
5475 
5476         rvh.add(pos, insRow);
5477         ++numRows;
5478         // notify the listeners that the row changed.
5479         notifyRowChanged();
5480     }
5481 
5482     /**
5483      * Marks the current row of this <code>CachedRowSetImpl</code> object as
5484      * updated and notifies listeners registered with this rowset that the
5485      * row has changed.
5486      * <P>
5487      * This method  cannot be called when the cursor is on the insert row, and
5488      * it should be called before the cursor moves to another row.  If it is
5489      * called after the cursor moves to another row, this method has no effect,
5490      * and the updates made before the cursor moved will be lost.
5491      *
5492      * @throws SQLException if the cursor is on the insert row or this
5493      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5494      */
5495     public void updateRow() throws SQLException {
5496         // make sure we aren't on the insert row
5497         if (onInsertRow == true) {
5498             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.updateins").toString());
5499         }
5500 
5501         ((Row)getCurrentRow()).setUpdated();
5502 
5503         // notify the listeners that the row changed.
5504         notifyRowChanged();
5505     }
5506 
5507     /**
5508      * Deletes the current row from this <code>CachedRowSetImpl</code> object and
5509      * notifies listeners registered with this rowset that a row has changed.
5510      * This method cannot be called when the cursor is on the insert row.
5511      * <P>
5512      * This method marks the current row as deleted, but it does not delete
5513      * the row from the underlying data source.  The method
5514      * <code>acceptChanges</code> must be called to delete the row in
5515      * the data source.
5516      *
5517      * @throws SQLException if (1) this method is called when the cursor
5518      *            is on the insert row, before the first row, or after the
5519      *            last row or (2) this rowset is
5520      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5521      */
5522     public void deleteRow() throws SQLException {
5523         // make sure the cursor is on a valid row
5524         checkCursor();
5525 
5526         ((Row)getCurrentRow()).setDeleted();
5527         ++numDeleted;
5528 
5529         // notify the listeners that the row changed.
5530         notifyRowChanged();
5531     }
5532 
5533     /**
5534      * Sets the current row with its original value and marks the row as
5535      * not updated, thus undoing any changes made to the row since the
5536      * last call to the methods <code>updateRow</code> or <code>deleteRow</code>.
5537      * This method should be called only when the cursor is on a row in
5538      * this rowset.
5539      *
5540      * @throws SQLException if the cursor is on the insert row, before the
5541      *            first row, or after the last row
5542      */
5543     public void refreshRow() throws SQLException {
5544         // make sure we are on a row
5545         checkCursor();
5546 
5547         // don't want this to happen...
5548         if (onInsertRow == true) {
5549             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
5550         }
5551 
5552         Row currentRow = (Row)getCurrentRow();
5553         // just undo any changes made to this row.
5554         currentRow.clearUpdated();
5555 
5556     }
5557 
5558     /**
5559      * Rolls back any updates made to the current row of this
5560      * <code>CachedRowSetImpl</code> object and notifies listeners that
5561      * a row has changed.  To have an effect, this method
5562      * must be called after an <code>updateXXX</code> method has been
5563      * called and before the method <code>updateRow</code> has been called.
5564      * If no updates have been made or the method <code>updateRow</code>
5565      * has already been called, this method has no effect.
5566      *
5567      * @throws SQLException if the cursor is on the insert row, before the
5568      *            first row, or after the last row
5569      */
5570     public void cancelRowUpdates() throws SQLException {
5571         // make sure we are on a row
5572         checkCursor();
5573 
5574         // don't want this to happen...
5575         if (onInsertRow == true) {
5576             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
5577         }
5578 
5579         Row currentRow = (Row)getCurrentRow();
5580         if (currentRow.getUpdated() == true) {
5581             currentRow.clearUpdated();
5582             notifyRowChanged();
5583         }
5584     }
5585 
5586     /**
5587      * Moves the cursor for this <code>CachedRowSetImpl</code> object
5588      * to the insert row.  The current row in the rowset is remembered
5589      * while the cursor is on the insert row.
5590      * <P>
5591      * The insert row is a special row associated with an updatable
5592      * rowset.  It is essentially a buffer where a new row may
5593      * be constructed by calling the appropriate <code>updateXXX</code>
5594      * methods to assign a value to each column in the row.  A complete
5595      * row must be constructed; that is, every column that is not nullable
5596      * must be assigned a value.  In order for the new row to become part
5597      * of this rowset, the method <code>insertRow</code> must be called
5598      * before the cursor is moved back to the rowset.
5599      * <P>
5600      * Only certain methods may be invoked while the cursor is on the insert
5601      * row; many methods throw an exception if they are called while the
5602      * cursor is there.  In addition to the <code>updateXXX</code>
5603      * and <code>insertRow</code> methods, only the <code>getXXX</code> methods
5604      * may be called when the cursor is on the insert row.  A <code>getXXX</code>
5605      * method should be called on a column only after an <code>updateXXX</code>
5606      * method has been called on that column; otherwise, the value returned is
5607      * undetermined.
5608      *
5609      * @throws SQLException if this <code>CachedRowSetImpl</code> object is
5610      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5611      */
5612     public void moveToInsertRow() throws SQLException {
5613         if (getConcurrency() == ResultSet.CONCUR_READ_ONLY) {
5614             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins").toString());
5615         }
5616         if (insertRow == null) {
5617             if (RowSetMD == null)
5618                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins1").toString());
5619             int numCols = RowSetMD.getColumnCount();
5620             if (numCols > 0) {
5621                 insertRow = new InsertRow(numCols);
5622             } else {
5623                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins2").toString());
5624             }
5625         }
5626         onInsertRow = true;
5627         // %%% setCurrentRow called in BaseRow
5628 
5629         currentRow = cursorPos;
5630         cursorPos = -1;
5631 
5632         insertRow.initInsertRow();
5633     }
5634 
5635     /**
5636      * Moves the cursor for this <code>CachedRowSetImpl</code> object to
5637      * the current row.  The current row is the row the cursor was on
5638      * when the method <code>moveToInsertRow</code> was called.
5639      * <P>
5640      * Calling this method has no effect unless it is called while the
5641      * cursor is on the insert row.
5642      *
5643      * @throws SQLException if an error occurs
5644      */
5645     public void moveToCurrentRow() throws SQLException {
5646         if (onInsertRow == false) {
5647             return;
5648         } else {
5649             cursorPos = currentRow;
5650             onInsertRow = false;
5651         }
5652     }
5653 
5654     /**
5655      * Returns <code>null</code>.
5656      *
5657      * @return <code>null</code>
5658      * @throws SQLException if an error occurs
5659      */
5660     public Statement getStatement() throws SQLException {
5661         return null;
5662     }
5663 
5664     /**
5665      * Retrieves the value of the designated column in this
5666      * <code>CachedRowSetImpl</code> object as an <code>Object</code> in
5667      * the Java programming language, using the given
5668      * <code>java.util.Map</code> object to custom map the value if
5669      * appropriate.
5670      *
5671      * @param columnIndex the first column is <code>1</code>, the second
5672      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5673      *        and equal to or less than the number of columns in this rowset
5674      * @param map a <code>java.util.Map</code> object showing the mapping
5675      *            from SQL type names to classes in the Java programming
5676      *            language
5677      * @return an <code>Object</code> representing the SQL value
5678      * @throws SQLException if the given column index is out of bounds or
5679      *            the cursor is not on one of this rowset's rows or its
5680      *            insert row
5681      */
5682      public Object getObject(int columnIndex,
5683                              java.util.Map<String,Class<?>> map)
5684          throws SQLException
5685      {
5686         Object value;
5687 
5688         // sanity check.
5689         checkIndex(columnIndex);
5690         // make sure the cursor is on a valid row
5691         checkCursor();
5692 
5693         setLastValueNull(false);
5694         value = getCurrentRow().getColumnObject(columnIndex);
5695 
5696         // check for SQL NULL
5697         if (value == null) {
5698             setLastValueNull(true);
5699             return null;
5700         }
5701         if (value instanceof Struct) {
5702             Struct s = (Struct)value;
5703 
5704             // look up the class in the map
5705             Class<?> c = map.get(s.getSQLTypeName());
5706             if (c != null) {
5707                 // create new instance of the class
5708                 SQLData obj = null;
5709                 try {
5710                     obj = (SQLData) ReflectUtil.newInstance(c);
5711                 } catch(Exception ex) {
5712                     throw new SQLException("Unable to Instantiate: ", ex);
5713                 }
5714                 // get the attributes from the struct
5715                 Object attribs[] = s.getAttributes(map);
5716                 // create the SQLInput "stream"
5717                 SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
5718                 // read the values...
5719                 obj.readSQL(sqlInput, s.getSQLTypeName());
5720                 return (Object)obj;
5721             }
5722         }
5723         return value;
5724     }
5725 
5726     /**
5727      * Retrieves the value of the designated column in this
5728      * <code>CachedRowSetImpl</code> object as a <code>Ref</code> object
5729      * in the Java programming language.
5730      *
5731      * @param columnIndex the first column is <code>1</code>, the second
5732      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5733      *        and equal to or less than the number of columns in this rowset
5734      * @return a <code>Ref</code> object representing an SQL<code> REF</code> value
5735      * @throws SQLException if (1) the given column index is out of bounds,
5736      *            (2) the cursor is not on one of this rowset's rows or its
5737      *            insert row, or (3) the designated column does not store an
5738      *            SQL <code>REF</code> value
5739      * @see #getRef(String)
5740      */
5741     public Ref getRef(int columnIndex) throws SQLException {
5742         Ref value;
5743 
5744         // sanity check.
5745         checkIndex(columnIndex);
5746         // make sure the cursor is on a valid row
5747         checkCursor();
5748 
5749         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.REF) {
5750             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5751         }
5752 
5753         setLastValueNull(false);
5754         value = (Ref)(getCurrentRow().getColumnObject(columnIndex));
5755 
5756         // check for SQL NULL
5757         if (value == null) {
5758             setLastValueNull(true);
5759             return null;
5760         }
5761 
5762         return value;
5763     }
5764 
5765     /**
5766      * Retrieves the value of the designated column in this
5767      * <code>CachedRowSetImpl</code> object as a <code>Blob</code> object
5768      * in the Java programming language.
5769      *
5770      * @param columnIndex the first column is <code>1</code>, the second
5771      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5772      *        and equal to or less than the number of columns in this rowset
5773      * @return a <code>Blob</code> object representing an SQL <code>BLOB</code> value
5774      * @throws SQLException if (1) the given column index is out of bounds,
5775      *            (2) the cursor is not on one of this rowset's rows or its
5776      *            insert row, or (3) the designated column does not store an
5777      *            SQL <code>BLOB</code> value
5778      * @see #getBlob(String)
5779      */
5780     public Blob getBlob(int columnIndex) throws SQLException {
5781         Blob value;
5782 
5783         // sanity check.
5784         checkIndex(columnIndex);
5785         // make sure the cursor is on a valid row
5786         checkCursor();
5787 
5788         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.BLOB) {
5789             System.out.println(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.type").toString(), RowSetMD.getColumnType(columnIndex)));
5790             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5791         }
5792 
5793         setLastValueNull(false);
5794         value = (Blob)(getCurrentRow().getColumnObject(columnIndex));
5795 
5796         // check for SQL NULL
5797         if (value == null) {
5798             setLastValueNull(true);
5799             return null;
5800         }
5801 
5802         return value;
5803     }
5804 
5805     /**
5806      * Retrieves the value of the designated column in this
5807      * <code>CachedRowSetImpl</code> object as a <code>Clob</code> object
5808      * in the Java programming language.
5809      *
5810      * @param columnIndex the first column is <code>1</code>, the second
5811      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5812      *        and equal to or less than the number of columns in this rowset
5813      * @return a <code>Clob</code> object representing an SQL <code>CLOB</code> value
5814      * @throws SQLException if (1) the given column index is out of bounds,
5815      *            (2) the cursor is not on one of this rowset's rows or its
5816      *            insert row, or (3) the designated column does not store an
5817      *            SQL <code>CLOB</code> value
5818      * @see #getClob(String)
5819      */
5820     public Clob getClob(int columnIndex) throws SQLException {
5821         Clob value;
5822 
5823         // sanity check.
5824         checkIndex(columnIndex);
5825         // make sure the cursor is on a valid row
5826         checkCursor();
5827 
5828         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.CLOB) {
5829             System.out.println(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.type").toString(), RowSetMD.getColumnType(columnIndex)));
5830             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5831         }
5832 
5833         setLastValueNull(false);
5834         value = (Clob)(getCurrentRow().getColumnObject(columnIndex));
5835 
5836         // check for SQL NULL
5837         if (value == null) {
5838             setLastValueNull(true);
5839             return null;
5840         }
5841 
5842         return value;
5843     }
5844 
5845     /**
5846      * Retrieves the value of the designated column in this
5847      * <code>CachedRowSetImpl</code> object as an <code>Array</code> object
5848      * in the Java programming language.
5849      *
5850      * @param columnIndex the first column is <code>1</code>, the second
5851      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5852      *        and equal to or less than the number of columns in this rowset
5853      * @return an <code>Array</code> object representing an SQL
5854      *         <code>ARRAY</code> value
5855      * @throws SQLException if (1) the given column index is out of bounds,
5856      *            (2) the cursor is not on one of this rowset's rows or its
5857      *            insert row, or (3) the designated column does not store an
5858      *            SQL <code>ARRAY</code> value
5859      * @see #getArray(String)
5860      */
5861     public Array getArray(int columnIndex) throws SQLException {
5862         java.sql.Array value;
5863 
5864         // sanity check.
5865         checkIndex(columnIndex);
5866         // make sure the cursor is on a valid row
5867         checkCursor();
5868 
5869         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.ARRAY) {
5870             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5871         }
5872 
5873         setLastValueNull(false);
5874         value = (java.sql.Array)(getCurrentRow().getColumnObject(columnIndex));
5875 
5876         // check for SQL NULL
5877         if (value == null) {
5878             setLastValueNull(true);
5879             return null;
5880         }
5881 
5882         return value;
5883     }
5884 
5885     /**
5886      * Retrieves the value of the designated column in this
5887      * <code>CachedRowSetImpl</code> object as an <code>Object</code> in
5888      * the Java programming language, using the given
5889      * <code>java.util.Map</code> object to custom map the value if
5890      * appropriate.
5891      *
5892      * @param columnName a <code>String</code> object that must match the
5893      *        SQL name of a column in this rowset, ignoring case
5894      * @param map a <code>java.util.Map</code> object showing the mapping
5895      *        from SQL type names to classes in the Java programming
5896      *        language
5897      * @return an <code>Object</code> representing the SQL value
5898      * @throws SQLException if the given column name is not the name of
5899      *         a column in this rowset or the cursor is not on one of
5900      *         this rowset's rows or its insert row
5901      */
5902     public Object getObject(String columnName,
5903                             java.util.Map<String,Class<?>> map)
5904     throws SQLException {
5905         return getObject(getColIdxByName(columnName), map);
5906     }
5907 
5908     /**
5909      * Retrieves the value of the designated column in this
5910      * <code>CachedRowSetImpl</code> object as a <code>Ref</code> object
5911      * in the Java programming language.
5912      *
5913      * @param colName a <code>String</code> object that must match the
5914      *        SQL name of a column in this rowset, ignoring case
5915      * @return a <code>Ref</code> object representing an SQL<code> REF</code> value
5916      * @throws SQLException  if (1) the given column name is not the name of
5917      *            a column in this rowset, (2) the cursor is not on one of
5918      *            this rowset's rows or its insert row, or (3) the column value
5919      *            is not an SQL <code>REF</code> value
5920      * @see #getRef(int)
5921      */
5922     public Ref getRef(String colName) throws SQLException {
5923         return getRef(getColIdxByName(colName));
5924     }
5925 
5926     /**
5927      * Retrieves the value of the designated column in this
5928      * <code>CachedRowSetImpl</code> object as a <code>Blob</code> object
5929      * in the Java programming language.
5930      *
5931      * @param colName a <code>String</code> object that must match the
5932      *        SQL name of a column in this rowset, ignoring case
5933      * @return a <code>Blob</code> object representing an SQL <code>BLOB</code> value
5934      * @throws SQLException if (1) the given column name is not the name of
5935      *            a column in this rowset, (2) the cursor is not on one of
5936      *            this rowset's rows or its insert row, or (3) the designated
5937      *            column does not store an SQL <code>BLOB</code> value
5938      * @see #getBlob(int)
5939      */
5940     public Blob getBlob(String colName) throws SQLException {
5941         return getBlob(getColIdxByName(colName));
5942     }
5943 
5944     /**
5945      * Retrieves the value of the designated column in this
5946      * <code>CachedRowSetImpl</code> object as a <code>Clob</code> object
5947      * in the Java programming language.
5948      *
5949      * @param colName a <code>String</code> object that must match the
5950      *        SQL name of a column in this rowset, ignoring case
5951      * @return a <code>Clob</code> object representing an SQL
5952      *         <code>CLOB</code> value
5953      * @throws SQLException if (1) the given column name is not the name of
5954      *            a column in this rowset, (2) the cursor is not on one of
5955      *            this rowset's rows or its insert row, or (3) the designated
5956      *            column does not store an SQL <code>CLOB</code> value
5957      * @see #getClob(int)
5958      */
5959     public Clob getClob(String colName) throws SQLException {
5960         return getClob(getColIdxByName(colName));
5961     }
5962 
5963     /**
5964      * Retrieves the value of the designated column in this
5965      * <code>CachedRowSetImpl</code> object as an <code>Array</code> object
5966      * in the Java programming langugage.
5967      *
5968      * @param colName a <code>String</code> object that must match the
5969      *        SQL name of a column in this rowset, ignoring case
5970      * @return an <code>Array</code> object representing an SQL
5971      *         <code>ARRAY</code> value
5972      * @throws SQLException if (1) the given column name is not the name of
5973      *            a column in this rowset, (2) the cursor is not on one of
5974      *            this rowset's rows or its insert row, or (3) the designated
5975      *            column does not store an SQL <code>ARRAY</code> value
5976      * @see #getArray(int)
5977      */
5978     public Array getArray(String colName) throws SQLException {
5979         return getArray(getColIdxByName(colName));
5980     }
5981 
5982     /**
5983      * Retrieves the value of the designated column in the current row
5984      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Date</code>
5985      * object, using the given <code>Calendar</code> object to construct an
5986      * appropriate millisecond value for the date.
5987      *
5988      * @param columnIndex the first column is <code>1</code>, the second
5989      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5990      *        and equal to or less than the number of columns in the rowset
5991      * @param cal the <code>java.util.Calendar</code> object to use in
5992      *            constructing the date
5993      * @return the column value; if the value is SQL <code>NULL</code>,
5994      *         the result is <code>null</code>
5995      * @throws SQLException if (1) the given column name is not the name of
5996      *            a column in this rowset, (2) the cursor is not on one of
5997      *            this rowset's rows or its insert row, or (3) the designated
5998      *            column does not store an SQL <code>DATE</code> or
5999      *            <code>TIMESTAMP</code> value
6000      */
6001     public java.sql.Date getDate(int columnIndex, Calendar cal) throws SQLException {
6002         Object value;
6003 
6004         // sanity check.
6005         checkIndex(columnIndex);
6006         // make sure the cursor is on a valid row
6007         checkCursor();
6008 
6009         setLastValueNull(false);
6010         value = getCurrentRow().getColumnObject(columnIndex);
6011 
6012         // check for SQL NULL
6013         if (value == null) {
6014             setLastValueNull(true);
6015             return null;
6016         }
6017 
6018         value = convertTemporal(value,
6019         RowSetMD.getColumnType(columnIndex),
6020         java.sql.Types.DATE);
6021 
6022         // create a default calendar
6023         Calendar defaultCal = Calendar.getInstance();
6024         // set this Calendar to the time we have
6025         defaultCal.setTime((java.util.Date)value);
6026 
6027         /*
6028          * Now we can pull the pieces of the date out
6029          * of the default calendar and put them into
6030          * the user provided calendar
6031          */
6032         cal.set(Calendar.YEAR, defaultCal.get(Calendar.YEAR));
6033         cal.set(Calendar.MONTH, defaultCal.get(Calendar.MONTH));
6034         cal.set(Calendar.DAY_OF_MONTH, defaultCal.get(Calendar.DAY_OF_MONTH));
6035 
6036         /*
6037          * This looks a little odd but it is correct -
6038          * Calendar.getTime() returns a Date...
6039          */
6040         return new java.sql.Date(cal.getTime().getTime());
6041     }
6042 
6043     /**
6044      * Retrieves the value of the designated column in the current row
6045      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Date</code>
6046      * object, using the given <code>Calendar</code> object to construct an
6047      * appropriate millisecond value for the date.
6048      *
6049      * @param columnName a <code>String</code> object that must match the
6050      *        SQL name of a column in this rowset, ignoring case
6051      * @param cal the <code>java.util.Calendar</code> object to use in
6052      *            constructing the date
6053      * @return the column value; if the value is SQL <code>NULL</code>,
6054      *         the result is <code>null</code>
6055      * @throws SQLException if (1) the given column name is not the name of
6056      *            a column in this rowset, (2) the cursor is not on one of
6057      *            this rowset's rows or its insert row, or (3) the designated
6058      *            column does not store an SQL <code>DATE</code> or
6059      *            <code>TIMESTAMP</code> value
6060      */
6061     public java.sql.Date getDate(String columnName, Calendar cal) throws SQLException {
6062         return getDate(getColIdxByName(columnName), cal);
6063     }
6064 
6065     /**
6066      * Retrieves the value of the designated column in the current row
6067      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Time</code>
6068      * object, using the given <code>Calendar</code> object to construct an
6069      * appropriate millisecond value for the date.
6070      *
6071      * @param columnIndex the first column is <code>1</code>, the second
6072      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6073      *        and equal to or less than the number of columns in the rowset
6074      * @param cal the <code>java.util.Calendar</code> object to use in
6075      *            constructing the date
6076      * @return the column value; if the value is SQL <code>NULL</code>,
6077      *         the result is <code>null</code>
6078      * @throws SQLException if (1) the given column name is not the name of
6079      *            a column in this rowset, (2) the cursor is not on one of
6080      *            this rowset's rows or its insert row, or (3) the designated
6081      *            column does not store an SQL <code>TIME</code> or
6082      *            <code>TIMESTAMP</code> value
6083      */
6084     public java.sql.Time getTime(int columnIndex, Calendar cal) throws SQLException {
6085         Object value;
6086 
6087         // sanity check.
6088         checkIndex(columnIndex);
6089         // make sure the cursor is on a valid row
6090         checkCursor();
6091 
6092         setLastValueNull(false);
6093         value = getCurrentRow().getColumnObject(columnIndex);
6094 
6095         // check for SQL NULL
6096         if (value == null) {
6097             setLastValueNull(true);
6098             return null;
6099         }
6100 
6101         value = convertTemporal(value,
6102         RowSetMD.getColumnType(columnIndex),
6103         java.sql.Types.TIME);
6104 
6105         // create a default calendar
6106         Calendar defaultCal = Calendar.getInstance();
6107         // set the time in the default calendar
6108         defaultCal.setTime((java.util.Date)value);
6109 
6110         /*
6111          * Now we can pull the pieces of the date out
6112          * of the default calendar and put them into
6113          * the user provided calendar
6114          */
6115         cal.set(Calendar.HOUR_OF_DAY, defaultCal.get(Calendar.HOUR_OF_DAY));
6116         cal.set(Calendar.MINUTE, defaultCal.get(Calendar.MINUTE));
6117         cal.set(Calendar.SECOND, defaultCal.get(Calendar.SECOND));
6118 
6119         return new java.sql.Time(cal.getTime().getTime());
6120     }
6121 
6122     /**
6123      * Retrieves the value of the designated column in the current row
6124      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Time</code>
6125      * object, using the given <code>Calendar</code> object to construct an
6126      * appropriate millisecond value for the date.
6127      *
6128      * @param columnName a <code>String</code> object that must match the
6129      *        SQL name of a column in this rowset, ignoring case
6130      * @param cal the <code>java.util.Calendar</code> object to use in
6131      *            constructing the date
6132      * @return the column value; if the value is SQL <code>NULL</code>,
6133      *         the result is <code>null</code>
6134      * @throws SQLException if (1) the given column name is not the name of
6135      *            a column in this rowset, (2) the cursor is not on one of
6136      *            this rowset's rows or its insert row, or (3) the designated
6137      *            column does not store an SQL <code>TIME</code> or
6138      *            <code>TIMESTAMP</code> value
6139      */
6140     public java.sql.Time getTime(String columnName, Calendar cal) throws SQLException {
6141         return getTime(getColIdxByName(columnName), cal);
6142     }
6143 
6144     /**
6145      * Retrieves the value of the designated column in the current row
6146      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Timestamp</code>
6147      * object, using the given <code>Calendar</code> object to construct an
6148      * appropriate millisecond value for the date.
6149      *
6150      * @param columnIndex the first column is <code>1</code>, the second
6151      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6152      *        and equal to or less than the number of columns in the rowset
6153      * @param cal the <code>java.util.Calendar</code> object to use in
6154      *            constructing the date
6155      * @return the column value; if the value is SQL <code>NULL</code>,
6156      *         the result is <code>null</code>
6157      * @throws SQLException if (1) the given column name is not the name of
6158      *            a column in this rowset, (2) the cursor is not on one of
6159      *            this rowset's rows or its insert row, or (3) the designated
6160      *            column does not store an SQL <code>TIME</code> or
6161      *            <code>TIMESTAMP</code> value
6162      */
6163     public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
6164         Object value;
6165 
6166         // sanity check.
6167         checkIndex(columnIndex);
6168         // make sure the cursor is on a valid row
6169         checkCursor();
6170 
6171         setLastValueNull(false);
6172         value = getCurrentRow().getColumnObject(columnIndex);
6173 
6174         // check for SQL NULL
6175         if (value == null) {
6176             setLastValueNull(true);
6177             return null;
6178         }
6179 
6180         value = convertTemporal(value,
6181         RowSetMD.getColumnType(columnIndex),
6182         java.sql.Types.TIMESTAMP);
6183 
6184         // create a default calendar
6185         Calendar defaultCal = Calendar.getInstance();
6186         // set the time in the default calendar
6187         defaultCal.setTime((java.util.Date)value);
6188 
6189         /*
6190          * Now we can pull the pieces of the date out
6191          * of the default calendar and put them into
6192          * the user provided calendar
6193          */
6194         cal.set(Calendar.YEAR, defaultCal.get(Calendar.YEAR));
6195         cal.set(Calendar.MONTH, defaultCal.get(Calendar.MONTH));
6196         cal.set(Calendar.DAY_OF_MONTH, defaultCal.get(Calendar.DAY_OF_MONTH));
6197         cal.set(Calendar.HOUR_OF_DAY, defaultCal.get(Calendar.HOUR_OF_DAY));
6198         cal.set(Calendar.MINUTE, defaultCal.get(Calendar.MINUTE));
6199         cal.set(Calendar.SECOND, defaultCal.get(Calendar.SECOND));
6200 
6201         return new java.sql.Timestamp(cal.getTime().getTime());
6202     }
6203 
6204     /**
6205      * Retrieves the value of the designated column in the current row
6206      * of this <code>CachedRowSetImpl</code> object as a
6207      * <code>java.sql.Timestamp</code> object, using the given
6208      * <code>Calendar</code> object to construct an appropriate
6209      * millisecond value for the date.
6210      *
6211      * @param columnName a <code>String</code> object that must match the
6212      *        SQL name of a column in this rowset, ignoring case
6213      * @param cal the <code>java.util.Calendar</code> object to use in
6214      *            constructing the date
6215      * @return the column value; if the value is SQL <code>NULL</code>,
6216      *         the result is <code>null</code>
6217      * @throws SQLException if (1) the given column name is not the name of
6218      *            a column in this rowset, (2) the cursor is not on one of
6219      *            this rowset's rows or its insert row, or (3) the designated
6220      *            column does not store an SQL <code>DATE</code>,
6221      *            <code>TIME</code>, or <code>TIMESTAMP</code> value
6222      */
6223     public java.sql.Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException {
6224         return getTimestamp(getColIdxByName(columnName), cal);
6225     }
6226 
6227     /*
6228      * RowSetInternal Interface
6229      */
6230 
6231     /**
6232      * Retrieves the <code>Connection</code> object passed to this
6233      * <code>CachedRowSetImpl</code> object.  This connection may be
6234      * used to populate this rowset with data or to write data back
6235      * to its underlying data source.
6236      *
6237      * @return the <code>Connection</code> object passed to this rowset;
6238      *         may be <code>null</code> if there is no connection
6239      * @throws SQLException if an error occurs
6240      */
6241     public Connection getConnection() throws SQLException{
6242         return conn;
6243     }
6244 
6245     /**
6246      * Sets the metadata for this <code>CachedRowSetImpl</code> object
6247      * with the given <code>RowSetMetaData</code> object.
6248      *
6249      * @param md a <code>RowSetMetaData</code> object instance containing
6250      *            metadata about the columsn in the rowset
6251      * @throws SQLException if invalid meta data is supplied to the
6252      *            rowset
6253      */
6254     public void setMetaData(RowSetMetaData md) throws SQLException {
6255         RowSetMD =(RowSetMetaDataImpl) md;
6256     }
6257 
6258     /**
6259      * Returns a result set containing the original value of the rowset. The
6260      * original value is the state of the <code>CachedRowSetImpl</code> after the
6261      * last population or synchronization (whichever occurred most recently) with
6262      * the data source.
6263      * <p>
6264      * The cursor is positioned before the first row in the result set.
6265      * Only rows contained in the result set returned by <code>getOriginal()</code>
6266      * are said to have an original value.
6267      *
6268      * @return the original result set of the rowset
6269      * @throws SQLException if an error occurs produce the
6270      *           <code>ResultSet</code> object
6271      */
6272     public ResultSet getOriginal() throws SQLException {
6273         CachedRowSetImpl crs = new CachedRowSetImpl();
6274         crs.RowSetMD = RowSetMD;
6275         crs.numRows = numRows;
6276         crs.cursorPos = 0;
6277 
6278         // make sure we don't get someone playing with these
6279         // %%% is this now necessary ???
6280         //crs.setReader(null);
6281         //crs.setWriter(null);
6282         int colCount = RowSetMD.getColumnCount();
6283         Row orig;
6284 
6285         for (Iterator<?> i = rvh.iterator(); i.hasNext();) {
6286             orig = new Row(colCount, ((Row)i.next()).getOrigRow());
6287             crs.rvh.add(orig);
6288         }
6289         return (ResultSet)crs;
6290     }
6291 
6292     /**
6293      * Returns a result set containing the original value of the current
6294      * row only.
6295      * The original value is the state of the <code>CachedRowSetImpl</code> after
6296      * the last population or synchronization (whichever occurred most recently)
6297      * with the data source.
6298      *
6299      * @return the original result set of the row
6300      * @throws SQLException if there is no current row
6301      * @see #setOriginalRow
6302      */
6303     public ResultSet getOriginalRow() throws SQLException {
6304         CachedRowSetImpl crs = new CachedRowSetImpl();
6305         crs.RowSetMD = RowSetMD;
6306         crs.numRows = 1;
6307         crs.cursorPos = 0;
6308         crs.setTypeMap(this.getTypeMap());
6309 
6310         // make sure we don't get someone playing with these
6311         // %%% is this now necessary ???
6312         //crs.setReader(null);
6313         //crs.setWriter(null);
6314 
6315         Row orig = new Row(RowSetMD.getColumnCount(),
6316         getCurrentRow().getOrigRow());
6317 
6318         crs.rvh.add(orig);
6319 
6320         return (ResultSet)crs;
6321 
6322     }
6323 
6324     /**
6325      * Marks the current row in this rowset as being an original row.
6326      *
6327      * @throws SQLException if there is no current row
6328      * @see #getOriginalRow
6329      */
6330     public void setOriginalRow() throws SQLException {
6331         if (onInsertRow == true) {
6332             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
6333         }
6334 
6335         Row row = (Row)getCurrentRow();
6336         makeRowOriginal(row);
6337 
6338         // this can happen if deleted rows are being shown
6339         if (row.getDeleted() == true) {
6340             removeCurrentRow();
6341         }
6342     }
6343 
6344     /**
6345      * Makes the given row of this rowset the original row by clearing any
6346      * settings that mark the row as having been inserted, deleted, or updated.
6347      * This method is called internally by the methods
6348      * <code>setOriginalRow</code>
6349      * and <code>setOriginal</code>.
6350      *
6351      * @param row the row to be made the original row
6352      */
6353     private void makeRowOriginal(Row row) {
6354         if (row.getInserted() == true) {
6355             row.clearInserted();
6356         }
6357 
6358         if (row.getUpdated() == true) {
6359             row.moveCurrentToOrig();
6360         }
6361     }
6362 
6363     /**
6364      * Marks all rows in this rowset as being original rows. Any updates
6365      * made to the rows become the original values for the rowset.
6366      * Calls to the method <code>setOriginal</code> connot be reversed.
6367      *
6368      * @throws SQLException if an error occurs
6369      */
6370     public void setOriginal() throws SQLException {
6371         for (Iterator<?> i = rvh.iterator(); i.hasNext();) {
6372             Row row = (Row)i.next();
6373             makeRowOriginal(row);
6374             // remove deleted rows from the collection.
6375             if (row.getDeleted() == true) {
6376                 i.remove();
6377                 --numRows;
6378             }
6379         }
6380         numDeleted = 0;
6381 
6382         // notify any listeners that the rowset has changed
6383         notifyRowSetChanged();
6384     }
6385 
6386     /**
6387      * Returns an identifier for the object (table) that was used to create this
6388      * rowset.
6389      *
6390      * @return a <code>String</code> object that identifies the table from
6391      *         which this <code>CachedRowSetImpl</code> object was derived
6392      * @throws SQLException if an error occurs
6393      */
6394     public String getTableName() throws SQLException {
6395         return tableName;
6396     }
6397 
6398     /**
6399      * Sets the identifier for the table from which this rowset was derived
6400      * to the given table name.
6401      *
6402      * @param tabName a <code>String</code> object that identifies the
6403      *          table from which this <code>CachedRowSetImpl</code> object
6404      *          was derived
6405      * @throws SQLException if an error occurs
6406      */
6407     public void setTableName(String tabName) throws SQLException {
6408         if (tabName == null)
6409             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.tablename").toString());
6410         else
6411             tableName = tabName;
6412     }
6413 
6414     /**
6415      * Returns the columns that make a key to uniquely identify a
6416      * row in this <code>CachedRowSetImpl</code> object.
6417      *
6418      * @return an array of column numbers that constitutes a primary
6419      *           key for this rowset. This array should be empty
6420      *           if no column is representitive of a primary key
6421      * @throws SQLException if the rowset is empty or no columns
6422      *           are designated as primary keys
6423      * @see #setKeyColumns
6424      */
6425     public int[] getKeyColumns() throws SQLException {
6426         int[]keyColumns  = this.keyCols;
6427         return (keyColumns == null) ? null : Arrays.copyOf(keyColumns, keyColumns.length);
6428     }
6429 
6430 
6431     /**
6432      * Sets this <code>CachedRowSetImpl</code> object's
6433      * <code>keyCols</code> field with the given array of column
6434      * numbers, which forms a key for uniquely identifying a row
6435      * in this rowset.
6436      *
6437      * @param keys an array of <code>int</code> indicating the
6438      *        columns that form a primary key for this
6439      *        <code>CachedRowSetImpl</code> object; every
6440      *        element in the array must be greater than
6441      *        <code>0</code> and less than or equal to the number
6442      *        of columns in this rowset
6443      * @throws SQLException if any of the numbers in the
6444      *            given array is not valid for this rowset
6445      * @see #getKeyColumns
6446      */
6447     public void setKeyColumns(int [] keys) throws SQLException {
6448         int numCols = 0;
6449         if (RowSetMD != null) {
6450             numCols = RowSetMD.getColumnCount();
6451             if (keys.length > numCols)
6452                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.keycols").toString());
6453         }
6454         keyCols = new int[keys.length];
6455         for (int i = 0; i < keys.length; i++) {
6456             if (RowSetMD != null && (keys[i] <= 0 ||
6457             keys[i] > numCols)) {
6458                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcol").toString() +
6459                 keys[i]);
6460             }
6461             keyCols[i] = keys[i];
6462         }
6463     }
6464 
6465     /**
6466      * Sets the designated column in either the current row or the insert
6467      * row of this <code>CachedRowSetImpl</code> object with the given
6468      * <code>Ref</code> value.
6469      *
6470      * This method updates a column value in either the current row or
6471      * the insert row of this rowset, but it does not update the
6472      * database.  If the cursor is on a row in the rowset, the
6473      * method {@link #updateRow} must be called to update the database.
6474      * If the cursor is on the insert row, the method {@link #insertRow}
6475      * must be called, which will insert the new row into both this rowset
6476      * and the database. Both of these methods must be called before the
6477      * cursor moves to another row.
6478      *
6479      * @param columnIndex the first column is <code>1</code>, the second
6480      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6481      *        and equal to or less than the number of columns in this rowset
6482      * @param ref the new column <code>java.sql.Ref</code> value
6483      * @throws SQLException if (1) the given column index is out of bounds,
6484      *        (2) the cursor is not on one of this rowset's rows or its
6485      *        insert row, or (3) this rowset is
6486      *        <code>ResultSet.CONCUR_READ_ONLY</code>
6487      */
6488     public void updateRef(int columnIndex, java.sql.Ref ref) throws SQLException {
6489         // sanity check.
6490         checkIndex(columnIndex);
6491         // make sure the cursor is on a valid row
6492         checkCursor();
6493 
6494         // SerialClob will help in getting the byte array and storing it.
6495         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6496         // or through RowSetMetaData.locatorsUpdatorCopy()
6497         getCurrentRow().setColumnObject(columnIndex, new SerialRef(ref));
6498     }
6499 
6500     /**
6501      * Sets the designated column in either the current row or the insert
6502      * row of this <code>CachedRowSetImpl</code> object with the given
6503      * <code>double</code> value.
6504      *
6505      * This method updates a column value in either the current row or
6506      * the insert row of this rowset, but it does not update the
6507      * database.  If the cursor is on a row in the rowset, the
6508      * method {@link #updateRow} must be called to update the database.
6509      * If the cursor is on the insert row, the method {@link #insertRow}
6510      * must be called, which will insert the new row into both this rowset
6511      * and the database. Both of these methods must be called before the
6512      * cursor moves to another row.
6513      *
6514      * @param columnName a <code>String</code> object that must match the
6515      *        SQL name of a column in this rowset, ignoring case
6516      * @param ref the new column <code>java.sql.Ref</code> value
6517      * @throws SQLException if (1) the given column name does not match the
6518      *        name of a column in this rowset, (2) the cursor is not on
6519      *        one of this rowset's rows or its insert row, or (3) this
6520      *        rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6521      */
6522     public void updateRef(String columnName, java.sql.Ref ref) throws SQLException {
6523         updateRef(getColIdxByName(columnName), ref);
6524     }
6525 
6526     /**
6527      * Sets the designated column in either the current row or the insert
6528      * row of this <code>CachedRowSetImpl</code> object with the given
6529      * <code>double</code> value.
6530      *
6531      * This method updates a column value in either the current row or
6532      * the insert row of this rowset, but it does not update the
6533      * database.  If the cursor is on a row in the rowset, the
6534      * method {@link #updateRow} must be called to update the database.
6535      * If the cursor is on the insert row, the method {@link #insertRow}
6536      * must be called, which will insert the new row into both this rowset
6537      * and the database. Both of these methods must be called before the
6538      * cursor moves to another row.
6539      *
6540      * @param columnIndex the first column is <code>1</code>, the second
6541      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6542      *        and equal to or less than the number of columns in this rowset
6543      * @param c the new column <code>Clob</code> value
6544      * @throws SQLException if (1) the given column index is out of bounds,
6545      *        (2) the cursor is not on one of this rowset's rows or its
6546      *        insert row, or (3) this rowset is
6547      *        <code>ResultSet.CONCUR_READ_ONLY</code>
6548      */
6549     public void updateClob(int columnIndex, Clob c) throws SQLException {
6550         // sanity check.
6551         checkIndex(columnIndex);
6552         // make sure the cursor is on a valid row
6553         checkCursor();
6554 
6555         // SerialClob will help in getting the byte array and storing it.
6556         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6557         // or through RowSetMetaData.locatorsUpdatorCopy()
6558 
6559         if(dbmslocatorsUpdateCopy){
6560            getCurrentRow().setColumnObject(columnIndex, new SerialClob(c));
6561         }
6562         else{
6563            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.opnotsupp").toString());
6564         }
6565     }
6566 
6567     /**
6568      * Sets the designated column in either the current row or the insert
6569      * row of this <code>CachedRowSetImpl</code> object with the given
6570      * <code>double</code> value.
6571      *
6572      * This method updates a column value in either the current row or
6573      * the insert row of this rowset, but it does not update the
6574      * database.  If the cursor is on a row in the rowset, the
6575      * method {@link #updateRow} must be called to update the database.
6576      * If the cursor is on the insert row, the method {@link #insertRow}
6577      * must be called, which will insert the new row into both this rowset
6578      * and the database. Both of these methods must be called before the
6579      * cursor moves to another row.
6580      *
6581      * @param columnName a <code>String</code> object that must match the
6582      *        SQL name of a column in this rowset, ignoring case
6583      * @param c the new column <code>Clob</code> value
6584      * @throws SQLException if (1) the given column name does not match the
6585      *            name of a column in this rowset, (2) the cursor is not on
6586      *            one of this rowset's rows or its insert row, or (3) this
6587      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6588      */
6589     public void updateClob(String columnName, Clob c) throws SQLException {
6590         updateClob(getColIdxByName(columnName), c);
6591     }
6592 
6593     /**
6594      * Sets the designated column in either the current row or the insert
6595      * row of this <code>CachedRowSetImpl</code> object with the given
6596      * <code>java.sql.Blob</code> value.
6597      *
6598      * This method updates a column value in either the current row or
6599      * the insert row of this rowset, but it does not update the
6600      * database.  If the cursor is on a row in the rowset, the
6601      * method {@link #updateRow} must be called to update the database.
6602      * If the cursor is on the insert row, the method {@link #insertRow}
6603      * must be called, which will insert the new row into both this rowset
6604      * and the database. Both of these methods must be called before the
6605      * cursor moves to another row.
6606      *
6607      * @param columnIndex the first column is <code>1</code>, the second
6608      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6609      *        and equal to or less than the number of columns in this rowset
6610      * @param b the new column <code>Blob</code> value
6611      * @throws SQLException if (1) the given column index is out of bounds,
6612      *            (2) the cursor is not on one of this rowset's rows or its
6613      *            insert row, or (3) this rowset is
6614      *            <code>ResultSet.CONCUR_READ_ONLY</code>
6615      */
6616     public void updateBlob(int columnIndex, Blob b) throws SQLException {
6617         // sanity check.
6618         checkIndex(columnIndex);
6619         // make sure the cursor is on a valid row
6620         checkCursor();
6621 
6622         // SerialBlob will help in getting the byte array and storing it.
6623         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6624         // or through RowSetMetaData.locatorsUpdatorCopy()
6625 
6626         if(dbmslocatorsUpdateCopy){
6627            getCurrentRow().setColumnObject(columnIndex, new SerialBlob(b));
6628         }
6629         else{
6630            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.opnotsupp").toString());
6631         }
6632     }
6633 
6634     /**
6635      * Sets the designated column in either the current row or the insert
6636      * row of this <code>CachedRowSetImpl</code> object with the given
6637      * <code>java.sql.Blob </code> value.
6638      *
6639      * This method updates a column value in either the current row or
6640      * the insert row of this rowset, but it does not update the
6641      * database.  If the cursor is on a row in the rowset, the
6642      * method {@link #updateRow} must be called to update the database.
6643      * If the cursor is on the insert row, the method {@link #insertRow}
6644      * must be called, which will insert the new row into both this rowset
6645      * and the database. Both of these methods must be called before the
6646      * cursor moves to another row.
6647      *
6648      * @param columnName a <code>String</code> object that must match the
6649      *        SQL name of a column in this rowset, ignoring case
6650      * @param b the new column <code>Blob</code> value
6651      * @throws SQLException if (1) the given column name does not match the
6652      *            name of a column in this rowset, (2) the cursor is not on
6653      *            one of this rowset's rows or its insert row, or (3) this
6654      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6655      */
6656     public void updateBlob(String columnName, Blob b) throws SQLException {
6657         updateBlob(getColIdxByName(columnName), b);
6658     }
6659 
6660     /**
6661      * Sets the designated column in either the current row or the insert
6662      * row of this <code>CachedRowSetImpl</code> object with the given
6663      * <code>java.sql.Array</code> values.
6664      *
6665      * This method updates a column value in either the current row or
6666      * the insert row of this rowset, but it does not update the
6667      * database.  If the cursor is on a row in the rowset, the
6668      * method {@link #updateRow} must be called to update the database.
6669      * If the cursor is on the insert row, the method {@link #insertRow}
6670      * must be called, which will insert the new row into both this rowset
6671      * and the database. Both of these methods must be called before the
6672      * cursor moves to another row.
6673      *
6674      * @param columnIndex the first column is <code>1</code>, the second
6675      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6676      *        and equal to or less than the number of columns in this rowset
6677      * @param a the new column <code>Array</code> value
6678      * @throws SQLException if (1) the given column index is out of bounds,
6679      *            (2) the cursor is not on one of this rowset's rows or its
6680      *            insert row, or (3) this rowset is
6681      *            <code>ResultSet.CONCUR_READ_ONLY</code>
6682      */
6683     public void updateArray(int columnIndex, Array a) throws SQLException {
6684         // sanity check.
6685         checkIndex(columnIndex);
6686         // make sure the cursor is on a valid row
6687         checkCursor();
6688 
6689         // SerialArray will help in getting the byte array and storing it.
6690         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6691         // or through RowSetMetaData.locatorsUpdatorCopy()
6692         getCurrentRow().setColumnObject(columnIndex, new SerialArray(a));
6693     }
6694 
6695     /**
6696      * Sets the designated column in either the current row or the insert
6697      * row of this <code>CachedRowSetImpl</code> object with the given
6698      * <code>java.sql.Array</code> value.
6699      *
6700      * This method updates a column value in either the current row or
6701      * the insert row of this rowset, but it does not update the
6702      * database.  If the cursor is on a row in the rowset, the
6703      * method {@link #updateRow} must be called to update the database.
6704      * If the cursor is on the insert row, the method {@link #insertRow}
6705      * must be called, which will insert the new row into both this rowset
6706      * and the database. Both of these methods must be called before the
6707      * cursor moves to another row.
6708      *
6709      * @param columnName a <code>String</code> object that must match the
6710      *        SQL name of a column in this rowset, ignoring case
6711      * @param a the new column <code>Array</code> value
6712      * @throws SQLException if (1) the given column name does not match the
6713      *            name of a column in this rowset, (2) the cursor is not on
6714      *            one of this rowset's rows or its insert row, or (3) this
6715      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6716      */
6717     public void updateArray(String columnName, Array a) throws SQLException {
6718         updateArray(getColIdxByName(columnName), a);
6719     }
6720 
6721 
6722     /**
6723      * Retrieves the value of the designated column in this
6724      * <code>CachedRowSetImpl</code> object as a <code>java.net.URL</code> object
6725      * in the Java programming language.
6726      *
6727      * @return a java.net.URL object containing the resource reference described by
6728      * the URL
6729      * @throws SQLException if (1) the given column index is out of bounds,
6730      * (2) the cursor is not on one of this rowset's rows or its
6731      * insert row, or (3) the designated column does not store an
6732      * SQL <code>DATALINK</code> value.
6733      * @see #getURL(String)
6734      */
6735     public java.net.URL getURL(int columnIndex) throws SQLException {
6736         //throw new SQLException("Operation not supported");
6737 
6738         java.net.URL value;
6739 
6740         // sanity check.
6741         checkIndex(columnIndex);
6742         // make sure the cursor is on a valid row
6743         checkCursor();
6744 
6745         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.DATALINK) {
6746             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
6747         }
6748 
6749         setLastValueNull(false);
6750         value = (java.net.URL)(getCurrentRow().getColumnObject(columnIndex));
6751 
6752         // check for SQL NULL
6753         if (value == null) {
6754             setLastValueNull(true);
6755             return null;
6756         }
6757 
6758         return value;
6759     }
6760 
6761     /**
6762      * Retrieves the value of the designated column in this
6763      * <code>CachedRowSetImpl</code> object as a <code>java.net.URL</code> object
6764      * in the Java programming language.
6765      *
6766      * @return a java.net.URL object containing the resource reference described by
6767      * the URL
6768      * @throws SQLException if (1) the given column name not the name of a column
6769      * in this rowset, or
6770      * (2) the cursor is not on one of this rowset's rows or its
6771      * insert row, or (3) the designated column does not store an
6772      * SQL <code>DATALINK</code> value.
6773      * @see #getURL(int)
6774      */
6775     public java.net.URL getURL(String columnName) throws SQLException {
6776         return getURL(getColIdxByName(columnName));
6777 
6778     }
6779 
6780     /**
6781      * The first warning reported by calls on this <code>CachedRowSetImpl</code>
6782      * object is returned. Subsequent <code>CachedRowSetImpl</code> warnings will
6783      * be chained to this <code>SQLWarning</code>. All <code>RowSetWarnings</code>
6784      * warnings are generated in the disconnected environment and remain a
6785      * seperate warning chain to that provided by the <code>getWarnings</code>
6786      * method.
6787      *
6788      * <P>The warning chain is automatically cleared each time a new
6789      * row is read.
6790      *
6791      * <P><B>Note:</B> This warning chain only covers warnings caused
6792      * by <code>CachedRowSet</code> (and their child interface)
6793      * methods. All <code>SQLWarnings</code> can be obtained using the
6794      * <code>getWarnings</code> method which tracks warnings generated
6795      * by the underlying JDBC driver.
6796      * @return the first SQLWarning or null
6797      *
6798      */
6799     public RowSetWarning getRowSetWarnings() {
6800         try {
6801             notifyCursorMoved();
6802         } catch (SQLException e) {} // mask exception
6803         return rowsetWarning;
6804     }
6805 
6806 
6807     /**
6808      * The function tries to isolate the tablename when only setCommand
6809      * is set and not setTablename is called provided there is only one table
6810      * name in the query else just leaves the setting of table name as such.
6811      * If setTablename is set later it will over ride this table name
6812      * value so retrieved.
6813      *
6814      * @return the tablename if only one table in query else return ""
6815      */
6816     private String buildTableName(String command) throws SQLException {
6817 
6818         // If we have a query from one table,
6819         // we set the table name implicitly
6820         // else user has to explicitly set the table name.
6821 
6822         int indexFrom, indexComma;
6823         String strTablename ="";
6824         command = command.trim();
6825 
6826         // Query can be a select, insert or  update
6827 
6828         if(command.toLowerCase().startsWith("select")) {
6829             // look for "from" keyword, after that look for a
6830             // comma after from. If comma is there don't set
6831             // table name else isolate table name.
6832 
6833             indexFrom = command.toLowerCase().indexOf("from");
6834             indexComma = command.indexOf(',', indexFrom);
6835 
6836             if(indexComma == -1) {
6837                 // implies only one table
6838                 strTablename = (command.substring(indexFrom+"from".length(),command.length())).trim();
6839 
6840                 String tabName = strTablename;
6841 
6842                 int idxWhere = tabName.toLowerCase().indexOf("where");
6843 
6844                 /**
6845                   * Adding the addtional check for conditions following the table name.
6846                   * If a condition is found truncate it.
6847                   **/
6848 
6849                 if(idxWhere != -1)
6850                 {
6851                    tabName = tabName.substring(0,idxWhere).trim();
6852                 }
6853 
6854                 strTablename = tabName;
6855 
6856             } else {
6857                 //strTablename="";
6858             }
6859 
6860         } else if(command.toLowerCase().startsWith("insert")) {
6861             //strTablename="";
6862         } else if(command.toLowerCase().startsWith("update")) {
6863             //strTablename="";
6864         }
6865         return strTablename;
6866     }
6867 
6868     /**
6869      * Commits all changes performed by the <code>acceptChanges()</code>
6870      * methods
6871      *
6872      * @see java.sql.Connection#commit
6873      */
6874     public void commit() throws SQLException {
6875         conn.commit();
6876     }
6877 
6878     /**
6879      * Rolls back all changes performed by the <code>acceptChanges()</code>
6880      * methods
6881      *
6882      * @see java.sql.Connection#rollback
6883      */
6884     public void rollback() throws SQLException {
6885         conn.rollback();
6886     }
6887 
6888     /**
6889      * Rolls back all changes performed by the <code>acceptChanges()</code>
6890      * to the last <code>Savepoint</code> transaction marker.
6891      *
6892      * @see java.sql.Connection#rollback(Savepoint)
6893      */
6894     public void rollback(Savepoint s) throws SQLException {
6895         conn.rollback(s);
6896     }
6897 
6898     /**
6899      * Unsets the designated parameter to the given int array.
6900      * This was set using <code>setMatchColumn</code>
6901      * as the column which will form the basis of the join.
6902      * <P>
6903      * The parameter value unset by this method should be same
6904      * as was set.
6905      *
6906      * @param columnIdxes the index into this rowset
6907      *        object's internal representation of parameter values
6908      * @throws SQLException if an error occurs or the
6909      *  parameter index is out of bounds or if the columnIdx is
6910      *  not the same as set using <code>setMatchColumn(int [])</code>
6911      */
6912     public void unsetMatchColumn(int[] columnIdxes) throws SQLException {
6913 
6914          int i_val;
6915          for( int j= 0 ;j < columnIdxes.length; j++) {
6916             i_val = (Integer.parseInt(iMatchColumns.get(j).toString()));
6917             if(columnIdxes[j] != i_val) {
6918                throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols").toString());
6919             }
6920          }
6921 
6922          for( int i = 0;i < columnIdxes.length ;i++) {
6923             iMatchColumns.set(i, -1);
6924          }
6925     }
6926 
6927    /**
6928      * Unsets the designated parameter to the given String array.
6929      * This was set using <code>setMatchColumn</code>
6930      * as the column which will form the basis of the join.
6931      * <P>
6932      * The parameter value unset by this method should be same
6933      * as was set.
6934      *
6935      * @param columnIdxes the index into this rowset
6936      *        object's internal representation of parameter values
6937      * @throws SQLException if an error occurs or the
6938      *  parameter index is out of bounds or if the columnName is
6939      *  not the same as set using <code>setMatchColumn(String [])</code>
6940      */
6941     public void unsetMatchColumn(String[] columnIdxes) throws SQLException {
6942 
6943         for(int j = 0 ;j < columnIdxes.length; j++) {
6944            if( !columnIdxes[j].equals(strMatchColumns.get(j)) ){
6945               throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols").toString());
6946            }
6947         }
6948 
6949         for(int i = 0 ; i < columnIdxes.length; i++) {
6950            strMatchColumns.set(i,null);
6951         }
6952     }
6953 
6954     /**
6955      * Retrieves the column name as <code>String</code> array
6956      * that was set using <code>setMatchColumn(String [])</code>
6957      * for this rowset.
6958      *
6959      * @return a <code>String</code> array object that contains the column names
6960      *         for the rowset which has this the match columns
6961      *
6962      * @throws SQLException if an error occurs or column name is not set
6963      */
6964     public String[] getMatchColumnNames() throws SQLException {
6965 
6966         String []str_temp = new String[strMatchColumns.size()];
6967 
6968         if( strMatchColumns.get(0) == null) {
6969            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.setmatchcols").toString());
6970         }
6971 
6972         strMatchColumns.copyInto(str_temp);
6973         return str_temp;
6974     }
6975 
6976     /**
6977      * Retrieves the column id as <code>int</code> array that was set using
6978      * <code>setMatchColumn(int [])</code> for this rowset.
6979      *
6980      * @return a <code>int</code> array object that contains the column ids
6981      *         for the rowset which has this as the match columns.
6982      *
6983      * @throws SQLException if an error occurs or column index is not set
6984      */
6985     public int[] getMatchColumnIndexes() throws SQLException {
6986 
6987         Integer []int_temp = new Integer[iMatchColumns.size()];
6988         int [] i_temp = new int[iMatchColumns.size()];
6989         int i_val;
6990 
6991         i_val = iMatchColumns.get(0);
6992 
6993         if( i_val == -1 ) {
6994            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.setmatchcols").toString());
6995         }
6996 
6997 
6998         iMatchColumns.copyInto(int_temp);
6999 
7000         for(int i = 0; i < int_temp.length; i++) {
7001            i_temp[i] = (int_temp[i]).intValue();
7002         }
7003 
7004         return i_temp;
7005     }
7006 
7007     /**
7008      * Sets the designated parameter to the given int array.
7009      * This forms the basis of the join for the
7010      * <code>JoinRowSet</code> as the column which will form the basis of the
7011      * join.
7012      * <P>
7013      * The parameter value set by this method is stored internally and
7014      * will be supplied as the appropriate parameter in this rowset's
7015      * command when the method <code>getMatchColumnIndexes</code> is called.
7016      *
7017      * @param columnIdxes the indexes into this rowset
7018      *        object's internal representation of parameter values; the
7019      *        first parameter is 0, the second is 1, and so on; must be
7020      *        <code>0</code> or greater
7021      * @throws SQLException if an error occurs or the
7022      *                         parameter index is out of bounds
7023      */
7024     public void setMatchColumn(int[] columnIdxes) throws SQLException {
7025 
7026         for(int j = 0 ; j < columnIdxes.length; j++) {
7027            if( columnIdxes[j] < 0 ) {
7028               throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols1").toString());
7029            }
7030         }
7031         for(int i = 0 ;i < columnIdxes.length; i++) {
7032            iMatchColumns.add(i,columnIdxes[i]);
7033         }
7034     }
7035 
7036     /**
7037      * Sets the designated parameter to the given String array.
7038      *  This forms the basis of the join for the
7039      * <code>JoinRowSet</code> as the column which will form the basis of the
7040      * join.
7041      * <P>
7042      * The parameter value set by this method is stored internally and
7043      * will be supplied as the appropriate parameter in this rowset's
7044      * command when the method <code>getMatchColumn</code> is called.
7045      *
7046      * @param columnNames the name of the column into this rowset
7047      *        object's internal representation of parameter values
7048      * @throws SQLException if an error occurs or the
7049      *  parameter index is out of bounds
7050      */
7051     public void setMatchColumn(String[] columnNames) throws SQLException {
7052 
7053         for(int j = 0; j < columnNames.length; j++) {
7054            if( columnNames[j] == null || columnNames[j].equals("")) {
7055               throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols2").toString());
7056            }
7057         }
7058         for( int i = 0; i < columnNames.length; i++) {
7059            strMatchColumns.add(i,columnNames[i]);
7060         }
7061     }
7062 
7063 
7064     /**
7065      * Sets the designated parameter to the given <code>int</code>
7066      * object.  This forms the basis of the join for the
7067      * <code>JoinRowSet</code> as the column which will form the basis of the
7068      * join.
7069      * <P>
7070      * The parameter value set by this method is stored internally and
7071      * will be supplied as the appropriate parameter in this rowset's
7072      * command when the method <code>getMatchColumn</code> is called.
7073      *
7074      * @param columnIdx the index into this rowset
7075      *        object's internal representation of parameter values; the
7076      *        first parameter is 0, the second is 1, and so on; must be
7077      *        <code>0</code> or greater
7078      * @throws SQLException if an error occurs or the
7079      *                         parameter index is out of bounds
7080      */
7081     public void setMatchColumn(int columnIdx) throws SQLException {
7082         // validate, if col is ok to be set
7083         if(columnIdx < 0) {
7084             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols1").toString());
7085         } else {
7086             // set iMatchColumn
7087             iMatchColumns.set(0, columnIdx);
7088             //strMatchColumn = null;
7089         }
7090     }
7091 
7092     /**
7093      * Sets the designated parameter to the given <code>String</code>
7094      * object.  This forms the basis of the join for the
7095      * <code>JoinRowSet</code> as the column which will form the basis of the
7096      * join.
7097      * <P>
7098      * The parameter value set by this method is stored internally and
7099      * will be supplied as the appropriate parameter in this rowset's
7100      * command when the method <code>getMatchColumn</code> is called.
7101      *
7102      * @param columnName the name of the column into this rowset
7103      *        object's internal representation of parameter values
7104      * @throws SQLException if an error occurs or the
7105      *  parameter index is out of bounds
7106      */
7107     public void setMatchColumn(String columnName) throws SQLException {
7108         // validate, if col is ok to be set
7109         if(columnName == null || (columnName= columnName.trim()).equals("") ) {
7110             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols2").toString());
7111         } else {
7112             // set strMatchColumn
7113             strMatchColumns.set(0, columnName);
7114             //iMatchColumn = -1;
7115         }
7116     }
7117 
7118     /**
7119      * Unsets the designated parameter to the given <code>int</code>
7120      * object.  This was set using <code>setMatchColumn</code>
7121      * as the column which will form the basis of the join.
7122      * <P>
7123      * The parameter value unset by this method should be same
7124      * as was set.
7125      *
7126      * @param columnIdx the index into this rowset
7127      *        object's internal representation of parameter values
7128      * @throws SQLException if an error occurs or the
7129      *  parameter index is out of bounds or if the columnIdx is
7130      *  not the same as set using <code>setMatchColumn(int)</code>
7131      */
7132     public void unsetMatchColumn(int columnIdx) throws SQLException {
7133         // check if we are unsetting the SAME column
7134         if(! iMatchColumns.get(0).equals(Integer.valueOf(columnIdx) )  ) {
7135             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch").toString());
7136         } else if(strMatchColumns.get(0) != null) {
7137             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch1").toString());
7138         } else {
7139                 // that is, we are unsetting it.
7140                iMatchColumns.set(0, -1);
7141         }
7142     }
7143 
7144     /**
7145      * Unsets the designated parameter to the given <code>String</code>
7146      * object.  This was set using <code>setMatchColumn</code>
7147      * as the column which will form the basis of the join.
7148      * <P>
7149      * The parameter value unset by this method should be same
7150      * as was set.
7151      *
7152      * @param columnName the index into this rowset
7153      *        object's internal representation of parameter values
7154      * @throws SQLException if an error occurs or the
7155      *  parameter index is out of bounds or if the columnName is
7156      *  not the same as set using <code>setMatchColumn(String)</code>
7157      */
7158     public void unsetMatchColumn(String columnName) throws SQLException {
7159         // check if we are unsetting the same column
7160         columnName = columnName.trim();
7161 
7162         if(!((strMatchColumns.get(0)).equals(columnName))) {
7163             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch").toString());
7164         } else if(iMatchColumns.get(0) > 0) {
7165             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch2").toString());
7166         } else {
7167             strMatchColumns.set(0, null);   // that is, we are unsetting it.
7168         }
7169     }
7170 
7171     /**
7172      * Notifies registered listeners that a RowSet object in the given RowSetEvent
7173      * object has populated a number of additional rows. The <code>numRows</code> parameter
7174      * ensures that this event will only be fired every <code>numRow</code>.
7175      * <p>
7176      * The source of the event can be retrieved with the method event.getSource.
7177      *
7178      * @param event a <code>RowSetEvent</code> object that contains the
7179      *     <code>RowSet</code> object that is the source of the events
7180      * @param numRows when populating, the number of rows interval on which the
7181      *     <code>CachedRowSet</code> populated should fire; the default value
7182      *     is zero; cannot be less than <code>fetchSize</code> or zero
7183      */
7184     public void rowSetPopulated(RowSetEvent event, int numRows) throws SQLException {
7185 
7186         if( numRows < 0 || numRows < getFetchSize()) {
7187            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.numrows").toString());
7188         }
7189 
7190         if(size() % numRows == 0) {
7191             RowSetEvent event_temp = new RowSetEvent(this);
7192             event = event_temp;
7193             notifyRowSetChanged();
7194         }
7195     }
7196 
7197     /**
7198      * Populates this <code>CachedRowSet</code> object with data from
7199      * the given <code>ResultSet</code> object. While related to the <code>populate(ResultSet)</code>
7200      * method, an additional parameter is provided to allow starting position within
7201      * the <code>ResultSet</code> from where to populate the CachedRowSet
7202      * instance.
7203      *
7204      * This method is an alternative to the method <code>execute</code>
7205      * for filling the rowset with data.  The method <code>populate</code>
7206      * does not require that the properties needed by the method
7207      * <code>execute</code>, such as the <code>command</code> property,
7208      * be set. This is true because the method <code>populate</code>
7209      * is given the <code>ResultSet</code> object from
7210      * which to get data and thus does not need to use the properties
7211      * required for setting up a connection and executing this
7212      * <code>CachedRowSetImpl</code> object's command.
7213      * <P>
7214      * After populating this rowset with data, the method
7215      * <code>populate</code> sets the rowset's metadata and
7216      * then sends a <code>RowSetChangedEvent</code> object
7217      * to all registered listeners prior to returning.
7218      *
7219      * @param data the <code>ResultSet</code> object containing the data
7220      *             to be read into this <code>CachedRowSetImpl</code> object
7221      * @param start the integer specifing the position in the
7222      *        <code>ResultSet</code> object to popultate the
7223      *        <code>CachedRowSetImpl</code> object.
7224      * @throws SQLException if an error occurs; or the max row setting is
7225      *          violated while populating the RowSet.Also id the start position
7226      *          is negative.
7227      * @see #execute
7228      */
7229      public void populate(ResultSet data, int start) throws SQLException{
7230 
7231         int rowsFetched;
7232         Row currentRow;
7233         int numCols;
7234         int i;
7235         Map<String, Class<?>> map = getTypeMap();
7236         Object obj;
7237         int mRows;
7238 
7239         cursorPos = 0;
7240         if(populatecallcount == 0){
7241             if(start < 0){
7242                throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.startpos").toString());
7243             }
7244             if(getMaxRows() == 0){
7245                data.absolute(start);
7246                while(data.next()){
7247                    totalRows++;
7248                }
7249                totalRows++;
7250             }
7251             startPos = start;
7252         }
7253         populatecallcount = populatecallcount +1;
7254         resultSet = data;
7255         if((endPos - startPos) >= getMaxRows() && (getMaxRows() > 0)){
7256             endPos = prevEndPos;
7257             pagenotend = false;
7258             return;
7259         }
7260 
7261         if((maxRowsreached != getMaxRows() || maxRowsreached != totalRows) && pagenotend) {
7262            startPrev = start - getPageSize();
7263         }
7264 
7265         if( pageSize == 0){
7266            prevEndPos = endPos;
7267            endPos = start + getMaxRows() ;
7268         }
7269         else{
7270             prevEndPos = endPos;
7271             endPos = start + getPageSize();
7272         }
7273 
7274 
7275         if (start == 1){
7276             resultSet.beforeFirst();
7277         }
7278         else {
7279             resultSet.absolute(start -1);
7280         }
7281         if( pageSize == 0) {
7282            rvh = new Vector<Object>(getMaxRows());
7283 
7284         }
7285         else{
7286             rvh = new Vector<Object>(getPageSize());
7287         }
7288 
7289         if (data == null) {
7290             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.populate").toString());
7291         }
7292 
7293         // get the meta data for this ResultSet
7294         RSMD = data.getMetaData();
7295 
7296         // set up the metadata
7297         RowSetMD = new RowSetMetaDataImpl();
7298         initMetaData(RowSetMD, RSMD);
7299 
7300         // release the meta-data so that aren't tempted to use it.
7301         RSMD = null;
7302         numCols = RowSetMD.getColumnCount();
7303         mRows = this.getMaxRows();
7304         rowsFetched = 0;
7305         currentRow = null;
7306 
7307         if(!data.next() && mRows == 0){
7308             endPos = prevEndPos;
7309             pagenotend = false;
7310             return;
7311         }
7312 
7313         data.previous();
7314 
7315         while ( data.next()) {
7316 
7317             currentRow = new Row(numCols);
7318           if(pageSize == 0){
7319             if ( rowsFetched >= mRows && mRows > 0) {
7320                 rowsetWarning.setNextException(new SQLException("Populating rows "
7321                 + "setting has exceeded max row setting"));
7322                 break;
7323             }
7324           }
7325           else {
7326               if ( (rowsFetched >= pageSize) ||( maxRowsreached >= mRows && mRows > 0)) {
7327                 rowsetWarning.setNextException(new SQLException("Populating rows "
7328                 + "setting has exceeded max row setting"));
7329                 break;
7330             }
7331           }
7332 
7333             for ( i = 1; i <= numCols; i++) {
7334                 /*
7335                  * check if the user has set a map. If no map
7336                  * is set then use plain getObject. This lets
7337                  * us work with drivers that do not support
7338                  * getObject with a map in fairly sensible way
7339                  */
7340                 if (map == null) {
7341                     obj = data.getObject(i);
7342                 } else {
7343                     obj = data.getObject(i, map);
7344                 }
7345                 /*
7346                  * the following block checks for the various
7347                  * types that we have to serialize in order to
7348                  * store - right now only structs have been tested
7349                  */
7350                 if (obj instanceof Struct) {
7351                     obj = new SerialStruct((Struct)obj, map);
7352                 } else if (obj instanceof SQLData) {
7353                     obj = new SerialStruct((SQLData)obj, map);
7354                 } else if (obj instanceof Blob) {
7355                     obj = new SerialBlob((Blob)obj);
7356                 } else if (obj instanceof Clob) {
7357                     obj = new SerialClob((Clob)obj);
7358                 } else if (obj instanceof java.sql.Array) {
7359                     obj = new SerialArray((java.sql.Array)obj, map);
7360                 }
7361 
7362                 currentRow.initColumnObject(i, obj);
7363             }
7364             rowsFetched++;
7365             maxRowsreached++;
7366             rvh.add(currentRow);
7367         }
7368         numRows = rowsFetched ;
7369         // Also rowsFetched should be equal to rvh.size()
7370         // notify any listeners that the rowset has changed
7371         notifyRowSetChanged();
7372 
7373      }
7374 
7375     /**
7376      * The nextPage gets the next page, that is a <code>CachedRowSetImpl</code> object
7377      * containing the number of rows specified by page size.
7378      * @return boolean value true indicating whether there are more pages to come and
7379      *         false indicating that this is the last page.
7380      * @throws SQLException if an error occurs or this called before calling populate.
7381      */
7382      public boolean nextPage() throws SQLException {
7383 
7384          if (populatecallcount == 0){
7385              throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.nextpage").toString());
7386          }
7387          // Fix for 6554186
7388          onFirstPage = false;
7389          if(callWithCon){
7390             crsReader.setStartPosition(endPos);
7391             crsReader.readData((RowSetInternal)this);
7392             resultSet = null;
7393          }
7394          else {
7395             populate(resultSet,endPos);
7396          }
7397          return pagenotend;
7398      }
7399 
7400     /**
7401      * This is the setter function for setting the size of the page, which specifies
7402      * how many rows have to be retrived at a time.
7403      *
7404      * @param size which is the page size
7405      * @throws SQLException if size is less than zero or greater than max rows.
7406      */
7407      public void setPageSize (int size) throws SQLException {
7408         if (size < 0) {
7409             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.pagesize").toString());
7410         }
7411         if (size > getMaxRows() && getMaxRows() != 0) {
7412             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.pagesize1").toString());
7413         }
7414         pageSize = size;
7415      }
7416 
7417     /**
7418      * This is the getter function for the size of the page.
7419      *
7420      * @return an integer that is the page size.
7421      */
7422     public int getPageSize() {
7423         return pageSize;
7424     }
7425 
7426 
7427     /**
7428      * Retrieves the data present in the page prior to the page from where it is
7429      * called.
7430      * @return boolean value true if it retrieves the previous page, flase if it
7431      *         is on the first page.
7432      * @throws SQLException if it is called before populate is called or ResultSet
7433      *         is of type <code>ResultSet.TYPE_FORWARD_ONLY</code> or if an error
7434      *         occurs.
7435      */
7436     public boolean previousPage() throws SQLException {
7437         int pS;
7438         int mR;
7439         int rem;
7440 
7441         pS = getPageSize();
7442         mR = maxRowsreached;
7443 
7444         if (populatecallcount == 0){
7445              throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.nextpage").toString());
7446          }
7447 
7448         if( !callWithCon){
7449            if(resultSet.getType() == ResultSet.TYPE_FORWARD_ONLY){
7450                throw new SQLException (resBundle.handleGetObject("cachedrowsetimpl.fwdonly").toString());
7451            }
7452         }
7453 
7454         pagenotend = true;
7455 
7456         if(startPrev < startPos ){
7457                 onFirstPage = true;
7458                return false;
7459             }
7460 
7461         if(onFirstPage){
7462             return false;
7463         }
7464 
7465         rem = mR % pS;
7466 
7467         if(rem == 0){
7468             maxRowsreached -= (2 * pS);
7469             if(callWithCon){
7470                 crsReader.setStartPosition(startPrev);
7471                 crsReader.readData((RowSetInternal)this);
7472                 resultSet = null;
7473             }
7474             else {
7475                populate(resultSet,startPrev);
7476             }
7477             return true;
7478         }
7479         else
7480         {
7481             maxRowsreached -= (pS + rem);
7482             if(callWithCon){
7483                 crsReader.setStartPosition(startPrev);
7484                 crsReader.readData((RowSetInternal)this);
7485                 resultSet = null;
7486             }
7487             else {
7488                populate(resultSet,startPrev);
7489             }
7490             return true;
7491         }
7492     }
7493 
7494     /**
7495      * Goes to the page number passed as the parameter
7496      * @param page , the page loaded on a call to this function
7497      * @return true if the page exists false otherwise
7498      * @throws SQLException if an error occurs
7499      */
7500     /*
7501     public boolean absolutePage(int page) throws SQLException{
7502 
7503         boolean isAbs = true, retVal = true;
7504         int counter;
7505 
7506         if( page <= 0 ){
7507             throw new SQLException("Absolute positoin is invalid");
7508         }
7509         counter = 0;
7510 
7511         firstPage();
7512         counter++;
7513         while((counter < page) && isAbs) {
7514             isAbs = nextPage();
7515             counter ++;
7516         }
7517 
7518         if( !isAbs && counter < page){
7519             retVal = false;
7520         }
7521         else if(counter == page){
7522             retVal = true;
7523         }
7524 
7525        return retVal;
7526     }
7527     */
7528 
7529 
7530     /**
7531      * Goes to the page number passed as the parameter  from the current page.
7532      * The parameter can take postive or negative value accordingly.
7533      * @param page , the page loaded on a call to this function
7534      * @return true if the page exists false otherwise
7535      * @throws SQLException if an error occurs
7536      */
7537     /*
7538     public boolean relativePage(int page) throws SQLException {
7539 
7540         boolean isRel = true,retVal = true;
7541         int counter;
7542 
7543         if(page > 0){
7544            counter  = 0;
7545            while((counter < page) && isRel){
7546               isRel = nextPage();
7547               counter++;
7548            }
7549 
7550            if(!isRel && counter < page){
7551                retVal = false;
7552            }
7553            else if( counter == page){
7554                retVal = true;
7555            }
7556            return retVal;
7557         }
7558         else {
7559             counter = page;
7560             isRel = true;
7561             while((counter < 0) && isRel){
7562                 isRel = previousPage();
7563                 counter++;
7564             }
7565 
7566             if( !isRel && counter < 0){
7567                 retVal = false;
7568             }
7569             else if(counter == 0){
7570                 retVal = true;
7571             }
7572             return retVal;
7573         }
7574     }
7575     */
7576 
7577      /**
7578      * Retrieves the first page of data as specified by the page size.
7579      * @return boolean value true if present on first page, false otherwise
7580      * @throws SQLException if it called before populate or ResultSet is of
7581      *         type <code>ResultSet.TYPE_FORWARD_ONLY</code> or an error occurs
7582      */
7583     /*
7584     public boolean firstPage() throws SQLException {
7585            if (populatecallcount == 0){
7586              throw new SQLException("Populate the data before calling ");
7587            }
7588            if( !callWithCon){
7589               if(resultSet.getType() == ResultSet.TYPE_FORWARD_ONLY) {
7590                   throw new SQLException("Result of type forward only");
7591               }
7592            }
7593            endPos = 0;
7594            maxRowsreached = 0;
7595            pagenotend = true;
7596            if(callWithCon){
7597                crsReader.setStartPosition(startPos);
7598                crsReader.readData((RowSetInternal)this);
7599                resultSet = null;
7600            }
7601            else {
7602               populate(resultSet,startPos);
7603            }
7604            onFirstPage = true;
7605            return onFirstPage;
7606     }
7607     */
7608 
7609     /**
7610      * Retrives the last page of data as specified by the page size.
7611      * @return boolean value tur if present on the last page, false otherwise
7612      * @throws SQLException if called before populate or if an error occurs.
7613      */
7614      /*
7615     public boolean lastPage() throws SQLException{
7616           int pS;
7617           int mR;
7618           int quo;
7619           int rem;
7620 
7621           pS = getPageSize();
7622           mR = getMaxRows();
7623 
7624           if(pS == 0){
7625               onLastPage = true;
7626               return onLastPage;
7627           }
7628 
7629           if(getMaxRows() == 0){
7630               mR = totalRows;
7631           }
7632 
7633           if (populatecallcount == 0){
7634              throw new SQLException("Populate the data before calling ");
7635          }
7636 
7637          onFirstPage = false;
7638 
7639          if((mR % pS) == 0){
7640              quo = mR / pS;
7641              int start = startPos + (pS * (quo - 1));
7642              maxRowsreached = mR - pS;
7643              if(callWithCon){
7644                  crsReader.setStartPosition(start);
7645                  crsReader.readData((RowSetInternal)this);
7646                  resultSet = null;
7647              }
7648              else {
7649                 populate(resultSet,start);
7650              }
7651              onLastPage = true;
7652              return onLastPage;
7653          }
7654         else {
7655               quo = mR /pS;
7656               rem = mR % pS;
7657               int start = startPos + (pS * quo);
7658              maxRowsreached = mR - (rem);
7659              if(callWithCon){
7660                  crsReader.setStartPosition(start);
7661                  crsReader.readData((RowSetInternal)this);
7662                  resultSet = null;
7663              }
7664              else {
7665                 populate(resultSet,start);
7666              }
7667              onLastPage = true;
7668              return onLastPage;
7669          }
7670     }
7671     */
7672 
7673    /**
7674      * Sets the status for the row on which the cursor is positioned. The insertFlag is used
7675      * to mention the toggle status for this row
7676      * @param insertFlag if it is true  - marks this row as inserted
7677      *                   if it is false - marks it as not a newly inserted row
7678      * @throws SQLException if an error occurs while doing this operation
7679      */
7680     public void setRowInserted(boolean insertFlag) throws SQLException {
7681 
7682         checkCursor();
7683 
7684         if(onInsertRow == true)
7685           throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
7686 
7687         if( insertFlag ) {
7688           ((Row)getCurrentRow()).setInserted();
7689         } else {
7690           ((Row)getCurrentRow()).clearInserted();
7691         }
7692     }
7693 
7694     /**
7695      * Retrieves the value of the designated <code>SQL XML</code> parameter as a
7696      * <code>SQLXML</code> object in the Java programming language.
7697      * @param columnIndex the first column is 1, the second is 2, ...
7698      * @return a SQLXML object that maps an SQL XML value
7699      * @throws SQLException if a database access error occurs
7700      * @since 1.6
7701      */
7702     public SQLXML getSQLXML(int columnIndex) throws SQLException {
7703         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7704     }
7705 
7706     /**
7707      * Retrieves the value of the designated <code>SQL XML</code> parameter as a
7708      * <code>SQLXML</code> object in the Java programming language.
7709      * @param colName the name of the column from which to retrieve the value
7710      * @return a SQLXML object that maps an SQL XML value
7711      * @throws SQLException if a database access error occurs
7712      */
7713     public SQLXML getSQLXML(String colName) throws SQLException {
7714         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7715     }
7716 
7717     /**
7718      * Retrieves the value of the designated column in the current row of this
7719      * <code>ResultSet</code> object as a java.sql.RowId object in the Java
7720      * programming language.
7721      *
7722      * @param columnIndex the first column is 1, the second 2, ...
7723      * @return the column value if the value is a SQL <code>NULL</code> the
7724      *     value returned is <code>null</code>
7725      * @throws SQLException if a database access error occurs
7726      * @since 1.6
7727      */
7728     public RowId getRowId(int columnIndex) throws SQLException {
7729         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7730     }
7731 
7732     /**
7733      * Retrieves the value of the designated column in the current row of this
7734      * <code>ResultSet</code> object as a java.sql.RowId object in the Java
7735      * programming language.
7736      *
7737      * @param columnName the name of the column
7738      * @return the column value if the value is a SQL <code>NULL</code> the
7739      *     value returned is <code>null</code>
7740      * @throws SQLException if a database access error occurs
7741      * @since 1.6
7742      */
7743     public RowId getRowId(String columnName) throws SQLException {
7744         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7745     }
7746 
7747     /**
7748      * Updates the designated column with a <code>RowId</code> value. The updater
7749      * methods are used to update column values in the current row or the insert
7750      * row. The updater methods do not update the underlying database; instead
7751      * the <code>updateRow<code> or <code>insertRow</code> methods are called
7752      * to update the database.
7753      *
7754      * @param columnIndex the first column is 1, the second 2, ...
7755      * @param x the column value
7756      * @throws SQLException if a database access occurs
7757      * @since 1.6
7758      */
7759     public void updateRowId(int columnIndex, RowId x) throws SQLException {
7760         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7761     }
7762 
7763     /**
7764      * Updates the designated column with a <code>RowId</code> value. The updater
7765      * methods are used to update column values in the current row or the insert
7766      * row. The updater methods do not update the underlying database; instead
7767      * the <code>updateRow<code> or <code>insertRow</code> methods are called
7768      * to update the database.
7769      *
7770      * @param columnName the name of the column
7771      * @param x the column value
7772      * @throws SQLException if a database access occurs
7773      * @since 1.6
7774      */
7775     public void updateRowId(String columnName, RowId x) throws SQLException {
7776         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7777     }
7778 
7779     /**
7780      * Retrieves the holdability of this ResultSet object
7781      * @return  either ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT
7782      * @throws SQLException if a database error occurs
7783      * @since 1.6
7784      */
7785     public int getHoldability() throws SQLException {
7786         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7787     }
7788 
7789     /**
7790      * Retrieves whether this ResultSet object has been closed. A ResultSet is closed if the
7791      * method close has been called on it, or if it is automatically closed.
7792      * @return true if this ResultSet object is closed; false if it is still open
7793      * @throws SQLException if a database access error occurs
7794      * @since 1.6
7795      */
7796     public boolean isClosed() throws SQLException {
7797         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7798     }
7799 
7800     /**
7801      * This method is used for updating columns that support National Character sets.
7802      * It can be used for updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
7803      * @param columnIndex the first column is 1, the second 2, ...
7804      * @param nString the value for the column to be updated
7805      * @throws SQLException if a database access error occurs
7806      * @since 1.6
7807      */
7808     public void updateNString(int columnIndex, String nString) throws SQLException {
7809         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7810     }
7811 
7812     /**
7813      * This method is used for updating columns that support National Character sets.
7814      * It can be used for updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
7815      * @param columnName name of the Column
7816      * @param nString the value for the column to be updated
7817      * @throws SQLException if a database access error occurs
7818      * @since 1.6
7819      */
7820     public void updateNString(String columnName, String nString) throws SQLException {
7821         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7822     }
7823 
7824 
7825     /*o
7826      * This method is used for updating SQL <code>NCLOB</code>  type that maps
7827      * to <code>java.sql.Types.NCLOB</code>
7828      * @param columnIndex the first column is 1, the second 2, ...
7829      * @param nClob the value for the column to be updated
7830      * @throws SQLException if a database access error occurs
7831      * @since 1.6
7832      */
7833     public void updateNClob(int columnIndex, NClob nClob) throws SQLException {
7834         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7835     }
7836 
7837     /**
7838      * This method is used for updating SQL <code>NCLOB</code>  type that maps
7839      * to <code>java.sql.Types.NCLOB</code>
7840      * @param columnName name of the column
7841      * @param nClob the value for the column to be updated
7842      * @throws SQLException if a database access error occurs
7843      * @since 1.6
7844      */
7845     public void updateNClob(String columnName, NClob nClob) throws SQLException {
7846        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7847     }
7848 
7849     /**
7850      * Retrieves the value of the designated column in the current row
7851      * of this <code>ResultSet</code> object as a <code>NClob</code> object
7852      * in the Java programming language.
7853      *
7854      * @param i the first column is 1, the second is 2, ...
7855      * @return a <code>NClob</code> object representing the SQL
7856      *         <code>NCLOB</code> value in the specified column
7857      * @exception SQLException if a database access error occurs
7858      * @since 1.6
7859      */
7860     public NClob getNClob(int i) throws SQLException {
7861         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7862     }
7863 
7864 
7865    /**
7866      * Retrieves the value of the designated column in the current row
7867      * of this <code>ResultSet</code> object as a <code>NClob</code> object
7868      * in the Java programming language.
7869      *
7870      * @param colName the name of the column from which to retrieve the value
7871      * @return a <code>NClob</code> object representing the SQL <code>NCLOB</code>
7872      * value in the specified column
7873      * @exception SQLException if a database access error occurs
7874      * @since 1.6
7875      */
7876     public NClob getNClob(String colName) throws SQLException {
7877         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7878     }
7879 
7880     public <T> T unwrap(java.lang.Class<T> iface) throws java.sql.SQLException {
7881         return null;
7882     }
7883 
7884     public boolean isWrapperFor(Class<?> interfaces) throws SQLException {
7885         return false;
7886     }
7887 
7888 
7889    /**
7890       * Sets the designated parameter to the given <code>java.sql.SQLXML</code> object. The driver converts this to an
7891       * SQL <code>XML</code> value when it sends it to the database.
7892       * @param parameterIndex index of the first parameter is 1, the second is 2, ...
7893       * @param xmlObject a <code>SQLXML</code> object that maps an SQL <code>XML</code> value
7894       * @throws SQLException if a database access error occurs
7895       * @since 1.6
7896       */
7897      public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
7898          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7899      }
7900 
7901    /**
7902      * Sets the designated parameter to the given <code>java.sql.SQLXML</code> object. The driver converts this to an
7903      * <code>SQL XML</code> value when it sends it to the database.
7904      * @param parameterName the name of the parameter
7905      * @param xmlObject a <code>SQLXML</code> object that maps an <code>SQL XML</code> value
7906      * @throws SQLException if a database access error occurs
7907      * @since 1.6
7908      */
7909     public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException {
7910          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7911      }
7912 
7913 
7914     /**
7915      * Sets the designated parameter to the given <code>java.sql.RowId</code> object. The
7916      * driver converts this to a SQL <code>ROWID</code> value when it sends it
7917      * to the database
7918      *
7919      * @param parameterIndex the first parameter is 1, the second is 2, ...
7920      * @param x the parameter value
7921      * @throws SQLException if a database access error occurs
7922      *
7923      * @since 1.6
7924      */
7925     public void setRowId(int parameterIndex, RowId x) throws SQLException {
7926          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7927      }
7928 
7929 
7930     /**
7931     * Sets the designated parameter to the given <code>java.sql.RowId</code> object. The
7932     * driver converts this to a SQL <code>ROWID</code> when it sends it to the
7933     * database.
7934     *
7935     * @param parameterName the name of the parameter
7936     * @param x the parameter value
7937     * @throws SQLException if a database access error occurs
7938     * @since 1.6
7939     */
7940    public void setRowId(String parameterName, RowId x) throws SQLException {
7941          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7942      }
7943 
7944 
7945     /**
7946      * Sets the designated parameter to a <code>Reader</code> object. The
7947      * <code>Reader</code> reads the data till end-of-file is reached. The
7948      * driver does the necessary conversion from Java character format to
7949      * the national character set in the database.
7950 
7951      * <P><B>Note:</B> This stream object can either be a standard
7952      * Java stream object or your own subclass that implements the
7953      * standard interface.
7954      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
7955      * it might be more efficient to use a version of
7956      * <code>setNCharacterStream</code> which takes a length parameter.
7957      *
7958      * @param parameterIndex of the first parameter is 1, the second is 2, ...
7959      * @param value the parameter value
7960      * @throws SQLException if the driver does not support national
7961      *         character sets;  if the driver can detect that a data conversion
7962      *  error could occur ; if a database access error occurs; or
7963      * this method is called on a closed <code>PreparedStatement</code>
7964      * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
7965      * @since 1.6
7966      */
7967      public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
7968         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
7969      }
7970 
7971 
7972     /**
7973     * Sets the designated parameter to a <code>java.sql.NClob</code> object. The object
7974     * implements the <code>java.sql.NClob</code> interface. This <code>NClob</code>
7975     * object maps to a SQL <code>NCLOB</code>.
7976     * @param parameterName the name of the column to be set
7977     * @param value the parameter value
7978     * @throws SQLException if the driver does not support national
7979     *         character sets;  if the driver can detect that a data conversion
7980     *  error could occur; or if a database access error occurs
7981     * @since 1.6
7982     */
7983     public void setNClob(String parameterName, NClob value) throws SQLException {
7984          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7985      }
7986 
7987 
7988   /**
7989      * Retrieves the value of the designated column in the current row
7990      * of this <code>ResultSet</code> object as a
7991      * <code>java.io.Reader</code> object.
7992      * It is intended for use when
7993      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
7994      * and <code>LONGNVARCHAR</code> columns.
7995      *
7996      * @return a <code>java.io.Reader</code> object that contains the column
7997      * value; if the value is SQL <code>NULL</code>, the value returned is
7998      * <code>null</code> in the Java programming language.
7999      * @param columnIndex the first column is 1, the second is 2, ...
8000      * @exception SQLException if a database access error occurs
8001      * @since 1.6
8002      */
8003     public java.io.Reader getNCharacterStream(int columnIndex) throws SQLException {
8004        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8005      }
8006 
8007 
8008     /**
8009      * Retrieves the value of the designated column in the current row
8010      * of this <code>ResultSet</code> object as a
8011      * <code>java.io.Reader</code> object.
8012      * It is intended for use when
8013      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8014      * and <code>LONGNVARCHAR</code> columns.
8015      *
8016      * @param columnName the name of the column
8017      * @return a <code>java.io.Reader</code> object that contains the column
8018      * value; if the value is SQL <code>NULL</code>, the value returned is
8019      * <code>null</code> in the Java programming language
8020      * @exception SQLException if a database access error occurs
8021      * @since 1.6
8022      */
8023     public java.io.Reader getNCharacterStream(String columnName) throws SQLException {
8024        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8025      }
8026 
8027 
8028     /**
8029      * Updates the designated column with a <code>java.sql.SQLXML</code> value.
8030      * The updater
8031      * methods are used to update column values in the current row or the insert
8032      * row. The updater methods do not update the underlying database; instead
8033      * the <code>updateRow</code> or <code>insertRow</code> methods are called
8034      * to update the database.
8035      * @param columnIndex the first column is 1, the second 2, ...
8036      * @param xmlObject the value for the column to be updated
8037      * @throws SQLException if a database access error occurs
8038      * @since 1.6
8039      */
8040     public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException {
8041         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8042     }
8043 
8044     /**
8045      * Updates the designated column with a <code>java.sql.SQLXML</code> value.
8046      * The updater
8047      * methods are used to update column values in the current row or the insert
8048      * row. The updater methods do not update the underlying database; instead
8049      * the <code>updateRow</code> or <code>insertRow</code> methods are called
8050      * to update the database.
8051      *
8052      * @param columnName the name of the column
8053      * @param xmlObject the column value
8054      * @throws SQLException if a database access occurs
8055      * @since 1.6
8056      */
8057     public void updateSQLXML(String columnName, SQLXML xmlObject) throws SQLException {
8058         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8059     }
8060 
8061      /**
8062      * Retrieves the value of the designated column in the current row
8063      * of this <code>ResultSet</code> object as
8064      * a <code>String</code> in the Java programming language.
8065      * It is intended for use when
8066      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8067      * and <code>LONGNVARCHAR</code> columns.
8068      *
8069      * @param columnIndex the first column is 1, the second is 2, ...
8070      * @return the column value; if the value is SQL <code>NULL</code>, the
8071      * value returned is <code>null</code>
8072      * @exception SQLException if a database access error occurs
8073      * @since 1.6
8074      */
8075     public String getNString(int columnIndex) throws SQLException {
8076         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8077     }
8078 
8079     /**
8080      * Retrieves the value of the designated column in the current row
8081      * of this <code>ResultSet</code> object as
8082      * a <code>String</code> in the Java programming language.
8083      * It is intended for use when
8084      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8085      * and <code>LONGNVARCHAR</code> columns.
8086      *
8087      * @param columnName the SQL name of the column
8088      * @return the column value; if the value is SQL <code>NULL</code>, the
8089      * value returned is <code>null</code>
8090      * @exception SQLException if a database access error occurs
8091      * @since 1.6
8092      */
8093     public String getNString(String columnName) throws SQLException {
8094         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8095     }
8096 
8097      /**
8098        * Updates the designated column with a character stream value, which will
8099        * have the specified number of bytes. The driver does the necessary conversion
8100        * from Java character format to the national character set in the database.
8101        * It is intended for use when updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
8102        * The updater methods are used to update column values in the current row or
8103        * the insert row. The updater methods do not update the underlying database;
8104        * instead the updateRow or insertRow methods are called to update the database.
8105        *
8106        * @param columnIndex - the first column is 1, the second is 2, ...
8107        * @param x - the new column value
8108        * @param length - the length of the stream
8109        * @exception SQLException if a database access error occurs
8110        * @since 1.6
8111        */
8112        public void updateNCharacterStream(int columnIndex,
8113                             java.io.Reader x,
8114                             long length)
8115                             throws SQLException {
8116           throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8117        }
8118 
8119      /**
8120        * Updates the designated column with a character stream value, which will
8121        * have the specified number of bytes. The driver does the necessary conversion
8122        * from Java character format to the national character set in the database.
8123        * It is intended for use when updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
8124        * The updater methods are used to update column values in the current row or
8125        * the insert row. The updater methods do not update the underlying database;
8126        * instead the updateRow or insertRow methods are called to update the database.
8127        *
8128        * @param columnName - name of the Column
8129        * @param x - the new column value
8130        * @param length - the length of the stream
8131        * @exception SQLException if a database access error occurs
8132        * @since 1.6
8133        */
8134        public void updateNCharacterStream(String columnName,
8135                             java.io.Reader x,
8136                             long length)
8137                             throws SQLException {
8138           throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8139        }
8140 
8141      /**
8142      * Updates the designated column with a character stream value.   The
8143      * driver does the necessary conversion from Java character format to
8144      * the national character set in the database.
8145      * It is intended for use when
8146      * updating  <code>NCHAR</code>,<code>NVARCHAR</code>
8147      * and <code>LONGNVARCHAR</code> columns.
8148      *
8149      * The updater methods are used to update column values in the
8150      * current row or the insert row.  The updater methods do not
8151      * update the underlying database; instead the <code>updateRow</code> or
8152      * <code>insertRow</code> methods are called to update the database.
8153      *
8154      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8155      * it might be more efficient to use a version of
8156      * <code>updateNCharacterStream</code> which takes a length parameter.
8157      *
8158      * @param columnIndex the first column is 1, the second is 2, ...
8159      * @param x the new column value
8160      * @exception SQLException if a database access error occurs,
8161      * the result set concurrency is <code>CONCUR_READ_ONLY</code> or this method is called on a closed result set
8162      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8163      * this method
8164      * @since 1.6
8165      */
8166     public void updateNCharacterStream(int columnIndex,
8167                              java.io.Reader x) throws SQLException {
8168         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8169     }
8170 
8171     /**
8172      * Updates the designated column with a character stream value.  The
8173      * driver does the necessary conversion from Java character format to
8174      * the national character set in the database.
8175      * It is intended for use when
8176      * updating  <code>NCHAR</code>,<code>NVARCHAR</code>
8177      * and <code>LONGNVARCHAR</code> columns.
8178      *
8179      * The updater methods are used to update column values in the
8180      * current row or the insert row.  The updater methods do not
8181      * update the underlying database; instead the <code>updateRow</code> or
8182      * <code>insertRow</code> methods are called to update the database.
8183      *
8184      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8185      * it might be more efficient to use a version of
8186      * <code>updateNCharacterStream</code> which takes a length parameter.
8187      *
8188      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8189 bel is the name of the column
8190      * @param reader the <code>java.io.Reader</code> object containing
8191      *        the new column value
8192      * @exception SQLException if a database access error occurs,
8193      * the result set concurrency is <code>CONCUR_READ_ONLY</code> or this method is called on a closed result set
8194       * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8195      * this method
8196      * @since 1.6
8197      */
8198     public void updateNCharacterStream(String columnLabel,
8199                              java.io.Reader reader) throws SQLException {
8200         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8201     }
8202 
8203 //////////////////////////
8204 
8205     /**
8206      * Updates the designated column using the given input stream, which
8207      * will have the specified number of bytes.
8208      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8209      * parameter, it may be more practical to send it via a
8210      * <code>java.io.InputStream</code>. Data will be read from the stream
8211      * as needed until end-of-file is reached.  The JDBC driver will
8212      * do any necessary conversion from ASCII to the database char format.
8213      *
8214      * <P><B>Note:</B> This stream object can either be a standard
8215      * Java stream object or your own subclass that implements the
8216      * standard interface.
8217      * <p>
8218      * The updater methods are used to update column values in the
8219      * current row or the insert row.  The updater methods do not
8220      * update the underlying database; instead the <code>updateRow</code> or
8221      * <code>insertRow</code> methods are called to update the database.
8222      *
8223      * @param columnIndex the first column is 1, the second is 2, ...
8224      * @param inputStream An object that contains the data to set the parameter
8225      * value to.
8226      * @param length the number of bytes in the parameter data.
8227      * @exception SQLException if a database access error occurs,
8228      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8229      * or this method is called on a closed result set
8230      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8231      * this method
8232      * @since 1.6
8233      */
8234     public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException{
8235         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8236     }
8237 
8238     /**
8239      * Updates the designated column using the given input stream, which
8240      * will have the specified number of bytes.
8241      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8242      * parameter, it may be more practical to send it via a
8243      * <code>java.io.InputStream</code>. Data will be read from the stream
8244      * as needed until end-of-file is reached.  The JDBC driver will
8245      * do any necessary conversion from ASCII to the database char format.
8246      *
8247      * <P><B>Note:</B> This stream object can either be a standard
8248      * Java stream object or your own subclass that implements the
8249      * standard interface.
8250      * <p>
8251      * The updater methods are used to update column values in the
8252      * current row or the insert row.  The updater methods do not
8253      * update the underlying database; instead the <code>updateRow</code> or
8254      * <code>insertRow</code> methods are called to update the database.
8255      *
8256      * @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
8257      * @param inputStream An object that contains the data to set the parameter
8258      * value to.
8259      * @param length the number of bytes in the parameter data.
8260      * @exception SQLException if a database access error occurs,
8261      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8262      * or this method is called on a closed result set
8263      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8264      * this method
8265      * @since 1.6
8266      */
8267     public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException {
8268         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8269     }
8270 
8271     /**
8272      * Updates the designated column using the given input stream.
8273      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8274      * parameter, it may be more practical to send it via a
8275      * <code>java.io.InputStream</code>. Data will be read from the stream
8276      * as needed until end-of-file is reached.  The JDBC driver will
8277      * do any necessary conversion from ASCII to the database char format.
8278      *
8279      * <P><B>Note:</B> This stream object can either be a standard
8280      * Java stream object or your own subclass that implements the
8281      * standard interface.
8282      *
8283      *  <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8284      * it might be more efficient to use a version of
8285      * <code>updateBlob</code> which takes a length parameter.
8286      * <p>
8287      * The updater methods are used to update column values in the
8288      * current row or the insert row.  The updater methods do not
8289      * update the underlying database; instead the <code>updateRow</code> or
8290      * <code>insertRow</code> methods are called to update the database.
8291      *
8292      * @param columnIndex the first column is 1, the second is 2, ...
8293      * @param inputStream An object that contains the data to set the parameter
8294      * value to.
8295      * @exception SQLException if a database access error occurs,
8296      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8297      * or this method is called on a closed result set
8298      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8299      * this method
8300      * @since 1.6
8301      */
8302     public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException {
8303         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8304     }
8305 
8306     /**
8307      * Updates the designated column using the given input stream.
8308      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8309      * parameter, it may be more practical to send it via a
8310      * <code>java.io.InputStream</code>. Data will be read from the stream
8311      * as needed until end-of-file is reached.  The JDBC driver will
8312      * do any necessary conversion from ASCII to the database char format.
8313      *
8314      * <P><B>Note:</B> This stream object can either be a standard
8315      * Java stream object or your own subclass that implements the
8316      * standard interface.
8317      *   <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8318      * it might be more efficient to use a version of
8319      * <code>updateBlob</code> which takes a length parameter.
8320      * <p>
8321      * The updater methods are used to update column values in the
8322      * current row or the insert row.  The updater methods do not
8323      * update the underlying database; instead the <code>updateRow</code> or
8324      * <code>insertRow</code> methods are called to update the database.
8325      *
8326      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8327 bel is the name of the column
8328      * @param inputStream An object that contains the data to set the parameter
8329      * value to.
8330      * @exception SQLException if a database access error occurs,
8331      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8332      * or this method is called on a closed result set
8333      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8334      * this method
8335      * @since 1.6
8336      */
8337     public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException {
8338         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8339     }
8340 
8341     /**
8342      * Updates the designated column using the given <code>Reader</code>
8343      * object, which is the given number of characters long.
8344      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8345      * parameter, it may be more practical to send it via a
8346      * <code>java.io.Reader</code> object. The data will be read from the stream
8347      * as needed until end-of-file is reached.  The JDBC driver will
8348      * do any necessary conversion from UNICODE to the database char format.
8349      *
8350      * <P><B>Note:</B> This stream object can either be a standard
8351      * Java stream object or your own subclass that implements the
8352      * standard interface.
8353      * <p>
8354      * The updater methods are used to update column values in the
8355      * current row or the insert row.  The updater methods do not
8356      * update the underlying database; instead the <code>updateRow</code> or
8357      * <code>insertRow</code> methods are called to update the database.
8358      *
8359      * @param columnIndex the first column is 1, the second is 2, ...
8360      * @param reader An object that contains the data to set the parameter value to.
8361      * @param length the number of characters in the parameter data.
8362      * @exception SQLException if a database access error occurs,
8363      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8364      * or this method is called on a closed result set
8365      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8366      * this method
8367      * @since 1.6
8368      */
8369     public void updateClob(int columnIndex,  Reader reader, long length) throws SQLException {
8370         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8371     }
8372 
8373     /**
8374      * Updates the designated column using the given <code>Reader</code>
8375      * object, which is the given number of characters long.
8376      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8377      * parameter, it may be more practical to send it via a
8378      * <code>java.io.Reader</code> object. The data will be read from the stream
8379      * as needed until end-of-file is reached.  The JDBC driver will
8380      * do any necessary conversion from UNICODE to the database char format.
8381      *
8382      * <P><B>Note:</B> This stream object can either be a standard
8383      * Java stream object or your own subclass that implements the
8384      * standard interface.
8385      * <p>
8386      * The updater methods are used to update column values in the
8387      * current row or the insert row.  The updater methods do not
8388      * update the underlying database; instead the <code>updateRow</code> or
8389      * <code>insertRow</code> methods are called to update the database.
8390      *
8391      * @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
8392      * @param reader An object that contains the data to set the parameter value to.
8393      * @param length the number of characters in the parameter data.
8394      * @exception SQLException if a database access error occurs,
8395      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8396      * or this method is called on a closed result set
8397      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8398      * this method
8399      * @since 1.6
8400      */
8401     public void updateClob(String columnLabel,  Reader reader, long length) throws SQLException {
8402         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8403     }
8404 
8405    /**
8406      * Updates the designated column using the given <code>Reader</code>
8407      * object.
8408      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8409      * parameter, it may be more practical to send it via a
8410      * <code>java.io.Reader</code> object. The data will be read from the stream
8411      * as needed until end-of-file is reached.  The JDBC driver will
8412      * do any necessary conversion from UNICODE to the database char format.
8413      *
8414      * <P><B>Note:</B> This stream object can either be a standard
8415      * Java stream object or your own subclass that implements the
8416      * standard interface.
8417      *   <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8418      * it might be more efficient to use a version of
8419      * <code>updateClob</code> which takes a length parameter.
8420      * <p>
8421      * The updater methods are used to update column values in the
8422      * current row or the insert row.  The updater methods do not
8423      * update the underlying database; instead the <code>updateRow</code> or
8424      * <code>insertRow</code> methods are called to update the database.
8425      *
8426      * @param columnIndex the first column is 1, the second is 2, ...
8427      * @param reader An object that contains the data to set the parameter value to.
8428      * @exception SQLException if a database access error occurs,
8429      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8430      * or this method is called on a closed result set
8431      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8432      * this method
8433      * @since 1.6
8434      */
8435     public void updateClob(int columnIndex,  Reader reader) throws SQLException {
8436         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8437     }
8438 
8439     /**
8440      * Updates the designated column using the given <code>Reader</code>
8441      * object.
8442      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8443      * parameter, it may be more practical to send it via a
8444      * <code>java.io.Reader</code> object. The data will be read from the stream
8445      * as needed until end-of-file is reached.  The JDBC driver will
8446      * do any necessary conversion from UNICODE to the database char format.
8447      *
8448      * <P><B>Note:</B> This stream object can either be a standard
8449      * Java stream object or your own subclass that implements the
8450      * standard interface.
8451      *  <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8452      * it might be more efficient to use a version of
8453      * <code>updateClob</code> which takes a length parameter.
8454      * <p>
8455      * The updater methods are used to update column values in the
8456      * current row or the insert row.  The updater methods do not
8457      * update the underlying database; instead the <code>updateRow</code> or
8458      * <code>insertRow</code> methods are called to update the database.
8459      *
8460      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8461 bel is the name of the column
8462      * @param reader An object that contains the data to set the parameter value to.
8463      * @exception SQLException if a database access error occurs,
8464      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8465      * or this method is called on a closed result set
8466      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8467      * this method
8468      * @since 1.6
8469      */
8470     public void updateClob(String columnLabel,  Reader reader) throws SQLException {
8471         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8472     }
8473 
8474    /**
8475      * Updates the designated column using the given <code>Reader</code>
8476      * object, which is the given number of characters long.
8477      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8478      * parameter, it may be more practical to send it via a
8479      * <code>java.io.Reader</code> object. The data will be read from the stream
8480      * as needed until end-of-file is reached.  The JDBC driver will
8481      * do any necessary conversion from UNICODE to the database char format.
8482      *
8483      * <P><B>Note:</B> This stream object can either be a standard
8484      * Java stream object or your own subclass that implements the
8485      * standard interface.
8486      * <p>
8487      * The updater methods are used to update column values in the
8488      * current row or the insert row.  The updater methods do not
8489      * update the underlying database; instead the <code>updateRow</code> or
8490      * <code>insertRow</code> methods are called to update the database.
8491      *
8492      * @param columnIndex the first column is 1, the second 2, ...
8493      * @param reader An object that contains the data to set the parameter value to.
8494      * @param length the number of characters in the parameter data.
8495      * @throws SQLException if the driver does not support national
8496      *         character sets;  if the driver can detect that a data conversion
8497      *  error could occur; this method is called on a closed result set,
8498      * if a database access error occurs or
8499      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8500      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8501      * this method
8502      * @since 1.6
8503      */
8504     public void updateNClob(int columnIndex,  Reader reader, long length) throws SQLException {
8505         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8506     }
8507 
8508     /**
8509      * Updates the designated column using the given <code>Reader</code>
8510      * object, which is the given number of characters long.
8511      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8512      * parameter, it may be more practical to send it via a
8513      * <code>java.io.Reader</code> object. The data will be read from the stream
8514      * as needed until end-of-file is reached.  The JDBC driver will
8515      * do any necessary conversion from UNICODE to the database char format.
8516      *
8517      * <P><B>Note:</B> This stream object can either be a standard
8518      * Java stream object or your own subclass that implements the
8519      * standard interface.
8520      * <p>
8521      * The updater methods are used to update column values in the
8522      * current row or the insert row.  The updater methods do not
8523      * update the underlying database; instead the <code>updateRow</code> or
8524      * <code>insertRow</code> methods are called to update the database.
8525      *
8526      * @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
8527      * @param reader An object that contains the data to set the parameter value to.
8528      * @param length the number of characters in the parameter data.
8529      * @throws SQLException if the driver does not support national
8530      *         character sets;  if the driver can detect that a data conversion
8531      *  error could occur; this method is called on a closed result set;
8532      *  if a database access error occurs or
8533      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8534      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8535      * this method
8536      * @since 1.6
8537      */
8538     public void updateNClob(String columnLabel,  Reader reader, long length) throws SQLException {
8539         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8540     }
8541 
8542     /**
8543      * Updates the designated column using the given <code>Reader</code>
8544      * object.
8545      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8546      * parameter, it may be more practical to send it via a
8547      * <code>java.io.Reader</code> object. The data will be read from the stream
8548      * as needed until end-of-file is reached.  The JDBC driver will
8549      * do any necessary conversion from UNICODE to the database char format.
8550      *
8551      * <P><B>Note:</B> This stream object can either be a standard
8552      * Java stream object or your own subclass that implements the
8553      * standard interface.
8554      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8555      * it might be more efficient to use a version of
8556      * <code>updateNClob</code> which takes a length parameter.
8557      * <p>
8558      * The updater methods are used to update column values in the
8559      * current row or the insert row.  The updater methods do not
8560      * update the underlying database; instead the <code>updateRow</code> or
8561      * <code>insertRow</code> methods are called to update the database.
8562      *
8563      * @param columnIndex the first column is 1, the second 2, ...
8564      * @param reader An object that contains the data to set the parameter value to.
8565      * @throws SQLException if the driver does not support national
8566      *         character sets;  if the driver can detect that a data conversion
8567      *  error could occur; this method is called on a closed result set,
8568      * if a database access error occurs or
8569      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8570      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8571      * this method
8572      * @since 1.6
8573      */
8574     public void updateNClob(int columnIndex,  Reader reader) throws SQLException {
8575         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8576     }
8577 
8578     /**
8579      * Updates the designated column using the given <code>Reader</code>
8580      * object.
8581      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8582      * parameter, it may be more practical to send it via a
8583      * <code>java.io.Reader</code> object. The data will be read from the stream
8584      * as needed until end-of-file is reached.  The JDBC driver will
8585      * do any necessary conversion from UNICODE to the database char format.
8586      *
8587      * <P><B>Note:</B> This stream object can either be a standard
8588      * Java stream object or your own subclass that implements the
8589      * standard interface.
8590      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8591      * it might be more efficient to use a version of
8592      * <code>updateNClob</code> which takes a length parameter.
8593      * <p>
8594      * The updater methods are used to update column values in the
8595      * current row or the insert row.  The updater methods do not
8596      * update the underlying database; instead the <code>updateRow</code> or
8597      * <code>insertRow</code> methods are called to update the database.
8598      *
8599      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8600 bel is the name of the column
8601      * @param reader An object that contains the data to set the parameter value to.
8602      * @throws SQLException if the driver does not support national
8603      *         character sets;  if the driver can detect that a data conversion
8604      *  error could occur; this method is called on a closed result set;
8605      *  if a database access error occurs or
8606      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8607      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8608      * this method
8609      * @since 1.6
8610      */
8611     public void updateNClob(String columnLabel,  Reader reader) throws SQLException {
8612         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8613     }
8614 
8615         /**
8616      * Updates the designated column with an ascii stream value, which will have
8617      * the specified number of bytes.
8618      * The updater methods are used to update column values in the
8619      * current row or the insert row.  The updater methods do not
8620      * update the underlying database; instead the <code>updateRow</code> or
8621      * <code>insertRow</code> methods are called to update the database.
8622      *
8623      * @param columnIndex the first column is 1, the second is 2, ...
8624      * @param x the new column value
8625      * @param length the length of the stream
8626      * @exception SQLException if a database access error occurs,
8627      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8628      * or this method is called on a closed result set
8629      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8630      * this method
8631      * @since 1.6
8632      */
8633     public void updateAsciiStream(int columnIndex,
8634                            java.io.InputStream x,
8635                            long length) throws SQLException {
8636 
8637     }
8638 
8639     /**
8640      * Updates the designated column with a binary stream value, which will have
8641      * the specified number of bytes.
8642      * The updater methods are used to update column values in the
8643      * current row or the insert row.  The updater methods do not
8644      * update the underlying database; instead the <code>updateRow</code> or
8645      * <code>insertRow</code> methods are called to update the database.
8646      *
8647      * @param columnIndex the first column is 1, the second is 2, ...
8648      * @param x the new column value
8649      * @param length the length of the stream
8650      * @exception SQLException if a database access error occurs,
8651      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8652      * or this method is called on a closed result set
8653      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8654      * this method
8655      * @since 1.6
8656      */
8657     public void updateBinaryStream(int columnIndex,
8658                             java.io.InputStream x,
8659                             long length) throws SQLException {
8660     }
8661 
8662     /**
8663      * Updates the designated column with a character stream value, which will have
8664      * the specified number of bytes.
8665      * The updater methods are used to update column values in the
8666      * current row or the insert row.  The updater methods do not
8667      * update the underlying database; instead the <code>updateRow</code> or
8668      * <code>insertRow</code> methods are called to update the database.
8669      *
8670      * @param columnIndex the first column is 1, the second is 2, ...
8671      * @param x the new column value
8672      * @param length the length of the stream
8673      * @exception SQLException if a database access error occurs,
8674      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8675      * or this method is called on a closed result set
8676      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8677      * this method
8678      * @since 1.6
8679      */
8680     public void updateCharacterStream(int columnIndex,
8681                              java.io.Reader x,
8682                              long length) throws SQLException {
8683         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8684     }
8685 
8686     /**
8687      * Updates the designated column with a character stream value, which will have
8688      * the specified number of bytes.
8689      * The updater methods are used to update column values in the
8690      * current row or the insert row.  The updater methods do not
8691      * update the underlying database; instead the <code>updateRow</code> or
8692      * <code>insertRow</code> methods are called to update the database.
8693      *
8694      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8695 bel is the name of the column
8696      * @param reader the <code>java.io.Reader</code> object containing
8697      *        the new column value
8698      * @param length the length of the stream
8699      * @exception SQLException if a database access error occurs,
8700      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8701      * or this method is called on a closed result set
8702      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8703      * this method
8704      * @since 1.6
8705      */
8706     public void updateCharacterStream(String columnLabel,
8707                              java.io.Reader reader,
8708                              long length) throws SQLException {
8709         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8710     }
8711      /**
8712      * Updates the designated column with an ascii stream value, which will have
8713      * the specified number of bytes..
8714      * The updater methods are used to update column values in the
8715      * current row or the insert row.  The updater methods do not
8716      * update the underlying database; instead the <code>updateRow</code> or
8717      * <code>insertRow</code> methods are called to update the database.
8718      *
8719      * @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
8720      * @param x the new column value
8721      * @param length the length of the stream
8722      * @exception SQLException if a database access error occurs,
8723      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8724      * or this method is called on a closed result set
8725      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8726      * this method
8727      * @since 1.6
8728      */
8729     public void updateAsciiStream(String columnLabel,
8730                            java.io.InputStream x,
8731                            long length) throws SQLException {
8732     }
8733 
8734     /**
8735      * Updates the designated column with a binary stream value, which will have
8736      * the specified number of bytes.
8737      * The updater methods are used to update column values in the
8738      * current row or the insert row.  The updater methods do not
8739      * update the underlying database; instead the <code>updateRow</code> or
8740      * <code>insertRow</code> methods are called to update the database.
8741      *
8742      * @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
8743      * @param x the new column value
8744      * @param length the length of the stream
8745      * @exception SQLException if a database access error occurs,
8746      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8747      * or this method is called on a closed result set
8748      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8749      * this method
8750      * @since 1.6
8751      */
8752     public void updateBinaryStream(String columnLabel,
8753                             java.io.InputStream x,
8754                             long length) throws SQLException {
8755     }
8756 
8757     /**
8758      * Updates the designated column with a binary stream value.
8759      * The updater methods are used to update column values in the
8760      * current row or the insert row.  The updater methods do not
8761      * update the underlying database; instead the <code>updateRow</code> or
8762      * <code>insertRow</code> methods are called to update the database.
8763      *
8764      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8765      * it might be more efficient to use a version of
8766      * <code>updateBinaryStream</code> which takes a length parameter.
8767      *
8768      * @param columnIndex the first column is 1, the second is 2, ...
8769      * @param x the new column value
8770      * @exception SQLException if a database access error occurs,
8771      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8772      * or this method is called on a closed result set
8773      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8774      * this method
8775      * @since 1.6
8776      */
8777     public void updateBinaryStream(int columnIndex,
8778                             java.io.InputStream x) throws SQLException {
8779         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8780     }
8781 
8782 
8783     /**
8784      * Updates the designated column with a binary stream value.
8785      * The updater methods are used to update column values in the
8786      * current row or the insert row.  The updater methods do not
8787      * update the underlying database; instead the <code>updateRow</code> or
8788      * <code>insertRow</code> methods are called to update the database.
8789      *
8790      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8791      * it might be more efficient to use a version of
8792      * <code>updateBinaryStream</code> which takes a length parameter.
8793      *
8794      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8795 bel is the name of the column
8796      * @param x the new column value
8797      * @exception SQLException if a database access error occurs,
8798      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8799      * or this method is called on a closed result set
8800      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8801      * this method
8802      * @since 1.6
8803      */
8804     public void updateBinaryStream(String columnLabel,
8805                             java.io.InputStream x) throws SQLException {
8806         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8807     }
8808 
8809     /**
8810      * Updates the designated column with a character stream value.
8811      * The updater methods are used to update column values in the
8812      * current row or the insert row.  The updater methods do not
8813      * update the underlying database; instead the <code>updateRow</code> or
8814      * <code>insertRow</code> methods are called to update the database.
8815      *
8816      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8817      * it might be more efficient to use a version of
8818      * <code>updateCharacterStream</code> which takes a length parameter.
8819      *
8820      * @param columnIndex the first column is 1, the second is 2, ...
8821      * @param x the new column value
8822      * @exception SQLException if a database access error occurs,
8823      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8824      * or this method is called on a closed result set
8825      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8826      * this method
8827      * @since 1.6
8828      */
8829     public void updateCharacterStream(int columnIndex,
8830                              java.io.Reader x) throws SQLException {
8831         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8832     }
8833 
8834     /**
8835      * Updates the designated column with a character stream value.
8836      * The updater methods are used to update column values in the
8837      * current row or the insert row.  The updater methods do not
8838      * update the underlying database; instead the <code>updateRow</code> or
8839      * <code>insertRow</code> methods are called to update the database.
8840      *
8841      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8842      * it might be more efficient to use a version of
8843      * <code>updateCharacterStream</code> which takes a length parameter.
8844      *
8845      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8846 bel is the name of the column
8847      * @param reader the <code>java.io.Reader</code> object containing
8848      *        the new column value
8849      * @exception SQLException if a database access error occurs,
8850      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8851      * or this method is called on a closed result set
8852      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8853      * this method
8854      * @since 1.6
8855      */
8856     public void updateCharacterStream(String columnLabel,
8857                              java.io.Reader reader) throws SQLException {
8858         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8859     }
8860 
8861     /**
8862      * Updates the designated column with an ascii stream value.
8863      * The updater methods are used to update column values in the
8864      * current row or the insert row.  The updater methods do not
8865      * update the underlying database; instead the <code>updateRow</code> or
8866      * <code>insertRow</code> methods are called to update the database.
8867      *
8868      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8869      * it might be more efficient to use a version of
8870      * <code>updateAsciiStream</code> which takes a length parameter.
8871      *
8872      * @param columnIndex the first column is 1, the second is 2, ...
8873      * @param x the new column value
8874      * @exception SQLException if a database access error occurs,
8875      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8876      * or this method is called on a closed result set
8877      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8878      * this method
8879      * @since 1.6
8880      */
8881     public void updateAsciiStream(int columnIndex,
8882                            java.io.InputStream x) throws SQLException {
8883         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8884     }
8885 
8886     /**
8887      * Updates the designated column with an ascii stream value.
8888      * The updater methods are used to update column values in the
8889      * current row or the insert row.  The updater methods do not
8890      * update the underlying database; instead the <code>updateRow</code> or
8891      * <code>insertRow</code> methods are called to update the database.
8892      *
8893      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8894      * it might be more efficient to use a version of
8895      * <code>updateAsciiStream</code> which takes a length parameter.
8896      *
8897      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8898 bel is the name of the column
8899      * @param x the new column value
8900      * @exception SQLException if a database access error occurs,
8901      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8902      * or this method is called on a closed result set
8903      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8904      * this method
8905      * @since 1.6
8906      */
8907     public void updateAsciiStream(String columnLabel,
8908                            java.io.InputStream x) throws SQLException {
8909 
8910     }
8911 
8912    /**
8913   * Sets the designated parameter to the given <code>java.net.URL</code> value.
8914   * The driver converts this to an SQL <code>DATALINK</code> value
8915   * when it sends it to the database.
8916   *
8917   * @param parameterIndex the first parameter is 1, the second is 2, ...
8918   * @param x the <code>java.net.URL</code> object to be set
8919   * @exception SQLException if a database access error occurs or
8920   * this method is called on a closed <code>PreparedStatement</code>
8921   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
8922   * @since 1.4
8923   */
8924   public void setURL(int parameterIndex, java.net.URL x) throws SQLException{
8925         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8926    }
8927 
8928   /**
8929   * Sets the designated parameter to a <code>Reader</code> object.
8930   * This method differs from the <code>setCharacterStream (int, Reader)</code> method
8931   * because it informs the driver that the parameter value should be sent to
8932   * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
8933   * driver may have to do extra work to determine whether the parameter
8934   * data should be sent to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
8935   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8936   * it might be more efficient to use a version of
8937   * <code>setNClob</code> which takes a length parameter.
8938   *
8939   * @param parameterIndex index of the first parameter is 1, the second is 2, ...
8940   * @param reader An object that contains the data to set the parameter value to.
8941   * @throws SQLException if parameterIndex does not correspond to a parameter
8942   * marker in the SQL statement;
8943   * if the driver does not support national character sets;
8944   * if the driver can detect that a data conversion
8945   *  error could occur;  if a database access error occurs or
8946   * this method is called on a closed <code>PreparedStatement</code>
8947   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
8948   *
8949   * @since 1.6
8950   */
8951   public void setNClob(int parameterIndex, Reader reader)
8952     throws SQLException{
8953         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8954    }
8955 
8956   /**
8957   * Sets the designated parameter to a <code>Reader</code> object.  The <code>reader</code> must contain  the number
8958              * of characters specified by length otherwise a <code>SQLException</code> will be
8959             * generated when the <code>CallableStatement</code> is executed.
8960             * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
8961             * because it informs the driver that the parameter value should be sent to
8962             * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
8963             * driver may have to do extra work to determine whether the parameter
8964             * data should be send to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
8965             *
8966             * @param parameterName the name of the parameter to be set
8967             * @param reader An object that contains the data to set the parameter value to.
8968             * @param length the number of characters in the parameter data.
8969             * @throws SQLException if parameterIndex does not correspond to a parameter
8970             * marker in the SQL statement; if the length specified is less than zero;
8971             * if the driver does not support national
8972             *         character sets;  if the driver can detect that a data conversion
8973             *  error could occur; if a database access error occurs or
8974             * this method is called on a closed <code>CallableStatement</code>
8975             * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8976             * this method
8977             * @since 1.6
8978             */
8979             public void setNClob(String parameterName, Reader reader, long length)
8980     throws SQLException{
8981         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8982    }
8983 
8984 
8985  /**
8986   * Sets the designated parameter to a <code>Reader</code> object.
8987   * This method differs from the <code>setCharacterStream (int, Reader)</code> method
8988   * because it informs the driver that the parameter value should be sent to
8989   * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
8990   * driver may have to do extra work to determine whether the parameter
8991   * data should be send to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
8992   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8993   * it might be more efficient to use a version of
8994   * <code>setNClob</code> which takes a length parameter.
8995   *
8996   * @param parameterName the name of the parameter
8997   * @param reader An object that contains the data to set the parameter value to.
8998   * @throws SQLException if the driver does not support national character sets;
8999   * if the driver can detect that a data conversion
9000   *  error could occur;  if a database access error occurs or
9001   * this method is called on a closed <code>CallableStatement</code>
9002   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9003   *
9004   * @since 1.6
9005   */
9006   public void setNClob(String parameterName, Reader reader)
9007     throws SQLException{
9008         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9009    }
9010 
9011 
9012     /**
9013      * Sets the designated parameter to a <code>Reader</code> object.  The reader must contain  the number
9014      * of characters specified by length otherwise a <code>SQLException</code> will be
9015      * generated when the <code>PreparedStatement</code> is executed.
9016      * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
9017      * because it informs the driver that the parameter value should be sent to
9018      * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9019      * driver may have to do extra work to determine whether the parameter
9020      * data should be sent to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
9021      * @param parameterIndex index of the first parameter is 1, the second is 2, ...
9022      * @param reader An object that contains the data to set the parameter value to.
9023      * @param length the number of characters in the parameter data.
9024      * @throws SQLException if parameterIndex does not correspond to a parameter
9025      * marker in the SQL statement; if the length specified is less than zero;
9026      * if the driver does not support national character sets;
9027      * if the driver can detect that a data conversion
9028      *  error could occur;  if a database access error occurs or
9029      * this method is called on a closed <code>PreparedStatement</code>
9030      * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9031      *
9032      * @since 1.6
9033      */
9034      public void setNClob(int parameterIndex, Reader reader, long length)
9035        throws SQLException{
9036         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9037    }
9038 
9039 
9040     /**
9041      * Sets the designated parameter to a <code>java.sql.NClob</code> object. The driver converts this to
9042 a
9043      * SQL <code>NCLOB</code> value when it sends it to the database.
9044      * @param parameterIndex of the first parameter is 1, the second is 2, ...
9045      * @param value the parameter value
9046      * @throws SQLException if the driver does not support national
9047      *         character sets;  if the driver can detect that a data conversion
9048      *  error could occur ; or if a database access error occurs
9049      * @since 1.6
9050      */
9051      public void setNClob(int parameterIndex, NClob value) throws SQLException{
9052         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9053    }
9054 
9055 
9056    /**
9057   * Sets the designated parameter to the given <code>String</code> object.
9058   * The driver converts this to a SQL <code>NCHAR</code> or
9059   * <code>NVARCHAR</code> or <code>LONGNVARCHAR</code> value
9060   * (depending on the argument's
9061   * size relative to the driver's limits on <code>NVARCHAR</code> values)
9062   * when it sends it to the database.
9063   *
9064   * @param parameterIndex of the first parameter is 1, the second is 2, ...
9065   * @param value the parameter value
9066   * @throws SQLException if the driver does not support national
9067   *         character sets;  if the driver can detect that a data conversion
9068   *  error could occur ; or if a database access error occurs
9069   * @since 1.6
9070   */
9071   public void setNString(int parameterIndex, String value) throws SQLException{
9072         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9073    }
9074 
9075 
9076  /**
9077   * Sets the designated parameter to the given <code>String</code> object.
9078   * The driver converts this to a SQL <code>NCHAR</code> or
9079   * <code>NVARCHAR</code> or <code>LONGNVARCHAR</code>
9080   * @param parameterName the name of the column to be set
9081   * @param value the parameter value
9082   * @throws SQLException if the driver does not support national
9083   *         character sets;  if the driver can detect that a data conversion
9084   *  error could occur; or if a database access error occurs
9085   * @since 1.6
9086   */
9087  public void setNString(String parameterName, String value)
9088          throws SQLException{
9089         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9090    }
9091 
9092 
9093  /**
9094   * Sets the designated parameter to a <code>Reader</code> object. The
9095   * <code>Reader</code> reads the data till end-of-file is reached. The
9096   * driver does the necessary conversion from Java character format to
9097   * the national character set in the database.
9098   * @param parameterIndex of the first parameter is 1, the second is 2, ...
9099   * @param value the parameter value
9100   * @param length the number of characters in the parameter data.
9101   * @throws SQLException if the driver does not support national
9102   *         character sets;  if the driver can detect that a data conversion
9103   *  error could occur ; or if a database access error occurs
9104   * @since 1.6
9105   */
9106   public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException{
9107         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9108    }
9109 
9110 
9111  /**
9112   * Sets the designated parameter to a <code>Reader</code> object. The
9113   * <code>Reader</code> reads the data till end-of-file is reached. The
9114   * driver does the necessary conversion from Java character format to
9115   * the national character set in the database.
9116   * @param parameterName the name of the column to be set
9117   * @param value the parameter value
9118   * @param length the number of characters in the parameter data.
9119   * @throws SQLException if the driver does not support national
9120   *         character sets;  if the driver can detect that a data conversion
9121   *  error could occur; or if a database access error occurs
9122   * @since 1.6
9123   */
9124  public void setNCharacterStream(String parameterName, Reader value, long length)
9125          throws SQLException{
9126         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9127    }
9128 
9129   /**
9130   * Sets the designated parameter to a <code>Reader</code> object. The
9131   * <code>Reader</code> reads the data till end-of-file is reached. The
9132   * driver does the necessary conversion from Java character format to
9133   * the national character set in the database.
9134 
9135   * <P><B>Note:</B> This stream object can either be a standard
9136   * Java stream object or your own subclass that implements the
9137   * standard interface.
9138   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9139   * it might be more efficient to use a version of
9140   * <code>setNCharacterStream</code> which takes a length parameter.
9141   *
9142   * @param parameterName the name of the parameter
9143   * @param value the parameter value
9144   * @throws SQLException if the driver does not support national
9145   *         character sets;  if the driver can detect that a data conversion
9146   *  error could occur ; if a database access error occurs; or
9147   * this method is called on a closed <code>CallableStatement</code>
9148   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9149   * @since 1.6
9150   */
9151   public void setNCharacterStream(String parameterName, Reader value) throws SQLException{
9152         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9153    }
9154 
9155   /**
9156     * Sets the designated parameter to the given <code>java.sql.Timestamp</code> value,
9157     * using the given <code>Calendar</code> object.  The driver uses
9158     * the <code>Calendar</code> object to construct an SQL <code>TIMESTAMP</code> value,
9159     * which the driver then sends to the database.  With a
9160     * a <code>Calendar</code> object, the driver can calculate the timestamp
9161     * taking into account a custom timezone.  If no
9162     * <code>Calendar</code> object is specified, the driver uses the default
9163     * timezone, which is that of the virtual machine running the application.
9164     *
9165     * @param parameterName the name of the parameter
9166     * @param x the parameter value
9167     * @param cal the <code>Calendar</code> object the driver will use
9168     *            to construct the timestamp
9169     * @exception SQLException if a database access error occurs or
9170     * this method is called on a closed <code>CallableStatement</code>
9171     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9172     * this method
9173     * @see #getTimestamp
9174     * @since 1.4
9175     */
9176     public void setTimestamp(String parameterName, java.sql.Timestamp x, Calendar cal)
9177        throws SQLException{
9178         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9179    }
9180 
9181     /**
9182     * Sets the designated parameter to a <code>Reader</code> object.  The <code>reader</code> must contain  the number
9183                * of characters specified by length otherwise a <code>SQLException</code> will be
9184                * generated when the <code>CallableStatement</code> is executed.
9185               * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
9186               * because it informs the driver that the parameter value should be sent to
9187               * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9188               * driver may have to do extra work to determine whether the parameter
9189               * data should be send to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9190               * @param parameterName the name of the parameter to be set
9191               * @param reader An object that contains the data to set the parameter value to.
9192               * @param length the number of characters in the parameter data.
9193               * @throws SQLException if parameterIndex does not correspond to a parameter
9194               * marker in the SQL statement; if the length specified is less than zero;
9195               * a database access error occurs or
9196               * this method is called on a closed <code>CallableStatement</code>
9197               * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9198               * this method
9199               *
9200               * @since 1.6
9201               */
9202       public  void setClob(String parameterName, Reader reader, long length)
9203       throws SQLException{
9204         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9205    }
9206 
9207 
9208   /**
9209     * Sets the designated parameter to the given <code>java.sql.Clob</code> object.
9210     * The driver converts this to an SQL <code>CLOB</code> value when it
9211     * sends it to the database.
9212     *
9213     * @param parameterName the name of the parameter
9214     * @param x a <code>Clob</code> object that maps an SQL <code>CLOB</code> value
9215     * @exception SQLException if a database access error occurs or
9216     * this method is called on a closed <code>CallableStatement</code>
9217     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9218     * this method
9219     * @since 1.6
9220     */
9221     public void setClob (String parameterName, Clob x) throws SQLException{
9222         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9223    }
9224 
9225 
9226  /**
9227     * Sets the designated parameter to a <code>Reader</code> object.
9228     * This method differs from the <code>setCharacterStream (int, Reader)</code> method
9229     * because it informs the driver that the parameter value should be sent to
9230     * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9231     * driver may have to do extra work to determine whether the parameter
9232     * data should be send to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9233     *
9234     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9235     * it might be more efficient to use a version of
9236     * <code>setClob</code> which takes a length parameter.
9237     *
9238     * @param parameterName the name of the parameter
9239     * @param reader An object that contains the data to set the parameter value to.
9240     * @throws SQLException if a database access error occurs or this method is called on
9241     * a closed <code>CallableStatement</code>
9242     *
9243     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9244     * @since 1.6
9245     */
9246     public void setClob(String parameterName, Reader reader)
9247       throws SQLException{
9248         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9249    }
9250 
9251 
9252  /**
9253     * Sets the designated parameter to the given <code>java.sql.Date</code> value
9254     * using the default time zone of the virtual machine that is running
9255     * the application.
9256     * The driver converts this
9257     * to an SQL <code>DATE</code> value when it sends it to the database.
9258     *
9259     * @param parameterName the name of the parameter
9260     * @param x the parameter value
9261     * @exception SQLException if a database access error occurs or
9262     * this method is called on a closed <code>CallableStatement</code>
9263     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9264     * this method
9265     * @see #getDate
9266     * @since 1.4
9267     */
9268     public void setDate(String parameterName, java.sql.Date x)
9269        throws SQLException{
9270         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9271    }
9272 
9273 
9274  /**
9275     * Sets the designated parameter to the given <code>java.sql.Date</code> value,
9276     * using the given <code>Calendar</code> object.  The driver uses
9277     * the <code>Calendar</code> object to construct an SQL <code>DATE</code> value,
9278     * which the driver then sends to the database.  With a
9279     * a <code>Calendar</code> object, the driver can calculate the date
9280     * taking into account a custom timezone.  If no
9281     * <code>Calendar</code> object is specified, the driver uses the default
9282     * timezone, which is that of the virtual machine running the application.
9283     *
9284     * @param parameterName the name of the parameter
9285     * @param x the parameter value
9286     * @param cal the <code>Calendar</code> object the driver will use
9287     *            to construct the date
9288     * @exception SQLException if a database access error occurs or
9289     * this method is called on a closed <code>CallableStatement</code>
9290     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9291     * this method
9292     * @see #getDate
9293     * @since 1.4
9294     */
9295    public void setDate(String parameterName, java.sql.Date x, Calendar cal)
9296        throws SQLException{
9297         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9298    }
9299 
9300 
9301  /**
9302     * Sets the designated parameter to the given <code>java.sql.Time</code> value.
9303     * The driver converts this
9304     * to an SQL <code>TIME</code> value when it sends it to the database.
9305     *
9306     * @param parameterName the name of the parameter
9307     * @param x the parameter value
9308     * @exception SQLException if a database access error occurs or
9309     * this method is called on a closed <code>CallableStatement</code>
9310     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9311     * this method
9312     * @see #getTime
9313     * @since 1.4
9314     */
9315    public void setTime(String parameterName, java.sql.Time x)
9316        throws SQLException{
9317         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9318    }
9319 
9320 
9321  /**
9322     * Sets the designated parameter to the given <code>java.sql.Time</code> value,
9323     * using the given <code>Calendar</code> object.  The driver uses
9324     * the <code>Calendar</code> object to construct an SQL <code>TIME</code> value,
9325     * which the driver then sends to the database.  With a
9326     * a <code>Calendar</code> object, the driver can calculate the time
9327     * taking into account a custom timezone.  If no
9328     * <code>Calendar</code> object is specified, the driver uses the default
9329     * timezone, which is that of the virtual machine running the application.
9330     *
9331     * @param parameterName the name of the parameter
9332     * @param x the parameter value
9333     * @param cal the <code>Calendar</code> object the driver will use
9334     *            to construct the time
9335     * @exception SQLException if a database access error occurs or
9336     * this method is called on a closed <code>CallableStatement</code>
9337     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9338     * this method
9339     * @see #getTime
9340     * @since 1.4
9341     */
9342    public void setTime(String parameterName, java.sql.Time x, Calendar cal)
9343        throws SQLException{
9344         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9345    }
9346 
9347    /**
9348    * Sets the designated parameter to a <code>Reader</code> object.
9349    * This method differs from the <code>setCharacterStream (int, Reader)</code> method
9350    * because it informs the driver that the parameter value should be sent to
9351    * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9352    * driver may have to do extra work to determine whether the parameter
9353    * data should be sent to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9354    *
9355    * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9356    * it might be more efficient to use a version of
9357    * <code>setClob</code> which takes a length parameter.
9358    *
9359    * @param parameterIndex index of the first parameter is 1, the second is 2, ...
9360    * @param reader An object that contains the data to set the parameter value to.
9361    * @throws SQLException if a database access error occurs, this method is called on
9362    * a closed <code>PreparedStatement</code>or if parameterIndex does not correspond to a parameter
9363    * marker in the SQL statement
9364    *
9365    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9366    * @since 1.6
9367    */
9368    public void setClob(int parameterIndex, Reader reader)
9369      throws SQLException{
9370         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9371    }
9372 
9373     /**
9374    * Sets the designated parameter to a <code>Reader</code> object.  The reader must contain  the number
9375    * of characters specified by length otherwise a <code>SQLException</code> will be
9376    * generated when the <code>PreparedStatement</code> is executed.
9377    *This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
9378    * because it informs the driver that the parameter value should be sent to
9379    * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9380    * driver may have to do extra work to determine whether the parameter
9381    * data should be sent to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9382    * @param parameterIndex index of the first parameter is 1, the second is 2, ...
9383    * @param reader An object that contains the data to set the parameter value to.
9384    * @param length the number of characters in the parameter data.
9385    * @throws SQLException if a database access error occurs, this method is called on
9386    * a closed <code>PreparedStatement</code>, if parameterIndex does not correspond to a parameter
9387    * marker in the SQL statement, or if the length specified is less than zero.
9388    *
9389    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9390    * @since 1.6
9391    */
9392    public void setClob(int parameterIndex, Reader reader, long length)
9393      throws SQLException{
9394         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9395    }
9396 
9397 
9398  /**
9399     * Sets the designated parameter to a <code>InputStream</code> object.  The inputstream must contain  the number
9400     * of characters specified by length otherwise a <code>SQLException</code> will be
9401     * generated when the <code>PreparedStatement</code> is executed.
9402     * This method differs from the <code>setBinaryStream (int, InputStream, int)</code>
9403     * method because it informs the driver that the parameter value should be
9404     * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9405     * the driver may have to do extra work to determine whether the parameter
9406     * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9407     * @param parameterIndex index of the first parameter is 1,
9408     * the second is 2, ...
9409     * @param inputStream An object that contains the data to set the parameter
9410     * value to.
9411     * @param length the number of bytes in the parameter data.
9412     * @throws SQLException if a database access error occurs,
9413     * this method is called on a closed <code>PreparedStatement</code>,
9414     * if parameterIndex does not correspond
9415     * to a parameter marker in the SQL statement,  if the length specified
9416     * is less than zero or if the number of bytes in the inputstream does not match
9417     * the specified length.
9418     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9419     *
9420     * @since 1.6
9421     */
9422     public void setBlob(int parameterIndex, InputStream inputStream, long length)
9423        throws SQLException{
9424         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9425    }
9426 
9427 
9428  /**
9429     * Sets the designated parameter to a <code>InputStream</code> object.
9430     * This method differs from the <code>setBinaryStream (int, InputStream)</code>
9431     * method because it informs the driver that the parameter value should be
9432     * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9433     * the driver may have to do extra work to determine whether the parameter
9434     * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9435     *
9436     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9437     * it might be more efficient to use a version of
9438     * <code>setBlob</code> which takes a length parameter.
9439     *
9440     * @param parameterIndex index of the first parameter is 1,
9441     * the second is 2, ...
9442     * @param inputStream An object that contains the data to set the parameter
9443     * value to.
9444     * @throws SQLException if a database access error occurs,
9445     * this method is called on a closed <code>PreparedStatement</code> or
9446     * if parameterIndex does not correspond
9447     * to a parameter marker in the SQL statement,
9448     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9449     *
9450     * @since 1.6
9451     */
9452     public void setBlob(int parameterIndex, InputStream inputStream)
9453        throws SQLException{
9454         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9455    }
9456 
9457 
9458  /**
9459     * Sets the designated parameter to a <code>InputStream</code> object.  The <code>inputstream</code> must contain  the number
9460      * of characters specified by length, otherwise a <code>SQLException</code> will be
9461      * generated when the <code>CallableStatement</code> is executed.
9462      * This method differs from the <code>setBinaryStream (int, InputStream, int)</code>
9463      * method because it informs the driver that the parameter value should be
9464      * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9465      * the driver may have to do extra work to determine whether the parameter
9466      * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9467      *
9468      * @param parameterName the name of the parameter to be set
9469      * the second is 2, ...
9470      *
9471      * @param inputStream An object that contains the data to set the parameter
9472      * value to.
9473      * @param length the number of bytes in the parameter data.
9474      * @throws SQLException  if parameterIndex does not correspond
9475      * to a parameter marker in the SQL statement,  or if the length specified
9476      * is less than zero; if the number of bytes in the inputstream does not match
9477      * the specified length; if a database access error occurs or
9478      * this method is called on a closed <code>CallableStatement</code>
9479      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9480      * this method
9481      *
9482      * @since 1.6
9483      */
9484      public void setBlob(String parameterName, InputStream inputStream, long length)
9485         throws SQLException{
9486         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9487    }
9488 
9489 
9490  /**
9491     * Sets the designated parameter to the given <code>java.sql.Blob</code> object.
9492     * The driver converts this to an SQL <code>BLOB</code> value when it
9493     * sends it to the database.
9494     *
9495     * @param parameterName the name of the parameter
9496     * @param x a <code>Blob</code> object that maps an SQL <code>BLOB</code> value
9497     * @exception SQLException if a database access error occurs or
9498     * this method is called on a closed <code>CallableStatement</code>
9499     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9500     * this method
9501     * @since 1.6
9502     */
9503    public void setBlob (String parameterName, Blob x) throws SQLException{
9504         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9505    }
9506 
9507 
9508  /**
9509     * Sets the designated parameter to a <code>InputStream</code> object.
9510     * This method differs from the <code>setBinaryStream (int, InputStream)</code>
9511     * method because it informs the driver that the parameter value should be
9512     * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9513     * the driver may have to do extra work to determine whether the parameter
9514     * data should be send to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9515     *
9516     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9517     * it might be more efficient to use a version of
9518     * <code>setBlob</code> which takes a length parameter.
9519     *
9520     * @param parameterName the name of the parameter
9521     * @param inputStream An object that contains the data to set the parameter
9522     * value to.
9523     * @throws SQLException if a database access error occurs or
9524     * this method is called on a closed <code>CallableStatement</code>
9525     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9526     *
9527     * @since 1.6
9528     */
9529     public void setBlob(String parameterName, InputStream inputStream)
9530        throws SQLException{
9531         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9532    }
9533 
9534     /**
9535     * Sets the value of the designated parameter with the given object. The second
9536     * argument must be an object type; for integral values, the
9537     * <code>java.lang</code> equivalent objects should be used.
9538     *
9539     * <p>The given Java object will be converted to the given targetSqlType
9540     * before being sent to the database.
9541     *
9542     * If the object has a custom mapping (is of a class implementing the
9543     * interface <code>SQLData</code>),
9544     * the JDBC driver should call the method <code>SQLData.writeSQL</code> to write it
9545     * to the SQL data stream.
9546     * If, on the other hand, the object is of a class implementing
9547     * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>,  <code>NClob</code>,
9548     *  <code>Struct</code>, <code>java.net.URL</code>,
9549     * or <code>Array</code>, the driver should pass it to the database as a
9550     * value of the corresponding SQL type.
9551     * <P>
9552     * Note that this method may be used to pass datatabase-
9553     * specific abstract data types.
9554     *
9555     * @param parameterName the name of the parameter
9556     * @param x the object containing the input parameter value
9557     * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
9558     * sent to the database. The scale argument may further qualify this type.
9559     * @param scale for java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types,
9560     *          this is the number of digits after the decimal point.  For all other
9561     *          types, this value will be ignored.
9562     * @exception SQLException if a database access error occurs or
9563     * this method is called on a closed <code>CallableStatement</code>
9564     * @exception SQLFeatureNotSupportedException if <code>targetSqlType</code> is
9565     * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,
9566     * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,
9567     * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,
9568     *  <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
9569     * or  <code>STRUCT</code> data type and the JDBC driver does not support
9570     * this data type
9571     * @see Types
9572     * @see #getObject
9573     * @since 1.4
9574     */
9575     public void setObject(String parameterName, Object x, int targetSqlType, int scale)
9576        throws SQLException{
9577         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9578    }
9579 
9580 
9581 
9582  /**
9583     * Sets the value of the designated parameter with the given object.
9584     * This method is like the method <code>setObject</code>
9585     * above, except that it assumes a scale of zero.
9586     *
9587     * @param parameterName the name of the parameter
9588     * @param x the object containing the input parameter value
9589     * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
9590     *                      sent to the database
9591     * @exception SQLException if a database access error occurs or
9592     * this method is called on a closed <code>CallableStatement</code>
9593     * @exception SQLFeatureNotSupportedException if <code>targetSqlType</code> is
9594     * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,
9595     * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,
9596     * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,
9597     *  <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
9598     * or  <code>STRUCT</code> data type and the JDBC driver does not support
9599     * this data type
9600     * @see #getObject
9601     * @since 1.4
9602     */
9603     public void setObject(String parameterName, Object x, int targetSqlType)
9604        throws SQLException{
9605         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9606    }
9607 
9608 
9609  /**
9610    * Sets the value of the designated parameter with the given object.
9611    * The second parameter must be of type <code>Object</code>; therefore, the
9612    * <code>java.lang</code> equivalent objects should be used for built-in types.
9613    *
9614    * <p>The JDBC specification specifies a standard mapping from
9615    * Java <code>Object</code> types to SQL types.  The given argument
9616    * will be converted to the corresponding SQL type before being
9617    * sent to the database.
9618    *
9619    * <p>Note that this method may be used to pass datatabase-
9620    * specific abstract data types, by using a driver-specific Java
9621    * type.
9622    *
9623    * If the object is of a class implementing the interface <code>SQLData</code>,
9624    * the JDBC driver should call the method <code>SQLData.writeSQL</code>
9625    * to write it to the SQL data stream.
9626    * If, on the other hand, the object is of a class implementing
9627    * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>,  <code>NClob</code>,
9628    *  <code>Struct</code>, <code>java.net.URL</code>,
9629    * or <code>Array</code>, the driver should pass it to the database as a
9630    * value of the corresponding SQL type.
9631    * <P>
9632    * This method throws an exception if there is an ambiguity, for example, if the
9633    * object is of a class implementing more than one of the interfaces named above.
9634    *
9635    * @param parameterName the name of the parameter
9636    * @param x the object containing the input parameter value
9637    * @exception SQLException if a database access error occurs,
9638    * this method is called on a closed <code>CallableStatement</code> or if the given
9639    *            <code>Object</code> parameter is ambiguous
9640    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9641    * this method
9642    * @see #getObject
9643    * @since 1.4
9644    */
9645    public void setObject(String parameterName, Object x) throws SQLException{
9646         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9647    }
9648 
9649     /**
9650     * Sets the designated parameter to the given input stream, which will have
9651     * the specified number of bytes.
9652     * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
9653     * parameter, it may be more practical to send it via a
9654     * <code>java.io.InputStream</code>. Data will be read from the stream
9655     * as needed until end-of-file is reached.  The JDBC driver will
9656     * do any necessary conversion from ASCII to the database char format.
9657     *
9658     * <P><B>Note:</B> This stream object can either be a standard
9659     * Java stream object or your own subclass that implements the
9660     * standard interface.
9661     *
9662     * @param parameterName the name of the parameter
9663     * @param x the Java input stream that contains the ASCII parameter value
9664     * @param length the number of bytes in the stream
9665     * @exception SQLException if a database access error occurs or
9666     * this method is called on a closed <code>CallableStatement</code>
9667     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9668     * this method
9669     * @since 1.4
9670     */
9671    public void setAsciiStream(String parameterName, java.io.InputStream x, int length)
9672        throws SQLException{
9673         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9674    }
9675 
9676 
9677  /**
9678     * Sets the designated parameter to the given input stream, which will have
9679     * the specified number of bytes.
9680     * When a very large binary value is input to a <code>LONGVARBINARY</code>
9681     * parameter, it may be more practical to send it via a
9682     * <code>java.io.InputStream</code> object. The data will be read from the stream
9683     * as needed until end-of-file is reached.
9684     *
9685     * <P><B>Note:</B> This stream object can either be a standard
9686     * Java stream object or your own subclass that implements the
9687     * standard interface.
9688     *
9689     * @param parameterName the name of the parameter
9690     * @param x the java input stream which contains the binary parameter value
9691     * @param length the number of bytes in the stream
9692     * @exception SQLException if a database access error occurs or
9693     * this method is called on a closed <code>CallableStatement</code>
9694     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9695     * this method
9696     * @since 1.4
9697     */
9698    public void setBinaryStream(String parameterName, java.io.InputStream x,
9699                         int length) throws SQLException{
9700         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9701    }
9702 
9703 
9704   /**
9705     * Sets the designated parameter to the given <code>Reader</code>
9706     * object, which is the given number of characters long.
9707     * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
9708     * parameter, it may be more practical to send it via a
9709     * <code>java.io.Reader</code> object. The data will be read from the stream
9710     * as needed until end-of-file is reached.  The JDBC driver will
9711     * do any necessary conversion from UNICODE to the database char format.
9712     *
9713     * <P><B>Note:</B> This stream object can either be a standard
9714     * Java stream object or your own subclass that implements the
9715     * standard interface.
9716     *
9717     * @param parameterName the name of the parameter
9718     * @param reader the <code>java.io.Reader</code> object that
9719     *        contains the UNICODE data used as the designated parameter
9720     * @param length the number of characters in the stream
9721     * @exception SQLException if a database access error occurs or
9722     * this method is called on a closed <code>CallableStatement</code>
9723     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9724     * this method
9725     * @since 1.4
9726     */
9727    public void setCharacterStream(String parameterName,
9728                            java.io.Reader reader,
9729                            int length) throws SQLException{
9730         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9731    }
9732 
9733 
9734   /**
9735    * Sets the designated parameter to the given input stream.
9736    * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
9737    * parameter, it may be more practical to send it via a
9738    * <code>java.io.InputStream</code>. Data will be read from the stream
9739    * as needed until end-of-file is reached.  The JDBC driver will
9740    * do any necessary conversion from ASCII to the database char format.
9741    *
9742    * <P><B>Note:</B> This stream object can either be a standard
9743    * Java stream object or your own subclass that implements the
9744    * standard interface.
9745    * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9746    * it might be more efficient to use a version of
9747    * <code>setAsciiStream</code> which takes a length parameter.
9748    *
9749    * @param parameterName the name of the parameter
9750    * @param x the Java input stream that contains the ASCII parameter value
9751    * @exception SQLException if a database access error occurs or
9752    * this method is called on a closed <code>CallableStatement</code>
9753    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9754      * @since 1.6
9755   */
9756   public void setAsciiStream(String parameterName, java.io.InputStream x)
9757           throws SQLException{
9758         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9759    }
9760 
9761 
9762  /**
9763     * Sets the designated parameter to the given input stream.
9764     * When a very large binary value is input to a <code>LONGVARBINARY</code>
9765     * parameter, it may be more practical to send it via a
9766     * <code>java.io.InputStream</code> object. The data will be read from the
9767     * stream as needed until end-of-file is reached.
9768     *
9769     * <P><B>Note:</B> This stream object can either be a standard
9770     * Java stream object or your own subclass that implements the
9771     * standard interface.
9772     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9773     * it might be more efficient to use a version of
9774     * <code>setBinaryStream</code> which takes a length parameter.
9775     *
9776     * @param parameterName the name of the parameter
9777     * @param x the java input stream which contains the binary parameter value
9778     * @exception SQLException if a database access error occurs or
9779     * this method is called on a closed <code>CallableStatement</code>
9780     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9781     * @since 1.6
9782     */
9783    public void setBinaryStream(String parameterName, java.io.InputStream x)
9784    throws SQLException{
9785         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9786    }
9787 
9788 
9789 
9790  /**
9791     * Sets the designated parameter to the given <code>Reader</code>
9792     * object.
9793     * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
9794     * parameter, it may be more practical to send it via a
9795     * <code>java.io.Reader</code> object. The data will be read from the stream
9796     * as needed until end-of-file is reached.  The JDBC driver will
9797     * do any necessary conversion from UNICODE to the database char format.
9798     *
9799     * <P><B>Note:</B> This stream object can either be a standard
9800     * Java stream object or your own subclass that implements the
9801     * standard interface.
9802     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9803     * it might be more efficient to use a version of
9804     * <code>setCharacterStream</code> which takes a length parameter.
9805     *
9806     * @param parameterName the name of the parameter
9807     * @param reader the <code>java.io.Reader</code> object that contains the
9808     *        Unicode data
9809     * @exception SQLException if a database access error occurs or
9810     * this method is called on a closed <code>CallableStatement</code>
9811     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9812     * @since 1.6
9813     */
9814    public void setCharacterStream(String parameterName,
9815                          java.io.Reader reader) throws SQLException{
9816         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9817    }
9818 
9819    /**
9820     * Sets the designated parameter to the given
9821     * <code>java.math.BigDecimal</code> value.
9822     * The driver converts this to an SQL <code>NUMERIC</code> value when
9823     * it sends it to the database.
9824     *
9825     * @param parameterName the name of the parameter
9826     * @param x the parameter value
9827     * @exception SQLException if a database access error occurs or
9828     * this method is called on a closed <code>CallableStatement</code>
9829     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9830     * this method
9831     * @see #getBigDecimal
9832     * @since 1.4
9833     */
9834    public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException{
9835         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9836    }
9837 
9838 
9839 
9840  /**
9841     * Sets the designated parameter to the given Java <code>String</code> value.
9842     * The driver converts this
9843     * to an SQL <code>VARCHAR</code> or <code>LONGVARCHAR</code> value
9844     * (depending on the argument's
9845     * size relative to the driver's limits on <code>VARCHAR</code> values)
9846     * when it sends it to the database.
9847     *
9848     * @param parameterName the name of the parameter
9849     * @param x the parameter value
9850     * @exception SQLException if a database access error occurs or
9851     * this method is called on a closed <code>CallableStatement</code>
9852     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9853     * this method
9854     * @see #getString
9855     * @since 1.4
9856     */
9857    public void setString(String parameterName, String x) throws SQLException{
9858         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9859    }
9860 
9861 
9862 
9863  /**
9864     * Sets the designated parameter to the given Java array of bytes.
9865     * The driver converts this to an SQL <code>VARBINARY</code> or
9866     * <code>LONGVARBINARY</code> (depending on the argument's size relative
9867     * to the driver's limits on <code>VARBINARY</code> values) when it sends
9868     * it to the database.
9869     *
9870     * @param parameterName the name of the parameter
9871     * @param x the parameter value
9872     * @exception SQLException if a database access error occurs or
9873     * this method is called on a closed <code>CallableStatement</code>
9874     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9875     * this method
9876     * @see #getBytes
9877     * @since 1.4
9878     */
9879    public void setBytes(String parameterName, byte x[]) throws SQLException{
9880         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9881    }
9882 
9883 
9884 
9885  /**
9886     * Sets the designated parameter to the given <code>java.sql.Timestamp</code> value.
9887     * The driver
9888     * converts this to an SQL <code>TIMESTAMP</code> value when it sends it to the
9889     * database.
9890     *
9891     * @param parameterName the name of the parameter
9892     * @param x the parameter value
9893     * @exception SQLException if a database access error occurs or
9894     * this method is called on a closed <code>CallableStatement</code>
9895     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9896     * this method
9897     * @see #getTimestamp
9898     * @since 1.4
9899     */
9900    public void setTimestamp(String parameterName, java.sql.Timestamp x)
9901        throws SQLException{
9902         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9903    }
9904 
9905     /**
9906     * Sets the designated parameter to SQL <code>NULL</code>.
9907     *
9908     * <P><B>Note:</B> You must specify the parameter's SQL type.
9909     *
9910     * @param parameterName the name of the parameter
9911     * @param sqlType the SQL type code defined in <code>java.sql.Types</code>
9912     * @exception SQLException if a database access error occurs or
9913     * this method is called on a closed <code>CallableStatement</code>
9914     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9915     * this method
9916     * @since 1.4
9917     */
9918    public void setNull(String parameterName, int sqlType) throws SQLException {
9919         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9920    }
9921 
9922 
9923  /**
9924     * Sets the designated parameter to SQL <code>NULL</code>.
9925     * This version of the method <code>setNull</code> should
9926     * be used for user-defined types and REF type parameters.  Examples
9927     * of user-defined types include: STRUCT, DISTINCT, JAVA_OBJECT, and
9928     * named array types.
9929     *
9930     * <P><B>Note:</B> To be portable, applications must give the
9931     * SQL type code and the fully-qualified SQL type name when specifying
9932     * a NULL user-defined or REF parameter.  In the case of a user-defined type
9933     * the name is the type name of the parameter itself.  For a REF
9934     * parameter, the name is the type name of the referenced type.  If
9935     * a JDBC driver does not need the type code or type name information,
9936     * it may ignore it.
9937     *
9938     * Although it is intended for user-defined and Ref parameters,
9939     * this method may be used to set a null parameter of any JDBC type.
9940     * If the parameter does not have a user-defined or REF type, the given
9941     * typeName is ignored.
9942     *
9943     *
9944     * @param parameterName the name of the parameter
9945     * @param sqlType a value from <code>java.sql.Types</code>
9946     * @param typeName the fully-qualified name of an SQL user-defined type;
9947     *        ignored if the parameter is not a user-defined type or
9948     *        SQL <code>REF</code> value
9949     * @exception SQLException if a database access error occurs or
9950     * this method is called on a closed <code>CallableStatement</code>
9951     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9952     * this method
9953     * @since 1.4
9954     */
9955    public void setNull (String parameterName, int sqlType, String typeName)
9956        throws SQLException{
9957         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9958    }
9959 
9960 
9961 
9962  /**
9963     * Sets the designated parameter to the given Java <code>boolean</code> value.
9964     * The driver converts this
9965     * to an SQL <code>BIT</code> or <code>BOOLEAN</code> value when it sends it to the database.
9966     *
9967     * @param parameterName the name of the parameter
9968     * @param x the parameter value
9969     * @exception SQLException if a database access error occurs or
9970     * this method is called on a closed <code>CallableStatement</code>
9971     * @see #getBoolean
9972     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9973     * this method
9974     * @since 1.4
9975     */
9976    public void setBoolean(String parameterName, boolean x) throws SQLException{
9977         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9978    }
9979 
9980 
9981 
9982  /**
9983     * Sets the designated parameter to the given Java <code>byte</code> value.
9984     * The driver converts this
9985     * to an SQL <code>TINYINT</code> value when it sends it to the database.
9986     *
9987     * @param parameterName the name of the parameter
9988     * @param x the parameter value
9989     * @exception SQLException if a database access error occurs or
9990     * this method is called on a closed <code>CallableStatement</code>
9991     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9992     * this method
9993     * @see #getByte
9994     * @since 1.4
9995     */
9996    public void setByte(String parameterName, byte x) throws SQLException{
9997         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9998    }
9999 
10000 
10001 
10002  /**
10003     * Sets the designated parameter to the given Java <code>short</code> value.
10004     * The driver converts this
10005     * to an SQL <code>SMALLINT</code> value when it sends it to the database.
10006     *
10007     * @param parameterName the name of the parameter
10008     * @param x the parameter value
10009     * @exception SQLException if a database access error occurs or
10010     * this method is called on a closed <code>CallableStatement</code>
10011     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10012     * this method
10013     * @see #getShort
10014     * @since 1.4
10015     */
10016    public void setShort(String parameterName, short x) throws SQLException{
10017         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10018    }
10019 
10020 
10021  /**
10022     * Sets the designated parameter to the given Java <code>int</code> value.
10023     * The driver converts this
10024     * to an SQL <code>INTEGER</code> value when it sends it to the database.
10025     *
10026     * @param parameterName the name of the parameter
10027     * @param x the parameter value
10028     * @exception SQLException if a database access error occurs or
10029     * this method is called on a closed <code>CallableStatement</code>
10030     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10031     * this method
10032     * @see #getInt
10033     * @since 1.4
10034     */
10035    public void setInt(String parameterName, int x) throws SQLException{
10036         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10037    }
10038 
10039 
10040  /**
10041     * Sets the designated parameter to the given Java <code>long</code> value.
10042     * The driver converts this
10043     * to an SQL <code>BIGINT</code> value when it sends it to the database.
10044     *
10045     * @param parameterName the name of the parameter
10046     * @param x the parameter value
10047     * @exception SQLException if a database access error occurs or
10048     * this method is called on a closed <code>CallableStatement</code>
10049     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10050     * this method
10051     * @see #getLong
10052     * @since 1.4
10053     */
10054    public void setLong(String parameterName, long x) throws SQLException{
10055         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10056    }
10057 
10058 
10059  /**
10060     * Sets the designated parameter to the given Java <code>float</code> value.
10061     * The driver converts this
10062     * to an SQL <code>FLOAT</code> value when it sends it to the database.
10063     *
10064     * @param parameterName the name of the parameter
10065     * @param x the parameter value
10066     * @exception SQLException if a database access error occurs or
10067     * this method is called on a closed <code>CallableStatement</code>
10068     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10069     * this method
10070     * @see #getFloat
10071     * @since 1.4
10072     */
10073    public void setFloat(String parameterName, float x) throws SQLException{
10074         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10075    }
10076 
10077 
10078  /**
10079     * Sets the designated parameter to the given Java <code>double</code> value.
10080     * The driver converts this
10081     * to an SQL <code>DOUBLE</code> value when it sends it to the database.
10082     *
10083     * @param parameterName the name of the parameter
10084     * @param x the parameter value
10085     * @exception SQLException if a database access error occurs or
10086     * this method is called on a closed <code>CallableStatement</code>
10087     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10088     * this method
10089     * @see #getDouble
10090     * @since 1.4
10091     */
10092    public void setDouble(String parameterName, double x) throws SQLException{
10093         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10094    }
10095 
10096    /**
10097      * This method re populates the resBundle
10098      * during the deserialization process
10099      *
10100      */
10101     private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
10102         // Default state initialization happens here
10103         ois.defaultReadObject();
10104         // Initialization of transient Res Bundle happens here .
10105         try {
10106            resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
10107         } catch(IOException ioe) {
10108             throw new RuntimeException(ioe);
10109         }
10110 
10111     }
10112 
10113     //------------------------- JDBC 4.1 -----------------------------------
10114     public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
10115         throw new SQLFeatureNotSupportedException("Not supported yet.");
10116     }
10117 
10118     public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
10119         throw new SQLFeatureNotSupportedException("Not supported yet.");
10120     }
10121 
10122     static final long serialVersionUID =1884577171200622428L;
10123 }