1 /*
   2  * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.rowset;
  27 
  28 import java.sql.*;
  29 import javax.sql.*;
  30 import java.io.*;
  31 import java.math.*;
  32 import java.util.*;
  33 import java.text.*;
  34 
  35 import javax.sql.rowset.*;
  36 import javax.sql.rowset.spi.*;
  37 import javax.sql.rowset.serial.*;
  38 import com.sun.rowset.internal.*;
  39 import com.sun.rowset.providers.*;
  40 import sun.reflect.misc.ReflectUtil;
  41 
  42 /**
  43  * The standard implementation of the <code>CachedRowSet</code> interface.
  44  *
  45  * See interface definition for full behavior and implementation requirements.
  46  * This reference implementation has made provision for a one-to-one write back
  47  * facility and it is curremtly be possible to change the peristence provider
  48  * during the life-time of any CachedRowSetImpl.
  49  *
  50  * @author Jonathan Bruce, Amit Handa
  51  */
  52 
  53 public class CachedRowSetImpl extends BaseRowSet implements RowSet, RowSetInternal, Serializable, Cloneable, CachedRowSet {
  54 
  55     /**
  56      * The <code>SyncProvider</code> used by the CachedRowSet
  57      */
  58     private SyncProvider provider;
  59 
  60     /**
  61      * The <code>RowSetReaderImpl</code> object that is the reader
  62      * for this rowset.  The method <code>execute</code> uses this
  63      * reader as part of its implementation.
  64      * @serial
  65      */
  66     private RowSetReader rowSetReader;
  67 
  68     /**
  69      * The <code>RowSetWriterImpl</code> object that is the writer
  70      * for this rowset.  The method <code>acceptChanges</code> uses
  71      * this writer as part of its implementation.
  72      * @serial
  73      */
  74     private RowSetWriter rowSetWriter;
  75 
  76     /**
  77      * The <code>Connection</code> object that connects with this
  78      * <code>CachedRowSetImpl</code> object's current underlying data source.
  79      */
  80     private transient Connection conn;
  81 
  82     /**
  83      * The <code>ResultSetMetaData</code> object that contains information
  84      * about the columns in the <code>ResultSet</code> object that is the
  85      * current source of data for this <code>CachedRowSetImpl</code> object.
  86      */
  87     private transient ResultSetMetaData RSMD;
  88 
  89     /**
  90      * The <code>RowSetMetaData</code> object that contains information about
  91      * the columns in this <code>CachedRowSetImpl</code> object.
  92      * @serial
  93      */
  94     private RowSetMetaDataImpl RowSetMD;
  95 
  96     // Properties of this RowSet
  97 
  98     /**
  99      * An array containing the columns in this <code>CachedRowSetImpl</code>
 100      * object that form a unique identifier for a row. This array
 101      * is used by the writer.
 102      * @serial
 103      */
 104     private int keyCols[];
 105 
 106     /**
 107      * The name of the table in the underlying database to which updates
 108      * should be written.  This name is needed because most drivers
 109      * do not return this information in a <code>ResultSetMetaData</code>
 110      * object.
 111      * @serial
 112      */
 113     private String tableName;
 114 
 115     /**
 116      * A <code>Vector</code> object containing the <code>Row</code>
 117      * objects that comprise  this <code>CachedRowSetImpl</code> object.
 118      * @serial
 119      */
 120     private Vector<Object> rvh;
 121 
 122     /**
 123      * The current position of the cursor in this <code>CachedRowSetImpl</code>
 124      * object.
 125      * @serial
 126      */
 127     private int cursorPos;
 128 
 129     /**
 130      * The current position of the cursor in this <code>CachedRowSetImpl</code>
 131      * object not counting rows that have been deleted, if any.
 132      * <P>
 133      * For example, suppose that the cursor is on the last row of a rowset
 134      * that started with five rows and subsequently had the second and third
 135      * rows deleted. The <code>absolutePos</code> would be <code>3</code>,
 136      * whereas the <code>cursorPos</code> would be <code>5</code>.
 137      * @serial
 138      */
 139     private int absolutePos;
 140 
 141     /**
 142      * The number of deleted rows currently in this <code>CachedRowSetImpl</code>
 143      * object.
 144      * @serial
 145      */
 146     private int numDeleted;
 147 
 148     /**
 149      * The total number of rows currently in this <code>CachedRowSetImpl</code>
 150      * object.
 151      * @serial
 152      */
 153     private int numRows;
 154 
 155     /**
 156      * A special row used for constructing a new row. A new
 157      * row is constructed by using <code>ResultSet.updateXXX</code>
 158      * methods to insert column values into the insert row.
 159      * @serial
 160      */
 161     private InsertRow insertRow;
 162 
 163     /**
 164      * A <code>boolean</code> indicating whether the cursor is
 165      * currently on the insert row.
 166      * @serial
 167      */
 168     private boolean onInsertRow;
 169 
 170     /**
 171      * The field that temporarily holds the last position of the
 172      * cursor before it moved to the insert row, thus preserving
 173      * the number of the current row to which the cursor may return.
 174      * @serial
 175      */
 176     private int currentRow;
 177 
 178     /**
 179      * A <code>boolean</code> indicating whether the last value
 180      * returned was an SQL <code>NULL</code>.
 181      * @serial
 182      */
 183     private boolean lastValueNull;
 184 
 185     /**
 186      * A <code>SQLWarning</code> which logs on the warnings
 187      */
 188     private SQLWarning sqlwarn;
 189 
 190     /**
 191      * Used to track match column for JoinRowSet consumption
 192      */
 193     private String strMatchColumn ="";
 194 
 195     /**
 196      * Used to track match column for JoinRowSet consumption
 197      */
 198     private int iMatchColumn = -1;
 199 
 200     /**
 201      * A <code>RowSetWarning</code> which logs on the warnings
 202      */
 203     private RowSetWarning rowsetWarning;
 204 
 205     /**
 206      * The default SyncProvider for the RI CachedRowSetImpl
 207      */
 208     private String DEFAULT_SYNC_PROVIDER = "com.sun.rowset.providers.RIOptimisticProvider";
 209 
 210     /**
 211      * The boolean variable indicating locatorsUpdateValue
 212      */
 213     private boolean dbmslocatorsUpdateCopy;
 214 
 215     /**
 216      * The <code>ResultSet</code> object that is used to maintain the data when
 217      * a ResultSet and start position are passed as parameters to the populate function
 218      */
 219     private transient ResultSet resultSet;
 220 
 221     /**
 222      * The integer value indicating the end position in the ResultSetwhere the picking
 223      * up of rows for populating a CachedRowSet object was left off.
 224      */
 225     private int endPos;
 226 
 227     /**
 228      * The integer value indicating the end position in the ResultSetwhere the picking
 229      * up of rows for populating a CachedRowSet object was left off.
 230      */
 231     private int prevEndPos;
 232 
 233     /**
 234      * The integer value indicating the position in the ResultSet, to populate the
 235      * CachedRowSet object.
 236      */
 237     private int startPos;
 238 
 239     /**
 240      * The integer value indicating the position from where the page prior to this
 241      * was populated.
 242      */
 243     private int startPrev;
 244 
 245     /**
 246      * The integer value indicating size of the page.
 247      */
 248     private int pageSize;
 249 
 250     /**
 251      * The integer value indicating number of rows that have been processed so far.
 252      * Used for checking whether maxRows has been reached or not.
 253      */
 254     private int maxRowsreached;
 255     /**
 256      * The boolean value when true signifies that pages are still to follow and a
 257      * false value indicates that this is the last page.
 258      */
 259     private boolean pagenotend = true;
 260 
 261     /**
 262      * The boolean value indicating whether this is the first page or not.
 263      */
 264     private boolean onFirstPage;
 265 
 266     /**
 267      * The boolean value indicating whether this is the last page or not.
 268      */
 269     private boolean onLastPage;
 270 
 271     /**
 272      * The integer value indicating how many times the populate function has been called.
 273      */
 274     private int populatecallcount;
 275 
 276     /**
 277      * The integer value indicating the total number of rows to be processed in the
 278      * ResultSet object passed to the populate function.
 279      */
 280     private int totalRows;
 281 
 282     /**
 283      * The boolean value indicating how the CahedRowSet object has been populated for
 284      * paging purpose. True indicates that connection parameter is passed.
 285      */
 286     private boolean callWithCon;
 287 
 288     /**
 289      * CachedRowSet reader object to read the data from the ResultSet when a connection
 290      * parameter is passed to populate the CachedRowSet object for paging.
 291      */
 292     private CachedRowSetReader crsReader;
 293 
 294     /**
 295      * The Vector holding the Match Columns
 296      */
 297     private Vector<Integer> iMatchColumns;
 298 
 299     /**
 300      * The Vector that will hold the Match Column names.
 301      */
 302     private Vector<String> strMatchColumns;
 303 
 304     /**
 305      * Trigger that indicates whether the active SyncProvider is exposes the
 306      * additional TransactionalWriter method
 307      */
 308     private boolean tXWriter = false;
 309 
 310     /**
 311      * The field object for a transactional RowSet writer
 312      */
 313     private TransactionalWriter tWriter = null;
 314 
 315     protected transient JdbcRowSetResourceBundle resBundle;
 316 
 317     private boolean updateOnInsert;
 318 
 319 
 320 
 321     /**
 322      * Constructs a new default <code>CachedRowSetImpl</code> object with
 323      * the capacity to hold 100 rows. This new object has no metadata
 324      * and has the following default values:
 325      * <pre>
 326      *     onInsertRow = false
 327      *     insertRow = null
 328      *     cursorPos = 0
 329      *     numRows = 0
 330      *     showDeleted = false
 331      *     queryTimeout = 0
 332      *     maxRows = 0
 333      *     maxFieldSize = 0
 334      *     rowSetType = ResultSet.TYPE_SCROLL_INSENSITIVE
 335      *     concurrency = ResultSet.CONCUR_UPDATABLE
 336      *     readOnly = false
 337      *     isolation = Connection.TRANSACTION_READ_COMMITTED
 338      *     escapeProcessing = true
 339      *     onInsertRow = false
 340      *     insertRow = null
 341      *     cursorPos = 0
 342      *     absolutePos = 0
 343      *     numRows = 0
 344      * </pre>
 345      * A <code>CachedRowSetImpl</code> object is configured to use the default
 346      * <code>RIOptimisticProvider</code> implementation to provide connectivity
 347      * and synchronization capabilities to the set data source.
 348      * <P>
 349      * @throws SQLException if an error occurs
 350      */
 351     public CachedRowSetImpl() throws SQLException {
 352 
 353         try {
 354            resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
 355         } catch(IOException ioe) {
 356             throw new RuntimeException(ioe);
 357         }
 358 
 359         // set the Reader, this maybe overridden latter
 360         provider =
 361         SyncFactory.getInstance(DEFAULT_SYNC_PROVIDER);
 362 
 363         if (!(provider instanceof RIOptimisticProvider)) {
 364             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidp").toString());
 365         }
 366 
 367         rowSetReader = (CachedRowSetReader)provider.getRowSetReader();
 368         rowSetWriter = (CachedRowSetWriter)provider.getRowSetWriter();
 369 
 370         // allocate the parameters collection
 371         initParams();
 372 
 373         initContainer();
 374 
 375         // set up some default values
 376         initProperties();
 377 
 378         // insert row setup
 379         onInsertRow = false;
 380         insertRow = null;
 381 
 382         // set the warninings
 383         sqlwarn = new SQLWarning();
 384         rowsetWarning = new RowSetWarning();
 385 
 386     }
 387 
 388     /**
 389      * Provides a <code>CachedRowSetImpl</code> instance with the same default properties as
 390      * as the zero parameter constructor.
 391      * <pre>
 392      *     onInsertRow = false
 393      *     insertRow = null
 394      *     cursorPos = 0
 395      *     numRows = 0
 396      *     showDeleted = false
 397      *     queryTimeout = 0
 398      *     maxRows = 0
 399      *     maxFieldSize = 0
 400      *     rowSetType = ResultSet.TYPE_SCROLL_INSENSITIVE
 401      *     concurrency = ResultSet.CONCUR_UPDATABLE
 402      *     readOnly = false
 403      *     isolation = Connection.TRANSACTION_READ_COMMITTED
 404      *     escapeProcessing = true
 405      *     onInsertRow = false
 406      *     insertRow = null
 407      *     cursorPos = 0
 408      *     absolutePos = 0
 409      *     numRows = 0
 410      * </pre>
 411      *
 412      * However, applications will have the means to specify at runtime the
 413      * desired <code>SyncProvider</code> object.
 414      * <p>
 415      * For example, creating a <code>CachedRowSetImpl</code> object as follows ensures
 416      * that a it is established with the <code>com.foo.provider.Impl</code> synchronization
 417      * implementation providing the synchronization mechanism for this disconnected
 418      * <code>RowSet</code> object.
 419      * <pre>
 420      *     Hashtable env = new Hashtable();
 421      *     env.put(javax.sql.rowset.spi.SyncFactory.ROWSET_PROVIDER_NAME,
 422      *         "com.foo.provider.Impl");
 423      *     CachedRowSetImpl crs = new CachedRowSet(env);
 424      * </pre>
 425      * <p>
 426      * Calling this constructor with a <code>null</code> parameter will
 427      * cause the <code>SyncFactory</code> to provide the reference
 428      * optimistic provider <code>com.sun.rowset.providers.RIOptimisticProvider</code>.
 429      * <p>
 430      * In addition, the following properties can be associated with the
 431      * provider to assist in determining the choice of the synchronizaton
 432      * provider such as:
 433      * <ul>
 434      * <li><code>ROWSET_SYNC_PROVIDER</code> - the property specifying the
 435      * <code>SyncProvider</code> class name to be instantiated by the
 436      * <code>SyncFacttory</code>
 437      * <li><code>ROWSET_SYNC_VENDOR</code> - the property specifying the software
 438      * vendor associated with a <code>SyncProvider</code> implementation.
 439      * <li><code>ROWSET_SYNC_PROVIDER_VER</code> - the property specifying the
 440      * version of the <code>SyncProvider</code> implementation provided by the
 441      * software vendor.
 442      * </ul>
 443      * More specific detailes are available in the <code>SyncFactory</code>
 444      * and <code>SyncProvider</code> specificiations later in this document.
 445      * <p>
 446      * @param env a <code>Hashtable</code> object with a list of desired
 447      *        synchronization providers
 448      * @throws SQLException if the requested provider cannot be found by the
 449      * synchronization factory
 450      * @see SyncProvider
 451      */
 452     public CachedRowSetImpl(@SuppressWarnings("rawtypes") Hashtable env) throws SQLException {
 453 
 454 
 455         try {
 456            resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
 457         } catch(IOException ioe) {
 458             throw new RuntimeException(ioe);
 459         }
 460 
 461         if (env == null) {
 462             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.nullhash").toString());
 463         }
 464 
 465         String providerName = (String)env.get(
 466         javax.sql.rowset.spi.SyncFactory.ROWSET_SYNC_PROVIDER);
 467 
 468         // set the Reader, this maybe overridden latter
 469         provider =
 470         SyncFactory.getInstance(providerName);
 471 
 472         rowSetReader = provider.getRowSetReader();
 473         rowSetWriter = provider.getRowSetWriter();
 474 
 475         initParams(); // allocate the parameters collection
 476         initContainer();
 477         initProperties(); // set up some default values
 478     }
 479 
 480     /**
 481      * Sets the <code>rvh</code> field to a new <code>Vector</code>
 482      * object with a capacity of 100 and sets the
 483      * <code>cursorPos</code> and <code>numRows</code> fields to zero.
 484      */
 485     private void initContainer() {
 486 
 487         rvh = new Vector<Object>(100);
 488         cursorPos = 0;
 489         absolutePos = 0;
 490         numRows = 0;
 491         numDeleted = 0;
 492     }
 493 
 494     /**
 495      * Sets the properties for this <code>CachedRowSetImpl</code> object to
 496      * their default values. This method is called internally by the
 497      * default constructor.
 498      */
 499 
 500     private void initProperties() throws SQLException {
 501 
 502         if(resBundle == null) {
 503             try {
 504                resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
 505             } catch(IOException ioe) {
 506                 throw new RuntimeException(ioe);
 507             }
 508         }
 509         setShowDeleted(false);
 510         setQueryTimeout(0);
 511         setMaxRows(0);
 512         setMaxFieldSize(0);
 513         setType(ResultSet.TYPE_SCROLL_INSENSITIVE);
 514         setConcurrency(ResultSet.CONCUR_UPDATABLE);
 515         if((rvh.size() > 0) && (isReadOnly() == false))
 516             setReadOnly(false);
 517         else
 518             setReadOnly(true);
 519         setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
 520         setEscapeProcessing(true);
 521         //setTypeMap(null);
 522         checkTransactionalWriter();
 523 
 524         //Instantiating the vector for MatchColumns
 525 
 526         iMatchColumns = new Vector<Integer>(10);
 527         for(int i = 0; i < 10 ; i++) {
 528            iMatchColumns.add(i, -1);
 529         }
 530 
 531         strMatchColumns = new Vector<String>(10);
 532         for(int j = 0; j < 10; j++) {
 533            strMatchColumns.add(j,null);
 534         }
 535     }
 536 
 537     /**
 538      * Determine whether the SyncProvider's writer implements the
 539      * <code>TransactionalWriter<code> interface
 540      */
 541     private void checkTransactionalWriter() {
 542         if (rowSetWriter != null) {
 543             Class<?> c = rowSetWriter.getClass();
 544             if (c != null) {
 545                 Class<?>[] theInterfaces = c.getInterfaces();
 546                 for (int i = 0; i < theInterfaces.length; i++) {
 547                     if ((theInterfaces[i].getName()).indexOf("TransactionalWriter") > 0) {
 548                         tXWriter = true;
 549                         establishTransactionalWriter();
 550                     }
 551                 }
 552             }
 553         }
 554     }
 555 
 556     /**
 557      * Sets an private field to all transaction bounddaries to be set
 558      */
 559     private void establishTransactionalWriter() {
 560         tWriter = (TransactionalWriter)provider.getRowSetWriter();
 561     }
 562 
 563     //-----------------------------------------------------------------------
 564     // Properties
 565     //-----------------------------------------------------------------------
 566 
 567     /**
 568      * Sets this <code>CachedRowSetImpl</code> object's command property
 569      * to the given <code>String</code> object and clears the parameters,
 570      * if any, that were set for the previous command.
 571      * <P>
 572      * The command property may not be needed
 573      * if the rowset is produced by a data source, such as a spreadsheet,
 574      * that does not support commands. Thus, this property is optional
 575      * and may be <code>null</code>.
 576      *
 577      * @param cmd a <code>String</code> object containing an SQL query
 578      *            that will be set as the command; may be <code>null</code>
 579      * @throws SQLException if an error occurs
 580      */
 581     public void setCommand(String cmd) throws SQLException {
 582 
 583         super.setCommand(cmd);
 584 
 585         if(!buildTableName(cmd).equals("")) {
 586             this.setTableName(buildTableName(cmd));
 587         }
 588     }
 589 
 590 
 591     //---------------------------------------------------------------------
 592     // Reading and writing data
 593     //---------------------------------------------------------------------
 594 
 595     /**
 596      * Populates this <code>CachedRowSetImpl</code> object with data from
 597      * the given <code>ResultSet</code> object.  This
 598      * method is an alternative to the method <code>execute</code>
 599      * for filling the rowset with data.  The method <code>populate</code>
 600      * does not require that the properties needed by the method
 601      * <code>execute</code>, such as the <code>command</code> property,
 602      * be set. This is true because the method <code>populate</code>
 603      * is given the <code>ResultSet</code> object from
 604      * which to get data and thus does not need to use the properties
 605      * required for setting up a connection and executing this
 606      * <code>CachedRowSetImpl</code> object's command.
 607      * <P>
 608      * After populating this rowset with data, the method
 609      * <code>populate</code> sets the rowset's metadata and
 610      * then sends a <code>RowSetChangedEvent</code> object
 611      * to all registered listeners prior to returning.
 612      *
 613      * @param data the <code>ResultSet</code> object containing the data
 614      *             to be read into this <code>CachedRowSetImpl</code> object
 615      * @throws SQLException if an error occurs; or the max row setting is
 616      *          violated while populating the RowSet
 617      * @see #execute
 618      */
 619 
 620      public void populate(ResultSet data) throws SQLException {
 621         int rowsFetched;
 622         Row currentRow;
 623         int numCols;
 624         int i;
 625         Map<String, Class<?>> map = getTypeMap();
 626         Object obj;
 627         int mRows;
 628 
 629         if (data == null) {
 630             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.populate").toString());
 631         }
 632         this.resultSet = data;
 633 
 634         // get the meta data for this ResultSet
 635         RSMD = data.getMetaData();
 636 
 637         // set up the metadata
 638         RowSetMD = new RowSetMetaDataImpl();
 639         initMetaData(RowSetMD, RSMD);
 640 
 641         // release the meta-data so that aren't tempted to use it.
 642         RSMD = null;
 643         numCols = RowSetMD.getColumnCount();
 644         mRows = this.getMaxRows();
 645         rowsFetched = 0;
 646         currentRow = null;
 647 
 648         while ( data.next()) {
 649 
 650             currentRow = new Row(numCols);
 651 
 652             if ( rowsFetched > mRows && mRows > 0) {
 653                 rowsetWarning.setNextWarning(new RowSetWarning("Populating rows "
 654                 + "setting has exceeded max row setting"));
 655             }
 656             for ( i = 1; i <= numCols; i++) {
 657                 /*
 658                  * check if the user has set a map. If no map
 659                  * is set then use plain getObject. This lets
 660                  * us work with drivers that do not support
 661                  * getObject with a map in fairly sensible way
 662                  */
 663                 if (map == null || map.isEmpty()) {
 664                     obj = data.getObject(i);
 665                 } else {
 666                     obj = data.getObject(i, map);
 667                 }
 668                 /*
 669                  * the following block checks for the various
 670                  * types that we have to serialize in order to
 671                  * store - right now only structs have been tested
 672                  */
 673                 if (obj instanceof Struct) {
 674                     obj = new SerialStruct((Struct)obj, map);
 675                 } else if (obj instanceof SQLData) {
 676                     obj = new SerialStruct((SQLData)obj, map);
 677                 } else if (obj instanceof Blob) {
 678                     obj = new SerialBlob((Blob)obj);
 679                 } else if (obj instanceof Clob) {
 680                     obj = new SerialClob((Clob)obj);
 681                 } else if (obj instanceof java.sql.Array) {
 682                     if(map != null)
 683                         obj = new SerialArray((java.sql.Array)obj, map);
 684                     else
 685                         obj = new SerialArray((java.sql.Array)obj);
 686                 }
 687 
 688                 currentRow.initColumnObject(i, obj);
 689             }
 690             rowsFetched++;
 691             rvh.add(currentRow);
 692         }
 693 
 694         numRows = rowsFetched ;
 695         // Also rowsFetched should be equal to rvh.size()
 696 
 697         // notify any listeners that the rowset has changed
 698         notifyRowSetChanged();
 699 
 700 
 701     }
 702 
 703     /**
 704      * Initializes the given <code>RowSetMetaData</code> object with the values
 705      * in the given <code>ResultSetMetaData</code> object.
 706      *
 707      * @param md the <code>RowSetMetaData</code> object for this
 708      *           <code>CachedRowSetImpl</code> object, which will be set with
 709      *           values from rsmd
 710      * @param rsmd the <code>ResultSetMetaData</code> object from which new
 711      *             values for md will be read
 712      * @throws SQLException if an error occurs
 713      */
 714     private void initMetaData(RowSetMetaDataImpl md, ResultSetMetaData rsmd) throws SQLException {
 715         int numCols = rsmd.getColumnCount();
 716 
 717         md.setColumnCount(numCols);
 718         for (int col=1; col <= numCols; col++) {
 719             md.setAutoIncrement(col, rsmd.isAutoIncrement(col));
 720             if(rsmd.isAutoIncrement(col))
 721                 updateOnInsert = true;
 722             md.setCaseSensitive(col, rsmd.isCaseSensitive(col));
 723             md.setCurrency(col, rsmd.isCurrency(col));
 724             md.setNullable(col, rsmd.isNullable(col));
 725             md.setSigned(col, rsmd.isSigned(col));
 726             md.setSearchable(col, rsmd.isSearchable(col));
 727              /*
 728              * The PostgreSQL drivers sometimes return negative columnDisplaySize,
 729              * which causes an exception to be thrown.  Check for it.
 730              */
 731             int size = rsmd.getColumnDisplaySize(col);
 732             if (size < 0) {
 733                 size = 0;
 734             }
 735             md.setColumnDisplaySize(col, size);
 736             md.setColumnLabel(col, rsmd.getColumnLabel(col));
 737             md.setColumnName(col, rsmd.getColumnName(col));
 738             md.setSchemaName(col, rsmd.getSchemaName(col));
 739             /*
 740              * Drivers return some strange values for precision, for non-numeric data, including reports of
 741              * non-integer values; maybe we should check type, & set to 0 for non-numeric types.
 742              */
 743             int precision = rsmd.getPrecision(col);
 744             if (precision < 0) {
 745                 precision = 0;
 746             }
 747             md.setPrecision(col, precision);
 748 
 749             /*
 750              * It seems, from a bug report, that a driver can sometimes return a negative
 751              * value for scale.  javax.sql.rowset.RowSetMetaDataImpl will throw an exception
 752              * if we attempt to set a negative value.  As such, we'll check for this case.
 753              */
 754             int scale = rsmd.getScale(col);
 755             if (scale < 0) {
 756                 scale = 0;
 757             }
 758             md.setScale(col, scale);
 759             md.setTableName(col, rsmd.getTableName(col));
 760             md.setCatalogName(col, rsmd.getCatalogName(col));
 761             md.setColumnType(col, rsmd.getColumnType(col));
 762             md.setColumnTypeName(col, rsmd.getColumnTypeName(col));
 763         }
 764 
 765         if( conn != null){
 766            // JDBC 4.0 mandates as does the Java EE spec that all DataBaseMetaData methods
 767            // must be implemented, therefore, the previous fix for 5055528 is being backed out
 768             dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy();
 769         }
 770     }
 771 
 772     /**
 773      * Populates this <code>CachedRowSetImpl</code> object with data,
 774      * using the given connection to produce the result set from
 775      * which data will be read.  A second form of this method,
 776      * which takes no arguments, uses the values from this rowset's
 777      * user, password, and either url or data source properties to
 778      * create a new database connection. The form of <code>execute</code>
 779      * that is given a connection ignores these properties.
 780      *
 781      * @param conn A standard JDBC <code>Connection</code> object that this
 782      * <code>CachedRowSet</code> object can pass to a synchronization provider
 783      * to establish a connection to the data source
 784      * @throws SQLException if an invalid <code>Connection</code> is supplied
 785      *           or an error occurs in establishing the connection to the
 786      *           data source
 787      * @see #populate
 788      * @see java.sql.Connection
 789      */
 790     public void execute(Connection conn) throws SQLException {
 791         // store the connection so the reader can find it.
 792         setConnection(conn);
 793 
 794         if(getPageSize() != 0){
 795             crsReader = (CachedRowSetReader)provider.getRowSetReader();
 796             crsReader.setStartPosition(1);
 797             callWithCon = true;
 798             crsReader.readData((RowSetInternal)this);
 799         }
 800 
 801         // Now call the current reader's readData method
 802         else {
 803            rowSetReader.readData((RowSetInternal)this);
 804         }
 805         RowSetMD = (RowSetMetaDataImpl)this.getMetaData();
 806 
 807         if(conn != null){
 808             // JDBC 4.0 mandates as does the Java EE spec that all DataBaseMetaData methods
 809             // must be implemented, therefore, the previous fix for 5055528 is being backed out
 810             dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy();
 811         }
 812 
 813     }
 814 
 815     /**
 816      * Sets this <code>CachedRowSetImpl</code> object's connection property
 817      * to the given <code>Connection</code> object.  This method is called
 818      * internally by the version of the method <code>execute</code> that takes a
 819      * <code>Connection</code> object as an argument. The reader for this
 820      * <code>CachedRowSetImpl</code> object can retrieve the connection stored
 821      * in the rowset's connection property by calling its
 822      * <code>getConnection</code> method.
 823      *
 824      * @param connection the <code>Connection</code> object that was passed in
 825      *                   to the method <code>execute</code> and is to be stored
 826      *                   in this <code>CachedRowSetImpl</code> object's connection
 827      *                   property
 828      */
 829     private void setConnection (Connection connection) {
 830         conn = connection;
 831     }
 832 
 833 
 834     /**
 835      * Propagates all row update, insert, and delete changes to the
 836      * underlying data source backing this <code>CachedRowSetImpl</code>
 837      * object.
 838      * <P>
 839      * <b>Note</b>In the reference implementation an optimistic concurrency implementation
 840      * is provided as a sample implementation of a the <code>SyncProvider</code>
 841      * abstract class.
 842      * <P>
 843      * This method fails if any of the updates cannot be propagated back
 844      * to the data source.  When it fails, the caller can assume that
 845      * none of the updates are reflected in the data source.
 846      * When an exception is thrown, the current row
 847      * is set to the first "updated" row that resulted in an exception
 848      * unless the row that caused the exception is a "deleted" row.
 849      * In that case, when deleted rows are not shown, which is usually true,
 850      * the current row is not affected.
 851      * <P>
 852      * If no <code>SyncProvider</code> is configured, the reference implementation
 853      * leverages the <code>RIOptimisticProvider</code> available which provides the
 854      * default and reference synchronization capabilities for disconnected
 855      * <code>RowSets</code>.
 856      *
 857      * @throws SQLException if the cursor is on the insert row or the underlying
 858      *          reference synchronization provider fails to commit the updates
 859      *          to the datasource
 860      * @throws SyncProviderException if an internal error occurs within the
 861      *          <code>SyncProvider</code> instance during either during the
 862      *          process or at any time when the <code>SyncProvider</code>
 863      *          instance touches the data source.
 864      * @see #acceptChanges(java.sql.Connection)
 865      * @see javax.sql.RowSetWriter
 866      * @see javax.sql.rowset.spi.SyncProvider
 867      */
 868     public void acceptChanges() throws SyncProviderException {
 869         if (onInsertRow == true) {
 870             throw new SyncProviderException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
 871         }
 872 
 873         int saveCursorPos = cursorPos;
 874         boolean success = false;
 875         boolean conflict = false;
 876 
 877         try {
 878             if (rowSetWriter != null) {
 879                 saveCursorPos = cursorPos;
 880                 conflict = rowSetWriter.writeData((RowSetInternal)this);
 881                 cursorPos = saveCursorPos;
 882             }
 883 
 884             if (tXWriter) {
 885                 // do commit/rollback's here
 886                 if (!conflict) {
 887                     tWriter = (TransactionalWriter)rowSetWriter;
 888                     tWriter.rollback();
 889                     success = false;
 890                 } else {
 891                     tWriter = (TransactionalWriter)rowSetWriter;
 892                     if (tWriter instanceof CachedRowSetWriter) {
 893                         ((CachedRowSetWriter)tWriter).commit(this, updateOnInsert);
 894                     } else {
 895                         tWriter.commit();
 896                     }
 897 
 898                     success = true;
 899                 }
 900             }
 901 
 902             if (success == true) {
 903                 setOriginal();
 904             } else if (!(success) ) {
 905                 throw new SyncProviderException(resBundle.handleGetObject("cachedrowsetimpl.accfailed").toString());
 906             }
 907 
 908         } catch (SyncProviderException spe) {
 909                throw spe;
 910         } catch (SQLException e) {
 911             e.printStackTrace();
 912             throw new SyncProviderException(e.getMessage());
 913         } catch (SecurityException e) {
 914             throw new SyncProviderException(e.getMessage());
 915         }
 916     }
 917 
 918     /**
 919      * Propagates all row update, insert, and delete changes to the
 920      * data source backing this <code>CachedRowSetImpl</code> object
 921      * using the given <code>Connection</code> object.
 922      * <P>
 923      * The reference implementation <code>RIOptimisticProvider</code>
 924      * modifies its synchronization to a write back function given
 925      * the updated connection
 926      * The reference implementation modifies its synchronization behaviour
 927      * via the <code>SyncProvider</code> to ensure the synchronization
 928      * occurs according to the updated JDBC <code>Connection</code>
 929      * properties.
 930      *
 931      * @param con a standard JDBC <code>Connection</code> object
 932      * @throws SQLException if the cursor is on the insert row or the underlying
 933      *                   synchronization provider fails to commit the updates
 934      *                   back to the data source
 935      * @see #acceptChanges
 936      * @see javax.sql.RowSetWriter
 937      * @see javax.sql.rowset.spi.SyncFactory
 938      * @see javax.sql.rowset.spi.SyncProvider
 939      */
 940     public void acceptChanges(Connection con) throws SyncProviderException{
 941       setConnection(con);
 942       acceptChanges();
 943     }
 944 
 945     /**
 946      * Restores this <code>CachedRowSetImpl</code> object to its original state,
 947      * that is, its state before the last set of changes.
 948      * <P>
 949      * Before returning, this method moves the cursor before the first row
 950      * and sends a <code>rowSetChanged</code> event to all registered
 951      * listeners.
 952      * @throws SQLException if an error is occurs rolling back the RowSet
 953      *           state to the definied original value.
 954      * @see javax.sql.RowSetListener#rowSetChanged
 955      */
 956     public void restoreOriginal() throws SQLException {
 957         Row currentRow;
 958         for (Iterator<?> i = rvh.iterator(); i.hasNext();) {
 959             currentRow = (Row)i.next();
 960             if (currentRow.getInserted() == true) {
 961                 i.remove();
 962                 --numRows;
 963             } else {
 964                 if (currentRow.getDeleted() == true) {
 965                     currentRow.clearDeleted();
 966                 }
 967                 if (currentRow.getUpdated() == true) {
 968                     currentRow.clearUpdated();
 969                 }
 970             }
 971         }
 972         // move to before the first
 973         cursorPos = 0;
 974 
 975         // notify any listeners
 976         notifyRowSetChanged();
 977     }
 978 
 979     /**
 980      * Releases the current contents of this <code>CachedRowSetImpl</code>
 981      * object and sends a <code>rowSetChanged</code> event object to all
 982      * registered listeners.
 983      *
 984      * @throws SQLException if an error occurs flushing the contents of
 985      *           RowSet.
 986      * @see javax.sql.RowSetListener#rowSetChanged
 987      */
 988     public void release() throws SQLException {
 989         initContainer();
 990         notifyRowSetChanged();
 991     }
 992 
 993     /**
 994      * Cancels deletion of the current row and notifies listeners that
 995      * a row has changed.
 996      * <P>
 997      * Note:  This method can be ignored if deleted rows are not being shown,
 998      * which is the normal case.
 999      *
1000      * @throws SQLException if the cursor is not on a valid row
1001      */
1002     public void undoDelete() throws SQLException {
1003         if (getShowDeleted() == false) {
1004             return;
1005         }
1006         // make sure we are on a row
1007         checkCursor();
1008 
1009         // don't want this to happen...
1010         if (onInsertRow == true) {
1011             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1012         }
1013 
1014         Row currentRow = (Row)getCurrentRow();
1015         if (currentRow.getDeleted() == true) {
1016             currentRow.clearDeleted();
1017             --numDeleted;
1018             notifyRowChanged();
1019         }
1020     }
1021 
1022     /**
1023      * Immediately removes the current row from this
1024      * <code>CachedRowSetImpl</code> object if the row has been inserted, and
1025      * also notifies listeners the a row has changed.  An exception is thrown
1026      * if the row is not a row that has been inserted or the cursor is before
1027      * the first row, after the last row, or on the insert row.
1028      * <P>
1029      * This operation cannot be undone.
1030      *
1031      * @throws SQLException if an error occurs,
1032      *                         the cursor is not on a valid row,
1033      *                         or the row has not been inserted
1034      */
1035     public void undoInsert() throws SQLException {
1036         // make sure we are on a row
1037         checkCursor();
1038 
1039         // don't want this to happen...
1040         if (onInsertRow == true) {
1041             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1042         }
1043 
1044         Row currentRow = (Row)getCurrentRow();
1045         if (currentRow.getInserted() == true) {
1046             rvh.remove(cursorPos-1);
1047             --numRows;
1048             notifyRowChanged();
1049         } else {
1050             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.illegalop").toString());
1051         }
1052     }
1053 
1054     /**
1055      * Immediately reverses the last update operation if the
1056      * row has been modified. This method can be
1057      * called to reverse updates on a all columns until all updates in a row have
1058      * been rolled back to their originating state since the last synchronization
1059      * (<code>acceptChanges</code>) or population. This method may also be called
1060      * while performing updates to the insert row.
1061      * <P>
1062      * {@code undoUpdate} may be called at any time during the life-time of a
1063      * rowset, however after a synchronization has occurs this method has no
1064      * affect until further modification to the RowSet data occurs.
1065      *
1066      * @throws SQLException if cursor is before the first row, after the last
1067      *     row in rowset.
1068      * @see #undoDelete
1069      * @see #undoInsert
1070      * @see java.sql.ResultSet#cancelRowUpdates
1071      */
1072     public void undoUpdate() throws SQLException {
1073         // if on insert row, cancel the insert row
1074         // make the insert row flag,
1075         // cursorPos back to the current row
1076         moveToCurrentRow();
1077 
1078         // else if not on insert row
1079         // call undoUpdate or undoInsert
1080         undoDelete();
1081 
1082         undoInsert();
1083 
1084     }
1085 
1086     //--------------------------------------------------------------------
1087     // Views
1088     //--------------------------------------------------------------------
1089 
1090     /**
1091      * Returns a new <code>RowSet</code> object backed by the same data as
1092      * that of this <code>CachedRowSetImpl</code> object and sharing a set of cursors
1093      * with it. This allows cursors to interate over a shared set of rows, providing
1094      * multiple views of the underlying data.
1095      *
1096      * @return a <code>RowSet</code> object that is a copy of this <code>CachedRowSetImpl</code>
1097      * object and shares a set of cursors with it
1098      * @throws SQLException if an error occurs or cloning is
1099      *                         not supported
1100      * @see javax.sql.RowSetEvent
1101      * @see javax.sql.RowSetListener
1102      */
1103     public RowSet createShared() throws SQLException {
1104         RowSet clone;
1105         try {
1106             clone = (RowSet)clone();
1107         } catch (CloneNotSupportedException ex) {
1108             throw new SQLException(ex.getMessage());
1109         }
1110         return clone;
1111     }
1112 
1113     /**
1114      * Returns a new <code>RowSet</code> object containing by the same data
1115      * as this <code>CachedRowSetImpl</code> object.  This method
1116      * differs from the method <code>createCopy</code> in that it throws a
1117      * <code>CloneNotSupportedException</code> object instead of an
1118      * <code>SQLException</code> object, as the method <code>createShared</code>
1119      * does.  This <code>clone</code>
1120      * method is called internally by the method <code>createShared</code>,
1121      * which catches the <code>CloneNotSupportedException</code> object
1122      * and in turn throws a new <code>SQLException</code> object.
1123      *
1124      * @return a copy of this <code>CachedRowSetImpl</code> object
1125      * @throws CloneNotSupportedException if an error occurs when
1126      * attempting to clone this <code>CachedRowSetImpl</code> object
1127      * @see #createShared
1128      */
1129     protected Object clone() throws CloneNotSupportedException  {
1130         return (super.clone());
1131     }
1132 
1133     /**
1134      * Creates a <code>RowSet</code> object that is a deep copy of
1135      * this <code>CachedRowSetImpl</code> object's data, including
1136      * constraints.  Updates made
1137      * on a copy are not visible to the original rowset;
1138      * a copy of a rowset is completely independent from the original.
1139      * <P>
1140      * Making a copy saves the cost of creating an identical rowset
1141      * from first principles, which can be quite expensive.
1142      * For example, it can eliminate the need to query a
1143      * remote database server.
1144      * @return a new <code>CachedRowSet</code> object that is a deep copy
1145      *           of this <code>CachedRowSet</code> object and is
1146      *           completely independent from this <code>CachedRowSetImpl</code>
1147      *           object.
1148      * @throws SQLException if an error occurs in generating the copy of this
1149      *           of the <code>CachedRowSetImpl</code>
1150      * @see #createShared
1151      * @see javax.sql.RowSetEvent
1152      * @see javax.sql.RowSetListener
1153      */
1154     public CachedRowSet createCopy() throws SQLException {
1155         ObjectOutputStream out;
1156         ByteArrayOutputStream bOut = new ByteArrayOutputStream();
1157         try {
1158             out = new ObjectOutputStream(bOut);
1159             out.writeObject(this);
1160         } catch (IOException ex) {
1161             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1162         }
1163 
1164         ObjectInputStream in;
1165 
1166         try {
1167             ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
1168             in = new ObjectInputStream(bIn);
1169         } catch (StreamCorruptedException ex) {
1170             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1171         } catch (IOException ex) {
1172             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1173         }
1174 
1175         try {
1176             //return ((CachedRowSet)(in.readObject()));
1177             CachedRowSetImpl crsTemp = (CachedRowSetImpl)in.readObject();
1178             crsTemp.resBundle = this.resBundle;
1179             return ((CachedRowSet)crsTemp);
1180 
1181         } catch (ClassNotFoundException ex) {
1182             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1183         } catch (OptionalDataException ex) {
1184             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1185         } catch (IOException ex) {
1186             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1187         }
1188     }
1189 
1190     /**
1191      * Creates a <code>RowSet</code> object that is a copy of
1192      * this <code>CachedRowSetImpl</code> object's table structure
1193      * and the constraints only.
1194      * There will be no data in the object being returned.
1195      * Updates made on a copy are not visible to the original rowset.
1196      * <P>
1197      * This helps in getting the underlying XML schema which can
1198      * be used as the basis for populating a <code>WebRowSet</code>.
1199      *
1200      * @return a new <code>CachedRowSet</code> object that is a copy
1201      * of this <code>CachedRowSetImpl</code> object's schema and
1202      * retains all the constraints on the original rowset but contains
1203      * no data
1204      * @throws SQLException if an error occurs in generating the copy
1205      * of the <code>CachedRowSet</code> object
1206      * @see #createShared
1207      * @see #createCopy
1208      * @see #createCopyNoConstraints
1209      * @see javax.sql.RowSetEvent
1210      * @see javax.sql.RowSetListener
1211      */
1212     public CachedRowSet createCopySchema() throws SQLException {
1213         // Copy everything except data i.e all constraints
1214 
1215         // Store the number of rows of "this"
1216         // and make numRows equals zero.
1217         // and make data also zero.
1218         int nRows = numRows;
1219         numRows = 0;
1220 
1221         CachedRowSet crs = this.createCopy();
1222 
1223         // reset this object back to number of rows.
1224         numRows = nRows;
1225 
1226         return crs;
1227     }
1228 
1229     /**
1230      * Creates a <code>CachedRowSet</code> object that is a copy of
1231      * this <code>CachedRowSetImpl</code> object's data only.
1232      * All constraints set in this object will not be there
1233      * in the returning object.  Updates made
1234      * on a copy are not visible to the original rowset.
1235      *
1236      * @return a new <code>CachedRowSet</code> object that is a deep copy
1237      * of this <code>CachedRowSetImpl</code> object and is
1238      * completely independent from this <code>CachedRowSetImpl</code> object
1239      * @throws SQLException if an error occurs in generating the copy of the
1240      * of the <code>CachedRowSet</code>
1241      * @see #createShared
1242      * @see #createCopy
1243      * @see #createCopySchema
1244      * @see javax.sql.RowSetEvent
1245      * @see javax.sql.RowSetListener
1246      */
1247     public CachedRowSet createCopyNoConstraints() throws SQLException {
1248         // Copy the whole data ONLY without any constraints.
1249         CachedRowSetImpl crs;
1250         crs = (CachedRowSetImpl)this.createCopy();
1251 
1252         crs.initProperties();
1253         try {
1254             crs.unsetMatchColumn(crs.getMatchColumnIndexes());
1255         } catch(SQLException sqle) {
1256             //do nothing, if the setMatchColumn is not set.
1257         }
1258 
1259         try {
1260             crs.unsetMatchColumn(crs.getMatchColumnNames());
1261         } catch(SQLException sqle) {
1262             //do nothing, if the setMatchColumn is not set.
1263         }
1264 
1265         return crs;
1266     }
1267 
1268     /**
1269      * Converts this <code>CachedRowSetImpl</code> object to a collection
1270      * of tables. The sample implementation utilitizes the <code>TreeMap</code>
1271      * collection type.
1272      * This class guarantees that the map will be in ascending key order,
1273      * sorted according to the natural order for the key's class.
1274      *
1275      * @return a <code>Collection</code> object consisting of tables,
1276      *         each of which is a copy of a row in this
1277      *         <code>CachedRowSetImpl</code> object
1278      * @throws SQLException if an error occurs in generating the collection
1279      * @see #toCollection(int)
1280      * @see #toCollection(String)
1281      * @see java.util.TreeMap
1282      */
1283     public Collection<?> toCollection() throws SQLException {
1284 
1285         TreeMap<Integer, Object> tMap = new TreeMap<>();
1286 
1287         for (int i = 0; i<numRows; i++) {
1288             tMap.put(i, rvh.get(i));
1289         }
1290 
1291         return (tMap.values());
1292     }
1293 
1294     /**
1295      * Returns the specified column of this <code>CachedRowSetImpl</code> object
1296      * as a <code>Collection</code> object.  This method makes a copy of the
1297      * column's data and utilitizes the <code>Vector</code> to establish the
1298      * collection. The <code>Vector</code> class implements a growable array
1299      * objects allowing the individual components to be accessed using an
1300      * an integer index similar to that of an array.
1301      *
1302      * @return a <code>Collection</code> object that contains the value(s)
1303      *         stored in the specified column of this
1304      *         <code>CachedRowSetImpl</code>
1305      *         object
1306      * @throws SQLException if an error occurs generated the collection; or
1307      *          an invalid column is provided.
1308      * @see #toCollection()
1309      * @see #toCollection(String)
1310      * @see java.util.Vector
1311      */
1312     public Collection<?> toCollection(int column) throws SQLException {
1313 
1314         int nRows = numRows;
1315         Vector<Object> vec = new Vector<>(nRows);
1316 
1317         // create a copy
1318         CachedRowSetImpl crsTemp;
1319         crsTemp = (CachedRowSetImpl) this.createCopy();
1320 
1321         while(nRows!=0) {
1322             crsTemp.next();
1323             vec.add(crsTemp.getObject(column));
1324             nRows--;
1325         }
1326 
1327         return (Collection)vec;
1328     }
1329 
1330     /**
1331      * Returns the specified column of this <code>CachedRowSetImpl</code> object
1332      * as a <code>Collection</code> object.  This method makes a copy of the
1333      * column's data and utilitizes the <code>Vector</code> to establish the
1334      * collection. The <code>Vector</code> class implements a growable array
1335      * objects allowing the individual components to be accessed using an
1336      * an integer index similar to that of an array.
1337      *
1338      * @return a <code>Collection</code> object that contains the value(s)
1339      *         stored in the specified column of this
1340      *         <code>CachedRowSetImpl</code>
1341      *         object
1342      * @throws SQLException if an error occurs generated the collection; or
1343      *          an invalid column is provided.
1344      * @see #toCollection()
1345      * @see #toCollection(int)
1346      * @see java.util.Vector
1347      */
1348     public Collection<?> toCollection(String column) throws SQLException {
1349         return toCollection(getColIdxByName(column));
1350     }
1351 
1352     //--------------------------------------------------------------------
1353     // Advanced features
1354     //--------------------------------------------------------------------
1355 
1356 
1357     /**
1358      * Returns the <code>SyncProvider</code> implementation being used
1359      * with this <code>CachedRowSetImpl</code> implementation rowset.
1360      *
1361      * @return the SyncProvider used by the rowset. If not provider was
1362      *          set when the rowset was instantiated, the reference
1363      *          implementation (default) provider is returned.
1364      * @throws SQLException if error occurs while return the
1365      *          <code>SyncProvider</code> instance.
1366      */
1367     public SyncProvider getSyncProvider() throws SQLException {
1368         return provider;
1369     }
1370 
1371     /**
1372      * Sets the active <code>SyncProvider</code> and attempts to load
1373      * load the new provider using the <code>SyncFactory</code> SPI.
1374      *
1375      * @throws SQLException if an error occurs while resetting the
1376      *          <code>SyncProvider</code>.
1377      */
1378     public void setSyncProvider(String providerStr) throws SQLException {
1379         provider =
1380         SyncFactory.getInstance(providerStr);
1381 
1382         rowSetReader = provider.getRowSetReader();
1383         rowSetWriter = provider.getRowSetWriter();
1384     }
1385 
1386 
1387     //-----------------
1388     // methods inherited from RowSet
1389     //-----------------
1390 
1391 
1392 
1393 
1394 
1395 
1396     //---------------------------------------------------------------------
1397     // Reading and writing data
1398     //---------------------------------------------------------------------
1399 
1400     /**
1401      * Populates this <code>CachedRowSetImpl</code> object with data.
1402      * This form of the method uses the rowset's user, password, and url or
1403      * data source name properties to create a database
1404      * connection.  If properties that are needed
1405      * have not been set, this method will throw an exception.
1406      * <P>
1407      * Another form of this method uses an existing JDBC <code>Connection</code>
1408      * object instead of creating a new one; therefore, it ignores the
1409      * properties used for establishing a new connection.
1410      * <P>
1411      * The query specified by the command property is executed to create a
1412      * <code>ResultSet</code> object from which to retrieve data.
1413      * The current contents of the rowset are discarded, and the
1414      * rowset's metadata is also (re)set.  If there are outstanding updates,
1415      * they are also ignored.
1416      * <P>
1417      * The method <code>execute</code> closes any database connections that it
1418      * creates.
1419      *
1420      * @throws SQLException if an error occurs or the
1421      *                         necessary properties have not been set
1422      */
1423     public void execute() throws SQLException {
1424         execute(null);
1425     }
1426 
1427 
1428 
1429     //-----------------------------------
1430     // Methods inherited from ResultSet
1431     //-----------------------------------
1432 
1433     /**
1434      * Moves the cursor down one row from its current position and
1435      * returns <code>true</code> if the new cursor position is a
1436      * valid row.
1437      * The cursor for a new <code>ResultSet</code> object is initially
1438      * positioned before the first row. The first call to the method
1439      * <code>next</code> moves the cursor to the first row, making it
1440      * the current row; the second call makes the second row the
1441      * current row, and so on.
1442      *
1443      * <P>If an input stream from the previous row is open, it is
1444      * implicitly closed. The <code>ResultSet</code> object's warning
1445      * chain is cleared when a new row is read.
1446      *
1447      * @return <code>true</code> if the new current row is valid;
1448      *         <code>false</code> if there are no more rows
1449      * @throws SQLException if an error occurs or
1450      *            the cursor is not positioned in the rowset, before
1451      *            the first row, or after the last row
1452      */
1453     public boolean next() throws SQLException {
1454         /*
1455          * make sure things look sane. The cursor must be
1456          * positioned in the rowset or before first (0) or
1457          * after last (numRows + 1)
1458          */
1459         if (cursorPos < 0 || cursorPos >= numRows + 1) {
1460             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1461         }
1462         // now move and notify
1463         boolean ret = this.internalNext();
1464         notifyCursorMoved();
1465 
1466         return ret;
1467     }
1468 
1469     /**
1470      * Moves this <code>CachedRowSetImpl</code> object's cursor to the next
1471      * row and returns <code>true</code> if the cursor is still in the rowset;
1472      * returns <code>false</code> if the cursor has moved to the position after
1473      * the last row.
1474      * <P>
1475      * This method handles the cases where the cursor moves to a row that
1476      * has been deleted.
1477      * If this rowset shows deleted rows and the cursor moves to a row
1478      * that has been deleted, this method moves the cursor to the next
1479      * row until the cursor is on a row that has not been deleted.
1480      * <P>
1481      * The method <code>internalNext</code> is called by methods such as
1482      * <code>next</code>, <code>absolute</code>, and <code>relative</code>,
1483      * and, as its name implies, is only called internally.
1484      * <p>
1485      * This is a implementation only method and is not required as a standard
1486      * implementation of the <code>CachedRowSet</code> interface.
1487      *
1488      * @return <code>true</code> if the cursor is on a valid row in this
1489      *         rowset; <code>false</code> if it is after the last row
1490      * @throws SQLException if an error occurs
1491      */
1492     protected boolean internalNext() throws SQLException {
1493         boolean ret = false;
1494 
1495         do {
1496             if (cursorPos < numRows) {
1497                 ++cursorPos;
1498                 ret = true;
1499             } else if (cursorPos == numRows) {
1500                 // increment to after last
1501                 ++cursorPos;
1502                 ret = false;
1503                 break;
1504             }
1505         } while ((getShowDeleted() == false) && (rowDeleted() == true));
1506 
1507         /* each call to internalNext may increment cursorPos multiple
1508          * times however, the absolutePos only increments once per call.
1509          */
1510         if (ret == true)
1511             absolutePos++;
1512         else
1513             absolutePos = 0;
1514 
1515         return ret;
1516     }
1517 
1518     /**
1519      * Closes this <code>CachedRowSetImpl</code> objecy and releases any resources
1520      * it was using.
1521      *
1522      * @throws SQLException if an error occurs when releasing any resources in use
1523      * by this <code>CachedRowSetImpl</code> object
1524      */
1525     public void close() throws SQLException {
1526 
1527         // close all data structures holding
1528         // the disconnected rowset
1529 
1530         cursorPos = 0;
1531         absolutePos = 0;
1532         numRows = 0;
1533         numDeleted = 0;
1534 
1535         // set all insert(s), update(s) & delete(s),
1536         // if at all, to their initial values.
1537         initProperties();
1538 
1539         // clear the vector of it's present contents
1540         rvh.clear();
1541 
1542         // this will make it eligible for gc
1543         // rvh = null;
1544     }
1545 
1546     /**
1547      * Reports whether the last column read was SQL <code>NULL</code>.
1548      * Note that you must first call the method <code>getXXX</code>
1549      * on a column to try to read its value and then call the method
1550      * <code>wasNull</code> to determine whether the value was
1551      * SQL <code>NULL</code>.
1552      *
1553      * @return <code>true</code> if the value in the last column read
1554      *         was SQL <code>NULL</code>; <code>false</code> otherwise
1555      * @throws SQLException if an error occurs
1556      */
1557     public boolean wasNull() throws SQLException {
1558         return lastValueNull;
1559     }
1560 
1561     /**
1562      * Sets the field <code>lastValueNull</code> to the given
1563      * <code>boolean</code> value.
1564      *
1565      * @param value <code>true</code> to indicate that the value of
1566      *        the last column read was SQL <code>NULL</code>;
1567      *        <code>false</code> to indicate that it was not
1568      */
1569     private void setLastValueNull(boolean value) {
1570         lastValueNull = value;
1571     }
1572 
1573     // Methods for accessing results by column index
1574 
1575     /**
1576      * Checks to see whether the given index is a valid column number
1577      * in this <code>CachedRowSetImpl</code> object and throws
1578      * an <code>SQLException</code> if it is not. The index is out of bounds
1579      * if it is less than <code>1</code> or greater than the number of
1580      * columns in this rowset.
1581      * <P>
1582      * This method is called internally by the <code>getXXX</code> and
1583      * <code>updateXXX</code> methods.
1584      *
1585      * @param idx the number of a column in this <code>CachedRowSetImpl</code>
1586      *            object; must be between <code>1</code> and the number of
1587      *            rows in this rowset
1588      * @throws SQLException if the given index is out of bounds
1589      */
1590     private void checkIndex(int idx) throws SQLException {
1591         if (idx < 1 || idx > RowSetMD.getColumnCount()) {
1592             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcol").toString());
1593         }
1594     }
1595 
1596     /**
1597      * Checks to see whether the cursor for this <code>CachedRowSetImpl</code>
1598      * object is on a row in the rowset and throws an
1599      * <code>SQLException</code> if it is not.
1600      * <P>
1601      * This method is called internally by <code>getXXX</code> methods, by
1602      * <code>updateXXX</code> methods, and by methods that update, insert,
1603      * or delete a row or that cancel a row update, insert, or delete.
1604      *
1605      * @throws SQLException if the cursor for this <code>CachedRowSetImpl</code>
1606      *         object is not on a valid row
1607      */
1608     private void checkCursor() throws SQLException {
1609         if (isAfterLast() == true || isBeforeFirst() == true) {
1610             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1611         }
1612     }
1613 
1614     /**
1615      * Returns the column number of the column with the given name in this
1616      * <code>CachedRowSetImpl</code> object.  This method throws an
1617      * <code>SQLException</code> if the given name is not the name of
1618      * one of the columns in this rowset.
1619      *
1620      * @param name a <code>String</code> object that is the name of a column in
1621      *              this <code>CachedRowSetImpl</code> object
1622      * @throws SQLException if the given name does not match the name of one of
1623      *         the columns in this rowset
1624      */
1625     private int getColIdxByName(String name) throws SQLException {
1626         RowSetMD = (RowSetMetaDataImpl)this.getMetaData();
1627         int cols = RowSetMD.getColumnCount();
1628 
1629         for (int i=1; i <= cols; ++i) {
1630             String colName = RowSetMD.getColumnName(i);
1631             if (colName != null)
1632                 if (name.equalsIgnoreCase(colName))
1633                     return (i);
1634                 else
1635                     continue;
1636         }
1637         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalcolnm").toString());
1638 
1639     }
1640 
1641     /**
1642      * Returns the insert row or the current row of this
1643      * <code>CachedRowSetImpl</code>object.
1644      *
1645      * @return the <code>Row</code> object on which this <code>CachedRowSetImpl</code>
1646      * objects's cursor is positioned
1647      */
1648     protected BaseRow getCurrentRow() {
1649         if (onInsertRow == true) {
1650             return (BaseRow)insertRow;
1651         } else {
1652             return (BaseRow)(rvh.get(cursorPos - 1));
1653         }
1654     }
1655 
1656     /**
1657      * Removes the row on which the cursor is positioned.
1658      * <p>
1659      * This is a implementation only method and is not required as a standard
1660      * implementation of the <code>CachedRowSet</code> interface.
1661      *
1662      * @throws SQLException if the cursor is positioned on the insert
1663      *            row
1664      */
1665     protected void removeCurrentRow() {
1666         ((Row)getCurrentRow()).setDeleted();
1667         rvh.remove(cursorPos - 1);
1668         --numRows;
1669     }
1670 
1671 
1672     /**
1673      * Retrieves the value of the designated column in the current row
1674      * of this <code>CachedRowSetImpl</code> object as a
1675      * <code>String</code> object.
1676      *
1677      * @param columnIndex the first column is <code>1</code>, the second
1678      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1679      *        and equal to or less than the number of columns in the rowset
1680      * @return the column value; if the value is SQL <code>NULL</code>, the
1681      *         result is <code>null</code>
1682      * @throws SQLException if (1) the given column index is out of bounds,
1683      * (2) the cursor is not on one of this rowset's rows or its
1684      * insert row, or (3) the designated column does not store an
1685      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
1686      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, <b>CHAR</b>, <b>VARCHAR</b></code>
1687      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1688      * recommended return type.
1689      */
1690     public String getString(int columnIndex) throws SQLException {
1691         Object value;
1692 
1693         // sanity check.
1694         checkIndex(columnIndex);
1695         // make sure the cursor is on a valid row
1696         checkCursor();
1697 
1698         setLastValueNull(false);
1699         value = getCurrentRow().getColumnObject(columnIndex);
1700 
1701         // check for SQL NULL
1702         if (value == null) {
1703             setLastValueNull(true);
1704             return null;
1705         }
1706 
1707         return value.toString();
1708     }
1709 
1710     /**
1711      * Retrieves the value of the designated column in the current row
1712      * of this <code>CachedRowSetImpl</code> object as a
1713      * <code>boolean</code> value.
1714      *
1715      * @param columnIndex the first column is <code>1</code>, the second
1716      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1717      *        and equal to or less than the number of columns in the rowset
1718      * @return the column value as a <code>boolean</code> in the Java progamming language;
1719      *        if the value is SQL <code>NULL</code>, the result is <code>false</code>
1720      * @throws SQLException if (1) the given column index is out of bounds,
1721      *            (2) the cursor is not on one of this rowset's rows or its
1722      *            insert row, or (3) the designated column does not store an
1723      *            SQL <code>BOOLEAN</code> value
1724      * @see #getBoolean(String)
1725      */
1726     public boolean getBoolean(int columnIndex) throws SQLException {
1727         Object value;
1728 
1729         // sanity check.
1730         checkIndex(columnIndex);
1731         // make sure the cursor is on a valid row
1732         checkCursor();
1733 
1734         setLastValueNull(false);
1735         value = getCurrentRow().getColumnObject(columnIndex);
1736 
1737         // check for SQL NULL
1738         if (value == null) {
1739             setLastValueNull(true);
1740             return false;
1741         }
1742 
1743         // check for Boolean...
1744         if (value instanceof Boolean) {
1745             return ((Boolean)value).booleanValue();
1746         }
1747 
1748         // convert to a Double and compare to zero
1749         try {
1750             return Double.compare(Double.parseDouble(value.toString()), 0) != 0;
1751         } catch (NumberFormatException ex) {
1752             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.boolfail").toString(),
1753                   new Object[] {value.toString().trim(), columnIndex}));
1754         }
1755     }
1756 
1757     /**
1758      * Retrieves the value of the designated column in the current row
1759      * of this <code>CachedRowSetImpl</code> object as a
1760      * <code>byte</code> value.
1761      *
1762      * @param columnIndex the first column is <code>1</code>, the second
1763      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1764      *        and equal to or less than the number of columns in the rowset
1765      * @return the column value as a <code>byte</code> in the Java programming
1766      * language; if the value is SQL <code>NULL</code>, the result is <code>0</code>
1767      * @throws SQLException if (1) the given column index is out of bounds,
1768      *            (2) the cursor is not on one of this rowset's rows or its
1769      *            insert row, or (3) the designated column does not store an
1770      *            SQL <code><b>TINYINT</b>, SMALLINT, INTEGER, BIGINT, REAL,
1771      *            FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1772      *            or <code>LONGVARCHAR</code> value. The bold SQL type
1773      *            designates the recommended return type.
1774      * @see #getByte(String)
1775      */
1776     public byte getByte(int columnIndex) throws SQLException {
1777         Object value;
1778 
1779         // sanity check.
1780         checkIndex(columnIndex);
1781         // make sure the cursor is on a valid row
1782         checkCursor();
1783 
1784         setLastValueNull(false);
1785         value = getCurrentRow().getColumnObject(columnIndex);
1786 
1787         // check for SQL NULL
1788         if (value == null) {
1789             setLastValueNull(true);
1790             return (byte)0;
1791         }
1792         try {
1793             return ((Byte.valueOf(value.toString())).byteValue());
1794         } catch (NumberFormatException ex) {
1795             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.bytefail").toString(),
1796                   new Object[] {value.toString().trim(), columnIndex}));
1797         }
1798     }
1799 
1800     /**
1801      * Retrieves the value of the designated column in the current row
1802      * of this <code>CachedRowSetImpl</code> object as a
1803      * <code>short</code> value.
1804      *
1805      * @param columnIndex the first column is <code>1</code>, the second
1806      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1807      *        and equal to or less than the number of columns in the rowset
1808      * @return the column value; if the value is SQL <code>NULL</code>, the
1809      *         result is <code>0</code>
1810      * @throws SQLException if (1) the given column index is out of bounds,
1811      * (2) the cursor is not on one of this rowset's rows or its
1812      * insert row, or (3) the designated column does not store an
1813      * SQL <code>TINYINT, <b>SMALLINT</b>, INTEGER, BIGINT, REAL
1814      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1815      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1816      * recommended return type.
1817      * @see #getShort(String)
1818      */
1819     public short getShort(int columnIndex) throws SQLException {
1820         Object value;
1821 
1822         // sanity check.
1823         checkIndex(columnIndex);
1824         // make sure the cursor is on a valid row
1825         checkCursor();
1826 
1827         setLastValueNull(false);
1828         value = getCurrentRow().getColumnObject(columnIndex);
1829 
1830         // check for SQL NULL
1831         if (value == null) {
1832             setLastValueNull(true);
1833             return (short)0;
1834         }
1835 
1836         try {
1837             return ((Short.valueOf(value.toString().trim())).shortValue());
1838         } catch (NumberFormatException ex) {
1839             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.shortfail").toString(),
1840                   new Object[] {value.toString().trim(), columnIndex}));
1841         }
1842     }
1843 
1844     /**
1845      * Retrieves the value of the designated column in the current row
1846      * of this <code>CachedRowSetImpl</code> object as an
1847      * <code>int</code> value.
1848      *
1849      * @param columnIndex the first column is <code>1</code>, the second
1850      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1851      *        and equal to or less than the number of columns in the rowset
1852      * @return the column value; if the value is SQL <code>NULL</code>, the
1853      *         result is <code>0</code>
1854      * @throws SQLException if (1) the given column index is out of bounds,
1855      * (2) the cursor is not on one of this rowset's rows or its
1856      * insert row, or (3) the designated column does not store an
1857      * SQL <code>TINYINT, SMALLINT, <b>INTEGER</b>, BIGINT, REAL
1858      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1859      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1860      * recommended return type.
1861      */
1862     public int getInt(int columnIndex) throws SQLException {
1863         Object value;
1864 
1865         // sanity check.
1866         checkIndex(columnIndex);
1867         // make sure the cursor is on a valid row
1868         checkCursor();
1869 
1870         setLastValueNull(false);
1871         value = getCurrentRow().getColumnObject(columnIndex);
1872 
1873         // check for SQL NULL
1874         if (value == null) {
1875             setLastValueNull(true);
1876             return 0;
1877         }
1878 
1879         try {
1880             return ((Integer.valueOf(value.toString().trim())).intValue());
1881         } catch (NumberFormatException ex) {
1882             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.intfail").toString(),
1883                   new Object[] {value.toString().trim(), columnIndex}));
1884         }
1885     }
1886 
1887     /**
1888      * Retrieves the value of the designated column in the current row
1889      * of this <code>CachedRowSetImpl</code> object as a
1890      * <code>long</code> value.
1891      *
1892      * @param columnIndex the first column is <code>1</code>, the second
1893      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1894      *        and equal to or less than the number of columns in the rowset
1895      * @return the column value; if the value is SQL <code>NULL</code>, the
1896      *         result is <code>0</code>
1897      * @throws SQLException if (1) the given column index is out of bounds,
1898      * (2) the cursor is not on one of this rowset's rows or its
1899      * insert row, or (3) the designated column does not store an
1900      * SQL <code>TINYINT, SMALLINT, INTEGER, <b>BIGINT</b>, REAL
1901      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1902      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1903      * recommended return type.
1904      * @see #getLong(String)
1905      */
1906     public long getLong(int columnIndex) throws SQLException {
1907         Object value;
1908 
1909         // sanity check.
1910         checkIndex(columnIndex);
1911         // make sure the cursor is on a valid row
1912         checkCursor();
1913 
1914         setLastValueNull(false);
1915         value = getCurrentRow().getColumnObject(columnIndex);
1916 
1917         // check for SQL NULL
1918         if (value == null) {
1919             setLastValueNull(true);
1920             return (long)0;
1921         }
1922         try {
1923             return ((Long.valueOf(value.toString().trim())).longValue());
1924         } catch (NumberFormatException ex) {
1925             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.longfail").toString(),
1926                   new Object[] {value.toString().trim(), columnIndex}));
1927         }
1928     }
1929 
1930     /**
1931      * Retrieves the value of the designated column in the current row
1932      * of this <code>CachedRowSetImpl</code> object as a
1933      * <code>float</code> value.
1934      *
1935      * @param columnIndex the first column is <code>1</code>, the second
1936      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1937      *        and equal to or less than the number of columns in the rowset
1938      * @return the column value; if the value is SQL <code>NULL</code>, the
1939      *         result is <code>0</code>
1940      * @throws SQLException if (1) the given column index is out of bounds,
1941      * (2) the cursor is not on one of this rowset's rows or its
1942      * insert row, or (3) the designated column does not store an
1943      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, <b>REAL</b>,
1944      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1945      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1946      * recommended return type.
1947      * @see #getFloat(String)
1948      */
1949     public float getFloat(int columnIndex) throws SQLException {
1950         Object value;
1951 
1952         // sanity check.
1953         checkIndex(columnIndex);
1954         // make sure the cursor is on a valid row
1955         checkCursor();
1956 
1957         setLastValueNull(false);
1958         value = getCurrentRow().getColumnObject(columnIndex);
1959 
1960         // check for SQL NULL
1961         if (value == null) {
1962             setLastValueNull(true);
1963             return (float)0;
1964         }
1965         try {
1966             return Float.parseFloat(value.toString());
1967         } catch (NumberFormatException ex) {
1968             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.floatfail").toString(),
1969                   new Object[] {value.toString().trim(), columnIndex}));
1970         }
1971     }
1972 
1973     /**
1974      * Retrieves the value of the designated column in the current row
1975      * of this <code>CachedRowSetImpl</code> object as a
1976      * <code>double</code> value.
1977      *
1978      * @param columnIndex the first column is <code>1</code>, the second
1979      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1980      *        and equal to or less than the number of columns in the rowset
1981      * @return the column value; if the value is SQL <code>NULL</code>, the
1982      *         result is <code>0</code>
1983      * @throws SQLException if (1) the given column index is out of bounds,
1984      * (2) the cursor is not on one of this rowset's rows or its
1985      * insert row, or (3) the designated column does not store an
1986      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
1987      * <b>FLOAT</b>, <b>DOUBLE</b>, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1988      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1989      * recommended return type.
1990      * @see #getDouble(String)
1991      *
1992      */
1993     public double getDouble(int columnIndex) throws SQLException {
1994         Object value;
1995 
1996         // sanity check.
1997         checkIndex(columnIndex);
1998         // make sure the cursor is on a valid row
1999         checkCursor();
2000 
2001         setLastValueNull(false);
2002         value = getCurrentRow().getColumnObject(columnIndex);
2003 
2004         // check for SQL NULL
2005         if (value == null) {
2006             setLastValueNull(true);
2007             return (double)0;
2008         }
2009         try {
2010             return Double.parseDouble(value.toString().trim());
2011         } catch (NumberFormatException ex) {
2012             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.doublefail").toString(),
2013                   new Object[] {value.toString().trim(), columnIndex}));
2014         }
2015     }
2016 
2017     /**
2018      * Retrieves the value of the designated column in the current row
2019      * of this <code>CachedRowSetImpl</code> object as a
2020      * <code>java.math.BigDecimal</code> object.
2021      * <P>
2022      * This method is deprecated; use the version of <code>getBigDecimal</code>
2023      * that does not take a scale parameter and returns a value with full
2024      * precision.
2025      *
2026      * @param columnIndex the first column is <code>1</code>, the second
2027      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2028      *        and equal to or less than the number of columns in the rowset
2029      * @param scale the number of digits to the right of the decimal point in the
2030      *        value returned
2031      * @return the column value with the specified number of digits to the right
2032      *         of the decimal point; if the value is SQL <code>NULL</code>, the
2033      *         result is <code>null</code>
2034      * @throws SQLException if the given column index is out of bounds,
2035      *            the cursor is not on a valid row, or this method fails
2036      * @deprecated
2037      */
2038     @Deprecated
2039     public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
2040         Object value;
2041         BigDecimal bDecimal, retVal;
2042 
2043         // sanity check.
2044         checkIndex(columnIndex);
2045         // make sure the cursor is on a valid row
2046         checkCursor();
2047 
2048         setLastValueNull(false);
2049         value = getCurrentRow().getColumnObject(columnIndex);
2050 
2051         // check for SQL NULL
2052         if (value == null) {
2053             setLastValueNull(true);
2054             return (new BigDecimal(0));
2055         }
2056 
2057         bDecimal = this.getBigDecimal(columnIndex);
2058 
2059         retVal = bDecimal.setScale(scale);
2060 
2061         return retVal;
2062     }
2063 
2064     /**
2065      * Retrieves the value of the designated column in the current row
2066      * of this <code>CachedRowSetImpl</code> object as a
2067      * <code>byte</code> array value.
2068      *
2069      * @param columnIndex the first column is <code>1</code>, the second
2070      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2071      *        and equal to or less than the number of columns in the rowset
2072      * @return the column value as a <code>byte</code> array in the Java programming
2073      * language; if the value is SQL <code>NULL</code>, the
2074      * result is <code>null</code>
2075      *
2076      * @throws SQLException if (1) the given column index is out of bounds,
2077      * (2) the cursor is not on one of this rowset's rows or its
2078      * insert row, or (3) the designated column does not store an
2079      * SQL <code><b>BINARY</b>, <b>VARBINARY</b> or
2080      * LONGVARBINARY</code> value.
2081      * The bold SQL type designates the recommended return type.
2082      * @see #getBytes(String)
2083      */
2084     public byte[] getBytes(int columnIndex) throws SQLException {
2085         // sanity check.
2086         checkIndex(columnIndex);
2087         // make sure the cursor is on a valid row
2088         checkCursor();
2089 
2090         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
2091             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2092         }
2093 
2094         return (byte[])(getCurrentRow().getColumnObject(columnIndex));
2095     }
2096 
2097     /**
2098      * Retrieves the value of the designated column in the current row
2099      * of this <code>CachedRowSetImpl</code> object as a
2100      * <code>java.sql.Date</code> object.
2101      *
2102      * @param columnIndex the first column is <code>1</code>, the second
2103      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2104      *        and equal to or less than the number of columns in the rowset
2105      * @return the column value as a <code>java.sql.Data</code> object; if
2106      *        the value is SQL <code>NULL</code>, the
2107      *        result is <code>null</code>
2108      * @throws SQLException if the given column index is out of bounds,
2109      *            the cursor is not on a valid row, or this method fails
2110      */
2111     public java.sql.Date getDate(int columnIndex) throws SQLException {
2112         Object value;
2113 
2114         // sanity check.
2115         checkIndex(columnIndex);
2116         // make sure the cursor is on a valid row
2117         checkCursor();
2118 
2119         setLastValueNull(false);
2120         value = getCurrentRow().getColumnObject(columnIndex);
2121 
2122         // check for SQL NULL
2123         if (value == null) {
2124             setLastValueNull(true);
2125             return null;
2126         }
2127 
2128         /*
2129          * The object coming back from the db could be
2130          * a date, a timestamp, or a char field variety.
2131          * If it's a date type return it, a timestamp
2132          * we turn into a long and then into a date,
2133          * char strings we try to parse. Yuck.
2134          */
2135         switch (RowSetMD.getColumnType(columnIndex)) {
2136             case java.sql.Types.DATE: {
2137                 long sec = ((java.sql.Date)value).getTime();
2138                 return new java.sql.Date(sec);
2139             }
2140             case java.sql.Types.TIMESTAMP: {
2141                 long sec = ((java.sql.Timestamp)value).getTime();
2142                 return new java.sql.Date(sec);
2143             }
2144             case java.sql.Types.CHAR:
2145             case java.sql.Types.VARCHAR:
2146             case java.sql.Types.LONGVARCHAR: {
2147                 try {
2148                     DateFormat df = DateFormat.getDateInstance();
2149                     return ((java.sql.Date)(df.parse(value.toString())));
2150                 } catch (ParseException ex) {
2151                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.datefail").toString(),
2152                         new Object[] {value.toString().trim(), columnIndex}));
2153                 }
2154             }
2155             default: {
2156                 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.datefail").toString(),
2157                         new Object[] {value.toString().trim(), columnIndex}));
2158             }
2159         }
2160     }
2161 
2162     /**
2163      * Retrieves the value of the designated column in the current row
2164      * of this <code>CachedRowSetImpl</code> object as a
2165      * <code>java.sql.Time</code> object.
2166      *
2167      * @param columnIndex the first column is <code>1</code>, the second
2168      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2169      *        and equal to or less than the number of columns in the rowset
2170      * @return the column value; if the value is SQL <code>NULL</code>, the
2171      *         result is <code>null</code>
2172      * @throws SQLException if the given column index is out of bounds,
2173      *         the cursor is not on a valid row, or this method fails
2174      */
2175     public java.sql.Time getTime(int columnIndex) throws SQLException {
2176         Object value;
2177 
2178         // sanity check.
2179         checkIndex(columnIndex);
2180         // make sure the cursor is on a valid row
2181         checkCursor();
2182 
2183         setLastValueNull(false);
2184         value = getCurrentRow().getColumnObject(columnIndex);
2185 
2186         // check for SQL NULL
2187         if (value == null) {
2188             setLastValueNull(true);
2189             return null;
2190         }
2191 
2192         /*
2193          * The object coming back from the db could be
2194          * a date, a timestamp, or a char field variety.
2195          * If it's a date type return it, a timestamp
2196          * we turn into a long and then into a date,
2197          * char strings we try to parse. Yuck.
2198          */
2199         switch (RowSetMD.getColumnType(columnIndex)) {
2200             case java.sql.Types.TIME: {
2201                 return (java.sql.Time)value;
2202             }
2203             case java.sql.Types.TIMESTAMP: {
2204                 long sec = ((java.sql.Timestamp)value).getTime();
2205                 return new java.sql.Time(sec);
2206             }
2207             case java.sql.Types.CHAR:
2208             case java.sql.Types.VARCHAR:
2209             case java.sql.Types.LONGVARCHAR: {
2210                 try {
2211                     DateFormat tf = DateFormat.getTimeInstance();
2212                     return ((java.sql.Time)(tf.parse(value.toString())));
2213                 } catch (ParseException ex) {
2214                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2215                         new Object[] {value.toString().trim(), columnIndex}));
2216                 }
2217             }
2218             default: {
2219                 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2220                         new Object[] {value.toString().trim(), columnIndex}));
2221             }
2222         }
2223     }
2224 
2225     /**
2226      * Retrieves the value of the designated column in the current row
2227      * of this <code>CachedRowSetImpl</code> object as a
2228      * <code>java.sql.Timestamp</code> object.
2229      *
2230      * @param columnIndex the first column is <code>1</code>, the second
2231      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2232      *        and equal to or less than the number of columns in the rowset
2233      * @return the column value; if the value is SQL <code>NULL</code>, the
2234      *         result is <code>null</code>
2235      * @throws SQLException if the given column index is out of bounds,
2236      *            the cursor is not on a valid row, or this method fails
2237      */
2238     public java.sql.Timestamp getTimestamp(int columnIndex) throws SQLException {
2239         Object value;
2240 
2241         // sanity check.
2242         checkIndex(columnIndex);
2243         // make sure the cursor is on a valid row
2244         checkCursor();
2245 
2246         setLastValueNull(false);
2247         value = getCurrentRow().getColumnObject(columnIndex);
2248 
2249         // check for SQL NULL
2250         if (value == null) {
2251             setLastValueNull(true);
2252             return null;
2253         }
2254 
2255         /*
2256          * The object coming back from the db could be
2257          * a date, a timestamp, or a char field variety.
2258          * If it's a date type return it; a timestamp
2259          * we turn into a long and then into a date;
2260          * char strings we try to parse. Yuck.
2261          */
2262         switch (RowSetMD.getColumnType(columnIndex)) {
2263             case java.sql.Types.TIMESTAMP: {
2264                 return (java.sql.Timestamp)value;
2265             }
2266             case java.sql.Types.TIME: {
2267                 long sec = ((java.sql.Time)value).getTime();
2268                 return new java.sql.Timestamp(sec);
2269             }
2270             case java.sql.Types.DATE: {
2271                 long sec = ((java.sql.Date)value).getTime();
2272                 return new java.sql.Timestamp(sec);
2273             }
2274             case java.sql.Types.CHAR:
2275             case java.sql.Types.VARCHAR:
2276             case java.sql.Types.LONGVARCHAR: {
2277                 try {
2278                     DateFormat tf = DateFormat.getTimeInstance();
2279                     return ((java.sql.Timestamp)(tf.parse(value.toString())));
2280                 } catch (ParseException ex) {
2281                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2282                         new Object[] {value.toString().trim(), columnIndex}));
2283                 }
2284             }
2285             default: {
2286                 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2287                         new Object[] {value.toString().trim(), columnIndex}));
2288             }
2289         }
2290     }
2291 
2292     /**
2293      * Retrieves the value of the designated column in the current row of this
2294      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2295      * object.
2296      *
2297      * A column value can be retrieved as a stream of ASCII characters
2298      * and then read in chunks from the stream.  This method is particularly
2299      * suitable for retrieving large <code>LONGVARCHAR</code> values.  The JDBC
2300      * driver will do any necessary conversion from the database format into ASCII.
2301      *
2302      * <P><B>Note:</B> All the data in the returned stream must be
2303      * read prior to getting the value of any other column. The next
2304      * call to a get method implicitly closes the stream. . Also, a
2305      * stream may return <code>0</code> for <code>CachedRowSetImpl.available()</code>
2306      * whether there is data available or not.
2307      *
2308      * @param columnIndex the first column is <code>1</code>, the second
2309      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2310      *        and equal to or less than the number of columns in this rowset
2311      * @return a Java input stream that delivers the database column value
2312      *         as a stream of one-byte ASCII characters.  If the value is SQL
2313      *         <code>NULL</code>, the result is <code>null</code>.
2314      * @throws SQLException if (1) the given column index is out of bounds,
2315      * (2) the cursor is not on one of this rowset's rows or its
2316      * insert row, or (3) the designated column does not store an
2317      * SQL <code>CHAR, VARCHAR</code>, <code><b>LONGVARCHAR</b></code>
2318      * <code>BINARY, VARBINARY</code> or <code>LONGVARBINARY</code> value. The
2319      * bold SQL type designates the recommended return types that this method is
2320      * used to retrieve.
2321      * @see #getAsciiStream(String)
2322      */
2323     public java.io.InputStream getAsciiStream(int columnIndex) throws SQLException {
2324         Object value;
2325 
2326         // always free an old stream
2327         asciiStream = null;
2328 
2329         // sanity check
2330         checkIndex(columnIndex);
2331         //make sure the cursor is on a vlid row
2332         checkCursor();
2333 
2334         value =  getCurrentRow().getColumnObject(columnIndex);
2335         if (value == null) {
2336             lastValueNull = true;
2337             return null;
2338         }
2339 
2340         try {
2341             if (isString(RowSetMD.getColumnType(columnIndex))) {
2342                 asciiStream = new ByteArrayInputStream(((String)value).getBytes("ASCII"));
2343             } else {
2344                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2345             }
2346         } catch (java.io.UnsupportedEncodingException ex) {
2347             throw new SQLException(ex.getMessage());
2348         }
2349 
2350         return asciiStream;
2351     }
2352 
2353     /**
2354      * A column value can be retrieved as a stream of Unicode characters
2355      * and then read in chunks from the stream.  This method is particularly
2356      * suitable for retrieving large LONGVARCHAR values.  The JDBC driver will
2357      * do any necessary conversion from the database format into Unicode.
2358      *
2359      * <P><B>Note:</B> All the data in the returned stream must be
2360      * read prior to getting the value of any other column. The next
2361      * call to a get method implicitly closes the stream. . Also, a
2362      * stream may return 0 for available() whether there is data
2363      * available or not.
2364      *
2365      * @param columnIndex the first column is <code>1</code>, the second
2366      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2367      *        and equal to or less than the number of columns in this rowset
2368      * @return a Java input stream that delivers the database column value
2369      * as a stream of two byte Unicode characters.  If the value is SQL NULL
2370      * then the result is null.
2371      * @throws SQLException if an error occurs
2372      * @deprecated
2373      */
2374     @Deprecated
2375     public java.io.InputStream getUnicodeStream(int columnIndex) throws SQLException {
2376         // always free an old stream
2377         unicodeStream = null;
2378 
2379         // sanity check.
2380         checkIndex(columnIndex);
2381         // make sure the cursor is on a valid row
2382         checkCursor();
2383 
2384         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false &&
2385         isString(RowSetMD.getColumnType(columnIndex)) == false) {
2386             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2387         }
2388 
2389         Object value = getCurrentRow().getColumnObject(columnIndex);
2390         if (value == null) {
2391             lastValueNull = true;
2392             return null;
2393         }
2394 
2395         unicodeStream = new StringBufferInputStream(value.toString());
2396 
2397         return unicodeStream;
2398     }
2399 
2400     /**
2401      * Retrieves the value of the designated column in the current row of this
2402      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2403      * object.
2404      * <P>
2405      * A column value can be retrieved as a stream of uninterpreted bytes
2406      * and then read in chunks from the stream.  This method is particularly
2407      * suitable for retrieving large <code>LONGVARBINARY</code> values.
2408      *
2409      * <P><B>Note:</B> All the data in the returned stream must be
2410      * read prior to getting the value of any other column. The next
2411      * call to a get method implicitly closes the stream. Also, a
2412      * stream may return <code>0</code> for
2413      * <code>CachedRowSetImpl.available()</code> whether there is data
2414      * available or not.
2415      *
2416      * @param columnIndex the first column is <code>1</code>, the second
2417      * is <code>2</code>, and so on; must be <code>1</code> or larger
2418      * and equal to or less than the number of columns in the rowset
2419      * @return a Java input stream that delivers the database column value
2420      * as a stream of uninterpreted bytes.  If the value is SQL <code>NULL</code>
2421      * then the result is <code>null</code>.
2422      * @throws SQLException if (1) the given column index is out of bounds,
2423      * (2) the cursor is not on one of this rowset's rows or its
2424      * insert row, or (3) the designated column does not store an
2425      * SQL <code>BINARY, VARBINARY</code> or <code><b>LONGVARBINARY</b></code>
2426      * The bold type indicates the SQL type that this method is recommened
2427      * to retrieve.
2428      * @see #getBinaryStream(String)
2429      */
2430     public java.io.InputStream getBinaryStream(int columnIndex) throws SQLException {
2431 
2432         // always free an old stream
2433         binaryStream = null;
2434 
2435         // sanity check.
2436         checkIndex(columnIndex);
2437         // make sure the cursor is on a valid row
2438         checkCursor();
2439 
2440         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
2441             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2442         }
2443 
2444         Object value = getCurrentRow().getColumnObject(columnIndex);
2445         if (value == null) {
2446             lastValueNull = true;
2447             return null;
2448         }
2449 
2450         binaryStream = new ByteArrayInputStream((byte[])value);
2451 
2452         return binaryStream;
2453 
2454     }
2455 
2456 
2457     // Methods for accessing results by column name
2458 
2459     /**
2460      * Retrieves the value stored in the designated column
2461      * of the current row as a <code>String</code> object.
2462      *
2463      * @param columnName a <code>String</code> object giving the SQL name of
2464      *        a column in this <code>CachedRowSetImpl</code> object
2465      * @return the column value; if the value is SQL <code>NULL</code>,
2466      *         the result is <code>null</code>
2467      * @throws SQLException if (1) the given column name is not the name of
2468      * a column in this rowset, (2) the cursor is not on one of
2469      * this rowset's rows or its insert row, or (3) the designated
2470      * column does not store an SQL {@code TINYINT, SMALLINT, INTEGER
2471      * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, }
2472      * <b>{@code CHAR, VARCHAR}</b> or
2473      * <b>{@code LONGVARCHAR}</b> value.
2474      * The bold SQL type designates the recommended return type.
2475      */
2476     public String getString(String columnName) throws SQLException {
2477         return getString(getColIdxByName(columnName));
2478     }
2479 
2480     /**
2481      * Retrieves the value stored in the designated column
2482      * of the current row as a <code>boolean</code> value.
2483      *
2484      * @param columnName a <code>String</code> object giving the SQL name of
2485      *        a column in this <code>CachedRowSetImpl</code> object
2486      * @return the column value as a <code>boolean</code> in the Java programming
2487      *        language; if the value is SQL <code>NULL</code>,
2488      *        the result is <code>false</code>
2489      * @throws SQLException if (1) the given column name is not the name of
2490      *            a column in this rowset, (2) the cursor is not on one of
2491      *            this rowset's rows or its insert row, or (3) the designated
2492      *            column does not store an SQL <code>BOOLEAN</code> value
2493      * @see #getBoolean(int)
2494      */
2495     public boolean getBoolean(String columnName) throws SQLException {
2496         return getBoolean(getColIdxByName(columnName));
2497     }
2498 
2499     /**
2500      * Retrieves the value stored in the designated column
2501      * of the current row as a <code>byte</code> value.
2502      *
2503      * @param columnName a <code>String</code> object giving the SQL name of
2504      *        a column in this <code>CachedRowSetImpl</code> object
2505      * @return the column value as a <code>byte</code> in the Java programming
2506      * language; if the value is SQL <code>NULL</code>, the result is <code>0</code>
2507      * @throws SQLException if (1) the given column name is not the name of
2508      * a column in this rowset, (2) the cursor is not on one of
2509      * this rowset's rows or its insert row, or (3) the designated
2510      * column does not store an SQL <code><B>TINYINT</B>, SMALLINT, INTEGER,
2511      * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2512      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The
2513      * bold type designates the recommended return type
2514      */
2515     public byte getByte(String columnName) throws SQLException {
2516         return getByte(getColIdxByName(columnName));
2517     }
2518 
2519     /**
2520      * Retrieves the value stored in the designated column
2521      * of the current row as a <code>short</code> value.
2522      *
2523      * @param columnName a <code>String</code> object giving the SQL name of
2524      *        a column in this <code>CachedRowSetImpl</code> object
2525      * @return the column value; if the value is SQL <code>NULL</code>,
2526      *         the result is <code>0</code>
2527      * @throws SQLException if (1) the given column name is not the name of
2528      * a column in this rowset, (2) the cursor is not on one of
2529      * this rowset's rows or its insert row, or (3) the designated
2530      * column does not store an SQL <code>TINYINT, <b>SMALLINT</b>, INTEGER
2531      * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2532      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2533      * designates the recommended return type.
2534      * @see #getShort(int)
2535      */
2536     public short getShort(String columnName) throws SQLException {
2537         return getShort(getColIdxByName(columnName));
2538     }
2539 
2540     /**
2541      * Retrieves the value stored in the designated column
2542      * of the current row as an <code>int</code> value.
2543      *
2544      * @param columnName a <code>String</code> object giving the SQL name of
2545      *        a column in this <code>CachedRowSetImpl</code> object
2546      * @return the column value; if the value is SQL <code>NULL</code>,
2547      *         the result is <code>0</code>
2548      * @throws SQLException if (1) the given column name is not the name
2549      * of a column in this rowset,
2550      * (2) the cursor is not on one of this rowset's rows or its
2551      * insert row, or (3) the designated column does not store an
2552      * SQL <code>TINYINT, SMALLINT, <b>INTEGER</b>, BIGINT, REAL
2553      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
2554      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
2555      * recommended return type.
2556      */
2557     public int getInt(String columnName) throws SQLException {
2558         return getInt(getColIdxByName(columnName));
2559     }
2560 
2561     /**
2562      * Retrieves the value stored in the designated column
2563      * of the current row as a <code>long</code> value.
2564      *
2565      * @param columnName a <code>String</code> object giving the SQL name of
2566      *        a column in this <code>CachedRowSetImpl</code> object
2567      * @return the column value; if the value is SQL <code>NULL</code>,
2568      *         the result is <code>0</code>
2569      * @throws SQLException if (1) the given column name is not the name of
2570      * a column in this rowset, (2) the cursor is not on one of
2571      * this rowset's rows or its insert row, or (3) the designated
2572      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2573      * <b>BIGINT</b>, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2574      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2575      * designates the recommended return type.
2576      * @see #getLong(int)
2577      */
2578     public long getLong(String columnName) throws SQLException {
2579         return getLong(getColIdxByName(columnName));
2580     }
2581 
2582     /**
2583      * Retrieves the value stored in the designated column
2584      * of the current row as a <code>float</code> value.
2585      *
2586      * @param columnName a <code>String</code> object giving the SQL name of
2587      *        a column in this <code>CachedRowSetImpl</code> object
2588      * @return the column value; if the value is SQL <code>NULL</code>,
2589      *         the result is <code>0</code>
2590      * @throws SQLException if (1) the given column name is not the name of
2591      * a column in this rowset, (2) the cursor is not on one of
2592      * this rowset's rows or its insert row, or (3) the designated
2593      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2594      * BIGINT, <b>REAL</b>, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2595      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2596      * designates the recommended return type.
2597      * @see #getFloat(String)
2598      */
2599     public float getFloat(String columnName) throws SQLException {
2600         return getFloat(getColIdxByName(columnName));
2601     }
2602 
2603     /**
2604      * Retrieves the value stored in the designated column
2605      * of the current row of this <code>CachedRowSetImpl</code> object
2606      * as a <code>double</code> value.
2607      *
2608      * @param columnName a <code>String</code> object giving the SQL name of
2609      *        a column in this <code>CachedRowSetImpl</code> object
2610      * @return the column value; if the value is SQL <code>NULL</code>,
2611      *         the result is <code>0</code>
2612      * @throws SQLException if (1) the given column name is not the name of
2613      * a column in this rowset, (2) the cursor is not on one of
2614      * this rowset's rows or its insert row, or (3) the designated
2615      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2616      * BIGINT, REAL, <b>FLOAT</b>, <b>DOUBLE</b>, DECIMAL, NUMERIC, BIT, CHAR,
2617      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2618      * designates the recommended return types.
2619      * @see #getDouble(int)
2620      */
2621     public double getDouble(String columnName) throws SQLException {
2622         return getDouble(getColIdxByName(columnName));
2623     }
2624 
2625     /**
2626      * Retrieves the value stored in the designated column
2627      * of the current row as a <code>java.math.BigDecimal</code> object.
2628      *
2629      * @param columnName a <code>String</code> object giving the SQL name of
2630      *        a column in this <code>CachedRowSetImpl</code> object
2631      * @param scale the number of digits to the right of the decimal point
2632      * @return a java.math.BugDecimal object with <code><i>scale</i></code>
2633      * number of digits to the right of the decimal point.
2634      * @throws SQLException if (1) the given column name is not the name of
2635      * a column in this rowset, (2) the cursor is not on one of
2636      * this rowset's rows or its insert row, or (3) the designated
2637      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2638      * BIGINT, REAL, FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT CHAR,
2639      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2640      * designates the recommended return type that this method is used to
2641      * retrieve.
2642      * @deprecated Use the <code>getBigDecimal(String columnName)</code>
2643      *             method instead
2644      */
2645     @Deprecated
2646     public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {
2647         return getBigDecimal(getColIdxByName(columnName), scale);
2648     }
2649 
2650     /**
2651      * Retrieves the value stored in the designated column
2652      * of the current row as a <code>byte</code> array.
2653      * The bytes represent the raw values returned by the driver.
2654      *
2655      * @param columnName a <code>String</code> object giving the SQL name of
2656      *        a column in this <code>CachedRowSetImpl</code> object
2657      * @return the column value as a <code>byte</code> array in the Java programming
2658      * language; if the value is SQL <code>NULL</code>, the result is <code>null</code>
2659      * @throws SQLException if (1) the given column name is not the name of
2660      * a column in this rowset, (2) the cursor is not on one of
2661      * this rowset's rows or its insert row, or (3) the designated
2662      * column does not store an SQL <code><b>BINARY</b>, <b>VARBINARY</b>
2663      * </code> or <code>LONGVARBINARY</code> values
2664      * The bold SQL type designates the recommended return type.
2665      * @see #getBytes(int)
2666      */
2667     public byte[] getBytes(String columnName) throws SQLException {
2668         return getBytes(getColIdxByName(columnName));
2669     }
2670 
2671     /**
2672      * Retrieves the value stored in the designated column
2673      * of the current row as a <code>java.sql.Date</code> object.
2674      *
2675      * @param columnName a <code>String</code> object giving the SQL name of
2676      *        a column in this <code>CachedRowSetImpl</code> object
2677      * @return the column value; if the value is SQL <code>NULL</code>,
2678      *         the result is <code>null</code>
2679      * @throws SQLException if (1) the given column name is not the name of
2680      *            a column in this rowset, (2) the cursor is not on one of
2681      *            this rowset's rows or its insert row, or (3) the designated
2682      *            column does not store an SQL <code>DATE</code> or
2683      *            <code>TIMESTAMP</code> value
2684      */
2685     public java.sql.Date getDate(String columnName) throws SQLException {
2686         return getDate(getColIdxByName(columnName));
2687     }
2688 
2689     /**
2690      * Retrieves the value stored in the designated column
2691      * of the current row as a <code>java.sql.Time</code> object.
2692      *
2693      * @param columnName a <code>String</code> object giving the SQL name of
2694      *        a column in this <code>CachedRowSetImpl</code> object
2695      * @return the column value; if the value is SQL <code>NULL</code>,
2696      *         the result is <code>null</code>
2697      * @throws SQLException if the given column name does not match one of
2698      *            this rowset's column names or the cursor is not on one of
2699      *            this rowset's rows or its insert row
2700      */
2701     public java.sql.Time getTime(String columnName) throws SQLException {
2702         return getTime(getColIdxByName(columnName));
2703     }
2704 
2705     /**
2706      * Retrieves the value stored in the designated column
2707      * of the current row as a <code>java.sql.Timestamp</code> object.
2708      *
2709      * @param columnName a <code>String</code> object giving the SQL name of
2710      *        a column in this <code>CachedRowSetImpl</code> object
2711      * @return the column value; if the value is SQL <code>NULL</code>,
2712      *         the result is <code>null</code>
2713      * @throws SQLException if the given column name does not match one of
2714      *            this rowset's column names or the cursor is not on one of
2715      *            this rowset's rows or its insert row
2716      */
2717     public java.sql.Timestamp getTimestamp(String columnName) throws SQLException {
2718         return getTimestamp(getColIdxByName(columnName));
2719     }
2720 
2721     /**
2722      * Retrieves the value of the designated column in the current row of this
2723      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2724      * object.
2725      *
2726      * A column value can be retrieved as a stream of ASCII characters
2727      * and then read in chunks from the stream. This method is particularly
2728      * suitable for retrieving large <code>LONGVARCHAR</code> values. The
2729      * <code>SyncProvider</code> will rely on the JDBC driver to do any necessary
2730      * conversion from the database format into ASCII format.
2731      *
2732      * <P><B>Note:</B> All the data in the returned stream must
2733      * be read prior to getting the value of any other column. The
2734      * next call to a <code>getXXX</code> method implicitly closes the stream.
2735      *
2736      * @param columnName a <code>String</code> object giving the SQL name of
2737      *        a column in this <code>CachedRowSetImpl</code> object
2738      * @return a Java input stream that delivers the database column value
2739      *         as a stream of one-byte ASCII characters.  If the value is SQL
2740      *         <code>NULL</code>, the result is <code>null</code>.
2741      * @throws SQLException if (1) the given column name is not the name of
2742      * a column in this rowset
2743      * (2) the cursor is not on one of this rowset's rows or its
2744      * insert row, or (3) the designated column does not store an
2745      * SQL <code>CHAR, VARCHAR</code>, <code><b>LONGVARCHAR</b></code>
2746      * <code>BINARY, VARBINARY</code> or <code>LONGVARBINARY</code> value. The
2747      * bold SQL type designates the recommended return types that this method is
2748      * used to retrieve.
2749      * @see #getAsciiStream(int)
2750      */
2751     public java.io.InputStream getAsciiStream(String columnName) throws SQLException {
2752         return getAsciiStream(getColIdxByName(columnName));
2753 
2754     }
2755 
2756     /**
2757      * A column value can be retrieved as a stream of Unicode characters
2758      * and then read in chunks from the stream.  This method is particularly
2759      * suitable for retrieving large <code>LONGVARCHAR</code> values.
2760      * The JDBC driver will do any necessary conversion from the database
2761      * format into Unicode.
2762      *
2763      * <P><B>Note:</B> All the data in the returned stream must
2764      * be read prior to getting the value of any other column. The
2765      * next call to a <code>getXXX</code> method implicitly closes the stream.
2766      *
2767      * @param columnName a <code>String</code> object giving the SQL name of
2768      *        a column in this <code>CachedRowSetImpl</code> object
2769      * @return a Java input stream that delivers the database column value
2770      *         as a stream of two-byte Unicode characters.  If the value is
2771      *         SQL <code>NULL</code>, the result is <code>null</code>.
2772      * @throws SQLException if the given column name does not match one of
2773      *            this rowset's column names or the cursor is not on one of
2774      *            this rowset's rows or its insert row
2775      * @deprecated use the method <code>getCharacterStream</code> instead
2776      */
2777     @Deprecated
2778     public java.io.InputStream getUnicodeStream(String columnName) throws SQLException {
2779         return getUnicodeStream(getColIdxByName(columnName));
2780     }
2781 
2782     /**
2783      * Retrieves the value of the designated column in the current row of this
2784      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2785      * object.
2786      * <P>
2787      * A column value can be retrieved as a stream of uninterpreted bytes
2788      * and then read in chunks from the stream.  This method is particularly
2789      * suitable for retrieving large <code>LONGVARBINARY</code> values.
2790      *
2791      * <P><B>Note:</B> All the data in the returned stream must be
2792      * read prior to getting the value of any other column. The next
2793      * call to a get method implicitly closes the stream. Also, a
2794      * stream may return <code>0</code> for <code>CachedRowSetImpl.available()</code>
2795      * whether there is data available or not.
2796      *
2797      * @param columnName a <code>String</code> object giving the SQL name of
2798      *        a column in this <code>CachedRowSetImpl</code> object
2799      * @return a Java input stream that delivers the database column value
2800      *         as a stream of uninterpreted bytes.  If the value is SQL
2801      *         <code>NULL</code>, the result is <code>null</code>.
2802      * @throws SQLException if (1) the given column name is unknown,
2803      * (2) the cursor is not on one of this rowset's rows or its
2804      * insert row, or (3) the designated column does not store an
2805      * SQL <code>BINARY, VARBINARY</code> or <code><b>LONGVARBINARY</b></code>
2806      * The bold type indicates the SQL type that this method is recommened
2807      * to retrieve.
2808      * @see #getBinaryStream(int)
2809      *
2810      */
2811     public java.io.InputStream getBinaryStream(String columnName) throws SQLException {
2812         return getBinaryStream(getColIdxByName(columnName));
2813     }
2814 
2815 
2816     // Advanced features:
2817 
2818     /**
2819      * The first warning reported by calls on this <code>CachedRowSetImpl</code>
2820      * object is returned. Subsequent <code>CachedRowSetImpl</code> warnings will
2821      * be chained to this <code>SQLWarning</code>.
2822      *
2823      * <P>The warning chain is automatically cleared each time a new
2824      * row is read.
2825      *
2826      * <P><B>Note:</B> This warning chain only covers warnings caused
2827      * by <code>ResultSet</code> methods.  Any warning caused by statement
2828      * methods (such as reading OUT parameters) will be chained on the
2829      * <code>Statement</code> object.
2830      *
2831      * @return the first SQLWarning or null
2832      */
2833     public SQLWarning getWarnings() {
2834         return sqlwarn;
2835     }
2836 
2837     /**
2838      * Clears all the warnings reporeted for the <code>CachedRowSetImpl</code>
2839      * object. After a call to this method, the <code>getWarnings</code> method
2840      * returns <code>null</code> until a new warning is reported for this
2841      * <code>CachedRowSetImpl</code> object.
2842      */
2843     public void clearWarnings() {
2844         sqlwarn = null;
2845     }
2846 
2847     /**
2848      * Retrieves the name of the SQL cursor used by this
2849      * <code>CachedRowSetImpl</code> object.
2850      *
2851      * <P>In SQL, a result table is retrieved through a cursor that is
2852      * named. The current row of a <code>ResultSet</code> can be updated or deleted
2853      * using a positioned update/delete statement that references the
2854      * cursor name. To ensure that the cursor has the proper isolation
2855      * level to support an update operation, the cursor's <code>SELECT</code>
2856      * statement should be of the form <code>select for update</code>.
2857      * If the <code>for update</code> clause
2858      * is omitted, positioned updates may fail.
2859      *
2860      * <P>JDBC supports this SQL feature by providing the name of the
2861      * SQL cursor used by a <code>ResultSet</code> object. The current row
2862      * of a result set is also the current row of this SQL cursor.
2863      *
2864      * <P><B>Note:</B> If positioned updates are not supported, an
2865      * <code>SQLException</code> is thrown.
2866      *
2867      * @return the SQL cursor name for this <code>CachedRowSetImpl</code> object's
2868      *         cursor
2869      * @throws SQLException if an error occurs
2870      */
2871     public String getCursorName() throws SQLException {
2872         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.posupdate").toString());
2873     }
2874 
2875     /**
2876      * Retrieves a <code>ResultSetMetaData</code> object instance that
2877      * contains information about the <code>CachedRowSet</code> object.
2878      * However, applications should cast the returned object to a
2879      * <code>RowSetMetaData</code> interface implementation. In the
2880      * reference implementation, this cast can be done on the
2881      * <code>RowSetMetaDataImpl</code> class.
2882      * <P>
2883      * For example:
2884      * <pre>
2885      * CachedRowSet crs = new CachedRowSetImpl();
2886      * RowSetMetaDataImpl metaData =
2887      *     (RowSetMetaDataImpl)crs.getMetaData();
2888      * // Set the number of columns in the RowSet object for
2889      * // which this RowSetMetaDataImpl object was created to the
2890      * // given number.
2891      * metaData.setColumnCount(3);
2892      * crs.setMetaData(metaData);
2893      * </pre>
2894      *
2895      * @return the <code>ResultSetMetaData</code> object that describes this
2896      *         <code>CachedRowSetImpl</code> object's columns
2897      * @throws SQLException if an error occurs in generating the RowSet
2898      * meta data; or if the <code>CachedRowSetImpl</code> is empty.
2899      * @see javax.sql.RowSetMetaData
2900      */
2901     public ResultSetMetaData getMetaData() throws SQLException {
2902         return (ResultSetMetaData)RowSetMD;
2903     }
2904 
2905 
2906     /**
2907      * Retrieves the value of the designated column in the current row
2908      * of this <code>CachedRowSetImpl</code> object as an
2909      * <code>Object</code> value.
2910      * <P>
2911      * The type of the <code>Object</code> will be the default
2912      * Java object type corresponding to the column's SQL type,
2913      * following the mapping for built-in types specified in the JDBC 3.0
2914      * specification.
2915      * <P>
2916      * This method may also be used to read datatabase-specific
2917      * abstract data types.
2918      * <P>
2919      * This implementation of the method <code>getObject</code> extends its
2920      * behavior so that it gets the attributes of an SQL structured type
2921      * as an array of <code>Object</code> values.  This method also custom
2922      * maps SQL user-defined types to classes in the Java programming language.
2923      * When the specified column contains
2924      * a structured or distinct value, the behavior of this method is as
2925      * if it were a call to the method <code>getObject(columnIndex,
2926      * this.getStatement().getConnection().getTypeMap())</code>.
2927      *
2928      * @param columnIndex the first column is <code>1</code>, the second
2929      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2930      *        and equal to or less than the number of columns in the rowset
2931      * @return a <code>java.lang.Object</code> holding the column value;
2932      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
2933      * @throws SQLException if the given column index is out of bounds,
2934      *            the cursor is not on a valid row, or there is a problem getting
2935      *            the <code>Class</code> object for a custom mapping
2936      * @see #getObject(String)
2937      */
2938     public Object getObject(int columnIndex) throws SQLException {
2939         Object value;
2940         Map<String, Class<?>> map;
2941 
2942         // sanity check.
2943         checkIndex(columnIndex);
2944         // make sure the cursor is on a valid row
2945         checkCursor();
2946 
2947         setLastValueNull(false);
2948         value = getCurrentRow().getColumnObject(columnIndex);
2949 
2950         // check for SQL NULL
2951         if (value == null) {
2952             setLastValueNull(true);
2953             return null;
2954         }
2955         if (value instanceof Struct) {
2956             Struct s = (Struct)value;
2957             map = getTypeMap();
2958             // look up the class in the map
2959             Class<?> c = map.get(s.getSQLTypeName());
2960             if (c != null) {
2961                 // create new instance of the class
2962                 SQLData obj = null;
2963                 try {
2964                     ReflectUtil.checkPackageAccess(c);
2965                     @SuppressWarnings("deprecation")
2966                     Object tmp = c.newInstance();
2967                     obj = (SQLData) tmp;
2968                 } catch(Exception ex) {
2969                     throw new SQLException("Unable to Instantiate: ", ex);
2970                 }
2971                 // get the attributes from the struct
2972                 Object attribs[] = s.getAttributes(map);
2973                 // create the SQLInput "stream"
2974                 SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
2975                 // read the values...
2976                 obj.readSQL(sqlInput, s.getSQLTypeName());
2977                 return (Object)obj;
2978             }
2979         }
2980         return value;
2981     }
2982 
2983     /**
2984      * Retrieves the value of the designated column in the current row
2985      * of this <code>CachedRowSetImpl</code> object as an
2986      * <code>Object</code> value.
2987      * <P>
2988      * The type of the <code>Object</code> will be the default
2989      * Java object type corresponding to the column's SQL type,
2990      * following the mapping for built-in types specified in the JDBC 3.0
2991      * specification.
2992      * <P>
2993      * This method may also be used to read datatabase-specific
2994      * abstract data types.
2995      * <P>
2996      * This implementation of the method <code>getObject</code> extends its
2997      * behavior so that it gets the attributes of an SQL structured type
2998      * as an array of <code>Object</code> values.  This method also custom
2999      * maps SQL user-defined types to classes
3000      * in the Java programming language. When the specified column contains
3001      * a structured or distinct value, the behavior of this method is as
3002      * if it were a call to the method <code>getObject(columnIndex,
3003      * this.getStatement().getConnection().getTypeMap())</code>.
3004      *
3005      * @param columnName a <code>String</code> object that must match the
3006      *        SQL name of a column in this rowset, ignoring case
3007      * @return a <code>java.lang.Object</code> holding the column value;
3008      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3009      * @throws SQLException if (1) the given column name does not match one of
3010      *            this rowset's column names, (2) the cursor is not
3011      *            on a valid row, or (3) there is a problem getting
3012      *            the <code>Class</code> object for a custom mapping
3013      * @see #getObject(int)
3014      */
3015     public Object getObject(String columnName) throws SQLException {
3016         return getObject(getColIdxByName(columnName));
3017     }
3018 
3019     //----------------------------------------------------------------
3020 
3021     /**
3022      * Maps the given column name for one of this <code>CachedRowSetImpl</code>
3023      * object's columns to its column number.
3024      *
3025      * @param columnName a <code>String</code> object that must match the
3026      *        SQL name of a column in this rowset, ignoring case
3027      * @return the column index of the given column name
3028      * @throws SQLException if the given column name does not match one
3029      *            of this rowset's column names
3030      */
3031     public int findColumn(String columnName) throws SQLException {
3032         return getColIdxByName(columnName);
3033     }
3034 
3035 
3036     //--------------------------JDBC 2.0-----------------------------------
3037 
3038     //---------------------------------------------------------------------
3039     // Getter's and Setter's
3040     //---------------------------------------------------------------------
3041 
3042     /**
3043      * Retrieves the value stored in the designated column
3044      * of the current row as a <code>java.io.Reader</code> object.
3045      *
3046      * <P><B>Note:</B> All the data in the returned stream must
3047      * be read prior to getting the value of any other column. The
3048      * next call to a <code>getXXX</code> method implicitly closes the stream.
3049      *
3050      * @param columnIndex the first column is <code>1</code>, the second
3051      *        is <code>2</code>, and so on; must be <code>1</code> or larger
3052      *        and equal to or less than the number of columns in the rowset
3053      * @return a Java character stream that delivers the database column value
3054      * as a stream of two-byte unicode characters in a
3055      * <code>java.io.Reader</code> object.  If the value is
3056      * SQL <code>NULL</code>, the result is <code>null</code>.
3057      * @throws SQLException if (1) the given column index is out of bounds,
3058      * (2) the cursor is not on one of this rowset's rows or its
3059      * insert row, or (3) the designated column does not store an
3060      * SQL <code>CHAR, VARCHAR, <b>LONGVARCHAR</b>, BINARY, VARBINARY</code> or
3061      * <code>LONGVARBINARY</code> value.
3062      * The bold SQL type designates the recommended return type.
3063      * @see #getCharacterStream(String)
3064      */
3065     public java.io.Reader getCharacterStream(int columnIndex) throws SQLException{
3066 
3067         // sanity check.
3068         checkIndex(columnIndex);
3069         // make sure the cursor is on a valid row
3070         checkCursor();
3071 
3072         if (isBinary(RowSetMD.getColumnType(columnIndex))) {
3073             Object value = getCurrentRow().getColumnObject(columnIndex);
3074             if (value == null) {
3075                 lastValueNull = true;
3076                 return null;
3077             }
3078             charStream = new InputStreamReader
3079             (new ByteArrayInputStream((byte[])value));
3080         } else if (isString(RowSetMD.getColumnType(columnIndex))) {
3081             Object value = getCurrentRow().getColumnObject(columnIndex);
3082             if (value == null) {
3083                 lastValueNull = true;
3084                 return null;
3085             }
3086             charStream = new StringReader(value.toString());
3087         } else {
3088             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
3089         }
3090 
3091         return charStream;
3092     }
3093 
3094     /**
3095      * Retrieves the value stored in the designated column
3096      * of the current row as a <code>java.io.Reader</code> object.
3097      *
3098      * <P><B>Note:</B> All the data in the returned stream must
3099      * be read prior to getting the value of any other column. The
3100      * next call to a <code>getXXX</code> method implicitly closes the stream.
3101      *
3102      * @param columnName a <code>String</code> object giving the SQL name of
3103      *        a column in this <code>CachedRowSetImpl</code> object
3104      * @return a Java input stream that delivers the database column value
3105      *         as a stream of two-byte Unicode characters.  If the value is
3106      *         SQL <code>NULL</code>, the result is <code>null</code>.
3107      * @throws SQLException if (1) the given column name is not the name of
3108      * a column in this rowset, (2) the cursor is not on one of
3109      * this rowset's rows or its insert row, or (3) the designated
3110      * column does not store an SQL <code>CHAR, VARCHAR, <b>LONGVARCHAR</b>,
3111      * BINARY, VARYBINARY</code> or <code>LONGVARBINARY</code> value.
3112      * The bold SQL type designates the recommended return type.
3113      */
3114     public java.io.Reader getCharacterStream(String columnName) throws SQLException {
3115         return getCharacterStream(getColIdxByName(columnName));
3116     }
3117 
3118     /**
3119      * Retrieves the value of the designated column in the current row
3120      * of this <code>CachedRowSetImpl</code> object as a
3121      * <code>java.math.BigDecimal</code> object.
3122      *
3123      * @param columnIndex the first column is <code>1</code>, the second
3124      *        is <code>2</code>, and so on; must be <code>1</code> or larger
3125      *        and equal to or less than the number of columns in the rowset
3126      * @return a <code>java.math.BigDecimal</code> value with full precision;
3127      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3128      * @throws SQLException if (1) the given column index is out of bounds,
3129      * (2) the cursor is not on one of this rowset's rows or its
3130      * insert row, or (3) the designated column does not store an
3131      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
3132      * FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT, CHAR, VARCHAR</code>
3133      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
3134      * recommended return types that this method is used to retrieve.
3135      * @see #getBigDecimal(String)
3136      */
3137     public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
3138         Object value;
3139 
3140         // sanity check.
3141         checkIndex(columnIndex);
3142         // make sure the cursor is on a valid row
3143         checkCursor();
3144 
3145         setLastValueNull(false);
3146         value = getCurrentRow().getColumnObject(columnIndex);
3147 
3148         // check for SQL NULL
3149         if (value == null) {
3150             setLastValueNull(true);
3151             return null;
3152         }
3153         try {
3154             return (new BigDecimal(value.toString().trim()));
3155         } catch (NumberFormatException ex) {
3156             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.doublefail").toString(),
3157                 new Object[] {value.toString().trim(), columnIndex}));
3158         }
3159     }
3160 
3161     /**
3162      * Retrieves the value of the designated column in the current row
3163      * of this <code>CachedRowSetImpl</code> object as a
3164      * <code>java.math.BigDecimal</code> object.
3165      *
3166      * @param columnName a <code>String</code> object that must match the
3167      *        SQL name of a column in this rowset, ignoring case
3168      * @return a <code>java.math.BigDecimal</code> value with full precision;
3169      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3170      * @throws SQLException if (1) the given column name is not the name of
3171      * a column in this rowset, (2) the cursor is not on one of
3172      * this rowset's rows or its insert row, or (3) the designated
3173      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
3174      * BIGINT, REAL, FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT CHAR,
3175      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
3176      * designates the recommended return type that this method is used to
3177      * retrieve
3178      * @see #getBigDecimal(int)
3179      */
3180     public BigDecimal getBigDecimal(String columnName) throws SQLException {
3181         return getBigDecimal(getColIdxByName(columnName));
3182     }
3183 
3184     //---------------------------------------------------------------------
3185     // Traversal/Positioning
3186     //---------------------------------------------------------------------
3187 
3188     /**
3189      * Returns the number of rows in this <code>CachedRowSetImpl</code> object.
3190      *
3191      * @return number of rows in the rowset
3192      */
3193     public int size() {
3194         return numRows;
3195     }
3196 
3197     /**
3198      * Indicates whether the cursor is before the first row in this
3199      * <code>CachedRowSetImpl</code> object.
3200      *
3201      * @return <code>true</code> if the cursor is before the first row;
3202      *         <code>false</code> otherwise or if the rowset contains no rows
3203      * @throws SQLException if an error occurs
3204      */
3205     public boolean isBeforeFirst() throws SQLException {
3206         if (cursorPos == 0 && numRows > 0) {
3207             return true;
3208         } else {
3209             return false;
3210         }
3211     }
3212 
3213     /**
3214      * Indicates whether the cursor is after the last row in this
3215      * <code>CachedRowSetImpl</code> object.
3216      *
3217      * @return <code>true</code> if the cursor is after the last row;
3218      *         <code>false</code> otherwise or if the rowset contains no rows
3219      * @throws SQLException if an error occurs
3220      */
3221     public boolean isAfterLast() throws SQLException {
3222         if (cursorPos == numRows+1 && numRows > 0) {
3223             return true;
3224         } else {
3225             return false;
3226         }
3227     }
3228 
3229     /**
3230      * Indicates whether the cursor is on the first row in this
3231      * <code>CachedRowSetImpl</code> object.
3232      *
3233      * @return <code>true</code> if the cursor is on the first row;
3234      *         <code>false</code> otherwise or if the rowset contains no rows
3235      * @throws SQLException if an error occurs
3236      */
3237     public boolean isFirst() throws SQLException {
3238         // this becomes nasty because of deletes.
3239         int saveCursorPos = cursorPos;
3240         int saveAbsoluteCursorPos = absolutePos;
3241         internalFirst();
3242         if (cursorPos == saveCursorPos) {
3243             return true;
3244         } else {
3245             cursorPos = saveCursorPos;
3246             absolutePos = saveAbsoluteCursorPos;
3247             return false;
3248         }
3249     }
3250 
3251     /**
3252      * Indicates whether the cursor is on the last row in this
3253      * <code>CachedRowSetImpl</code> object.
3254      * <P>
3255      * Note: Calling the method <code>isLast</code> may be expensive
3256      * because the JDBC driver might need to fetch ahead one row in order
3257      * to determine whether the current row is the last row in this rowset.
3258      *
3259      * @return <code>true</code> if the cursor is on the last row;
3260      *         <code>false</code> otherwise or if this rowset contains no rows
3261      * @throws SQLException if an error occurs
3262      */
3263     public boolean isLast() throws SQLException {
3264         int saveCursorPos = cursorPos;
3265         int saveAbsoluteCursorPos = absolutePos;
3266         boolean saveShowDeleted = getShowDeleted();
3267         setShowDeleted(true);
3268         internalLast();
3269         if (cursorPos == saveCursorPos) {
3270             setShowDeleted(saveShowDeleted);
3271             return true;
3272         } else {
3273             setShowDeleted(saveShowDeleted);
3274             cursorPos = saveCursorPos;
3275             absolutePos = saveAbsoluteCursorPos;
3276             return false;
3277         }
3278     }
3279 
3280     /**
3281      * Moves this <code>CachedRowSetImpl</code> object's cursor to the front of
3282      * the rowset, just before the first row. This method has no effect if
3283      * this rowset contains no rows.
3284      *
3285      * @throws SQLException if an error occurs or the type of this rowset
3286      *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3287      */
3288     public void beforeFirst() throws SQLException {
3289        if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3290             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.beforefirst").toString());
3291         }
3292         cursorPos = 0;
3293         absolutePos = 0;
3294         notifyCursorMoved();
3295     }
3296 
3297     /**
3298      * Moves this <code>CachedRowSetImpl</code> object's cursor to the end of
3299      * the rowset, just after the last row. This method has no effect if
3300      * this rowset contains no rows.
3301      *
3302      * @throws SQLException if an error occurs
3303      */
3304     public void afterLast() throws SQLException {
3305         if (numRows > 0) {
3306             cursorPos = numRows + 1;
3307             absolutePos = 0;
3308             notifyCursorMoved();
3309         }
3310     }
3311 
3312     /**
3313      * Moves this <code>CachedRowSetImpl</code> object's cursor to the first row
3314      * and returns <code>true</code> if the operation was successful.  This
3315      * method also notifies registered listeners that the cursor has moved.
3316      *
3317      * @return <code>true</code> if the cursor is on a valid row;
3318      *         <code>false</code> otherwise or if there are no rows in this
3319      *         <code>CachedRowSetImpl</code> object
3320      * @throws SQLException if the type of this rowset
3321      *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3322      */
3323     public boolean first() throws SQLException {
3324         if(getType() == ResultSet.TYPE_FORWARD_ONLY) {
3325             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.first").toString());
3326         }
3327 
3328         // move and notify
3329         boolean ret = this.internalFirst();
3330         notifyCursorMoved();
3331 
3332         return ret;
3333     }
3334 
3335     /**
3336      * Moves this <code>CachedRowSetImpl</code> object's cursor to the first
3337      * row and returns <code>true</code> if the operation is successful.
3338      * <P>
3339      * This method is called internally by the methods <code>first</code>,
3340      * <code>isFirst</code>, and <code>absolute</code>.
3341      * It in turn calls the method <code>internalNext</code> in order to
3342      * handle the case where the first row is a deleted row that is not visible.
3343      * <p>
3344      * This is a implementation only method and is not required as a standard
3345      * implementation of the <code>CachedRowSet</code> interface.
3346      *
3347      * @return <code>true</code> if the cursor moved to the first row;
3348      *         <code>false</code> otherwise
3349      * @throws SQLException if an error occurs
3350      */
3351     protected boolean internalFirst() throws SQLException {
3352         boolean ret = false;
3353 
3354         if (numRows > 0) {
3355             cursorPos = 1;
3356             if ((getShowDeleted() == false) && (rowDeleted() == true)) {
3357                 ret = internalNext();
3358             } else {
3359                 ret = true;
3360             }
3361         }
3362 
3363         if (ret == true)
3364             absolutePos = 1;
3365         else
3366             absolutePos = 0;
3367 
3368         return ret;
3369     }
3370 
3371     /**
3372      * Moves this <code>CachedRowSetImpl</code> object's cursor to the last row
3373      * and returns <code>true</code> if the operation was successful.  This
3374      * method also notifies registered listeners that the cursor has moved.
3375      *
3376      * @return <code>true</code> if the cursor is on a valid row;
3377      *         <code>false</code> otherwise or if there are no rows in this
3378      *         <code>CachedRowSetImpl</code> object
3379      * @throws SQLException if the type of this rowset
3380      *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3381      */
3382     public boolean last() throws SQLException {
3383         if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3384             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.last").toString());
3385         }
3386 
3387         // move and notify
3388         boolean ret = this.internalLast();
3389         notifyCursorMoved();
3390 
3391         return ret;
3392     }
3393 
3394     /**
3395      * Moves this <code>CachedRowSetImpl</code> object's cursor to the last
3396      * row and returns <code>true</code> if the operation is successful.
3397      * <P>
3398      * This method is called internally by the method <code>last</code>
3399      * when rows have been deleted and the deletions are not visible.
3400      * The method <code>internalLast</code> handles the case where the
3401      * last row is a deleted row that is not visible by in turn calling
3402      * the method <code>internalPrevious</code>.
3403      * <p>
3404      * This is a implementation only method and is not required as a standard
3405      * implementation of the <code>CachedRowSet</code> interface.
3406      *
3407      * @return <code>true</code> if the cursor moved to the last row;
3408      *         <code>false</code> otherwise
3409      * @throws SQLException if an error occurs
3410      */
3411     protected boolean internalLast() throws SQLException {
3412         boolean ret = false;
3413 
3414         if (numRows > 0) {
3415             cursorPos = numRows;
3416             if ((getShowDeleted() == false) && (rowDeleted() == true)) {
3417                 ret = internalPrevious();
3418             } else {
3419                 ret = true;
3420             }
3421         }
3422         if (ret == true)
3423             absolutePos = numRows - numDeleted;
3424         else
3425             absolutePos = 0;
3426         return ret;
3427     }
3428 
3429     /**
3430      * Returns the number of the current row in this <code>CachedRowSetImpl</code>
3431      * object. The first row is number 1, the second number 2, and so on.
3432      *
3433      * @return the number of the current row;  <code>0</code> if there is no
3434      *         current row
3435      * @throws SQLException if an error occurs; or if the <code>CacheRowSetImpl</code>
3436      *         is empty
3437      */
3438     public int getRow() throws SQLException {
3439         // are we on a valid row? Valid rows are between first and last
3440         if (numRows > 0 &&
3441         cursorPos > 0 &&
3442         cursorPos < (numRows + 1) &&
3443         (getShowDeleted() == false && rowDeleted() == false)) {
3444             return absolutePos;
3445         } else if (getShowDeleted() == true) {
3446             return cursorPos;
3447         } else {
3448             return 0;
3449         }
3450     }
3451 
3452     /**
3453      * Moves this <code>CachedRowSetImpl</code> object's cursor to the row number
3454      * specified.
3455      *
3456      * <p>If the number is positive, the cursor moves to an absolute row with
3457      * respect to the beginning of the rowset.  The first row is row 1, the second
3458      * is row 2, and so on.  For example, the following command, in which
3459      * <code>crs</code> is a <code>CachedRowSetImpl</code> object, moves the cursor
3460      * to the fourth row, starting from the beginning of the rowset.
3461      * <PRE><code>
3462      *
3463      *    crs.absolute(4);
3464      *
3465      * </code> </PRE>
3466      * <P>
3467      * If the number is negative, the cursor moves to an absolute row position
3468      * with respect to the end of the rowset.  For example, calling
3469      * <code>absolute(-1)</code> positions the cursor on the last row,
3470      * <code>absolute(-2)</code> moves it on the next-to-last row, and so on.
3471      * If the <code>CachedRowSetImpl</code> object <code>crs</code> has five rows,
3472      * the following command moves the cursor to the fourth-to-last row, which
3473      * in the case of a  rowset with five rows, is also the second row, counting
3474      * from the beginning.
3475      * <PRE><code>
3476      *
3477      *    crs.absolute(-4);
3478      *
3479      * </code> </PRE>
3480      *
3481      * If the number specified is larger than the number of rows, the cursor
3482      * will move to the position after the last row. If the number specified
3483      * would move the cursor one or more rows before the first row, the cursor
3484      * moves to the position before the first row.
3485      * <P>
3486      * Note: Calling <code>absolute(1)</code> is the same as calling the
3487      * method <code>first()</code>.  Calling <code>absolute(-1)</code> is the
3488      * same as calling <code>last()</code>.
3489      *
3490      * @param row a positive number to indicate the row, starting row numbering from
3491      *        the first row, which is <code>1</code>; a negative number to indicate
3492      *        the row, starting row numbering from the last row, which is
3493      *        <code>-1</code>; it must not be <code>0</code>
3494      * @return <code>true</code> if the cursor is on the rowset; <code>false</code>
3495      *         otherwise
3496      * @throws SQLException if the given cursor position is <code>0</code> or the
3497      *            type of this rowset is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3498      */
3499     public boolean absolute( int row ) throws SQLException {
3500         if (row == 0 || getType() == ResultSet.TYPE_FORWARD_ONLY) {
3501             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.absolute").toString());
3502         }
3503 
3504         if (row > 0) { // we are moving foward
3505             if (row > numRows) {
3506                 // fell off the end
3507                 afterLast();
3508                 return false;
3509             } else {
3510                 if (absolutePos <= 0)
3511                     internalFirst();
3512             }
3513         } else { // we are moving backward
3514             if (cursorPos + row < 0) {
3515                 // fell off the front
3516                 beforeFirst();
3517                 return false;
3518             } else {
3519                 if (absolutePos >= 0)
3520                     internalLast();
3521             }
3522         }
3523 
3524         // Now move towards the absolute row that we're looking for
3525         while (absolutePos != row) {
3526             if (absolutePos < row) {
3527                 if (!internalNext())
3528                     break;
3529             }
3530             else {
3531                 if (!internalPrevious())
3532                     break;
3533             }
3534         }
3535 
3536         notifyCursorMoved();
3537 
3538         if (isAfterLast() || isBeforeFirst()) {
3539             return false;
3540         } else {
3541             return true;
3542         }
3543     }
3544 
3545     /**
3546      * Moves the cursor the specified number of rows from the current
3547      * position, with a positive number moving it forward and a
3548      * negative number moving it backward.
3549      * <P>
3550      * If the number is positive, the cursor moves the specified number of
3551      * rows toward the end of the rowset, starting at the current row.
3552      * For example, the following command, in which
3553      * <code>crs</code> is a <code>CachedRowSetImpl</code> object with 100 rows,
3554      * moves the cursor forward four rows from the current row.  If the
3555      * current row is 50, the cursor would move to row 54.
3556      * <PRE><code>
3557      *
3558      *    crs.relative(4);
3559      *
3560      * </code> </PRE>
3561      * <P>
3562      * If the number is negative, the cursor moves back toward the beginning
3563      * the specified number of rows, starting at the current row.
3564      * For example, calling the method
3565      * <code>absolute(-1)</code> positions the cursor on the last row,
3566      * <code>absolute(-2)</code> moves it on the next-to-last row, and so on.
3567      * If the <code>CachedRowSetImpl</code> object <code>crs</code> has five rows,
3568      * the following command moves the cursor to the fourth-to-last row, which
3569      * in the case of a  rowset with five rows, is also the second row
3570      * from the beginning.
3571      * <PRE><code>
3572      *
3573      *    crs.absolute(-4);
3574      *
3575      * </code> </PRE>
3576      *
3577      * If the number specified is larger than the number of rows, the cursor
3578      * will move to the position after the last row. If the number specified
3579      * would move the cursor one or more rows before the first row, the cursor
3580      * moves to the position before the first row. In both cases, this method
3581      * throws an <code>SQLException</code>.
3582      * <P>
3583      * Note: Calling <code>absolute(1)</code> is the same as calling the
3584      * method <code>first()</code>.  Calling <code>absolute(-1)</code> is the
3585      * same as calling <code>last()</code>.  Calling <code>relative(0)</code>
3586      * is valid, but it does not change the cursor position.
3587      *
3588      * @param rows an <code>int</code> indicating the number of rows to move
3589      *             the cursor, starting at the current row; a positive number
3590      *             moves the cursor forward; a negative number moves the cursor
3591      *             backward; must not move the cursor past the valid
3592      *             rows
3593      * @return <code>true</code> if the cursor is on a row in this
3594      *         <code>CachedRowSetImpl</code> object; <code>false</code>
3595      *         otherwise
3596      * @throws SQLException if there are no rows in this rowset, the cursor is
3597      *         positioned either before the first row or after the last row, or
3598      *         the rowset is type <code>ResultSet.TYPE_FORWARD_ONLY</code>
3599      */
3600     public boolean relative(int rows) throws SQLException {
3601         if (numRows == 0 || isBeforeFirst() ||
3602         isAfterLast() || getType() == ResultSet.TYPE_FORWARD_ONLY) {
3603             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.relative").toString());
3604         }
3605 
3606         if (rows == 0) {
3607             return true;
3608         }
3609 
3610         if (rows > 0) { // we are moving forward
3611             if (cursorPos + rows > numRows) {
3612                 // fell off the end
3613                 afterLast();
3614             } else {
3615                 for (int i=0; i < rows; i++) {
3616                     if (!internalNext())
3617                         break;
3618                 }
3619             }
3620         } else { // we are moving backward
3621             if (cursorPos + rows < 0) {
3622                 // fell off the front
3623                 beforeFirst();
3624             } else {
3625                 for (int i=rows; i < 0; i++) {
3626                     if (!internalPrevious())
3627                         break;
3628                 }
3629             }
3630         }
3631         notifyCursorMoved();
3632 
3633         if (isAfterLast() || isBeforeFirst()) {
3634             return false;
3635         } else {
3636             return true;
3637         }
3638     }
3639 
3640     /**
3641      * Moves this <code>CachedRowSetImpl</code> object's cursor to the
3642      * previous row and returns <code>true</code> if the cursor is on
3643      * a valid row or <code>false</code> if it is not.
3644      * This method also notifies all listeners registered with this
3645      * <code>CachedRowSetImpl</code> object that its cursor has moved.
3646      * <P>
3647      * Note: calling the method <code>previous()</code> is not the same
3648      * as calling the method <code>relative(-1)</code>.  This is true
3649      * because it is possible to call <code>previous()</code> from the insert
3650      * row, from after the last row, or from the current row, whereas
3651      * <code>relative</code> may only be called from the current row.
3652      * <P>
3653      * The method <code>previous</code> may used in a <code>while</code>
3654      * loop to iterate through a rowset starting after the last row
3655      * and moving toward the beginning. The loop ends when <code>previous</code>
3656      * returns <code>false</code>, meaning that there are no more rows.
3657      * For example, the following code fragment retrieves all the data in
3658      * the <code>CachedRowSetImpl</code> object <code>crs</code>, which has
3659      * three columns.  Note that the cursor must initially be positioned
3660      * after the last row so that the first call to the method
3661      * <code>previous</code> places the cursor on the last line.
3662      * <PRE> <code>
3663      *
3664      *     crs.afterLast();
3665      *     while (previous()) {
3666      *         String name = crs.getString(1);
3667      *         int age = crs.getInt(2);
3668      *         short ssn = crs.getShort(3);
3669      *         System.out.println(name + "   " + age + "   " + ssn);
3670      *     }
3671      *
3672      * </code> </PRE>
3673      * This method throws an <code>SQLException</code> if the cursor is not
3674      * on a row in the rowset, before the first row, or after the last row.
3675      *
3676      * @return <code>true</code> if the cursor is on a valid row;
3677      *         <code>false</code> if it is before the first row or after the
3678      *         last row
3679      * @throws SQLException if the cursor is not on a valid position or the
3680      *           type of this rowset is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3681      */
3682     public boolean previous() throws SQLException {
3683         if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3684             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.last").toString());
3685         }
3686         /*
3687          * make sure things look sane. The cursor must be
3688          * positioned in the rowset or before first (0) or
3689          * after last (numRows + 1)
3690          */
3691         if (cursorPos < 0 || cursorPos > numRows + 1) {
3692             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
3693         }
3694         // move and notify
3695         boolean ret = this.internalPrevious();
3696         notifyCursorMoved();
3697 
3698         return ret;
3699     }
3700 
3701     /**
3702      * Moves the cursor to the previous row in this <code>CachedRowSetImpl</code>
3703      * object, skipping past deleted rows that are not visible; returns
3704      * <code>true</code> if the cursor is on a row in this rowset and
3705      * <code>false</code> when the cursor goes before the first row.
3706      * <P>
3707      * This method is called internally by the method <code>previous</code>.
3708      * <P>
3709      * This is a implementation only method and is not required as a standard
3710      * implementation of the <code>CachedRowSet</code> interface.
3711      *
3712      * @return <code>true</code> if the cursor is on a row in this rowset;
3713      *         <code>false</code> when the cursor reaches the position before
3714      *         the first row
3715      * @throws SQLException if an error occurs
3716      */
3717     protected boolean internalPrevious() throws SQLException {
3718         boolean ret = false;
3719 
3720         do {
3721             if (cursorPos > 1) {
3722                 --cursorPos;
3723                 ret = true;
3724             } else if (cursorPos == 1) {
3725                 // decrement to before first
3726                 --cursorPos;
3727                 ret = false;
3728                 break;
3729             }
3730         } while ((getShowDeleted() == false) && (rowDeleted() == true));
3731 
3732         /*
3733          * Each call to internalPrevious may move the cursor
3734          * over multiple rows, the absolute position moves one row
3735          */
3736         if (ret == true)
3737             --absolutePos;
3738         else
3739             absolutePos = 0;
3740 
3741         return ret;
3742     }
3743 
3744 
3745     //---------------------------------------------------------------------
3746     // Updates
3747     //---------------------------------------------------------------------
3748 
3749     /**
3750      * Indicates whether the current row of this <code>CachedRowSetImpl</code>
3751      * object has been updated.  The value returned
3752      * depends on whether this rowset can detect updates: <code>false</code>
3753      * will always be returned if it does not detect updates.
3754      *
3755      * @return <code>true</code> if the row has been visibly updated
3756      *         by the owner or another and updates are detected;
3757      *         <code>false</code> otherwise
3758      * @throws SQLException if the cursor is on the insert row or not
3759      *            not on a valid row
3760      *
3761      * @see DatabaseMetaData#updatesAreDetected
3762      */
3763     public boolean rowUpdated() throws SQLException {
3764         // make sure the cursor is on a valid row
3765         checkCursor();
3766         if (onInsertRow == true) {
3767             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3768         }
3769         return(((Row)getCurrentRow()).getUpdated());
3770     }
3771 
3772     /**
3773      * Indicates whether the designated column of the current row of
3774      * this <code>CachedRowSetImpl</code> object has been updated. The
3775      * value returned depends on whether this rowset can detcted updates:
3776      * <code>false</code> will always be returned if it does not detect updates.
3777      *
3778      * @param idx the index identifier of the column that may be have been updated.
3779      * @return <code>true</code> is the designated column has been updated
3780      * and the rowset detects updates; <code>false</code> if the rowset has not
3781      * been updated or the rowset does not detect updates
3782      * @throws SQLException if the cursor is on the insert row or not
3783      *          on a valid row
3784      * @see DatabaseMetaData#updatesAreDetected
3785      */
3786     public boolean columnUpdated(int idx) throws SQLException {
3787         // make sure the cursor is on a valid row
3788         checkCursor();
3789         if (onInsertRow == true) {
3790             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3791         }
3792         return (((Row)getCurrentRow()).getColUpdated(idx - 1));
3793     }
3794 
3795     /**
3796      * Indicates whether the designated column of the current row of
3797      * this <code>CachedRowSetImpl</code> object has been updated. The
3798      * value returned depends on whether this rowset can detcted updates:
3799      * <code>false</code> will always be returned if it does not detect updates.
3800      *
3801      * @param columnName the <code>String</code> column name column that may be have
3802      * been updated.
3803      * @return <code>true</code> is the designated column has been updated
3804      * and the rowset detects updates; <code>false</code> if the rowset has not
3805      * been updated or the rowset does not detect updates
3806      * @throws SQLException if the cursor is on the insert row or not
3807      *          on a valid row
3808      * @see DatabaseMetaData#updatesAreDetected
3809      */
3810     public boolean columnUpdated(String columnName) throws SQLException {
3811         return columnUpdated(getColIdxByName(columnName));
3812     }
3813 
3814     /**
3815      * Indicates whether the current row has been inserted.  The value returned
3816      * depends on whether or not the rowset can detect visible inserts.
3817      *
3818      * @return <code>true</code> if a row has been inserted and inserts are detected;
3819      *         <code>false</code> otherwise
3820      * @throws SQLException if the cursor is on the insert row or not
3821      *            not on a valid row
3822      *
3823      * @see DatabaseMetaData#insertsAreDetected
3824      */
3825     public boolean rowInserted() throws SQLException {
3826         // make sure the cursor is on a valid row
3827         checkCursor();
3828         if (onInsertRow == true) {
3829             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3830         }
3831         return(((Row)getCurrentRow()).getInserted());
3832     }
3833 
3834     /**
3835      * Indicates whether the current row has been deleted.  A deleted row
3836      * may leave a visible "hole" in a rowset.  This method can be used to
3837      * detect such holes if the rowset can detect deletions. This method
3838      * will always return <code>false</code> if this rowset cannot detect
3839      * deletions.
3840      *
3841      * @return <code>true</code> if (1)the current row is blank, indicating that
3842      *         the row has been deleted, and (2)deletions are detected;
3843      *         <code>false</code> otherwise
3844      * @throws SQLException if the cursor is on a valid row in this rowset
3845      * @see DatabaseMetaData#deletesAreDetected
3846      */
3847     public boolean rowDeleted() throws SQLException {
3848         // make sure the cursor is on a valid row
3849 
3850         if (isAfterLast() == true ||
3851         isBeforeFirst() == true ||
3852         onInsertRow == true) {
3853 
3854             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
3855         }
3856         return(((Row)getCurrentRow()).getDeleted());
3857     }
3858 
3859     /**
3860      * Indicates whether the given SQL data type is a numberic type.
3861      *
3862      * @param type one of the constants from <code>java.sql.Types</code>
3863      * @return <code>true</code> if the given type is <code>NUMERIC</code>,'
3864      *         <code>DECIMAL</code>, <code>BIT</code>, <code>TINYINT</code>,
3865      *         <code>SMALLINT</code>, <code>INTEGER</code>, <code>BIGINT</code>,
3866      *         <code>REAL</code>, <code>DOUBLE</code>, or <code>FLOAT</code>;
3867      *         <code>false</code> otherwise
3868      */
3869     private boolean isNumeric(int type) {
3870         switch (type) {
3871             case java.sql.Types.NUMERIC:
3872             case java.sql.Types.DECIMAL:
3873             case java.sql.Types.BIT:
3874             case java.sql.Types.TINYINT:
3875             case java.sql.Types.SMALLINT:
3876             case java.sql.Types.INTEGER:
3877             case java.sql.Types.BIGINT:
3878             case java.sql.Types.REAL:
3879             case java.sql.Types.DOUBLE:
3880             case java.sql.Types.FLOAT:
3881                 return true;
3882             default:
3883                 return false;
3884         }
3885     }
3886 
3887     /**
3888      * Indicates whether the given SQL data type is a string type.
3889      *
3890      * @param type one of the constants from <code>java.sql.Types</code>
3891      * @return <code>true</code> if the given type is <code>CHAR</code>,'
3892      *         <code>VARCHAR</code>, or <code>LONGVARCHAR</code>;
3893      *         <code>false</code> otherwise
3894      */
3895     private boolean isString(int type) {
3896         switch (type) {
3897             case java.sql.Types.CHAR:
3898             case java.sql.Types.VARCHAR:
3899             case java.sql.Types.LONGVARCHAR:
3900                 return true;
3901             default:
3902                 return false;
3903         }
3904     }
3905 
3906     /**
3907      * Indicates whether the given SQL data type is a binary type.
3908      *
3909      * @param type one of the constants from <code>java.sql.Types</code>
3910      * @return <code>true</code> if the given type is <code>BINARY</code>,'
3911      *         <code>VARBINARY</code>, or <code>LONGVARBINARY</code>;
3912      *         <code>false</code> otherwise
3913      */
3914     private boolean isBinary(int type) {
3915         switch (type) {
3916             case java.sql.Types.BINARY:
3917             case java.sql.Types.VARBINARY:
3918             case java.sql.Types.LONGVARBINARY:
3919                 return true;
3920             default:
3921                 return false;
3922         }
3923     }
3924 
3925     /**
3926      * Indicates whether the given SQL data type is a temporal type.
3927      * This method is called internally by the conversion methods
3928      * <code>convertNumeric</code> and <code>convertTemporal</code>.
3929      *
3930      * @param type one of the constants from <code>java.sql.Types</code>
3931      * @return <code>true</code> if the given type is <code>DATE</code>,
3932      *         <code>TIME</code>, or <code>TIMESTAMP</code>;
3933      *         <code>false</code> otherwise
3934      */
3935     private boolean isTemporal(int type) {
3936         switch (type) {
3937             case java.sql.Types.DATE:
3938             case java.sql.Types.TIME:
3939             case java.sql.Types.TIMESTAMP:
3940                 return true;
3941             default:
3942                 return false;
3943         }
3944     }
3945 
3946     /**
3947      * Indicates whether the given SQL data type is a boolean type.
3948      * This method is called internally by the conversion methods
3949      * <code>convertNumeric</code> and <code>convertBoolean</code>.
3950      *
3951      * @param type one of the constants from <code>java.sql.Types</code>
3952      * @return <code>true</code> if the given type is <code>BIT</code>,
3953      *         , or <code>BOOLEAN</code>;
3954      *         <code>false</code> otherwise
3955      */
3956     private boolean isBoolean(int type) {
3957         switch (type) {
3958             case java.sql.Types.BIT:
3959             case java.sql.Types.BOOLEAN:
3960                 return true;
3961             default:
3962                 return false;
3963         }
3964     }
3965 
3966 
3967     /**
3968      * Converts the given <code>Object</code> in the Java programming language
3969      * to the standard mapping for the specified SQL target data type.
3970      * The conversion must be to a string or numeric type, but there are no
3971      * restrictions on the type to be converted.  If the source type and target
3972      * type are the same, the given object is simply returned.
3973      *
3974      * @param srcObj the <code>Object</code> in the Java programming language
3975      *               that is to be converted to the target type
3976      * @param srcType the data type that is the standard mapping in SQL of the
3977      *                object to be converted; must be one of the constants in
3978      *                <code>java.sql.Types</code>
3979      * @param trgType the SQL data type to which to convert the given object;
3980      *                must be one of the following constants in
3981      *                <code>java.sql.Types</code>: <code>NUMERIC</code>,
3982      *         <code>DECIMAL</code>, <code>BIT</code>, <code>TINYINT</code>,
3983      *         <code>SMALLINT</code>, <code>INTEGER</code>, <code>BIGINT</code>,
3984      *         <code>REAL</code>, <code>DOUBLE</code>, <code>FLOAT</code>,
3985      *         <code>VARCHAR</code>, <code>LONGVARCHAR</code>, or <code>CHAR</code>
3986      * @return an <code>Object</code> value.that is
3987      *         the standard object mapping for the target SQL type
3988      * @throws SQLException if the given target type is not one of the string or
3989      *         numeric types in <code>java.sql.Types</code>
3990      */
3991     private Object convertNumeric(Object srcObj, int srcType,
3992     int trgType) throws SQLException {
3993 
3994         if (srcType == trgType) {
3995             return srcObj;
3996         }
3997 
3998         if (isNumeric(trgType) == false && isString(trgType) == false) {
3999             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4000         }
4001 
4002         try {
4003             switch (trgType) {
4004                 case java.sql.Types.BIT:
4005                     Integer i = Integer.valueOf(srcObj.toString().trim());
4006                     return i.equals(0) ?
4007                     Boolean.valueOf(false) :
4008                         Boolean.valueOf(true);
4009                 case java.sql.Types.TINYINT:
4010                     return Byte.valueOf(srcObj.toString().trim());
4011                 case java.sql.Types.SMALLINT:
4012                     return Short.valueOf(srcObj.toString().trim());
4013                 case java.sql.Types.INTEGER:
4014                     return Integer.valueOf(srcObj.toString().trim());
4015                 case java.sql.Types.BIGINT:
4016                     return Long.valueOf(srcObj.toString().trim());
4017                 case java.sql.Types.NUMERIC:
4018                 case java.sql.Types.DECIMAL:
4019                     return new BigDecimal(srcObj.toString().trim());
4020                 case java.sql.Types.REAL:
4021                 case java.sql.Types.FLOAT:
4022                     return Float.valueOf(srcObj.toString().trim());
4023                 case java.sql.Types.DOUBLE:
4024                     return Double.valueOf(srcObj.toString().trim());
4025                 case java.sql.Types.CHAR:
4026                 case java.sql.Types.VARCHAR:
4027                 case java.sql.Types.LONGVARCHAR:
4028                     return srcObj.toString();
4029                 default:
4030                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString()+ trgType);
4031             }
4032         } catch (NumberFormatException ex) {
4033             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4034         }
4035     }
4036 
4037     /**
4038      * Converts the given <code>Object</code> in the Java programming language
4039      * to the standard object mapping for the specified SQL target data type.
4040      * The conversion must be to a string or temporal type, and there are also
4041      * restrictions on the type to be converted.
4042      * <P>
4043      * <TABLE ALIGN="CENTER" BORDER CELLPADDING=10 BORDERCOLOR="#0000FF"
4044      * <CAPTION ALIGN="CENTER"><B>Parameters and Return Values</B></CAPTION>
4045      * <TR>
4046      *   <TD><B>Source SQL Type</B>
4047      *   <TD><B>Target SQL Type</B>
4048      *   <TD><B>Object Returned</B>
4049      * </TR>
4050      * <TR>
4051      *   <TD><code>TIMESTAMP</code>
4052      *   <TD><code>DATE</code>
4053      *   <TD><code>java.sql.Date</code>
4054      * </TR>
4055      * <TR>
4056      *   <TD><code>TIMESTAMP</code>
4057      *   <TD><code>TIME</code>
4058      *   <TD><code>java.sql.Time</code>
4059      * </TR>
4060      * <TR>
4061      *   <TD><code>TIME</code>
4062      *   <TD><code>TIMESTAMP</code>
4063      *   <TD><code>java.sql.Timestamp</code>
4064      * </TR>
4065      * <TR>
4066      *   <TD><code>DATE</code>, <code>TIME</code>, or <code>TIMESTAMP</code>
4067      *   <TD><code>CHAR</code>, <code>VARCHAR</code>, or <code>LONGVARCHAR</code>
4068      *   <TD><code>java.lang.String</code>
4069      * </TR>
4070      * </TABLE>
4071      * <P>
4072      * If the source type and target type are the same,
4073      * the given object is simply returned.
4074      *
4075      * @param srcObj the <code>Object</code> in the Java programming language
4076      *               that is to be converted to the target type
4077      * @param srcType the data type that is the standard mapping in SQL of the
4078      *                object to be converted; must be one of the constants in
4079      *                <code>java.sql.Types</code>
4080      * @param trgType the SQL data type to which to convert the given object;
4081      *                must be one of the following constants in
4082      *                <code>java.sql.Types</code>: <code>DATE</code>,
4083      *         <code>TIME</code>, <code>TIMESTAMP</code>, <code>CHAR</code>,
4084      *         <code>VARCHAR</code>, or <code>LONGVARCHAR</code>
4085      * @return an <code>Object</code> value.that is
4086      *         the standard object mapping for the target SQL type
4087      * @throws SQLException if the given target type is not one of the string or
4088      *         temporal types in <code>java.sql.Types</code>
4089      */
4090     private Object convertTemporal(Object srcObj,
4091     int srcType, int trgType) throws SQLException {
4092 
4093         if (srcType == trgType) {
4094             return srcObj;
4095         }
4096 
4097         if (isNumeric(trgType) == true ||
4098         (isString(trgType) == false && isTemporal(trgType) == false)) {
4099             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4100         }
4101 
4102         try {
4103             switch (trgType) {
4104                 case java.sql.Types.DATE:
4105                     if (srcType == java.sql.Types.TIMESTAMP) {
4106                         return new java.sql.Date(((java.sql.Timestamp)srcObj).getTime());
4107                     } else {
4108                         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4109                     }
4110                 case java.sql.Types.TIMESTAMP:
4111                     if (srcType == java.sql.Types.TIME) {
4112                         return new Timestamp(((java.sql.Time)srcObj).getTime());
4113                     } else {
4114                         return new Timestamp(((java.sql.Date)srcObj).getTime());
4115                     }
4116                 case java.sql.Types.TIME:
4117                     if (srcType == java.sql.Types.TIMESTAMP) {
4118                         return new Time(((java.sql.Timestamp)srcObj).getTime());
4119                     } else {
4120                         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4121                     }
4122                 case java.sql.Types.CHAR:
4123                 case java.sql.Types.VARCHAR:
4124                 case java.sql.Types.LONGVARCHAR:
4125                     return srcObj.toString();
4126                 default:
4127                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4128             }
4129         } catch (NumberFormatException ex) {
4130             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4131         }
4132 
4133     }
4134 
4135     /**
4136      * Converts the given <code>Object</code> in the Java programming language
4137      * to the standard mapping for the specified SQL target data type.
4138      * The conversion must be to a string or numeric type, but there are no
4139      * restrictions on the type to be converted.  If the source type and target
4140      * type are the same, the given object is simply returned.
4141      *
4142      * @param srcObj the <code>Object</code> in the Java programming language
4143      *               that is to be converted to the target type
4144      * @param srcType the data type that is the standard mapping in SQL of the
4145      *                object to be converted; must be one of the constants in
4146      *                <code>java.sql.Types</code>
4147      * @param trgType the SQL data type to which to convert the given object;
4148      *                must be one of the following constants in
4149      *                <code>java.sql.Types</code>: <code>BIT</code>,
4150      *         or <code>BOOLEAN</code>
4151      * @return an <code>Object</code> value.that is
4152      *         the standard object mapping for the target SQL type
4153      * @throws SQLException if the given target type is not one of the Boolean
4154      *         types in <code>java.sql.Types</code>
4155      */
4156     private Object convertBoolean(Object srcObj, int srcType,
4157     int trgType) throws SQLException {
4158 
4159         if (srcType == trgType) {
4160             return srcObj;
4161         }
4162 
4163         if (isNumeric(trgType) == true ||
4164         (isString(trgType) == false && isBoolean(trgType) == false)) {
4165             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4166         }
4167 
4168 
4169         try {
4170             switch (trgType) {
4171                 case java.sql.Types.BIT:
4172                     Integer i = Integer.valueOf(srcObj.toString().trim());
4173                     return i.equals(0) ?
4174                     Boolean.valueOf(false) :
4175                         Boolean.valueOf(true);
4176                 case java.sql.Types.BOOLEAN:
4177                     return Boolean.valueOf(srcObj.toString().trim());
4178                 default:
4179                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString()+ trgType);
4180             }
4181         } catch (NumberFormatException ex) {
4182             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4183         }
4184     }
4185 
4186     /**
4187      * Sets the designated nullable column in the current row or the
4188      * insert row of this <code>CachedRowSetImpl</code> object with
4189      * <code>null</code> value.
4190      * <P>
4191      * This method updates a column value in the current row or the insert
4192      * row of this rowset; however, another method must be called to complete
4193      * the update process. If the cursor is on a row in the rowset, the
4194      * method {@link #updateRow} must be called to mark the row as updated
4195      * and to notify listeners that the row has changed.
4196      * If the cursor is on the insert row, the method {@link #insertRow}
4197      * must be called to insert the new row into this rowset and to notify
4198      * listeners that a row has changed.
4199      * <P>
4200      * In order to propagate updates in this rowset to the underlying
4201      * data source, an application must call the method {@link #acceptChanges}
4202      * after it calls either <code>updateRow</code> or <code>insertRow</code>.
4203      *
4204      * @param columnIndex the first column is <code>1</code>, the second
4205      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4206      *        and equal to or less than the number of columns in this rowset
4207      * @throws SQLException if (1) the given column index is out of bounds,
4208      *            (2) the cursor is not on one of this rowset's rows or its
4209      *            insert row, or (3) this rowset is
4210      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4211      */
4212     public void updateNull(int columnIndex) throws SQLException {
4213         // sanity check.
4214         checkIndex(columnIndex);
4215         // make sure the cursor is on a valid row
4216         checkCursor();
4217 
4218         BaseRow row = getCurrentRow();
4219         row.setColumnObject(columnIndex, null);
4220 
4221     }
4222 
4223     /**
4224      * Sets the designated column in either the current row or the insert
4225      * row of this <code>CachedRowSetImpl</code> object with the given
4226      * <code>boolean</code> value.
4227      * <P>
4228      * This method updates a column value in the current row or the insert
4229      * row of this rowset, but it does not update the database.
4230      * If the cursor is on a row in the rowset, the
4231      * method {@link #updateRow} must be called to update the database.
4232      * If the cursor is on the insert row, the method {@link #insertRow}
4233      * must be called, which will insert the new row into both this rowset
4234      * and the database. Both of these methods must be called before the
4235      * cursor moves to another row.
4236      *
4237      * @param columnIndex the first column is <code>1</code>, the second
4238      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4239      *        and equal to or less than the number of columns in this rowset
4240      * @param x the new column value
4241      * @throws SQLException if (1) the given column index is out of bounds,
4242      *            (2) the cursor is not on one of this rowset's rows or its
4243      *            insert row, or (3) this rowset is
4244      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4245      */
4246     public void updateBoolean(int columnIndex, boolean x) throws SQLException {
4247         // sanity check.
4248         checkIndex(columnIndex);
4249         // make sure the cursor is on a valid row
4250         checkCursor();
4251         Object obj = convertBoolean(Boolean.valueOf(x),
4252         java.sql.Types.BIT,
4253         RowSetMD.getColumnType(columnIndex));
4254 
4255         getCurrentRow().setColumnObject(columnIndex, obj);
4256     }
4257 
4258     /**
4259      * Sets the designated column in either the current row or the insert
4260      * row of this <code>CachedRowSetImpl</code> object with the given
4261      * <code>byte</code> value.
4262      * <P>
4263      * This method updates a column value in the current row or the insert
4264      * row of this rowset, but it does not update the database.
4265      * If the cursor is on a row in the rowset, the
4266      * method {@link #updateRow} must be called to update the database.
4267      * If the cursor is on the insert row, the method {@link #insertRow}
4268      * must be called, which will insert the new row into both this rowset
4269      * and the database. Both of these methods must be called before the
4270      * cursor moves to another row.
4271      *
4272      * @param columnIndex the first column is <code>1</code>, the second
4273      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4274      *        and equal to or less than the number of columns in this rowset
4275      * @param x the new column value
4276      * @throws SQLException if (1) the given column index is out of bounds,
4277      *            (2) the cursor is not on one of this rowset's rows or its
4278      *            insert row, or (3) this rowset is
4279      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4280      */
4281     public void updateByte(int columnIndex, byte x) throws SQLException {
4282         // sanity check.
4283         checkIndex(columnIndex);
4284         // make sure the cursor is on a valid row
4285         checkCursor();
4286 
4287         Object obj = convertNumeric(Byte.valueOf(x),
4288         java.sql.Types.TINYINT,
4289         RowSetMD.getColumnType(columnIndex));
4290 
4291         getCurrentRow().setColumnObject(columnIndex, obj);
4292     }
4293 
4294     /**
4295      * Sets the designated column in either the current row or the insert
4296      * row of this <code>CachedRowSetImpl</code> object with the given
4297      * <code>short</code> value.
4298      * <P>
4299      * This method updates a column value in the current row or the insert
4300      * row of this rowset, but it does not update the database.
4301      * If the cursor is on a row in the rowset, the
4302      * method {@link #updateRow} must be called to update the database.
4303      * If the cursor is on the insert row, the method {@link #insertRow}
4304      * must be called, which will insert the new row into both this rowset
4305      * and the database. Both of these methods must be called before the
4306      * cursor moves to another row.
4307      *
4308      * @param columnIndex the first column is <code>1</code>, the second
4309      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4310      *        and equal to or less than the number of columns in this rowset
4311      * @param x the new column value
4312      * @throws SQLException if (1) the given column index is out of bounds,
4313      *            (2) the cursor is not on one of this rowset's rows or its
4314      *            insert row, or (3) this rowset is
4315      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4316      */
4317     public void updateShort(int columnIndex, short x) throws SQLException {
4318         // sanity check.
4319         checkIndex(columnIndex);
4320         // make sure the cursor is on a valid row
4321         checkCursor();
4322 
4323         Object obj = convertNumeric(Short.valueOf(x),
4324         java.sql.Types.SMALLINT,
4325         RowSetMD.getColumnType(columnIndex));
4326 
4327         getCurrentRow().setColumnObject(columnIndex, obj);
4328     }
4329 
4330     /**
4331      * Sets the designated column in either the current row or the insert
4332      * row of this <code>CachedRowSetImpl</code> object with the given
4333      * <code>int</code> value.
4334      * <P>
4335      * This method updates a column value in the current row or the insert
4336      * row of this rowset, but it does not update the database.
4337      * If the cursor is on a row in the rowset, the
4338      * method {@link #updateRow} must be called to update the database.
4339      * If the cursor is on the insert row, the method {@link #insertRow}
4340      * must be called, which will insert the new row into both this rowset
4341      * and the database. Both of these methods must be called before the
4342      * cursor moves to another row.
4343      *
4344      * @param columnIndex the first column is <code>1</code>, the second
4345      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4346      *        and equal to or less than the number of columns in this rowset
4347      * @param x the new column value
4348      * @throws SQLException if (1) the given column index is out of bounds,
4349      *            (2) the cursor is not on one of this rowset's rows or its
4350      *            insert row, or (3) this rowset is
4351      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4352      */
4353     public void updateInt(int columnIndex, int x) throws SQLException {
4354         // sanity check.
4355         checkIndex(columnIndex);
4356         // make sure the cursor is on a valid row
4357         checkCursor();
4358         Object obj = convertNumeric(x,
4359         java.sql.Types.INTEGER,
4360         RowSetMD.getColumnType(columnIndex));
4361 
4362         getCurrentRow().setColumnObject(columnIndex, obj);
4363     }
4364 
4365     /**
4366      * Sets the designated column in either the current row or the insert
4367      * row of this <code>CachedRowSetImpl</code> object with the given
4368      * <code>long</code> value.
4369      * <P>
4370      * This method updates a column value in the current row or the insert
4371      * row of this rowset, but it does not update the database.
4372      * If the cursor is on a row in the rowset, the
4373      * method {@link #updateRow} must be called to update the database.
4374      * If the cursor is on the insert row, the method {@link #insertRow}
4375      * must be called, which will insert the new row into both this rowset
4376      * and the database. Both of these methods must be called before the
4377      * cursor moves to another row.
4378      *
4379      * @param columnIndex the first column is <code>1</code>, the second
4380      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4381      *        and equal to or less than the number of columns in this rowset
4382      * @param x the new column value
4383      * @throws SQLException if (1) the given column index is out of bounds,
4384      *            (2) the cursor is not on one of this rowset's rows or its
4385      *            insert row, or (3) this rowset is
4386      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4387      */
4388     public void updateLong(int columnIndex, long x) throws SQLException {
4389         // sanity check.
4390         checkIndex(columnIndex);
4391         // make sure the cursor is on a valid row
4392         checkCursor();
4393 
4394         Object obj = convertNumeric(Long.valueOf(x),
4395         java.sql.Types.BIGINT,
4396         RowSetMD.getColumnType(columnIndex));
4397 
4398         getCurrentRow().setColumnObject(columnIndex, obj);
4399 
4400     }
4401 
4402     /**
4403      * Sets the designated column in either the current row or the insert
4404      * row of this <code>CachedRowSetImpl</code> object with the given
4405      * <code>float</code> value.
4406      * <P>
4407      * This method updates a column value in the current row or the insert
4408      * row of this rowset, but it does not update the database.
4409      * If the cursor is on a row in the rowset, the
4410      * method {@link #updateRow} must be called to update the database.
4411      * If the cursor is on the insert row, the method {@link #insertRow}
4412      * must be called, which will insert the new row into both this rowset
4413      * and the database. Both of these methods must be called before the
4414      * cursor moves to another row.
4415      *
4416      * @param columnIndex the first column is <code>1</code>, the second
4417      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4418      *        and equal to or less than the number of columns in this rowset
4419      * @param x the new column value
4420      * @throws SQLException if (1) the given column index is out of bounds,
4421      *            (2) the cursor is not on one of this rowset's rows or its
4422      *            insert row, or (3) this rowset is
4423      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4424      */
4425     public void updateFloat(int columnIndex, float x) throws SQLException {
4426         // sanity check.
4427         checkIndex(columnIndex);
4428         // make sure the cursor is on a valid row
4429         checkCursor();
4430 
4431         Object obj = convertNumeric(Float.valueOf(x),
4432         java.sql.Types.REAL,
4433         RowSetMD.getColumnType(columnIndex));
4434 
4435         getCurrentRow().setColumnObject(columnIndex, obj);
4436     }
4437 
4438     /**
4439      * Sets the designated column in either the current row or the insert
4440      * row of this <code>CachedRowSetImpl</code> object with the given
4441      * <code>double</code> value.
4442      *
4443      * This method updates a column value in either the current row or
4444      * the insert row of this rowset, but it does not update the
4445      * database.  If the cursor is on a row in the rowset, the
4446      * method {@link #updateRow} must be called to update the database.
4447      * If the cursor is on the insert row, the method {@link #insertRow}
4448      * must be called, which will insert the new row into both this rowset
4449      * and the database. Both of these methods must be called before the
4450      * cursor moves to another row.
4451      *
4452      * @param columnIndex the first column is <code>1</code>, the second
4453      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4454      *        and equal to or less than the number of columns in this rowset
4455      * @param x the new column value
4456      * @throws SQLException if (1) the given column index is out of bounds,
4457      *            (2) the cursor is not on one of this rowset's rows or its
4458      *            insert row, or (3) this rowset is
4459      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4460      */
4461     public void updateDouble(int columnIndex, double x) throws SQLException {
4462         // sanity check.
4463         checkIndex(columnIndex);
4464         // make sure the cursor is on a valid row
4465         checkCursor();
4466         Object obj = convertNumeric(Double.valueOf(x),
4467         java.sql.Types.DOUBLE,
4468         RowSetMD.getColumnType(columnIndex));
4469 
4470         getCurrentRow().setColumnObject(columnIndex, obj);
4471     }
4472 
4473     /**
4474      * Sets the designated column in either the current row or the insert
4475      * row of this <code>CachedRowSetImpl</code> object with the given
4476      * <code>java.math.BigDecimal</code> object.
4477      * <P>
4478      * This method updates a column value in the current row or the insert
4479      * row of this rowset, but it does not update the database.
4480      * If the cursor is on a row in the rowset, the
4481      * method {@link #updateRow} must be called to update the database.
4482      * If the cursor is on the insert row, the method {@link #insertRow}
4483      * must be called, which will insert the new row into both this rowset
4484      * and the database. Both of these methods must be called before the
4485      * cursor moves to another row.
4486      *
4487      * @param columnIndex the first column is <code>1</code>, the second
4488      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4489      *        and equal to or less than the number of columns in this rowset
4490      * @param x the new column value
4491      * @throws SQLException if (1) the given column index is out of bounds,
4492      *            (2) the cursor is not on one of this rowset's rows or its
4493      *            insert row, or (3) this rowset is
4494      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4495      */
4496     public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {
4497         // sanity check.
4498         checkIndex(columnIndex);
4499         // make sure the cursor is on a valid row
4500         checkCursor();
4501 
4502         Object obj = convertNumeric(x,
4503         java.sql.Types.NUMERIC,
4504         RowSetMD.getColumnType(columnIndex));
4505 
4506         getCurrentRow().setColumnObject(columnIndex, obj);
4507     }
4508 
4509     /**
4510      * Sets the designated column in either the current row or the insert
4511      * row of this <code>CachedRowSetImpl</code> object with the given
4512      * <code>String</code> object.
4513      * <P>
4514      * This method updates a column value in either the current row or
4515      * the insert row of this rowset, but it does not update the
4516      * database.  If the cursor is on a row in the rowset, the
4517      * method {@link #updateRow} must be called to mark the row as updated.
4518      * If the cursor is on the insert row, the method {@link #insertRow}
4519      * must be called to insert the new row into this rowset and mark it
4520      * as inserted. Both of these methods must be called before the
4521      * cursor moves to another row.
4522      * <P>
4523      * The method <code>acceptChanges</code> must be called if the
4524      * updated values are to be written back to the underlying database.
4525      *
4526      * @param columnIndex the first column is <code>1</code>, the second
4527      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4528      *        and equal to or less than the number of columns in this rowset
4529      * @param x the new column value
4530      * @throws SQLException if (1) the given column index is out of bounds,
4531      *            (2) the cursor is not on one of this rowset's rows or its
4532      *            insert row, or (3) this rowset is
4533      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4534      */
4535     public void updateString(int columnIndex, String x) throws SQLException {
4536         // sanity check.
4537         checkIndex(columnIndex);
4538         // make sure the cursor is on a valid row
4539         checkCursor();
4540 
4541         getCurrentRow().setColumnObject(columnIndex, x);
4542     }
4543 
4544     /**
4545      * Sets the designated column in either the current row or the insert
4546      * row of this <code>CachedRowSetImpl</code> object with the given
4547      * <code>byte</code> array.
4548      *
4549      * This method updates a column value in either the current row or
4550      * the insert row of this rowset, but it does not update the
4551      * database.  If the cursor is on a row in the rowset, the
4552      * method {@link #updateRow} must be called to update the database.
4553      * If the cursor is on the insert row, the method {@link #insertRow}
4554      * must be called, which will insert the new row into both this rowset
4555      * and the database. Both of these methods must be called before the
4556      * cursor moves to another row.
4557      *
4558      * @param columnIndex the first column is <code>1</code>, the second
4559      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4560      *        and equal to or less than the number of columns in this rowset
4561      * @param x the new column value
4562      * @throws SQLException if (1) the given column index is out of bounds,
4563      *            (2) the cursor is not on one of this rowset's rows or its
4564      *            insert row, or (3) this rowset is
4565      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4566      */
4567     public void updateBytes(int columnIndex, byte x[]) throws SQLException {
4568         // sanity check.
4569         checkIndex(columnIndex);
4570         // make sure the cursor is on a valid row
4571         checkCursor();
4572 
4573         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4574             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4575         }
4576 
4577         getCurrentRow().setColumnObject(columnIndex, x);
4578     }
4579 
4580     /**
4581      * Sets the designated column in either the current row or the insert
4582      * row of this <code>CachedRowSetImpl</code> object with the given
4583      * <code>Date</code> object.
4584      *
4585      * This method updates a column value in either the current row or
4586      * the insert row of this rowset, but it does not update the
4587      * database.  If the cursor is on a row in the rowset, the
4588      * method {@link #updateRow} must be called to update the database.
4589      * If the cursor is on the insert row, the method {@link #insertRow}
4590      * must be called, which will insert the new row into both this rowset
4591      * and the database. Both of these methods must be called before the
4592      * cursor moves to another row.
4593      *
4594      * @param columnIndex the first column is <code>1</code>, the second
4595      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4596      *        and equal to or less than the number of columns in this rowset
4597      * @param x the new column value
4598      * @throws SQLException if (1) the given column index is out of bounds,
4599      *            (2) the cursor is not on one of this rowset's rows or its
4600      *            insert row, (3) the type of the designated column is not
4601      *            an SQL <code>DATE</code> or <code>TIMESTAMP</code>, or
4602      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4603      */
4604     public void updateDate(int columnIndex, java.sql.Date x) throws SQLException {
4605         // sanity check.
4606         checkIndex(columnIndex);
4607         // make sure the cursor is on a valid row
4608         checkCursor();
4609 
4610         Object obj = convertTemporal(x,
4611         java.sql.Types.DATE,
4612         RowSetMD.getColumnType(columnIndex));
4613 
4614         getCurrentRow().setColumnObject(columnIndex, obj);
4615     }
4616 
4617     /**
4618      * Sets the designated column in either the current row or the insert
4619      * row of this <code>CachedRowSetImpl</code> object with the given
4620      * <code>Time</code> object.
4621      *
4622      * This method updates a column value in either the current row or
4623      * the insert row of this rowset, but it does not update the
4624      * database.  If the cursor is on a row in the rowset, the
4625      * method {@link #updateRow} must be called to update the database.
4626      * If the cursor is on the insert row, the method {@link #insertRow}
4627      * must be called, which will insert the new row into both this rowset
4628      * and the database. Both of these methods must be called before the
4629      * cursor moves to another row.
4630      *
4631      * @param columnIndex the first column is <code>1</code>, the second
4632      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4633      *        and equal to or less than the number of columns in this rowset
4634      * @param x the new column value
4635      * @throws SQLException if (1) the given column index is out of bounds,
4636      *            (2) the cursor is not on one of this rowset's rows or its
4637      *            insert row, (3) the type of the designated column is not
4638      *            an SQL <code>TIME</code> or <code>TIMESTAMP</code>, or
4639      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4640      */
4641     public void updateTime(int columnIndex, java.sql.Time x) throws SQLException {
4642         // sanity check.
4643         checkIndex(columnIndex);
4644         // make sure the cursor is on a valid row
4645         checkCursor();
4646 
4647         Object obj = convertTemporal(x,
4648         java.sql.Types.TIME,
4649         RowSetMD.getColumnType(columnIndex));
4650 
4651         getCurrentRow().setColumnObject(columnIndex, obj);
4652     }
4653 
4654     /**
4655      * Sets the designated column in either the current row or the insert
4656      * row of this <code>CachedRowSetImpl</code> object with the given
4657      * <code>Timestamp</code> object.
4658      *
4659      * This method updates a column value in either the current row or
4660      * the insert row of this rowset, but it does not update the
4661      * database.  If the cursor is on a row in the rowset, the
4662      * method {@link #updateRow} must be called to update the database.
4663      * If the cursor is on the insert row, the method {@link #insertRow}
4664      * must be called, which will insert the new row into both this rowset
4665      * and the database. Both of these methods must be called before the
4666      * cursor moves to another row.
4667      *
4668      * @param columnIndex the first column is <code>1</code>, the second
4669      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4670      *        and equal to or less than the number of columns in this rowset
4671      * @param x the new column value
4672      * @throws SQLException if (1) the given column index is out of bounds,
4673      *            (2) the cursor is not on one of this rowset's rows or its
4674      *            insert row, (3) the type of the designated column is not
4675      *            an SQL <code>DATE</code>, <code>TIME</code>, or
4676      *            <code>TIMESTAMP</code>, or (4) this rowset is
4677      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4678      */
4679     public void updateTimestamp(int columnIndex, java.sql.Timestamp x) throws SQLException {
4680         // sanity check.
4681         checkIndex(columnIndex);
4682         // make sure the cursor is on a valid row
4683         checkCursor();
4684 
4685         Object obj = convertTemporal(x,
4686         java.sql.Types.TIMESTAMP,
4687         RowSetMD.getColumnType(columnIndex));
4688 
4689         getCurrentRow().setColumnObject(columnIndex, obj);
4690     }
4691 
4692     /**
4693      * Sets the designated column in either the current row or the insert
4694      * row of this <code>CachedRowSetImpl</code> object with the given
4695      * ASCII stream value.
4696      * <P>
4697      * This method updates a column value in either the current row or
4698      * the insert row of this rowset, but it does not update the
4699      * database.  If the cursor is on a row in the rowset, the
4700      * method {@link #updateRow} must be called to update the database.
4701      * If the cursor is on the insert row, the method {@link #insertRow}
4702      * must be called, which will insert the new row into both this rowset
4703      * and the database. Both of these methods must be called before the
4704      * cursor moves to another row.
4705      *
4706      * @param columnIndex the first column is <code>1</code>, the second
4707      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4708      *        and equal to or less than the number of columns in this rowset
4709      * @param x the new column value
4710      * @param length the number of one-byte ASCII characters in the stream
4711      * @throws SQLException if this method is invoked
4712      */
4713     public void updateAsciiStream(int columnIndex, java.io.InputStream x, int length) throws SQLException {
4714         // sanity Check
4715         checkIndex(columnIndex);
4716         // make sure the cursor is on a valid row
4717         checkCursor();
4718 
4719 
4720         if (isString(RowSetMD.getColumnType(columnIndex)) == false &&
4721         isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4722             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4723         }
4724 
4725         byte buf[] = new byte[length];
4726         try {
4727             int charsRead = 0;
4728             do {
4729                 charsRead += x.read(buf, charsRead, length - charsRead);
4730             } while (charsRead != length);
4731             //Changed the condition check to check for length instead of -1
4732         } catch (java.io.IOException ex) {
4733             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.asciistream").toString());
4734         }
4735         String str = new String(buf);
4736 
4737         getCurrentRow().setColumnObject(columnIndex, str);
4738 
4739     }
4740 
4741     /**
4742      * Sets the designated column in either the current row or the insert
4743      * row of this <code>CachedRowSetImpl</code> object with the given
4744      * <code>java.io.InputStream</code> object.
4745      * <P>
4746      * This method updates a column value in either the current row or
4747      * the insert row of this rowset, but it does not update the
4748      * database.  If the cursor is on a row in the rowset, the
4749      * method {@link #updateRow} must be called to update the database.
4750      * If the cursor is on the insert row, the method {@link #insertRow}
4751      * must be called, which will insert the new row into both this rowset
4752      * and the database. Both of these methods must be called before the
4753      * cursor moves to another row.
4754      *
4755      * @param columnIndex the first column is <code>1</code>, the second
4756      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4757      *        and equal to or less than the number of columns in this rowset
4758      * @param x the new column value; must be a <code>java.io.InputStream</code>
4759      *          containing <code>BINARY</code>, <code>VARBINARY</code>, or
4760      *          <code>LONGVARBINARY</code> data
4761      * @param length the length of the stream in bytes
4762      * @throws SQLException if (1) the given column index is out of bounds,
4763      *            (2) the cursor is not on one of this rowset's rows or its
4764      *            insert row, (3) the data in the stream is not binary, or
4765      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4766      */
4767     public void updateBinaryStream(int columnIndex, java.io.InputStream x,int length) throws SQLException {
4768         // sanity Check
4769         checkIndex(columnIndex);
4770         // make sure the cursor is on a valid row
4771         checkCursor();
4772 
4773         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4774             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4775         }
4776 
4777         byte buf[] = new byte[length];
4778         try {
4779             int bytesRead = 0;
4780             do {
4781                 bytesRead += x.read(buf, bytesRead, length - bytesRead);
4782             } while (bytesRead != -1);
4783         } catch (java.io.IOException ex) {
4784             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.binstream").toString());
4785         }
4786 
4787         getCurrentRow().setColumnObject(columnIndex, buf);
4788     }
4789 
4790     /**
4791      * Sets the designated column in either the current row or the insert
4792      * row of this <code>CachedRowSetImpl</code> object with the given
4793      * <code>java.io.Reader</code> object.
4794      * <P>
4795      * This method updates a column value in either the current row or
4796      * the insert row of this rowset, but it does not update the
4797      * database.  If the cursor is on a row in the rowset, the
4798      * method {@link #updateRow} must be called to update the database.
4799      * If the cursor is on the insert row, the method {@link #insertRow}
4800      * must be called, which will insert the new row into both this rowset
4801      * and the database. Both of these methods must be called before the
4802      * cursor moves to another row.
4803      *
4804      * @param columnIndex the first column is <code>1</code>, the second
4805      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4806      *        and equal to or less than the number of columns in this rowset
4807      * @param x the new column value; must be a <code>java.io.Reader</code>
4808      *          containing <code>BINARY</code>, <code>VARBINARY</code>,
4809      *          <code>LONGVARBINARY</code>, <code>CHAR</code>, <code>VARCHAR</code>,
4810      *          or <code>LONGVARCHAR</code> data
4811      * @param length the length of the stream in characters
4812      * @throws SQLException if (1) the given column index is out of bounds,
4813      *            (2) the cursor is not on one of this rowset's rows or its
4814      *            insert row, (3) the data in the stream is not a binary or
4815      *            character type, or (4) this rowset is
4816      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4817      */
4818     public void updateCharacterStream(int columnIndex, java.io.Reader x, int length) throws SQLException {
4819         // sanity Check
4820         checkIndex(columnIndex);
4821         // make sure the cursor is on a valid row
4822         checkCursor();
4823 
4824         if (isString(RowSetMD.getColumnType(columnIndex)) == false &&
4825         isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4826             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4827         }
4828 
4829         char buf[] = new char[length];
4830         try {
4831             int charsRead = 0;
4832             do {
4833                 charsRead += x.read(buf, charsRead, length - charsRead);
4834             } while (charsRead != length);
4835             //Changed the condition checking to check for length instead of -1
4836         } catch (java.io.IOException ex) {
4837             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.binstream").toString());
4838         }
4839         String str = new String(buf);
4840 
4841         getCurrentRow().setColumnObject(columnIndex, str);
4842     }
4843 
4844     /**
4845      * Sets the designated column in either the current row or the insert
4846      * row of this <code>CachedRowSetImpl</code> object with the given
4847      * <code>Object</code> value.  The <code>scale</code> parameter indicates
4848      * the number of digits to the right of the decimal point and is ignored
4849      * if the new column value is not a type that will be mapped to an SQL
4850      * <code>DECIMAL</code> or <code>NUMERIC</code> value.
4851      * <P>
4852      * This method updates a column value in either the current row or
4853      * the insert row of this rowset, but it does not update the
4854      * database.  If the cursor is on a row in the rowset, the
4855      * method {@link #updateRow} must be called to update the database.
4856      * If the cursor is on the insert row, the method {@link #insertRow}
4857      * must be called, which will insert the new row into both this rowset
4858      * and the database. Both of these methods must be called before the
4859      * cursor moves to another row.
4860      *
4861      * @param columnIndex the first column is <code>1</code>, the second
4862      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4863      *        and equal to or less than the number of columns in this rowset
4864      * @param x the new column value
4865      * @param scale the number of digits to the right of the decimal point (for
4866      *              <code>DECIMAL</code> and <code>NUMERIC</code> types only)
4867      * @throws SQLException if (1) the given column index is out of bounds,
4868      *            (2) the cursor is not on one of this rowset's rows or its
4869      *            insert row, or (3) this rowset is
4870      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4871      */
4872     public void updateObject(int columnIndex, Object x, int scale) throws SQLException {
4873         // sanity check.
4874         checkIndex(columnIndex);
4875         // make sure the cursor is on a valid row
4876         checkCursor();
4877 
4878         int type = RowSetMD.getColumnType(columnIndex);
4879         if (type == Types.DECIMAL || type == Types.NUMERIC) {
4880             ((java.math.BigDecimal)x).setScale(scale);
4881         }
4882         getCurrentRow().setColumnObject(columnIndex, x);
4883     }
4884 
4885     /**
4886      * Sets the designated column in either the current row or the insert
4887      * row of this <code>CachedRowSetImpl</code> object with the given
4888      * <code>Object</code> value.
4889      * <P>
4890      * This method updates a column value in either the current row or
4891      * the insert row of this rowset, but it does not update the
4892      * database.  If the cursor is on a row in the rowset, the
4893      * method {@link #updateRow} must be called to update the database.
4894      * If the cursor is on the insert row, the method {@link #insertRow}
4895      * must be called, which will insert the new row into both this rowset
4896      * and the database. Both of these methods must be called before the
4897      * cursor moves to another row.
4898      *
4899      * @param columnIndex the first column is <code>1</code>, the second
4900      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4901      *        and equal to or less than the number of columns in this rowset
4902      * @param x the new column value
4903      * @throws SQLException if (1) the given column index is out of bounds,
4904      *            (2) the cursor is not on one of this rowset's rows or its
4905      *            insert row, or (3) this rowset is
4906      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4907      */
4908     public void updateObject(int columnIndex, Object x) throws SQLException {
4909         // sanity check.
4910         checkIndex(columnIndex);
4911         // make sure the cursor is on a valid row
4912         checkCursor();
4913 
4914         getCurrentRow().setColumnObject(columnIndex, x);
4915     }
4916 
4917     /**
4918      * Sets the designated nullable column in the current row or the
4919      * insert row of this <code>CachedRowSetImpl</code> object with
4920      * <code>null</code> value.
4921      * <P>
4922      * This method updates a column value in the current row or the insert
4923      * row of this rowset, but it does not update the database.
4924      * If the cursor is on a row in the rowset, the
4925      * method {@link #updateRow} must be called to update the database.
4926      * If the cursor is on the insert row, the method {@link #insertRow}
4927      * must be called, which will insert the new row into both this rowset
4928      * and the database.
4929      *
4930      * @param columnName a <code>String</code> object that must match the
4931      *        SQL name of a column in this rowset, ignoring case
4932      * @throws SQLException if (1) the given column name does not match the
4933      *            name of a column in this rowset, (2) the cursor is not on
4934      *            one of this rowset's rows or its insert row, or (3) this
4935      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4936      */
4937     public void updateNull(String columnName) throws SQLException {
4938         updateNull(getColIdxByName(columnName));
4939     }
4940 
4941     /**
4942      * Sets the designated column in either the current row or the insert
4943      * row of this <code>CachedRowSetImpl</code> object with the given
4944      * <code>boolean</code> value.
4945      * <P>
4946      * This method updates a column value in the current row or the insert
4947      * row of this rowset, but it does not update the database.
4948      * If the cursor is on a row in the rowset, the
4949      * method {@link #updateRow} must be called to update the database.
4950      * If the cursor is on the insert row, the method {@link #insertRow}
4951      * must be called, which will insert the new row into both this rowset
4952      * and the database. Both of these methods must be called before the
4953      * cursor moves to another row.
4954      *
4955      * @param columnName a <code>String</code> object that must match the
4956      *        SQL name of a column in this rowset, ignoring case
4957      * @param x the new column value
4958      * @throws SQLException if (1) the given column name does not match the
4959      *            name of a column in this rowset, (2) the cursor is not on
4960      *            one of this rowset's rows or its insert row, or (3) this
4961      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4962      */
4963     public void updateBoolean(String columnName, boolean x) throws SQLException {
4964         updateBoolean(getColIdxByName(columnName), x);
4965     }
4966 
4967     /**
4968      * Sets the designated column in either the current row or the insert
4969      * row of this <code>CachedRowSetImpl</code> object with the given
4970      * <code>byte</code> value.
4971      * <P>
4972      * This method updates a column value in the current row or the insert
4973      * row of this rowset, but it does not update the database.
4974      * If the cursor is on a row in the rowset, the
4975      * method {@link #updateRow} must be called to update the database.
4976      * If the cursor is on the insert row, the method {@link #insertRow}
4977      * must be called, which will insert the new row into both this rowset
4978      * and the database. Both of these methods must be called before the
4979      * cursor moves to another row.
4980      *
4981      * @param columnName a <code>String</code> object that must match the
4982      *        SQL name of a column in this rowset, ignoring case
4983      * @param x the new column value
4984      * @throws SQLException if (1) the given column name does not match the
4985      *            name of a column in this rowset, (2) the cursor is not on
4986      *            one of this rowset's rows or its insert row, or (3) this
4987      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4988      */
4989     public void updateByte(String columnName, byte x) throws SQLException {
4990         updateByte(getColIdxByName(columnName), x);
4991     }
4992 
4993     /**
4994      * Sets the designated column in either the current row or the insert
4995      * row of this <code>CachedRowSetImpl</code> object with the given
4996      * <code>short</code> value.
4997      * <P>
4998      * This method updates a column value in the current row or the insert
4999      * row of this rowset, but it does not update the database.
5000      * If the cursor is on a row in the rowset, the
5001      * method {@link #updateRow} must be called to update the database.
5002      * If the cursor is on the insert row, the method {@link #insertRow}
5003      * must be called, which will insert the new row into both this rowset
5004      * and the database. Both of these methods must be called before the
5005      * cursor moves to another row.
5006      *
5007      * @param columnName a <code>String</code> object that must match the
5008      *        SQL name of a column in this rowset, ignoring case
5009      * @param x the new column value
5010      * @throws SQLException if (1) the given column name does not match the
5011      *            name of a column in this rowset, (2) the cursor is not on
5012      *            one of this rowset's rows or its insert row, or (3) this
5013      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5014      */
5015     public void updateShort(String columnName, short x) throws SQLException {
5016         updateShort(getColIdxByName(columnName), x);
5017     }
5018 
5019     /**
5020      * Sets the designated column in either the current row or the insert
5021      * row of this <code>CachedRowSetImpl</code> object with the given
5022      * <code>int</code> value.
5023      * <P>
5024      * This method updates a column value in the current row or the insert
5025      * row of this rowset, but it does not update the database.
5026      * If the cursor is on a row in the rowset, the
5027      * method {@link #updateRow} must be called to update the database.
5028      * If the cursor is on the insert row, the method {@link #insertRow}
5029      * must be called, which will insert the new row into both this rowset
5030      * and the database. Both of these methods must be called before the
5031      * cursor moves to another row.
5032      *
5033      * @param columnName a <code>String</code> object that must match the
5034      *        SQL name of a column in this rowset, ignoring case
5035      * @param x the new column value
5036      * @throws SQLException if (1) the given column name does not match the
5037      *            name of a column in this rowset, (2) the cursor is not on
5038      *            one of this rowset's rows or its insert row, or (3) this
5039      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5040      */
5041     public void updateInt(String columnName, int x) throws SQLException {
5042         updateInt(getColIdxByName(columnName), x);
5043     }
5044 
5045     /**
5046      * Sets the designated column in either the current row or the insert
5047      * row of this <code>CachedRowSetImpl</code> object with the given
5048      * <code>long</code> value.
5049      * <P>
5050      * This method updates a column value in the current row or the insert
5051      * row of this rowset, but it does not update the database.
5052      * If the cursor is on a row in the rowset, the
5053      * method {@link #updateRow} must be called to update the database.
5054      * If the cursor is on the insert row, the method {@link #insertRow}
5055      * must be called, which will insert the new row into both this rowset
5056      * and the database. Both of these methods must be called before the
5057      * cursor moves to another row.
5058      *
5059      * @param columnName a <code>String</code> object that must match the
5060      *        SQL name of a column in this rowset, ignoring case
5061      * @param x the new column value
5062      * @throws SQLException if (1) the given column name does not match the
5063      *            name of a column in this rowset, (2) the cursor is not on
5064      *            one of this rowset's rows or its insert row, or (3) this
5065      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5066      */
5067     public void updateLong(String columnName, long x) throws SQLException {
5068         updateLong(getColIdxByName(columnName), x);
5069     }
5070 
5071     /**
5072      * Sets the designated column in either the current row or the insert
5073      * row of this <code>CachedRowSetImpl</code> object with the given
5074      * <code>float</code> value.
5075      * <P>
5076      * This method updates a column value in the current row or the insert
5077      * row of this rowset, but it does not update the database.
5078      * If the cursor is on a row in the rowset, the
5079      * method {@link #updateRow} must be called to update the database.
5080      * If the cursor is on the insert row, the method {@link #insertRow}
5081      * must be called, which will insert the new row into both this rowset
5082      * and the database. Both of these methods must be called before the
5083      * cursor moves to another row.
5084      *
5085      * @param columnName a <code>String</code> object that must match the
5086      *        SQL name of a column in this rowset, ignoring case
5087      * @param x the new column value
5088      * @throws SQLException if (1) the given column name does not match the
5089      *            name of a column in this rowset, (2) the cursor is not on
5090      *            one of this rowset's rows or its insert row, or (3) this
5091      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5092      */
5093     public void updateFloat(String columnName, float x) throws SQLException {
5094         updateFloat(getColIdxByName(columnName), x);
5095     }
5096 
5097     /**
5098      * Sets the designated column in either the current row or the insert
5099      * row of this <code>CachedRowSetImpl</code> object with the given
5100      * <code>double</code> value.
5101      *
5102      * This method updates a column value in either the current row or
5103      * the insert row of this rowset, but it does not update the
5104      * database.  If the cursor is on a row in the rowset, the
5105      * method {@link #updateRow} must be called to update the database.
5106      * If the cursor is on the insert row, the method {@link #insertRow}
5107      * must be called, which will insert the new row into both this rowset
5108      * and the database. Both of these methods must be called before the
5109      * cursor moves to another row.
5110      *
5111      * @param columnName a <code>String</code> object that must match the
5112      *        SQL name of a column in this rowset, ignoring case
5113      * @param x the new column value
5114      * @throws SQLException if (1) the given column name does not match the
5115      *            name of a column in this rowset, (2) the cursor is not on
5116      *            one of this rowset's rows or its insert row, or (3) this
5117      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5118      */
5119     public void updateDouble(String columnName, double x) throws SQLException {
5120         updateDouble(getColIdxByName(columnName), x);
5121     }
5122 
5123     /**
5124      * Sets the designated column in either the current row or the insert
5125      * row of this <code>CachedRowSetImpl</code> object with the given
5126      * <code>java.math.BigDecimal</code> object.
5127      * <P>
5128      * This method updates a column value in the current row or the insert
5129      * row of this rowset, but it does not update the database.
5130      * If the cursor is on a row in the rowset, the
5131      * method {@link #updateRow} must be called to update the database.
5132      * If the cursor is on the insert row, the method {@link #insertRow}
5133      * must be called, which will insert the new row into both this rowset
5134      * and the database. Both of these methods must be called before the
5135      * cursor moves to another row.
5136      *
5137      * @param columnName a <code>String</code> object that must match the
5138      *        SQL name of a column in this rowset, ignoring case
5139      * @param x the new column value
5140      * @throws SQLException if (1) the given column name does not match the
5141      *            name of a column in this rowset, (2) the cursor is not on
5142      *            one of this rowset's rows or its insert row, or (3) this
5143      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5144      */
5145     public void updateBigDecimal(String columnName, BigDecimal x) throws SQLException {
5146         updateBigDecimal(getColIdxByName(columnName), x);
5147     }
5148 
5149     /**
5150      * Sets the designated column in either the current row or the insert
5151      * row of this <code>CachedRowSetImpl</code> object with the given
5152      * <code>String</code> object.
5153      *
5154      * This method updates a column value in either the current row or
5155      * the insert row of this rowset, but it does not update the
5156      * database.  If the cursor is on a row in the rowset, the
5157      * method {@link #updateRow} must be called to update the database.
5158      * If the cursor is on the insert row, the method {@link #insertRow}
5159      * must be called, which will insert the new row into both this rowset
5160      * and the database. Both of these methods must be called before the
5161      * cursor moves to another row.
5162      *
5163      * @param columnName a <code>String</code> object that must match the
5164      *        SQL name of a column in this rowset, ignoring case
5165      * @param x the new column value
5166      * @throws SQLException if (1) the given column name does not match the
5167      *            name of a column in this rowset, (2) the cursor is not on
5168      *            one of this rowset's rows or its insert row, or (3) this
5169      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5170      */
5171     public void updateString(String columnName, String x) throws SQLException {
5172         updateString(getColIdxByName(columnName), x);
5173     }
5174 
5175     /**
5176      * Sets the designated column in either the current row or the insert
5177      * row of this <code>CachedRowSetImpl</code> object with the given
5178      * <code>byte</code> array.
5179      *
5180      * This method updates a column value in either the current row or
5181      * the insert row of this rowset, but it does not update the
5182      * database.  If the cursor is on a row in the rowset, the
5183      * method {@link #updateRow} must be called to update the database.
5184      * If the cursor is on the insert row, the method {@link #insertRow}
5185      * must be called, which will insert the new row into both this rowset
5186      * and the database. Both of these methods must be called before the
5187      * cursor moves to another row.
5188      *
5189      * @param columnName a <code>String</code> object that must match the
5190      *        SQL name of a column in this rowset, ignoring case
5191      * @param x the new column value
5192      * @throws SQLException if (1) the given column name does not match the
5193      *            name of a column in this rowset, (2) the cursor is not on
5194      *            one of this rowset's rows or its insert row, or (3) this
5195      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5196      */
5197     public void updateBytes(String columnName, byte x[]) throws SQLException {
5198         updateBytes(getColIdxByName(columnName), x);
5199     }
5200 
5201     /**
5202      * Sets the designated column in either the current row or the insert
5203      * row of this <code>CachedRowSetImpl</code> object with the given
5204      * <code>Date</code> object.
5205      *
5206      * This method updates a column value in either the current row or
5207      * the insert row of this rowset, but it does not update the
5208      * database.  If the cursor is on a row in the rowset, the
5209      * method {@link #updateRow} must be called to update the database.
5210      * If the cursor is on the insert row, the method {@link #insertRow}
5211      * must be called, which will insert the new row into both this rowset
5212      * and the database. Both of these methods must be called before the
5213      * cursor moves to another row.
5214      *
5215      * @param columnName a <code>String</code> object that must match the
5216      *        SQL name of a column in this rowset, ignoring case
5217      * @param x the new column value
5218      * @throws SQLException if (1) the given column name does not match the
5219      *            name of a column in this rowset, (2) the cursor is not on
5220      *            one of this rowset's rows or its insert row, (3) the type
5221      *            of the designated column is not an SQL <code>DATE</code> or
5222      *            <code>TIMESTAMP</code>, or (4) this rowset is
5223      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5224      */
5225     public void updateDate(String columnName, java.sql.Date x) throws SQLException {
5226         updateDate(getColIdxByName(columnName), x);
5227     }
5228 
5229     /**
5230      * Sets the designated column in either the current row or the insert
5231      * row of this <code>CachedRowSetImpl</code> object with the given
5232      * <code>Time</code> object.
5233      *
5234      * This method updates a column value in either the current row or
5235      * the insert row of this rowset, but it does not update the
5236      * database.  If the cursor is on a row in the rowset, the
5237      * method {@link #updateRow} must be called to update the database.
5238      * If the cursor is on the insert row, the method {@link #insertRow}
5239      * must be called, which will insert the new row into both this rowset
5240      * and the database. Both of these methods must be called before the
5241      * cursor moves to another row.
5242      *
5243      * @param columnName a <code>String</code> object that must match the
5244      *        SQL name of a column in this rowset, ignoring case
5245      * @param x the new column value
5246      * @throws SQLException if (1) the given column name does not match the
5247      *            name of a column in this rowset, (2) the cursor is not on
5248      *            one of this rowset's rows or its insert row, (3) the type
5249      *            of the designated column is not an SQL <code>TIME</code> or
5250      *            <code>TIMESTAMP</code>, or (4) this rowset is
5251      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5252      */
5253     public void updateTime(String columnName, java.sql.Time x) throws SQLException {
5254         updateTime(getColIdxByName(columnName), x);
5255     }
5256 
5257     /**
5258      * Sets the designated column in either the current row or the insert
5259      * row of this <code>CachedRowSetImpl</code> object with the given
5260      * <code>Timestamp</code> object.
5261      *
5262      * This method updates a column value in either the current row or
5263      * the insert row of this rowset, but it does not update the
5264      * database.  If the cursor is on a row in the rowset, the
5265      * method {@link #updateRow} must be called to update the database.
5266      * If the cursor is on the insert row, the method {@link #insertRow}
5267      * must be called, which will insert the new row into both this rowset
5268      * and the database. Both of these methods must be called before the
5269      * cursor moves to another row.
5270      *
5271      * @param columnName a <code>String</code> object that must match the
5272      *        SQL name of a column in this rowset, ignoring case
5273      * @param x the new column value
5274      * @throws SQLException if the given column index is out of bounds or
5275      *            the cursor is not on one of this rowset's rows or its
5276      *            insert row
5277      * @throws SQLException if (1) the given column name does not match the
5278      *            name of a column in this rowset, (2) the cursor is not on
5279      *            one of this rowset's rows or its insert row, (3) the type
5280      *            of the designated column is not an SQL <code>DATE</code>,
5281      *            <code>TIME</code>, or <code>TIMESTAMP</code>, or (4) this
5282      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5283      */
5284     public void updateTimestamp(String columnName, java.sql.Timestamp x) throws SQLException {
5285         updateTimestamp(getColIdxByName(columnName), x);
5286     }
5287 
5288     /**
5289      * Sets the designated column in either the current row or the insert
5290      * row of this <code>CachedRowSetImpl</code> object with the given
5291      * ASCII stream value.
5292      * <P>
5293      * This method updates a column value in either the current row or
5294      * the insert row of this rowset, but it does not update the
5295      * database.  If the cursor is on a row in the rowset, the
5296      * method {@link #updateRow} must be called to update the database.
5297      * If the cursor is on the insert row, the method {@link #insertRow}
5298      * must be called, which will insert the new row into both this rowset
5299      * and the database. Both of these methods must be called before the
5300      * cursor moves to another row.
5301      *
5302      * @param columnName a <code>String</code> object that must match the
5303      *        SQL name of a column in this rowset, ignoring case
5304      * @param x the new column value
5305      * @param length the number of one-byte ASCII characters in the stream
5306      */
5307     public void updateAsciiStream(String columnName,
5308     java.io.InputStream x,
5309     int length) throws SQLException {
5310         updateAsciiStream(getColIdxByName(columnName), x, length);
5311     }
5312 
5313     /**
5314      * Sets the designated column in either the current row or the insert
5315      * row of this <code>CachedRowSetImpl</code> object with the given
5316      * <code>java.io.InputStream</code> object.
5317      * <P>
5318      * This method updates a column value in either the current row or
5319      * the insert row of this rowset, but it does not update the
5320      * database.  If the cursor is on a row in the rowset, the
5321      * method {@link #updateRow} must be called to update the database.
5322      * If the cursor is on the insert row, the method {@link #insertRow}
5323      * must be called, which will insert the new row into both this rowset
5324      * and the database. Both of these methods must be called before the
5325      * cursor moves to another row.
5326      *
5327      * @param columnName a <code>String</code> object that must match the
5328      *        SQL name of a column in this rowset, ignoring case
5329      * @param x the new column value; must be a <code>java.io.InputStream</code>
5330      *          containing <code>BINARY</code>, <code>VARBINARY</code>, or
5331      *          <code>LONGVARBINARY</code> data
5332      * @param length the length of the stream in bytes
5333      * @throws SQLException if (1) the given column name does not match the
5334      *            name of a column in this rowset, (2) the cursor is not on
5335      *            one of this rowset's rows or its insert row, (3) the data
5336      *            in the stream is not binary, or (4) this rowset is
5337      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5338      */
5339     public void updateBinaryStream(String columnName, java.io.InputStream x, int length) throws SQLException {
5340         updateBinaryStream(getColIdxByName(columnName), x, length);
5341     }
5342 
5343     /**
5344      * Sets the designated column in either the current row or the insert
5345      * row of this <code>CachedRowSetImpl</code> object with the given
5346      * <code>java.io.Reader</code> object.
5347      * <P>
5348      * This method updates a column value in either the current row or
5349      * the insert row of this rowset, but it does not update the
5350      * database.  If the cursor is on a row in the rowset, the
5351      * method {@link #updateRow} must be called to update the database.
5352      * If the cursor is on the insert row, the method {@link #insertRow}
5353      * must be called, which will insert the new row into both this rowset
5354      * and the database. Both of these methods must be called before the
5355      * cursor moves to another row.
5356      *
5357      * @param columnName a <code>String</code> object that must match the
5358      *        SQL name of a column in this rowset, ignoring case
5359      * @param reader the new column value; must be a
5360      * <code>java.io.Reader</code> containing <code>BINARY</code>,
5361      * <code>VARBINARY</code>, <code>LONGVARBINARY</code>, <code>CHAR</code>,
5362      * <code>VARCHAR</code>, or <code>LONGVARCHAR</code> data
5363      * @param length the length of the stream in characters
5364      * @throws SQLException if (1) the given column name does not match the
5365      *            name of a column in this rowset, (2) the cursor is not on
5366      *            one of this rowset's rows or its insert row, (3) the data
5367      *            in the stream is not a binary or character type, or (4) this
5368      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5369      */
5370     public void updateCharacterStream(String columnName,
5371     java.io.Reader reader,
5372     int length) throws SQLException {
5373         updateCharacterStream(getColIdxByName(columnName), reader, length);
5374     }
5375 
5376     /**
5377      * Sets the designated column in either the current row or the insert
5378      * row of this <code>CachedRowSetImpl</code> object with the given
5379      * <code>Object</code> value.  The <code>scale</code> parameter
5380      * indicates the number of digits to the right of the decimal point
5381      * and is ignored if the new column value is not a type that will be
5382      *  mapped to an SQL <code>DECIMAL</code> or <code>NUMERIC</code> value.
5383      * <P>
5384      * This method updates a column value in either the current row or
5385      * the insert row of this rowset, but it does not update the
5386      * database.  If the cursor is on a row in the rowset, the
5387      * method {@link #updateRow} must be called to update the database.
5388      * If the cursor is on the insert row, the method {@link #insertRow}
5389      * must be called, which will insert the new row into both this rowset
5390      * and the database. Both of these methods must be called before the
5391      * cursor moves to another row.
5392      *
5393      * @param columnName a <code>String</code> object that must match the
5394      *        SQL name of a column in this rowset, ignoring case
5395      * @param x the new column value
5396      * @param scale the number of digits to the right of the decimal point (for
5397      *              <code>DECIMAL</code> and <code>NUMERIC</code> types only)
5398      * @throws SQLException if (1) the given column name does not match the
5399      *            name of a column in this rowset, (2) the cursor is not on
5400      *            one of this rowset's rows or its insert row, or (3) this
5401      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5402      */
5403     public void updateObject(String columnName, Object x, int scale) throws SQLException {
5404         updateObject(getColIdxByName(columnName), x, scale);
5405     }
5406 
5407     /**
5408      * Sets the designated column in either the current row or the insert
5409      * row of this <code>CachedRowSetImpl</code> object with the given
5410      * <code>Object</code> value.
5411      * <P>
5412      * This method updates a column value in either the current row or
5413      * the insert row of this rowset, but it does not update the
5414      * database.  If the cursor is on a row in the rowset, the
5415      * method {@link #updateRow} must be called to update the database.
5416      * If the cursor is on the insert row, the method {@link #insertRow}
5417      * must be called, which will insert the new row into both this rowset
5418      * and the database. Both of these methods must be called before the
5419      * cursor moves to another row.
5420      *
5421      * @param columnName a <code>String</code> object that must match the
5422      *        SQL name of a column in this rowset, ignoring case
5423      * @param x the new column value
5424      * @throws SQLException if (1) the given column name does not match the
5425      *            name of a column in this rowset, (2) the cursor is not on
5426      *            one of this rowset's rows or its insert row, or (3) this
5427      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5428      */
5429     public void updateObject(String columnName, Object x) throws SQLException {
5430         updateObject(getColIdxByName(columnName), x);
5431     }
5432 
5433     /**
5434      * Inserts the contents of this <code>CachedRowSetImpl</code> object's insert
5435      * row into this rowset immediately following the current row.
5436      * If the current row is the
5437      * position after the last row or before the first row, the new row will
5438      * be inserted at the end of the rowset.  This method also notifies
5439      * listeners registered with this rowset that the row has changed.
5440      * <P>
5441      * The cursor must be on the insert row when this method is called.
5442      *
5443      * @throws SQLException if (1) the cursor is not on the insert row,
5444      *            (2) one or more of the non-nullable columns in the insert
5445      *            row has not been given a value, or (3) this rowset is
5446      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5447      */
5448     public void insertRow() throws SQLException {
5449         int pos;
5450 
5451         if (onInsertRow == false ||
5452             insertRow.isCompleteRow(RowSetMD) == false) {
5453                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.failedins").toString());
5454         }
5455         // Added the setting of parameters that are passed
5456         // to setXXX methods after an empty CRS Object is
5457         // created through RowSetMetaData object
5458         Object [] toInsert = getParams();
5459 
5460         for(int i = 0;i < toInsert.length; i++) {
5461           insertRow.setColumnObject(i+1,toInsert[i]);
5462         }
5463 
5464         Row insRow = new Row(RowSetMD.getColumnCount(),
5465         insertRow.getOrigRow());
5466         insRow.setInserted();
5467         /*
5468          * The new row is inserted into the RowSet
5469          * immediately following the current row.
5470          *
5471          * If we are afterlast then the rows are
5472          * inserted at the end.
5473          */
5474         if (currentRow >= numRows || currentRow < 0) {
5475             pos = numRows;
5476         } else {
5477             pos = currentRow;
5478         }
5479 
5480         rvh.add(pos, insRow);
5481         ++numRows;
5482         // notify the listeners that the row changed.
5483         notifyRowChanged();
5484     }
5485 
5486     /**
5487      * Marks the current row of this <code>CachedRowSetImpl</code> object as
5488      * updated and notifies listeners registered with this rowset that the
5489      * row has changed.
5490      * <P>
5491      * This method  cannot be called when the cursor is on the insert row, and
5492      * it should be called before the cursor moves to another row.  If it is
5493      * called after the cursor moves to another row, this method has no effect,
5494      * and the updates made before the cursor moved will be lost.
5495      *
5496      * @throws SQLException if the cursor is on the insert row or this
5497      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5498      */
5499     public void updateRow() throws SQLException {
5500         // make sure we aren't on the insert row
5501         if (onInsertRow == true) {
5502             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.updateins").toString());
5503         }
5504 
5505         ((Row)getCurrentRow()).setUpdated();
5506 
5507         // notify the listeners that the row changed.
5508         notifyRowChanged();
5509     }
5510 
5511     /**
5512      * Deletes the current row from this <code>CachedRowSetImpl</code> object and
5513      * notifies listeners registered with this rowset that a row has changed.
5514      * This method cannot be called when the cursor is on the insert row.
5515      * <P>
5516      * This method marks the current row as deleted, but it does not delete
5517      * the row from the underlying data source.  The method
5518      * <code>acceptChanges</code> must be called to delete the row in
5519      * the data source.
5520      *
5521      * @throws SQLException if (1) this method is called when the cursor
5522      *            is on the insert row, before the first row, or after the
5523      *            last row or (2) this rowset is
5524      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5525      */
5526     public void deleteRow() throws SQLException {
5527         // make sure the cursor is on a valid row
5528         checkCursor();
5529 
5530         ((Row)getCurrentRow()).setDeleted();
5531         ++numDeleted;
5532 
5533         // notify the listeners that the row changed.
5534         notifyRowChanged();
5535     }
5536 
5537     /**
5538      * Sets the current row with its original value and marks the row as
5539      * not updated, thus undoing any changes made to the row since the
5540      * last call to the methods <code>updateRow</code> or <code>deleteRow</code>.
5541      * This method should be called only when the cursor is on a row in
5542      * this rowset.
5543      *
5544      * @throws SQLException if the cursor is on the insert row, before the
5545      *            first row, or after the last row
5546      */
5547     public void refreshRow() throws SQLException {
5548         // make sure we are on a row
5549         checkCursor();
5550 
5551         // don't want this to happen...
5552         if (onInsertRow == true) {
5553             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
5554         }
5555 
5556         Row currentRow = (Row)getCurrentRow();
5557         // just undo any changes made to this row.
5558         currentRow.clearUpdated();
5559 
5560     }
5561 
5562     /**
5563      * Rolls back any updates made to the current row of this
5564      * <code>CachedRowSetImpl</code> object and notifies listeners that
5565      * a row has changed.  To have an effect, this method
5566      * must be called after an <code>updateXXX</code> method has been
5567      * called and before the method <code>updateRow</code> has been called.
5568      * If no updates have been made or the method <code>updateRow</code>
5569      * has already been called, this method has no effect.
5570      *
5571      * @throws SQLException if the cursor is on the insert row, before the
5572      *            first row, or after the last row
5573      */
5574     public void cancelRowUpdates() throws SQLException {
5575         // make sure we are on a row
5576         checkCursor();
5577 
5578         // don't want this to happen...
5579         if (onInsertRow == true) {
5580             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
5581         }
5582 
5583         Row currentRow = (Row)getCurrentRow();
5584         if (currentRow.getUpdated() == true) {
5585             currentRow.clearUpdated();
5586             notifyRowChanged();
5587         }
5588     }
5589 
5590     /**
5591      * Moves the cursor for this <code>CachedRowSetImpl</code> object
5592      * to the insert row.  The current row in the rowset is remembered
5593      * while the cursor is on the insert row.
5594      * <P>
5595      * The insert row is a special row associated with an updatable
5596      * rowset.  It is essentially a buffer where a new row may
5597      * be constructed by calling the appropriate <code>updateXXX</code>
5598      * methods to assign a value to each column in the row.  A complete
5599      * row must be constructed; that is, every column that is not nullable
5600      * must be assigned a value.  In order for the new row to become part
5601      * of this rowset, the method <code>insertRow</code> must be called
5602      * before the cursor is moved back to the rowset.
5603      * <P>
5604      * Only certain methods may be invoked while the cursor is on the insert
5605      * row; many methods throw an exception if they are called while the
5606      * cursor is there.  In addition to the <code>updateXXX</code>
5607      * and <code>insertRow</code> methods, only the <code>getXXX</code> methods
5608      * may be called when the cursor is on the insert row.  A <code>getXXX</code>
5609      * method should be called on a column only after an <code>updateXXX</code>
5610      * method has been called on that column; otherwise, the value returned is
5611      * undetermined.
5612      *
5613      * @throws SQLException if this <code>CachedRowSetImpl</code> object is
5614      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5615      */
5616     public void moveToInsertRow() throws SQLException {
5617         if (getConcurrency() == ResultSet.CONCUR_READ_ONLY) {
5618             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins").toString());
5619         }
5620         if (insertRow == null) {
5621             if (RowSetMD == null)
5622                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins1").toString());
5623             int numCols = RowSetMD.getColumnCount();
5624             if (numCols > 0) {
5625                 insertRow = new InsertRow(numCols);
5626             } else {
5627                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins2").toString());
5628             }
5629         }
5630         onInsertRow = true;
5631         // %%% setCurrentRow called in BaseRow
5632 
5633         currentRow = cursorPos;
5634         cursorPos = -1;
5635 
5636         insertRow.initInsertRow();
5637     }
5638 
5639     /**
5640      * Moves the cursor for this <code>CachedRowSetImpl</code> object to
5641      * the current row.  The current row is the row the cursor was on
5642      * when the method <code>moveToInsertRow</code> was called.
5643      * <P>
5644      * Calling this method has no effect unless it is called while the
5645      * cursor is on the insert row.
5646      *
5647      * @throws SQLException if an error occurs
5648      */
5649     public void moveToCurrentRow() throws SQLException {
5650         if (onInsertRow == false) {
5651             return;
5652         } else {
5653             cursorPos = currentRow;
5654             onInsertRow = false;
5655         }
5656     }
5657 
5658     /**
5659      * Returns <code>null</code>.
5660      *
5661      * @return <code>null</code>
5662      * @throws SQLException if an error occurs
5663      */
5664     public Statement getStatement() throws SQLException {
5665         return null;
5666     }
5667 
5668     /**
5669      * Retrieves the value of the designated column in this
5670      * <code>CachedRowSetImpl</code> object as an <code>Object</code> in
5671      * the Java programming language, using the given
5672      * <code>java.util.Map</code> object to custom map the value if
5673      * appropriate.
5674      *
5675      * @param columnIndex the first column is <code>1</code>, the second
5676      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5677      *        and equal to or less than the number of columns in this rowset
5678      * @param map a <code>java.util.Map</code> object showing the mapping
5679      *            from SQL type names to classes in the Java programming
5680      *            language
5681      * @return an <code>Object</code> representing the SQL value
5682      * @throws SQLException if the given column index is out of bounds or
5683      *            the cursor is not on one of this rowset's rows or its
5684      *            insert row
5685      */
5686      public Object getObject(int columnIndex,
5687                              java.util.Map<String,Class<?>> map)
5688          throws SQLException
5689      {
5690         Object value;
5691 
5692         // sanity check.
5693         checkIndex(columnIndex);
5694         // make sure the cursor is on a valid row
5695         checkCursor();
5696 
5697         setLastValueNull(false);
5698         value = getCurrentRow().getColumnObject(columnIndex);
5699 
5700         // check for SQL NULL
5701         if (value == null) {
5702             setLastValueNull(true);
5703             return null;
5704         }
5705         if (value instanceof Struct) {
5706             Struct s = (Struct)value;
5707 
5708             // look up the class in the map
5709             Class<?> c = map.get(s.getSQLTypeName());
5710             if (c != null) {
5711                 // create new instance of the class
5712                 SQLData obj = null;
5713                 try {
5714                     ReflectUtil.checkPackageAccess(c);
5715                     @SuppressWarnings("deprecation")
5716                     Object tmp = c.newInstance();
5717                     obj = (SQLData) tmp;
5718                 } catch(Exception ex) {
5719                     throw new SQLException("Unable to Instantiate: ", ex);
5720                 }
5721                 // get the attributes from the struct
5722                 Object attribs[] = s.getAttributes(map);
5723                 // create the SQLInput "stream"
5724                 SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
5725                 // read the values...
5726                 obj.readSQL(sqlInput, s.getSQLTypeName());
5727                 return (Object)obj;
5728             }
5729         }
5730         return value;
5731     }
5732 
5733     /**
5734      * Retrieves the value of the designated column in this
5735      * <code>CachedRowSetImpl</code> object as a <code>Ref</code> object
5736      * in the Java programming language.
5737      *
5738      * @param columnIndex the first column is <code>1</code>, the second
5739      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5740      *        and equal to or less than the number of columns in this rowset
5741      * @return a <code>Ref</code> object representing an SQL<code> REF</code> value
5742      * @throws SQLException if (1) the given column index is out of bounds,
5743      *            (2) the cursor is not on one of this rowset's rows or its
5744      *            insert row, or (3) the designated column does not store an
5745      *            SQL <code>REF</code> value
5746      * @see #getRef(String)
5747      */
5748     public Ref getRef(int columnIndex) throws SQLException {
5749         Ref value;
5750 
5751         // sanity check.
5752         checkIndex(columnIndex);
5753         // make sure the cursor is on a valid row
5754         checkCursor();
5755 
5756         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.REF) {
5757             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5758         }
5759 
5760         setLastValueNull(false);
5761         value = (Ref)(getCurrentRow().getColumnObject(columnIndex));
5762 
5763         // check for SQL NULL
5764         if (value == null) {
5765             setLastValueNull(true);
5766             return null;
5767         }
5768 
5769         return value;
5770     }
5771 
5772     /**
5773      * Retrieves the value of the designated column in this
5774      * <code>CachedRowSetImpl</code> object as a <code>Blob</code> object
5775      * in the Java programming language.
5776      *
5777      * @param columnIndex the first column is <code>1</code>, the second
5778      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5779      *        and equal to or less than the number of columns in this rowset
5780      * @return a <code>Blob</code> object representing an SQL <code>BLOB</code> value
5781      * @throws SQLException if (1) the given column index is out of bounds,
5782      *            (2) the cursor is not on one of this rowset's rows or its
5783      *            insert row, or (3) the designated column does not store an
5784      *            SQL <code>BLOB</code> value
5785      * @see #getBlob(String)
5786      */
5787     public Blob getBlob(int columnIndex) throws SQLException {
5788         Blob value;
5789 
5790         // sanity check.
5791         checkIndex(columnIndex);
5792         // make sure the cursor is on a valid row
5793         checkCursor();
5794 
5795         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.BLOB) {
5796             System.out.println(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.type").toString(), RowSetMD.getColumnType(columnIndex)));
5797             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5798         }
5799 
5800         setLastValueNull(false);
5801         value = (Blob)(getCurrentRow().getColumnObject(columnIndex));
5802 
5803         // check for SQL NULL
5804         if (value == null) {
5805             setLastValueNull(true);
5806             return null;
5807         }
5808 
5809         return value;
5810     }
5811 
5812     /**
5813      * Retrieves the value of the designated column in this
5814      * <code>CachedRowSetImpl</code> object as a <code>Clob</code> object
5815      * in the Java programming language.
5816      *
5817      * @param columnIndex the first column is <code>1</code>, the second
5818      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5819      *        and equal to or less than the number of columns in this rowset
5820      * @return a <code>Clob</code> object representing an SQL <code>CLOB</code> value
5821      * @throws SQLException if (1) the given column index is out of bounds,
5822      *            (2) the cursor is not on one of this rowset's rows or its
5823      *            insert row, or (3) the designated column does not store an
5824      *            SQL <code>CLOB</code> value
5825      * @see #getClob(String)
5826      */
5827     public Clob getClob(int columnIndex) throws SQLException {
5828         Clob value;
5829 
5830         // sanity check.
5831         checkIndex(columnIndex);
5832         // make sure the cursor is on a valid row
5833         checkCursor();
5834 
5835         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.CLOB) {
5836             System.out.println(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.type").toString(), RowSetMD.getColumnType(columnIndex)));
5837             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5838         }
5839 
5840         setLastValueNull(false);
5841         value = (Clob)(getCurrentRow().getColumnObject(columnIndex));
5842 
5843         // check for SQL NULL
5844         if (value == null) {
5845             setLastValueNull(true);
5846             return null;
5847         }
5848 
5849         return value;
5850     }
5851 
5852     /**
5853      * Retrieves the value of the designated column in this
5854      * <code>CachedRowSetImpl</code> object as an <code>Array</code> object
5855      * in the Java programming language.
5856      *
5857      * @param columnIndex the first column is <code>1</code>, the second
5858      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5859      *        and equal to or less than the number of columns in this rowset
5860      * @return an <code>Array</code> object representing an SQL
5861      *         <code>ARRAY</code> value
5862      * @throws SQLException if (1) the given column index is out of bounds,
5863      *            (2) the cursor is not on one of this rowset's rows or its
5864      *            insert row, or (3) the designated column does not store an
5865      *            SQL <code>ARRAY</code> value
5866      * @see #getArray(String)
5867      */
5868     public Array getArray(int columnIndex) throws SQLException {
5869         java.sql.Array value;
5870 
5871         // sanity check.
5872         checkIndex(columnIndex);
5873         // make sure the cursor is on a valid row
5874         checkCursor();
5875 
5876         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.ARRAY) {
5877             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5878         }
5879 
5880         setLastValueNull(false);
5881         value = (java.sql.Array)(getCurrentRow().getColumnObject(columnIndex));
5882 
5883         // check for SQL NULL
5884         if (value == null) {
5885             setLastValueNull(true);
5886             return null;
5887         }
5888 
5889         return value;
5890     }
5891 
5892     /**
5893      * Retrieves the value of the designated column in this
5894      * <code>CachedRowSetImpl</code> object as an <code>Object</code> in
5895      * the Java programming language, using the given
5896      * <code>java.util.Map</code> object to custom map the value if
5897      * appropriate.
5898      *
5899      * @param columnName a <code>String</code> object that must match the
5900      *        SQL name of a column in this rowset, ignoring case
5901      * @param map a <code>java.util.Map</code> object showing the mapping
5902      *        from SQL type names to classes in the Java programming
5903      *        language
5904      * @return an <code>Object</code> representing the SQL value
5905      * @throws SQLException if the given column name is not the name of
5906      *         a column in this rowset or the cursor is not on one of
5907      *         this rowset's rows or its insert row
5908      */
5909     public Object getObject(String columnName,
5910                             java.util.Map<String,Class<?>> map)
5911     throws SQLException {
5912         return getObject(getColIdxByName(columnName), map);
5913     }
5914 
5915     /**
5916      * Retrieves the value of the designated column in this
5917      * <code>CachedRowSetImpl</code> object as a <code>Ref</code> object
5918      * in the Java programming language.
5919      *
5920      * @param colName a <code>String</code> object that must match the
5921      *        SQL name of a column in this rowset, ignoring case
5922      * @return a <code>Ref</code> object representing an SQL<code> REF</code> value
5923      * @throws SQLException  if (1) the given column name is not the name of
5924      *            a column in this rowset, (2) the cursor is not on one of
5925      *            this rowset's rows or its insert row, or (3) the column value
5926      *            is not an SQL <code>REF</code> value
5927      * @see #getRef(int)
5928      */
5929     public Ref getRef(String colName) throws SQLException {
5930         return getRef(getColIdxByName(colName));
5931     }
5932 
5933     /**
5934      * Retrieves the value of the designated column in this
5935      * <code>CachedRowSetImpl</code> object as a <code>Blob</code> object
5936      * in the Java programming language.
5937      *
5938      * @param colName a <code>String</code> object that must match the
5939      *        SQL name of a column in this rowset, ignoring case
5940      * @return a <code>Blob</code> object representing an SQL <code>BLOB</code> value
5941      * @throws SQLException if (1) the given column name is not the name of
5942      *            a column in this rowset, (2) the cursor is not on one of
5943      *            this rowset's rows or its insert row, or (3) the designated
5944      *            column does not store an SQL <code>BLOB</code> value
5945      * @see #getBlob(int)
5946      */
5947     public Blob getBlob(String colName) throws SQLException {
5948         return getBlob(getColIdxByName(colName));
5949     }
5950 
5951     /**
5952      * Retrieves the value of the designated column in this
5953      * <code>CachedRowSetImpl</code> object as a <code>Clob</code> object
5954      * in the Java programming language.
5955      *
5956      * @param colName a <code>String</code> object that must match the
5957      *        SQL name of a column in this rowset, ignoring case
5958      * @return a <code>Clob</code> object representing an SQL
5959      *         <code>CLOB</code> value
5960      * @throws SQLException if (1) the given column name is not the name of
5961      *            a column in this rowset, (2) the cursor is not on one of
5962      *            this rowset's rows or its insert row, or (3) the designated
5963      *            column does not store an SQL <code>CLOB</code> value
5964      * @see #getClob(int)
5965      */
5966     public Clob getClob(String colName) throws SQLException {
5967         return getClob(getColIdxByName(colName));
5968     }
5969 
5970     /**
5971      * Retrieves the value of the designated column in this
5972      * <code>CachedRowSetImpl</code> object as an <code>Array</code> object
5973      * in the Java programming langugage.
5974      *
5975      * @param colName a <code>String</code> object that must match the
5976      *        SQL name of a column in this rowset, ignoring case
5977      * @return an <code>Array</code> object representing an SQL
5978      *         <code>ARRAY</code> value
5979      * @throws SQLException if (1) the given column name is not the name of
5980      *            a column in this rowset, (2) the cursor is not on one of
5981      *            this rowset's rows or its insert row, or (3) the designated
5982      *            column does not store an SQL <code>ARRAY</code> value
5983      * @see #getArray(int)
5984      */
5985     public Array getArray(String colName) throws SQLException {
5986         return getArray(getColIdxByName(colName));
5987     }
5988 
5989     /**
5990      * Retrieves the value of the designated column in the current row
5991      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Date</code>
5992      * object, using the given <code>Calendar</code> object to construct an
5993      * appropriate millisecond value for the date.
5994      *
5995      * @param columnIndex the first column is <code>1</code>, the second
5996      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5997      *        and equal to or less than the number of columns in the rowset
5998      * @param cal the <code>java.util.Calendar</code> object to use in
5999      *            constructing the date
6000      * @return the column value; if the value is SQL <code>NULL</code>,
6001      *         the result is <code>null</code>
6002      * @throws SQLException if (1) the given column name is not the name of
6003      *            a column in this rowset, (2) the cursor is not on one of
6004      *            this rowset's rows or its insert row, or (3) the designated
6005      *            column does not store an SQL <code>DATE</code> or
6006      *            <code>TIMESTAMP</code> value
6007      */
6008     public java.sql.Date getDate(int columnIndex, Calendar cal) throws SQLException {
6009         Object value;
6010 
6011         // sanity check.
6012         checkIndex(columnIndex);
6013         // make sure the cursor is on a valid row
6014         checkCursor();
6015 
6016         setLastValueNull(false);
6017         value = getCurrentRow().getColumnObject(columnIndex);
6018 
6019         // check for SQL NULL
6020         if (value == null) {
6021             setLastValueNull(true);
6022             return null;
6023         }
6024 
6025         value = convertTemporal(value,
6026         RowSetMD.getColumnType(columnIndex),
6027         java.sql.Types.DATE);
6028 
6029         // create a default calendar
6030         Calendar defaultCal = Calendar.getInstance();
6031         // set this Calendar to the time we have
6032         defaultCal.setTime((java.util.Date)value);
6033 
6034         /*
6035          * Now we can pull the pieces of the date out
6036          * of the default calendar and put them into
6037          * the user provided calendar
6038          */
6039         cal.set(Calendar.YEAR, defaultCal.get(Calendar.YEAR));
6040         cal.set(Calendar.MONTH, defaultCal.get(Calendar.MONTH));
6041         cal.set(Calendar.DAY_OF_MONTH, defaultCal.get(Calendar.DAY_OF_MONTH));
6042 
6043         /*
6044          * This looks a little odd but it is correct -
6045          * Calendar.getTime() returns a Date...
6046          */
6047         return new java.sql.Date(cal.getTime().getTime());
6048     }
6049 
6050     /**
6051      * Retrieves the value of the designated column in the current row
6052      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Date</code>
6053      * object, using the given <code>Calendar</code> object to construct an
6054      * appropriate millisecond value for the date.
6055      *
6056      * @param columnName a <code>String</code> object that must match the
6057      *        SQL name of a column in this rowset, ignoring case
6058      * @param cal the <code>java.util.Calendar</code> object to use in
6059      *            constructing the date
6060      * @return the column value; if the value is SQL <code>NULL</code>,
6061      *         the result is <code>null</code>
6062      * @throws SQLException if (1) the given column name is not the name of
6063      *            a column in this rowset, (2) the cursor is not on one of
6064      *            this rowset's rows or its insert row, or (3) the designated
6065      *            column does not store an SQL <code>DATE</code> or
6066      *            <code>TIMESTAMP</code> value
6067      */
6068     public java.sql.Date getDate(String columnName, Calendar cal) throws SQLException {
6069         return getDate(getColIdxByName(columnName), cal);
6070     }
6071 
6072     /**
6073      * Retrieves the value of the designated column in the current row
6074      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Time</code>
6075      * object, using the given <code>Calendar</code> object to construct an
6076      * appropriate millisecond value for the date.
6077      *
6078      * @param columnIndex the first column is <code>1</code>, the second
6079      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6080      *        and equal to or less than the number of columns in the rowset
6081      * @param cal the <code>java.util.Calendar</code> object to use in
6082      *            constructing the date
6083      * @return the column value; if the value is SQL <code>NULL</code>,
6084      *         the result is <code>null</code>
6085      * @throws SQLException if (1) the given column name is not the name of
6086      *            a column in this rowset, (2) the cursor is not on one of
6087      *            this rowset's rows or its insert row, or (3) the designated
6088      *            column does not store an SQL <code>TIME</code> or
6089      *            <code>TIMESTAMP</code> value
6090      */
6091     public java.sql.Time getTime(int columnIndex, Calendar cal) throws SQLException {
6092         Object value;
6093 
6094         // sanity check.
6095         checkIndex(columnIndex);
6096         // make sure the cursor is on a valid row
6097         checkCursor();
6098 
6099         setLastValueNull(false);
6100         value = getCurrentRow().getColumnObject(columnIndex);
6101 
6102         // check for SQL NULL
6103         if (value == null) {
6104             setLastValueNull(true);
6105             return null;
6106         }
6107 
6108         value = convertTemporal(value,
6109         RowSetMD.getColumnType(columnIndex),
6110         java.sql.Types.TIME);
6111 
6112         // create a default calendar
6113         Calendar defaultCal = Calendar.getInstance();
6114         // set the time in the default calendar
6115         defaultCal.setTime((java.util.Date)value);
6116 
6117         /*
6118          * Now we can pull the pieces of the date out
6119          * of the default calendar and put them into
6120          * the user provided calendar
6121          */
6122         cal.set(Calendar.HOUR_OF_DAY, defaultCal.get(Calendar.HOUR_OF_DAY));
6123         cal.set(Calendar.MINUTE, defaultCal.get(Calendar.MINUTE));
6124         cal.set(Calendar.SECOND, defaultCal.get(Calendar.SECOND));
6125 
6126         return new java.sql.Time(cal.getTime().getTime());
6127     }
6128 
6129     /**
6130      * Retrieves the value of the designated column in the current row
6131      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Time</code>
6132      * object, using the given <code>Calendar</code> object to construct an
6133      * appropriate millisecond value for the date.
6134      *
6135      * @param columnName a <code>String</code> object that must match the
6136      *        SQL name of a column in this rowset, ignoring case
6137      * @param cal the <code>java.util.Calendar</code> object to use in
6138      *            constructing the date
6139      * @return the column value; if the value is SQL <code>NULL</code>,
6140      *         the result is <code>null</code>
6141      * @throws SQLException if (1) the given column name is not the name of
6142      *            a column in this rowset, (2) the cursor is not on one of
6143      *            this rowset's rows or its insert row, or (3) the designated
6144      *            column does not store an SQL <code>TIME</code> or
6145      *            <code>TIMESTAMP</code> value
6146      */
6147     public java.sql.Time getTime(String columnName, Calendar cal) throws SQLException {
6148         return getTime(getColIdxByName(columnName), cal);
6149     }
6150 
6151     /**
6152      * Retrieves the value of the designated column in the current row
6153      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Timestamp</code>
6154      * object, using the given <code>Calendar</code> object to construct an
6155      * appropriate millisecond value for the date.
6156      *
6157      * @param columnIndex the first column is <code>1</code>, the second
6158      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6159      *        and equal to or less than the number of columns in the rowset
6160      * @param cal the <code>java.util.Calendar</code> object to use in
6161      *            constructing the date
6162      * @return the column value; if the value is SQL <code>NULL</code>,
6163      *         the result is <code>null</code>
6164      * @throws SQLException if (1) the given column name is not the name of
6165      *            a column in this rowset, (2) the cursor is not on one of
6166      *            this rowset's rows or its insert row, or (3) the designated
6167      *            column does not store an SQL <code>TIME</code> or
6168      *            <code>TIMESTAMP</code> value
6169      */
6170     public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
6171         Object value;
6172 
6173         // sanity check.
6174         checkIndex(columnIndex);
6175         // make sure the cursor is on a valid row
6176         checkCursor();
6177 
6178         setLastValueNull(false);
6179         value = getCurrentRow().getColumnObject(columnIndex);
6180 
6181         // check for SQL NULL
6182         if (value == null) {
6183             setLastValueNull(true);
6184             return null;
6185         }
6186 
6187         value = convertTemporal(value,
6188         RowSetMD.getColumnType(columnIndex),
6189         java.sql.Types.TIMESTAMP);
6190 
6191         // create a default calendar
6192         Calendar defaultCal = Calendar.getInstance();
6193         // set the time in the default calendar
6194         defaultCal.setTime((java.util.Date)value);
6195 
6196         /*
6197          * Now we can pull the pieces of the date out
6198          * of the default calendar and put them into
6199          * the user provided calendar
6200          */
6201         cal.set(Calendar.YEAR, defaultCal.get(Calendar.YEAR));
6202         cal.set(Calendar.MONTH, defaultCal.get(Calendar.MONTH));
6203         cal.set(Calendar.DAY_OF_MONTH, defaultCal.get(Calendar.DAY_OF_MONTH));
6204         cal.set(Calendar.HOUR_OF_DAY, defaultCal.get(Calendar.HOUR_OF_DAY));
6205         cal.set(Calendar.MINUTE, defaultCal.get(Calendar.MINUTE));
6206         cal.set(Calendar.SECOND, defaultCal.get(Calendar.SECOND));
6207 
6208         return new java.sql.Timestamp(cal.getTime().getTime());
6209     }
6210 
6211     /**
6212      * Retrieves the value of the designated column in the current row
6213      * of this <code>CachedRowSetImpl</code> object as a
6214      * <code>java.sql.Timestamp</code> object, using the given
6215      * <code>Calendar</code> object to construct an appropriate
6216      * millisecond value for the date.
6217      *
6218      * @param columnName a <code>String</code> object that must match the
6219      *        SQL name of a column in this rowset, ignoring case
6220      * @param cal the <code>java.util.Calendar</code> object to use in
6221      *            constructing the date
6222      * @return the column value; if the value is SQL <code>NULL</code>,
6223      *         the result is <code>null</code>
6224      * @throws SQLException if (1) the given column name is not the name of
6225      *            a column in this rowset, (2) the cursor is not on one of
6226      *            this rowset's rows or its insert row, or (3) the designated
6227      *            column does not store an SQL <code>DATE</code>,
6228      *            <code>TIME</code>, or <code>TIMESTAMP</code> value
6229      */
6230     public java.sql.Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException {
6231         return getTimestamp(getColIdxByName(columnName), cal);
6232     }
6233 
6234     /*
6235      * RowSetInternal Interface
6236      */
6237 
6238     /**
6239      * Retrieves the <code>Connection</code> object passed to this
6240      * <code>CachedRowSetImpl</code> object.  This connection may be
6241      * used to populate this rowset with data or to write data back
6242      * to its underlying data source.
6243      *
6244      * @return the <code>Connection</code> object passed to this rowset;
6245      *         may be <code>null</code> if there is no connection
6246      * @throws SQLException if an error occurs
6247      */
6248     public Connection getConnection() throws SQLException{
6249         return conn;
6250     }
6251 
6252     /**
6253      * Sets the metadata for this <code>CachedRowSetImpl</code> object
6254      * with the given <code>RowSetMetaData</code> object.
6255      *
6256      * @param md a <code>RowSetMetaData</code> object instance containing
6257      *            metadata about the columsn in the rowset
6258      * @throws SQLException if invalid meta data is supplied to the
6259      *            rowset
6260      */
6261     public void setMetaData(RowSetMetaData md) throws SQLException {
6262         RowSetMD =(RowSetMetaDataImpl) md;
6263     }
6264 
6265     /**
6266      * Returns a result set containing the original value of the rowset. The
6267      * original value is the state of the <code>CachedRowSetImpl</code> after the
6268      * last population or synchronization (whichever occurred most recently) with
6269      * the data source.
6270      * <p>
6271      * The cursor is positioned before the first row in the result set.
6272      * Only rows contained in the result set returned by <code>getOriginal()</code>
6273      * are said to have an original value.
6274      *
6275      * @return the original result set of the rowset
6276      * @throws SQLException if an error occurs produce the
6277      *           <code>ResultSet</code> object
6278      */
6279     public ResultSet getOriginal() throws SQLException {
6280         CachedRowSetImpl crs = new CachedRowSetImpl();
6281         crs.RowSetMD = RowSetMD;
6282         crs.numRows = numRows;
6283         crs.cursorPos = 0;
6284 
6285         // make sure we don't get someone playing with these
6286         // %%% is this now necessary ???
6287         //crs.setReader(null);
6288         //crs.setWriter(null);
6289         int colCount = RowSetMD.getColumnCount();
6290         Row orig;
6291 
6292         for (Iterator<?> i = rvh.iterator(); i.hasNext();) {
6293             orig = new Row(colCount, ((Row)i.next()).getOrigRow());
6294             crs.rvh.add(orig);
6295         }
6296         return (ResultSet)crs;
6297     }
6298 
6299     /**
6300      * Returns a result set containing the original value of the current
6301      * row only.
6302      * The original value is the state of the <code>CachedRowSetImpl</code> after
6303      * the last population or synchronization (whichever occurred most recently)
6304      * with the data source.
6305      *
6306      * @return the original result set of the row
6307      * @throws SQLException if there is no current row
6308      * @see #setOriginalRow
6309      */
6310     public ResultSet getOriginalRow() throws SQLException {
6311         CachedRowSetImpl crs = new CachedRowSetImpl();
6312         crs.RowSetMD = RowSetMD;
6313         crs.numRows = 1;
6314         crs.cursorPos = 0;
6315         crs.setTypeMap(this.getTypeMap());
6316 
6317         // make sure we don't get someone playing with these
6318         // %%% is this now necessary ???
6319         //crs.setReader(null);
6320         //crs.setWriter(null);
6321 
6322         Row orig = new Row(RowSetMD.getColumnCount(),
6323         getCurrentRow().getOrigRow());
6324 
6325         crs.rvh.add(orig);
6326 
6327         return (ResultSet)crs;
6328 
6329     }
6330 
6331     /**
6332      * Marks the current row in this rowset as being an original row.
6333      *
6334      * @throws SQLException if there is no current row
6335      * @see #getOriginalRow
6336      */
6337     public void setOriginalRow() throws SQLException {
6338         if (onInsertRow == true) {
6339             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
6340         }
6341 
6342         Row row = (Row)getCurrentRow();
6343         makeRowOriginal(row);
6344 
6345         // this can happen if deleted rows are being shown
6346         if (row.getDeleted() == true) {
6347             removeCurrentRow();
6348         }
6349     }
6350 
6351     /**
6352      * Makes the given row of this rowset the original row by clearing any
6353      * settings that mark the row as having been inserted, deleted, or updated.
6354      * This method is called internally by the methods
6355      * <code>setOriginalRow</code>
6356      * and <code>setOriginal</code>.
6357      *
6358      * @param row the row to be made the original row
6359      */
6360     private void makeRowOriginal(Row row) {
6361         if (row.getInserted() == true) {
6362             row.clearInserted();
6363         }
6364 
6365         if (row.getUpdated() == true) {
6366             row.moveCurrentToOrig();
6367         }
6368     }
6369 
6370     /**
6371      * Marks all rows in this rowset as being original rows. Any updates
6372      * made to the rows become the original values for the rowset.
6373      * Calls to the method <code>setOriginal</code> connot be reversed.
6374      *
6375      * @throws SQLException if an error occurs
6376      */
6377     public void setOriginal() throws SQLException {
6378         for (Iterator<?> i = rvh.iterator(); i.hasNext();) {
6379             Row row = (Row)i.next();
6380             makeRowOriginal(row);
6381             // remove deleted rows from the collection.
6382             if (row.getDeleted() == true) {
6383                 i.remove();
6384                 --numRows;
6385             }
6386         }
6387         numDeleted = 0;
6388 
6389         // notify any listeners that the rowset has changed
6390         notifyRowSetChanged();
6391     }
6392 
6393     /**
6394      * Returns an identifier for the object (table) that was used to create this
6395      * rowset.
6396      *
6397      * @return a <code>String</code> object that identifies the table from
6398      *         which this <code>CachedRowSetImpl</code> object was derived
6399      * @throws SQLException if an error occurs
6400      */
6401     public String getTableName() throws SQLException {
6402         return tableName;
6403     }
6404 
6405     /**
6406      * Sets the identifier for the table from which this rowset was derived
6407      * to the given table name.
6408      *
6409      * @param tabName a <code>String</code> object that identifies the
6410      *          table from which this <code>CachedRowSetImpl</code> object
6411      *          was derived
6412      * @throws SQLException if an error occurs
6413      */
6414     public void setTableName(String tabName) throws SQLException {
6415         if (tabName == null)
6416             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.tablename").toString());
6417         else
6418             tableName = tabName;
6419     }
6420 
6421     /**
6422      * Returns the columns that make a key to uniquely identify a
6423      * row in this <code>CachedRowSetImpl</code> object.
6424      *
6425      * @return an array of column numbers that constitutes a primary
6426      *           key for this rowset. This array should be empty
6427      *           if no column is representitive of a primary key
6428      * @throws SQLException if the rowset is empty or no columns
6429      *           are designated as primary keys
6430      * @see #setKeyColumns
6431      */
6432     public int[] getKeyColumns() throws SQLException {
6433         int[]keyColumns  = this.keyCols;
6434         return (keyColumns == null) ? null : Arrays.copyOf(keyColumns, keyColumns.length);
6435     }
6436 
6437 
6438     /**
6439      * Sets this <code>CachedRowSetImpl</code> object's
6440      * <code>keyCols</code> field with the given array of column
6441      * numbers, which forms a key for uniquely identifying a row
6442      * in this rowset.
6443      *
6444      * @param keys an array of <code>int</code> indicating the
6445      *        columns that form a primary key for this
6446      *        <code>CachedRowSetImpl</code> object; every
6447      *        element in the array must be greater than
6448      *        <code>0</code> and less than or equal to the number
6449      *        of columns in this rowset
6450      * @throws SQLException if any of the numbers in the
6451      *            given array is not valid for this rowset
6452      * @see #getKeyColumns
6453      */
6454     public void setKeyColumns(int [] keys) throws SQLException {
6455         int numCols = 0;
6456         if (RowSetMD != null) {
6457             numCols = RowSetMD.getColumnCount();
6458             if (keys.length > numCols)
6459                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.keycols").toString());
6460         }
6461         keyCols = new int[keys.length];
6462         for (int i = 0; i < keys.length; i++) {
6463             if (RowSetMD != null && (keys[i] <= 0 ||
6464             keys[i] > numCols)) {
6465                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcol").toString() +
6466                 keys[i]);
6467             }
6468             keyCols[i] = keys[i];
6469         }
6470     }
6471 
6472     /**
6473      * Sets the designated column in either the current row or the insert
6474      * row of this <code>CachedRowSetImpl</code> object with the given
6475      * <code>Ref</code> value.
6476      *
6477      * This method updates a column value in either the current row or
6478      * the insert row of this rowset, but it does not update the
6479      * database.  If the cursor is on a row in the rowset, the
6480      * method {@link #updateRow} must be called to update the database.
6481      * If the cursor is on the insert row, the method {@link #insertRow}
6482      * must be called, which will insert the new row into both this rowset
6483      * and the database. Both of these methods must be called before the
6484      * cursor moves to another row.
6485      *
6486      * @param columnIndex the first column is <code>1</code>, the second
6487      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6488      *        and equal to or less than the number of columns in this rowset
6489      * @param ref the new column <code>java.sql.Ref</code> value
6490      * @throws SQLException if (1) the given column index is out of bounds,
6491      *        (2) the cursor is not on one of this rowset's rows or its
6492      *        insert row, or (3) this rowset is
6493      *        <code>ResultSet.CONCUR_READ_ONLY</code>
6494      */
6495     public void updateRef(int columnIndex, java.sql.Ref ref) throws SQLException {
6496         // sanity check.
6497         checkIndex(columnIndex);
6498         // make sure the cursor is on a valid row
6499         checkCursor();
6500 
6501         // SerialClob will help in getting the byte array and storing it.
6502         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6503         // or through RowSetMetaData.locatorsUpdatorCopy()
6504         getCurrentRow().setColumnObject(columnIndex, new SerialRef(ref));
6505     }
6506 
6507     /**
6508      * Sets the designated column in either the current row or the insert
6509      * row of this <code>CachedRowSetImpl</code> object with the given
6510      * <code>double</code> value.
6511      *
6512      * This method updates a column value in either the current row or
6513      * the insert row of this rowset, but it does not update the
6514      * database.  If the cursor is on a row in the rowset, the
6515      * method {@link #updateRow} must be called to update the database.
6516      * If the cursor is on the insert row, the method {@link #insertRow}
6517      * must be called, which will insert the new row into both this rowset
6518      * and the database. Both of these methods must be called before the
6519      * cursor moves to another row.
6520      *
6521      * @param columnName a <code>String</code> object that must match the
6522      *        SQL name of a column in this rowset, ignoring case
6523      * @param ref the new column <code>java.sql.Ref</code> value
6524      * @throws SQLException if (1) the given column name does not match the
6525      *        name of a column in this rowset, (2) the cursor is not on
6526      *        one of this rowset's rows or its insert row, or (3) this
6527      *        rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6528      */
6529     public void updateRef(String columnName, java.sql.Ref ref) throws SQLException {
6530         updateRef(getColIdxByName(columnName), ref);
6531     }
6532 
6533     /**
6534      * Sets the designated column in either the current row or the insert
6535      * row of this <code>CachedRowSetImpl</code> object with the given
6536      * <code>double</code> value.
6537      *
6538      * This method updates a column value in either the current row or
6539      * the insert row of this rowset, but it does not update the
6540      * database.  If the cursor is on a row in the rowset, the
6541      * method {@link #updateRow} must be called to update the database.
6542      * If the cursor is on the insert row, the method {@link #insertRow}
6543      * must be called, which will insert the new row into both this rowset
6544      * and the database. Both of these methods must be called before the
6545      * cursor moves to another row.
6546      *
6547      * @param columnIndex the first column is <code>1</code>, the second
6548      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6549      *        and equal to or less than the number of columns in this rowset
6550      * @param c the new column <code>Clob</code> value
6551      * @throws SQLException if (1) the given column index is out of bounds,
6552      *        (2) the cursor is not on one of this rowset's rows or its
6553      *        insert row, or (3) this rowset is
6554      *        <code>ResultSet.CONCUR_READ_ONLY</code>
6555      */
6556     public void updateClob(int columnIndex, Clob c) throws SQLException {
6557         // sanity check.
6558         checkIndex(columnIndex);
6559         // make sure the cursor is on a valid row
6560         checkCursor();
6561 
6562         // SerialClob will help in getting the byte array and storing it.
6563         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6564         // or through RowSetMetaData.locatorsUpdatorCopy()
6565 
6566         if(dbmslocatorsUpdateCopy){
6567            getCurrentRow().setColumnObject(columnIndex, new SerialClob(c));
6568         }
6569         else{
6570            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.opnotsupp").toString());
6571         }
6572     }
6573 
6574     /**
6575      * Sets the designated column in either the current row or the insert
6576      * row of this <code>CachedRowSetImpl</code> object with the given
6577      * <code>double</code> value.
6578      *
6579      * This method updates a column value in either the current row or
6580      * the insert row of this rowset, but it does not update the
6581      * database.  If the cursor is on a row in the rowset, the
6582      * method {@link #updateRow} must be called to update the database.
6583      * If the cursor is on the insert row, the method {@link #insertRow}
6584      * must be called, which will insert the new row into both this rowset
6585      * and the database. Both of these methods must be called before the
6586      * cursor moves to another row.
6587      *
6588      * @param columnName a <code>String</code> object that must match the
6589      *        SQL name of a column in this rowset, ignoring case
6590      * @param c the new column <code>Clob</code> value
6591      * @throws SQLException if (1) the given column name does not match the
6592      *            name of a column in this rowset, (2) the cursor is not on
6593      *            one of this rowset's rows or its insert row, or (3) this
6594      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6595      */
6596     public void updateClob(String columnName, Clob c) throws SQLException {
6597         updateClob(getColIdxByName(columnName), c);
6598     }
6599 
6600     /**
6601      * Sets the designated column in either the current row or the insert
6602      * row of this <code>CachedRowSetImpl</code> object with the given
6603      * <code>java.sql.Blob</code> value.
6604      *
6605      * This method updates a column value in either the current row or
6606      * the insert row of this rowset, but it does not update the
6607      * database.  If the cursor is on a row in the rowset, the
6608      * method {@link #updateRow} must be called to update the database.
6609      * If the cursor is on the insert row, the method {@link #insertRow}
6610      * must be called, which will insert the new row into both this rowset
6611      * and the database. Both of these methods must be called before the
6612      * cursor moves to another row.
6613      *
6614      * @param columnIndex the first column is <code>1</code>, the second
6615      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6616      *        and equal to or less than the number of columns in this rowset
6617      * @param b the new column <code>Blob</code> value
6618      * @throws SQLException if (1) the given column index is out of bounds,
6619      *            (2) the cursor is not on one of this rowset's rows or its
6620      *            insert row, or (3) this rowset is
6621      *            <code>ResultSet.CONCUR_READ_ONLY</code>
6622      */
6623     public void updateBlob(int columnIndex, Blob b) throws SQLException {
6624         // sanity check.
6625         checkIndex(columnIndex);
6626         // make sure the cursor is on a valid row
6627         checkCursor();
6628 
6629         // SerialBlob will help in getting the byte array and storing it.
6630         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6631         // or through RowSetMetaData.locatorsUpdatorCopy()
6632 
6633         if(dbmslocatorsUpdateCopy){
6634            getCurrentRow().setColumnObject(columnIndex, new SerialBlob(b));
6635         }
6636         else{
6637            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.opnotsupp").toString());
6638         }
6639     }
6640 
6641     /**
6642      * Sets the designated column in either the current row or the insert
6643      * row of this <code>CachedRowSetImpl</code> object with the given
6644      * <code>java.sql.Blob </code> value.
6645      *
6646      * This method updates a column value in either the current row or
6647      * the insert row of this rowset, but it does not update the
6648      * database.  If the cursor is on a row in the rowset, the
6649      * method {@link #updateRow} must be called to update the database.
6650      * If the cursor is on the insert row, the method {@link #insertRow}
6651      * must be called, which will insert the new row into both this rowset
6652      * and the database. Both of these methods must be called before the
6653      * cursor moves to another row.
6654      *
6655      * @param columnName a <code>String</code> object that must match the
6656      *        SQL name of a column in this rowset, ignoring case
6657      * @param b the new column <code>Blob</code> value
6658      * @throws SQLException if (1) the given column name does not match the
6659      *            name of a column in this rowset, (2) the cursor is not on
6660      *            one of this rowset's rows or its insert row, or (3) this
6661      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6662      */
6663     public void updateBlob(String columnName, Blob b) throws SQLException {
6664         updateBlob(getColIdxByName(columnName), b);
6665     }
6666 
6667     /**
6668      * Sets the designated column in either the current row or the insert
6669      * row of this <code>CachedRowSetImpl</code> object with the given
6670      * <code>java.sql.Array</code> values.
6671      *
6672      * This method updates a column value in either the current row or
6673      * the insert row of this rowset, but it does not update the
6674      * database.  If the cursor is on a row in the rowset, the
6675      * method {@link #updateRow} must be called to update the database.
6676      * If the cursor is on the insert row, the method {@link #insertRow}
6677      * must be called, which will insert the new row into both this rowset
6678      * and the database. Both of these methods must be called before the
6679      * cursor moves to another row.
6680      *
6681      * @param columnIndex the first column is <code>1</code>, the second
6682      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6683      *        and equal to or less than the number of columns in this rowset
6684      * @param a the new column <code>Array</code> value
6685      * @throws SQLException if (1) the given column index is out of bounds,
6686      *            (2) the cursor is not on one of this rowset's rows or its
6687      *            insert row, or (3) this rowset is
6688      *            <code>ResultSet.CONCUR_READ_ONLY</code>
6689      */
6690     public void updateArray(int columnIndex, Array a) throws SQLException {
6691         // sanity check.
6692         checkIndex(columnIndex);
6693         // make sure the cursor is on a valid row
6694         checkCursor();
6695 
6696         // SerialArray will help in getting the byte array and storing it.
6697         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6698         // or through RowSetMetaData.locatorsUpdatorCopy()
6699         getCurrentRow().setColumnObject(columnIndex, new SerialArray(a));
6700     }
6701 
6702     /**
6703      * Sets the designated column in either the current row or the insert
6704      * row of this <code>CachedRowSetImpl</code> object with the given
6705      * <code>java.sql.Array</code> value.
6706      *
6707      * This method updates a column value in either the current row or
6708      * the insert row of this rowset, but it does not update the
6709      * database.  If the cursor is on a row in the rowset, the
6710      * method {@link #updateRow} must be called to update the database.
6711      * If the cursor is on the insert row, the method {@link #insertRow}
6712      * must be called, which will insert the new row into both this rowset
6713      * and the database. Both of these methods must be called before the
6714      * cursor moves to another row.
6715      *
6716      * @param columnName a <code>String</code> object that must match the
6717      *        SQL name of a column in this rowset, ignoring case
6718      * @param a the new column <code>Array</code> value
6719      * @throws SQLException if (1) the given column name does not match the
6720      *            name of a column in this rowset, (2) the cursor is not on
6721      *            one of this rowset's rows or its insert row, or (3) this
6722      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6723      */
6724     public void updateArray(String columnName, Array a) throws SQLException {
6725         updateArray(getColIdxByName(columnName), a);
6726     }
6727 
6728 
6729     /**
6730      * Retrieves the value of the designated column in this
6731      * <code>CachedRowSetImpl</code> object as a <code>java.net.URL</code> object
6732      * in the Java programming language.
6733      *
6734      * @return a java.net.URL object containing the resource reference described by
6735      * the URL
6736      * @throws SQLException if (1) the given column index is out of bounds,
6737      * (2) the cursor is not on one of this rowset's rows or its
6738      * insert row, or (3) the designated column does not store an
6739      * SQL <code>DATALINK</code> value.
6740      * @see #getURL(String)
6741      */
6742     public java.net.URL getURL(int columnIndex) throws SQLException {
6743         //throw new SQLException("Operation not supported");
6744 
6745         java.net.URL value;
6746 
6747         // sanity check.
6748         checkIndex(columnIndex);
6749         // make sure the cursor is on a valid row
6750         checkCursor();
6751 
6752         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.DATALINK) {
6753             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
6754         }
6755 
6756         setLastValueNull(false);
6757         value = (java.net.URL)(getCurrentRow().getColumnObject(columnIndex));
6758 
6759         // check for SQL NULL
6760         if (value == null) {
6761             setLastValueNull(true);
6762             return null;
6763         }
6764 
6765         return value;
6766     }
6767 
6768     /**
6769      * Retrieves the value of the designated column in this
6770      * <code>CachedRowSetImpl</code> object as a <code>java.net.URL</code> object
6771      * in the Java programming language.
6772      *
6773      * @return a java.net.URL object containing the resource reference described by
6774      * the URL
6775      * @throws SQLException if (1) the given column name not the name of a column
6776      * in this rowset, or
6777      * (2) the cursor is not on one of this rowset's rows or its
6778      * insert row, or (3) the designated column does not store an
6779      * SQL <code>DATALINK</code> value.
6780      * @see #getURL(int)
6781      */
6782     public java.net.URL getURL(String columnName) throws SQLException {
6783         return getURL(getColIdxByName(columnName));
6784 
6785     }
6786 
6787     /**
6788      * The first warning reported by calls on this <code>CachedRowSetImpl</code>
6789      * object is returned. Subsequent <code>CachedRowSetImpl</code> warnings will
6790      * be chained to this <code>SQLWarning</code>. All <code>RowSetWarnings</code>
6791      * warnings are generated in the disconnected environment and remain a
6792      * seperate warning chain to that provided by the <code>getWarnings</code>
6793      * method.
6794      *
6795      * <P>The warning chain is automatically cleared each time a new
6796      * row is read.
6797      *
6798      * <P><B>Note:</B> This warning chain only covers warnings caused
6799      * by <code>CachedRowSet</code> (and their child interface)
6800      * methods. All <code>SQLWarnings</code> can be obtained using the
6801      * <code>getWarnings</code> method which tracks warnings generated
6802      * by the underlying JDBC driver.
6803      * @return the first SQLWarning or null
6804      *
6805      */
6806     public RowSetWarning getRowSetWarnings() {
6807         try {
6808             notifyCursorMoved();
6809         } catch (SQLException e) {} // mask exception
6810         return rowsetWarning;
6811     }
6812 
6813 
6814     /**
6815      * The function tries to isolate the tablename when only setCommand
6816      * is set and not setTablename is called provided there is only one table
6817      * name in the query else just leaves the setting of table name as such.
6818      * If setTablename is set later it will over ride this table name
6819      * value so retrieved.
6820      *
6821      * @return the tablename if only one table in query else return ""
6822      */
6823     private String buildTableName(String command) throws SQLException {
6824 
6825         // If we have a query from one table,
6826         // we set the table name implicitly
6827         // else user has to explicitly set the table name.
6828 
6829         int indexFrom, indexComma;
6830         String strTablename ="";
6831         command = command.trim();
6832 
6833         // Query can be a select, insert or  update
6834 
6835         if(command.toLowerCase().startsWith("select")) {
6836             // look for "from" keyword, after that look for a
6837             // comma after from. If comma is there don't set
6838             // table name else isolate table name.
6839 
6840             indexFrom = command.toLowerCase().indexOf("from");
6841             indexComma = command.indexOf(',', indexFrom);
6842 
6843             if(indexComma == -1) {
6844                 // implies only one table
6845                 strTablename = (command.substring(indexFrom+"from".length(),command.length())).trim();
6846 
6847                 String tabName = strTablename;
6848 
6849                 int idxWhere = tabName.toLowerCase().indexOf("where");
6850 
6851                 /**
6852                   * Adding the addtional check for conditions following the table name.
6853                   * If a condition is found truncate it.
6854                   **/
6855 
6856                 if(idxWhere != -1)
6857                 {
6858                    tabName = tabName.substring(0,idxWhere).trim();
6859                 }
6860 
6861                 strTablename = tabName;
6862 
6863             } else {
6864                 //strTablename="";
6865             }
6866 
6867         } else if(command.toLowerCase().startsWith("insert")) {
6868             //strTablename="";
6869         } else if(command.toLowerCase().startsWith("update")) {
6870             //strTablename="";
6871         }
6872         return strTablename;
6873     }
6874 
6875     /**
6876      * Commits all changes performed by the <code>acceptChanges()</code>
6877      * methods
6878      *
6879      * @see java.sql.Connection#commit
6880      */
6881     public void commit() throws SQLException {
6882         conn.commit();
6883     }
6884 
6885     /**
6886      * Rolls back all changes performed by the <code>acceptChanges()</code>
6887      * methods
6888      *
6889      * @see java.sql.Connection#rollback
6890      */
6891     public void rollback() throws SQLException {
6892         conn.rollback();
6893     }
6894 
6895     /**
6896      * Rolls back all changes performed by the <code>acceptChanges()</code>
6897      * to the last <code>Savepoint</code> transaction marker.
6898      *
6899      * @see java.sql.Connection#rollback(Savepoint)
6900      */
6901     public void rollback(Savepoint s) throws SQLException {
6902         conn.rollback(s);
6903     }
6904 
6905     /**
6906      * Unsets the designated parameter to the given int array.
6907      * This was set using <code>setMatchColumn</code>
6908      * as the column which will form the basis of the join.
6909      * <P>
6910      * The parameter value unset by this method should be same
6911      * as was set.
6912      *
6913      * @param columnIdxes the index into this rowset
6914      *        object's internal representation of parameter values
6915      * @throws SQLException if an error occurs or the
6916      *  parameter index is out of bounds or if the columnIdx is
6917      *  not the same as set using <code>setMatchColumn(int [])</code>
6918      */
6919     public void unsetMatchColumn(int[] columnIdxes) throws SQLException {
6920 
6921          int i_val;
6922          for( int j= 0 ;j < columnIdxes.length; j++) {
6923             i_val = (Integer.parseInt(iMatchColumns.get(j).toString()));
6924             if(columnIdxes[j] != i_val) {
6925                throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols").toString());
6926             }
6927          }
6928 
6929          for( int i = 0;i < columnIdxes.length ;i++) {
6930             iMatchColumns.set(i, -1);
6931          }
6932     }
6933 
6934    /**
6935      * Unsets the designated parameter to the given String array.
6936      * This was set using <code>setMatchColumn</code>
6937      * as the column which will form the basis of the join.
6938      * <P>
6939      * The parameter value unset by this method should be same
6940      * as was set.
6941      *
6942      * @param columnIdxes the index into this rowset
6943      *        object's internal representation of parameter values
6944      * @throws SQLException if an error occurs or the
6945      *  parameter index is out of bounds or if the columnName is
6946      *  not the same as set using <code>setMatchColumn(String [])</code>
6947      */
6948     public void unsetMatchColumn(String[] columnIdxes) throws SQLException {
6949 
6950         for(int j = 0 ;j < columnIdxes.length; j++) {
6951            if( !columnIdxes[j].equals(strMatchColumns.get(j)) ){
6952               throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols").toString());
6953            }
6954         }
6955 
6956         for(int i = 0 ; i < columnIdxes.length; i++) {
6957            strMatchColumns.set(i,null);
6958         }
6959     }
6960 
6961     /**
6962      * Retrieves the column name as <code>String</code> array
6963      * that was set using <code>setMatchColumn(String [])</code>
6964      * for this rowset.
6965      *
6966      * @return a <code>String</code> array object that contains the column names
6967      *         for the rowset which has this the match columns
6968      *
6969      * @throws SQLException if an error occurs or column name is not set
6970      */
6971     public String[] getMatchColumnNames() throws SQLException {
6972 
6973         String []str_temp = new String[strMatchColumns.size()];
6974 
6975         if( strMatchColumns.get(0) == null) {
6976            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.setmatchcols").toString());
6977         }
6978 
6979         strMatchColumns.copyInto(str_temp);
6980         return str_temp;
6981     }
6982 
6983     /**
6984      * Retrieves the column id as <code>int</code> array that was set using
6985      * <code>setMatchColumn(int [])</code> for this rowset.
6986      *
6987      * @return a <code>int</code> array object that contains the column ids
6988      *         for the rowset which has this as the match columns.
6989      *
6990      * @throws SQLException if an error occurs or column index is not set
6991      */
6992     public int[] getMatchColumnIndexes() throws SQLException {
6993 
6994         Integer []int_temp = new Integer[iMatchColumns.size()];
6995         int [] i_temp = new int[iMatchColumns.size()];
6996         int i_val;
6997 
6998         i_val = iMatchColumns.get(0);
6999 
7000         if( i_val == -1 ) {
7001            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.setmatchcols").toString());
7002         }
7003 
7004 
7005         iMatchColumns.copyInto(int_temp);
7006 
7007         for(int i = 0; i < int_temp.length; i++) {
7008            i_temp[i] = (int_temp[i]).intValue();
7009         }
7010 
7011         return i_temp;
7012     }
7013 
7014     /**
7015      * Sets the designated parameter to the given int array.
7016      * This forms the basis of the join for the
7017      * <code>JoinRowSet</code> as the column which will form the basis of the
7018      * join.
7019      * <P>
7020      * The parameter value set by this method is stored internally and
7021      * will be supplied as the appropriate parameter in this rowset's
7022      * command when the method <code>getMatchColumnIndexes</code> is called.
7023      *
7024      * @param columnIdxes the indexes into this rowset
7025      *        object's internal representation of parameter values; the
7026      *        first parameter is 0, the second is 1, and so on; must be
7027      *        <code>0</code> or greater
7028      * @throws SQLException if an error occurs or the
7029      *                         parameter index is out of bounds
7030      */
7031     public void setMatchColumn(int[] columnIdxes) throws SQLException {
7032 
7033         for(int j = 0 ; j < columnIdxes.length; j++) {
7034            if( columnIdxes[j] < 0 ) {
7035               throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols1").toString());
7036            }
7037         }
7038         for(int i = 0 ;i < columnIdxes.length; i++) {
7039            iMatchColumns.add(i,columnIdxes[i]);
7040         }
7041     }
7042 
7043     /**
7044      * Sets the designated parameter to the given String array.
7045      *  This forms the basis of the join for the
7046      * <code>JoinRowSet</code> as the column which will form the basis of the
7047      * join.
7048      * <P>
7049      * The parameter value set by this method is stored internally and
7050      * will be supplied as the appropriate parameter in this rowset's
7051      * command when the method <code>getMatchColumn</code> is called.
7052      *
7053      * @param columnNames the name of the column into this rowset
7054      *        object's internal representation of parameter values
7055      * @throws SQLException if an error occurs or the
7056      *  parameter index is out of bounds
7057      */
7058     public void setMatchColumn(String[] columnNames) throws SQLException {
7059 
7060         for(int j = 0; j < columnNames.length; j++) {
7061            if( columnNames[j] == null || columnNames[j].equals("")) {
7062               throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols2").toString());
7063            }
7064         }
7065         for( int i = 0; i < columnNames.length; i++) {
7066            strMatchColumns.add(i,columnNames[i]);
7067         }
7068     }
7069 
7070 
7071     /**
7072      * Sets the designated parameter to the given <code>int</code>
7073      * object.  This forms the basis of the join for the
7074      * <code>JoinRowSet</code> as the column which will form the basis of the
7075      * join.
7076      * <P>
7077      * The parameter value set by this method is stored internally and
7078      * will be supplied as the appropriate parameter in this rowset's
7079      * command when the method <code>getMatchColumn</code> is called.
7080      *
7081      * @param columnIdx the index into this rowset
7082      *        object's internal representation of parameter values; the
7083      *        first parameter is 0, the second is 1, and so on; must be
7084      *        <code>0</code> or greater
7085      * @throws SQLException if an error occurs or the
7086      *                         parameter index is out of bounds
7087      */
7088     public void setMatchColumn(int columnIdx) throws SQLException {
7089         // validate, if col is ok to be set
7090         if(columnIdx < 0) {
7091             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols1").toString());
7092         } else {
7093             // set iMatchColumn
7094             iMatchColumns.set(0, columnIdx);
7095             //strMatchColumn = null;
7096         }
7097     }
7098 
7099     /**
7100      * Sets the designated parameter to the given <code>String</code>
7101      * object.  This forms the basis of the join for the
7102      * <code>JoinRowSet</code> as the column which will form the basis of the
7103      * join.
7104      * <P>
7105      * The parameter value set by this method is stored internally and
7106      * will be supplied as the appropriate parameter in this rowset's
7107      * command when the method <code>getMatchColumn</code> is called.
7108      *
7109      * @param columnName the name of the column into this rowset
7110      *        object's internal representation of parameter values
7111      * @throws SQLException if an error occurs or the
7112      *  parameter index is out of bounds
7113      */
7114     public void setMatchColumn(String columnName) throws SQLException {
7115         // validate, if col is ok to be set
7116         if(columnName == null || (columnName= columnName.trim()).equals("") ) {
7117             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols2").toString());
7118         } else {
7119             // set strMatchColumn
7120             strMatchColumns.set(0, columnName);
7121             //iMatchColumn = -1;
7122         }
7123     }
7124 
7125     /**
7126      * Unsets the designated parameter to the given <code>int</code>
7127      * object.  This was set using <code>setMatchColumn</code>
7128      * as the column which will form the basis of the join.
7129      * <P>
7130      * The parameter value unset by this method should be same
7131      * as was set.
7132      *
7133      * @param columnIdx the index into this rowset
7134      *        object's internal representation of parameter values
7135      * @throws SQLException if an error occurs or the
7136      *  parameter index is out of bounds or if the columnIdx is
7137      *  not the same as set using <code>setMatchColumn(int)</code>
7138      */
7139     public void unsetMatchColumn(int columnIdx) throws SQLException {
7140         // check if we are unsetting the SAME column
7141         if(! iMatchColumns.get(0).equals(Integer.valueOf(columnIdx) )  ) {
7142             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch").toString());
7143         } else if(strMatchColumns.get(0) != null) {
7144             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch1").toString());
7145         } else {
7146                 // that is, we are unsetting it.
7147                iMatchColumns.set(0, -1);
7148         }
7149     }
7150 
7151     /**
7152      * Unsets the designated parameter to the given <code>String</code>
7153      * object.  This was set using <code>setMatchColumn</code>
7154      * as the column which will form the basis of the join.
7155      * <P>
7156      * The parameter value unset by this method should be same
7157      * as was set.
7158      *
7159      * @param columnName the index into this rowset
7160      *        object's internal representation of parameter values
7161      * @throws SQLException if an error occurs or the
7162      *  parameter index is out of bounds or if the columnName is
7163      *  not the same as set using <code>setMatchColumn(String)</code>
7164      */
7165     public void unsetMatchColumn(String columnName) throws SQLException {
7166         // check if we are unsetting the same column
7167         columnName = columnName.trim();
7168 
7169         if(!((strMatchColumns.get(0)).equals(columnName))) {
7170             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch").toString());
7171         } else if(iMatchColumns.get(0) > 0) {
7172             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch2").toString());
7173         } else {
7174             strMatchColumns.set(0, null);   // that is, we are unsetting it.
7175         }
7176     }
7177 
7178     /**
7179      * Notifies registered listeners that a RowSet object in the given RowSetEvent
7180      * object has populated a number of additional rows. The <code>numRows</code> parameter
7181      * ensures that this event will only be fired every <code>numRow</code>.
7182      * <p>
7183      * The source of the event can be retrieved with the method event.getSource.
7184      *
7185      * @param event a <code>RowSetEvent</code> object that contains the
7186      *     <code>RowSet</code> object that is the source of the events
7187      * @param numRows when populating, the number of rows interval on which the
7188      *     <code>CachedRowSet</code> populated should fire; the default value
7189      *     is zero; cannot be less than <code>fetchSize</code> or zero
7190      */
7191     public void rowSetPopulated(RowSetEvent event, int numRows) throws SQLException {
7192 
7193         if( numRows < 0 || numRows < getFetchSize()) {
7194            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.numrows").toString());
7195         }
7196 
7197         if(size() % numRows == 0) {
7198             RowSetEvent event_temp = new RowSetEvent(this);
7199             event = event_temp;
7200             notifyRowSetChanged();
7201         }
7202     }
7203 
7204     /**
7205      * Populates this <code>CachedRowSet</code> object with data from
7206      * the given <code>ResultSet</code> object. While related to the <code>populate(ResultSet)</code>
7207      * method, an additional parameter is provided to allow starting position within
7208      * the <code>ResultSet</code> from where to populate the CachedRowSet
7209      * instance.
7210      *
7211      * This method is an alternative to the method <code>execute</code>
7212      * for filling the rowset with data.  The method <code>populate</code>
7213      * does not require that the properties needed by the method
7214      * <code>execute</code>, such as the <code>command</code> property,
7215      * be set. This is true because the method <code>populate</code>
7216      * is given the <code>ResultSet</code> object from
7217      * which to get data and thus does not need to use the properties
7218      * required for setting up a connection and executing this
7219      * <code>CachedRowSetImpl</code> object's command.
7220      * <P>
7221      * After populating this rowset with data, the method
7222      * <code>populate</code> sets the rowset's metadata and
7223      * then sends a <code>RowSetChangedEvent</code> object
7224      * to all registered listeners prior to returning.
7225      *
7226      * @param data the <code>ResultSet</code> object containing the data
7227      *             to be read into this <code>CachedRowSetImpl</code> object
7228      * @param start the integer specifing the position in the
7229      *        <code>ResultSet</code> object to popultate the
7230      *        <code>CachedRowSetImpl</code> object.
7231      * @throws SQLException if an error occurs; or the max row setting is
7232      *          violated while populating the RowSet.Also id the start position
7233      *          is negative.
7234      * @see #execute
7235      */
7236      public void populate(ResultSet data, int start) throws SQLException{
7237 
7238         int rowsFetched;
7239         Row currentRow;
7240         int numCols;
7241         int i;
7242         Map<String, Class<?>> map = getTypeMap();
7243         Object obj;
7244         int mRows;
7245 
7246         cursorPos = 0;
7247         if(populatecallcount == 0){
7248             if(start < 0){
7249                throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.startpos").toString());
7250             }
7251             if(getMaxRows() == 0){
7252                data.absolute(start);
7253                while(data.next()){
7254                    totalRows++;
7255                }
7256                totalRows++;
7257             }
7258             startPos = start;
7259         }
7260         populatecallcount = populatecallcount +1;
7261         resultSet = data;
7262         if((endPos - startPos) >= getMaxRows() && (getMaxRows() > 0)){
7263             endPos = prevEndPos;
7264             pagenotend = false;
7265             return;
7266         }
7267 
7268         if((maxRowsreached != getMaxRows() || maxRowsreached != totalRows) && pagenotend) {
7269            startPrev = start - getPageSize();
7270         }
7271 
7272         if( pageSize == 0){
7273            prevEndPos = endPos;
7274            endPos = start + getMaxRows() ;
7275         }
7276         else{
7277             prevEndPos = endPos;
7278             endPos = start + getPageSize();
7279         }
7280 
7281 
7282         if (start == 1){
7283             resultSet.beforeFirst();
7284         }
7285         else {
7286             resultSet.absolute(start -1);
7287         }
7288         if( pageSize == 0) {
7289            rvh = new Vector<Object>(getMaxRows());
7290 
7291         }
7292         else{
7293             rvh = new Vector<Object>(getPageSize());
7294         }
7295 
7296         if (data == null) {
7297             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.populate").toString());
7298         }
7299 
7300         // get the meta data for this ResultSet
7301         RSMD = data.getMetaData();
7302 
7303         // set up the metadata
7304         RowSetMD = new RowSetMetaDataImpl();
7305         initMetaData(RowSetMD, RSMD);
7306 
7307         // release the meta-data so that aren't tempted to use it.
7308         RSMD = null;
7309         numCols = RowSetMD.getColumnCount();
7310         mRows = this.getMaxRows();
7311         rowsFetched = 0;
7312         currentRow = null;
7313 
7314         if(!data.next() && mRows == 0){
7315             endPos = prevEndPos;
7316             pagenotend = false;
7317             return;
7318         }
7319 
7320         data.previous();
7321 
7322         while ( data.next()) {
7323 
7324             currentRow = new Row(numCols);
7325           if(pageSize == 0){
7326             if ( rowsFetched >= mRows && mRows > 0) {
7327                 rowsetWarning.setNextException(new SQLException("Populating rows "
7328                 + "setting has exceeded max row setting"));
7329                 break;
7330             }
7331           }
7332           else {
7333               if ( (rowsFetched >= pageSize) ||( maxRowsreached >= mRows && mRows > 0)) {
7334                 rowsetWarning.setNextException(new SQLException("Populating rows "
7335                 + "setting has exceeded max row setting"));
7336                 break;
7337             }
7338           }
7339 
7340             for ( i = 1; i <= numCols; i++) {
7341                 /*
7342                  * check if the user has set a map. If no map
7343                  * is set then use plain getObject. This lets
7344                  * us work with drivers that do not support
7345                  * getObject with a map in fairly sensible way
7346                  */
7347                 if (map == null) {
7348                     obj = data.getObject(i);
7349                 } else {
7350                     obj = data.getObject(i, map);
7351                 }
7352                 /*
7353                  * the following block checks for the various
7354                  * types that we have to serialize in order to
7355                  * store - right now only structs have been tested
7356                  */
7357                 if (obj instanceof Struct) {
7358                     obj = new SerialStruct((Struct)obj, map);
7359                 } else if (obj instanceof SQLData) {
7360                     obj = new SerialStruct((SQLData)obj, map);
7361                 } else if (obj instanceof Blob) {
7362                     obj = new SerialBlob((Blob)obj);
7363                 } else if (obj instanceof Clob) {
7364                     obj = new SerialClob((Clob)obj);
7365                 } else if (obj instanceof java.sql.Array) {
7366                     obj = new SerialArray((java.sql.Array)obj, map);
7367                 }
7368 
7369                 currentRow.initColumnObject(i, obj);
7370             }
7371             rowsFetched++;
7372             maxRowsreached++;
7373             rvh.add(currentRow);
7374         }
7375         numRows = rowsFetched ;
7376         // Also rowsFetched should be equal to rvh.size()
7377         // notify any listeners that the rowset has changed
7378         notifyRowSetChanged();
7379 
7380      }
7381 
7382     /**
7383      * The nextPage gets the next page, that is a <code>CachedRowSetImpl</code> object
7384      * containing the number of rows specified by page size.
7385      * @return boolean value true indicating whether there are more pages to come and
7386      *         false indicating that this is the last page.
7387      * @throws SQLException if an error occurs or this called before calling populate.
7388      */
7389      public boolean nextPage() throws SQLException {
7390 
7391          if (populatecallcount == 0){
7392              throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.nextpage").toString());
7393          }
7394          // Fix for 6554186
7395          onFirstPage = false;
7396          if(callWithCon){
7397             crsReader.setStartPosition(endPos);
7398             crsReader.readData((RowSetInternal)this);
7399             resultSet = null;
7400          }
7401          else {
7402             populate(resultSet,endPos);
7403          }
7404          return pagenotend;
7405      }
7406 
7407     /**
7408      * This is the setter function for setting the size of the page, which specifies
7409      * how many rows have to be retrived at a time.
7410      *
7411      * @param size which is the page size
7412      * @throws SQLException if size is less than zero or greater than max rows.
7413      */
7414      public void setPageSize (int size) throws SQLException {
7415         if (size < 0) {
7416             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.pagesize").toString());
7417         }
7418         if (size > getMaxRows() && getMaxRows() != 0) {
7419             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.pagesize1").toString());
7420         }
7421         pageSize = size;
7422      }
7423 
7424     /**
7425      * This is the getter function for the size of the page.
7426      *
7427      * @return an integer that is the page size.
7428      */
7429     public int getPageSize() {
7430         return pageSize;
7431     }
7432 
7433 
7434     /**
7435      * Retrieves the data present in the page prior to the page from where it is
7436      * called.
7437      * @return boolean value true if it retrieves the previous page, flase if it
7438      *         is on the first page.
7439      * @throws SQLException if it is called before populate is called or ResultSet
7440      *         is of type <code>ResultSet.TYPE_FORWARD_ONLY</code> or if an error
7441      *         occurs.
7442      */
7443     public boolean previousPage() throws SQLException {
7444         int pS;
7445         int mR;
7446         int rem;
7447 
7448         pS = getPageSize();
7449         mR = maxRowsreached;
7450 
7451         if (populatecallcount == 0){
7452              throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.nextpage").toString());
7453          }
7454 
7455         if( !callWithCon){
7456            if(resultSet.getType() == ResultSet.TYPE_FORWARD_ONLY){
7457                throw new SQLException (resBundle.handleGetObject("cachedrowsetimpl.fwdonly").toString());
7458            }
7459         }
7460 
7461         pagenotend = true;
7462 
7463         if(startPrev < startPos ){
7464                 onFirstPage = true;
7465                return false;
7466             }
7467 
7468         if(onFirstPage){
7469             return false;
7470         }
7471 
7472         rem = mR % pS;
7473 
7474         if(rem == 0){
7475             maxRowsreached -= (2 * pS);
7476             if(callWithCon){
7477                 crsReader.setStartPosition(startPrev);
7478                 crsReader.readData((RowSetInternal)this);
7479                 resultSet = null;
7480             }
7481             else {
7482                populate(resultSet,startPrev);
7483             }
7484             return true;
7485         }
7486         else
7487         {
7488             maxRowsreached -= (pS + rem);
7489             if(callWithCon){
7490                 crsReader.setStartPosition(startPrev);
7491                 crsReader.readData((RowSetInternal)this);
7492                 resultSet = null;
7493             }
7494             else {
7495                populate(resultSet,startPrev);
7496             }
7497             return true;
7498         }
7499     }
7500 
7501     /**
7502      * Goes to the page number passed as the parameter
7503      * @param page , the page loaded on a call to this function
7504      * @return true if the page exists false otherwise
7505      * @throws SQLException if an error occurs
7506      */
7507     /*
7508     public boolean absolutePage(int page) throws SQLException{
7509 
7510         boolean isAbs = true, retVal = true;
7511         int counter;
7512 
7513         if( page <= 0 ){
7514             throw new SQLException("Absolute positoin is invalid");
7515         }
7516         counter = 0;
7517 
7518         firstPage();
7519         counter++;
7520         while((counter < page) && isAbs) {
7521             isAbs = nextPage();
7522             counter ++;
7523         }
7524 
7525         if( !isAbs && counter < page){
7526             retVal = false;
7527         }
7528         else if(counter == page){
7529             retVal = true;
7530         }
7531 
7532        return retVal;
7533     }
7534     */
7535 
7536 
7537     /**
7538      * Goes to the page number passed as the parameter  from the current page.
7539      * The parameter can take postive or negative value accordingly.
7540      * @param page , the page loaded on a call to this function
7541      * @return true if the page exists false otherwise
7542      * @throws SQLException if an error occurs
7543      */
7544     /*
7545     public boolean relativePage(int page) throws SQLException {
7546 
7547         boolean isRel = true,retVal = true;
7548         int counter;
7549 
7550         if(page > 0){
7551            counter  = 0;
7552            while((counter < page) && isRel){
7553               isRel = nextPage();
7554               counter++;
7555            }
7556 
7557            if(!isRel && counter < page){
7558                retVal = false;
7559            }
7560            else if( counter == page){
7561                retVal = true;
7562            }
7563            return retVal;
7564         }
7565         else {
7566             counter = page;
7567             isRel = true;
7568             while((counter < 0) && isRel){
7569                 isRel = previousPage();
7570                 counter++;
7571             }
7572 
7573             if( !isRel && counter < 0){
7574                 retVal = false;
7575             }
7576             else if(counter == 0){
7577                 retVal = true;
7578             }
7579             return retVal;
7580         }
7581     }
7582     */
7583 
7584      /**
7585      * Retrieves the first page of data as specified by the page size.
7586      * @return boolean value true if present on first page, false otherwise
7587      * @throws SQLException if it called before populate or ResultSet is of
7588      *         type <code>ResultSet.TYPE_FORWARD_ONLY</code> or an error occurs
7589      */
7590     /*
7591     public boolean firstPage() throws SQLException {
7592            if (populatecallcount == 0){
7593              throw new SQLException("Populate the data before calling ");
7594            }
7595            if( !callWithCon){
7596               if(resultSet.getType() == ResultSet.TYPE_FORWARD_ONLY) {
7597                   throw new SQLException("Result of type forward only");
7598               }
7599            }
7600            endPos = 0;
7601            maxRowsreached = 0;
7602            pagenotend = true;
7603            if(callWithCon){
7604                crsReader.setStartPosition(startPos);
7605                crsReader.readData((RowSetInternal)this);
7606                resultSet = null;
7607            }
7608            else {
7609               populate(resultSet,startPos);
7610            }
7611            onFirstPage = true;
7612            return onFirstPage;
7613     }
7614     */
7615 
7616     /**
7617      * Retrives the last page of data as specified by the page size.
7618      * @return boolean value tur if present on the last page, false otherwise
7619      * @throws SQLException if called before populate or if an error occurs.
7620      */
7621      /*
7622     public boolean lastPage() throws SQLException{
7623           int pS;
7624           int mR;
7625           int quo;
7626           int rem;
7627 
7628           pS = getPageSize();
7629           mR = getMaxRows();
7630 
7631           if(pS == 0){
7632               onLastPage = true;
7633               return onLastPage;
7634           }
7635 
7636           if(getMaxRows() == 0){
7637               mR = totalRows;
7638           }
7639 
7640           if (populatecallcount == 0){
7641              throw new SQLException("Populate the data before calling ");
7642          }
7643 
7644          onFirstPage = false;
7645 
7646          if((mR % pS) == 0){
7647              quo = mR / pS;
7648              int start = startPos + (pS * (quo - 1));
7649              maxRowsreached = mR - pS;
7650              if(callWithCon){
7651                  crsReader.setStartPosition(start);
7652                  crsReader.readData((RowSetInternal)this);
7653                  resultSet = null;
7654              }
7655              else {
7656                 populate(resultSet,start);
7657              }
7658              onLastPage = true;
7659              return onLastPage;
7660          }
7661         else {
7662               quo = mR /pS;
7663               rem = mR % pS;
7664               int start = startPos + (pS * quo);
7665              maxRowsreached = mR - (rem);
7666              if(callWithCon){
7667                  crsReader.setStartPosition(start);
7668                  crsReader.readData((RowSetInternal)this);
7669                  resultSet = null;
7670              }
7671              else {
7672                 populate(resultSet,start);
7673              }
7674              onLastPage = true;
7675              return onLastPage;
7676          }
7677     }
7678     */
7679 
7680    /**
7681      * Sets the status for the row on which the cursor is positioned. The insertFlag is used
7682      * to mention the toggle status for this row
7683      * @param insertFlag if it is true  - marks this row as inserted
7684      *                   if it is false - marks it as not a newly inserted row
7685      * @throws SQLException if an error occurs while doing this operation
7686      */
7687     public void setRowInserted(boolean insertFlag) throws SQLException {
7688 
7689         checkCursor();
7690 
7691         if(onInsertRow == true)
7692           throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
7693 
7694         if( insertFlag ) {
7695           ((Row)getCurrentRow()).setInserted();
7696         } else {
7697           ((Row)getCurrentRow()).clearInserted();
7698         }
7699     }
7700 
7701     /**
7702      * Retrieves the value of the designated <code>SQL XML</code> parameter as a
7703      * <code>SQLXML</code> object in the Java programming language.
7704      * @param columnIndex the first column is 1, the second is 2, ...
7705      * @return a SQLXML object that maps an SQL XML value
7706      * @throws SQLException if a database access error occurs
7707      * @since 1.6
7708      */
7709     public SQLXML getSQLXML(int columnIndex) throws SQLException {
7710         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7711     }
7712 
7713     /**
7714      * Retrieves the value of the designated <code>SQL XML</code> parameter as a
7715      * <code>SQLXML</code> object in the Java programming language.
7716      * @param colName the name of the column from which to retrieve the value
7717      * @return a SQLXML object that maps an SQL XML value
7718      * @throws SQLException if a database access error occurs
7719      */
7720     public SQLXML getSQLXML(String colName) throws SQLException {
7721         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7722     }
7723 
7724     /**
7725      * Retrieves the value of the designated column in the current row of this
7726      * <code>ResultSet</code> object as a java.sql.RowId object in the Java
7727      * programming language.
7728      *
7729      * @param columnIndex the first column is 1, the second 2, ...
7730      * @return the column value if the value is a SQL <code>NULL</code> the
7731      *     value returned is <code>null</code>
7732      * @throws SQLException if a database access error occurs
7733      * @since 1.6
7734      */
7735     public RowId getRowId(int columnIndex) throws SQLException {
7736         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7737     }
7738 
7739     /**
7740      * Retrieves the value of the designated column in the current row of this
7741      * <code>ResultSet</code> object as a java.sql.RowId object in the Java
7742      * programming language.
7743      *
7744      * @param columnName the name of the column
7745      * @return the column value if the value is a SQL <code>NULL</code> the
7746      *     value returned is <code>null</code>
7747      * @throws SQLException if a database access error occurs
7748      * @since 1.6
7749      */
7750     public RowId getRowId(String columnName) throws SQLException {
7751         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7752     }
7753 
7754     /**
7755      * Updates the designated column with a <code>RowId</code> value. The updater
7756      * methods are used to update column values in the current row or the insert
7757      * row. The updater methods do not update the underlying database; instead
7758      * the {@code updateRow} or {@code insertRow} methods are called
7759      * to update the database.
7760      *
7761      * @param columnIndex the first column is 1, the second 2, ...
7762      * @param x the column value
7763      * @throws SQLException if a database access occurs
7764      * @since 1.6
7765      */
7766     public void updateRowId(int columnIndex, RowId x) throws SQLException {
7767         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7768     }
7769 
7770     /**
7771      * Updates the designated column with a <code>RowId</code> value. The updater
7772      * methods are used to update column values in the current row or the insert
7773      * row. The updater methods do not update the underlying database; instead
7774      * the {@code updateRow} or {@code insertRow} methods are called
7775      * to update the database.
7776      *
7777      * @param columnName the name of the column
7778      * @param x the column value
7779      * @throws SQLException if a database access occurs
7780      * @since 1.6
7781      */
7782     public void updateRowId(String columnName, RowId x) throws SQLException {
7783         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7784     }
7785 
7786     /**
7787      * Retrieves the holdability of this ResultSet object
7788      * @return  either ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT
7789      * @throws SQLException if a database error occurs
7790      * @since 1.6
7791      */
7792     public int getHoldability() throws SQLException {
7793         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7794     }
7795 
7796     /**
7797      * Retrieves whether this ResultSet object has been closed. A ResultSet is closed if the
7798      * method close has been called on it, or if it is automatically closed.
7799      * @return true if this ResultSet object is closed; false if it is still open
7800      * @throws SQLException if a database access error occurs
7801      * @since 1.6
7802      */
7803     public boolean isClosed() throws SQLException {
7804         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7805     }
7806 
7807     /**
7808      * This method is used for updating columns that support National Character sets.
7809      * It can be used for updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
7810      * @param columnIndex the first column is 1, the second 2, ...
7811      * @param nString the value for the column to be updated
7812      * @throws SQLException if a database access error occurs
7813      * @since 1.6
7814      */
7815     public void updateNString(int columnIndex, String nString) throws SQLException {
7816         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7817     }
7818 
7819     /**
7820      * This method is used for updating columns that support National Character sets.
7821      * It can be used for updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
7822      * @param columnName name of the Column
7823      * @param nString the value for the column to be updated
7824      * @throws SQLException if a database access error occurs
7825      * @since 1.6
7826      */
7827     public void updateNString(String columnName, String nString) throws SQLException {
7828         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7829     }
7830 
7831 
7832     /*o
7833      * This method is used for updating SQL <code>NCLOB</code>  type that maps
7834      * to <code>java.sql.Types.NCLOB</code>
7835      * @param columnIndex the first column is 1, the second 2, ...
7836      * @param nClob the value for the column to be updated
7837      * @throws SQLException if a database access error occurs
7838      * @since 1.6
7839      */
7840     public void updateNClob(int columnIndex, NClob nClob) throws SQLException {
7841         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7842     }
7843 
7844     /**
7845      * This method is used for updating SQL <code>NCLOB</code>  type that maps
7846      * to <code>java.sql.Types.NCLOB</code>
7847      * @param columnName name of the column
7848      * @param nClob the value for the column to be updated
7849      * @throws SQLException if a database access error occurs
7850      * @since 1.6
7851      */
7852     public void updateNClob(String columnName, NClob nClob) throws SQLException {
7853        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7854     }
7855 
7856     /**
7857      * Retrieves the value of the designated column in the current row
7858      * of this <code>ResultSet</code> object as a <code>NClob</code> object
7859      * in the Java programming language.
7860      *
7861      * @param i the first column is 1, the second is 2, ...
7862      * @return a <code>NClob</code> object representing the SQL
7863      *         <code>NCLOB</code> value in the specified column
7864      * @exception SQLException if a database access error occurs
7865      * @since 1.6
7866      */
7867     public NClob getNClob(int i) throws SQLException {
7868         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7869     }
7870 
7871 
7872    /**
7873      * Retrieves the value of the designated column in the current row
7874      * of this <code>ResultSet</code> object as a <code>NClob</code> object
7875      * in the Java programming language.
7876      *
7877      * @param colName the name of the column from which to retrieve the value
7878      * @return a <code>NClob</code> object representing the SQL <code>NCLOB</code>
7879      * value in the specified column
7880      * @exception SQLException if a database access error occurs
7881      * @since 1.6
7882      */
7883     public NClob getNClob(String colName) throws SQLException {
7884         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7885     }
7886 
7887     public <T> T unwrap(java.lang.Class<T> iface) throws java.sql.SQLException {
7888         return null;
7889     }
7890 
7891     public boolean isWrapperFor(Class<?> interfaces) throws SQLException {
7892         return false;
7893     }
7894 
7895 
7896    /**
7897       * Sets the designated parameter to the given <code>java.sql.SQLXML</code> object. The driver converts this to an
7898       * SQL <code>XML</code> value when it sends it to the database.
7899       * @param parameterIndex index of the first parameter is 1, the second is 2, ...
7900       * @param xmlObject a <code>SQLXML</code> object that maps an SQL <code>XML</code> value
7901       * @throws SQLException if a database access error occurs
7902       * @since 1.6
7903       */
7904      public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
7905          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7906      }
7907 
7908    /**
7909      * Sets the designated parameter to the given <code>java.sql.SQLXML</code> object. The driver converts this to an
7910      * <code>SQL XML</code> value when it sends it to the database.
7911      * @param parameterName the name of the parameter
7912      * @param xmlObject a <code>SQLXML</code> object that maps an <code>SQL XML</code> value
7913      * @throws SQLException if a database access error occurs
7914      * @since 1.6
7915      */
7916     public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException {
7917          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7918      }
7919 
7920 
7921     /**
7922      * Sets the designated parameter to the given <code>java.sql.RowId</code> object. The
7923      * driver converts this to a SQL <code>ROWID</code> value when it sends it
7924      * to the database
7925      *
7926      * @param parameterIndex the first parameter is 1, the second is 2, ...
7927      * @param x the parameter value
7928      * @throws SQLException if a database access error occurs
7929      *
7930      * @since 1.6
7931      */
7932     public void setRowId(int parameterIndex, RowId x) throws SQLException {
7933          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7934      }
7935 
7936 
7937     /**
7938     * Sets the designated parameter to the given <code>java.sql.RowId</code> object. The
7939     * driver converts this to a SQL <code>ROWID</code> when it sends it to the
7940     * database.
7941     *
7942     * @param parameterName the name of the parameter
7943     * @param x the parameter value
7944     * @throws SQLException if a database access error occurs
7945     * @since 1.6
7946     */
7947    public void setRowId(String parameterName, RowId x) throws SQLException {
7948          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7949      }
7950 
7951 
7952     /**
7953      * Sets the designated parameter to a <code>Reader</code> object. The
7954      * <code>Reader</code> reads the data till end-of-file is reached. The
7955      * driver does the necessary conversion from Java character format to
7956      * the national character set in the database.
7957 
7958      * <P><B>Note:</B> This stream object can either be a standard
7959      * Java stream object or your own subclass that implements the
7960      * standard interface.
7961      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
7962      * it might be more efficient to use a version of
7963      * <code>setNCharacterStream</code> which takes a length parameter.
7964      *
7965      * @param parameterIndex of the first parameter is 1, the second is 2, ...
7966      * @param value the parameter value
7967      * @throws SQLException if the driver does not support national
7968      *         character sets;  if the driver can detect that a data conversion
7969      *  error could occur ; if a database access error occurs; or
7970      * this method is called on a closed <code>PreparedStatement</code>
7971      * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
7972      * @since 1.6
7973      */
7974      public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
7975         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
7976      }
7977 
7978 
7979     /**
7980     * Sets the designated parameter to a <code>java.sql.NClob</code> object. The object
7981     * implements the <code>java.sql.NClob</code> interface. This <code>NClob</code>
7982     * object maps to a SQL <code>NCLOB</code>.
7983     * @param parameterName the name of the column to be set
7984     * @param value the parameter value
7985     * @throws SQLException if the driver does not support national
7986     *         character sets;  if the driver can detect that a data conversion
7987     *  error could occur; or if a database access error occurs
7988     * @since 1.6
7989     */
7990     public void setNClob(String parameterName, NClob value) throws SQLException {
7991          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7992      }
7993 
7994 
7995   /**
7996      * Retrieves the value of the designated column in the current row
7997      * of this <code>ResultSet</code> object as a
7998      * <code>java.io.Reader</code> object.
7999      * It is intended for use when
8000      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8001      * and <code>LONGNVARCHAR</code> columns.
8002      *
8003      * @return a <code>java.io.Reader</code> object that contains the column
8004      * value; if the value is SQL <code>NULL</code>, the value returned is
8005      * <code>null</code> in the Java programming language.
8006      * @param columnIndex the first column is 1, the second is 2, ...
8007      * @exception SQLException if a database access error occurs
8008      * @since 1.6
8009      */
8010     public java.io.Reader getNCharacterStream(int columnIndex) throws SQLException {
8011        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8012      }
8013 
8014 
8015     /**
8016      * Retrieves the value of the designated column in the current row
8017      * of this <code>ResultSet</code> object as a
8018      * <code>java.io.Reader</code> object.
8019      * It is intended for use when
8020      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8021      * and <code>LONGNVARCHAR</code> columns.
8022      *
8023      * @param columnName the name of the column
8024      * @return a <code>java.io.Reader</code> object that contains the column
8025      * value; if the value is SQL <code>NULL</code>, the value returned is
8026      * <code>null</code> in the Java programming language
8027      * @exception SQLException if a database access error occurs
8028      * @since 1.6
8029      */
8030     public java.io.Reader getNCharacterStream(String columnName) throws SQLException {
8031        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8032      }
8033 
8034 
8035     /**
8036      * Updates the designated column with a <code>java.sql.SQLXML</code> value.
8037      * The updater
8038      * methods are used to update column values in the current row or the insert
8039      * row. The updater methods do not update the underlying database; instead
8040      * the <code>updateRow</code> or <code>insertRow</code> methods are called
8041      * to update the database.
8042      * @param columnIndex the first column is 1, the second 2, ...
8043      * @param xmlObject the value for the column to be updated
8044      * @throws SQLException if a database access error occurs
8045      * @since 1.6
8046      */
8047     public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException {
8048         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8049     }
8050 
8051     /**
8052      * Updates the designated column with a <code>java.sql.SQLXML</code> value.
8053      * The updater
8054      * methods are used to update column values in the current row or the insert
8055      * row. The updater methods do not update the underlying database; instead
8056      * the <code>updateRow</code> or <code>insertRow</code> methods are called
8057      * to update the database.
8058      *
8059      * @param columnName the name of the column
8060      * @param xmlObject the column value
8061      * @throws SQLException if a database access occurs
8062      * @since 1.6
8063      */
8064     public void updateSQLXML(String columnName, SQLXML xmlObject) throws SQLException {
8065         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8066     }
8067 
8068      /**
8069      * Retrieves the value of the designated column in the current row
8070      * of this <code>ResultSet</code> object as
8071      * a <code>String</code> in the Java programming language.
8072      * It is intended for use when
8073      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8074      * and <code>LONGNVARCHAR</code> columns.
8075      *
8076      * @param columnIndex the first column is 1, the second is 2, ...
8077      * @return the column value; if the value is SQL <code>NULL</code>, the
8078      * value returned is <code>null</code>
8079      * @exception SQLException if a database access error occurs
8080      * @since 1.6
8081      */
8082     public String getNString(int columnIndex) throws SQLException {
8083         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8084     }
8085 
8086     /**
8087      * Retrieves the value of the designated column in the current row
8088      * of this <code>ResultSet</code> object as
8089      * a <code>String</code> in the Java programming language.
8090      * It is intended for use when
8091      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8092      * and <code>LONGNVARCHAR</code> columns.
8093      *
8094      * @param columnName the SQL name of the column
8095      * @return the column value; if the value is SQL <code>NULL</code>, the
8096      * value returned is <code>null</code>
8097      * @exception SQLException if a database access error occurs
8098      * @since 1.6
8099      */
8100     public String getNString(String columnName) throws SQLException {
8101         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8102     }
8103 
8104      /**
8105        * Updates the designated column with a character stream value, which will
8106        * have the specified number of bytes. The driver does the necessary conversion
8107        * from Java character format to the national character set in the database.
8108        * It is intended for use when updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
8109        * The updater methods are used to update column values in the current row or
8110        * the insert row. The updater methods do not update the underlying database;
8111        * instead the updateRow or insertRow methods are called to update the database.
8112        *
8113        * @param columnIndex - the first column is 1, the second is 2, ...
8114        * @param x - the new column value
8115        * @param length - the length of the stream
8116        * @exception SQLException if a database access error occurs
8117        * @since 1.6
8118        */
8119        public void updateNCharacterStream(int columnIndex,
8120                             java.io.Reader x,
8121                             long length)
8122                             throws SQLException {
8123           throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8124        }
8125 
8126      /**
8127        * Updates the designated column with a character stream value, which will
8128        * have the specified number of bytes. The driver does the necessary conversion
8129        * from Java character format to the national character set in the database.
8130        * It is intended for use when updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
8131        * The updater methods are used to update column values in the current row or
8132        * the insert row. The updater methods do not update the underlying database;
8133        * instead the updateRow or insertRow methods are called to update the database.
8134        *
8135        * @param columnName - name of the Column
8136        * @param x - the new column value
8137        * @param length - the length of the stream
8138        * @exception SQLException if a database access error occurs
8139        * @since 1.6
8140        */
8141        public void updateNCharacterStream(String columnName,
8142                             java.io.Reader x,
8143                             long length)
8144                             throws SQLException {
8145           throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8146        }
8147 
8148      /**
8149      * Updates the designated column with a character stream value.   The
8150      * driver does the necessary conversion from Java character format to
8151      * the national character set in the database.
8152      * It is intended for use when
8153      * updating  <code>NCHAR</code>,<code>NVARCHAR</code>
8154      * and <code>LONGNVARCHAR</code> columns.
8155      *
8156      * The updater methods are used to update column values in the
8157      * current row or the insert row.  The updater methods do not
8158      * update the underlying database; instead the <code>updateRow</code> or
8159      * <code>insertRow</code> methods are called to update the database.
8160      *
8161      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8162      * it might be more efficient to use a version of
8163      * <code>updateNCharacterStream</code> which takes a length parameter.
8164      *
8165      * @param columnIndex the first column is 1, the second is 2, ...
8166      * @param x the new column value
8167      * @exception SQLException if a database access error occurs,
8168      * the result set concurrency is <code>CONCUR_READ_ONLY</code> or this method is called on a closed result set
8169      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8170      * this method
8171      * @since 1.6
8172      */
8173     public void updateNCharacterStream(int columnIndex,
8174                              java.io.Reader x) throws SQLException {
8175         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8176     }
8177 
8178     /**
8179      * Updates the designated column with a character stream value.  The
8180      * driver does the necessary conversion from Java character format to
8181      * the national character set in the database.
8182      * It is intended for use when
8183      * updating  <code>NCHAR</code>,<code>NVARCHAR</code>
8184      * and <code>LONGNVARCHAR</code> columns.
8185      *
8186      * The updater methods are used to update column values in the
8187      * current row or the insert row.  The updater methods do not
8188      * update the underlying database; instead the <code>updateRow</code> or
8189      * <code>insertRow</code> methods are called to update the database.
8190      *
8191      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8192      * it might be more efficient to use a version of
8193      * <code>updateNCharacterStream</code> which takes a length parameter.
8194      *
8195      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8196 bel is the name of the column
8197      * @param reader the <code>java.io.Reader</code> object containing
8198      *        the new column value
8199      * @exception SQLException if a database access error occurs,
8200      * the result set concurrency is <code>CONCUR_READ_ONLY</code> or this method is called on a closed result set
8201       * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8202      * this method
8203      * @since 1.6
8204      */
8205     public void updateNCharacterStream(String columnLabel,
8206                              java.io.Reader reader) throws SQLException {
8207         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8208     }
8209 
8210 //////////////////////////
8211 
8212     /**
8213      * Updates the designated column using the given input stream, which
8214      * will have the specified number of bytes.
8215      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8216      * parameter, it may be more practical to send it via a
8217      * <code>java.io.InputStream</code>. Data will be read from the stream
8218      * as needed until end-of-file is reached.  The JDBC driver will
8219      * do any necessary conversion from ASCII to the database char format.
8220      *
8221      * <P><B>Note:</B> This stream object can either be a standard
8222      * Java stream object or your own subclass that implements the
8223      * standard interface.
8224      * <p>
8225      * The updater methods are used to update column values in the
8226      * current row or the insert row.  The updater methods do not
8227      * update the underlying database; instead the <code>updateRow</code> or
8228      * <code>insertRow</code> methods are called to update the database.
8229      *
8230      * @param columnIndex the first column is 1, the second is 2, ...
8231      * @param inputStream An object that contains the data to set the parameter
8232      * value to.
8233      * @param length the number of bytes in the parameter data.
8234      * @exception SQLException if a database access error occurs,
8235      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8236      * or this method is called on a closed result set
8237      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8238      * this method
8239      * @since 1.6
8240      */
8241     public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException{
8242         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8243     }
8244 
8245     /**
8246      * Updates the designated column using the given input stream, which
8247      * will have the specified number of bytes.
8248      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8249      * parameter, it may be more practical to send it via a
8250      * <code>java.io.InputStream</code>. Data will be read from the stream
8251      * as needed until end-of-file is reached.  The JDBC driver will
8252      * do any necessary conversion from ASCII to the database char format.
8253      *
8254      * <P><B>Note:</B> This stream object can either be a standard
8255      * Java stream object or your own subclass that implements the
8256      * standard interface.
8257      * <p>
8258      * The updater methods are used to update column values in the
8259      * current row or the insert row.  The updater methods do not
8260      * update the underlying database; instead the <code>updateRow</code> or
8261      * <code>insertRow</code> methods are called to update the database.
8262      *
8263      * @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
8264      * @param inputStream An object that contains the data to set the parameter
8265      * value to.
8266      * @param length the number of bytes in the parameter data.
8267      * @exception SQLException if a database access error occurs,
8268      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8269      * or this method is called on a closed result set
8270      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8271      * this method
8272      * @since 1.6
8273      */
8274     public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException {
8275         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8276     }
8277 
8278     /**
8279      * Updates the designated column using the given input stream.
8280      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8281      * parameter, it may be more practical to send it via a
8282      * <code>java.io.InputStream</code>. Data will be read from the stream
8283      * as needed until end-of-file is reached.  The JDBC driver will
8284      * do any necessary conversion from ASCII to the database char format.
8285      *
8286      * <P><B>Note:</B> This stream object can either be a standard
8287      * Java stream object or your own subclass that implements the
8288      * standard interface.
8289      *
8290      *  <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8291      * it might be more efficient to use a version of
8292      * <code>updateBlob</code> which takes a length parameter.
8293      * <p>
8294      * The updater methods are used to update column values in the
8295      * current row or the insert row.  The updater methods do not
8296      * update the underlying database; instead the <code>updateRow</code> or
8297      * <code>insertRow</code> methods are called to update the database.
8298      *
8299      * @param columnIndex the first column is 1, the second is 2, ...
8300      * @param inputStream An object that contains the data to set the parameter
8301      * value to.
8302      * @exception SQLException if a database access error occurs,
8303      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8304      * or this method is called on a closed result set
8305      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8306      * this method
8307      * @since 1.6
8308      */
8309     public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException {
8310         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8311     }
8312 
8313     /**
8314      * Updates the designated column using the given input stream.
8315      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8316      * parameter, it may be more practical to send it via a
8317      * <code>java.io.InputStream</code>. Data will be read from the stream
8318      * as needed until end-of-file is reached.  The JDBC driver will
8319      * do any necessary conversion from ASCII to the database char format.
8320      *
8321      * <P><B>Note:</B> This stream object can either be a standard
8322      * Java stream object or your own subclass that implements the
8323      * standard interface.
8324      *   <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8325      * it might be more efficient to use a version of
8326      * <code>updateBlob</code> which takes a length parameter.
8327      * <p>
8328      * The updater methods are used to update column values in the
8329      * current row or the insert row.  The updater methods do not
8330      * update the underlying database; instead the <code>updateRow</code> or
8331      * <code>insertRow</code> methods are called to update the database.
8332      *
8333      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8334 bel is the name of the column
8335      * @param inputStream An object that contains the data to set the parameter
8336      * value to.
8337      * @exception SQLException if a database access error occurs,
8338      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8339      * or this method is called on a closed result set
8340      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8341      * this method
8342      * @since 1.6
8343      */
8344     public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException {
8345         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8346     }
8347 
8348     /**
8349      * Updates the designated column using the given <code>Reader</code>
8350      * object, which is the given number of characters long.
8351      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8352      * parameter, it may be more practical to send it via a
8353      * <code>java.io.Reader</code> object. The data will be read from the stream
8354      * as needed until end-of-file is reached.  The JDBC driver will
8355      * do any necessary conversion from UNICODE to the database char format.
8356      *
8357      * <P><B>Note:</B> This stream object can either be a standard
8358      * Java stream object or your own subclass that implements the
8359      * standard interface.
8360      * <p>
8361      * The updater methods are used to update column values in the
8362      * current row or the insert row.  The updater methods do not
8363      * update the underlying database; instead the <code>updateRow</code> or
8364      * <code>insertRow</code> methods are called to update the database.
8365      *
8366      * @param columnIndex the first column is 1, the second is 2, ...
8367      * @param reader An object that contains the data to set the parameter value to.
8368      * @param length the number of characters in the parameter data.
8369      * @exception SQLException if a database access error occurs,
8370      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8371      * or this method is called on a closed result set
8372      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8373      * this method
8374      * @since 1.6
8375      */
8376     public void updateClob(int columnIndex,  Reader reader, long length) throws SQLException {
8377         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8378     }
8379 
8380     /**
8381      * Updates the designated column using the given <code>Reader</code>
8382      * object, which is the given number of characters long.
8383      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8384      * parameter, it may be more practical to send it via a
8385      * <code>java.io.Reader</code> object. The data will be read from the stream
8386      * as needed until end-of-file is reached.  The JDBC driver will
8387      * do any necessary conversion from UNICODE to the database char format.
8388      *
8389      * <P><B>Note:</B> This stream object can either be a standard
8390      * Java stream object or your own subclass that implements the
8391      * standard interface.
8392      * <p>
8393      * The updater methods are used to update column values in the
8394      * current row or the insert row.  The updater methods do not
8395      * update the underlying database; instead the <code>updateRow</code> or
8396      * <code>insertRow</code> methods are called to update the database.
8397      *
8398      * @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
8399      * @param reader An object that contains the data to set the parameter value to.
8400      * @param length the number of characters in the parameter data.
8401      * @exception SQLException if a database access error occurs,
8402      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8403      * or this method is called on a closed result set
8404      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8405      * this method
8406      * @since 1.6
8407      */
8408     public void updateClob(String columnLabel,  Reader reader, long length) throws SQLException {
8409         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8410     }
8411 
8412    /**
8413      * Updates the designated column using the given <code>Reader</code>
8414      * object.
8415      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8416      * parameter, it may be more practical to send it via a
8417      * <code>java.io.Reader</code> object. The data will be read from the stream
8418      * as needed until end-of-file is reached.  The JDBC driver will
8419      * do any necessary conversion from UNICODE to the database char format.
8420      *
8421      * <P><B>Note:</B> This stream object can either be a standard
8422      * Java stream object or your own subclass that implements the
8423      * standard interface.
8424      *   <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8425      * it might be more efficient to use a version of
8426      * <code>updateClob</code> which takes a length parameter.
8427      * <p>
8428      * The updater methods are used to update column values in the
8429      * current row or the insert row.  The updater methods do not
8430      * update the underlying database; instead the <code>updateRow</code> or
8431      * <code>insertRow</code> methods are called to update the database.
8432      *
8433      * @param columnIndex the first column is 1, the second is 2, ...
8434      * @param reader An object that contains the data to set the parameter value to.
8435      * @exception SQLException if a database access error occurs,
8436      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8437      * or this method is called on a closed result set
8438      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8439      * this method
8440      * @since 1.6
8441      */
8442     public void updateClob(int columnIndex,  Reader reader) throws SQLException {
8443         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8444     }
8445 
8446     /**
8447      * Updates the designated column using the given <code>Reader</code>
8448      * object.
8449      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8450      * parameter, it may be more practical to send it via a
8451      * <code>java.io.Reader</code> object. The data will be read from the stream
8452      * as needed until end-of-file is reached.  The JDBC driver will
8453      * do any necessary conversion from UNICODE to the database char format.
8454      *
8455      * <P><B>Note:</B> This stream object can either be a standard
8456      * Java stream object or your own subclass that implements the
8457      * standard interface.
8458      *  <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8459      * it might be more efficient to use a version of
8460      * <code>updateClob</code> which takes a length parameter.
8461      * <p>
8462      * The updater methods are used to update column values in the
8463      * current row or the insert row.  The updater methods do not
8464      * update the underlying database; instead the <code>updateRow</code> or
8465      * <code>insertRow</code> methods are called to update the database.
8466      *
8467      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8468 bel is the name of the column
8469      * @param reader An object that contains the data to set the parameter value to.
8470      * @exception SQLException if a database access error occurs,
8471      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8472      * or this method is called on a closed result set
8473      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8474      * this method
8475      * @since 1.6
8476      */
8477     public void updateClob(String columnLabel,  Reader reader) throws SQLException {
8478         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8479     }
8480 
8481    /**
8482      * Updates the designated column using the given <code>Reader</code>
8483      * object, which is the given number of characters long.
8484      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8485      * parameter, it may be more practical to send it via a
8486      * <code>java.io.Reader</code> object. The data will be read from the stream
8487      * as needed until end-of-file is reached.  The JDBC driver will
8488      * do any necessary conversion from UNICODE to the database char format.
8489      *
8490      * <P><B>Note:</B> This stream object can either be a standard
8491      * Java stream object or your own subclass that implements the
8492      * standard interface.
8493      * <p>
8494      * The updater methods are used to update column values in the
8495      * current row or the insert row.  The updater methods do not
8496      * update the underlying database; instead the <code>updateRow</code> or
8497      * <code>insertRow</code> methods are called to update the database.
8498      *
8499      * @param columnIndex the first column is 1, the second 2, ...
8500      * @param reader An object that contains the data to set the parameter value to.
8501      * @param length the number of characters in the parameter data.
8502      * @throws SQLException if the driver does not support national
8503      *         character sets;  if the driver can detect that a data conversion
8504      *  error could occur; this method is called on a closed result set,
8505      * if a database access error occurs or
8506      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8507      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8508      * this method
8509      * @since 1.6
8510      */
8511     public void updateNClob(int columnIndex,  Reader reader, long length) throws SQLException {
8512         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8513     }
8514 
8515     /**
8516      * Updates the designated column using the given <code>Reader</code>
8517      * object, which is the given number of characters long.
8518      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8519      * parameter, it may be more practical to send it via a
8520      * <code>java.io.Reader</code> object. The data will be read from the stream
8521      * as needed until end-of-file is reached.  The JDBC driver will
8522      * do any necessary conversion from UNICODE to the database char format.
8523      *
8524      * <P><B>Note:</B> This stream object can either be a standard
8525      * Java stream object or your own subclass that implements the
8526      * standard interface.
8527      * <p>
8528      * The updater methods are used to update column values in the
8529      * current row or the insert row.  The updater methods do not
8530      * update the underlying database; instead the <code>updateRow</code> or
8531      * <code>insertRow</code> methods are called to update the database.
8532      *
8533      * @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
8534      * @param reader An object that contains the data to set the parameter value to.
8535      * @param length the number of characters in the parameter data.
8536      * @throws SQLException if the driver does not support national
8537      *         character sets;  if the driver can detect that a data conversion
8538      *  error could occur; this method is called on a closed result set;
8539      *  if a database access error occurs or
8540      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8541      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8542      * this method
8543      * @since 1.6
8544      */
8545     public void updateNClob(String columnLabel,  Reader reader, long length) throws SQLException {
8546         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8547     }
8548 
8549     /**
8550      * Updates the designated column using the given <code>Reader</code>
8551      * object.
8552      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8553      * parameter, it may be more practical to send it via a
8554      * <code>java.io.Reader</code> object. The data will be read from the stream
8555      * as needed until end-of-file is reached.  The JDBC driver will
8556      * do any necessary conversion from UNICODE to the database char format.
8557      *
8558      * <P><B>Note:</B> This stream object can either be a standard
8559      * Java stream object or your own subclass that implements the
8560      * standard interface.
8561      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8562      * it might be more efficient to use a version of
8563      * <code>updateNClob</code> which takes a length parameter.
8564      * <p>
8565      * The updater methods are used to update column values in the
8566      * current row or the insert row.  The updater methods do not
8567      * update the underlying database; instead the <code>updateRow</code> or
8568      * <code>insertRow</code> methods are called to update the database.
8569      *
8570      * @param columnIndex the first column is 1, the second 2, ...
8571      * @param reader An object that contains the data to set the parameter value to.
8572      * @throws SQLException if the driver does not support national
8573      *         character sets;  if the driver can detect that a data conversion
8574      *  error could occur; this method is called on a closed result set,
8575      * if a database access error occurs or
8576      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8577      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8578      * this method
8579      * @since 1.6
8580      */
8581     public void updateNClob(int columnIndex,  Reader reader) throws SQLException {
8582         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8583     }
8584 
8585     /**
8586      * Updates the designated column using the given <code>Reader</code>
8587      * object.
8588      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8589      * parameter, it may be more practical to send it via a
8590      * <code>java.io.Reader</code> object. The data will be read from the stream
8591      * as needed until end-of-file is reached.  The JDBC driver will
8592      * do any necessary conversion from UNICODE to the database char format.
8593      *
8594      * <P><B>Note:</B> This stream object can either be a standard
8595      * Java stream object or your own subclass that implements the
8596      * standard interface.
8597      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8598      * it might be more efficient to use a version of
8599      * <code>updateNClob</code> which takes a length parameter.
8600      * <p>
8601      * The updater methods are used to update column values in the
8602      * current row or the insert row.  The updater methods do not
8603      * update the underlying database; instead the <code>updateRow</code> or
8604      * <code>insertRow</code> methods are called to update the database.
8605      *
8606      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8607 bel is the name of the column
8608      * @param reader An object that contains the data to set the parameter value to.
8609      * @throws SQLException if the driver does not support national
8610      *         character sets;  if the driver can detect that a data conversion
8611      *  error could occur; this method is called on a closed result set;
8612      *  if a database access error occurs or
8613      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8614      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8615      * this method
8616      * @since 1.6
8617      */
8618     public void updateNClob(String columnLabel,  Reader reader) throws SQLException {
8619         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8620     }
8621 
8622         /**
8623      * Updates the designated column with an ascii stream value, which will have
8624      * the specified number of bytes.
8625      * The updater methods are used to update column values in the
8626      * current row or the insert row.  The updater methods do not
8627      * update the underlying database; instead the <code>updateRow</code> or
8628      * <code>insertRow</code> methods are called to update the database.
8629      *
8630      * @param columnIndex the first column is 1, the second is 2, ...
8631      * @param x the new column value
8632      * @param length the length of the stream
8633      * @exception SQLException if a database access error occurs,
8634      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8635      * or this method is called on a closed result set
8636      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8637      * this method
8638      * @since 1.6
8639      */
8640     public void updateAsciiStream(int columnIndex,
8641                            java.io.InputStream x,
8642                            long length) throws SQLException {
8643 
8644     }
8645 
8646     /**
8647      * Updates the designated column with a binary stream value, which will have
8648      * the specified number of bytes.
8649      * The updater methods are used to update column values in the
8650      * current row or the insert row.  The updater methods do not
8651      * update the underlying database; instead the <code>updateRow</code> or
8652      * <code>insertRow</code> methods are called to update the database.
8653      *
8654      * @param columnIndex the first column is 1, the second is 2, ...
8655      * @param x the new column value
8656      * @param length the length of the stream
8657      * @exception SQLException if a database access error occurs,
8658      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8659      * or this method is called on a closed result set
8660      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8661      * this method
8662      * @since 1.6
8663      */
8664     public void updateBinaryStream(int columnIndex,
8665                             java.io.InputStream x,
8666                             long length) throws SQLException {
8667     }
8668 
8669     /**
8670      * Updates the designated column with a character stream value, which will have
8671      * the specified number of bytes.
8672      * The updater methods are used to update column values in the
8673      * current row or the insert row.  The updater methods do not
8674      * update the underlying database; instead the <code>updateRow</code> or
8675      * <code>insertRow</code> methods are called to update the database.
8676      *
8677      * @param columnIndex the first column is 1, the second is 2, ...
8678      * @param x the new column value
8679      * @param length the length of the stream
8680      * @exception SQLException if a database access error occurs,
8681      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8682      * or this method is called on a closed result set
8683      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8684      * this method
8685      * @since 1.6
8686      */
8687     public void updateCharacterStream(int columnIndex,
8688                              java.io.Reader x,
8689                              long length) throws SQLException {
8690         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8691     }
8692 
8693     /**
8694      * Updates the designated column with a character stream value, which will have
8695      * the specified number of bytes.
8696      * The updater methods are used to update column values in the
8697      * current row or the insert row.  The updater methods do not
8698      * update the underlying database; instead the <code>updateRow</code> or
8699      * <code>insertRow</code> methods are called to update the database.
8700      *
8701      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8702 bel is the name of the column
8703      * @param reader the <code>java.io.Reader</code> object containing
8704      *        the new column value
8705      * @param length the length of the stream
8706      * @exception SQLException if a database access error occurs,
8707      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8708      * or this method is called on a closed result set
8709      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8710      * this method
8711      * @since 1.6
8712      */
8713     public void updateCharacterStream(String columnLabel,
8714                              java.io.Reader reader,
8715                              long length) throws SQLException {
8716         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8717     }
8718      /**
8719      * Updates the designated column with an ascii stream value, which will have
8720      * the specified number of bytes..
8721      * The updater methods are used to update column values in the
8722      * current row or the insert row.  The updater methods do not
8723      * update the underlying database; instead the <code>updateRow</code> or
8724      * <code>insertRow</code> methods are called to update the database.
8725      *
8726      * @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
8727      * @param x the new column value
8728      * @param length the length of the stream
8729      * @exception SQLException if a database access error occurs,
8730      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8731      * or this method is called on a closed result set
8732      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8733      * this method
8734      * @since 1.6
8735      */
8736     public void updateAsciiStream(String columnLabel,
8737                            java.io.InputStream x,
8738                            long length) throws SQLException {
8739     }
8740 
8741     /**
8742      * Updates the designated column with a binary stream value, which will have
8743      * the specified number of bytes.
8744      * The updater methods are used to update column values in the
8745      * current row or the insert row.  The updater methods do not
8746      * update the underlying database; instead the <code>updateRow</code> or
8747      * <code>insertRow</code> methods are called to update the database.
8748      *
8749      * @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
8750      * @param x the new column value
8751      * @param length the length of the stream
8752      * @exception SQLException if a database access error occurs,
8753      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8754      * or this method is called on a closed result set
8755      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8756      * this method
8757      * @since 1.6
8758      */
8759     public void updateBinaryStream(String columnLabel,
8760                             java.io.InputStream x,
8761                             long length) throws SQLException {
8762     }
8763 
8764     /**
8765      * Updates the designated column with a binary stream value.
8766      * The updater methods are used to update column values in the
8767      * current row or the insert row.  The updater methods do not
8768      * update the underlying database; instead the <code>updateRow</code> or
8769      * <code>insertRow</code> methods are called to update the database.
8770      *
8771      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8772      * it might be more efficient to use a version of
8773      * <code>updateBinaryStream</code> which takes a length parameter.
8774      *
8775      * @param columnIndex the first column is 1, the second is 2, ...
8776      * @param x the new column value
8777      * @exception SQLException if a database access error occurs,
8778      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8779      * or this method is called on a closed result set
8780      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8781      * this method
8782      * @since 1.6
8783      */
8784     public void updateBinaryStream(int columnIndex,
8785                             java.io.InputStream x) throws SQLException {
8786         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8787     }
8788 
8789 
8790     /**
8791      * Updates the designated column with a binary stream value.
8792      * The updater methods are used to update column values in the
8793      * current row or the insert row.  The updater methods do not
8794      * update the underlying database; instead the <code>updateRow</code> or
8795      * <code>insertRow</code> methods are called to update the database.
8796      *
8797      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8798      * it might be more efficient to use a version of
8799      * <code>updateBinaryStream</code> which takes a length parameter.
8800      *
8801      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8802 bel is the name of the column
8803      * @param x the new column value
8804      * @exception SQLException if a database access error occurs,
8805      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8806      * or this method is called on a closed result set
8807      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8808      * this method
8809      * @since 1.6
8810      */
8811     public void updateBinaryStream(String columnLabel,
8812                             java.io.InputStream x) throws SQLException {
8813         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8814     }
8815 
8816     /**
8817      * Updates the designated column with a character stream value.
8818      * The updater methods are used to update column values in the
8819      * current row or the insert row.  The updater methods do not
8820      * update the underlying database; instead the <code>updateRow</code> or
8821      * <code>insertRow</code> methods are called to update the database.
8822      *
8823      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8824      * it might be more efficient to use a version of
8825      * <code>updateCharacterStream</code> which takes a length parameter.
8826      *
8827      * @param columnIndex the first column is 1, the second is 2, ...
8828      * @param x the new column value
8829      * @exception SQLException if a database access error occurs,
8830      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8831      * or this method is called on a closed result set
8832      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8833      * this method
8834      * @since 1.6
8835      */
8836     public void updateCharacterStream(int columnIndex,
8837                              java.io.Reader x) throws SQLException {
8838         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8839     }
8840 
8841     /**
8842      * Updates the designated column with a character stream value.
8843      * The updater methods are used to update column values in the
8844      * current row or the insert row.  The updater methods do not
8845      * update the underlying database; instead the <code>updateRow</code> or
8846      * <code>insertRow</code> methods are called to update the database.
8847      *
8848      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8849      * it might be more efficient to use a version of
8850      * <code>updateCharacterStream</code> which takes a length parameter.
8851      *
8852      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8853 bel is the name of the column
8854      * @param reader the <code>java.io.Reader</code> object containing
8855      *        the new column value
8856      * @exception SQLException if a database access error occurs,
8857      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8858      * or this method is called on a closed result set
8859      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8860      * this method
8861      * @since 1.6
8862      */
8863     public void updateCharacterStream(String columnLabel,
8864                              java.io.Reader reader) throws SQLException {
8865         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8866     }
8867 
8868     /**
8869      * Updates the designated column with an ascii stream value.
8870      * The updater methods are used to update column values in the
8871      * current row or the insert row.  The updater methods do not
8872      * update the underlying database; instead the <code>updateRow</code> or
8873      * <code>insertRow</code> methods are called to update the database.
8874      *
8875      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8876      * it might be more efficient to use a version of
8877      * <code>updateAsciiStream</code> which takes a length parameter.
8878      *
8879      * @param columnIndex the first column is 1, the second is 2, ...
8880      * @param x the new column value
8881      * @exception SQLException if a database access error occurs,
8882      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8883      * or this method is called on a closed result set
8884      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8885      * this method
8886      * @since 1.6
8887      */
8888     public void updateAsciiStream(int columnIndex,
8889                            java.io.InputStream x) throws SQLException {
8890         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8891     }
8892 
8893     /**
8894      * Updates the designated column with an ascii stream value.
8895      * The updater methods are used to update column values in the
8896      * current row or the insert row.  The updater methods do not
8897      * update the underlying database; instead the <code>updateRow</code> or
8898      * <code>insertRow</code> methods are called to update the database.
8899      *
8900      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8901      * it might be more efficient to use a version of
8902      * <code>updateAsciiStream</code> which takes a length parameter.
8903      *
8904      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8905 bel is the name of the column
8906      * @param x the new column value
8907      * @exception SQLException if a database access error occurs,
8908      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8909      * or this method is called on a closed result set
8910      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8911      * this method
8912      * @since 1.6
8913      */
8914     public void updateAsciiStream(String columnLabel,
8915                            java.io.InputStream x) throws SQLException {
8916 
8917     }
8918 
8919    /**
8920   * Sets the designated parameter to the given <code>java.net.URL</code> value.
8921   * The driver converts this to an SQL <code>DATALINK</code> value
8922   * when it sends it to the database.
8923   *
8924   * @param parameterIndex the first parameter is 1, the second is 2, ...
8925   * @param x the <code>java.net.URL</code> object to be set
8926   * @exception SQLException if a database access error occurs or
8927   * this method is called on a closed <code>PreparedStatement</code>
8928   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
8929   * @since 1.4
8930   */
8931   public void setURL(int parameterIndex, java.net.URL x) throws SQLException{
8932         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8933    }
8934 
8935   /**
8936   * Sets the designated parameter to a <code>Reader</code> object.
8937   * This method differs from the <code>setCharacterStream (int, Reader)</code> method
8938   * because it informs the driver that the parameter value should be sent to
8939   * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
8940   * driver may have to do extra work to determine whether the parameter
8941   * data should be sent to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
8942   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8943   * it might be more efficient to use a version of
8944   * <code>setNClob</code> which takes a length parameter.
8945   *
8946   * @param parameterIndex index of the first parameter is 1, the second is 2, ...
8947   * @param reader An object that contains the data to set the parameter value to.
8948   * @throws SQLException if parameterIndex does not correspond to a parameter
8949   * marker in the SQL statement;
8950   * if the driver does not support national character sets;
8951   * if the driver can detect that a data conversion
8952   *  error could occur;  if a database access error occurs or
8953   * this method is called on a closed <code>PreparedStatement</code>
8954   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
8955   *
8956   * @since 1.6
8957   */
8958   public void setNClob(int parameterIndex, Reader reader)
8959     throws SQLException{
8960         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8961    }
8962 
8963   /**
8964   * Sets the designated parameter to a <code>Reader</code> object.  The <code>reader</code> must contain  the number
8965              * of characters specified by length otherwise a <code>SQLException</code> will be
8966             * generated when the <code>CallableStatement</code> is executed.
8967             * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
8968             * because it informs the driver that the parameter value should be sent to
8969             * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
8970             * driver may have to do extra work to determine whether the parameter
8971             * data should be send to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
8972             *
8973             * @param parameterName the name of the parameter to be set
8974             * @param reader An object that contains the data to set the parameter value to.
8975             * @param length the number of characters in the parameter data.
8976             * @throws SQLException if parameterIndex does not correspond to a parameter
8977             * marker in the SQL statement; if the length specified is less than zero;
8978             * if the driver does not support national
8979             *         character sets;  if the driver can detect that a data conversion
8980             *  error could occur; if a database access error occurs or
8981             * this method is called on a closed <code>CallableStatement</code>
8982             * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8983             * this method
8984             * @since 1.6
8985             */
8986             public void setNClob(String parameterName, Reader reader, long length)
8987     throws SQLException{
8988         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8989    }
8990 
8991 
8992  /**
8993   * Sets the designated parameter to a <code>Reader</code> object.
8994   * This method differs from the <code>setCharacterStream (int, Reader)</code> method
8995   * because it informs the driver that the parameter value should be sent to
8996   * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
8997   * driver may have to do extra work to determine whether the parameter
8998   * data should be send to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
8999   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9000   * it might be more efficient to use a version of
9001   * <code>setNClob</code> which takes a length parameter.
9002   *
9003   * @param parameterName the name of the parameter
9004   * @param reader An object that contains the data to set the parameter value to.
9005   * @throws SQLException if the driver does not support national character sets;
9006   * if the driver can detect that a data conversion
9007   *  error could occur;  if a database access error occurs or
9008   * this method is called on a closed <code>CallableStatement</code>
9009   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9010   *
9011   * @since 1.6
9012   */
9013   public void setNClob(String parameterName, Reader reader)
9014     throws SQLException{
9015         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9016    }
9017 
9018 
9019     /**
9020      * Sets the designated parameter to a <code>Reader</code> object.  The reader must contain  the number
9021      * of characters specified by length otherwise a <code>SQLException</code> will be
9022      * generated when the <code>PreparedStatement</code> is executed.
9023      * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
9024      * because it informs the driver that the parameter value should be sent to
9025      * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9026      * driver may have to do extra work to determine whether the parameter
9027      * data should be sent to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
9028      * @param parameterIndex index of the first parameter is 1, the second is 2, ...
9029      * @param reader An object that contains the data to set the parameter value to.
9030      * @param length the number of characters in the parameter data.
9031      * @throws SQLException if parameterIndex does not correspond to a parameter
9032      * marker in the SQL statement; if the length specified is less than zero;
9033      * if the driver does not support national character sets;
9034      * if the driver can detect that a data conversion
9035      *  error could occur;  if a database access error occurs or
9036      * this method is called on a closed <code>PreparedStatement</code>
9037      * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9038      *
9039      * @since 1.6
9040      */
9041      public void setNClob(int parameterIndex, Reader reader, long length)
9042        throws SQLException{
9043         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9044    }
9045 
9046 
9047     /**
9048      * Sets the designated parameter to a <code>java.sql.NClob</code> object. The driver converts this to
9049 a
9050      * SQL <code>NCLOB</code> value when it sends it to the database.
9051      * @param parameterIndex of the first parameter is 1, the second is 2, ...
9052      * @param value the parameter value
9053      * @throws SQLException if the driver does not support national
9054      *         character sets;  if the driver can detect that a data conversion
9055      *  error could occur ; or if a database access error occurs
9056      * @since 1.6
9057      */
9058      public void setNClob(int parameterIndex, NClob value) throws SQLException{
9059         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9060    }
9061 
9062 
9063    /**
9064   * Sets the designated parameter to the given <code>String</code> object.
9065   * The driver converts this to a SQL <code>NCHAR</code> or
9066   * <code>NVARCHAR</code> or <code>LONGNVARCHAR</code> value
9067   * (depending on the argument's
9068   * size relative to the driver's limits on <code>NVARCHAR</code> values)
9069   * when it sends it to the database.
9070   *
9071   * @param parameterIndex of the first parameter is 1, the second is 2, ...
9072   * @param value the parameter value
9073   * @throws SQLException if the driver does not support national
9074   *         character sets;  if the driver can detect that a data conversion
9075   *  error could occur ; or if a database access error occurs
9076   * @since 1.6
9077   */
9078   public void setNString(int parameterIndex, String value) throws SQLException{
9079         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9080    }
9081 
9082 
9083  /**
9084   * Sets the designated parameter to the given <code>String</code> object.
9085   * The driver converts this to a SQL <code>NCHAR</code> or
9086   * <code>NVARCHAR</code> or <code>LONGNVARCHAR</code>
9087   * @param parameterName the name of the column to be set
9088   * @param value the parameter value
9089   * @throws SQLException if the driver does not support national
9090   *         character sets;  if the driver can detect that a data conversion
9091   *  error could occur; or if a database access error occurs
9092   * @since 1.6
9093   */
9094  public void setNString(String parameterName, String value)
9095          throws SQLException{
9096         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9097    }
9098 
9099 
9100  /**
9101   * Sets the designated parameter to a <code>Reader</code> object. The
9102   * <code>Reader</code> reads the data till end-of-file is reached. The
9103   * driver does the necessary conversion from Java character format to
9104   * the national character set in the database.
9105   * @param parameterIndex of the first parameter is 1, the second is 2, ...
9106   * @param value the parameter value
9107   * @param length the number of characters in the parameter data.
9108   * @throws SQLException if the driver does not support national
9109   *         character sets;  if the driver can detect that a data conversion
9110   *  error could occur ; or if a database access error occurs
9111   * @since 1.6
9112   */
9113   public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException{
9114         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9115    }
9116 
9117 
9118  /**
9119   * Sets the designated parameter to a <code>Reader</code> object. The
9120   * <code>Reader</code> reads the data till end-of-file is reached. The
9121   * driver does the necessary conversion from Java character format to
9122   * the national character set in the database.
9123   * @param parameterName the name of the column to be set
9124   * @param value the parameter value
9125   * @param length the number of characters in the parameter data.
9126   * @throws SQLException if the driver does not support national
9127   *         character sets;  if the driver can detect that a data conversion
9128   *  error could occur; or if a database access error occurs
9129   * @since 1.6
9130   */
9131  public void setNCharacterStream(String parameterName, Reader value, long length)
9132          throws SQLException{
9133         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9134    }
9135 
9136   /**
9137   * Sets the designated parameter to a <code>Reader</code> object. The
9138   * <code>Reader</code> reads the data till end-of-file is reached. The
9139   * driver does the necessary conversion from Java character format to
9140   * the national character set in the database.
9141 
9142   * <P><B>Note:</B> This stream object can either be a standard
9143   * Java stream object or your own subclass that implements the
9144   * standard interface.
9145   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9146   * it might be more efficient to use a version of
9147   * <code>setNCharacterStream</code> which takes a length parameter.
9148   *
9149   * @param parameterName the name of the parameter
9150   * @param value the parameter value
9151   * @throws SQLException if the driver does not support national
9152   *         character sets;  if the driver can detect that a data conversion
9153   *  error could occur ; if a database access error occurs; or
9154   * this method is called on a closed <code>CallableStatement</code>
9155   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9156   * @since 1.6
9157   */
9158   public void setNCharacterStream(String parameterName, Reader value) throws SQLException{
9159         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9160    }
9161 
9162   /**
9163     * Sets the designated parameter to the given <code>java.sql.Timestamp</code> value,
9164     * using the given <code>Calendar</code> object.  The driver uses
9165     * the <code>Calendar</code> object to construct an SQL <code>TIMESTAMP</code> value,
9166     * which the driver then sends to the database.  With a
9167     * a <code>Calendar</code> object, the driver can calculate the timestamp
9168     * taking into account a custom timezone.  If no
9169     * <code>Calendar</code> object is specified, the driver uses the default
9170     * timezone, which is that of the virtual machine running the application.
9171     *
9172     * @param parameterName the name of the parameter
9173     * @param x the parameter value
9174     * @param cal the <code>Calendar</code> object the driver will use
9175     *            to construct the timestamp
9176     * @exception SQLException if a database access error occurs or
9177     * this method is called on a closed <code>CallableStatement</code>
9178     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9179     * this method
9180     * @see #getTimestamp
9181     * @since 1.4
9182     */
9183     public void setTimestamp(String parameterName, java.sql.Timestamp x, Calendar cal)
9184        throws SQLException{
9185         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9186    }
9187 
9188     /**
9189     * Sets the designated parameter to a <code>Reader</code> object.  The <code>reader</code> must contain  the number
9190                * of characters specified by length otherwise a <code>SQLException</code> will be
9191                * generated when the <code>CallableStatement</code> is executed.
9192               * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
9193               * because it informs the driver that the parameter value should be sent to
9194               * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9195               * driver may have to do extra work to determine whether the parameter
9196               * data should be send to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9197               * @param parameterName the name of the parameter to be set
9198               * @param reader An object that contains the data to set the parameter value to.
9199               * @param length the number of characters in the parameter data.
9200               * @throws SQLException if parameterIndex does not correspond to a parameter
9201               * marker in the SQL statement; if the length specified is less than zero;
9202               * a database access error occurs or
9203               * this method is called on a closed <code>CallableStatement</code>
9204               * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9205               * this method
9206               *
9207               * @since 1.6
9208               */
9209       public  void setClob(String parameterName, Reader reader, long length)
9210       throws SQLException{
9211         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9212    }
9213 
9214 
9215   /**
9216     * Sets the designated parameter to the given <code>java.sql.Clob</code> object.
9217     * The driver converts this to an SQL <code>CLOB</code> value when it
9218     * sends it to the database.
9219     *
9220     * @param parameterName the name of the parameter
9221     * @param x a <code>Clob</code> object that maps an SQL <code>CLOB</code> value
9222     * @exception SQLException if a database access error occurs or
9223     * this method is called on a closed <code>CallableStatement</code>
9224     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9225     * this method
9226     * @since 1.6
9227     */
9228     public void setClob (String parameterName, Clob x) throws SQLException{
9229         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9230    }
9231 
9232 
9233  /**
9234     * Sets the designated parameter to a <code>Reader</code> object.
9235     * This method differs from the <code>setCharacterStream (int, Reader)</code> method
9236     * because it informs the driver that the parameter value should be sent to
9237     * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9238     * driver may have to do extra work to determine whether the parameter
9239     * data should be send to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9240     *
9241     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9242     * it might be more efficient to use a version of
9243     * <code>setClob</code> which takes a length parameter.
9244     *
9245     * @param parameterName the name of the parameter
9246     * @param reader An object that contains the data to set the parameter value to.
9247     * @throws SQLException if a database access error occurs or this method is called on
9248     * a closed <code>CallableStatement</code>
9249     *
9250     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9251     * @since 1.6
9252     */
9253     public void setClob(String parameterName, Reader reader)
9254       throws SQLException{
9255         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9256    }
9257 
9258 
9259  /**
9260     * Sets the designated parameter to the given <code>java.sql.Date</code> value
9261     * using the default time zone of the virtual machine that is running
9262     * the application.
9263     * The driver converts this
9264     * to an SQL <code>DATE</code> value when it sends it to the database.
9265     *
9266     * @param parameterName the name of the parameter
9267     * @param x the parameter value
9268     * @exception SQLException if a database access error occurs or
9269     * this method is called on a closed <code>CallableStatement</code>
9270     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9271     * this method
9272     * @see #getDate
9273     * @since 1.4
9274     */
9275     public void setDate(String parameterName, java.sql.Date x)
9276        throws SQLException{
9277         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9278    }
9279 
9280 
9281  /**
9282     * Sets the designated parameter to the given <code>java.sql.Date</code> value,
9283     * using the given <code>Calendar</code> object.  The driver uses
9284     * the <code>Calendar</code> object to construct an SQL <code>DATE</code> value,
9285     * which the driver then sends to the database.  With a
9286     * a <code>Calendar</code> object, the driver can calculate the date
9287     * taking into account a custom timezone.  If no
9288     * <code>Calendar</code> object is specified, the driver uses the default
9289     * timezone, which is that of the virtual machine running the application.
9290     *
9291     * @param parameterName the name of the parameter
9292     * @param x the parameter value
9293     * @param cal the <code>Calendar</code> object the driver will use
9294     *            to construct the date
9295     * @exception SQLException if a database access error occurs or
9296     * this method is called on a closed <code>CallableStatement</code>
9297     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9298     * this method
9299     * @see #getDate
9300     * @since 1.4
9301     */
9302    public void setDate(String parameterName, java.sql.Date x, Calendar cal)
9303        throws SQLException{
9304         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9305    }
9306 
9307 
9308  /**
9309     * Sets the designated parameter to the given <code>java.sql.Time</code> value.
9310     * The driver converts this
9311     * to an SQL <code>TIME</code> value when it sends it to the database.
9312     *
9313     * @param parameterName the name of the parameter
9314     * @param x the parameter value
9315     * @exception SQLException if a database access error occurs or
9316     * this method is called on a closed <code>CallableStatement</code>
9317     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9318     * this method
9319     * @see #getTime
9320     * @since 1.4
9321     */
9322    public void setTime(String parameterName, java.sql.Time x)
9323        throws SQLException{
9324         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9325    }
9326 
9327 
9328  /**
9329     * Sets the designated parameter to the given <code>java.sql.Time</code> value,
9330     * using the given <code>Calendar</code> object.  The driver uses
9331     * the <code>Calendar</code> object to construct an SQL <code>TIME</code> value,
9332     * which the driver then sends to the database.  With a
9333     * a <code>Calendar</code> object, the driver can calculate the time
9334     * taking into account a custom timezone.  If no
9335     * <code>Calendar</code> object is specified, the driver uses the default
9336     * timezone, which is that of the virtual machine running the application.
9337     *
9338     * @param parameterName the name of the parameter
9339     * @param x the parameter value
9340     * @param cal the <code>Calendar</code> object the driver will use
9341     *            to construct the time
9342     * @exception SQLException if a database access error occurs or
9343     * this method is called on a closed <code>CallableStatement</code>
9344     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9345     * this method
9346     * @see #getTime
9347     * @since 1.4
9348     */
9349    public void setTime(String parameterName, java.sql.Time x, Calendar cal)
9350        throws SQLException{
9351         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9352    }
9353 
9354    /**
9355    * Sets the designated parameter to a <code>Reader</code> object.
9356    * This method differs from the <code>setCharacterStream (int, Reader)</code> method
9357    * because it informs the driver that the parameter value should be sent to
9358    * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9359    * driver may have to do extra work to determine whether the parameter
9360    * data should be sent to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9361    *
9362    * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9363    * it might be more efficient to use a version of
9364    * <code>setClob</code> which takes a length parameter.
9365    *
9366    * @param parameterIndex index of the first parameter is 1, the second is 2, ...
9367    * @param reader An object that contains the data to set the parameter value to.
9368    * @throws SQLException if a database access error occurs, this method is called on
9369    * a closed <code>PreparedStatement</code>or if parameterIndex does not correspond to a parameter
9370    * marker in the SQL statement
9371    *
9372    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9373    * @since 1.6
9374    */
9375    public void setClob(int parameterIndex, Reader reader)
9376      throws SQLException{
9377         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9378    }
9379 
9380     /**
9381    * Sets the designated parameter to a <code>Reader</code> object.  The reader must contain  the number
9382    * of characters specified by length otherwise a <code>SQLException</code> will be
9383    * generated when the <code>PreparedStatement</code> is executed.
9384    *This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
9385    * because it informs the driver that the parameter value should be sent to
9386    * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9387    * driver may have to do extra work to determine whether the parameter
9388    * data should be sent to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9389    * @param parameterIndex index of the first parameter is 1, the second is 2, ...
9390    * @param reader An object that contains the data to set the parameter value to.
9391    * @param length the number of characters in the parameter data.
9392    * @throws SQLException if a database access error occurs, this method is called on
9393    * a closed <code>PreparedStatement</code>, if parameterIndex does not correspond to a parameter
9394    * marker in the SQL statement, or if the length specified is less than zero.
9395    *
9396    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9397    * @since 1.6
9398    */
9399    public void setClob(int parameterIndex, Reader reader, long length)
9400      throws SQLException{
9401         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9402    }
9403 
9404 
9405  /**
9406     * Sets the designated parameter to a <code>InputStream</code> object.  The inputstream must contain  the number
9407     * of characters specified by length otherwise a <code>SQLException</code> will be
9408     * generated when the <code>PreparedStatement</code> is executed.
9409     * This method differs from the <code>setBinaryStream (int, InputStream, int)</code>
9410     * method because it informs the driver that the parameter value should be
9411     * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9412     * the driver may have to do extra work to determine whether the parameter
9413     * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9414     * @param parameterIndex index of the first parameter is 1,
9415     * the second is 2, ...
9416     * @param inputStream An object that contains the data to set the parameter
9417     * value to.
9418     * @param length the number of bytes in the parameter data.
9419     * @throws SQLException if a database access error occurs,
9420     * this method is called on a closed <code>PreparedStatement</code>,
9421     * if parameterIndex does not correspond
9422     * to a parameter marker in the SQL statement,  if the length specified
9423     * is less than zero or if the number of bytes in the inputstream does not match
9424     * the specified length.
9425     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9426     *
9427     * @since 1.6
9428     */
9429     public void setBlob(int parameterIndex, InputStream inputStream, long length)
9430        throws SQLException{
9431         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9432    }
9433 
9434 
9435  /**
9436     * Sets the designated parameter to a <code>InputStream</code> object.
9437     * This method differs from the <code>setBinaryStream (int, InputStream)</code>
9438     * method because it informs the driver that the parameter value should be
9439     * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9440     * the driver may have to do extra work to determine whether the parameter
9441     * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9442     *
9443     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9444     * it might be more efficient to use a version of
9445     * <code>setBlob</code> which takes a length parameter.
9446     *
9447     * @param parameterIndex index of the first parameter is 1,
9448     * the second is 2, ...
9449     * @param inputStream An object that contains the data to set the parameter
9450     * value to.
9451     * @throws SQLException if a database access error occurs,
9452     * this method is called on a closed <code>PreparedStatement</code> or
9453     * if parameterIndex does not correspond
9454     * to a parameter marker in the SQL statement,
9455     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9456     *
9457     * @since 1.6
9458     */
9459     public void setBlob(int parameterIndex, InputStream inputStream)
9460        throws SQLException{
9461         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9462    }
9463 
9464 
9465  /**
9466     * Sets the designated parameter to a <code>InputStream</code> object.  The <code>inputstream</code> must contain  the number
9467      * of characters specified by length, otherwise a <code>SQLException</code> will be
9468      * generated when the <code>CallableStatement</code> is executed.
9469      * This method differs from the <code>setBinaryStream (int, InputStream, int)</code>
9470      * method because it informs the driver that the parameter value should be
9471      * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9472      * the driver may have to do extra work to determine whether the parameter
9473      * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9474      *
9475      * @param parameterName the name of the parameter to be set
9476      * the second is 2, ...
9477      *
9478      * @param inputStream An object that contains the data to set the parameter
9479      * value to.
9480      * @param length the number of bytes in the parameter data.
9481      * @throws SQLException  if parameterIndex does not correspond
9482      * to a parameter marker in the SQL statement,  or if the length specified
9483      * is less than zero; if the number of bytes in the inputstream does not match
9484      * the specified length; if a database access error occurs or
9485      * this method is called on a closed <code>CallableStatement</code>
9486      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9487      * this method
9488      *
9489      * @since 1.6
9490      */
9491      public void setBlob(String parameterName, InputStream inputStream, long length)
9492         throws SQLException{
9493         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9494    }
9495 
9496 
9497  /**
9498     * Sets the designated parameter to the given <code>java.sql.Blob</code> object.
9499     * The driver converts this to an SQL <code>BLOB</code> value when it
9500     * sends it to the database.
9501     *
9502     * @param parameterName the name of the parameter
9503     * @param x a <code>Blob</code> object that maps an SQL <code>BLOB</code> value
9504     * @exception SQLException if a database access error occurs or
9505     * this method is called on a closed <code>CallableStatement</code>
9506     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9507     * this method
9508     * @since 1.6
9509     */
9510    public void setBlob (String parameterName, Blob x) throws SQLException{
9511         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9512    }
9513 
9514 
9515  /**
9516     * Sets the designated parameter to a <code>InputStream</code> object.
9517     * This method differs from the <code>setBinaryStream (int, InputStream)</code>
9518     * method because it informs the driver that the parameter value should be
9519     * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9520     * the driver may have to do extra work to determine whether the parameter
9521     * data should be send to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9522     *
9523     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9524     * it might be more efficient to use a version of
9525     * <code>setBlob</code> which takes a length parameter.
9526     *
9527     * @param parameterName the name of the parameter
9528     * @param inputStream An object that contains the data to set the parameter
9529     * value to.
9530     * @throws SQLException if a database access error occurs or
9531     * this method is called on a closed <code>CallableStatement</code>
9532     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9533     *
9534     * @since 1.6
9535     */
9536     public void setBlob(String parameterName, InputStream inputStream)
9537        throws SQLException{
9538         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9539    }
9540 
9541     /**
9542     * Sets the value of the designated parameter with the given object. The second
9543     * argument must be an object type; for integral values, the
9544     * <code>java.lang</code> equivalent objects should be used.
9545     *
9546     * <p>The given Java object will be converted to the given targetSqlType
9547     * before being sent to the database.
9548     *
9549     * If the object has a custom mapping (is of a class implementing the
9550     * interface <code>SQLData</code>),
9551     * the JDBC driver should call the method <code>SQLData.writeSQL</code> to write it
9552     * to the SQL data stream.
9553     * If, on the other hand, the object is of a class implementing
9554     * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>,  <code>NClob</code>,
9555     *  <code>Struct</code>, <code>java.net.URL</code>,
9556     * or <code>Array</code>, the driver should pass it to the database as a
9557     * value of the corresponding SQL type.
9558     * <P>
9559     * Note that this method may be used to pass datatabase-
9560     * specific abstract data types.
9561     *
9562     * @param parameterName the name of the parameter
9563     * @param x the object containing the input parameter value
9564     * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
9565     * sent to the database. The scale argument may further qualify this type.
9566     * @param scale for java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types,
9567     *          this is the number of digits after the decimal point.  For all other
9568     *          types, this value will be ignored.
9569     * @exception SQLException if a database access error occurs or
9570     * this method is called on a closed <code>CallableStatement</code>
9571     * @exception SQLFeatureNotSupportedException if <code>targetSqlType</code> is
9572     * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,
9573     * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,
9574     * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,
9575     *  <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
9576     * or  <code>STRUCT</code> data type and the JDBC driver does not support
9577     * this data type
9578     * @see Types
9579     * @see #getObject
9580     * @since 1.4
9581     */
9582     public void setObject(String parameterName, Object x, int targetSqlType, int scale)
9583        throws SQLException{
9584         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9585    }
9586 
9587 
9588 
9589  /**
9590     * Sets the value of the designated parameter with the given object.
9591     * This method is like the method <code>setObject</code>
9592     * above, except that it assumes a scale of zero.
9593     *
9594     * @param parameterName the name of the parameter
9595     * @param x the object containing the input parameter value
9596     * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
9597     *                      sent to the database
9598     * @exception SQLException if a database access error occurs or
9599     * this method is called on a closed <code>CallableStatement</code>
9600     * @exception SQLFeatureNotSupportedException if <code>targetSqlType</code> is
9601     * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,
9602     * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,
9603     * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,
9604     *  <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
9605     * or  <code>STRUCT</code> data type and the JDBC driver does not support
9606     * this data type
9607     * @see #getObject
9608     * @since 1.4
9609     */
9610     public void setObject(String parameterName, Object x, int targetSqlType)
9611        throws SQLException{
9612         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9613    }
9614 
9615 
9616  /**
9617    * Sets the value of the designated parameter with the given object.
9618    * The second parameter must be of type <code>Object</code>; therefore, the
9619    * <code>java.lang</code> equivalent objects should be used for built-in types.
9620    *
9621    * <p>The JDBC specification specifies a standard mapping from
9622    * Java <code>Object</code> types to SQL types.  The given argument
9623    * will be converted to the corresponding SQL type before being
9624    * sent to the database.
9625    *
9626    * <p>Note that this method may be used to pass datatabase-
9627    * specific abstract data types, by using a driver-specific Java
9628    * type.
9629    *
9630    * If the object is of a class implementing the interface <code>SQLData</code>,
9631    * the JDBC driver should call the method <code>SQLData.writeSQL</code>
9632    * to write it to the SQL data stream.
9633    * If, on the other hand, the object is of a class implementing
9634    * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>,  <code>NClob</code>,
9635    *  <code>Struct</code>, <code>java.net.URL</code>,
9636    * or <code>Array</code>, the driver should pass it to the database as a
9637    * value of the corresponding SQL type.
9638    * <P>
9639    * This method throws an exception if there is an ambiguity, for example, if the
9640    * object is of a class implementing more than one of the interfaces named above.
9641    *
9642    * @param parameterName the name of the parameter
9643    * @param x the object containing the input parameter value
9644    * @exception SQLException if a database access error occurs,
9645    * this method is called on a closed <code>CallableStatement</code> or if the given
9646    *            <code>Object</code> parameter is ambiguous
9647    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9648    * this method
9649    * @see #getObject
9650    * @since 1.4
9651    */
9652    public void setObject(String parameterName, Object x) throws SQLException{
9653         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9654    }
9655 
9656     /**
9657     * Sets the designated parameter to the given input stream, which will have
9658     * the specified number of bytes.
9659     * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
9660     * parameter, it may be more practical to send it via a
9661     * <code>java.io.InputStream</code>. Data will be read from the stream
9662     * as needed until end-of-file is reached.  The JDBC driver will
9663     * do any necessary conversion from ASCII to the database char format.
9664     *
9665     * <P><B>Note:</B> This stream object can either be a standard
9666     * Java stream object or your own subclass that implements the
9667     * standard interface.
9668     *
9669     * @param parameterName the name of the parameter
9670     * @param x the Java input stream that contains the ASCII parameter value
9671     * @param length the number of bytes in the stream
9672     * @exception SQLException if a database access error occurs or
9673     * this method is called on a closed <code>CallableStatement</code>
9674     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9675     * this method
9676     * @since 1.4
9677     */
9678    public void setAsciiStream(String parameterName, java.io.InputStream x, int length)
9679        throws SQLException{
9680         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9681    }
9682 
9683 
9684  /**
9685     * Sets the designated parameter to the given input stream, which will have
9686     * the specified number of bytes.
9687     * When a very large binary value is input to a <code>LONGVARBINARY</code>
9688     * parameter, it may be more practical to send it via a
9689     * <code>java.io.InputStream</code> object. The data will be read from the stream
9690     * as needed until end-of-file is reached.
9691     *
9692     * <P><B>Note:</B> This stream object can either be a standard
9693     * Java stream object or your own subclass that implements the
9694     * standard interface.
9695     *
9696     * @param parameterName the name of the parameter
9697     * @param x the java input stream which contains the binary parameter value
9698     * @param length the number of bytes in the stream
9699     * @exception SQLException if a database access error occurs or
9700     * this method is called on a closed <code>CallableStatement</code>
9701     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9702     * this method
9703     * @since 1.4
9704     */
9705    public void setBinaryStream(String parameterName, java.io.InputStream x,
9706                         int length) throws SQLException{
9707         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9708    }
9709 
9710 
9711   /**
9712     * Sets the designated parameter to the given <code>Reader</code>
9713     * object, which is the given number of characters long.
9714     * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
9715     * parameter, it may be more practical to send it via a
9716     * <code>java.io.Reader</code> object. The data will be read from the stream
9717     * as needed until end-of-file is reached.  The JDBC driver will
9718     * do any necessary conversion from UNICODE to the database char format.
9719     *
9720     * <P><B>Note:</B> This stream object can either be a standard
9721     * Java stream object or your own subclass that implements the
9722     * standard interface.
9723     *
9724     * @param parameterName the name of the parameter
9725     * @param reader the <code>java.io.Reader</code> object that
9726     *        contains the UNICODE data used as the designated parameter
9727     * @param length the number of characters in the stream
9728     * @exception SQLException if a database access error occurs or
9729     * this method is called on a closed <code>CallableStatement</code>
9730     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9731     * this method
9732     * @since 1.4
9733     */
9734    public void setCharacterStream(String parameterName,
9735                            java.io.Reader reader,
9736                            int length) throws SQLException{
9737         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9738    }
9739 
9740 
9741   /**
9742    * Sets the designated parameter to the given input stream.
9743    * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
9744    * parameter, it may be more practical to send it via a
9745    * <code>java.io.InputStream</code>. Data will be read from the stream
9746    * as needed until end-of-file is reached.  The JDBC driver will
9747    * do any necessary conversion from ASCII to the database char format.
9748    *
9749    * <P><B>Note:</B> This stream object can either be a standard
9750    * Java stream object or your own subclass that implements the
9751    * standard interface.
9752    * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9753    * it might be more efficient to use a version of
9754    * <code>setAsciiStream</code> which takes a length parameter.
9755    *
9756    * @param parameterName the name of the parameter
9757    * @param x the Java input stream that contains the ASCII parameter value
9758    * @exception SQLException if a database access error occurs or
9759    * this method is called on a closed <code>CallableStatement</code>
9760    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9761      * @since 1.6
9762   */
9763   public void setAsciiStream(String parameterName, java.io.InputStream x)
9764           throws SQLException{
9765         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9766    }
9767 
9768 
9769  /**
9770     * Sets the designated parameter to the given input stream.
9771     * When a very large binary value is input to a <code>LONGVARBINARY</code>
9772     * parameter, it may be more practical to send it via a
9773     * <code>java.io.InputStream</code> object. The data will be read from the
9774     * stream as needed until end-of-file is reached.
9775     *
9776     * <P><B>Note:</B> This stream object can either be a standard
9777     * Java stream object or your own subclass that implements the
9778     * standard interface.
9779     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9780     * it might be more efficient to use a version of
9781     * <code>setBinaryStream</code> which takes a length parameter.
9782     *
9783     * @param parameterName the name of the parameter
9784     * @param x the java input stream which contains the binary parameter value
9785     * @exception SQLException if a database access error occurs or
9786     * this method is called on a closed <code>CallableStatement</code>
9787     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9788     * @since 1.6
9789     */
9790    public void setBinaryStream(String parameterName, java.io.InputStream x)
9791    throws SQLException{
9792         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9793    }
9794 
9795 
9796 
9797  /**
9798     * Sets the designated parameter to the given <code>Reader</code>
9799     * object.
9800     * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
9801     * parameter, it may be more practical to send it via a
9802     * <code>java.io.Reader</code> object. The data will be read from the stream
9803     * as needed until end-of-file is reached.  The JDBC driver will
9804     * do any necessary conversion from UNICODE to the database char format.
9805     *
9806     * <P><B>Note:</B> This stream object can either be a standard
9807     * Java stream object or your own subclass that implements the
9808     * standard interface.
9809     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9810     * it might be more efficient to use a version of
9811     * <code>setCharacterStream</code> which takes a length parameter.
9812     *
9813     * @param parameterName the name of the parameter
9814     * @param reader the <code>java.io.Reader</code> object that contains the
9815     *        Unicode data
9816     * @exception SQLException if a database access error occurs or
9817     * this method is called on a closed <code>CallableStatement</code>
9818     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9819     * @since 1.6
9820     */
9821    public void setCharacterStream(String parameterName,
9822                          java.io.Reader reader) throws SQLException{
9823         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9824    }
9825 
9826    /**
9827     * Sets the designated parameter to the given
9828     * <code>java.math.BigDecimal</code> value.
9829     * The driver converts this to an SQL <code>NUMERIC</code> value when
9830     * it sends it to the database.
9831     *
9832     * @param parameterName the name of the parameter
9833     * @param x the parameter value
9834     * @exception SQLException if a database access error occurs or
9835     * this method is called on a closed <code>CallableStatement</code>
9836     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9837     * this method
9838     * @see #getBigDecimal
9839     * @since 1.4
9840     */
9841    public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException{
9842         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9843    }
9844 
9845 
9846 
9847  /**
9848     * Sets the designated parameter to the given Java <code>String</code> value.
9849     * The driver converts this
9850     * to an SQL <code>VARCHAR</code> or <code>LONGVARCHAR</code> value
9851     * (depending on the argument's
9852     * size relative to the driver's limits on <code>VARCHAR</code> values)
9853     * when it sends it to the database.
9854     *
9855     * @param parameterName the name of the parameter
9856     * @param x the parameter value
9857     * @exception SQLException if a database access error occurs or
9858     * this method is called on a closed <code>CallableStatement</code>
9859     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9860     * this method
9861     * @see #getString
9862     * @since 1.4
9863     */
9864    public void setString(String parameterName, String x) throws SQLException{
9865         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9866    }
9867 
9868 
9869 
9870  /**
9871     * Sets the designated parameter to the given Java array of bytes.
9872     * The driver converts this to an SQL <code>VARBINARY</code> or
9873     * <code>LONGVARBINARY</code> (depending on the argument's size relative
9874     * to the driver's limits on <code>VARBINARY</code> values) when it sends
9875     * it to the database.
9876     *
9877     * @param parameterName the name of the parameter
9878     * @param x the parameter value
9879     * @exception SQLException if a database access error occurs or
9880     * this method is called on a closed <code>CallableStatement</code>
9881     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9882     * this method
9883     * @see #getBytes
9884     * @since 1.4
9885     */
9886    public void setBytes(String parameterName, byte x[]) throws SQLException{
9887         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9888    }
9889 
9890 
9891 
9892  /**
9893     * Sets the designated parameter to the given <code>java.sql.Timestamp</code> value.
9894     * The driver
9895     * converts this to an SQL <code>TIMESTAMP</code> value when it sends it to the
9896     * database.
9897     *
9898     * @param parameterName the name of the parameter
9899     * @param x the parameter value
9900     * @exception SQLException if a database access error occurs or
9901     * this method is called on a closed <code>CallableStatement</code>
9902     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9903     * this method
9904     * @see #getTimestamp
9905     * @since 1.4
9906     */
9907    public void setTimestamp(String parameterName, java.sql.Timestamp x)
9908        throws SQLException{
9909         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9910    }
9911 
9912     /**
9913     * Sets the designated parameter to SQL <code>NULL</code>.
9914     *
9915     * <P><B>Note:</B> You must specify the parameter's SQL type.
9916     *
9917     * @param parameterName the name of the parameter
9918     * @param sqlType the SQL type code defined in <code>java.sql.Types</code>
9919     * @exception SQLException if a database access error occurs or
9920     * this method is called on a closed <code>CallableStatement</code>
9921     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9922     * this method
9923     * @since 1.4
9924     */
9925    public void setNull(String parameterName, int sqlType) throws SQLException {
9926         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9927    }
9928 
9929 
9930  /**
9931     * Sets the designated parameter to SQL <code>NULL</code>.
9932     * This version of the method <code>setNull</code> should
9933     * be used for user-defined types and REF type parameters.  Examples
9934     * of user-defined types include: STRUCT, DISTINCT, JAVA_OBJECT, and
9935     * named array types.
9936     *
9937     * <P><B>Note:</B> To be portable, applications must give the
9938     * SQL type code and the fully-qualified SQL type name when specifying
9939     * a NULL user-defined or REF parameter.  In the case of a user-defined type
9940     * the name is the type name of the parameter itself.  For a REF
9941     * parameter, the name is the type name of the referenced type.  If
9942     * a JDBC driver does not need the type code or type name information,
9943     * it may ignore it.
9944     *
9945     * Although it is intended for user-defined and Ref parameters,
9946     * this method may be used to set a null parameter of any JDBC type.
9947     * If the parameter does not have a user-defined or REF type, the given
9948     * typeName is ignored.
9949     *
9950     *
9951     * @param parameterName the name of the parameter
9952     * @param sqlType a value from <code>java.sql.Types</code>
9953     * @param typeName the fully-qualified name of an SQL user-defined type;
9954     *        ignored if the parameter is not a user-defined type or
9955     *        SQL <code>REF</code> value
9956     * @exception SQLException if a database access error occurs or
9957     * this method is called on a closed <code>CallableStatement</code>
9958     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9959     * this method
9960     * @since 1.4
9961     */
9962    public void setNull (String parameterName, int sqlType, String typeName)
9963        throws SQLException{
9964         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9965    }
9966 
9967 
9968 
9969  /**
9970     * Sets the designated parameter to the given Java <code>boolean</code> value.
9971     * The driver converts this
9972     * to an SQL <code>BIT</code> or <code>BOOLEAN</code> value when it sends it to the database.
9973     *
9974     * @param parameterName the name of the parameter
9975     * @param x the parameter value
9976     * @exception SQLException if a database access error occurs or
9977     * this method is called on a closed <code>CallableStatement</code>
9978     * @see #getBoolean
9979     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9980     * this method
9981     * @since 1.4
9982     */
9983    public void setBoolean(String parameterName, boolean x) throws SQLException{
9984         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9985    }
9986 
9987 
9988 
9989  /**
9990     * Sets the designated parameter to the given Java <code>byte</code> value.
9991     * The driver converts this
9992     * to an SQL <code>TINYINT</code> value when it sends it to the database.
9993     *
9994     * @param parameterName the name of the parameter
9995     * @param x the parameter value
9996     * @exception SQLException if a database access error occurs or
9997     * this method is called on a closed <code>CallableStatement</code>
9998     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9999     * this method
10000     * @see #getByte
10001     * @since 1.4
10002     */
10003    public void setByte(String parameterName, byte x) throws SQLException{
10004         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10005    }
10006 
10007 
10008 
10009  /**
10010     * Sets the designated parameter to the given Java <code>short</code> value.
10011     * The driver converts this
10012     * to an SQL <code>SMALLINT</code> value when it sends it to the database.
10013     *
10014     * @param parameterName the name of the parameter
10015     * @param x the parameter value
10016     * @exception SQLException if a database access error occurs or
10017     * this method is called on a closed <code>CallableStatement</code>
10018     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10019     * this method
10020     * @see #getShort
10021     * @since 1.4
10022     */
10023    public void setShort(String parameterName, short x) throws SQLException{
10024         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10025    }
10026 
10027 
10028  /**
10029     * Sets the designated parameter to the given Java <code>int</code> value.
10030     * The driver converts this
10031     * to an SQL <code>INTEGER</code> value when it sends it to the database.
10032     *
10033     * @param parameterName the name of the parameter
10034     * @param x the parameter value
10035     * @exception SQLException if a database access error occurs or
10036     * this method is called on a closed <code>CallableStatement</code>
10037     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10038     * this method
10039     * @see #getInt
10040     * @since 1.4
10041     */
10042    public void setInt(String parameterName, int x) throws SQLException{
10043         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10044    }
10045 
10046 
10047  /**
10048     * Sets the designated parameter to the given Java <code>long</code> value.
10049     * The driver converts this
10050     * to an SQL <code>BIGINT</code> value when it sends it to the database.
10051     *
10052     * @param parameterName the name of the parameter
10053     * @param x the parameter value
10054     * @exception SQLException if a database access error occurs or
10055     * this method is called on a closed <code>CallableStatement</code>
10056     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10057     * this method
10058     * @see #getLong
10059     * @since 1.4
10060     */
10061    public void setLong(String parameterName, long x) throws SQLException{
10062         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10063    }
10064 
10065 
10066  /**
10067     * Sets the designated parameter to the given Java <code>float</code> value.
10068     * The driver converts this
10069     * to an SQL <code>FLOAT</code> value when it sends it to the database.
10070     *
10071     * @param parameterName the name of the parameter
10072     * @param x the parameter value
10073     * @exception SQLException if a database access error occurs or
10074     * this method is called on a closed <code>CallableStatement</code>
10075     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10076     * this method
10077     * @see #getFloat
10078     * @since 1.4
10079     */
10080    public void setFloat(String parameterName, float x) throws SQLException{
10081         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10082    }
10083 
10084 
10085  /**
10086     * Sets the designated parameter to the given Java <code>double</code> value.
10087     * The driver converts this
10088     * to an SQL <code>DOUBLE</code> value when it sends it to the database.
10089     *
10090     * @param parameterName the name of the parameter
10091     * @param x the parameter value
10092     * @exception SQLException if a database access error occurs or
10093     * this method is called on a closed <code>CallableStatement</code>
10094     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10095     * this method
10096     * @see #getDouble
10097     * @since 1.4
10098     */
10099    public void setDouble(String parameterName, double x) throws SQLException{
10100         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10101    }
10102 
10103    /**
10104      * This method re populates the resBundle
10105      * during the deserialization process
10106      *
10107      */
10108     private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
10109         // Default state initialization happens here
10110         ois.defaultReadObject();
10111         // Initialization of transient Res Bundle happens here .
10112         try {
10113            resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
10114         } catch(IOException ioe) {
10115             throw new RuntimeException(ioe);
10116         }
10117 
10118     }
10119 
10120     //------------------------- JDBC 4.1 -----------------------------------
10121     public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
10122         throw new SQLFeatureNotSupportedException("Not supported yet.");
10123     }
10124 
10125     public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
10126         throw new SQLFeatureNotSupportedException("Not supported yet.");
10127     }
10128 
10129     static final long serialVersionUID =1884577171200622428L;
10130 }