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