1 /*
   2  * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.rowset;
  27 
  28 import java.sql.*;
  29 import javax.sql.*;
  30 import java.io.*;
  31 import java.math.*;
  32 import java.util.*;
  33 import java.text.*;
  34 
  35 import javax.sql.rowset.*;
  36 import javax.sql.rowset.spi.*;
  37 import javax.sql.rowset.serial.*;
  38 import com.sun.rowset.internal.*;
  39 import com.sun.rowset.providers.*;
  40 
  41 /**
  42  * The standard implementation of the <code>CachedRowSet</code> interface.
  43  *
  44  * See interface defintion for full behaviour and implementation requirements.
  45  * This reference implementation has made provision for a one-to-one write back
  46  * facility and it is curremtly be possible to change the peristence provider
  47  * during the life-time of any CachedRowSetImpl.
  48  *
  49  * @author Jonathan Bruce, Amit Handa
  50  */
  51 
  52 public class CachedRowSetImpl extends BaseRowSet implements RowSet, RowSetInternal, Serializable, Cloneable, CachedRowSet {
  53 
  54     /**
  55      * The <code>SyncProvider</code> used by the CachedRowSet
  56      */
  57     private SyncProvider provider;
  58 
  59     /**
  60      * The <code>RowSetReaderImpl</code> object that is the reader
  61      * for this rowset.  The method <code>execute</code> uses this
  62      * reader as part of its implementation.
  63      * @serial
  64      */
  65     private RowSetReader rowSetReader;
  66 
  67     /**
  68      * The <code>RowSetWriterImpl</code> object that is the writer
  69      * for this rowset.  The method <code>acceptChanges</code> uses
  70      * this writer as part of its implementation.
  71      * @serial
  72      */
  73     private RowSetWriter rowSetWriter;
  74 
  75     /**
  76      * The <code>Connection</code> object that connects with this
  77      * <code>CachedRowSetImpl</code> object's current underlying data source.
  78      */
  79     private transient Connection conn;
  80 
  81     /**
  82      * The <code>ResultSetMetaData</code> object that contains information
  83      * about the columns in the <code>ResultSet</code> object that is the
  84      * current source of data for this <code>CachedRowSetImpl</code> object.
  85      */
  86     private transient ResultSetMetaData RSMD;
  87 
  88     /**
  89      * The <code>RowSetMetaData</code> object that contains information about
  90      * the columns in this <code>CachedRowSetImpl</code> object.
  91      * @serial
  92      */
  93     private RowSetMetaDataImpl RowSetMD;
  94 
  95     // Properties of this RowSet
  96 
  97     /**
  98      * An array containing the columns in this <code>CachedRowSetImpl</code>
  99      * object that form a unique identifier for a row. This array
 100      * is used by the writer.
 101      * @serial
 102      */
 103     private int keyCols[];
 104 
 105     /**
 106      * The name of the table in the underlying database to which updates
 107      * should be written.  This name is needed because most drivers
 108      * do not return this information in a <code>ResultSetMetaData</code>
 109      * object.
 110      * @serial
 111      */
 112     private String tableName;
 113 
 114     /**
 115      * A <code>Vector</code> object containing the <code>Row</code>
 116      * objects that comprise  this <code>CachedRowSetImpl</code> object.
 117      * @serial
 118      */
 119     private Vector<Object> rvh;
 120 
 121     /**
 122      * The current postion of the cursor in this <code>CachedRowSetImpl</code>
 123      * object.
 124      * @serial
 125      */
 126     private int cursorPos;
 127 
 128     /**
 129      * The current postion of the cursor in this <code>CachedRowSetImpl</code>
 130      * object not counting rows that have been deleted, if any.
 131      * <P>
 132      * For example, suppose that the cursor is on the last row of a rowset
 133      * that started with five rows and subsequently had the second and third
 134      * rows deleted. The <code>absolutePos</code> would be <code>3</code>,
 135      * whereas the <code>cursorPos</code> would be <code>5</code>.
 136      * @serial
 137      */
 138     private int absolutePos;
 139 
 140     /**
 141      * The number of deleted rows currently in this <code>CachedRowSetImpl</code>
 142      * object.
 143      * @serial
 144      */
 145     private int numDeleted;
 146 
 147     /**
 148      * The total number of rows currently in this <code>CachedRowSetImpl</code>
 149      * object.
 150      * @serial
 151      */
 152     private int numRows;
 153 
 154     /**
 155      * A special row used for constructing a new row. A new
 156      * row is constructed by using <code>ResultSet.updateXXX</code>
 157      * methods to insert column values into the insert row.
 158      * @serial
 159      */
 160     private InsertRow insertRow;
 161 
 162     /**
 163      * A <code>boolean</code> indicating whether the cursor is
 164      * currently on the insert row.
 165      * @serial
 166      */
 167     private boolean onInsertRow;
 168 
 169     /**
 170      * The field that temporarily holds the last position of the
 171      * cursor before it moved to the insert row, thus preserving
 172      * the number of the current row to which the cursor may return.
 173      * @serial
 174      */
 175     private int currentRow;
 176 
 177     /**
 178      * A <code>boolean</code> indicating whether the last value
 179      * returned was an SQL <code>NULL</code>.
 180      * @serial
 181      */
 182     private boolean lastValueNull;
 183 
 184     /**
 185      * A <code>SQLWarning</code> which logs on the warnings
 186      */
 187     private SQLWarning sqlwarn;
 188 
 189     /**
 190      * Used to track match column for JoinRowSet consumption
 191      */
 192     private String strMatchColumn ="";
 193 
 194     /**
 195      * Used to track match column for JoinRowSet consumption
 196      */
 197     private int iMatchColumn = -1;
 198 
 199     /**
 200      * A <code>RowSetWarning</code> which logs on the warnings
 201      */
 202     private RowSetWarning rowsetWarning;
 203 
 204     /**
 205      * The default SyncProvider for the RI CachedRowSetImpl
 206      */
 207     private String DEFAULT_SYNC_PROVIDER = "com.sun.rowset.providers.RIOptimisticProvider";
 208 
 209     /**
 210      * The boolean variable indicating locatorsUpdateValue
 211      */
 212     private boolean dbmslocatorsUpdateCopy;
 213 
 214     /**
 215      * The <code>ResultSet</code> object that is used to maintain the data when
 216      * a ResultSet and start position are passed as parameters to the populate function
 217      */
 218     private transient ResultSet resultSet;
 219 
 220     /**
 221      * The integer value indicating the end position in the ResultSetwhere the picking
 222      * up of rows for populating a CachedRowSet object was left off.
 223      */
 224     private int endPos;
 225 
 226     /**
 227      * The integer value indicating the end position in the ResultSetwhere the picking
 228      * up of rows for populating a CachedRowSet object was left off.
 229      */
 230     private int prevEndPos;
 231 
 232     /**
 233      * The integer value indicating the position in the ResultSet, to populate the
 234      * CachedRowSet object.
 235      */
 236     private int startPos;
 237 
 238     /**
 239      * The integer value indicating the positon from where the page prior to this
 240      * was populated.
 241      */
 242     private int startPrev;
 243 
 244     /**
 245      * The integer value indicating size of the page.
 246      */
 247     private int pageSize;
 248 
 249     /**
 250      * The integer value indicating number of rows that have been processed so far.
 251      * Used for checking whether maxRows has been reached or not.
 252      */
 253     private int maxRowsreached;
 254     /**
 255      * The boolean value when true signifies that pages are still to follow and a
 256      * false value indicates that this is the last page.
 257      */
 258     private boolean pagenotend = true;
 259 
 260     /**
 261      * The boolean value indicating whether this is the first page or not.
 262      */
 263     private boolean onFirstPage;
 264 
 265     /**
 266      * The boolean value indicating whether this is the last page or not.
 267      */
 268     private boolean onLastPage;
 269 
 270     /**
 271      * The integer value indicating how many times the populate function has been called.
 272      */
 273     private int populatecallcount;
 274 
 275     /**
 276      * The integer value indicating the total number of rows to be processed in the
 277      * ResultSet object passed to the populate function.
 278      */
 279     private int totalRows;
 280 
 281     /**
 282      * The boolean value indicating how the CahedRowSet object has been populated for
 283      * paging purpose. True indicates that connection parameter is passed.
 284      */
 285     private boolean callWithCon;
 286 
 287     /**
 288      * CachedRowSet reader object to read the data from the ResultSet when a connection
 289      * parameter is passed to populate the CachedRowSet object for paging.
 290      */
 291     private CachedRowSetReader crsReader;
 292 
 293     /**
 294      * The Vector holding the Match Columns
 295      */
 296     private Vector<Integer> iMatchColumns;
 297 
 298     /**
 299      * The Vector that will hold the Match Column names.
 300      */
 301     private Vector<String> strMatchColumns;
 302 
 303     /**
 304      * Trigger that indicates whether the active SyncProvider is exposes the
 305      * additional TransactionalWriter method
 306      */
 307     private boolean tXWriter = false;
 308 
 309     /**
 310      * The field object for a transactional RowSet writer
 311      */
 312     private TransactionalWriter tWriter = null;
 313 
 314     protected transient JdbcRowSetResourceBundle resBundle;
 315 
 316     private boolean updateOnInsert;
 317 
 318 
 319 
 320     /**
 321      * Constructs a new default <code>CachedRowSetImpl</code> object with
 322      * the capacity to hold 100 rows. This new object has no metadata
 323      * and has the following default values:
 324      * <pre>
 325      *     onInsertRow = false
 326      *     insertRow = null
 327      *     cursorPos = 0
 328      *     numRows = 0
 329      *     showDeleted = false
 330      *     queryTimeout = 0
 331      *     maxRows = 0
 332      *     maxFieldSize = 0
 333      *     rowSetType = ResultSet.TYPE_SCROLL_INSENSITIVE
 334      *     concurrency = ResultSet.CONCUR_UPDATABLE
 335      *     readOnly = false
 336      *     isolation = Connection.TRANSACTION_READ_COMMITTED
 337      *     escapeProcessing = true
 338      *     onInsertRow = false
 339      *     insertRow = null
 340      *     cursorPos = 0
 341      *     absolutePos = 0
 342      *     numRows = 0
 343      * </pre>
 344      * A <code>CachedRowSetImpl</code> object is configured to use the default
 345      * <code>RIOptimisticProvider</code> implementation to provide connectivity
 346      * and synchronization capabilities to the set data source.
 347      * <P>
 348      * @throws SQLException if an error occurs
 349      */
 350     public CachedRowSetImpl() throws SQLException {
 351 
 352         try {
 353            resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
 354         } catch(IOException ioe) {
 355             throw new RuntimeException(ioe);
 356         }
 357 
 358         // set the Reader, this maybe overridden latter
 359         provider =
 360         (SyncProvider)SyncFactory.getInstance(DEFAULT_SYNC_PROVIDER);
 361 
 362         if (!(provider instanceof RIOptimisticProvider)) {
 363             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidp").toString());
 364         }
 365 
 366         rowSetReader = (CachedRowSetReader)provider.getRowSetReader();
 367         rowSetWriter = (CachedRowSetWriter)provider.getRowSetWriter();
 368 
 369         // allocate the parameters collection
 370         initParams();
 371 
 372         initContainer();
 373 
 374         // set up some default values
 375         initProperties();
 376 
 377         // insert row setup
 378         onInsertRow = false;
 379         insertRow = null;
 380 
 381         // set the warninings
 382         sqlwarn = new SQLWarning();
 383         rowsetWarning = new RowSetWarning();
 384 
 385     }
 386 
 387     /**
 388      * Provides a <code>CachedRowSetImpl</code> instance with the same default properties as
 389      * as the zero parameter constructor.
 390      * <pre>
 391      *     onInsertRow = false
 392      *     insertRow = null
 393      *     cursorPos = 0
 394      *     numRows = 0
 395      *     showDeleted = false
 396      *     queryTimeout = 0
 397      *     maxRows = 0
 398      *     maxFieldSize = 0
 399      *     rowSetType = ResultSet.TYPE_SCROLL_INSENSITIVE
 400      *     concurrency = ResultSet.CONCUR_UPDATABLE
 401      *     readOnly = false
 402      *     isolation = Connection.TRANSACTION_READ_COMMITTED
 403      *     escapeProcessing = true
 404      *     onInsertRow = false
 405      *     insertRow = null
 406      *     cursorPos = 0
 407      *     absolutePos = 0
 408      *     numRows = 0
 409      * </pre>
 410      *
 411      * However, applications will have the means to specify at runtime the
 412      * desired <code>SyncProvider</code> object.
 413      * <p>
 414      * For example, creating a <code>CachedRowSetImpl</code> object as follows ensures
 415      * that a it is established with the <code>com.foo.provider.Impl</code> synchronization
 416      * implementation providing the synchronization mechanism for this disconnected
 417      * <code>RowSet</code> object.
 418      * <pre>
 419      *     Hashtable env = new Hashtable();
 420      *     env.put(javax.sql.rowset.spi.SyncFactory.ROWSET_PROVIDER_NAME,
 421      *         "com.foo.provider.Impl");
 422      *     CachedRowSetImpl crs = new CachedRowSet(env);
 423      * </pre>
 424      * <p>
 425      * Calling this constructor with a <code>null</code> parameter will
 426      * cause the <code>SyncFactory</code> to provide the reference
 427      * optimistic provider <code>com.sun.rowset.providers.RIOptimisticProvider</code>.
 428      * <p>
 429      * In addition, the following properties can be associated with the
 430      * provider to assist in determining the choice of the synchronizaton
 431      * provider such as:
 432      * <ul>
 433      * <li><code>ROWSET_SYNC_PROVIDER</code> - the property specifying the the
 434      * <code>SyncProvider</code> class name to be instantiated by the
 435      * <code>SyncFacttory</code>
 436      * <li><code>ROWSET_SYNC_VENDOR</code> - the property specifying the software
 437      * vendor associated with a <code>SyncProvider</code> implementation.
 438      * <li><code>ROWSET_SYNC_PROVIDER_VER</code> - the property specifying the
 439      * version of the <code>SyncProvider</code> implementation provided by the
 440      * software vendor.
 441      * </ul>
 442      * More specific detailes are available in the <code>SyncFactory</code>
 443      * and <code>SyncProvider</code> specificiations later in this document.
 444      * <p>
 445      * @param env a <code>Hashtable</code> object with a list of desired
 446      *        synchronization providers
 447      * @throws SQLException if the requested provider cannot be found by the
 448      * synchonization factory
 449      * @see SyncProvider
 450      */
 451 
 452     public CachedRowSetImpl(Hashtable env) throws SQLException {
 453 
 454 
 455         try {
 456            resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
 457         } catch(IOException ioe) {
 458             throw new RuntimeException(ioe);
 459         }
 460 
 461         if (env == null) {
 462             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.nullhash").toString());
 463         }
 464 
 465         String providerName = (String)env.get(
 466         javax.sql.rowset.spi.SyncFactory.ROWSET_SYNC_PROVIDER);
 467 
 468         // set the Reader, this maybe overridden latter
 469         provider =
 470         (SyncProvider)SyncFactory.getInstance(providerName);
 471 
 472         rowSetReader = provider.getRowSetReader();
 473         rowSetWriter = provider.getRowSetWriter();
 474 
 475         initParams(); // allocate the parameters collection
 476         initContainer();
 477         initProperties(); // set up some default values
 478     }
 479 
 480     /**
 481      * Sets the <code>rvh</code> field to a new <code>Vector</code>
 482      * object with a capacity of 100 and sets the
 483      * <code>cursorPos</code> and <code>numRows</code> fields to zero.
 484      */
 485     private void initContainer() {
 486 
 487         rvh = new Vector<Object>(100);
 488         cursorPos = 0;
 489         absolutePos = 0;
 490         numRows = 0;
 491         numDeleted = 0;
 492     }
 493 
 494     /**
 495      * Sets the properties for this <code>CachedRowSetImpl</code> object to
 496      * their default values. This method is called internally by the
 497      * default constructor.
 498      */
 499 
 500     private void initProperties() throws SQLException {
 501 
 502         if(resBundle == null) {
 503             try {
 504                resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
 505             } catch(IOException ioe) {
 506                 throw new RuntimeException(ioe);
 507             }
 508         }
 509         setShowDeleted(false);
 510         setQueryTimeout(0);
 511         setMaxRows(0);
 512         setMaxFieldSize(0);
 513         setType(ResultSet.TYPE_SCROLL_INSENSITIVE);
 514         setConcurrency(ResultSet.CONCUR_UPDATABLE);
 515         if((rvh.size() > 0) && (isReadOnly() == false))
 516             setReadOnly(false);
 517         else
 518             setReadOnly(true);
 519         setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
 520         setEscapeProcessing(true);
 521         //setTypeMap(null);
 522         checkTransactionalWriter();
 523 
 524         //Instantiating the vector for MatchColumns
 525 
 526         iMatchColumns = new Vector<Integer>(10);
 527         for(int i = 0; i < 10 ; i++) {
 528            iMatchColumns.add(i,Integer.valueOf(-1));
 529         }
 530 
 531         strMatchColumns = new Vector<String>(10);
 532         for(int j = 0; j < 10; j++) {
 533            strMatchColumns.add(j,null);
 534         }
 535     }
 536 
 537     /**
 538      * Determine whether the SyncProvider's writer implements the
 539      * <code>TransactionalWriter<code> interface
 540      */
 541     private void checkTransactionalWriter() {
 542         if (rowSetWriter != null) {
 543             Class c = rowSetWriter.getClass();
 544             if (c != null) {
 545                 Class[] theInterfaces = c.getInterfaces();
 546                 for (int i = 0; i < theInterfaces.length; i++) {
 547                     if ((theInterfaces[i].getName()).indexOf("TransactionalWriter") > 0) {
 548                         tXWriter = true;
 549                         establishTransactionalWriter();
 550                     }
 551                 }
 552             }
 553         }
 554     }
 555 
 556     /**
 557      * Sets an private field to all transaction bounddaries to be set
 558      */
 559     private void establishTransactionalWriter() {
 560         tWriter = (TransactionalWriter)provider.getRowSetWriter();
 561     }
 562 
 563     //-----------------------------------------------------------------------
 564     // Properties
 565     //-----------------------------------------------------------------------
 566 
 567     /**
 568      * Sets this <code>CachedRowSetImpl</code> object's command property
 569      * to the given <code>String</code> object and clears the parameters,
 570      * if any, that were set for the previous command.
 571      * <P>
 572      * The command property may not be needed
 573      * if the rowset is produced by a data source, such as a spreadsheet,
 574      * that does not support commands. Thus, this property is optional
 575      * and may be <code>null</code>.
 576      *
 577      * @param cmd a <code>String</code> object containing an SQL query
 578      *            that will be set as the command; may be <code>null</code>
 579      * @throws SQLException if an error occurs
 580      */
 581     public void setCommand(String cmd) throws SQLException {
 582 
 583         super.setCommand(cmd);
 584 
 585         if(!buildTableName(cmd).equals("")) {
 586             this.setTableName(buildTableName(cmd));
 587         }
 588     }
 589 
 590 
 591     //---------------------------------------------------------------------
 592     // Reading and writing data
 593     //---------------------------------------------------------------------
 594 
 595     /**
 596      * Populates this <code>CachedRowSetImpl</code> object with data from
 597      * the given <code>ResultSet</code> object.  This
 598      * method is an alternative to the method <code>execute</code>
 599      * for filling the rowset with data.  The method <code>populate</code>
 600      * does not require that the properties needed by the method
 601      * <code>execute</code>, such as the <code>command</code> property,
 602      * be set. This is true because the method <code>populate</code>
 603      * is given the <code>ResultSet</code> object from
 604      * which to get data and thus does not need to use the properties
 605      * required for setting up a connection and executing this
 606      * <code>CachedRowSetImpl</code> object's command.
 607      * <P>
 608      * After populating this rowset with data, the method
 609      * <code>populate</code> sets the rowset's metadata and
 610      * then sends a <code>RowSetChangedEvent</code> object
 611      * to all registered listeners prior to returning.
 612      *
 613      * @param data the <code>ResultSet</code> object containing the data
 614      *             to be read into this <code>CachedRowSetImpl</code> object
 615      * @throws SQLException if an error occurs; or the max row setting is
 616      *          violated while populating the RowSet
 617      * @see #execute
 618      */
 619 
 620      public void populate(ResultSet data) throws SQLException {
 621         int rowsFetched;
 622         Row currentRow;
 623         int numCols;
 624         int i;
 625         Map<String, Class<?>> map = getTypeMap();
 626         Object obj;
 627         int mRows;
 628 
 629         if (data == null) {
 630             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.populate").toString());
 631         }
 632         this.resultSet = data;
 633 
 634         // get the meta data for this ResultSet
 635         RSMD = data.getMetaData();
 636 
 637         // set up the metadata
 638         RowSetMD = new RowSetMetaDataImpl();
 639         initMetaData(RowSetMD, RSMD);
 640 
 641         // release the meta-data so that aren't tempted to use it.
 642         RSMD = null;
 643         numCols = RowSetMD.getColumnCount();
 644         mRows = this.getMaxRows();
 645         rowsFetched = 0;
 646         currentRow = null;
 647 
 648         while ( data.next()) {
 649 
 650             currentRow = new Row(numCols);
 651 
 652             if ( rowsFetched > mRows && mRows > 0) {
 653                 rowsetWarning.setNextWarning(new RowSetWarning("Populating rows "
 654                 + "setting has exceeded max row setting"));
 655             }
 656             for ( i = 1; i <= numCols; i++) {
 657                 /*
 658                  * check if the user has set a map. If no map
 659                  * is set then use plain getObject. This lets
 660                  * us work with drivers that do not support
 661                  * getObject with a map in fairly sensible way
 662                  */
 663                 if (map == null) {
 664                     obj = data.getObject(i);
 665                 } else {
 666                     obj = data.getObject(i, map);
 667                 }
 668                 /*
 669                  * the following block checks for the various
 670                  * types that we have to serialize in order to
 671                  * store - right now only structs have been tested
 672                  */
 673                 if (obj instanceof Struct) {
 674                     obj = new SerialStruct((Struct)obj, map);
 675                 } else if (obj instanceof SQLData) {
 676                     obj = new SerialStruct((SQLData)obj, map);
 677                 } else if (obj instanceof Blob) {
 678                     obj = new SerialBlob((Blob)obj);
 679                 } else if (obj instanceof Clob) {
 680                     obj = new SerialClob((Clob)obj);
 681                 } else if (obj instanceof java.sql.Array) {
 682                     if(map != null)
 683                         obj = new SerialArray((java.sql.Array)obj, map);
 684                     else
 685                         obj = new SerialArray((java.sql.Array)obj);
 686                 }
 687 
 688                 ((Row)currentRow).initColumnObject(i, obj);
 689             }
 690             rowsFetched++;
 691             rvh.add(currentRow);
 692         }
 693 
 694         numRows = rowsFetched ;
 695         // Also rowsFetched should be equal to rvh.size()
 696 
 697         // notify any listeners that the rowset has changed
 698         notifyRowSetChanged();
 699 
 700 
 701     }
 702 
 703     /**
 704      * Initializes the given <code>RowSetMetaData</code> object with the values
 705      * in the given <code>ResultSetMetaData</code> object.
 706      *
 707      * @param md the <code>RowSetMetaData</code> object for this
 708      *           <code>CachedRowSetImpl</code> object, which will be set with
 709      *           values from rsmd
 710      * @param rsmd the <code>ResultSetMetaData</code> object from which new
 711      *             values for md will be read
 712      * @throws SQLException if an error occurs
 713      */
 714     private void initMetaData(RowSetMetaDataImpl md, ResultSetMetaData rsmd) throws SQLException {
 715         int numCols = rsmd.getColumnCount();
 716 
 717         md.setColumnCount(numCols);
 718         for (int col=1; col <= numCols; col++) {
 719             md.setAutoIncrement(col, rsmd.isAutoIncrement(col));
 720             if(rsmd.isAutoIncrement(col))
 721                 updateOnInsert = true;
 722             md.setCaseSensitive(col, rsmd.isCaseSensitive(col));
 723             md.setCurrency(col, rsmd.isCurrency(col));
 724             md.setNullable(col, rsmd.isNullable(col));
 725             md.setSigned(col, rsmd.isSigned(col));
 726             md.setSearchable(col, rsmd.isSearchable(col));
 727              /*
 728              * The PostgreSQL drivers sometimes return negative columnDisplaySize,
 729              * which causes an exception to be thrown.  Check for it.
 730              */
 731             int size = rsmd.getColumnDisplaySize(col);
 732             if (size < 0) {
 733                 size = 0;
 734             }
 735             md.setColumnDisplaySize(col, size);
 736             md.setColumnLabel(col, rsmd.getColumnLabel(col));
 737             md.setColumnName(col, rsmd.getColumnName(col));
 738             md.setSchemaName(col, rsmd.getSchemaName(col));
 739             /*
 740              * Drivers return some strange values for precision, for non-numeric data, including reports of
 741              * non-integer values; maybe we should check type, & set to 0 for non-numeric types.
 742              */
 743             int precision = rsmd.getPrecision(col);
 744             if (precision < 0) {
 745                 precision = 0;
 746             }
 747             md.setPrecision(col, precision);
 748 
 749             /*
 750              * It seems, from a bug report, that a driver can sometimes return a negative
 751              * value for scale.  javax.sql.rowset.RowSetMetaDataImpl will throw an exception
 752              * if we attempt to set a negative value.  As such, we'll check for this case.
 753              */
 754             int scale = rsmd.getScale(col);
 755             if (scale < 0) {
 756                 scale = 0;
 757             }
 758             md.setScale(col, scale);
 759             md.setTableName(col, rsmd.getTableName(col));
 760             md.setCatalogName(col, rsmd.getCatalogName(col));
 761             md.setColumnType(col, rsmd.getColumnType(col));
 762             md.setColumnTypeName(col, rsmd.getColumnTypeName(col));
 763         }
 764 
 765         if( conn != null){
 766            // JDBC 4.0 mandates as does the Java EE spec that all DataBaseMetaData methods
 767            // must be implemented, therefore, the previous fix for 5055528 is being backed out
 768             dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy();
 769         }
 770     }
 771 
 772     /**
 773      * Populates this <code>CachedRowSetImpl</code> object with data,
 774      * using the given connection to produce the result set from
 775      * which data will be read.  A second form of this method,
 776      * which takes no arguments, uses the values from this rowset's
 777      * user, password, and either url or data source properties to
 778      * create a new database connection. The form of <code>execute</code>
 779      * that is given a connection ignores these properties.
 780      *
 781      * @param conn A standard JDBC <code>Connection</code> object that this
 782      * <code>CachedRowSet</code> object can pass to a synchronization provider
 783      * to establish a connection to the data source
 784      * @throws SQLException if an invalid <code>Connection</code> is supplied
 785      *           or an error occurs in establishing the connection to the
 786      *           data source
 787      * @see #populate
 788      * @see java.sql.Connection
 789      */
 790     public void execute(Connection conn) throws SQLException {
 791         // store the connection so the reader can find it.
 792         setConnection(conn);
 793 
 794         if(getPageSize() != 0){
 795             crsReader = (CachedRowSetReader)provider.getRowSetReader();
 796             crsReader.setStartPosition(1);
 797             callWithCon = true;
 798             crsReader.readData((RowSetInternal)this);
 799         }
 800 
 801         // Now call the current reader's readData method
 802         else {
 803            rowSetReader.readData((RowSetInternal)this);
 804         }
 805         RowSetMD = (RowSetMetaDataImpl)this.getMetaData();
 806 
 807         if(conn != null){
 808             // JDBC 4.0 mandates as does the Java EE spec that all DataBaseMetaData methods
 809             // must be implemented, therefore, the previous fix for 5055528 is being backed out
 810             dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy();
 811         }
 812 
 813     }
 814 
 815     /**
 816      * Sets this <code>CachedRowSetImpl</code> object's connection property
 817      * to the given <code>Connection</code> object.  This method is called
 818      * internally by the version of the method <code>execute</code> that takes a
 819      * <code>Connection</code> object as an argument. The reader for this
 820      * <code>CachedRowSetImpl</code> object can retrieve the connection stored
 821      * in the rowset's connection property by calling its
 822      * <code>getConnection</code> method.
 823      *
 824      * @param connection the <code>Connection</code> object that was passed in
 825      *                   to the method <code>execute</code> and is to be stored
 826      *                   in this <code>CachedRowSetImpl</code> object's connection
 827      *                   property
 828      */
 829     private void setConnection (Connection connection) {
 830         conn = connection;
 831     }
 832 
 833 
 834     /**
 835      * Propagates all row update, insert, and delete changes to the
 836      * underlying data source backing this <code>CachedRowSetImpl</code>
 837      * object.
 838      * <P>
 839      * <b>Note</b>In the reference implementation an optimistic concurrency implementation
 840      * is provided as a sample implementation of a the <code>SyncProvider</code>
 841      * abstract class.
 842      * <P>
 843      * This method fails if any of the updates cannot be propagated back
 844      * to the data source.  When it fails, the caller can assume that
 845      * none of the updates are reflected in the data source.
 846      * When an exception is thrown, the current row
 847      * is set to the first "updated" row that resulted in an exception
 848      * unless the row that caused the exception is a "deleted" row.
 849      * In that case, when deleted rows are not shown, which is usually true,
 850      * the current row is not affected.
 851      * <P>
 852      * If no <code>SyncProvider</code> is configured, the reference implementation
 853      * leverages the <code>RIOptimisticProvider</code> available which provides the
 854      * default and reference synchronization capabilities for disconnected
 855      * <code>RowSets</code>.
 856      *
 857      * @throws SQLException if the cursor is on the insert row or the underlying
 858      *          reference synchronization provider fails to commit the updates
 859      *          to the datasource
 860      * @throws SyncProviderException if an internal error occurs within the
 861      *          <code>SyncProvider</code> instance during either during the
 862      *          process or at any time when the <code>SyncProvider</code>
 863      *          instance touches the data source.
 864      * @see #acceptChanges(java.sql.Connection)
 865      * @see javax.sql.RowSetWriter
 866      * @see javax.sql.rowset.spi.SyncProvider
 867      */
 868     @SuppressWarnings("deprecation")
 869     public void acceptChanges() throws SyncProviderException {
 870         if (onInsertRow == true) {
 871             throw new SyncProviderException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
 872         }
 873 
 874         int saveCursorPos = cursorPos;
 875         boolean success = false;
 876         boolean conflict = false;
 877 
 878         try {
 879             if (rowSetWriter != null) {
 880                 saveCursorPos = cursorPos;
 881                 conflict = rowSetWriter.writeData((RowSetInternal)this);
 882                 cursorPos = saveCursorPos;
 883             }
 884 
 885             if ((tXWriter) && this.COMMIT_ON_ACCEPT_CHANGES) {
 886                 // do commit/rollback's here
 887                 if (!conflict) {
 888                     tWriter = (TransactionalWriter)rowSetWriter;
 889                     tWriter.rollback();
 890                     success = false;
 891                 } else {
 892                     tWriter = (TransactionalWriter)rowSetWriter;
 893                     if (tWriter instanceof CachedRowSetWriter) {
 894                         ((CachedRowSetWriter)tWriter).commit(this, updateOnInsert);
 895                     } else {
 896                         tWriter.commit();
 897                     }
 898 
 899                     success = true;
 900                 }
 901             }
 902 
 903             if (success == true) {
 904                 setOriginal();
 905             } else if (!(success) && !(this.COMMIT_ON_ACCEPT_CHANGES)) {
 906                 throw new SyncProviderException(resBundle.handleGetObject("cachedrowsetimpl.accfailed").toString());
 907             }
 908 
 909         } catch (SyncProviderException spe) {
 910                throw spe;
 911         } catch (SQLException e) {
 912             e.printStackTrace();
 913             throw new SyncProviderException(e.getMessage());
 914         } catch (SecurityException e) {
 915             throw new SyncProviderException(e.getMessage());
 916         }
 917     }
 918 
 919     /**
 920      * Propagates all row update, insert, and delete changes to the
 921      * data source backing this <code>CachedRowSetImpl</code> object
 922      * using the given <code>Connection</code> object.
 923      * <P>
 924      * The reference implementation <code>RIOptimisticProvider</code>
 925      * modifies its synchronization to a write back function given
 926      * the updated connection
 927      * The reference implementation modifies its synchronization behaviour
 928      * via the <code>SyncProvider</code> to ensure the synchronization
 929      * occurs according to the updated JDBC <code>Connection</code>
 930      * properties.
 931      *
 932      * @param con a standard JDBC <code>Connection</code> object
 933      * @throws SQLException if the cursor is on the insert row or the underlying
 934      *                   synchronization provider fails to commit the updates
 935      *                   back to the data source
 936      * @see #acceptChanges
 937      * @see javax.sql.RowSetWriter
 938      * @see javax.sql.rowset.spi.SyncFactory
 939      * @see javax.sql.rowset.spi.SyncProvider
 940      */
 941     public void acceptChanges(Connection con) throws SyncProviderException{
 942 
 943       setConnection(con);
 944       acceptChanges();
 945 
 946     }
 947 
 948     /**
 949      * Restores this <code>CachedRowSetImpl</code> object to its original state,
 950      * that is, its state before the last set of changes.
 951      * <P>
 952      * Before returning, this method moves the cursor before the first row
 953      * and sends a <code>rowSetChanged</code> event to all registered
 954      * listeners.
 955      * @throws SQLException if an error is occurs rolling back the RowSet
 956      *           state to the definied original value.
 957      * @see javax.sql.RowSetListener#rowSetChanged
 958      */
 959     public void restoreOriginal() throws SQLException {
 960         Row currentRow;
 961         for (Iterator i = rvh.iterator(); i.hasNext();) {
 962             currentRow = (Row)i.next();
 963             if (currentRow.getInserted() == true) {
 964                 i.remove();
 965                 --numRows;
 966             } else {
 967                 if (currentRow.getDeleted() == true) {
 968                     currentRow.clearDeleted();
 969                 }
 970                 if (currentRow.getUpdated() == true) {
 971                     currentRow.clearUpdated();
 972                 }
 973             }
 974         }
 975         // move to before the first
 976         cursorPos = 0;
 977 
 978         // notify any listeners
 979         notifyRowSetChanged();
 980     }
 981 
 982     /**
 983      * Releases the current contents of this <code>CachedRowSetImpl</code>
 984      * object and sends a <code>rowSetChanged</code> event object to all
 985      * registered listeners.
 986      *
 987      * @throws SQLException if an error occurs flushing the contents of
 988      *           RowSet.
 989      * @see javax.sql.RowSetListener#rowSetChanged
 990      */
 991     public void release() throws SQLException {
 992         initContainer();
 993         notifyRowSetChanged();
 994     }
 995 
 996     /**
 997      * Cancels deletion of the current row and notifies listeners that
 998      * a row has changed.
 999      * <P>
1000      * Note:  This method can be ignored if deleted rows are not being shown,
1001      * which is the normal case.
1002      *
1003      * @throws SQLException if the cursor is not on a valid row
1004      */
1005     public void undoDelete() throws SQLException {
1006         if (getShowDeleted() == false) {
1007             return;
1008         }
1009         // make sure we are on a row
1010         checkCursor();
1011 
1012         // don't want this to happen...
1013         if (onInsertRow == true) {
1014             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1015         }
1016 
1017         Row currentRow = (Row)getCurrentRow();
1018         if (currentRow.getDeleted() == true) {
1019             currentRow.clearDeleted();
1020             --numDeleted;
1021             notifyRowChanged();
1022         }
1023     }
1024 
1025     /**
1026      * Immediately removes the current row from this
1027      * <code>CachedRowSetImpl</code> object if the row has been inserted, and
1028      * also notifies listeners the a row has changed.  An exception is thrown
1029      * if the row is not a row that has been inserted or the cursor is before
1030      * the first row, after the last row, or on the insert row.
1031      * <P>
1032      * This operation cannot be undone.
1033      *
1034      * @throws SQLException if an error occurs,
1035      *                         the cursor is not on a valid row,
1036      *                         or the row has not been inserted
1037      */
1038     public void undoInsert() throws SQLException {
1039         // make sure we are on a row
1040         checkCursor();
1041 
1042         // don't want this to happen...
1043         if (onInsertRow == true) {
1044             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1045         }
1046 
1047         Row currentRow = (Row)getCurrentRow();
1048         if (currentRow.getInserted() == true) {
1049             rvh.remove(cursorPos-1);
1050             --numRows;
1051             notifyRowChanged();
1052         } else {
1053             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.illegalop").toString());
1054         }
1055     }
1056 
1057     /**
1058      * Immediately reverses the last update operation if the
1059      * row has been modified. This method can be
1060      * called to reverse updates on a all columns until all updates in a row have
1061      * been rolled back to their originating state since the last synchronization
1062      * (<code>acceptChanges</code>) or population. This method may also be called
1063      * while performing updates to the insert row.
1064      * <P>
1065      * <code>undoUpdate</code may be called at any time during the life-time of a
1066      * rowset, however after a synchronization has occurs this method has no
1067      * affect until further modification to the RowSet data occurs.
1068      *
1069      * @throws SQLException if cursor is before the first row, after the last
1070      *     row in rowset.
1071      * @see #undoDelete
1072      * @see #undoInsert
1073      * @see java.sql.ResultSet#cancelRowUpdates
1074      */
1075     public void undoUpdate() throws SQLException {
1076         // if on insert row, cancel the insert row
1077         // make the insert row flag,
1078         // cursorPos back to the current row
1079         moveToCurrentRow();
1080 
1081         // else if not on insert row
1082         // call undoUpdate or undoInsert
1083         undoDelete();
1084 
1085         undoInsert();
1086 
1087     }
1088 
1089     //--------------------------------------------------------------------
1090     // Views
1091     //--------------------------------------------------------------------
1092 
1093     /**
1094      * Returns a new <code>RowSet</code> object backed by the same data as
1095      * that of this <code>CachedRowSetImpl</code> object and sharing a set of cursors
1096      * with it. This allows cursors to interate over a shared set of rows, providing
1097      * multiple views of the underlying data.
1098      *
1099      * @return a <code>RowSet</code> object that is a copy of this <code>CachedRowSetImpl</code>
1100      * object and shares a set of cursors with it
1101      * @throws SQLException if an error occurs or cloning is
1102      *                         not supported
1103      * @see javax.sql.RowSetEvent
1104      * @see javax.sql.RowSetListener
1105      */
1106     public RowSet createShared() throws SQLException {
1107         RowSet clone;
1108         try {
1109             clone = (RowSet)clone();
1110         } catch (CloneNotSupportedException ex) {
1111             throw new SQLException(ex.getMessage());
1112         }
1113         return clone;
1114     }
1115 
1116     /**
1117      * Returns a new <code>RowSet</code> object containing by the same data
1118      * as this <code>CachedRowSetImpl</code> object.  This method
1119      * differs from the method <code>createCopy</code> in that it throws a
1120      * <code>CloneNotSupportedException</code> object instead of an
1121      * <code>SQLException</code> object, as the method <code>createShared</code>
1122      * does.  This <code>clone</code>
1123      * method is called internally by the method <code>createShared</code>,
1124      * which catches the <code>CloneNotSupportedException</code> object
1125      * and in turn throws a new <code>SQLException</code> object.
1126      *
1127      * @return a copy of this <code>CachedRowSetImpl</code> object
1128      * @throws CloneNotSupportedException if an error occurs when
1129      * attempting to clone this <code>CachedRowSetImpl</code> object
1130      * @see #createShared
1131      */
1132     protected Object clone() throws CloneNotSupportedException  {
1133         return (super.clone());
1134     }
1135 
1136     /**
1137      * Creates a <code>RowSet</code> object that is a deep copy of
1138      * this <code>CachedRowSetImpl</code> object's data, including
1139      * constraints.  Updates made
1140      * on a copy are not visible to the original rowset;
1141      * a copy of a rowset is completely independent from the original.
1142      * <P>
1143      * Making a copy saves the cost of creating an identical rowset
1144      * from first principles, which can be quite expensive.
1145      * For example, it can eliminate the need to query a
1146      * remote database server.
1147      * @return a new <code>CachedRowSet</code> object that is a deep copy
1148      *           of this <code>CachedRowSet</code> object and is
1149      *           completely independent from this <code>CachedRowSetImpl</code>
1150      *           object.
1151      * @throws SQLException if an error occurs in generating the copy of this
1152      *           of the <code>CachedRowSetImpl</code>
1153      * @see #createShared
1154      * @see javax.sql.RowSetEvent
1155      * @see javax.sql.RowSetListener
1156      */
1157     public CachedRowSet createCopy() throws SQLException {
1158         ObjectOutputStream out;
1159         ByteArrayOutputStream bOut = new ByteArrayOutputStream();
1160         try {
1161             out = new ObjectOutputStream(bOut);
1162             out.writeObject(this);
1163         } catch (IOException ex) {
1164             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1165         }
1166 
1167         ObjectInputStream in;
1168 
1169         try {
1170             ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
1171             in = new ObjectInputStream(bIn);
1172         } catch (StreamCorruptedException ex) {
1173             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1174         } catch (IOException ex) {
1175             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1176         }
1177 
1178         try {
1179             //return ((CachedRowSet)(in.readObject()));
1180             CachedRowSetImpl crsTemp = (CachedRowSetImpl)in.readObject();
1181             crsTemp.resBundle = this.resBundle;
1182             return ((CachedRowSet)crsTemp);
1183 
1184         } catch (ClassNotFoundException ex) {
1185             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1186         } catch (OptionalDataException ex) {
1187             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1188         } catch (IOException ex) {
1189             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1190         }
1191     }
1192 
1193     /**
1194      * Creates a <code>RowSet</code> object that is a copy of
1195      * this <code>CachedRowSetImpl</code> object's table structure
1196      * and the constraints only.
1197      * There will be no data in the object being returned.
1198      * Updates made on a copy are not visible to the original rowset.
1199      * <P>
1200      * This helps in getting the underlying XML schema which can
1201      * be used as the basis for populating a <code>WebRowSet</code>.
1202      *
1203      * @return a new <code>CachedRowSet</code> object that is a copy
1204      * of this <code>CachedRowSetImpl</code> object's schema and
1205      * retains all the constraints on the original rowset but contains
1206      * no data
1207      * @throws SQLException if an error occurs in generating the copy
1208      * of the <code>CachedRowSet</code> object
1209      * @see #createShared
1210      * @see #createCopy
1211      * @see #createCopyNoConstraints
1212      * @see javax.sql.RowSetEvent
1213      * @see javax.sql.RowSetListener
1214      */
1215     public CachedRowSet createCopySchema() throws SQLException {
1216         // Copy everything except data i.e all constraints
1217 
1218         // Store the number of rows of "this"
1219         // and make numRows equals zero.
1220         // and make data also zero.
1221         int nRows = numRows;
1222         numRows = 0;
1223 
1224         CachedRowSet crs = this.createCopy();
1225 
1226         // reset this object back to number of rows.
1227         numRows = nRows;
1228 
1229         return crs;
1230     }
1231 
1232     /**
1233      * Creates a <code>CachedRowSet</code> object that is a copy of
1234      * this <code>CachedRowSetImpl</code> object's data only.
1235      * All constraints set in this object will not be there
1236      * in the returning object.  Updates made
1237      * on a copy are not visible to the original rowset.
1238      *
1239      * @return a new <code>CachedRowSet</code> object that is a deep copy
1240      * of this <code>CachedRowSetImpl</code> object and is
1241      * completely independent from this <code>CachedRowSetImpl</code> object
1242      * @throws SQLException if an error occurs in generating the copy of the
1243      * of the <code>CachedRowSet</code>
1244      * @see #createShared
1245      * @see #createCopy
1246      * @see #createCopySchema
1247      * @see javax.sql.RowSetEvent
1248      * @see javax.sql.RowSetListener
1249      */
1250     public CachedRowSet createCopyNoConstraints() throws SQLException {
1251         // Copy the whole data ONLY without any constraints.
1252         CachedRowSetImpl crs;
1253         crs = (CachedRowSetImpl)this.createCopy();
1254 
1255         crs.initProperties();
1256         try {
1257             crs.unsetMatchColumn(crs.getMatchColumnIndexes());
1258         } catch(SQLException sqle) {
1259             //do nothing, if the setMatchColumn is not set.
1260         }
1261 
1262         try {
1263             crs.unsetMatchColumn(crs.getMatchColumnNames());
1264         } catch(SQLException sqle) {
1265             //do nothing, if the setMatchColumn is not set.
1266         }
1267 
1268         return crs;
1269     }
1270 
1271     /**
1272      * Converts this <code>CachedRowSetImpl</code> object to a collection
1273      * of tables. The sample implementation utilitizes the <code>TreeMap</code>
1274      * collection type.
1275      * This class guarantees that the map will be in ascending key order,
1276      * sorted according to the natural order for the key's class.
1277      *
1278      * @return a <code>Collection</code> object consisting of tables,
1279      *         each of which is a copy of a row in this
1280      *         <code>CachedRowSetImpl</code> object
1281      * @throws SQLException if an error occurs in generating the collection
1282      * @see #toCollection(int)
1283      * @see #toCollection(String)
1284      * @see java.util.TreeMap
1285      */
1286     public Collection<?> toCollection() throws SQLException {
1287 
1288         TreeMap<Integer, Object> tMap = new TreeMap<>();
1289 
1290         for (int i = 0; i<numRows; i++) {
1291             tMap.put(Integer.valueOf(i), rvh.get(i));
1292         }
1293 
1294         return (tMap.values());
1295     }
1296 
1297     /**
1298      * Returns the specified column of this <code>CachedRowSetImpl</code> object
1299      * as a <code>Collection</code> object.  This method makes a copy of the
1300      * column's data and utilitizes the <code>Vector</code> to establish the
1301      * collection. The <code>Vector</code> class implements a growable array
1302      * objects allowing the individual components to be accessed using an
1303      * an integer index similar to that of an array.
1304      *
1305      * @return a <code>Collection</code> object that contains the value(s)
1306      *         stored in the specified column of this
1307      *         <code>CachedRowSetImpl</code>
1308      *         object
1309      * @throws SQLException if an error occurs generated the collection; or
1310      *          an invalid column is provided.
1311      * @see #toCollection()
1312      * @see #toCollection(String)
1313      * @see java.util.Vector
1314      */
1315     public Collection<?> toCollection(int column) throws SQLException {
1316 
1317         int nRows = numRows;
1318         Vector<Object> vec = new Vector<>(nRows);
1319 
1320         // create a copy
1321         CachedRowSetImpl crsTemp;
1322         crsTemp = (CachedRowSetImpl) this.createCopy();
1323 
1324         while(nRows!=0) {
1325             crsTemp.next();
1326             vec.add(crsTemp.getObject(column));
1327             nRows--;
1328         }
1329 
1330         return (Collection)vec;
1331     }
1332 
1333     /**
1334      * Returns the specified column of this <code>CachedRowSetImpl</code> object
1335      * as a <code>Collection</code> object.  This method makes a copy of the
1336      * column's data and utilitizes the <code>Vector</code> to establish the
1337      * collection. The <code>Vector</code> class implements a growable array
1338      * objects allowing the individual components to be accessed using an
1339      * an integer index similar to that of an array.
1340      *
1341      * @return a <code>Collection</code> object that contains the value(s)
1342      *         stored in the specified column of this
1343      *         <code>CachedRowSetImpl</code>
1344      *         object
1345      * @throws SQLException if an error occurs generated the collection; or
1346      *          an invalid column is provided.
1347      * @see #toCollection()
1348      * @see #toCollection(int)
1349      * @see java.util.Vector
1350      */
1351     public Collection<?> toCollection(String column) throws SQLException {
1352         return toCollection(getColIdxByName(column));
1353     }
1354 
1355     //--------------------------------------------------------------------
1356     // Advanced features
1357     //--------------------------------------------------------------------
1358 
1359 
1360     /**
1361      * Returns the <code>SyncProvider</code> implementation being used
1362      * with this <code>CachedRowSetImpl</code> implementation rowset.
1363      *
1364      * @return the SyncProvider used by the rowset. If not provider was
1365      *          set when the rowset was instantiated, the reference
1366      *          implementation (default) provider is returned.
1367      * @throws SQLException if error occurs while return the
1368      *          <code>SyncProvider</code> instance.
1369      */
1370     public SyncProvider getSyncProvider() throws SQLException {
1371         return provider;
1372     }
1373 
1374     /**
1375      * Sets the active <code>SyncProvider</code> and attempts to load
1376      * load the new provider using the <code>SyncFactory</code> SPI.
1377      *
1378      * @throws SQLException if an error occurs while resetting the
1379      *          <code>SyncProvider</code>.
1380      */
1381     public void setSyncProvider(String providerStr) throws SQLException {
1382         provider =
1383         (SyncProvider)SyncFactory.getInstance(providerStr);
1384 
1385         rowSetReader = provider.getRowSetReader();
1386         rowSetWriter = provider.getRowSetWriter();
1387     }
1388 
1389 
1390     //-----------------
1391     // methods inherited from RowSet
1392     //-----------------
1393 
1394 
1395 
1396 
1397 
1398 
1399     //---------------------------------------------------------------------
1400     // Reading and writing data
1401     //---------------------------------------------------------------------
1402 
1403     /**
1404      * Populates this <code>CachedRowSetImpl</code> object with data.
1405      * This form of the method uses the rowset's user, password, and url or
1406      * data source name properties to create a database
1407      * connection.  If properties that are needed
1408      * have not been set, this method will throw an exception.
1409      * <P>
1410      * Another form of this method uses an existing JDBC <code>Connection</code>
1411      * object instead of creating a new one; therefore, it ignores the
1412      * properties used for establishing a new connection.
1413      * <P>
1414      * The query specified by the command property is executed to create a
1415      * <code>ResultSet</code> object from which to retrieve data.
1416      * The current contents of the rowset are discarded, and the
1417      * rowset's metadata is also (re)set.  If there are outstanding updates,
1418      * they are also ignored.
1419      * <P>
1420      * The method <code>execute</code> closes any database connections that it
1421      * creates.
1422      *
1423      * @throws SQLException if an error occurs or the
1424      *                         necessary properties have not been set
1425      */
1426     public void execute() throws SQLException {
1427         execute(null);
1428     }
1429 
1430 
1431 
1432     //-----------------------------------
1433     // Methods inherited from ResultSet
1434     //-----------------------------------
1435 
1436     /**
1437      * Moves the cursor down one row from its current position and
1438      * returns <code>true</code> if the new cursor position is a
1439      * valid row.
1440      * The cursor for a new <code>ResultSet</code> object is initially
1441      * positioned before the first row. The first call to the method
1442      * <code>next</code> moves the cursor to the first row, making it
1443      * the current row; the second call makes the second row the
1444      * current row, and so on.
1445      *
1446      * <P>If an input stream from the previous row is open, it is
1447      * implicitly closed. The <code>ResultSet</code> object's warning
1448      * chain is cleared when a new row is read.
1449      *
1450      * @return <code>true</code> if the new current row is valid;
1451      *         <code>false</code> if there are no more rows
1452      * @throws SQLException if an error occurs or
1453      *            the cursor is not positioned in the rowset, before
1454      *            the first row, or after the last row
1455      */
1456     public boolean next() throws SQLException {
1457         /*
1458          * make sure things look sane. The cursor must be
1459          * positioned in the rowset or before first (0) or
1460          * after last (numRows + 1)
1461          */
1462         if (cursorPos < 0 || cursorPos >= numRows + 1) {
1463             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1464         }
1465         // now move and notify
1466         boolean ret = this.internalNext();
1467         notifyCursorMoved();
1468 
1469         return ret;
1470     }
1471 
1472     /**
1473      * Moves this <code>CachedRowSetImpl</code> object's cursor to the next
1474      * row and returns <code>true</code> if the cursor is still in the rowset;
1475      * returns <code>false</code> if the cursor has moved to the position after
1476      * the last row.
1477      * <P>
1478      * This method handles the cases where the cursor moves to a row that
1479      * has been deleted.
1480      * If this rowset shows deleted rows and the cursor moves to a row
1481      * that has been deleted, this method moves the cursor to the next
1482      * row until the cursor is on a row that has not been deleted.
1483      * <P>
1484      * The method <code>internalNext</code> is called by methods such as
1485      * <code>next</code>, <code>absolute</code>, and <code>relative</code>,
1486      * and, as its name implies, is only called internally.
1487      * <p>
1488      * This is a implementation only method and is not required as a standard
1489      * implementation of the <code>CachedRowSet</code> interface.
1490      *
1491      * @return <code>true</code> if the cursor is on a valid row in this
1492      *         rowset; <code>false</code> if it is after the last row
1493      * @throws SQLException if an error occurs
1494      */
1495     protected boolean internalNext() throws SQLException {
1496         boolean ret = false;
1497 
1498         do {
1499             if (cursorPos < numRows) {
1500                 ++cursorPos;
1501                 ret = true;
1502             } else if (cursorPos == numRows) {
1503                 // increment to after last
1504                 ++cursorPos;
1505                 ret = false;
1506                 break;
1507             }
1508         } while ((getShowDeleted() == false) && (rowDeleted() == true));
1509 
1510         /* each call to internalNext may increment cursorPos multiple
1511          * times however, the absolutePos only increments once per call.
1512          */
1513         if (ret == true)
1514             absolutePos++;
1515         else
1516             absolutePos = 0;
1517 
1518         return ret;
1519     }
1520 
1521     /**
1522      * Closes this <code>CachedRowSetImpl</code> objecy and releases any resources
1523      * it was using.
1524      *
1525      * @throws SQLException if an error occurs when releasing any resources in use
1526      * by this <code>CachedRowSetImpl</code> object
1527      */
1528     public void close() throws SQLException {
1529 
1530         // close all data structures holding
1531         // the disconnected rowset
1532 
1533         cursorPos = 0;
1534         absolutePos = 0;
1535         numRows = 0;
1536         numDeleted = 0;
1537 
1538         // set all insert(s), update(s) & delete(s),
1539         // if at all, to their initial values.
1540         initProperties();
1541 
1542         // clear the vector of it's present contents
1543         rvh.clear();
1544 
1545         // this will make it eligible for gc
1546         // rvh = null;
1547     }
1548 
1549     /**
1550      * Reports whether the last column read was SQL <code>NULL</code>.
1551      * Note that you must first call the method <code>getXXX</code>
1552      * on a column to try to read its value and then call the method
1553      * <code>wasNull</code> to determine whether the value was
1554      * SQL <code>NULL</code>.
1555      *
1556      * @return <code>true</code> if the value in the last column read
1557      *         was SQL <code>NULL</code>; <code>false</code> otherwise
1558      * @throws SQLException if an error occurs
1559      */
1560     public boolean wasNull() throws SQLException {
1561         return lastValueNull;
1562     }
1563 
1564     /**
1565      * Sets the field <code>lastValueNull</code> to the given
1566      * <code>boolean</code> value.
1567      *
1568      * @param value <code>true</code> to indicate that the value of
1569      *        the last column read was SQL <code>NULL</code>;
1570      *        <code>false</code> to indicate that it was not
1571      */
1572     private void setLastValueNull(boolean value) {
1573         lastValueNull = value;
1574     }
1575 
1576     // Methods for accessing results by column index
1577 
1578     /**
1579      * Checks to see whether the given index is a valid column number
1580      * in this <code>CachedRowSetImpl</code> object and throws
1581      * an <code>SQLException</code> if it is not. The index is out of bounds
1582      * if it is less than <code>1</code> or greater than the number of
1583      * columns in this rowset.
1584      * <P>
1585      * This method is called internally by the <code>getXXX</code> and
1586      * <code>updateXXX</code> methods.
1587      *
1588      * @param idx the number of a column in this <code>CachedRowSetImpl</code>
1589      *            object; must be between <code>1</code> and the number of
1590      *            rows in this rowset
1591      * @throws SQLException if the given index is out of bounds
1592      */
1593     private void checkIndex(int idx) throws SQLException {
1594         if (idx < 1 || idx > RowSetMD.getColumnCount()) {
1595             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcol").toString());
1596         }
1597     }
1598 
1599     /**
1600      * Checks to see whether the cursor for this <code>CachedRowSetImpl</code>
1601      * object is on a row in the rowset and throws an
1602      * <code>SQLException</code> if it is not.
1603      * <P>
1604      * This method is called internally by <code>getXXX</code> methods, by
1605      * <code>updateXXX</code> methods, and by methods that update, insert,
1606      * or delete a row or that cancel a row update, insert, or delete.
1607      *
1608      * @throws SQLException if the cursor for this <code>CachedRowSetImpl</code>
1609      *         object is not on a valid row
1610      */
1611     private void checkCursor() throws SQLException {
1612         if (isAfterLast() == true || isBeforeFirst() == true) {
1613             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1614         }
1615     }
1616 
1617     /**
1618      * Returns the column number of the column with the given name in this
1619      * <code>CachedRowSetImpl</code> object.  This method throws an
1620      * <code>SQLException</code> if the given name is not the name of
1621      * one of the columns in this rowset.
1622      *
1623      * @param name a <code>String</code> object that is the name of a column in
1624      *              this <code>CachedRowSetImpl</code> object
1625      * @throws SQLException if the given name does not match the name of one of
1626      *         the columns in this rowset
1627      */
1628     private int getColIdxByName(String name) throws SQLException {
1629         RowSetMD = (RowSetMetaDataImpl)this.getMetaData();
1630         int cols = RowSetMD.getColumnCount();
1631 
1632         for (int i=1; i <= cols; ++i) {
1633             String colName = RowSetMD.getColumnName(i);
1634             if (colName != null)
1635                 if (name.equalsIgnoreCase(colName))
1636                     return (i);
1637                 else
1638                     continue;
1639         }
1640         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalcolnm").toString());
1641 
1642     }
1643 
1644     /**
1645      * Returns the insert row or the current row of this
1646      * <code>CachedRowSetImpl</code>object.
1647      *
1648      * @return the <code>Row</code> object on which this <code>CachedRowSetImpl</code>
1649      * objects's cursor is positioned
1650      */
1651     protected BaseRow getCurrentRow() {
1652         if (onInsertRow == true) {
1653             return (BaseRow)insertRow;
1654         } else {
1655             return (BaseRow)(rvh.get(cursorPos - 1));
1656         }
1657     }
1658 
1659     /**
1660      * Removes the row on which the cursor is positioned.
1661      * <p>
1662      * This is a implementation only method and is not required as a standard
1663      * implementation of the <code>CachedRowSet</code> interface.
1664      *
1665      * @throws SQLException if the cursor is positioned on the insert
1666      *            row
1667      */
1668     protected void removeCurrentRow() {
1669         ((Row)getCurrentRow()).setDeleted();
1670         rvh.remove(cursorPos - 1);
1671         --numRows;
1672     }
1673 
1674 
1675     /**
1676      * Retrieves the value of the designated column in the current row
1677      * of this <code>CachedRowSetImpl</code> object as a
1678      * <code>String</code> object.
1679      *
1680      * @param columnIndex the first column is <code>1</code>, the second
1681      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1682      *        and equal to or less than the number of columns in the rowset
1683      * @return the column value; if the value is SQL <code>NULL</code>, the
1684      *         result is <code>null</code>
1685      * @throws SQLException if (1) the given column index is out of bounds,
1686      * (2) the cursor is not on one of this rowset's rows or its
1687      * insert row, or (3) the designated column does not store an
1688      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
1689      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, <b>CHAR</b>, <b>VARCHAR</b></code>
1690      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1691      * recommended return type.
1692      */
1693     public String getString(int columnIndex) throws SQLException {
1694         Object value;
1695 
1696         // sanity check.
1697         checkIndex(columnIndex);
1698         // make sure the cursor is on a valid row
1699         checkCursor();
1700 
1701         setLastValueNull(false);
1702         value = getCurrentRow().getColumnObject(columnIndex);
1703 
1704         // check for SQL NULL
1705         if (value == null) {
1706             setLastValueNull(true);
1707             return null;
1708         }
1709 
1710         return value.toString();
1711     }
1712 
1713     /**
1714      * Retrieves the value of the designated column in the current row
1715      * of this <code>CachedRowSetImpl</code> object as a
1716      * <code>boolean</code> value.
1717      *
1718      * @param columnIndex the first column is <code>1</code>, the second
1719      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1720      *        and equal to or less than the number of columns in the rowset
1721      * @return the column value as a <code>boolean</code> in the Java progamming language;
1722      *        if the value is SQL <code>NULL</code>, the result is <code>false</code>
1723      * @throws SQLException if (1) the given column index is out of bounds,
1724      *            (2) the cursor is not on one of this rowset's rows or its
1725      *            insert row, or (3) the designated column does not store an
1726      *            SQL <code>BOOLEAN</code> value
1727      * @see #getBoolean(String)
1728      */
1729     public boolean getBoolean(int columnIndex) throws SQLException {
1730         Object value;
1731 
1732         // sanity check.
1733         checkIndex(columnIndex);
1734         // make sure the cursor is on a valid row
1735         checkCursor();
1736 
1737         setLastValueNull(false);
1738         value = getCurrentRow().getColumnObject(columnIndex);
1739 
1740         // check for SQL NULL
1741         if (value == null) {
1742             setLastValueNull(true);
1743             return false;
1744         }
1745 
1746         // check for Boolean...
1747         if (value instanceof Boolean) {
1748             return ((Boolean)value).booleanValue();
1749         }
1750 
1751         // convert to a Double and compare to zero
1752         try {
1753             Double d = new Double(value.toString());
1754             if (d.compareTo(new Double((double)0)) == 0) {
1755                 return false;
1756             } else {
1757                 return true;
1758             }
1759         } catch (NumberFormatException ex) {
1760             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.boolfail").toString(),
1761                   new Object[] {value.toString().trim(), columnIndex}));
1762         }
1763     }
1764 
1765     /**
1766      * Retrieves the value of the designated column in the current row
1767      * of this <code>CachedRowSetImpl</code> object as a
1768      * <code>byte</code> value.
1769      *
1770      * @param columnIndex the first column is <code>1</code>, the second
1771      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1772      *        and equal to or less than the number of columns in the rowset
1773      * @return the column value as a <code>byte</code> in the Java programming
1774      * language; if the value is SQL <code>NULL</code>, the result is <code>0</code>
1775      * @throws SQLException if (1) the given column index is out of bounds,
1776      *            (2) the cursor is not on one of this rowset's rows or its
1777      *            insert row, or (3) the designated column does not store an
1778      *            SQL <code><b>TINYINT</b>, SMALLINT, INTEGER, BIGINT, REAL,
1779      *            FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1780      *            or <code>LONGVARCHAR</code> value. The bold SQL type
1781      *            designates the recommended return type.
1782      * @see #getByte(String)
1783      */
1784     public byte getByte(int columnIndex) throws SQLException {
1785         Object value;
1786 
1787         // sanity check.
1788         checkIndex(columnIndex);
1789         // make sure the cursor is on a valid row
1790         checkCursor();
1791 
1792         setLastValueNull(false);
1793         value = getCurrentRow().getColumnObject(columnIndex);
1794 
1795         // check for SQL NULL
1796         if (value == null) {
1797             setLastValueNull(true);
1798             return (byte)0;
1799         }
1800         try {
1801             return ((Byte.valueOf(value.toString())).byteValue());
1802         } catch (NumberFormatException ex) {
1803             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.bytefail").toString(),
1804                   new Object[] {value.toString().trim(), columnIndex}));
1805         }
1806     }
1807 
1808     /**
1809      * Retrieves the value of the designated column in the current row
1810      * of this <code>CachedRowSetImpl</code> object as a
1811      * <code>short</code> value.
1812      *
1813      * @param columnIndex the first column is <code>1</code>, the second
1814      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1815      *        and equal to or less than the number of columns in the rowset
1816      * @return the column value; if the value is SQL <code>NULL</code>, the
1817      *         result is <code>0</code>
1818      * @throws SQLException if (1) the given column index is out of bounds,
1819      * (2) the cursor is not on one of this rowset's rows or its
1820      * insert row, or (3) the designated column does not store an
1821      * SQL <code>TINYINT, <b>SMALLINT</b>, INTEGER, BIGINT, REAL
1822      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1823      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1824      * recommended return type.
1825      * @see #getShort(String)
1826      */
1827     public short getShort(int columnIndex) throws SQLException {
1828         Object value;
1829 
1830         // sanity check.
1831         checkIndex(columnIndex);
1832         // make sure the cursor is on a valid row
1833         checkCursor();
1834 
1835         setLastValueNull(false);
1836         value = getCurrentRow().getColumnObject(columnIndex);
1837 
1838         // check for SQL NULL
1839         if (value == null) {
1840             setLastValueNull(true);
1841             return (short)0;
1842         }
1843 
1844         try {
1845             return ((Short.valueOf(value.toString().trim())).shortValue());
1846         } catch (NumberFormatException ex) {
1847             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.shortfail").toString(),
1848                   new Object[] {value.toString().trim(), columnIndex}));
1849         }
1850     }
1851 
1852     /**
1853      * Retrieves the value of the designated column in the current row
1854      * of this <code>CachedRowSetImpl</code> object as an
1855      * <code>int</code> value.
1856      *
1857      * @param columnIndex the first column is <code>1</code>, the second
1858      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1859      *        and equal to or less than the number of columns in the rowset
1860      * @return the column value; if the value is SQL <code>NULL</code>, the
1861      *         result is <code>0</code>
1862      * @throws SQLException if (1) the given column index is out of bounds,
1863      * (2) the cursor is not on one of this rowset's rows or its
1864      * insert row, or (3) the designated column does not store an
1865      * SQL <code>TINYINT, SMALLINT, <b>INTEGER</b>, BIGINT, REAL
1866      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1867      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1868      * recommended return type.
1869      */
1870     public int getInt(int columnIndex) throws SQLException {
1871         Object value;
1872 
1873         // sanity check.
1874         checkIndex(columnIndex);
1875         // make sure the cursor is on a valid row
1876         checkCursor();
1877 
1878         setLastValueNull(false);
1879         value = getCurrentRow().getColumnObject(columnIndex);
1880 
1881         // check for SQL NULL
1882         if (value == null) {
1883             setLastValueNull(true);
1884             return (int)0;
1885         }
1886 
1887         try {
1888             return ((Integer.valueOf(value.toString().trim())).intValue());
1889         } catch (NumberFormatException ex) {
1890             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.intfail").toString(),
1891                   new Object[] {value.toString().trim(), columnIndex}));
1892         }
1893     }
1894 
1895     /**
1896      * Retrieves the value of the designated column in the current row
1897      * of this <code>CachedRowSetImpl</code> object as a
1898      * <code>long</code> value.
1899      *
1900      * @param columnIndex the first column is <code>1</code>, the second
1901      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1902      *        and equal to or less than the number of columns in the rowset
1903      * @return the column value; if the value is SQL <code>NULL</code>, the
1904      *         result is <code>0</code>
1905      * @throws SQLException if (1) the given column index is out of bounds,
1906      * (2) the cursor is not on one of this rowset's rows or its
1907      * insert row, or (3) the designated column does not store an
1908      * SQL <code>TINYINT, SMALLINT, INTEGER, <b>BIGINT</b>, REAL
1909      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1910      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1911      * recommended return type.
1912      * @see #getLong(String)
1913      */
1914     public long getLong(int columnIndex) throws SQLException {
1915         Object value;
1916 
1917         // sanity check.
1918         checkIndex(columnIndex);
1919         // make sure the cursor is on a valid row
1920         checkCursor();
1921 
1922         setLastValueNull(false);
1923         value = getCurrentRow().getColumnObject(columnIndex);
1924 
1925         // check for SQL NULL
1926         if (value == null) {
1927             setLastValueNull(true);
1928             return (long)0;
1929         }
1930         try {
1931             return ((Long.valueOf(value.toString().trim())).longValue());
1932         } catch (NumberFormatException ex) {
1933             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.longfail").toString(),
1934                   new Object[] {value.toString().trim(), columnIndex}));
1935         }
1936     }
1937 
1938     /**
1939      * Retrieves the value of the designated column in the current row
1940      * of this <code>CachedRowSetImpl</code> object as a
1941      * <code>float</code> value.
1942      *
1943      * @param columnIndex the first column is <code>1</code>, the second
1944      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1945      *        and equal to or less than the number of columns in the rowset
1946      * @return the column value; if the value is SQL <code>NULL</code>, the
1947      *         result is <code>0</code>
1948      * @throws SQLException if (1) the given column index is out of bounds,
1949      * (2) the cursor is not on one of this rowset's rows or its
1950      * insert row, or (3) the designated column does not store an
1951      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, <b>REAL</b>,
1952      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1953      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1954      * recommended return type.
1955      * @see #getFloat(String)
1956      */
1957     public float getFloat(int columnIndex) throws SQLException {
1958         Object value;
1959 
1960         // sanity check.
1961         checkIndex(columnIndex);
1962         // make sure the cursor is on a valid row
1963         checkCursor();
1964 
1965         setLastValueNull(false);
1966         value = getCurrentRow().getColumnObject(columnIndex);
1967 
1968         // check for SQL NULL
1969         if (value == null) {
1970             setLastValueNull(true);
1971             return (float)0;
1972         }
1973         try {
1974             return ((new Float(value.toString())).floatValue());
1975         } catch (NumberFormatException ex) {
1976             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.floatfail").toString(),
1977                   new Object[] {value.toString().trim(), columnIndex}));
1978         }
1979     }
1980 
1981     /**
1982      * Retrieves the value of the designated column in the current row
1983      * of this <code>CachedRowSetImpl</code> object as a
1984      * <code>double</code> value.
1985      *
1986      * @param columnIndex the first column is <code>1</code>, the second
1987      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1988      *        and equal to or less than the number of columns in the rowset
1989      * @return the column value; if the value is SQL <code>NULL</code>, the
1990      *         result is <code>0</code>
1991      * @throws SQLException if (1) the given column index is out of bounds,
1992      * (2) the cursor is not on one of this rowset's rows or its
1993      * insert row, or (3) the designated column does not store an
1994      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
1995      * <b>FLOAT</b>, <b>DOUBLE</b>, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1996      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1997      * recommended return type.
1998      * @see #getDouble(String)
1999      *
2000      */
2001     public double getDouble(int columnIndex) throws SQLException {
2002         Object value;
2003 
2004         // sanity check.
2005         checkIndex(columnIndex);
2006         // make sure the cursor is on a valid row
2007         checkCursor();
2008 
2009         setLastValueNull(false);
2010         value = getCurrentRow().getColumnObject(columnIndex);
2011 
2012         // check for SQL NULL
2013         if (value == null) {
2014             setLastValueNull(true);
2015             return (double)0;
2016         }
2017         try {
2018             return ((new Double(value.toString().trim())).doubleValue());
2019         } catch (NumberFormatException ex) {
2020             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.doublefail").toString(),
2021                   new Object[] {value.toString().trim(), columnIndex}));
2022         }
2023     }
2024 
2025     /**
2026      * Retrieves the value of the designated column in the current row
2027      * of this <code>CachedRowSetImpl</code> object as a
2028      * <code>java.math.BigDecimal</code> object.
2029      * <P>
2030      * This method is deprecated; use the version of <code>getBigDecimal</code>
2031      * that does not take a scale parameter and returns a value with full
2032      * precision.
2033      *
2034      * @param columnIndex the first column is <code>1</code>, the second
2035      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2036      *        and equal to or less than the number of columns in the rowset
2037      * @param scale the number of digits to the right of the decimal point in the
2038      *        value returned
2039      * @return the column value with the specified number of digits to the right
2040      *         of the decimal point; if the value is SQL <code>NULL</code>, the
2041      *         result is <code>null</code>
2042      * @throws SQLException if the given column index is out of bounds,
2043      *            the cursor is not on a valid row, or this method fails
2044      * @deprecated
2045      */
2046     public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
2047         Object value;
2048         BigDecimal bDecimal, retVal;
2049 
2050         // sanity check.
2051         checkIndex(columnIndex);
2052         // make sure the cursor is on a valid row
2053         checkCursor();
2054 
2055         setLastValueNull(false);
2056         value = getCurrentRow().getColumnObject(columnIndex);
2057 
2058         // check for SQL NULL
2059         if (value == null) {
2060             setLastValueNull(true);
2061             return (new BigDecimal(0));
2062         }
2063 
2064         bDecimal = this.getBigDecimal(columnIndex);
2065 
2066         retVal = bDecimal.setScale(scale);
2067 
2068         return retVal;
2069     }
2070 
2071     /**
2072      * Retrieves the value of the designated column in the current row
2073      * of this <code>CachedRowSetImpl</code> object as a
2074      * <code>byte</code> array value.
2075      *
2076      * @param columnIndex the first column is <code>1</code>, the second
2077      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2078      *        and equal to or less than the number of columns in the rowset
2079      * @return the column value as a <code>byte</code> array in the Java programming
2080      * language; if the value is SQL <code>NULL</code>, the
2081      * result is <code>null</code>
2082      *
2083      * @throws SQLException if (1) the given column index is out of bounds,
2084      * (2) the cursor is not on one of this rowset's rows or its
2085      * insert row, or (3) the designated column does not store an
2086      * SQL <code><b>BINARY</b>, <b>VARBINARY</b> or
2087      * LONGVARBINARY</code> value.
2088      * The bold SQL type designates the recommended return type.
2089      * @see #getBytes(String)
2090      */
2091     public byte[] getBytes(int columnIndex) throws SQLException {
2092         // sanity check.
2093         checkIndex(columnIndex);
2094         // make sure the cursor is on a valid row
2095         checkCursor();
2096 
2097         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
2098             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2099         }
2100 
2101         return (byte[])(getCurrentRow().getColumnObject(columnIndex));
2102     }
2103 
2104     /**
2105      * Retrieves the value of the designated column in the current row
2106      * of this <code>CachedRowSetImpl</code> object as a
2107      * <code>java.sql.Date</code> object.
2108      *
2109      * @param columnIndex the first column is <code>1</code>, the second
2110      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2111      *        and equal to or less than the number of columns in the rowset
2112      * @return the column value as a <code>java.sql.Data</code> object; if
2113      *        the value is SQL <code>NULL</code>, the
2114      *        result is <code>null</code>
2115      * @throws SQLException if the given column index is out of bounds,
2116      *            the cursor is not on a valid row, or this method fails
2117      */
2118     public java.sql.Date getDate(int columnIndex) throws SQLException {
2119         Object value;
2120 
2121         // sanity check.
2122         checkIndex(columnIndex);
2123         // make sure the cursor is on a valid row
2124         checkCursor();
2125 
2126         setLastValueNull(false);
2127         value = getCurrentRow().getColumnObject(columnIndex);
2128 
2129         // check for SQL NULL
2130         if (value == null) {
2131             setLastValueNull(true);
2132             return null;
2133         }
2134 
2135         /*
2136          * The object coming back from the db could be
2137          * a date, a timestamp, or a char field variety.
2138          * If it's a date type return it, a timestamp
2139          * we turn into a long and then into a date,
2140          * char strings we try to parse. Yuck.
2141          */
2142         switch (RowSetMD.getColumnType(columnIndex)) {
2143             case java.sql.Types.DATE: {
2144                 long sec = ((java.sql.Date)value).getTime();
2145                 return new java.sql.Date(sec);
2146             }
2147             case java.sql.Types.TIMESTAMP: {
2148                 long sec = ((java.sql.Timestamp)value).getTime();
2149                 return new java.sql.Date(sec);
2150             }
2151             case java.sql.Types.CHAR:
2152             case java.sql.Types.VARCHAR:
2153             case java.sql.Types.LONGVARCHAR: {
2154                 try {
2155                     DateFormat df = DateFormat.getDateInstance();
2156                     return ((java.sql.Date)(df.parse(value.toString())));
2157                 } catch (ParseException ex) {
2158                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.datefail").toString(),
2159                         new Object[] {value.toString().trim(), columnIndex}));
2160                 }
2161             }
2162             default: {
2163                 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.datefail").toString(),
2164                         new Object[] {value.toString().trim(), columnIndex}));
2165             }
2166         }
2167     }
2168 
2169     /**
2170      * Retrieves the value of the designated column in the current row
2171      * of this <code>CachedRowSetImpl</code> object as a
2172      * <code>java.sql.Time</code> object.
2173      *
2174      * @param columnIndex the first column is <code>1</code>, the second
2175      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2176      *        and equal to or less than the number of columns in the rowset
2177      * @return the column value; if the value is SQL <code>NULL</code>, the
2178      *         result is <code>null</code>
2179      * @throws SQLException if the given column index is out of bounds,
2180      *         the cursor is not on a valid row, or this method fails
2181      */
2182     public java.sql.Time getTime(int columnIndex) throws SQLException {
2183         Object value;
2184 
2185         // sanity check.
2186         checkIndex(columnIndex);
2187         // make sure the cursor is on a valid row
2188         checkCursor();
2189 
2190         setLastValueNull(false);
2191         value = getCurrentRow().getColumnObject(columnIndex);
2192 
2193         // check for SQL NULL
2194         if (value == null) {
2195             setLastValueNull(true);
2196             return null;
2197         }
2198 
2199         /*
2200          * The object coming back from the db could be
2201          * a date, a timestamp, or a char field variety.
2202          * If it's a date type return it, a timestamp
2203          * we turn into a long and then into a date,
2204          * char strings we try to parse. Yuck.
2205          */
2206         switch (RowSetMD.getColumnType(columnIndex)) {
2207             case java.sql.Types.TIME: {
2208                 return (java.sql.Time)value;
2209             }
2210             case java.sql.Types.TIMESTAMP: {
2211                 long sec = ((java.sql.Timestamp)value).getTime();
2212                 return new java.sql.Time(sec);
2213             }
2214             case java.sql.Types.CHAR:
2215             case java.sql.Types.VARCHAR:
2216             case java.sql.Types.LONGVARCHAR: {
2217                 try {
2218                     DateFormat tf = DateFormat.getTimeInstance();
2219                     return ((java.sql.Time)(tf.parse(value.toString())));
2220                 } catch (ParseException ex) {
2221                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2222                         new Object[] {value.toString().trim(), columnIndex}));
2223                 }
2224             }
2225             default: {
2226                 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2227                         new Object[] {value.toString().trim(), columnIndex}));
2228             }
2229         }
2230     }
2231 
2232     /**
2233      * Retrieves the value of the designated column in the current row
2234      * of this <code>CachedRowSetImpl</code> object as a
2235      * <code>java.sql.Timestamp</code> object.
2236      *
2237      * @param columnIndex the first column is <code>1</code>, the second
2238      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2239      *        and equal to or less than the number of columns in the rowset
2240      * @return the column value; if the value is SQL <code>NULL</code>, the
2241      *         result is <code>null</code>
2242      * @throws SQLException if the given column index is out of bounds,
2243      *            the cursor is not on a valid row, or this method fails
2244      */
2245     public java.sql.Timestamp getTimestamp(int columnIndex) throws SQLException {
2246         Object value;
2247 
2248         // sanity check.
2249         checkIndex(columnIndex);
2250         // make sure the cursor is on a valid row
2251         checkCursor();
2252 
2253         setLastValueNull(false);
2254         value = getCurrentRow().getColumnObject(columnIndex);
2255 
2256         // check for SQL NULL
2257         if (value == null) {
2258             setLastValueNull(true);
2259             return null;
2260         }
2261 
2262         /*
2263          * The object coming back from the db could be
2264          * a date, a timestamp, or a char field variety.
2265          * If it's a date type return it; a timestamp
2266          * we turn into a long and then into a date;
2267          * char strings we try to parse. Yuck.
2268          */
2269         switch (RowSetMD.getColumnType(columnIndex)) {
2270             case java.sql.Types.TIMESTAMP: {
2271                 return (java.sql.Timestamp)value;
2272             }
2273             case java.sql.Types.TIME: {
2274                 long sec = ((java.sql.Time)value).getTime();
2275                 return new java.sql.Timestamp(sec);
2276             }
2277             case java.sql.Types.DATE: {
2278                 long sec = ((java.sql.Date)value).getTime();
2279                 return new java.sql.Timestamp(sec);
2280             }
2281             case java.sql.Types.CHAR:
2282             case java.sql.Types.VARCHAR:
2283             case java.sql.Types.LONGVARCHAR: {
2284                 try {
2285                     DateFormat tf = DateFormat.getTimeInstance();
2286                     return ((java.sql.Timestamp)(tf.parse(value.toString())));
2287                 } catch (ParseException ex) {
2288                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2289                         new Object[] {value.toString().trim(), columnIndex}));
2290                 }
2291             }
2292             default: {
2293                 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2294                         new Object[] {value.toString().trim(), columnIndex}));
2295             }
2296         }
2297     }
2298 
2299     /**
2300      * Retrieves the value of the designated column in the current row of this
2301      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2302      * object.
2303      *
2304      * A column value can be retrieved as a stream of ASCII characters
2305      * and then read in chunks from the stream.  This method is particularly
2306      * suitable for retrieving large <code>LONGVARCHAR</code> values.  The JDBC
2307      * driver will do any necessary conversion from the database format into ASCII.
2308      *
2309      * <P><B>Note:</B> All the data in the returned stream must be
2310      * read prior to getting the value of any other column. The next
2311      * call to a get method implicitly closes the stream. . Also, a
2312      * stream may return <code>0</code> for <code>CachedRowSetImpl.available()</code>
2313      * whether there is data available or not.
2314      *
2315      * @param columnIndex the first column is <code>1</code>, the second
2316      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2317      *        and equal to or less than the number of columns in this rowset
2318      * @return a Java input stream that delivers the database column value
2319      *         as a stream of one-byte ASCII characters.  If the value is SQL
2320      *         <code>NULL</code>, the result is <code>null</code>.
2321      * @throws SQLException if (1) the given column index is out of bounds,
2322      * (2) the cursor is not on one of this rowset's rows or its
2323      * insert row, or (3) the designated column does not store an
2324      * SQL <code>CHAR, VARCHAR</code>, <code><b>LONGVARCHAR</b></code>
2325      * <code>BINARY, VARBINARY</code> or <code>LONGVARBINARY</code> value. The
2326      * bold SQL type designates the recommended return types that this method is
2327      * used to retrieve.
2328      * @see #getAsciiStream(String)
2329      */
2330     public java.io.InputStream getAsciiStream(int columnIndex) throws SQLException {
2331         Object value;
2332 
2333         // always free an old stream
2334         asciiStream = null;
2335 
2336         // sanity check
2337         checkIndex(columnIndex);
2338         //make sure the cursor is on a vlid row
2339         checkCursor();
2340 
2341         value =  getCurrentRow().getColumnObject(columnIndex);
2342         if (value == null) {
2343             lastValueNull = true;
2344             return null;
2345         }
2346 
2347         try {
2348             if (isString(RowSetMD.getColumnType(columnIndex))) {
2349                 asciiStream = new ByteArrayInputStream(((String)value).getBytes("ASCII"));
2350             } else {
2351                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2352             }
2353         } catch (java.io.UnsupportedEncodingException ex) {
2354             throw new SQLException(ex.getMessage());
2355         }
2356 
2357         return (java.io.InputStream)asciiStream;
2358     }
2359 
2360     /**
2361      * A column value can be retrieved as a stream of Unicode characters
2362      * and then read in chunks from the stream.  This method is particularly
2363      * suitable for retrieving large LONGVARCHAR values.  The JDBC driver will
2364      * do any necessary conversion from the database format into Unicode.
2365      *
2366      * <P><B>Note:</B> All the data in the returned stream must be
2367      * read prior to getting the value of any other column. The next
2368      * call to a get method implicitly closes the stream. . Also, a
2369      * stream may return 0 for available() whether there is data
2370      * available or not.
2371      *
2372      * @param columnIndex the first column is <code>1</code>, the second
2373      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2374      *        and equal to or less than the number of columns in this rowset
2375      * @return a Java input stream that delivers the database column value
2376      * as a stream of two byte Unicode characters.  If the value is SQL NULL
2377      * then the result is null.
2378      * @throws SQLException if an error occurs
2379      * @deprecated
2380      */
2381     public java.io.InputStream getUnicodeStream(int columnIndex) throws SQLException {
2382         // always free an old stream
2383         unicodeStream = null;
2384 
2385         // sanity check.
2386         checkIndex(columnIndex);
2387         // make sure the cursor is on a valid row
2388         checkCursor();
2389 
2390         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false &&
2391         isString(RowSetMD.getColumnType(columnIndex)) == false) {
2392             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2393         }
2394 
2395         Object value = getCurrentRow().getColumnObject(columnIndex);
2396         if (value == null) {
2397             lastValueNull = true;
2398             return null;
2399         }
2400 
2401         unicodeStream = new StringBufferInputStream(value.toString());
2402 
2403         return (java.io.InputStream)unicodeStream;
2404     }
2405 
2406     /**
2407      * Retrieves the value of the designated column in the current row of this
2408      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2409      * object.
2410      * <P>
2411      * A column value can be retrieved as a stream of uninterpreted bytes
2412      * and then read in chunks from the stream.  This method is particularly
2413      * suitable for retrieving large <code>LONGVARBINARY</code> values.
2414      *
2415      * <P><B>Note:</B> All the data in the returned stream must be
2416      * read prior to getting the value of any other column. The next
2417      * call to a get method implicitly closes the stream. Also, a
2418      * stream may return <code>0</code> for
2419      * <code>CachedRowSetImpl.available()</code> whether there is data
2420      * available or not.
2421      *
2422      * @param columnIndex the first column is <code>1</code>, the second
2423      * is <code>2</code>, and so on; must be <code>1</code> or larger
2424      * and equal to or less than the number of columns in the rowset
2425      * @return a Java input stream that delivers the database column value
2426      * as a stream of uninterpreted bytes.  If the value is SQL <code>NULL</code>
2427      * then the result is <code>null</code>.
2428      * @throws SQLException if (1) the given column index is out of bounds,
2429      * (2) the cursor is not on one of this rowset's rows or its
2430      * insert row, or (3) the designated column does not store an
2431      * SQL <code>BINARY, VARBINARY</code> or <code><b>LONGVARBINARY</b></code>
2432      * The bold type indicates the SQL type that this method is recommened
2433      * to retrieve.
2434      * @see #getBinaryStream(String)
2435      */
2436     public java.io.InputStream getBinaryStream(int columnIndex) throws SQLException {
2437 
2438         // always free an old stream
2439         binaryStream = null;
2440 
2441         // sanity check.
2442         checkIndex(columnIndex);
2443         // make sure the cursor is on a valid row
2444         checkCursor();
2445 
2446         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
2447             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2448         }
2449 
2450         Object value = getCurrentRow().getColumnObject(columnIndex);
2451         if (value == null) {
2452             lastValueNull = true;
2453             return null;
2454         }
2455 
2456         binaryStream = new ByteArrayInputStream((byte[])value);
2457 
2458         return (java.io.InputStream)binaryStream;
2459 
2460     }
2461 
2462 
2463     // Methods for accessing results by column name
2464 
2465     /**
2466      * Retrieves the value stored in the designated column
2467      * of the current row as a <code>String</code> object.
2468      *
2469      * @param columnName a <code>String</code> object giving the SQL name of
2470      *        a column in this <code>CachedRowSetImpl</code> object
2471      * @return the column value; if the value is SQL <code>NULL</code>,
2472      *         the result is <code>null</code>
2473      * @throws SQLException if (1) the given column name is not the name of
2474      * a column in this rowset, (2) the cursor is not on one of
2475      * this rowset's rows or its insert row, or (3) the designated
2476      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2477      * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, <b>CHAR</b>,
2478      * <b>VARCHAR</b></code> or <code>LONGVARCHAR<</code> value. The bold SQL type
2479      * designates the recommended return type.
2480      */
2481     public String getString(String columnName) throws SQLException {
2482         return getString(getColIdxByName(columnName));
2483     }
2484 
2485     /**
2486      * Retrieves the value stored in the designated column
2487      * of the current row as a <code>boolean</code> value.
2488      *
2489      * @param columnName a <code>String</code> object giving the SQL name of
2490      *        a column in this <code>CachedRowSetImpl</code> object
2491      * @return the column value as a <code>boolean</code> in the Java programming
2492      *        language; if the value is SQL <code>NULL</code>,
2493      *        the result is <code>false</code>
2494      * @throws SQLException if (1) the given column name is not the name of
2495      *            a column in this rowset, (2) the cursor is not on one of
2496      *            this rowset's rows or its insert row, or (3) the designated
2497      *            column does not store an SQL <code>BOOLEAN</code> value
2498      * @see #getBoolean(int)
2499      */
2500     public boolean getBoolean(String columnName) throws SQLException {
2501         return getBoolean(getColIdxByName(columnName));
2502     }
2503 
2504     /**
2505      * Retrieves the value stored in the designated column
2506      * of the current row as a <code>byte</code> value.
2507      *
2508      * @param columnName a <code>String</code> object giving the SQL name of
2509      *        a column in this <code>CachedRowSetImpl</code> object
2510      * @return the column value as a <code>byte</code> in the Java programming
2511      * language; if the value is SQL <code>NULL</code>, the result is <code>0</code>
2512      * @throws SQLException if (1) the given column name is not the name of
2513      * a column in this rowset, (2) the cursor is not on one of
2514      * this rowset's rows or its insert row, or (3) the designated
2515      * column does not store an SQL <code><B>TINYINT</B>, SMALLINT, INTEGER,
2516      * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2517      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The
2518      * bold type designates the recommended return type
2519      */
2520     public byte getByte(String columnName) throws SQLException {
2521         return getByte(getColIdxByName(columnName));
2522     }
2523 
2524     /**
2525      * Retrieves the value stored in the designated column
2526      * of the current row as a <code>short</code> value.
2527      *
2528      * @param columnName a <code>String</code> object giving the SQL name of
2529      *        a column in this <code>CachedRowSetImpl</code> object
2530      * @return the column value; if the value is SQL <code>NULL</code>,
2531      *         the result is <code>0</code>
2532      * @throws SQLException if (1) the given column name is not the name of
2533      * a column in this rowset, (2) the cursor is not on one of
2534      * this rowset's rows or its insert row, or (3) the designated
2535      * column does not store an SQL <code>TINYINT, <b>SMALLINT</b>, INTEGER
2536      * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2537      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2538      * designates the recommended return type.
2539      * @see #getShort(int)
2540      */
2541     public short getShort(String columnName) throws SQLException {
2542         return getShort(getColIdxByName(columnName));
2543     }
2544 
2545     /**
2546      * Retrieves the value stored in the designated column
2547      * of the current row as an <code>int</code> value.
2548      *
2549      * @param columnName a <code>String</code> object giving the SQL name of
2550      *        a column in this <code>CachedRowSetImpl</code> object
2551      * @return the column value; if the value is SQL <code>NULL</code>,
2552      *         the result is <code>0</code>
2553      * @throws SQLException if (1) the given column name is not the name
2554      * of a column in this rowset,
2555      * (2) the cursor is not on one of this rowset's rows or its
2556      * insert row, or (3) the designated column does not store an
2557      * SQL <code>TINYINT, SMALLINT, <b>INTEGER</b>, BIGINT, REAL
2558      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
2559      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
2560      * recommended return type.
2561      */
2562     public int getInt(String columnName) throws SQLException {
2563         return getInt(getColIdxByName(columnName));
2564     }
2565 
2566     /**
2567      * Retrieves the value stored in the designated column
2568      * of the current row as a <code>long</code> value.
2569      *
2570      * @param columnName a <code>String</code> object giving the SQL name of
2571      *        a column in this <code>CachedRowSetImpl</code> object
2572      * @return the column value; if the value is SQL <code>NULL</code>,
2573      *         the result is <code>0</code>
2574      * @throws SQLException if (1) the given column name is not the name of
2575      * a column in this rowset, (2) the cursor is not on one of
2576      * this rowset's rows or its insert row, or (3) the designated
2577      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2578      * <b>BIGINT</b>, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2579      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2580      * designates the recommended return type.
2581      * @see #getLong(int)
2582      */
2583     public long getLong(String columnName) throws SQLException {
2584         return getLong(getColIdxByName(columnName));
2585     }
2586 
2587     /**
2588      * Retrieves the value stored in the designated column
2589      * of the current row as a <code>float</code> value.
2590      *
2591      * @param columnName a <code>String</code> object giving the SQL name of
2592      *        a column in this <code>CachedRowSetImpl</code> object
2593      * @return the column value; if the value is SQL <code>NULL</code>,
2594      *         the result is <code>0</code>
2595      * @throws SQLException if (1) the given column name is not the name of
2596      * a column in this rowset, (2) the cursor is not on one of
2597      * this rowset's rows or its insert row, or (3) the designated
2598      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2599      * BIGINT, <b>REAL</b>, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2600      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2601      * designates the recommended return type.
2602      * @see #getFloat(String)
2603      */
2604     public float getFloat(String columnName) throws SQLException {
2605         return getFloat(getColIdxByName(columnName));
2606     }
2607 
2608     /**
2609      * Retrieves the value stored in the designated column
2610      * of the current row of this <code>CachedRowSetImpl</code> object
2611      * as a <code>double</code> value.
2612      *
2613      * @param columnName a <code>String</code> object giving the SQL name of
2614      *        a column in this <code>CachedRowSetImpl</code> object
2615      * @return the column value; if the value is SQL <code>NULL</code>,
2616      *         the result is <code>0</code>
2617      * @throws SQLException if (1) the given column name is not the name of
2618      * a column in this rowset, (2) the cursor is not on one of
2619      * this rowset's rows or its insert row, or (3) the designated
2620      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2621      * BIGINT, REAL, <b>FLOAT</b>, <b>DOUBLE</b>, DECIMAL, NUMERIC, BIT, CHAR,
2622      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2623      * designates the recommended return types.
2624      * @see #getDouble(int)
2625      */
2626     public double getDouble(String columnName) throws SQLException {
2627         return getDouble(getColIdxByName(columnName));
2628     }
2629 
2630     /**
2631      * Retrieves the value stored in the designated column
2632      * of the current row as a <code>java.math.BigDecimal</code> object.
2633      *
2634      * @param columnName a <code>String</code> object giving the SQL name of
2635      *        a column in this <code>CachedRowSetImpl</code> object
2636      * @param scale the number of digits to the right of the decimal point
2637      * @return a java.math.BugDecimal object with <code><i>scale</i></code>
2638      * number of digits to the right of the decimal point.
2639      * @throws SQLException if (1) the given column name is not the name of
2640      * a column in this rowset, (2) the cursor is not on one of
2641      * this rowset's rows or its insert row, or (3) the designated
2642      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2643      * BIGINT, REAL, FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT CHAR,
2644      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2645      * designates the recommended return type that this method is used to
2646      * retrieve.
2647      * @deprecated Use the <code>getBigDecimal(String columnName)</code>
2648      *             method instead
2649      */
2650     public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {
2651         return getBigDecimal(getColIdxByName(columnName), scale);
2652     }
2653 
2654     /**
2655      * Retrieves the value stored in the designated column
2656      * of the current row as a <code>byte</code> array.
2657      * The bytes represent the raw values returned by the driver.
2658      *
2659      * @param columnName a <code>String</code> object giving the SQL name of
2660      *        a column in this <code>CachedRowSetImpl</code> object
2661      * @return the column value as a <code>byte</code> array in the Java programming
2662      * language; if the value is SQL <code>NULL</code>, the result is <code>null</code>
2663      * @throws SQLException if (1) the given column name is not the name of
2664      * a column in this rowset, (2) the cursor is not on one of
2665      * this rowset's rows or its insert row, or (3) the designated
2666      * column does not store an SQL <code><b>BINARY</b>, <b>VARBINARY</b>
2667      * </code> or <code>LONGVARBINARY</code> values
2668      * The bold SQL type designates the recommended return type.
2669      * @see #getBytes(int)
2670      */
2671     public byte[] getBytes(String columnName) throws SQLException {
2672         return getBytes(getColIdxByName(columnName));
2673     }
2674 
2675     /**
2676      * Retrieves the value stored in the designated column
2677      * of the current row as a <code>java.sql.Date</code> object.
2678      *
2679      * @param columnName a <code>String</code> object giving the SQL name of
2680      *        a column in this <code>CachedRowSetImpl</code> object
2681      * @return the column value; if the value is SQL <code>NULL</code>,
2682      *         the result is <code>null</code>
2683      * @throws SQLException if (1) the given column name is not the name of
2684      *            a column in this rowset, (2) the cursor is not on one of
2685      *            this rowset's rows or its insert row, or (3) the designated
2686      *            column does not store an SQL <code>DATE</code> or
2687      *            <code>TIMESTAMP</code> value
2688      */
2689     public java.sql.Date getDate(String columnName) throws SQLException {
2690         return getDate(getColIdxByName(columnName));
2691     }
2692 
2693     /**
2694      * Retrieves the value stored in the designated column
2695      * of the current row as a <code>java.sql.Time</code> object.
2696      *
2697      * @param columnName a <code>String</code> object giving the SQL name of
2698      *        a column in this <code>CachedRowSetImpl</code> object
2699      * @return the column value; if the value is SQL <code>NULL</code>,
2700      *         the result is <code>null</code>
2701      * @throws SQLException if the given column name does not match one of
2702      *            this rowset's column names or the cursor is not on one of
2703      *            this rowset's rows or its insert row
2704      */
2705     public java.sql.Time getTime(String columnName) throws SQLException {
2706         return getTime(getColIdxByName(columnName));
2707     }
2708 
2709     /**
2710      * Retrieves the value stored in the designated column
2711      * of the current row as a <code>java.sql.Timestamp</code> object.
2712      *
2713      * @param columnName a <code>String</code> object giving the SQL name of
2714      *        a column in this <code>CachedRowSetImpl</code> object
2715      * @return the column value; if the value is SQL <code>NULL</code>,
2716      *         the result is <code>null</code>
2717      * @throws SQLException if the given column name does not match one of
2718      *            this rowset's column names or the cursor is not on one of
2719      *            this rowset's rows or its insert row
2720      */
2721     public java.sql.Timestamp getTimestamp(String columnName) throws SQLException {
2722         return getTimestamp(getColIdxByName(columnName));
2723     }
2724 
2725     /**
2726      * Retrieves the value of the designated column in the current row of this
2727      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2728      * object.
2729      *
2730      * A column value can be retrieved as a stream of ASCII characters
2731      * and then read in chunks from the stream. This method is particularly
2732      * suitable for retrieving large <code>LONGVARCHAR</code> values. The
2733      * <code>SyncProvider</code> will rely on the JDBC driver to do any necessary
2734      * conversion from the database format into ASCII format.
2735      *
2736      * <P><B>Note:</B> All the data in the returned stream must
2737      * be read prior to getting the value of any other column. The
2738      * next call to a <code>getXXX</code> method implicitly closes the stream.
2739      *
2740      * @param columnName a <code>String</code> object giving the SQL name of
2741      *        a column in this <code>CachedRowSetImpl</code> object
2742      * @return a Java input stream that delivers the database column value
2743      *         as a stream of one-byte ASCII characters.  If the value is SQL
2744      *         <code>NULL</code>, the result is <code>null</code>.
2745      * @throws SQLException if (1) the given column name is not the name of
2746      * a column in this rowset
2747      * (2) the cursor is not on one of this rowset's rows or its
2748      * insert row, or (3) the designated column does not store an
2749      * SQL <code>CHAR, VARCHAR</code>, <code><b>LONGVARCHAR</b></code>
2750      * <code>BINARY, VARBINARY</code> or <code>LONGVARBINARY</code> value. The
2751      * bold SQL type designates the recommended return types that this method is
2752      * used to retrieve.
2753      * @see #getAsciiStream(int)
2754      */
2755     public java.io.InputStream getAsciiStream(String columnName) throws SQLException {
2756         return getAsciiStream(getColIdxByName(columnName));
2757 
2758     }
2759 
2760     /**
2761      * A column value can be retrieved as a stream of Unicode characters
2762      * and then read in chunks from the stream.  This method is particularly
2763      * suitable for retrieving large <code>LONGVARCHAR</code> values.
2764      * The JDBC driver will do any necessary conversion from the database
2765      * format into Unicode.
2766      *
2767      * <P><B>Note:</B> All the data in the returned stream must
2768      * be read prior to getting the value of any other column. The
2769      * next call to a <code>getXXX</code> method implicitly closes the stream.
2770      *
2771      * @param columnName a <code>String</code> object giving the SQL name of
2772      *        a column in this <code>CachedRowSetImpl</code> object
2773      * @return a Java input stream that delivers the database column value
2774      *         as a stream of two-byte Unicode characters.  If the value is
2775      *         SQL <code>NULL</code>, the result is <code>null</code>.
2776      * @throws SQLException if the given column name does not match one of
2777      *            this rowset's column names or the cursor is not on one of
2778      *            this rowset's rows or its insert row
2779      * @deprecated use the method <code>getCharacterStream</code> instead
2780      */
2781     public java.io.InputStream getUnicodeStream(String columnName) throws SQLException {
2782         return getUnicodeStream(getColIdxByName(columnName));
2783     }
2784 
2785     /**
2786      * Retrieves the value of the designated column in the current row of this
2787      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2788      * object.
2789      * <P>
2790      * A column value can be retrieved as a stream of uninterpreted bytes
2791      * and then read in chunks from the stream.  This method is particularly
2792      * suitable for retrieving large <code>LONGVARBINARY</code> values.
2793      *
2794      * <P><B>Note:</B> All the data in the returned stream must be
2795      * read prior to getting the value of any other column. The next
2796      * call to a get method implicitly closes the stream. Also, a
2797      * stream may return <code>0</code> for <code>CachedRowSetImpl.available()</code>
2798      * whether there is data available or not.
2799      *
2800      * @param columnName a <code>String</code> object giving the SQL name of
2801      *        a column in this <code>CachedRowSetImpl</code> object
2802      * @return a Java input stream that delivers the database column value
2803      *         as a stream of uninterpreted bytes.  If the value is SQL
2804      *         <code>NULL</code>, the result is <code>null</code>.
2805      * @throws SQLException if (1) the given column name is unknown,
2806      * (2) the cursor is not on one of this rowset's rows or its
2807      * insert row, or (3) the designated column does not store an
2808      * SQL <code>BINARY, VARBINARY</code> or <code><b>LONGVARBINARY</b></code>
2809      * The bold type indicates the SQL type that this method is recommened
2810      * to retrieve.
2811      * @see #getBinaryStream(int)
2812      *
2813      */
2814     public java.io.InputStream getBinaryStream(String columnName) throws SQLException {
2815         return getBinaryStream(getColIdxByName(columnName));
2816     }
2817 
2818 
2819     // Advanced features:
2820 
2821     /**
2822      * The first warning reported by calls on this <code>CachedRowSetImpl</code>
2823      * object is returned. Subsequent <code>CachedRowSetImpl</code> warnings will
2824      * be chained to this <code>SQLWarning</code>.
2825      *
2826      * <P>The warning chain is automatically cleared each time a new
2827      * row is read.
2828      *
2829      * <P><B>Note:</B> This warning chain only covers warnings caused
2830      * by <code>ResultSet</code> methods.  Any warning caused by statement
2831      * methods (such as reading OUT parameters) will be chained on the
2832      * <code>Statement</code> object.
2833      *
2834      * @return the first SQLWarning or null
2835      */
2836     public SQLWarning getWarnings() {
2837         return sqlwarn;
2838     }
2839 
2840     /**
2841      * Clears all the warnings reporeted for the <code>CachedRowSetImpl</code>
2842      * object. After a call to this method, the <code>getWarnings</code> method
2843      * returns <code>null</code> until a new warning is reported for this
2844      * <code>CachedRowSetImpl</code> object.
2845      */
2846     public void clearWarnings() {
2847         sqlwarn = null;
2848     }
2849 
2850     /**
2851      * Retrieves the name of the SQL cursor used by this
2852      * <code>CachedRowSetImpl</code> object.
2853      *
2854      * <P>In SQL, a result table is retrieved through a cursor that is
2855      * named. The current row of a <code>ResultSet</code> can be updated or deleted
2856      * using a positioned update/delete statement that references the
2857      * cursor name. To ensure that the cursor has the proper isolation
2858      * level to support an update operation, the cursor's <code>SELECT</code>
2859      * statement should be of the form <code>select for update</code>.
2860      * If the <code>for update</code> clause
2861      * is omitted, positioned updates may fail.
2862      *
2863      * <P>JDBC supports this SQL feature by providing the name of the
2864      * SQL cursor used by a <code>ResultSet</code> object. The current row
2865      * of a result set is also the current row of this SQL cursor.
2866      *
2867      * <P><B>Note:</B> If positioned updates are not supported, an
2868      * <code>SQLException</code> is thrown.
2869      *
2870      * @return the SQL cursor name for this <code>CachedRowSetImpl</code> object's
2871      *         cursor
2872      * @throws SQLException if an error occurs
2873      */
2874     public String getCursorName() throws SQLException {
2875         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.posupdate").toString());
2876     }
2877 
2878     /**
2879      * Retrieves a <code>ResultSetMetaData</code> object instance that
2880      * contains information about the <code>CachedRowSet</code> object.
2881      * However, applications should cast the returned object to a
2882      * <code>RowSetMetaData</code> interface implementation. In the
2883      * reference implementation, this cast can be done on the
2884      * <code>RowSetMetaDataImpl</code> class.
2885      * <P>
2886      * For example:
2887      * <pre>
2888      * CachedRowSet crs = new CachedRowSetImpl();
2889      * RowSetMetaDataImpl metaData =
2890      *     (RowSetMetaDataImpl)crs.getMetaData();
2891      * // Set the number of columns in the RowSet object for
2892      * // which this RowSetMetaDataImpl object was created to the
2893      * // given number.
2894      * metaData.setColumnCount(3);
2895      * crs.setMetaData(metaData);
2896      * </pre>
2897      *
2898      * @return the <code>ResultSetMetaData</code> object that describes this
2899      *         <code>CachedRowSetImpl</code> object's columns
2900      * @throws SQLException if an error occurs in generating the RowSet
2901      * meta data; or if the <code>CachedRowSetImpl</code> is empty.
2902      * @see javax.sql.RowSetMetaData
2903      */
2904     public ResultSetMetaData getMetaData() throws SQLException {
2905         return (ResultSetMetaData)RowSetMD;
2906     }
2907 
2908 
2909     /**
2910      * Retrieves the value of the designated column in the current row
2911      * of this <code>CachedRowSetImpl</code> object as an
2912      * <code>Object</code> value.
2913      * <P>
2914      * The type of the <code>Object</code> will be the default
2915      * Java object type corresponding to the column's SQL type,
2916      * following the mapping for built-in types specified in the JDBC 3.0
2917      * specification.
2918      * <P>
2919      * This method may also be used to read datatabase-specific
2920      * abstract data types.
2921      * <P>
2922      * This implementation of the method <code>getObject</code> extends its
2923      * behavior so that it gets the attributes of an SQL structured type
2924      * as an array of <code>Object</code> values.  This method also custom
2925      * maps SQL user-defined types to classes in the Java programming language.
2926      * When the specified column contains
2927      * a structured or distinct value, the behavior of this method is as
2928      * if it were a call to the method <code>getObject(columnIndex,
2929      * this.getStatement().getConnection().getTypeMap())</code>.
2930      *
2931      * @param columnIndex the first column is <code>1</code>, the second
2932      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2933      *        and equal to or less than the number of columns in the rowset
2934      * @return a <code>java.lang.Object</code> holding the column value;
2935      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
2936      * @throws SQLException if the given column index is out of bounds,
2937      *            the cursor is not on a valid row, or there is a problem getting
2938      *            the <code>Class</code> object for a custom mapping
2939      * @see #getObject(String)
2940      */
2941     public Object getObject(int columnIndex) throws SQLException {
2942         Object value;
2943         Map<String, Class<?>> map;
2944 
2945         // sanity check.
2946         checkIndex(columnIndex);
2947         // make sure the cursor is on a valid row
2948         checkCursor();
2949 
2950         setLastValueNull(false);
2951         value = getCurrentRow().getColumnObject(columnIndex);
2952 
2953         // check for SQL NULL
2954         if (value == null) {
2955             setLastValueNull(true);
2956             return null;
2957         }
2958         if (value instanceof Struct) {
2959             Struct s = (Struct)value;
2960             map = getTypeMap();
2961             // look up the class in the map
2962             Class c = (Class)map.get(s.getSQLTypeName());
2963             if (c != null) {
2964                 // create new instance of the class
2965                 SQLData obj = null;
2966                 try {
2967                     obj = (SQLData)c.newInstance();
2968                 } catch (java.lang.InstantiationException ex) {
2969                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
2970                     ex.getMessage()));
2971                 } catch (java.lang.IllegalAccessException ex) {
2972                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
2973                     ex.getMessage()));
2974                 }
2975                 // get the attributes from the struct
2976                 Object attribs[] = s.getAttributes(map);
2977                 // create the SQLInput "stream"
2978                 SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
2979                 // read the values...
2980                 obj.readSQL(sqlInput, s.getSQLTypeName());
2981                 return (Object)obj;
2982             }
2983         }
2984         return value;
2985     }
2986 
2987     /**
2988      * Retrieves the value of the designated column in the current row
2989      * of this <code>CachedRowSetImpl</code> object as an
2990      * <code>Object</code> value.
2991      * <P>
2992      * The type of the <code>Object</code> will be the default
2993      * Java object type corresponding to the column's SQL type,
2994      * following the mapping for built-in types specified in the JDBC 3.0
2995      * specification.
2996      * <P>
2997      * This method may also be used to read datatabase-specific
2998      * abstract data types.
2999      * <P>
3000      * This implementation of the method <code>getObject</code> extends its
3001      * behavior so that it gets the attributes of an SQL structured type
3002      * as an array of <code>Object</code> values.  This method also custom
3003      * maps SQL user-defined types to classes
3004      * in the Java programming language. When the specified column contains
3005      * a structured or distinct value, the behavior of this method is as
3006      * if it were a call to the method <code>getObject(columnIndex,
3007      * this.getStatement().getConnection().getTypeMap())</code>.
3008      *
3009      * @param columnName a <code>String</code> object that must match the
3010      *        SQL name of a column in this rowset, ignoring case
3011      * @return a <code>java.lang.Object</code> holding the column value;
3012      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3013      * @throws SQLException if (1) the given column name does not match one of
3014      *            this rowset's column names, (2) the cursor is not
3015      *            on a valid row, or (3) there is a problem getting
3016      *            the <code>Class</code> object for a custom mapping
3017      * @see #getObject(int)
3018      */
3019     public Object getObject(String columnName) throws SQLException {
3020         return getObject(getColIdxByName(columnName));
3021     }
3022 
3023     //----------------------------------------------------------------
3024 
3025     /**
3026      * Maps the given column name for one of this <code>CachedRowSetImpl</code>
3027      * object's columns to its column number.
3028      *
3029      * @param columnName a <code>String</code> object that must match the
3030      *        SQL name of a column in this rowset, ignoring case
3031      * @return the column index of the given column name
3032      * @throws SQLException if the given column name does not match one
3033      *            of this rowset's column names
3034      */
3035     public int findColumn(String columnName) throws SQLException {
3036         return getColIdxByName(columnName);
3037     }
3038 
3039 
3040     //--------------------------JDBC 2.0-----------------------------------
3041 
3042     //---------------------------------------------------------------------
3043     // Getter's and Setter's
3044     //---------------------------------------------------------------------
3045 
3046     /**
3047      * Retrieves the value stored in the designated column
3048      * of the current row as a <code>java.io.Reader</code> object.
3049      *
3050      * <P><B>Note:</B> All the data in the returned stream must
3051      * be read prior to getting the value of any other column. The
3052      * next call to a <code>getXXX</code> method implicitly closes the stream.
3053      *
3054      * @param columnIndex the first column is <code>1</code>, the second
3055      *        is <code>2</code>, and so on; must be <code>1</code> or larger
3056      *        and equal to or less than the number of columns in the rowset
3057      * @return a Java character stream that delivers the database column value
3058      * as a stream of two-byte unicode characters in a
3059      * <code>java.io.Reader</code> object.  If the value is
3060      * SQL <code>NULL</code>, the result is <code>null</code>.
3061      * @throws SQLException if (1) the given column index is out of bounds,
3062      * (2) the cursor is not on one of this rowset's rows or its
3063      * insert row, or (3) the designated column does not store an
3064      * SQL <code>CHAR, VARCHAR, <b>LONGVARCHAR</b>, BINARY, VARBINARY</code> or
3065      * <code>LONGVARBINARY</code> value.
3066      * The bold SQL type designates the recommended return type.
3067      * @see #getCharacterStream(String)
3068      */
3069     public java.io.Reader getCharacterStream(int columnIndex) throws SQLException{
3070 
3071         // sanity check.
3072         checkIndex(columnIndex);
3073         // make sure the cursor is on a valid row
3074         checkCursor();
3075 
3076         if (isBinary(RowSetMD.getColumnType(columnIndex))) {
3077             Object value = getCurrentRow().getColumnObject(columnIndex);
3078             if (value == null) {
3079                 lastValueNull = true;
3080                 return null;
3081             }
3082             charStream = new InputStreamReader
3083             (new ByteArrayInputStream((byte[])value));
3084         } else if (isString(RowSetMD.getColumnType(columnIndex))) {
3085             Object value = getCurrentRow().getColumnObject(columnIndex);
3086             if (value == null) {
3087                 lastValueNull = true;
3088                 return null;
3089             }
3090             charStream = new StringReader(value.toString());
3091         } else {
3092             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
3093         }
3094 
3095         return (java.io.Reader)charStream;
3096     }
3097 
3098     /**
3099      * Retrieves the value stored in the designated column
3100      * of the current row as a <code>java.io.Reader</code> object.
3101      *
3102      * <P><B>Note:</B> All the data in the returned stream must
3103      * be read prior to getting the value of any other column. The
3104      * next call to a <code>getXXX</code> method implicitly closes the stream.
3105      *
3106      * @param columnName a <code>String</code> object giving the SQL name of
3107      *        a column in this <code>CachedRowSetImpl</code> object
3108      * @return a Java input stream that delivers the database column value
3109      *         as a stream of two-byte Unicode characters.  If the value is
3110      *         SQL <code>NULL</code>, the result is <code>null</code>.
3111      * @throws SQLException if (1) the given column name is not the name of
3112      * a column in this rowset, (2) the cursor is not on one of
3113      * this rowset's rows or its insert row, or (3) the designated
3114      * column does not store an SQL <code>CHAR, VARCHAR, <b>LONGVARCHAR</b>,
3115      * BINARY, VARYBINARY</code> or <code>LONGVARBINARY</code> value.
3116      * The bold SQL type designates the recommended return type.
3117      */
3118     public java.io.Reader getCharacterStream(String columnName) throws SQLException {
3119         return getCharacterStream(getColIdxByName(columnName));
3120     }
3121 
3122     /**
3123      * Retrieves the value of the designated column in the current row
3124      * of this <code>CachedRowSetImpl</code> object as a
3125      * <code>java.math.BigDecimal</code> object.
3126      *
3127      * @param columnIndex the first column is <code>1</code>, the second
3128      *        is <code>2</code>, and so on; must be <code>1</code> or larger
3129      *        and equal to or less than the number of columns in the rowset
3130      * @return a <code>java.math.BigDecimal</code> value with full precision;
3131      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3132      * @throws SQLException if (1) the given column index is out of bounds,
3133      * (2) the cursor is not on one of this rowset's rows or its
3134      * insert row, or (3) the designated column does not store an
3135      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
3136      * FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT, CHAR, VARCHAR</code>
3137      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
3138      * recommended return types that this method is used to retrieve.
3139      * @see #getBigDecimal(String)
3140      */
3141     public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
3142         Object value;
3143 
3144         // sanity check.
3145         checkIndex(columnIndex);
3146         // make sure the cursor is on a valid row
3147         checkCursor();
3148 
3149         setLastValueNull(false);
3150         value = getCurrentRow().getColumnObject(columnIndex);
3151 
3152         // check for SQL NULL
3153         if (value == null) {
3154             setLastValueNull(true);
3155             return null;
3156         }
3157         try {
3158             return (new BigDecimal(value.toString().trim()));
3159         } catch (NumberFormatException ex) {
3160             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.doublefail").toString(),
3161                 new Object[] {value.toString().trim(), columnIndex}));
3162         }
3163     }
3164 
3165     /**
3166      * Retrieves the value of the designated column in the current row
3167      * of this <code>CachedRowSetImpl</code> object as a
3168      * <code>java.math.BigDecimal</code> object.
3169      *
3170      * @param columnName a <code>String</code> object that must match the
3171      *        SQL name of a column in this rowset, ignoring case
3172      * @return a <code>java.math.BigDecimal</code> value with full precision;
3173      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3174      * @throws SQLException if (1) the given column name is not the name of
3175      * a column in this rowset, (2) the cursor is not on one of
3176      * this rowset's rows or its insert row, or (3) the designated
3177      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
3178      * BIGINT, REAL, FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT CHAR,
3179      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
3180      * designates the recommended return type that this method is used to
3181      * retrieve
3182      * @see #getBigDecimal(int)
3183      */
3184     public BigDecimal getBigDecimal(String columnName) throws SQLException {
3185         return getBigDecimal(getColIdxByName(columnName));
3186     }
3187 
3188     //---------------------------------------------------------------------
3189     // Traversal/Positioning
3190     //---------------------------------------------------------------------
3191 
3192     /**
3193      * Returns the number of rows in this <code>CachedRowSetImpl</code> object.
3194      *
3195      * @return number of rows in the rowset
3196      */
3197     public int size() {
3198         return numRows;
3199     }
3200 
3201     /**
3202      * Indicates whether the cursor is before the first row in this
3203      * <code>CachedRowSetImpl</code> object.
3204      *
3205      * @return <code>true</code> if the cursor is before the first row;
3206      *         <code>false</code> otherwise or if the rowset contains no rows
3207      * @throws SQLException if an error occurs
3208      */
3209     public boolean isBeforeFirst() throws SQLException {
3210         if (cursorPos == 0 && numRows > 0) {
3211             return true;
3212         } else {
3213             return false;
3214         }
3215     }
3216 
3217     /**
3218      * Indicates whether the cursor is after the last row in this
3219      * <code>CachedRowSetImpl</code> object.
3220      *
3221      * @return <code>true</code> if the cursor is after the last row;
3222      *         <code>false</code> otherwise or if the rowset contains no rows
3223      * @throws SQLException if an error occurs
3224      */
3225     public boolean isAfterLast() throws SQLException {
3226         if (cursorPos == numRows+1 && numRows > 0) {
3227             return true;
3228         } else {
3229             return false;
3230         }
3231     }
3232 
3233     /**
3234      * Indicates whether the cursor is on the first row in this
3235      * <code>CachedRowSetImpl</code> object.
3236      *
3237      * @return <code>true</code> if the cursor is on the first row;
3238      *         <code>false</code> otherwise or if the rowset contains no rows
3239      * @throws SQLException if an error occurs
3240      */
3241     public boolean isFirst() throws SQLException {
3242         // this becomes nasty because of deletes.
3243         int saveCursorPos = cursorPos;
3244         int saveAbsoluteCursorPos = absolutePos;
3245         internalFirst();
3246         if (cursorPos == saveCursorPos) {
3247             return true;
3248         } else {
3249             cursorPos = saveCursorPos;
3250             absolutePos = saveAbsoluteCursorPos;
3251             return false;
3252         }
3253     }
3254 
3255     /**
3256      * Indicates whether the cursor is on the last row in this
3257      * <code>CachedRowSetImpl</code> object.
3258      * <P>
3259      * Note: Calling the method <code>isLast</code> may be expensive
3260      * because the JDBC driver might need to fetch ahead one row in order
3261      * to determine whether the current row is the last row in this rowset.
3262      *
3263      * @return <code>true</code> if the cursor is on the last row;
3264      *         <code>false</code> otherwise or if this rowset contains no rows
3265      * @throws SQLException if an error occurs
3266      */
3267     public boolean isLast() throws SQLException {
3268         int saveCursorPos = cursorPos;
3269         int saveAbsoluteCursorPos = absolutePos;
3270         boolean saveShowDeleted = getShowDeleted();
3271         setShowDeleted(true);
3272         internalLast();
3273         if (cursorPos == saveCursorPos) {
3274             setShowDeleted(saveShowDeleted);
3275             return true;
3276         } else {
3277             setShowDeleted(saveShowDeleted);
3278             cursorPos = saveCursorPos;
3279             absolutePos = saveAbsoluteCursorPos;
3280             return false;
3281         }
3282     }
3283 
3284     /**
3285      * Moves this <code>CachedRowSetImpl</code> object's cursor to the front of
3286      * the rowset, just before the first row. This method has no effect if
3287      * this rowset contains no rows.
3288      *
3289      * @throws SQLException if an error occurs or the type of this rowset
3290      *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3291      */
3292     public void beforeFirst() throws SQLException {
3293        if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3294             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.beforefirst").toString());
3295         }
3296         cursorPos = 0;
3297         absolutePos = 0;
3298         notifyCursorMoved();
3299     }
3300 
3301     /**
3302      * Moves this <code>CachedRowSetImpl</code> object's cursor to the end of
3303      * the rowset, just after the last row. This method has no effect if
3304      * this rowset contains no rows.
3305      *
3306      * @throws SQLException if an error occurs
3307      */
3308     public void afterLast() throws SQLException {
3309         if (numRows > 0) {
3310             cursorPos = numRows + 1;
3311             absolutePos = 0;
3312             notifyCursorMoved();
3313         }
3314     }
3315 
3316     /**
3317      * Moves this <code>CachedRowSetImpl</code> object's cursor to the first row
3318      * and returns <code>true</code> if the operation was successful.  This
3319      * method also notifies registered listeners that the cursor has moved.
3320      *
3321      * @return <code>true</code> if the cursor is on a valid row;
3322      *         <code>false</code> otherwise or if there are no rows in this
3323      *         <code>CachedRowSetImpl</code> object
3324      * @throws SQLException if the type of this rowset
3325      *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3326      */
3327     public boolean first() throws SQLException {
3328         if(getType() == ResultSet.TYPE_FORWARD_ONLY) {
3329             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.first").toString());
3330         }
3331 
3332         // move and notify
3333         boolean ret = this.internalFirst();
3334         notifyCursorMoved();
3335 
3336         return ret;
3337     }
3338 
3339     /**
3340      * Moves this <code>CachedRowSetImpl</code> object's cursor to the first
3341      * row and returns <code>true</code> if the operation is successful.
3342      * <P>
3343      * This method is called internally by the methods <code>first</code>,
3344      * <code>isFirst</code>, and <code>absolute</code>.
3345      * It in turn calls the method <code>internalNext</code> in order to
3346      * handle the case where the first row is a deleted row that is not visible.
3347      * <p>
3348      * This is a implementation only method and is not required as a standard
3349      * implementation of the <code>CachedRowSet</code> interface.
3350      *
3351      * @return <code>true</code> if the cursor moved to the first row;
3352      *         <code>false</code> otherwise
3353      * @throws SQLException if an error occurs
3354      */
3355     protected boolean internalFirst() throws SQLException {
3356         boolean ret = false;
3357 
3358         if (numRows > 0) {
3359             cursorPos = 1;
3360             if ((getShowDeleted() == false) && (rowDeleted() == true)) {
3361                 ret = internalNext();
3362             } else {
3363                 ret = true;
3364             }
3365         }
3366 
3367         if (ret == true)
3368             absolutePos = 1;
3369         else
3370             absolutePos = 0;
3371 
3372         return ret;
3373     }
3374 
3375     /**
3376      * Moves this <code>CachedRowSetImpl</code> object's cursor to the last row
3377      * and returns <code>true</code> if the operation was successful.  This
3378      * method also notifies registered listeners that the cursor has moved.
3379      *
3380      * @return <code>true</code> if the cursor is on a valid row;
3381      *         <code>false</code> otherwise or if there are no rows in this
3382      *         <code>CachedRowSetImpl</code> object
3383      * @throws SQLException if the type of this rowset
3384      *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3385      */
3386     public boolean last() throws SQLException {
3387         if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3388             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.last").toString());
3389         }
3390 
3391         // move and notify
3392         boolean ret = this.internalLast();
3393         notifyCursorMoved();
3394 
3395         return ret;
3396     }
3397 
3398     /**
3399      * Moves this <code>CachedRowSetImpl</code> object's cursor to the last
3400      * row and returns <code>true</code> if the operation is successful.
3401      * <P>
3402      * This method is called internally by the method <code>last</code>
3403      * when rows have been deleted and the deletions are not visible.
3404      * The method <code>internalLast</code> handles the case where the
3405      * last row is a deleted row that is not visible by in turn calling
3406      * the method <code>internalPrevious</code>.
3407      * <p>
3408      * This is a implementation only method and is not required as a standard
3409      * implementation of the <code>CachedRowSet</code> interface.
3410      *
3411      * @return <code>true</code> if the cursor moved to the last row;
3412      *         <code>false</code> otherwise
3413      * @throws SQLException if an error occurs
3414      */
3415     protected boolean internalLast() throws SQLException {
3416         boolean ret = false;
3417 
3418         if (numRows > 0) {
3419             cursorPos = numRows;
3420             if ((getShowDeleted() == false) && (rowDeleted() == true)) {
3421                 ret = internalPrevious();
3422             } else {
3423                 ret = true;
3424             }
3425         }
3426         if (ret == true)
3427             absolutePos = numRows - numDeleted;
3428         else
3429             absolutePos = 0;
3430         return ret;
3431     }
3432 
3433     /**
3434      * Returns the number of the current row in this <code>CachedRowSetImpl</code>
3435      * object. The first row is number 1, the second number 2, and so on.
3436      *
3437      * @return the number of the current row;  <code>0</code> if there is no
3438      *         current row
3439      * @throws SQLException if an error occurs; or if the <code>CacheRowSetImpl</code>
3440      *         is empty
3441      */
3442     public int getRow() throws SQLException {
3443         // are we on a valid row? Valid rows are between first and last
3444         if (numRows > 0 &&
3445         cursorPos > 0 &&
3446         cursorPos < (numRows + 1) &&
3447         (getShowDeleted() == false && rowDeleted() == false)) {
3448             return absolutePos;
3449         } else if (getShowDeleted() == true) {
3450             return cursorPos;
3451         } else {
3452             return 0;
3453         }
3454     }
3455 
3456     /**
3457      * Moves this <code>CachedRowSetImpl</code> object's cursor to the row number
3458      * specified.
3459      *
3460      * <p>If the number is positive, the cursor moves to an absolute row with
3461      * respect to the beginning of the rowset.  The first row is row 1, the second
3462      * is row 2, and so on.  For example, the following command, in which
3463      * <code>crs</code> is a <code>CachedRowSetImpl</code> object, moves the cursor
3464      * to the fourth row, starting from the beginning of the rowset.
3465      * <PRE><code>
3466      *
3467      *    crs.absolute(4);
3468      *
3469      * </code> </PRE>
3470      * <P>
3471      * If the number is negative, the cursor moves to an absolute row position
3472      * with respect to the end of the rowset.  For example, calling
3473      * <code>absolute(-1)</code> positions the cursor on the last row,
3474      * <code>absolute(-2)</code> moves it on the next-to-last row, and so on.
3475      * If the <code>CachedRowSetImpl</code> object <code>crs</code> has five rows,
3476      * the following command moves the cursor to the fourth-to-last row, which
3477      * in the case of a  rowset with five rows, is also the second row, counting
3478      * from the beginning.
3479      * <PRE><code>
3480      *
3481      *    crs.absolute(-4);
3482      *
3483      * </code> </PRE>
3484      *
3485      * If the number specified is larger than the number of rows, the cursor
3486      * will move to the position after the last row. If the number specified
3487      * would move the cursor one or more rows before the first row, the cursor
3488      * moves to the position before the first row.
3489      * <P>
3490      * Note: Calling <code>absolute(1)</code> is the same as calling the
3491      * method <code>first()</code>.  Calling <code>absolute(-1)</code> is the
3492      * same as calling <code>last()</code>.
3493      *
3494      * @param row a positive number to indicate the row, starting row numbering from
3495      *        the first row, which is <code>1</code>; a negative number to indicate
3496      *        the row, starting row numbering from the last row, which is
3497      *        <code>-1</code>; it must not be <code>0</code>
3498      * @return <code>true</code> if the cursor is on the rowset; <code>false</code>
3499      *         otherwise
3500      * @throws SQLException if the given cursor position is <code>0</code> or the
3501      *            type of this rowset is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3502      */
3503     public boolean absolute( int row ) throws SQLException {
3504         if (row == 0 || getType() == ResultSet.TYPE_FORWARD_ONLY) {
3505             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.absolute").toString());
3506         }
3507 
3508         if (row > 0) { // we are moving foward
3509             if (row > numRows) {
3510                 // fell off the end
3511                 afterLast();
3512                 return false;
3513             } else {
3514                 if (absolutePos <= 0)
3515                     internalFirst();
3516             }
3517         } else { // we are moving backward
3518             if (cursorPos + row < 0) {
3519                 // fell off the front
3520                 beforeFirst();
3521                 return false;
3522             } else {
3523                 if (absolutePos >= 0)
3524                     internalLast();
3525             }
3526         }
3527 
3528         // Now move towards the absolute row that we're looking for
3529         while (absolutePos != row) {
3530             if (absolutePos < row) {
3531                 if (!internalNext())
3532                     break;
3533             }
3534             else {
3535                 if (!internalPrevious())
3536                     break;
3537             }
3538         }
3539 
3540         notifyCursorMoved();
3541 
3542         if (isAfterLast() || isBeforeFirst()) {
3543             return false;
3544         } else {
3545             return true;
3546         }
3547     }
3548 
3549     /**
3550      * Moves the cursor the specified number of rows from the current
3551      * position, with a positive number moving it forward and a
3552      * negative number moving it backward.
3553      * <P>
3554      * If the number is positive, the cursor moves the specified number of
3555      * rows toward the end of the rowset, starting at the current row.
3556      * For example, the following command, in which
3557      * <code>crs</code> is a <code>CachedRowSetImpl</code> object with 100 rows,
3558      * moves the cursor forward four rows from the current row.  If the
3559      * current row is 50, the cursor would move to row 54.
3560      * <PRE><code>
3561      *
3562      *    crs.relative(4);
3563      *
3564      * </code> </PRE>
3565      * <P>
3566      * If the number is negative, the cursor moves back toward the beginning
3567      * the specified number of rows, starting at the current row.
3568      * For example, calling the method
3569      * <code>absolute(-1)</code> positions the cursor on the last row,
3570      * <code>absolute(-2)</code> moves it on the next-to-last row, and so on.
3571      * If the <code>CachedRowSetImpl</code> object <code>crs</code> has five rows,
3572      * the following command moves the cursor to the fourth-to-last row, which
3573      * in the case of a  rowset with five rows, is also the second row
3574      * from the beginning.
3575      * <PRE><code>
3576      *
3577      *    crs.absolute(-4);
3578      *
3579      * </code> </PRE>
3580      *
3581      * If the number specified is larger than the number of rows, the cursor
3582      * will move to the position after the last row. If the number specified
3583      * would move the cursor one or more rows before the first row, the cursor
3584      * moves to the position before the first row. In both cases, this method
3585      * throws an <code>SQLException</code>.
3586      * <P>
3587      * Note: Calling <code>absolute(1)</code> is the same as calling the
3588      * method <code>first()</code>.  Calling <code>absolute(-1)</code> is the
3589      * same as calling <code>last()</code>.  Calling <code>relative(0)</code>
3590      * is valid, but it does not change the cursor position.
3591      *
3592      * @param rows an <code>int</code> indicating the number of rows to move
3593      *             the cursor, starting at the current row; a positive number
3594      *             moves the cursor forward; a negative number moves the cursor
3595      *             backward; must not move the cursor past the valid
3596      *             rows
3597      * @return <code>true</code> if the cursor is on a row in this
3598      *         <code>CachedRowSetImpl</code> object; <code>false</code>
3599      *         otherwise
3600      * @throws SQLException if there are no rows in this rowset, the cursor is
3601      *         positioned either before the first row or after the last row, or
3602      *         the rowset is type <code>ResultSet.TYPE_FORWARD_ONLY</code>
3603      */
3604     public boolean relative(int rows) throws SQLException {
3605         if (numRows == 0 || isBeforeFirst() ||
3606         isAfterLast() || getType() == ResultSet.TYPE_FORWARD_ONLY) {
3607             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.relative").toString());
3608         }
3609 
3610         if (rows == 0) {
3611             return true;
3612         }
3613 
3614         if (rows > 0) { // we are moving forward
3615             if (cursorPos + rows > numRows) {
3616                 // fell off the end
3617                 afterLast();
3618             } else {
3619                 for (int i=0; i < rows; i++) {
3620                     if (!internalNext())
3621                         break;
3622                 }
3623             }
3624         } else { // we are moving backward
3625             if (cursorPos + rows < 0) {
3626                 // fell off the front
3627                 beforeFirst();
3628             } else {
3629                 for (int i=rows; i < 0; i++) {
3630                     if (!internalPrevious())
3631                         break;
3632                 }
3633             }
3634         }
3635         notifyCursorMoved();
3636 
3637         if (isAfterLast() || isBeforeFirst()) {
3638             return false;
3639         } else {
3640             return true;
3641         }
3642     }
3643 
3644     /**
3645      * Moves this <code>CachedRowSetImpl</code> object's cursor to the
3646      * previous row and returns <code>true</code> if the cursor is on
3647      * a valid row or <code>false</code> if it is not.
3648      * This method also notifies all listeners registered with this
3649      * <code>CachedRowSetImpl</code> object that its cursor has moved.
3650      * <P>
3651      * Note: calling the method <code>previous()</code> is not the same
3652      * as calling the method <code>relative(-1)</code>.  This is true
3653      * because it is possible to call <code>previous()</code> from the insert
3654      * row, from after the last row, or from the current row, whereas
3655      * <code>relative</code> may only be called from the current row.
3656      * <P>
3657      * The method <code>previous</code> may used in a <code>while</code>
3658      * loop to iterate through a rowset starting after the last row
3659      * and moving toward the beginning. The loop ends when <code>previous</code>
3660      * returns <code>false</code>, meaning that there are no more rows.
3661      * For example, the following code fragment retrieves all the data in
3662      * the <code>CachedRowSetImpl</code> object <code>crs</code>, which has
3663      * three columns.  Note that the cursor must initially be positioned
3664      * after the last row so that the first call to the method
3665      * <code>previous</code> places the cursor on the last line.
3666      * <PRE> <code>
3667      *
3668      *     crs.afterLast();
3669      *     while (previous()) {
3670      *         String name = crs.getString(1);
3671      *         int age = crs.getInt(2);
3672      *         short ssn = crs.getShort(3);
3673      *         System.out.println(name + "   " + age + "   " + ssn);
3674      *     }
3675      *
3676      * </code> </PRE>
3677      * This method throws an <code>SQLException</code> if the cursor is not
3678      * on a row in the rowset, before the first row, or after the last row.
3679      *
3680      * @return <code>true</code> if the cursor is on a valid row;
3681      *         <code>false</code> if it is before the first row or after the
3682      *         last row
3683      * @throws SQLException if the cursor is not on a valid position or the
3684      *           type of this rowset is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3685      */
3686     public boolean previous() throws SQLException {
3687         if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3688             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.last").toString());
3689         }
3690         /*
3691          * make sure things look sane. The cursor must be
3692          * positioned in the rowset or before first (0) or
3693          * after last (numRows + 1)
3694          */
3695         if (cursorPos < 0 || cursorPos > numRows + 1) {
3696             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
3697         }
3698         // move and notify
3699         boolean ret = this.internalPrevious();
3700         notifyCursorMoved();
3701 
3702         return ret;
3703     }
3704 
3705     /**
3706      * Moves the cursor to the previous row in this <code>CachedRowSetImpl</code>
3707      * object, skipping past deleted rows that are not visible; returns
3708      * <code>true</code> if the cursor is on a row in this rowset and
3709      * <code>false</code> when the cursor goes before the first row.
3710      * <P>
3711      * This method is called internally by the method <code>previous</code>.
3712      * <P>
3713      * This is a implementation only method and is not required as a standard
3714      * implementation of the <code>CachedRowSet</code> interface.
3715      *
3716      * @return <code>true</code> if the cursor is on a row in this rowset;
3717      *         <code>false</code> when the cursor reaches the position before
3718      *         the first row
3719      * @throws SQLException if an error occurs
3720      */
3721     protected boolean internalPrevious() throws SQLException {
3722         boolean ret = false;
3723 
3724         do {
3725             if (cursorPos > 1) {
3726                 --cursorPos;
3727                 ret = true;
3728             } else if (cursorPos == 1) {
3729                 // decrement to before first
3730                 --cursorPos;
3731                 ret = false;
3732                 break;
3733             }
3734         } while ((getShowDeleted() == false) && (rowDeleted() == true));
3735 
3736         /*
3737          * Each call to internalPrevious may move the cursor
3738          * over multiple rows, the absolute postion moves one one row
3739          */
3740         if (ret == true)
3741             --absolutePos;
3742         else
3743             absolutePos = 0;
3744 
3745         return ret;
3746     }
3747 
3748 
3749     //---------------------------------------------------------------------
3750     // Updates
3751     //---------------------------------------------------------------------
3752 
3753     /**
3754      * Indicates whether the current row of this <code>CachedRowSetImpl</code>
3755      * object has been updated.  The value returned
3756      * depends on whether this rowset can detect updates: <code>false</code>
3757      * will always be returned if it does not detect updates.
3758      *
3759      * @return <code>true</code> if the row has been visibly updated
3760      *         by the owner or another and updates are detected;
3761      *         <code>false</code> otherwise
3762      * @throws SQLException if the cursor is on the insert row or not
3763      *            not on a valid row
3764      *
3765      * @see DatabaseMetaData#updatesAreDetected
3766      */
3767     public boolean rowUpdated() throws SQLException {
3768         // make sure the cursor is on a valid row
3769         checkCursor();
3770         if (onInsertRow == true) {
3771             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3772         }
3773         return(((Row)getCurrentRow()).getUpdated());
3774     }
3775 
3776     /**
3777      * Indicates whether the designated column of the current row of
3778      * this <code>CachedRowSetImpl</code> object has been updated. The
3779      * value returned depends on whether this rowset can detcted updates:
3780      * <code>false</code> will always be returned if it does not detect updates.
3781      *
3782      * @param idx the index identifier of the column that may be have been updated.
3783      * @return <code>true</code> is the designated column has been updated
3784      * and the rowset detects updates; <code>false</code> if the rowset has not
3785      * been updated or the rowset does not detect updates
3786      * @throws SQLException if the cursor is on the insert row or not
3787      *          on a valid row
3788      * @see DatabaseMetaData#updatesAreDetected
3789      */
3790     public boolean columnUpdated(int idx) throws SQLException {
3791         // make sure the cursor is on a valid row
3792         checkCursor();
3793         if (onInsertRow == true) {
3794             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3795         }
3796         return (((Row)getCurrentRow()).getColUpdated(idx - 1));
3797     }
3798 
3799     /**
3800      * Indicates whether the designated column of the current row of
3801      * this <code>CachedRowSetImpl</code> object has been updated. The
3802      * value returned depends on whether this rowset can detcted updates:
3803      * <code>false</code> will always be returned if it does not detect updates.
3804      *
3805      * @param columnName the <code>String</code> column name column that may be have
3806      * been updated.
3807      * @return <code>true</code> is the designated column has been updated
3808      * and the rowset detects updates; <code>false</code> if the rowset has not
3809      * been updated or the rowset does not detect updates
3810      * @throws SQLException if the cursor is on the insert row or not
3811      *          on a valid row
3812      * @see DatabaseMetaData#updatesAreDetected
3813      */
3814     public boolean columnUpdated(String columnName) throws SQLException {
3815         return columnUpdated(getColIdxByName(columnName));
3816     }
3817 
3818     /**
3819      * Indicates whether the current row has been inserted.  The value returned
3820      * depends on whether or not the rowset can detect visible inserts.
3821      *
3822      * @return <code>true</code> if a row has been inserted and inserts are detected;
3823      *         <code>false</code> otherwise
3824      * @throws SQLException if the cursor is on the insert row or not
3825      *            not on a valid row
3826      *
3827      * @see DatabaseMetaData#insertsAreDetected
3828      */
3829     public boolean rowInserted() throws SQLException {
3830         // make sure the cursor is on a valid row
3831         checkCursor();
3832         if (onInsertRow == true) {
3833             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3834         }
3835         return(((Row)getCurrentRow()).getInserted());
3836     }
3837 
3838     /**
3839      * Indicates whether the current row has been deleted.  A deleted row
3840      * may leave a visible "hole" in a rowset.  This method can be used to
3841      * detect such holes if the rowset can detect deletions. This method
3842      * will always return <code>false</code> if this rowset cannot detect
3843      * deletions.
3844      *
3845      * @return <code>true</code> if (1)the current row is blank, indicating that
3846      *         the row has been deleted, and (2)deletions are detected;
3847      *         <code>false</code> otherwise
3848      * @throws SQLException if the cursor is on a valid row in this rowset
3849      * @see DatabaseMetaData#deletesAreDetected
3850      */
3851     public boolean rowDeleted() throws SQLException {
3852         // make sure the cursor is on a valid row
3853 
3854         if (isAfterLast() == true ||
3855         isBeforeFirst() == true ||
3856         onInsertRow == true) {
3857 
3858             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
3859         }
3860         return(((Row)getCurrentRow()).getDeleted());
3861     }
3862 
3863     /**
3864      * Indicates whether the given SQL data type is a numberic type.
3865      *
3866      * @param type one of the constants from <code>java.sql.Types</code>
3867      * @return <code>true</code> if the given type is <code>NUMERIC</code>,'
3868      *         <code>DECIMAL</code>, <code>BIT</code>, <code>TINYINT</code>,
3869      *         <code>SMALLINT</code>, <code>INTEGER</code>, <code>BIGINT</code>,
3870      *         <code>REAL</code>, <code>DOUBLE</code>, or <code>FLOAT</code>;
3871      *         <code>false</code> otherwise
3872      */
3873     private boolean isNumeric(int type) {
3874         switch (type) {
3875             case java.sql.Types.NUMERIC:
3876             case java.sql.Types.DECIMAL:
3877             case java.sql.Types.BIT:
3878             case java.sql.Types.TINYINT:
3879             case java.sql.Types.SMALLINT:
3880             case java.sql.Types.INTEGER:
3881             case java.sql.Types.BIGINT:
3882             case java.sql.Types.REAL:
3883             case java.sql.Types.DOUBLE:
3884             case java.sql.Types.FLOAT:
3885                 return true;
3886             default:
3887                 return false;
3888         }
3889     }
3890 
3891     /**
3892      * Indicates whether the given SQL data type is a string type.
3893      *
3894      * @param type one of the constants from <code>java.sql.Types</code>
3895      * @return <code>true</code> if the given type is <code>CHAR</code>,'
3896      *         <code>VARCHAR</code>, or <code>LONGVARCHAR</code>;
3897      *         <code>false</code> otherwise
3898      */
3899     private boolean isString(int type) {
3900         switch (type) {
3901             case java.sql.Types.CHAR:
3902             case java.sql.Types.VARCHAR:
3903             case java.sql.Types.LONGVARCHAR:
3904                 return true;
3905             default:
3906                 return false;
3907         }
3908     }
3909 
3910     /**
3911      * Indicates whether the given SQL data type is a binary type.
3912      *
3913      * @param type one of the constants from <code>java.sql.Types</code>
3914      * @return <code>true</code> if the given type is <code>BINARY</code>,'
3915      *         <code>VARBINARY</code>, or <code>LONGVARBINARY</code>;
3916      *         <code>false</code> otherwise
3917      */
3918     private boolean isBinary(int type) {
3919         switch (type) {
3920             case java.sql.Types.BINARY:
3921             case java.sql.Types.VARBINARY:
3922             case java.sql.Types.LONGVARBINARY:
3923                 return true;
3924             default:
3925                 return false;
3926         }
3927     }
3928 
3929     /**
3930      * Indicates whether the given SQL data type is a temporal type.
3931      * This method is called internally by the conversion methods
3932      * <code>convertNumeric</code> and <code>convertTemporal</code>.
3933      *
3934      * @param type one of the constants from <code>java.sql.Types</code>
3935      * @return <code>true</code> if the given type is <code>DATE</code>,
3936      *         <code>TIME</code>, or <code>TIMESTAMP</code>;
3937      *         <code>false</code> otherwise
3938      */
3939     private boolean isTemporal(int type) {
3940         switch (type) {
3941             case java.sql.Types.DATE:
3942             case java.sql.Types.TIME:
3943             case java.sql.Types.TIMESTAMP:
3944                 return true;
3945             default:
3946                 return false;
3947         }
3948     }
3949 
3950     /**
3951      * Indicates whether the given SQL data type is a boolean type.
3952      * This method is called internally by the conversion methods
3953      * <code>convertNumeric</code> and <code>convertBoolean</code>.
3954      *
3955      * @param type one of the constants from <code>java.sql.Types</code>
3956      * @return <code>true</code> if the given type is <code>BIT</code>,
3957      *         , or <code>BOOLEAN</code>;
3958      *         <code>false</code> otherwise
3959      */
3960     private boolean isBoolean(int type) {
3961         switch (type) {
3962             case java.sql.Types.BIT:
3963             case java.sql.Types.BOOLEAN:
3964                 return true;
3965             default:
3966                 return false;
3967         }
3968     }
3969 
3970 
3971     /**
3972      * Converts the given <code>Object</code> in the Java programming language
3973      * to the standard mapping for the specified SQL target data type.
3974      * The conversion must be to a string or numeric type, but there are no
3975      * restrictions on the type to be converted.  If the source type and target
3976      * type are the same, the given object is simply returned.
3977      *
3978      * @param srcObj the <code>Object</code> in the Java programming language
3979      *               that is to be converted to the target type
3980      * @param srcType the data type that is the standard mapping in SQL of the
3981      *                object to be converted; must be one of the constants in
3982      *                <code>java.sql.Types</code>
3983      * @param trgType the SQL data type to which to convert the given object;
3984      *                must be one of the following constants in
3985      *                <code>java.sql.Types</code>: <code>NUMERIC</code>,
3986      *         <code>DECIMAL</code>, <code>BIT</code>, <code>TINYINT</code>,
3987      *         <code>SMALLINT</code>, <code>INTEGER</code>, <code>BIGINT</code>,
3988      *         <code>REAL</code>, <code>DOUBLE</code>, <code>FLOAT</code>,
3989      *         <code>VARCHAR</code>, <code>LONGVARCHAR</code>, or <code>CHAR</code>
3990      * @return an <code>Object</code> value.that is
3991      *         the standard object mapping for the target SQL type
3992      * @throws SQLException if the given target type is not one of the string or
3993      *         numeric types in <code>java.sql.Types</code>
3994      */
3995     private Object convertNumeric(Object srcObj, int srcType,
3996     int trgType) throws SQLException {
3997 
3998         if (srcType == trgType) {
3999             return srcObj;
4000         }
4001 
4002         if (isNumeric(trgType) == false && isString(trgType) == false) {
4003             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4004         }
4005 
4006         try {
4007             switch (trgType) {
4008                 case java.sql.Types.BIT:
4009                     Integer i = Integer.valueOf(srcObj.toString().trim());
4010                     return i.equals(Integer.valueOf((int)0)) ?
4011                     Boolean.valueOf(false) :
4012                         Boolean.valueOf(true);
4013                 case java.sql.Types.TINYINT:
4014                     return Byte.valueOf(srcObj.toString().trim());
4015                 case java.sql.Types.SMALLINT:
4016                     return Short.valueOf(srcObj.toString().trim());
4017                 case java.sql.Types.INTEGER:
4018                     return Integer.valueOf(srcObj.toString().trim());
4019                 case java.sql.Types.BIGINT:
4020                     return Long.valueOf(srcObj.toString().trim());
4021                 case java.sql.Types.NUMERIC:
4022                 case java.sql.Types.DECIMAL:
4023                     return new BigDecimal(srcObj.toString().trim());
4024                 case java.sql.Types.REAL:
4025                 case java.sql.Types.FLOAT:
4026                     return new Float(srcObj.toString().trim());
4027                 case java.sql.Types.DOUBLE:
4028                     return new Double(srcObj.toString().trim());
4029                 case java.sql.Types.CHAR:
4030                 case java.sql.Types.VARCHAR:
4031                 case java.sql.Types.LONGVARCHAR:
4032                     return srcObj.toString();
4033                 default:
4034                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString()+ trgType);
4035             }
4036         } catch (NumberFormatException ex) {
4037             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4038         }
4039     }
4040 
4041     /**
4042      * Converts the given <code>Object</code> in the Java programming language
4043      * to the standard object mapping for the specified SQL target data type.
4044      * The conversion must be to a string or temporal type, and there are also
4045      * restrictions on the type to be converted.
4046      * <P>
4047      * <TABLE ALIGN="CENTER" BORDER CELLPADDING=10 BORDERCOLOR="#0000FF"
4048      * <CAPTION ALIGN="CENTER"><B>Parameters and Return Values</B></CAPTION>
4049      * <TR>
4050      *   <TD><B>Source SQL Type</B>
4051      *   <TD><B>Target SQL Type</B>
4052      *   <TD><B>Object Returned</B>
4053      * </TR>
4054      * <TR>
4055      *   <TD><code>TIMESTAMP</code>
4056      *   <TD><code>DATE</code>
4057      *   <TD><code>java.sql.Date</code>
4058      * </TR>
4059      * <TR>
4060      *   <TD><code>TIMESTAMP</code>
4061      *   <TD><code>TIME</code>
4062      *   <TD><code>java.sql.Time</code>
4063      * </TR>
4064      * <TR>
4065      *   <TD><code>TIME</code>
4066      *   <TD><code>TIMESTAMP</code>
4067      *   <TD><code>java.sql.Timestamp</code>
4068      * </TR>
4069      * <TR>
4070      *   <TD><code>DATE</code>, <code>TIME</code>, or <code>TIMESTAMP</code>
4071      *   <TD><code>CHAR</code>, <code>VARCHAR</code>, or <code>LONGVARCHAR</code>
4072      *   <TD><code>java.lang.String</code>
4073      * </TR>
4074      * </TABLE>
4075      * <P>
4076      * If the source type and target type are the same,
4077      * the given object is simply returned.
4078      *
4079      * @param srcObj the <code>Object</code> in the Java programming language
4080      *               that is to be converted to the target type
4081      * @param srcType the data type that is the standard mapping in SQL of the
4082      *                object to be converted; must be one of the constants in
4083      *                <code>java.sql.Types</code>
4084      * @param trgType the SQL data type to which to convert the given object;
4085      *                must be one of the following constants in
4086      *                <code>java.sql.Types</code>: <code>DATE</code>,
4087      *         <code>TIME</code>, <code>TIMESTAMP</code>, <code>CHAR</code>,
4088      *         <code>VARCHAR</code>, or <code>LONGVARCHAR</code>
4089      * @return an <code>Object</code> value.that is
4090      *         the standard object mapping for the target SQL type
4091      * @throws SQLException if the given target type is not one of the string or
4092      *         temporal types in <code>java.sql.Types</code>
4093      */
4094     private Object convertTemporal(Object srcObj,
4095     int srcType, int trgType) throws SQLException {
4096 
4097         if (srcType == trgType) {
4098             return srcObj;
4099         }
4100 
4101         if (isNumeric(trgType) == true ||
4102         (isString(trgType) == false && isTemporal(trgType) == false)) {
4103             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4104         }
4105 
4106         try {
4107             switch (trgType) {
4108                 case java.sql.Types.DATE:
4109                     if (srcType == java.sql.Types.TIMESTAMP) {
4110                         return new java.sql.Date(((java.sql.Timestamp)srcObj).getTime());
4111                     } else {
4112                         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4113                     }
4114                 case java.sql.Types.TIMESTAMP:
4115                     if (srcType == java.sql.Types.TIME) {
4116                         return new Timestamp(((java.sql.Time)srcObj).getTime());
4117                     } else {
4118                         return new Timestamp(((java.sql.Date)srcObj).getTime());
4119                     }
4120                 case java.sql.Types.TIME:
4121                     if (srcType == java.sql.Types.TIMESTAMP) {
4122                         return new Time(((java.sql.Timestamp)srcObj).getTime());
4123                     } else {
4124                         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4125                     }
4126                 case java.sql.Types.CHAR:
4127                 case java.sql.Types.VARCHAR:
4128                 case java.sql.Types.LONGVARCHAR:
4129                     return srcObj.toString();
4130                 default:
4131                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4132             }
4133         } catch (NumberFormatException ex) {
4134             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4135         }
4136 
4137     }
4138 
4139     /**
4140      * Converts the given <code>Object</code> in the Java programming language
4141      * to the standard mapping for the specified SQL target data type.
4142      * The conversion must be to a string or numeric type, but there are no
4143      * restrictions on the type to be converted.  If the source type and target
4144      * type are the same, the given object is simply returned.
4145      *
4146      * @param srcObj the <code>Object</code> in the Java programming language
4147      *               that is to be converted to the target type
4148      * @param srcType the data type that is the standard mapping in SQL of the
4149      *                object to be converted; must be one of the constants in
4150      *                <code>java.sql.Types</code>
4151      * @param trgType the SQL data type to which to convert the given object;
4152      *                must be one of the following constants in
4153      *                <code>java.sql.Types</code>: <code>BIT</code>,
4154      *         or <code>BOOLEAN</code>
4155      * @return an <code>Object</code> value.that is
4156      *         the standard object mapping for the target SQL type
4157      * @throws SQLException if the given target type is not one of the Boolean
4158      *         types in <code>java.sql.Types</code>
4159      */
4160     private Object convertBoolean(Object srcObj, int srcType,
4161     int trgType) throws SQLException {
4162 
4163         if (srcType == trgType) {
4164             return srcObj;
4165         }
4166 
4167         if (isNumeric(trgType) == true ||
4168         (isString(trgType) == false && isBoolean(trgType) == false)) {
4169             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4170         }
4171 
4172 
4173         try {
4174             switch (trgType) {
4175                 case java.sql.Types.BIT:
4176                     Integer i = Integer.valueOf(srcObj.toString().trim());
4177                     return i.equals(Integer.valueOf((int)0)) ?
4178                     Boolean.valueOf(false) :
4179                         Boolean.valueOf(true);
4180                 case java.sql.Types.BOOLEAN:
4181                     return Boolean.valueOf(srcObj.toString().trim());
4182                 default:
4183                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString()+ trgType);
4184             }
4185         } catch (NumberFormatException ex) {
4186             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4187         }
4188     }
4189 
4190     /**
4191      * Sets the designated nullable column in the current row or the
4192      * insert row of this <code>CachedRowSetImpl</code> object with
4193      * <code>null</code> value.
4194      * <P>
4195      * This method updates a column value in the current row or the insert
4196      * row of this rowset; however, another method must be called to complete
4197      * the update process. If the cursor is on a row in the rowset, the
4198      * method {@link #updateRow} must be called to mark the row as updated
4199      * and to notify listeners that the row has changed.
4200      * If the cursor is on the insert row, the method {@link #insertRow}
4201      * must be called to insert the new row into this rowset and to notify
4202      * listeners that a row has changed.
4203      * <P>
4204      * In order to propagate updates in this rowset to the underlying
4205      * data source, an application must call the method {@link #acceptChanges}
4206      * after it calls either <code>updateRow</code> or <code>insertRow</code>.
4207      *
4208      * @param columnIndex the first column is <code>1</code>, the second
4209      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4210      *        and equal to or less than the number of columns in this rowset
4211      * @throws SQLException if (1) the given column index is out of bounds,
4212      *            (2) the cursor is not on one of this rowset's rows or its
4213      *            insert row, or (3) this rowset is
4214      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4215      */
4216     public void updateNull(int columnIndex) throws SQLException {
4217         // sanity check.
4218         checkIndex(columnIndex);
4219         // make sure the cursor is on a valid row
4220         checkCursor();
4221 
4222         BaseRow row = getCurrentRow();
4223         row.setColumnObject(columnIndex, null);
4224 
4225     }
4226 
4227     /**
4228      * Sets the designated column in either the current row or the insert
4229      * row of this <code>CachedRowSetImpl</code> object with the given
4230      * <code>boolean</code> value.
4231      * <P>
4232      * This method updates a column value in the current row or the insert
4233      * row of this rowset, but it does not update the database.
4234      * If the cursor is on a row in the rowset, the
4235      * method {@link #updateRow} must be called to update the database.
4236      * If the cursor is on the insert row, the method {@link #insertRow}
4237      * must be called, which will insert the new row into both this rowset
4238      * and the database. Both of these methods must be called before the
4239      * cursor moves to another row.
4240      *
4241      * @param columnIndex the first column is <code>1</code>, the second
4242      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4243      *        and equal to or less than the number of columns in this rowset
4244      * @param x the new column value
4245      * @throws SQLException if (1) the given column index is out of bounds,
4246      *            (2) the cursor is not on one of this rowset's rows or its
4247      *            insert row, or (3) this rowset is
4248      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4249      */
4250     public void updateBoolean(int columnIndex, boolean x) throws SQLException {
4251         // sanity check.
4252         checkIndex(columnIndex);
4253         // make sure the cursor is on a valid row
4254         checkCursor();
4255         Object obj = convertBoolean(Boolean.valueOf(x),
4256         java.sql.Types.BIT,
4257         RowSetMD.getColumnType(columnIndex));
4258 
4259         getCurrentRow().setColumnObject(columnIndex, obj);
4260     }
4261 
4262     /**
4263      * Sets the designated column in either the current row or the insert
4264      * row of this <code>CachedRowSetImpl</code> object with the given
4265      * <code>byte</code> value.
4266      * <P>
4267      * This method updates a column value in the current row or the insert
4268      * row of this rowset, but it does not update the database.
4269      * If the cursor is on a row in the rowset, the
4270      * method {@link #updateRow} must be called to update the database.
4271      * If the cursor is on the insert row, the method {@link #insertRow}
4272      * must be called, which will insert the new row into both this rowset
4273      * and the database. Both of these methods must be called before the
4274      * cursor moves to another row.
4275      *
4276      * @param columnIndex the first column is <code>1</code>, the second
4277      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4278      *        and equal to or less than the number of columns in this rowset
4279      * @param x the new column value
4280      * @throws SQLException if (1) the given column index is out of bounds,
4281      *            (2) the cursor is not on one of this rowset's rows or its
4282      *            insert row, or (3) this rowset is
4283      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4284      */
4285     public void updateByte(int columnIndex, byte x) throws SQLException {
4286         // sanity check.
4287         checkIndex(columnIndex);
4288         // make sure the cursor is on a valid row
4289         checkCursor();
4290 
4291         Object obj = convertNumeric(Byte.valueOf(x),
4292         java.sql.Types.TINYINT,
4293         RowSetMD.getColumnType(columnIndex));
4294 
4295         getCurrentRow().setColumnObject(columnIndex, obj);
4296     }
4297 
4298     /**
4299      * Sets the designated column in either the current row or the insert
4300      * row of this <code>CachedRowSetImpl</code> object with the given
4301      * <code>short</code> value.
4302      * <P>
4303      * This method updates a column value in the current row or the insert
4304      * row of this rowset, but it does not update the database.
4305      * If the cursor is on a row in the rowset, the
4306      * method {@link #updateRow} must be called to update the database.
4307      * If the cursor is on the insert row, the method {@link #insertRow}
4308      * must be called, which will insert the new row into both this rowset
4309      * and the database. Both of these methods must be called before the
4310      * cursor moves to another row.
4311      *
4312      * @param columnIndex the first column is <code>1</code>, the second
4313      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4314      *        and equal to or less than the number of columns in this rowset
4315      * @param x the new column value
4316      * @throws SQLException if (1) the given column index is out of bounds,
4317      *            (2) the cursor is not on one of this rowset's rows or its
4318      *            insert row, or (3) this rowset is
4319      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4320      */
4321     public void updateShort(int columnIndex, short x) throws SQLException {
4322         // sanity check.
4323         checkIndex(columnIndex);
4324         // make sure the cursor is on a valid row
4325         checkCursor();
4326 
4327         Object obj = convertNumeric(Short.valueOf(x),
4328         java.sql.Types.SMALLINT,
4329         RowSetMD.getColumnType(columnIndex));
4330 
4331         getCurrentRow().setColumnObject(columnIndex, obj);
4332     }
4333 
4334     /**
4335      * Sets the designated column in either the current row or the insert
4336      * row of this <code>CachedRowSetImpl</code> object with the given
4337      * <code>int</code> value.
4338      * <P>
4339      * This method updates a column value in the current row or the insert
4340      * row of this rowset, but it does not update the database.
4341      * If the cursor is on a row in the rowset, the
4342      * method {@link #updateRow} must be called to update the database.
4343      * If the cursor is on the insert row, the method {@link #insertRow}
4344      * must be called, which will insert the new row into both this rowset
4345      * and the database. Both of these methods must be called before the
4346      * cursor moves to another row.
4347      *
4348      * @param columnIndex the first column is <code>1</code>, the second
4349      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4350      *        and equal to or less than the number of columns in this rowset
4351      * @param x the new column value
4352      * @throws SQLException if (1) the given column index is out of bounds,
4353      *            (2) the cursor is not on one of this rowset's rows or its
4354      *            insert row, or (3) this rowset is
4355      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4356      */
4357     public void updateInt(int columnIndex, int x) throws SQLException {
4358         // sanity check.
4359         checkIndex(columnIndex);
4360         // make sure the cursor is on a valid row
4361         checkCursor();
4362         Object obj = convertNumeric(Integer.valueOf(x),
4363         java.sql.Types.INTEGER,
4364         RowSetMD.getColumnType(columnIndex));
4365 
4366         getCurrentRow().setColumnObject(columnIndex, obj);
4367     }
4368 
4369     /**
4370      * Sets the designated column in either the current row or the insert
4371      * row of this <code>CachedRowSetImpl</code> object with the given
4372      * <code>long</code> value.
4373      * <P>
4374      * This method updates a column value in the current row or the insert
4375      * row of this rowset, but it does not update the database.
4376      * If the cursor is on a row in the rowset, the
4377      * method {@link #updateRow} must be called to update the database.
4378      * If the cursor is on the insert row, the method {@link #insertRow}
4379      * must be called, which will insert the new row into both this rowset
4380      * and the database. Both of these methods must be called before the
4381      * cursor moves to another row.
4382      *
4383      * @param columnIndex the first column is <code>1</code>, the second
4384      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4385      *        and equal to or less than the number of columns in this rowset
4386      * @param x the new column value
4387      * @throws SQLException if (1) the given column index is out of bounds,
4388      *            (2) the cursor is not on one of this rowset's rows or its
4389      *            insert row, or (3) this rowset is
4390      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4391      */
4392     public void updateLong(int columnIndex, long x) throws SQLException {
4393         // sanity check.
4394         checkIndex(columnIndex);
4395         // make sure the cursor is on a valid row
4396         checkCursor();
4397 
4398         Object obj = convertNumeric(Long.valueOf(x),
4399         java.sql.Types.BIGINT,
4400         RowSetMD.getColumnType(columnIndex));
4401 
4402         getCurrentRow().setColumnObject(columnIndex, obj);
4403 
4404     }
4405 
4406     /**
4407      * Sets the designated column in either the current row or the insert
4408      * row of this <code>CachedRowSetImpl</code> object with the given
4409      * <code>float</code> value.
4410      * <P>
4411      * This method updates a column value in the current row or the insert
4412      * row of this rowset, but it does not update the database.
4413      * If the cursor is on a row in the rowset, the
4414      * method {@link #updateRow} must be called to update the database.
4415      * If the cursor is on the insert row, the method {@link #insertRow}
4416      * must be called, which will insert the new row into both this rowset
4417      * and the database. Both of these methods must be called before the
4418      * cursor moves to another row.
4419      *
4420      * @param columnIndex the first column is <code>1</code>, the second
4421      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4422      *        and equal to or less than the number of columns in this rowset
4423      * @param x the new column value
4424      * @throws SQLException if (1) the given column index is out of bounds,
4425      *            (2) the cursor is not on one of this rowset's rows or its
4426      *            insert row, or (3) this rowset is
4427      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4428      */
4429     public void updateFloat(int columnIndex, float x) throws SQLException {
4430         // sanity check.
4431         checkIndex(columnIndex);
4432         // make sure the cursor is on a valid row
4433         checkCursor();
4434 
4435         Object obj = convertNumeric(new Float(x),
4436         java.sql.Types.REAL,
4437         RowSetMD.getColumnType(columnIndex));
4438 
4439         getCurrentRow().setColumnObject(columnIndex, obj);
4440     }
4441 
4442     /**
4443      * Sets the designated column in either the current row or the insert
4444      * row of this <code>CachedRowSetImpl</code> object with the given
4445      * <code>double</code> value.
4446      *
4447      * This method updates a column value in either the current row or
4448      * the insert row of this rowset, but it does not update the
4449      * database.  If the cursor is on a row in the rowset, the
4450      * method {@link #updateRow} must be called to update the database.
4451      * If the cursor is on the insert row, the method {@link #insertRow}
4452      * must be called, which will insert the new row into both this rowset
4453      * and the database. Both of these methods must be called before the
4454      * cursor moves to another row.
4455      *
4456      * @param columnIndex the first column is <code>1</code>, the second
4457      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4458      *        and equal to or less than the number of columns in this rowset
4459      * @param x the new column value
4460      * @throws SQLException if (1) the given column index is out of bounds,
4461      *            (2) the cursor is not on one of this rowset's rows or its
4462      *            insert row, or (3) this rowset is
4463      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4464      */
4465     public void updateDouble(int columnIndex, double x) throws SQLException {
4466         // sanity check.
4467         checkIndex(columnIndex);
4468         // make sure the cursor is on a valid row
4469         checkCursor();
4470         Object obj = convertNumeric(new Double(x),
4471         java.sql.Types.DOUBLE,
4472         RowSetMD.getColumnType(columnIndex));
4473 
4474         getCurrentRow().setColumnObject(columnIndex, obj);
4475     }
4476 
4477     /**
4478      * Sets the designated column in either the current row or the insert
4479      * row of this <code>CachedRowSetImpl</code> object with the given
4480      * <code>java.math.BigDecimal</code> object.
4481      * <P>
4482      * This method updates a column value in the current row or the insert
4483      * row of this rowset, but it does not update the database.
4484      * If the cursor is on a row in the rowset, the
4485      * method {@link #updateRow} must be called to update the database.
4486      * If the cursor is on the insert row, the method {@link #insertRow}
4487      * must be called, which will insert the new row into both this rowset
4488      * and the database. Both of these methods must be called before the
4489      * cursor moves to another row.
4490      *
4491      * @param columnIndex the first column is <code>1</code>, the second
4492      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4493      *        and equal to or less than the number of columns in this rowset
4494      * @param x the new column value
4495      * @throws SQLException if (1) the given column index is out of bounds,
4496      *            (2) the cursor is not on one of this rowset's rows or its
4497      *            insert row, or (3) this rowset is
4498      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4499      */
4500     public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {
4501         // sanity check.
4502         checkIndex(columnIndex);
4503         // make sure the cursor is on a valid row
4504         checkCursor();
4505 
4506         Object obj = convertNumeric(x,
4507         java.sql.Types.NUMERIC,
4508         RowSetMD.getColumnType(columnIndex));
4509 
4510         getCurrentRow().setColumnObject(columnIndex, obj);
4511     }
4512 
4513     /**
4514      * Sets the designated column in either the current row or the insert
4515      * row of this <code>CachedRowSetImpl</code> object with the given
4516      * <code>String</code> object.
4517      * <P>
4518      * This method updates a column value in either the current row or
4519      * the insert row of this rowset, but it does not update the
4520      * database.  If the cursor is on a row in the rowset, the
4521      * method {@link #updateRow} must be called to mark the row as updated.
4522      * If the cursor is on the insert row, the method {@link #insertRow}
4523      * must be called to insert the new row into this rowset and mark it
4524      * as inserted. Both of these methods must be called before the
4525      * cursor moves to another row.
4526      * <P>
4527      * The method <code>acceptChanges</code> must be called if the
4528      * updated values are to be written back to the underlying database.
4529      *
4530      * @param columnIndex the first column is <code>1</code>, the second
4531      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4532      *        and equal to or less than the number of columns in this rowset
4533      * @param x the new column value
4534      * @throws SQLException if (1) the given column index is out of bounds,
4535      *            (2) the cursor is not on one of this rowset's rows or its
4536      *            insert row, or (3) this rowset is
4537      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4538      */
4539     public void updateString(int columnIndex, String x) throws SQLException {
4540         // sanity check.
4541         checkIndex(columnIndex);
4542         // make sure the cursor is on a valid row
4543         checkCursor();
4544 
4545         getCurrentRow().setColumnObject(columnIndex, x);
4546     }
4547 
4548     /**
4549      * Sets the designated column in either the current row or the insert
4550      * row of this <code>CachedRowSetImpl</code> object with the given
4551      * <code>byte</code> array.
4552      *
4553      * This method updates a column value in either the current row or
4554      * the insert row of this rowset, but it does not update the
4555      * database.  If the cursor is on a row in the rowset, the
4556      * method {@link #updateRow} must be called to update the database.
4557      * If the cursor is on the insert row, the method {@link #insertRow}
4558      * must be called, which will insert the new row into both this rowset
4559      * and the database. Both of these methods must be called before the
4560      * cursor moves to another row.
4561      *
4562      * @param columnIndex the first column is <code>1</code>, the second
4563      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4564      *        and equal to or less than the number of columns in this rowset
4565      * @param x the new column value
4566      * @throws SQLException if (1) the given column index is out of bounds,
4567      *            (2) the cursor is not on one of this rowset's rows or its
4568      *            insert row, or (3) this rowset is
4569      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4570      */
4571     public void updateBytes(int columnIndex, byte x[]) throws SQLException {
4572         // sanity check.
4573         checkIndex(columnIndex);
4574         // make sure the cursor is on a valid row
4575         checkCursor();
4576 
4577         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4578             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4579         }
4580 
4581         getCurrentRow().setColumnObject(columnIndex, x);
4582     }
4583 
4584     /**
4585      * Sets the designated column in either the current row or the insert
4586      * row of this <code>CachedRowSetImpl</code> object with the given
4587      * <code>Date</code> object.
4588      *
4589      * This method updates a column value in either the current row or
4590      * the insert row of this rowset, but it does not update the
4591      * database.  If the cursor is on a row in the rowset, the
4592      * method {@link #updateRow} must be called to update the database.
4593      * If the cursor is on the insert row, the method {@link #insertRow}
4594      * must be called, which will insert the new row into both this rowset
4595      * and the database. Both of these methods must be called before the
4596      * cursor moves to another row.
4597      *
4598      * @param columnIndex the first column is <code>1</code>, the second
4599      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4600      *        and equal to or less than the number of columns in this rowset
4601      * @param x the new column value
4602      * @throws SQLException if (1) the given column index is out of bounds,
4603      *            (2) the cursor is not on one of this rowset's rows or its
4604      *            insert row, (3) the type of the designated column is not
4605      *            an SQL <code>DATE</code> or <code>TIMESTAMP</code>, or
4606      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4607      */
4608     public void updateDate(int columnIndex, java.sql.Date x) throws SQLException {
4609         // sanity check.
4610         checkIndex(columnIndex);
4611         // make sure the cursor is on a valid row
4612         checkCursor();
4613 
4614         Object obj = convertTemporal(x,
4615         java.sql.Types.DATE,
4616         RowSetMD.getColumnType(columnIndex));
4617 
4618         getCurrentRow().setColumnObject(columnIndex, obj);
4619     }
4620 
4621     /**
4622      * Sets the designated column in either the current row or the insert
4623      * row of this <code>CachedRowSetImpl</code> object with the given
4624      * <code>Time</code> object.
4625      *
4626      * This method updates a column value in either the current row or
4627      * the insert row of this rowset, but it does not update the
4628      * database.  If the cursor is on a row in the rowset, the
4629      * method {@link #updateRow} must be called to update the database.
4630      * If the cursor is on the insert row, the method {@link #insertRow}
4631      * must be called, which will insert the new row into both this rowset
4632      * and the database. Both of these methods must be called before the
4633      * cursor moves to another row.
4634      *
4635      * @param columnIndex the first column is <code>1</code>, the second
4636      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4637      *        and equal to or less than the number of columns in this rowset
4638      * @param x the new column value
4639      * @throws SQLException if (1) the given column index is out of bounds,
4640      *            (2) the cursor is not on one of this rowset's rows or its
4641      *            insert row, (3) the type of the designated column is not
4642      *            an SQL <code>TIME</code> or <code>TIMESTAMP</code>, or
4643      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4644      */
4645     public void updateTime(int columnIndex, java.sql.Time x) throws SQLException {
4646         // sanity check.
4647         checkIndex(columnIndex);
4648         // make sure the cursor is on a valid row
4649         checkCursor();
4650 
4651         Object obj = convertTemporal(x,
4652         java.sql.Types.TIME,
4653         RowSetMD.getColumnType(columnIndex));
4654 
4655         getCurrentRow().setColumnObject(columnIndex, obj);
4656     }
4657 
4658     /**
4659      * Sets the designated column in either the current row or the insert
4660      * row of this <code>CachedRowSetImpl</code> object with the given
4661      * <code>Timestamp</code> object.
4662      *
4663      * This method updates a column value in either the current row or
4664      * the insert row of this rowset, but it does not update the
4665      * database.  If the cursor is on a row in the rowset, the
4666      * method {@link #updateRow} must be called to update the database.
4667      * If the cursor is on the insert row, the method {@link #insertRow}
4668      * must be called, which will insert the new row into both this rowset
4669      * and the database. Both of these methods must be called before the
4670      * cursor moves to another row.
4671      *
4672      * @param columnIndex the first column is <code>1</code>, the second
4673      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4674      *        and equal to or less than the number of columns in this rowset
4675      * @param x the new column value
4676      * @throws SQLException if (1) the given column index is out of bounds,
4677      *            (2) the cursor is not on one of this rowset's rows or its
4678      *            insert row, (3) the type of the designated column is not
4679      *            an SQL <code>DATE</code>, <code>TIME</code>, or
4680      *            <code>TIMESTAMP</code>, or (4) this rowset is
4681      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4682      */
4683     public void updateTimestamp(int columnIndex, java.sql.Timestamp x) throws SQLException {
4684         // sanity check.
4685         checkIndex(columnIndex);
4686         // make sure the cursor is on a valid row
4687         checkCursor();
4688 
4689         Object obj = convertTemporal(x,
4690         java.sql.Types.TIMESTAMP,
4691         RowSetMD.getColumnType(columnIndex));
4692 
4693         getCurrentRow().setColumnObject(columnIndex, obj);
4694     }
4695 
4696     /**
4697      * Sets the designated column in either the current row or the insert
4698      * row of this <code>CachedRowSetImpl</code> object with the given
4699      * ASCII stream value.
4700      * <P>
4701      * This method updates a column value in either the current row or
4702      * the insert row of this rowset, but it does not update the
4703      * database.  If the cursor is on a row in the rowset, the
4704      * method {@link #updateRow} must be called to update the database.
4705      * If the cursor is on the insert row, the method {@link #insertRow}
4706      * must be called, which will insert the new row into both this rowset
4707      * and the database. Both of these methods must be called before the
4708      * cursor moves to another row.
4709      *
4710      * @param columnIndex the first column is <code>1</code>, the second
4711      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4712      *        and equal to or less than the number of columns in this rowset
4713      * @param x the new column value
4714      * @param length the number of one-byte ASCII characters in the stream
4715      * @throws SQLException if this method is invoked
4716      */
4717     public void updateAsciiStream(int columnIndex, java.io.InputStream x, int length) throws SQLException {
4718         // sanity Check
4719         checkIndex(columnIndex);
4720         // make sure the cursor is on a valid row
4721         checkCursor();
4722 
4723 
4724         if (isString(RowSetMD.getColumnType(columnIndex)) == false &&
4725         isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4726             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4727         }
4728 
4729         byte buf[] = new byte[length];
4730         try {
4731             int charsRead = 0;
4732             do {
4733                 charsRead += x.read(buf, charsRead, length - charsRead);
4734             } while (charsRead != length);
4735             //Changed the condition check to check for length instead of -1
4736         } catch (java.io.IOException ex) {
4737             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.asciistream").toString());
4738         }
4739         String str = new String(buf);
4740 
4741         getCurrentRow().setColumnObject(columnIndex, str);
4742 
4743     }
4744 
4745     /**
4746      * Sets the designated column in either the current row or the insert
4747      * row of this <code>CachedRowSetImpl</code> object with the given
4748      * <code>java.io.InputStream</code> object.
4749      * <P>
4750      * This method updates a column value in either the current row or
4751      * the insert row of this rowset, but it does not update the
4752      * database.  If the cursor is on a row in the rowset, the
4753      * method {@link #updateRow} must be called to update the database.
4754      * If the cursor is on the insert row, the method {@link #insertRow}
4755      * must be called, which will insert the new row into both this rowset
4756      * and the database. Both of these methods must be called before the
4757      * cursor moves to another row.
4758      *
4759      * @param columnIndex the first column is <code>1</code>, the second
4760      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4761      *        and equal to or less than the number of columns in this rowset
4762      * @param x the new column value; must be a <code>java.io.InputStream</code>
4763      *          containing <code>BINARY</code>, <code>VARBINARY</code>, or
4764      *          <code>LONGVARBINARY</code> data
4765      * @param length the length of the stream in bytes
4766      * @throws SQLException if (1) the given column index is out of bounds,
4767      *            (2) the cursor is not on one of this rowset's rows or its
4768      *            insert row, (3) the data in the stream is not binary, or
4769      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4770      */
4771     public void updateBinaryStream(int columnIndex, java.io.InputStream x,int length) throws SQLException {
4772         // sanity Check
4773         checkIndex(columnIndex);
4774         // make sure the cursor is on a valid row
4775         checkCursor();
4776 
4777         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4778             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4779         }
4780 
4781         byte buf[] = new byte[length];
4782         try {
4783             int bytesRead = 0;
4784             do {
4785                 bytesRead += x.read(buf, bytesRead, length - bytesRead);
4786             } while (bytesRead != -1);
4787         } catch (java.io.IOException ex) {
4788             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.binstream").toString());
4789         }
4790 
4791         getCurrentRow().setColumnObject(columnIndex, buf);
4792     }
4793 
4794     /**
4795      * Sets the designated column in either the current row or the insert
4796      * row of this <code>CachedRowSetImpl</code> object with the given
4797      * <code>java.io.Reader</code> object.
4798      * <P>
4799      * This method updates a column value in either the current row or
4800      * the insert row of this rowset, but it does not update the
4801      * database.  If the cursor is on a row in the rowset, the
4802      * method {@link #updateRow} must be called to update the database.
4803      * If the cursor is on the insert row, the method {@link #insertRow}
4804      * must be called, which will insert the new row into both this rowset
4805      * and the database. Both of these methods must be called before the
4806      * cursor moves to another row.
4807      *
4808      * @param columnIndex the first column is <code>1</code>, the second
4809      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4810      *        and equal to or less than the number of columns in this rowset
4811      * @param x the new column value; must be a <code>java.io.Reader</code>
4812      *          containing <code>BINARY</code>, <code>VARBINARY</code>,
4813      *          <code>LONGVARBINARY</code>, <code>CHAR</code>, <code>VARCHAR</code>,
4814      *          or <code>LONGVARCHAR</code> data
4815      * @param length the length of the stream in characters
4816      * @throws SQLException if (1) the given column index is out of bounds,
4817      *            (2) the cursor is not on one of this rowset's rows or its
4818      *            insert row, (3) the data in the stream is not a binary or
4819      *            character type, or (4) this rowset is
4820      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4821      */
4822     public void updateCharacterStream(int columnIndex, java.io.Reader x, int length) throws SQLException {
4823         // sanity Check
4824         checkIndex(columnIndex);
4825         // make sure the cursor is on a valid row
4826         checkCursor();
4827 
4828         if (isString(RowSetMD.getColumnType(columnIndex)) == false &&
4829         isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4830             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4831         }
4832 
4833         char buf[] = new char[length];
4834         try {
4835             int charsRead = 0;
4836             do {
4837                 charsRead += x.read(buf, charsRead, length - charsRead);
4838             } while (charsRead != length);
4839             //Changed the condition checking to check for length instead of -1
4840         } catch (java.io.IOException ex) {
4841             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.binstream").toString());
4842         }
4843         String str = new String(buf);
4844 
4845         getCurrentRow().setColumnObject(columnIndex, str);
4846     }
4847 
4848     /**
4849      * Sets the designated column in either the current row or the insert
4850      * row of this <code>CachedRowSetImpl</code> object with the given
4851      * <code>Object</code> value.  The <code>scale</code> parameter indicates
4852      * the number of digits to the right of the decimal point and is ignored
4853      * if the new column value is not a type that will be mapped to an SQL
4854      * <code>DECIMAL</code> or <code>NUMERIC</code> value.
4855      * <P>
4856      * This method updates a column value in either the current row or
4857      * the insert row of this rowset, but it does not update the
4858      * database.  If the cursor is on a row in the rowset, the
4859      * method {@link #updateRow} must be called to update the database.
4860      * If the cursor is on the insert row, the method {@link #insertRow}
4861      * must be called, which will insert the new row into both this rowset
4862      * and the database. Both of these methods must be called before the
4863      * cursor moves to another row.
4864      *
4865      * @param columnIndex the first column is <code>1</code>, the second
4866      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4867      *        and equal to or less than the number of columns in this rowset
4868      * @param x the new column value
4869      * @param scale the number of digits to the right of the decimal point (for
4870      *              <code>DECIMAL</code> and <code>NUMERIC</code> types only)
4871      * @throws SQLException if (1) the given column index is out of bounds,
4872      *            (2) the cursor is not on one of this rowset's rows or its
4873      *            insert row, or (3) this rowset is
4874      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4875      */
4876     public void updateObject(int columnIndex, Object x, int scale) throws SQLException {
4877         // sanity check.
4878         checkIndex(columnIndex);
4879         // make sure the cursor is on a valid row
4880         checkCursor();
4881 
4882         int type = RowSetMD.getColumnType(columnIndex);
4883         if (type == Types.DECIMAL || type == Types.NUMERIC) {
4884             ((java.math.BigDecimal)x).setScale(scale);
4885         }
4886         getCurrentRow().setColumnObject(columnIndex, x);
4887     }
4888 
4889     /**
4890      * Sets the designated column in either the current row or the insert
4891      * row of this <code>CachedRowSetImpl</code> object with the given
4892      * <code>Object</code> value.
4893      * <P>
4894      * This method updates a column value in either the current row or
4895      * the insert row of this rowset, but it does not update the
4896      * database.  If the cursor is on a row in the rowset, the
4897      * method {@link #updateRow} must be called to update the database.
4898      * If the cursor is on the insert row, the method {@link #insertRow}
4899      * must be called, which will insert the new row into both this rowset
4900      * and the database. Both of these methods must be called before the
4901      * cursor moves to another row.
4902      *
4903      * @param columnIndex the first column is <code>1</code>, the second
4904      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4905      *        and equal to or less than the number of columns in this rowset
4906      * @param x the new column value
4907      * @throws SQLException if (1) the given column index is out of bounds,
4908      *            (2) the cursor is not on one of this rowset's rows or its
4909      *            insert row, or (3) this rowset is
4910      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4911      */
4912     public void updateObject(int columnIndex, Object x) throws SQLException {
4913         // sanity check.
4914         checkIndex(columnIndex);
4915         // make sure the cursor is on a valid row
4916         checkCursor();
4917 
4918         getCurrentRow().setColumnObject(columnIndex, x);
4919     }
4920 
4921     /**
4922      * Sets the designated nullable column in the current row or the
4923      * insert row of this <code>CachedRowSetImpl</code> object with
4924      * <code>null</code> value.
4925      * <P>
4926      * This method updates a column value in the current row or the insert
4927      * row of this rowset, but it does not update the database.
4928      * If the cursor is on a row in the rowset, the
4929      * method {@link #updateRow} must be called to update the database.
4930      * If the cursor is on the insert row, the method {@link #insertRow}
4931      * must be called, which will insert the new row into both this rowset
4932      * and the database.
4933      *
4934      * @param columnName a <code>String</code> object that must match the
4935      *        SQL name of a column in this rowset, ignoring case
4936      * @throws SQLException if (1) the given column name does not match the
4937      *            name of a column in this rowset, (2) the cursor is not on
4938      *            one of this rowset's rows or its insert row, or (3) this
4939      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4940      */
4941     public void updateNull(String columnName) throws SQLException {
4942         updateNull(getColIdxByName(columnName));
4943     }
4944 
4945     /**
4946      * Sets the designated column in either the current row or the insert
4947      * row of this <code>CachedRowSetImpl</code> object with the given
4948      * <code>boolean</code> value.
4949      * <P>
4950      * This method updates a column value in the current row or the insert
4951      * row of this rowset, but it does not update the database.
4952      * If the cursor is on a row in the rowset, the
4953      * method {@link #updateRow} must be called to update the database.
4954      * If the cursor is on the insert row, the method {@link #insertRow}
4955      * must be called, which will insert the new row into both this rowset
4956      * and the database. Both of these methods must be called before the
4957      * cursor moves to another row.
4958      *
4959      * @param columnName a <code>String</code> object that must match the
4960      *        SQL name of a column in this rowset, ignoring case
4961      * @param x the new column value
4962      * @throws SQLException if (1) the given column name does not match the
4963      *            name of a column in this rowset, (2) the cursor is not on
4964      *            one of this rowset's rows or its insert row, or (3) this
4965      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4966      */
4967     public void updateBoolean(String columnName, boolean x) throws SQLException {
4968         updateBoolean(getColIdxByName(columnName), x);
4969     }
4970 
4971     /**
4972      * Sets the designated column in either the current row or the insert
4973      * row of this <code>CachedRowSetImpl</code> object with the given
4974      * <code>byte</code> value.
4975      * <P>
4976      * This method updates a column value in the current row or the insert
4977      * row of this rowset, but it does not update the database.
4978      * If the cursor is on a row in the rowset, the
4979      * method {@link #updateRow} must be called to update the database.
4980      * If the cursor is on the insert row, the method {@link #insertRow}
4981      * must be called, which will insert the new row into both this rowset
4982      * and the database. Both of these methods must be called before the
4983      * cursor moves to another row.
4984      *
4985      * @param columnName a <code>String</code> object that must match the
4986      *        SQL name of a column in this rowset, ignoring case
4987      * @param x the new column value
4988      * @throws SQLException if (1) the given column name does not match the
4989      *            name of a column in this rowset, (2) the cursor is not on
4990      *            one of this rowset's rows or its insert row, or (3) this
4991      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4992      */
4993     public void updateByte(String columnName, byte x) throws SQLException {
4994         updateByte(getColIdxByName(columnName), x);
4995     }
4996 
4997     /**
4998      * Sets the designated column in either the current row or the insert
4999      * row of this <code>CachedRowSetImpl</code> object with the given
5000      * <code>short</code> value.
5001      * <P>
5002      * This method updates a column value in the current row or the insert
5003      * row of this rowset, but it does not update the database.
5004      * If the cursor is on a row in the rowset, the
5005      * method {@link #updateRow} must be called to update the database.
5006      * If the cursor is on the insert row, the method {@link #insertRow}
5007      * must be called, which will insert the new row into both this rowset
5008      * and the database. Both of these methods must be called before the
5009      * cursor moves to another row.
5010      *
5011      * @param columnName a <code>String</code> object that must match the
5012      *        SQL name of a column in this rowset, ignoring case
5013      * @param x the new column value
5014      * @throws SQLException if (1) the given column name does not match the
5015      *            name of a column in this rowset, (2) the cursor is not on
5016      *            one of this rowset's rows or its insert row, or (3) this
5017      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5018      */
5019     public void updateShort(String columnName, short x) throws SQLException {
5020         updateShort(getColIdxByName(columnName), x);
5021     }
5022 
5023     /**
5024      * Sets the designated column in either the current row or the insert
5025      * row of this <code>CachedRowSetImpl</code> object with the given
5026      * <code>int</code> value.
5027      * <P>
5028      * This method updates a column value in the current row or the insert
5029      * row of this rowset, but it does not update the database.
5030      * If the cursor is on a row in the rowset, the
5031      * method {@link #updateRow} must be called to update the database.
5032      * If the cursor is on the insert row, the method {@link #insertRow}
5033      * must be called, which will insert the new row into both this rowset
5034      * and the database. Both of these methods must be called before the
5035      * cursor moves to another row.
5036      *
5037      * @param columnName a <code>String</code> object that must match the
5038      *        SQL name of a column in this rowset, ignoring case
5039      * @param x the new column value
5040      * @throws SQLException if (1) the given column name does not match the
5041      *            name of a column in this rowset, (2) the cursor is not on
5042      *            one of this rowset's rows or its insert row, or (3) this
5043      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5044      */
5045     public void updateInt(String columnName, int x) throws SQLException {
5046         updateInt(getColIdxByName(columnName), x);
5047     }
5048 
5049     /**
5050      * Sets the designated column in either the current row or the insert
5051      * row of this <code>CachedRowSetImpl</code> object with the given
5052      * <code>long</code> value.
5053      * <P>
5054      * This method updates a column value in the current row or the insert
5055      * row of this rowset, but it does not update the database.
5056      * If the cursor is on a row in the rowset, the
5057      * method {@link #updateRow} must be called to update the database.
5058      * If the cursor is on the insert row, the method {@link #insertRow}
5059      * must be called, which will insert the new row into both this rowset
5060      * and the database. Both of these methods must be called before the
5061      * cursor moves to another row.
5062      *
5063      * @param columnName a <code>String</code> object that must match the
5064      *        SQL name of a column in this rowset, ignoring case
5065      * @param x the new column value
5066      * @throws SQLException if (1) the given column name does not match the
5067      *            name of a column in this rowset, (2) the cursor is not on
5068      *            one of this rowset's rows or its insert row, or (3) this
5069      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5070      */
5071     public void updateLong(String columnName, long x) throws SQLException {
5072         updateLong(getColIdxByName(columnName), x);
5073     }
5074 
5075     /**
5076      * Sets the designated column in either the current row or the insert
5077      * row of this <code>CachedRowSetImpl</code> object with the given
5078      * <code>float</code> value.
5079      * <P>
5080      * This method updates a column value in the current row or the insert
5081      * row of this rowset, but it does not update the database.
5082      * If the cursor is on a row in the rowset, the
5083      * method {@link #updateRow} must be called to update the database.
5084      * If the cursor is on the insert row, the method {@link #insertRow}
5085      * must be called, which will insert the new row into both this rowset
5086      * and the database. Both of these methods must be called before the
5087      * cursor moves to another row.
5088      *
5089      * @param columnName a <code>String</code> object that must match the
5090      *        SQL name of a column in this rowset, ignoring case
5091      * @param x the new column value
5092      * @throws SQLException if (1) the given column name does not match the
5093      *            name of a column in this rowset, (2) the cursor is not on
5094      *            one of this rowset's rows or its insert row, or (3) this
5095      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5096      */
5097     public void updateFloat(String columnName, float x) throws SQLException {
5098         updateFloat(getColIdxByName(columnName), x);
5099     }
5100 
5101     /**
5102      * Sets the designated column in either the current row or the insert
5103      * row of this <code>CachedRowSetImpl</code> object with the given
5104      * <code>double</code> value.
5105      *
5106      * This method updates a column value in either the current row or
5107      * the insert row of this rowset, but it does not update the
5108      * database.  If the cursor is on a row in the rowset, the
5109      * method {@link #updateRow} must be called to update the database.
5110      * If the cursor is on the insert row, the method {@link #insertRow}
5111      * must be called, which will insert the new row into both this rowset
5112      * and the database. Both of these methods must be called before the
5113      * cursor moves to another row.
5114      *
5115      * @param columnName a <code>String</code> object that must match the
5116      *        SQL name of a column in this rowset, ignoring case
5117      * @param x the new column value
5118      * @throws SQLException if (1) the given column name does not match the
5119      *            name of a column in this rowset, (2) the cursor is not on
5120      *            one of this rowset's rows or its insert row, or (3) this
5121      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5122      */
5123     public void updateDouble(String columnName, double x) throws SQLException {
5124         updateDouble(getColIdxByName(columnName), x);
5125     }
5126 
5127     /**
5128      * Sets the designated column in either the current row or the insert
5129      * row of this <code>CachedRowSetImpl</code> object with the given
5130      * <code>java.math.BigDecimal</code> object.
5131      * <P>
5132      * This method updates a column value in the current row or the insert
5133      * row of this rowset, but it does not update the database.
5134      * If the cursor is on a row in the rowset, the
5135      * method {@link #updateRow} must be called to update the database.
5136      * If the cursor is on the insert row, the method {@link #insertRow}
5137      * must be called, which will insert the new row into both this rowset
5138      * and the database. Both of these methods must be called before the
5139      * cursor moves to another row.
5140      *
5141      * @param columnName a <code>String</code> object that must match the
5142      *        SQL name of a column in this rowset, ignoring case
5143      * @param x the new column value
5144      * @throws SQLException if (1) the given column name does not match the
5145      *            name of a column in this rowset, (2) the cursor is not on
5146      *            one of this rowset's rows or its insert row, or (3) this
5147      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5148      */
5149     public void updateBigDecimal(String columnName, BigDecimal x) throws SQLException {
5150         updateBigDecimal(getColIdxByName(columnName), x);
5151     }
5152 
5153     /**
5154      * Sets the designated column in either the current row or the insert
5155      * row of this <code>CachedRowSetImpl</code> object with the given
5156      * <code>String</code> object.
5157      *
5158      * This method updates a column value in either the current row or
5159      * the insert row of this rowset, but it does not update the
5160      * database.  If the cursor is on a row in the rowset, the
5161      * method {@link #updateRow} must be called to update the database.
5162      * If the cursor is on the insert row, the method {@link #insertRow}
5163      * must be called, which will insert the new row into both this rowset
5164      * and the database. Both of these methods must be called before the
5165      * cursor moves to another row.
5166      *
5167      * @param columnName a <code>String</code> object that must match the
5168      *        SQL name of a column in this rowset, ignoring case
5169      * @param x the new column value
5170      * @throws SQLException if (1) the given column name does not match the
5171      *            name of a column in this rowset, (2) the cursor is not on
5172      *            one of this rowset's rows or its insert row, or (3) this
5173      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5174      */
5175     public void updateString(String columnName, String x) throws SQLException {
5176         updateString(getColIdxByName(columnName), x);
5177     }
5178 
5179     /**
5180      * Sets the designated column in either the current row or the insert
5181      * row of this <code>CachedRowSetImpl</code> object with the given
5182      * <code>byte</code> array.
5183      *
5184      * This method updates a column value in either the current row or
5185      * the insert row of this rowset, but it does not update the
5186      * database.  If the cursor is on a row in the rowset, the
5187      * method {@link #updateRow} must be called to update the database.
5188      * If the cursor is on the insert row, the method {@link #insertRow}
5189      * must be called, which will insert the new row into both this rowset
5190      * and the database. Both of these methods must be called before the
5191      * cursor moves to another row.
5192      *
5193      * @param columnName a <code>String</code> object that must match the
5194      *        SQL name of a column in this rowset, ignoring case
5195      * @param x the new column value
5196      * @throws SQLException if (1) the given column name does not match the
5197      *            name of a column in this rowset, (2) the cursor is not on
5198      *            one of this rowset's rows or its insert row, or (3) this
5199      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5200      */
5201     public void updateBytes(String columnName, byte x[]) throws SQLException {
5202         updateBytes(getColIdxByName(columnName), x);
5203     }
5204 
5205     /**
5206      * Sets the designated column in either the current row or the insert
5207      * row of this <code>CachedRowSetImpl</code> object with the given
5208      * <code>Date</code> object.
5209      *
5210      * This method updates a column value in either the current row or
5211      * the insert row of this rowset, but it does not update the
5212      * database.  If the cursor is on a row in the rowset, the
5213      * method {@link #updateRow} must be called to update the database.
5214      * If the cursor is on the insert row, the method {@link #insertRow}
5215      * must be called, which will insert the new row into both this rowset
5216      * and the database. Both of these methods must be called before the
5217      * cursor moves to another row.
5218      *
5219      * @param columnName a <code>String</code> object that must match the
5220      *        SQL name of a column in this rowset, ignoring case
5221      * @param x the new column value
5222      * @throws SQLException if (1) the given column name does not match the
5223      *            name of a column in this rowset, (2) the cursor is not on
5224      *            one of this rowset's rows or its insert row, (3) the type
5225      *            of the designated column is not an SQL <code>DATE</code> or
5226      *            <code>TIMESTAMP</code>, or (4) this rowset is
5227      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5228      */
5229     public void updateDate(String columnName, java.sql.Date x) throws SQLException {
5230         updateDate(getColIdxByName(columnName), x);
5231     }
5232 
5233     /**
5234      * Sets the designated column in either the current row or the insert
5235      * row of this <code>CachedRowSetImpl</code> object with the given
5236      * <code>Time</code> object.
5237      *
5238      * This method updates a column value in either the current row or
5239      * the insert row of this rowset, but it does not update the
5240      * database.  If the cursor is on a row in the rowset, the
5241      * method {@link #updateRow} must be called to update the database.
5242      * If the cursor is on the insert row, the method {@link #insertRow}
5243      * must be called, which will insert the new row into both this rowset
5244      * and the database. Both of these methods must be called before the
5245      * cursor moves to another row.
5246      *
5247      * @param columnName a <code>String</code> object that must match the
5248      *        SQL name of a column in this rowset, ignoring case
5249      * @param x the new column value
5250      * @throws SQLException if (1) the given column name does not match the
5251      *            name of a column in this rowset, (2) the cursor is not on
5252      *            one of this rowset's rows or its insert row, (3) the type
5253      *            of the designated column is not an SQL <code>TIME</code> or
5254      *            <code>TIMESTAMP</code>, or (4) this rowset is
5255      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5256      */
5257     public void updateTime(String columnName, java.sql.Time x) throws SQLException {
5258         updateTime(getColIdxByName(columnName), x);
5259     }
5260 
5261     /**
5262      * Sets the designated column in either the current row or the insert
5263      * row of this <code>CachedRowSetImpl</code> object with the given
5264      * <code>Timestamp</code> object.
5265      *
5266      * This method updates a column value in either the current row or
5267      * the insert row of this rowset, but it does not update the
5268      * database.  If the cursor is on a row in the rowset, the
5269      * method {@link #updateRow} must be called to update the database.
5270      * If the cursor is on the insert row, the method {@link #insertRow}
5271      * must be called, which will insert the new row into both this rowset
5272      * and the database. Both of these methods must be called before the
5273      * cursor moves to another row.
5274      *
5275      * @param columnName a <code>String</code> object that must match the
5276      *        SQL name of a column in this rowset, ignoring case
5277      * @param x the new column value
5278      * @throws SQLException if the given column index is out of bounds or
5279      *            the cursor is not on one of this rowset's rows or its
5280      *            insert row
5281      * @throws SQLException if (1) the given column name does not match the
5282      *            name of a column in this rowset, (2) the cursor is not on
5283      *            one of this rowset's rows or its insert row, (3) the type
5284      *            of the designated column is not an SQL <code>DATE</code>,
5285      *            <code>TIME</code>, or <code>TIMESTAMP</code>, or (4) this
5286      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5287      */
5288     public void updateTimestamp(String columnName, java.sql.Timestamp x) throws SQLException {
5289         updateTimestamp(getColIdxByName(columnName), x);
5290     }
5291 
5292     /**
5293      * Sets the designated column in either the current row or the insert
5294      * row of this <code>CachedRowSetImpl</code> object with the given
5295      * ASCII stream value.
5296      * <P>
5297      * This method updates a column value in either the current row or
5298      * the insert row of this rowset, but it does not update the
5299      * database.  If the cursor is on a row in the rowset, the
5300      * method {@link #updateRow} must be called to update the database.
5301      * If the cursor is on the insert row, the method {@link #insertRow}
5302      * must be called, which will insert the new row into both this rowset
5303      * and the database. Both of these methods must be called before the
5304      * cursor moves to another row.
5305      *
5306      * @param columnName a <code>String</code> object that must match the
5307      *        SQL name of a column in this rowset, ignoring case
5308      * @param x the new column value
5309      * @param length the number of one-byte ASCII characters in the stream
5310      */
5311     public void updateAsciiStream(String columnName,
5312     java.io.InputStream x,
5313     int length) throws SQLException {
5314         updateAsciiStream(getColIdxByName(columnName), x, length);
5315     }
5316 
5317     /**
5318      * Sets the designated column in either the current row or the insert
5319      * row of this <code>CachedRowSetImpl</code> object with the given
5320      * <code>java.io.InputStream</code> object.
5321      * <P>
5322      * This method updates a column value in either the current row or
5323      * the insert row of this rowset, but it does not update the
5324      * database.  If the cursor is on a row in the rowset, the
5325      * method {@link #updateRow} must be called to update the database.
5326      * If the cursor is on the insert row, the method {@link #insertRow}
5327      * must be called, which will insert the new row into both this rowset
5328      * and the database. Both of these methods must be called before the
5329      * cursor moves to another row.
5330      *
5331      * @param columnName a <code>String</code> object that must match the
5332      *        SQL name of a column in this rowset, ignoring case
5333      * @param x the new column value; must be a <code>java.io.InputStream</code>
5334      *          containing <code>BINARY</code>, <code>VARBINARY</code>, or
5335      *          <code>LONGVARBINARY</code> data
5336      * @param length the length of the stream in bytes
5337      * @throws SQLException if (1) the given column name does not match the
5338      *            name of a column in this rowset, (2) the cursor is not on
5339      *            one of this rowset's rows or its insert row, (3) the data
5340      *            in the stream is not binary, or (4) this rowset is
5341      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5342      */
5343     public void updateBinaryStream(String columnName, java.io.InputStream x, int length) throws SQLException {
5344         updateBinaryStream(getColIdxByName(columnName), x, length);
5345     }
5346 
5347     /**
5348      * Sets the designated column in either the current row or the insert
5349      * row of this <code>CachedRowSetImpl</code> object with the given
5350      * <code>java.io.Reader</code> object.
5351      * <P>
5352      * This method updates a column value in either the current row or
5353      * the insert row of this rowset, but it does not update the
5354      * database.  If the cursor is on a row in the rowset, the
5355      * method {@link #updateRow} must be called to update the database.
5356      * If the cursor is on the insert row, the method {@link #insertRow}
5357      * must be called, which will insert the new row into both this rowset
5358      * and the database. Both of these methods must be called before the
5359      * cursor moves to another row.
5360      *
5361      * @param columnName a <code>String</code> object that must match the
5362      *        SQL name of a column in this rowset, ignoring case
5363      * @param reader the new column value; must be a
5364      * <code>java.io.Reader</code> containing <code>BINARY</code>,
5365      * <code>VARBINARY</code>, <code>LONGVARBINARY</code>, <code>CHAR</code>,
5366      * <code>VARCHAR</code>, or <code>LONGVARCHAR</code> data
5367      * @param length the length of the stream in characters
5368      * @throws SQLException if (1) the given column name does not match the
5369      *            name of a column in this rowset, (2) the cursor is not on
5370      *            one of this rowset's rows or its insert row, (3) the data
5371      *            in the stream is not a binary or character type, or (4) this
5372      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5373      */
5374     public void updateCharacterStream(String columnName,
5375     java.io.Reader reader,
5376     int length) throws SQLException {
5377         updateCharacterStream(getColIdxByName(columnName), reader, length);
5378     }
5379 
5380     /**
5381      * Sets the designated column in either the current row or the insert
5382      * row of this <code>CachedRowSetImpl</code> object with the given
5383      * <code>Object</code> value.  The <code>scale</code> parameter
5384      * indicates the number of digits to the right of the decimal point
5385      * and is ignored if the new column value is not a type that will be
5386      *  mapped to an SQL <code>DECIMAL</code> or <code>NUMERIC</code> value.
5387      * <P>
5388      * This method updates a column value in either the current row or
5389      * the insert row of this rowset, but it does not update the
5390      * database.  If the cursor is on a row in the rowset, the
5391      * method {@link #updateRow} must be called to update the database.
5392      * If the cursor is on the insert row, the method {@link #insertRow}
5393      * must be called, which will insert the new row into both this rowset
5394      * and the database. Both of these methods must be called before the
5395      * cursor moves to another row.
5396      *
5397      * @param columnName a <code>String</code> object that must match the
5398      *        SQL name of a column in this rowset, ignoring case
5399      * @param x the new column value
5400      * @param scale the number of digits to the right of the decimal point (for
5401      *              <code>DECIMAL</code> and <code>NUMERIC</code> types only)
5402      * @throws SQLException if (1) the given column name does not match the
5403      *            name of a column in this rowset, (2) the cursor is not on
5404      *            one of this rowset's rows or its insert row, or (3) this
5405      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5406      */
5407     public void updateObject(String columnName, Object x, int scale) throws SQLException {
5408         updateObject(getColIdxByName(columnName), x, scale);
5409     }
5410 
5411     /**
5412      * Sets the designated column in either the current row or the insert
5413      * row of this <code>CachedRowSetImpl</code> object with the given
5414      * <code>Object</code> value.
5415      * <P>
5416      * This method updates a column value in either the current row or
5417      * the insert row of this rowset, but it does not update the
5418      * database.  If the cursor is on a row in the rowset, the
5419      * method {@link #updateRow} must be called to update the database.
5420      * If the cursor is on the insert row, the method {@link #insertRow}
5421      * must be called, which will insert the new row into both this rowset
5422      * and the database. Both of these methods must be called before the
5423      * cursor moves to another row.
5424      *
5425      * @param columnName a <code>String</code> object that must match the
5426      *        SQL name of a column in this rowset, ignoring case
5427      * @param x the new column value
5428      * @throws SQLException if (1) the given column name does not match the
5429      *            name of a column in this rowset, (2) the cursor is not on
5430      *            one of this rowset's rows or its insert row, or (3) this
5431      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5432      */
5433     public void updateObject(String columnName, Object x) throws SQLException {
5434         updateObject(getColIdxByName(columnName), x);
5435     }
5436 
5437     /**
5438      * Inserts the contents of this <code>CachedRowSetImpl</code> object's insert
5439      * row into this rowset immediately following the current row.
5440      * If the current row is the
5441      * position after the last row or before the first row, the new row will
5442      * be inserted at the end of the rowset.  This method also notifies
5443      * listeners registered with this rowset that the row has changed.
5444      * <P>
5445      * The cursor must be on the insert row when this method is called.
5446      *
5447      * @throws SQLException if (1) the cursor is not on the insert row,
5448      *            (2) one or more of the non-nullable columns in the insert
5449      *            row has not been given a value, or (3) this rowset is
5450      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5451      */
5452     public void insertRow() throws SQLException {
5453         int pos;
5454 
5455         if (onInsertRow == false ||
5456             insertRow.isCompleteRow(RowSetMD) == false) {
5457                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.failedins").toString());
5458         }
5459         // Added the setting of parameters that are passed
5460         // to setXXX methods after an empty CRS Object is
5461         // created through RowSetMetaData object
5462         Object [] toInsert = getParams();
5463 
5464         for(int i = 0;i < toInsert.length; i++) {
5465           insertRow.setColumnObject(i+1,toInsert[i]);
5466         }
5467 
5468         Row insRow = new Row(RowSetMD.getColumnCount(),
5469         insertRow.getOrigRow());
5470         insRow.setInserted();
5471         /*
5472          * The new row is inserted into the RowSet
5473          * immediately following the current row.
5474          *
5475          * If we are afterlast then the rows are
5476          * inserted at the end.
5477          */
5478         if (currentRow >= numRows || currentRow < 0) {
5479             pos = numRows;
5480         } else {
5481             pos = currentRow;
5482         }
5483 
5484         rvh.add(pos, insRow);
5485         ++numRows;
5486         // notify the listeners that the row changed.
5487         notifyRowChanged();
5488     }
5489 
5490     /**
5491      * Marks the current row of this <code>CachedRowSetImpl</code> object as
5492      * updated and notifies listeners registered with this rowset that the
5493      * row has changed.
5494      * <P>
5495      * This method  cannot be called when the cursor is on the insert row, and
5496      * it should be called before the cursor moves to another row.  If it is
5497      * called after the cursor moves to another row, this method has no effect,
5498      * and the updates made before the cursor moved will be lost.
5499      *
5500      * @throws SQLException if the cursor is on the insert row or this
5501      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5502      */
5503     public void updateRow() throws SQLException {
5504         // make sure we aren't on the insert row
5505         if (onInsertRow == true) {
5506             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.updateins").toString());
5507         }
5508 
5509         ((Row)getCurrentRow()).setUpdated();
5510 
5511         // notify the listeners that the row changed.
5512         notifyRowChanged();
5513     }
5514 
5515     /**
5516      * Deletes the current row from this <code>CachedRowSetImpl</code> object and
5517      * notifies listeners registered with this rowset that a row has changed.
5518      * This method cannot be called when the cursor is on the insert row.
5519      * <P>
5520      * This method marks the current row as deleted, but it does not delete
5521      * the row from the underlying data source.  The method
5522      * <code>acceptChanges</code> must be called to delete the row in
5523      * the data source.
5524      *
5525      * @throws SQLException if (1) this method is called when the cursor
5526      *            is on the insert row, before the first row, or after the
5527      *            last row or (2) this rowset is
5528      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5529      */
5530     public void deleteRow() throws SQLException {
5531         // make sure the cursor is on a valid row
5532         checkCursor();
5533 
5534         ((Row)getCurrentRow()).setDeleted();
5535         ++numDeleted;
5536 
5537         // notify the listeners that the row changed.
5538         notifyRowChanged();
5539     }
5540 
5541     /**
5542      * Sets the current row with its original value and marks the row as
5543      * not updated, thus undoing any changes made to the row since the
5544      * last call to the methods <code>updateRow</code> or <code>deleteRow</code>.
5545      * This method should be called only when the cursor is on a row in
5546      * this rowset.
5547      *
5548      * @throws SQLException if the cursor is on the insert row, before the
5549      *            first row, or after the last row
5550      */
5551     public void refreshRow() throws SQLException {
5552         // make sure we are on a row
5553         checkCursor();
5554 
5555         // don't want this to happen...
5556         if (onInsertRow == true) {
5557             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
5558         }
5559 
5560         Row currentRow = (Row)getCurrentRow();
5561         // just undo any changes made to this row.
5562         currentRow.clearUpdated();
5563 
5564     }
5565 
5566     /**
5567      * Rolls back any updates made to the current row of this
5568      * <code>CachedRowSetImpl</code> object and notifies listeners that
5569      * a row has changed.  To have an effect, this method
5570      * must be called after an <code>updateXXX</code> method has been
5571      * called and before the method <code>updateRow</code> has been called.
5572      * If no updates have been made or the method <code>updateRow</code>
5573      * has already been called, this method has no effect.
5574      *
5575      * @throws SQLException if the cursor is on the insert row, before the
5576      *            first row, or after the last row
5577      */
5578     public void cancelRowUpdates() throws SQLException {
5579         // make sure we are on a row
5580         checkCursor();
5581 
5582         // don't want this to happen...
5583         if (onInsertRow == true) {
5584             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
5585         }
5586 
5587         Row currentRow = (Row)getCurrentRow();
5588         if (currentRow.getUpdated() == true) {
5589             currentRow.clearUpdated();
5590             notifyRowChanged();
5591         }
5592     }
5593 
5594     /**
5595      * Moves the cursor for this <code>CachedRowSetImpl</code> object
5596      * to the insert row.  The current row in the rowset is remembered
5597      * while the cursor is on the insert row.
5598      * <P>
5599      * The insert row is a special row associated with an updatable
5600      * rowset.  It is essentially a buffer where a new row may
5601      * be constructed by calling the appropriate <code>updateXXX</code>
5602      * methods to assign a value to each column in the row.  A complete
5603      * row must be constructed; that is, every column that is not nullable
5604      * must be assigned a value.  In order for the new row to become part
5605      * of this rowset, the method <code>insertRow</code> must be called
5606      * before the cursor is moved back to the rowset.
5607      * <P>
5608      * Only certain methods may be invoked while the cursor is on the insert
5609      * row; many methods throw an exception if they are called while the
5610      * cursor is there.  In addition to the <code>updateXXX</code>
5611      * and <code>insertRow</code> methods, only the <code>getXXX</code> methods
5612      * may be called when the cursor is on the insert row.  A <code>getXXX</code>
5613      * method should be called on a column only after an <code>updateXXX</code>
5614      * method has been called on that column; otherwise, the value returned is
5615      * undetermined.
5616      *
5617      * @throws SQLException if this <code>CachedRowSetImpl</code> object is
5618      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5619      */
5620     public void moveToInsertRow() throws SQLException {
5621         if (getConcurrency() == ResultSet.CONCUR_READ_ONLY) {
5622             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins").toString());
5623         }
5624         if (insertRow == null) {
5625             if (RowSetMD == null)
5626                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins1").toString());
5627             int numCols = RowSetMD.getColumnCount();
5628             if (numCols > 0) {
5629                 insertRow = new InsertRow(numCols);
5630             } else {
5631                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins2").toString());
5632             }
5633         }
5634         onInsertRow = true;
5635         // %%% setCurrentRow called in BaseRow
5636 
5637         currentRow = cursorPos;
5638         cursorPos = -1;
5639 
5640         insertRow.initInsertRow();
5641     }
5642 
5643     /**
5644      * Moves the cursor for this <code>CachedRowSetImpl</code> object to
5645      * the current row.  The current row is the row the cursor was on
5646      * when the method <code>moveToInsertRow</code> was called.
5647      * <P>
5648      * Calling this method has no effect unless it is called while the
5649      * cursor is on the insert row.
5650      *
5651      * @throws SQLException if an error occurs
5652      */
5653     public void moveToCurrentRow() throws SQLException {
5654         if (onInsertRow == false) {
5655             return;
5656         } else {
5657             cursorPos = currentRow;
5658             onInsertRow = false;
5659         }
5660     }
5661 
5662     /**
5663      * Returns <code>null</code>.
5664      *
5665      * @return <code>null</code>
5666      * @throws SQLException if an error occurs
5667      */
5668     public Statement getStatement() throws SQLException {
5669         return null;
5670     }
5671 
5672     /**
5673      * Retrieves the value of the designated column in this
5674      * <code>CachedRowSetImpl</code> object as an <code>Object</code> in
5675      * the Java programming language, using the given
5676      * <code>java.util.Map</code> object to custom map the value if
5677      * appropriate.
5678      *
5679      * @param columnIndex the first column is <code>1</code>, the second
5680      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5681      *        and equal to or less than the number of columns in this rowset
5682      * @param map a <code>java.util.Map</code> object showing the mapping
5683      *            from SQL type names to classes in the Java programming
5684      *            language
5685      * @return an <code>Object</code> representing the SQL value
5686      * @throws SQLException if the given column index is out of bounds or
5687      *            the cursor is not on one of this rowset's rows or its
5688      *            insert row
5689      */
5690      public Object getObject(int columnIndex,
5691                              java.util.Map<String,Class<?>> map)
5692          throws SQLException
5693      {
5694         Object value;
5695 
5696         // sanity check.
5697         checkIndex(columnIndex);
5698         // make sure the cursor is on a valid row
5699         checkCursor();
5700 
5701         setLastValueNull(false);
5702         value = getCurrentRow().getColumnObject(columnIndex);
5703 
5704         // check for SQL NULL
5705         if (value == null) {
5706             setLastValueNull(true);
5707             return null;
5708         }
5709         if (value instanceof Struct) {
5710             Struct s = (Struct)value;
5711 
5712             // look up the class in the map
5713             Class c = (Class)map.get(s.getSQLTypeName());
5714             if (c != null) {
5715                 // create new instance of the class
5716                 SQLData obj = null;
5717                 try {
5718                     obj = (SQLData)c.newInstance();
5719                 } catch (java.lang.InstantiationException ex) {
5720                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
5721                     ex.getMessage()));
5722                 } catch (java.lang.IllegalAccessException ex) {
5723                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
5724                     ex.getMessage()));
5725                 }
5726                 // get the attributes from the struct
5727                 Object attribs[] = s.getAttributes(map);
5728                 // create the SQLInput "stream"
5729                 SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
5730                 // read the values...
5731                 obj.readSQL(sqlInput, s.getSQLTypeName());
5732                 return (Object)obj;
5733             }
5734         }
5735         return value;
5736     }
5737 
5738     /**
5739      * Retrieves the value of the designated column in this
5740      * <code>CachedRowSetImpl</code> object as a <code>Ref</code> object
5741      * in the Java programming language.
5742      *
5743      * @param columnIndex the first column is <code>1</code>, the second
5744      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5745      *        and equal to or less than the number of columns in this rowset
5746      * @return a <code>Ref</code> object representing an SQL<code> REF</code> value
5747      * @throws SQLException if (1) the given column index is out of bounds,
5748      *            (2) the cursor is not on one of this rowset's rows or its
5749      *            insert row, or (3) the designated column does not store an
5750      *            SQL <code>REF</code> value
5751      * @see #getRef(String)
5752      */
5753     public Ref getRef(int columnIndex) throws SQLException {
5754         Ref value;
5755 
5756         // sanity check.
5757         checkIndex(columnIndex);
5758         // make sure the cursor is on a valid row
5759         checkCursor();
5760 
5761         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.REF) {
5762             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5763         }
5764 
5765         setLastValueNull(false);
5766         value = (Ref)(getCurrentRow().getColumnObject(columnIndex));
5767 
5768         // check for SQL NULL
5769         if (value == null) {
5770             setLastValueNull(true);
5771             return null;
5772         }
5773 
5774         return value;
5775     }
5776 
5777     /**
5778      * Retrieves the value of the designated column in this
5779      * <code>CachedRowSetImpl</code> object as a <code>Blob</code> object
5780      * in the Java programming language.
5781      *
5782      * @param columnIndex the first column is <code>1</code>, the second
5783      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5784      *        and equal to or less than the number of columns in this rowset
5785      * @return a <code>Blob</code> object representing an SQL <code>BLOB</code> value
5786      * @throws SQLException if (1) the given column index is out of bounds,
5787      *            (2) the cursor is not on one of this rowset's rows or its
5788      *            insert row, or (3) the designated column does not store an
5789      *            SQL <code>BLOB</code> value
5790      * @see #getBlob(String)
5791      */
5792     public Blob getBlob(int columnIndex) throws SQLException {
5793         Blob value;
5794 
5795         // sanity check.
5796         checkIndex(columnIndex);
5797         // make sure the cursor is on a valid row
5798         checkCursor();
5799 
5800         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.BLOB) {
5801             System.out.println(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.type").toString(), RowSetMD.getColumnType(columnIndex)));
5802             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5803         }
5804 
5805         setLastValueNull(false);
5806         value = (Blob)(getCurrentRow().getColumnObject(columnIndex));
5807 
5808         // check for SQL NULL
5809         if (value == null) {
5810             setLastValueNull(true);
5811             return null;
5812         }
5813 
5814         return value;
5815     }
5816 
5817     /**
5818      * Retrieves the value of the designated column in this
5819      * <code>CachedRowSetImpl</code> object as a <code>Clob</code> object
5820      * in the Java programming language.
5821      *
5822      * @param columnIndex the first column is <code>1</code>, the second
5823      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5824      *        and equal to or less than the number of columns in this rowset
5825      * @return a <code>Clob</code> object representing an SQL <code>CLOB</code> value
5826      * @throws SQLException if (1) the given column index is out of bounds,
5827      *            (2) the cursor is not on one of this rowset's rows or its
5828      *            insert row, or (3) the designated column does not store an
5829      *            SQL <code>CLOB</code> value
5830      * @see #getClob(String)
5831      */
5832     public Clob getClob(int columnIndex) throws SQLException {
5833         Clob value;
5834 
5835         // sanity check.
5836         checkIndex(columnIndex);
5837         // make sure the cursor is on a valid row
5838         checkCursor();
5839 
5840         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.CLOB) {
5841             System.out.println(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.type").toString(), RowSetMD.getColumnType(columnIndex)));
5842             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5843         }
5844 
5845         setLastValueNull(false);
5846         value = (Clob)(getCurrentRow().getColumnObject(columnIndex));
5847 
5848         // check for SQL NULL
5849         if (value == null) {
5850             setLastValueNull(true);
5851             return null;
5852         }
5853 
5854         return value;
5855     }
5856 
5857     /**
5858      * Retrieves the value of the designated column in this
5859      * <code>CachedRowSetImpl</code> object as an <code>Array</code> object
5860      * in the Java programming language.
5861      *
5862      * @param columnIndex the first column is <code>1</code>, the second
5863      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5864      *        and equal to or less than the number of columns in this rowset
5865      * @return an <code>Array</code> object representing an SQL
5866      *         <code>ARRAY</code> value
5867      * @throws SQLException if (1) the given column index is out of bounds,
5868      *            (2) the cursor is not on one of this rowset's rows or its
5869      *            insert row, or (3) the designated column does not store an
5870      *            SQL <code>ARRAY</code> value
5871      * @see #getArray(String)
5872      */
5873     public Array getArray(int columnIndex) throws SQLException {
5874         java.sql.Array value;
5875 
5876         // sanity check.
5877         checkIndex(columnIndex);
5878         // make sure the cursor is on a valid row
5879         checkCursor();
5880 
5881         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.ARRAY) {
5882             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5883         }
5884 
5885         setLastValueNull(false);
5886         value = (java.sql.Array)(getCurrentRow().getColumnObject(columnIndex));
5887 
5888         // check for SQL NULL
5889         if (value == null) {
5890             setLastValueNull(true);
5891             return null;
5892         }
5893 
5894         return value;
5895     }
5896 
5897     /**
5898      * Retrieves the value of the designated column in this
5899      * <code>CachedRowSetImpl</code> object as an <code>Object</code> in
5900      * the Java programming language, using the given
5901      * <code>java.util.Map</code> object to custom map the value if
5902      * appropriate.
5903      *
5904      * @param columnName a <code>String</code> object that must match the
5905      *        SQL name of a column in this rowset, ignoring case
5906      * @param map a <code>java.util.Map</code> object showing the mapping
5907      *        from SQL type names to classes in the Java programming
5908      *        language
5909      * @return an <code>Object</code> representing the SQL value
5910      * @throws SQLException if the given column name is not the name of
5911      *         a column in this rowset or the cursor is not on one of
5912      *         this rowset's rows or its insert row
5913      */
5914     public Object getObject(String columnName,
5915                             java.util.Map<String,Class<?>> map)
5916     throws SQLException {
5917         return getObject(getColIdxByName(columnName), map);
5918     }
5919 
5920     /**
5921      * Retrieves the value of the designated column in this
5922      * <code>CachedRowSetImpl</code> object as a <code>Ref</code> object
5923      * in the Java programming language.
5924      *
5925      * @param colName a <code>String</code> object that must match the
5926      *        SQL name of a column in this rowset, ignoring case
5927      * @return a <code>Ref</code> object representing an SQL<code> REF</code> value
5928      * @throws SQLException  if (1) the given column name is not the name of
5929      *            a column in this rowset, (2) the cursor is not on one of
5930      *            this rowset's rows or its insert row, or (3) the column value
5931      *            is not an SQL <code>REF</code> value
5932      * @see #getRef(int)
5933      */
5934     public Ref getRef(String colName) throws SQLException {
5935         return getRef(getColIdxByName(colName));
5936     }
5937 
5938     /**
5939      * Retrieves the value of the designated column in this
5940      * <code>CachedRowSetImpl</code> object as a <code>Blob</code> object
5941      * in the Java programming language.
5942      *
5943      * @param colName a <code>String</code> object that must match the
5944      *        SQL name of a column in this rowset, ignoring case
5945      * @return a <code>Blob</code> object representing an SQL <code>BLOB</code> value
5946      * @throws SQLException if (1) the given column name is not the name of
5947      *            a column in this rowset, (2) the cursor is not on one of
5948      *            this rowset's rows or its insert row, or (3) the designated
5949      *            column does not store an SQL <code>BLOB</code> value
5950      * @see #getBlob(int)
5951      */
5952     public Blob getBlob(String colName) throws SQLException {
5953         return getBlob(getColIdxByName(colName));
5954     }
5955 
5956     /**
5957      * Retrieves the value of the designated column in this
5958      * <code>CachedRowSetImpl</code> object as a <code>Clob</code> object
5959      * in the Java programming language.
5960      *
5961      * @param colName a <code>String</code> object that must match the
5962      *        SQL name of a column in this rowset, ignoring case
5963      * @return a <code>Clob</code> object representing an SQL
5964      *         <code>CLOB</code> value
5965      * @throws SQLException if (1) the given column name is not the name of
5966      *            a column in this rowset, (2) the cursor is not on one of
5967      *            this rowset's rows or its insert row, or (3) the designated
5968      *            column does not store an SQL <code>CLOB</code> value
5969      * @see #getClob(int)
5970      */
5971     public Clob getClob(String colName) throws SQLException {
5972         return getClob(getColIdxByName(colName));
5973     }
5974 
5975     /**
5976      * Retrieves the value of the designated column in this
5977      * <code>CachedRowSetImpl</code> object as an <code>Array</code> object
5978      * in the Java programming langugage.
5979      *
5980      * @param colName a <code>String</code> object that must match the
5981      *        SQL name of a column in this rowset, ignoring case
5982      * @return an <code>Array</code> object representing an SQL
5983      *         <code>ARRAY</code> value
5984      * @throws SQLException if (1) the given column name is not the name of
5985      *            a column in this rowset, (2) the cursor is not on one of
5986      *            this rowset's rows or its insert row, or (3) the designated
5987      *            column does not store an SQL <code>ARRAY</code> value
5988      * @see #getArray(int)
5989      */
5990     public Array getArray(String colName) throws SQLException {
5991         return getArray(getColIdxByName(colName));
5992     }
5993 
5994     /**
5995      * Retrieves the value of the designated column in the current row
5996      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Date</code>
5997      * object, using the given <code>Calendar</code> object to construct an
5998      * appropriate millisecond value for the date.
5999      *
6000      * @param columnIndex the first column is <code>1</code>, the second
6001      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6002      *        and equal to or less than the number of columns in the rowset
6003      * @param cal the <code>java.util.Calendar</code> object to use in
6004      *            constructing the date
6005      * @return the column value; if the value is SQL <code>NULL</code>,
6006      *         the result is <code>null</code>
6007      * @throws SQLException if (1) the given column name is not the name of
6008      *            a column in this rowset, (2) the cursor is not on one of
6009      *            this rowset's rows or its insert row, or (3) the designated
6010      *            column does not store an SQL <code>DATE</code> or
6011      *            <code>TIMESTAMP</code> value
6012      */
6013     public java.sql.Date getDate(int columnIndex, Calendar cal) throws SQLException {
6014         Object value;
6015 
6016         // sanity check.
6017         checkIndex(columnIndex);
6018         // make sure the cursor is on a valid row
6019         checkCursor();
6020 
6021         setLastValueNull(false);
6022         value = getCurrentRow().getColumnObject(columnIndex);
6023 
6024         // check for SQL NULL
6025         if (value == null) {
6026             setLastValueNull(true);
6027             return null;
6028         }
6029 
6030         value = convertTemporal(value,
6031         RowSetMD.getColumnType(columnIndex),
6032         java.sql.Types.DATE);
6033 
6034         // create a default calendar
6035         Calendar defaultCal = Calendar.getInstance();
6036         // set this Calendar to the time we have
6037         defaultCal.setTime((java.util.Date)value);
6038 
6039         /*
6040          * Now we can pull the pieces of the date out
6041          * of the default calendar and put them into
6042          * the user provided calendar
6043          */
6044         cal.set(Calendar.YEAR, defaultCal.get(Calendar.YEAR));
6045         cal.set(Calendar.MONTH, defaultCal.get(Calendar.MONTH));
6046         cal.set(Calendar.DAY_OF_MONTH, defaultCal.get(Calendar.DAY_OF_MONTH));
6047 
6048         /*
6049          * This looks a little odd but it is correct -
6050          * Calendar.getTime() returns a Date...
6051          */
6052         return new java.sql.Date(cal.getTime().getTime());
6053     }
6054 
6055     /**
6056      * Retrieves the value of the designated column in the current row
6057      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Date</code>
6058      * object, using the given <code>Calendar</code> object to construct an
6059      * appropriate millisecond value for the date.
6060      *
6061      * @param columnName a <code>String</code> object that must match the
6062      *        SQL name of a column in this rowset, ignoring case
6063      * @param cal the <code>java.util.Calendar</code> object to use in
6064      *            constructing the date
6065      * @return the column value; if the value is SQL <code>NULL</code>,
6066      *         the result is <code>null</code>
6067      * @throws SQLException if (1) the given column name is not the name of
6068      *            a column in this rowset, (2) the cursor is not on one of
6069      *            this rowset's rows or its insert row, or (3) the designated
6070      *            column does not store an SQL <code>DATE</code> or
6071      *            <code>TIMESTAMP</code> value
6072      */
6073     public java.sql.Date getDate(String columnName, Calendar cal) throws SQLException {
6074         return getDate(getColIdxByName(columnName), cal);
6075     }
6076 
6077     /**
6078      * Retrieves the value of the designated column in the current row
6079      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Time</code>
6080      * object, using the given <code>Calendar</code> object to construct an
6081      * appropriate millisecond value for the date.
6082      *
6083      * @param columnIndex the first column is <code>1</code>, the second
6084      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6085      *        and equal to or less than the number of columns in the rowset
6086      * @param cal the <code>java.util.Calendar</code> object to use in
6087      *            constructing the date
6088      * @return the column value; if the value is SQL <code>NULL</code>,
6089      *         the result is <code>null</code>
6090      * @throws SQLException if (1) the given column name is not the name of
6091      *            a column in this rowset, (2) the cursor is not on one of
6092      *            this rowset's rows or its insert row, or (3) the designated
6093      *            column does not store an SQL <code>TIME</code> or
6094      *            <code>TIMESTAMP</code> value
6095      */
6096     public java.sql.Time getTime(int columnIndex, Calendar cal) throws SQLException {
6097         Object value;
6098 
6099         // sanity check.
6100         checkIndex(columnIndex);
6101         // make sure the cursor is on a valid row
6102         checkCursor();
6103 
6104         setLastValueNull(false);
6105         value = getCurrentRow().getColumnObject(columnIndex);
6106 
6107         // check for SQL NULL
6108         if (value == null) {
6109             setLastValueNull(true);
6110             return null;
6111         }
6112 
6113         value = convertTemporal(value,
6114         RowSetMD.getColumnType(columnIndex),
6115         java.sql.Types.TIME);
6116 
6117         // create a default calendar
6118         Calendar defaultCal = Calendar.getInstance();
6119         // set the time in the default calendar
6120         defaultCal.setTime((java.util.Date)value);
6121 
6122         /*
6123          * Now we can pull the pieces of the date out
6124          * of the default calendar and put them into
6125          * the user provided calendar
6126          */
6127         cal.set(Calendar.HOUR_OF_DAY, defaultCal.get(Calendar.HOUR_OF_DAY));
6128         cal.set(Calendar.MINUTE, defaultCal.get(Calendar.MINUTE));
6129         cal.set(Calendar.SECOND, defaultCal.get(Calendar.SECOND));
6130 
6131         return new java.sql.Time(cal.getTime().getTime());
6132     }
6133 
6134     /**
6135      * Retrieves the value of the designated column in the current row
6136      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Time</code>
6137      * object, using the given <code>Calendar</code> object to construct an
6138      * appropriate millisecond value for the date.
6139      *
6140      * @param columnName a <code>String</code> object that must match the
6141      *        SQL name of a column in this rowset, ignoring case
6142      * @param cal the <code>java.util.Calendar</code> object to use in
6143      *            constructing the date
6144      * @return the column value; if the value is SQL <code>NULL</code>,
6145      *         the result is <code>null</code>
6146      * @throws SQLException if (1) the given column name is not the name of
6147      *            a column in this rowset, (2) the cursor is not on one of
6148      *            this rowset's rows or its insert row, or (3) the designated
6149      *            column does not store an SQL <code>TIME</code> or
6150      *            <code>TIMESTAMP</code> value
6151      */
6152     public java.sql.Time getTime(String columnName, Calendar cal) throws SQLException {
6153         return getTime(getColIdxByName(columnName), cal);
6154     }
6155 
6156     /**
6157      * Retrieves the value of the designated column in the current row
6158      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Timestamp</code>
6159      * object, using the given <code>Calendar</code> object to construct an
6160      * appropriate millisecond value for the date.
6161      *
6162      * @param columnIndex the first column is <code>1</code>, the second
6163      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6164      *        and equal to or less than the number of columns in the rowset
6165      * @param cal the <code>java.util.Calendar</code> object to use in
6166      *            constructing the date
6167      * @return the column value; if the value is SQL <code>NULL</code>,
6168      *         the result is <code>null</code>
6169      * @throws SQLException if (1) the given column name is not the name of
6170      *            a column in this rowset, (2) the cursor is not on one of
6171      *            this rowset's rows or its insert row, or (3) the designated
6172      *            column does not store an SQL <code>TIME</code> or
6173      *            <code>TIMESTAMP</code> value
6174      */
6175     public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
6176         Object value;
6177 
6178         // sanity check.
6179         checkIndex(columnIndex);
6180         // make sure the cursor is on a valid row
6181         checkCursor();
6182 
6183         setLastValueNull(false);
6184         value = getCurrentRow().getColumnObject(columnIndex);
6185 
6186         // check for SQL NULL
6187         if (value == null) {
6188             setLastValueNull(true);
6189             return null;
6190         }
6191 
6192         value = convertTemporal(value,
6193         RowSetMD.getColumnType(columnIndex),
6194         java.sql.Types.TIMESTAMP);
6195 
6196         // create a default calendar
6197         Calendar defaultCal = Calendar.getInstance();
6198         // set the time in the default calendar
6199         defaultCal.setTime((java.util.Date)value);
6200 
6201         /*
6202          * Now we can pull the pieces of the date out
6203          * of the default calendar and put them into
6204          * the user provided calendar
6205          */
6206         cal.set(Calendar.YEAR, defaultCal.get(Calendar.YEAR));
6207         cal.set(Calendar.MONTH, defaultCal.get(Calendar.MONTH));
6208         cal.set(Calendar.DAY_OF_MONTH, defaultCal.get(Calendar.DAY_OF_MONTH));
6209         cal.set(Calendar.HOUR_OF_DAY, defaultCal.get(Calendar.HOUR_OF_DAY));
6210         cal.set(Calendar.MINUTE, defaultCal.get(Calendar.MINUTE));
6211         cal.set(Calendar.SECOND, defaultCal.get(Calendar.SECOND));
6212 
6213         return new java.sql.Timestamp(cal.getTime().getTime());
6214     }
6215 
6216     /**
6217      * Retrieves the value of the designated column in the current row
6218      * of this <code>CachedRowSetImpl</code> object as a
6219      * <code>java.sql.Timestamp</code> object, using the given
6220      * <code>Calendar</code> object to construct an appropriate
6221      * millisecond value for the date.
6222      *
6223      * @param columnName a <code>String</code> object that must match the
6224      *        SQL name of a column in this rowset, ignoring case
6225      * @param cal the <code>java.util.Calendar</code> object to use in
6226      *            constructing the date
6227      * @return the column value; if the value is SQL <code>NULL</code>,
6228      *         the result is <code>null</code>
6229      * @throws SQLException if (1) the given column name is not the name of
6230      *            a column in this rowset, (2) the cursor is not on one of
6231      *            this rowset's rows or its insert row, or (3) the designated
6232      *            column does not store an SQL <code>DATE</code>,
6233      *            <code>TIME</code>, or <code>TIMESTAMP</code> value
6234      */
6235     public java.sql.Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException {
6236         return getTimestamp(getColIdxByName(columnName), cal);
6237     }
6238 
6239     /*
6240      * RowSetInternal Interface
6241      */
6242 
6243     /**
6244      * Retrieves the <code>Connection</code> object passed to this
6245      * <code>CachedRowSetImpl</code> object.  This connection may be
6246      * used to populate this rowset with data or to write data back
6247      * to its underlying data source.
6248      *
6249      * @return the <code>Connection</code> object passed to this rowset;
6250      *         may be <code>null</code> if there is no connection
6251      * @throws SQLException if an error occurs
6252      */
6253     public Connection getConnection() throws SQLException{
6254         return conn;
6255     }
6256 
6257     /**
6258      * Sets the metadata for this <code>CachedRowSetImpl</code> object
6259      * with the given <code>RowSetMetaData</code> object.
6260      *
6261      * @param md a <code>RowSetMetaData</code> object instance containing
6262      *            metadata about the columsn in the rowset
6263      * @throws SQLException if invalid meta data is supplied to the
6264      *            rowset
6265      */
6266     public void setMetaData(RowSetMetaData md) throws SQLException {
6267         RowSetMD =(RowSetMetaDataImpl) md;
6268     }
6269 
6270     /**
6271      * Returns a result set containing the original value of the rowset. The
6272      * original value is the state of the <code>CachedRowSetImpl</code> after the
6273      * last population or synchronization (whichever occured most recently) with
6274      * the data source.
6275      * <p>
6276      * The cursor is positioned before the first row in the result set.
6277      * Only rows contained in the result set returned by <code>getOriginal()</code>
6278      * are said to have an original value.
6279      *
6280      * @return the original result set of the rowset
6281      * @throws SQLException if an error occurs produce the
6282      *           <code>ResultSet</code> object
6283      */
6284     public ResultSet getOriginal() throws SQLException {
6285         CachedRowSetImpl crs = new CachedRowSetImpl();
6286         crs.RowSetMD = RowSetMD;
6287         crs.numRows = numRows;
6288         crs.cursorPos = 0;
6289 
6290         // make sure we don't get someone playing with these
6291         // %%% is this now necessary ???
6292         //crs.setReader(null);
6293         //crs.setWriter(null);
6294         int colCount = RowSetMD.getColumnCount();
6295         Row orig;
6296 
6297         for (Iterator i = rvh.iterator(); i.hasNext();) {
6298             orig = new Row(colCount, ((Row)i.next()).getOrigRow());
6299             crs.rvh.add(orig);
6300         }
6301         return (ResultSet)crs;
6302     }
6303 
6304     /**
6305      * Returns a result set containing the original value of the current
6306      * row only.
6307      * The original value is the state of the <code>CachedRowSetImpl</code> after
6308      * the last population or synchronization (whichever occured most recently)
6309      * with the data source.
6310      *
6311      * @return the original result set of the row
6312      * @throws SQLException if there is no current row
6313      * @see #setOriginalRow
6314      */
6315     public ResultSet getOriginalRow() throws SQLException {
6316         CachedRowSetImpl crs = new CachedRowSetImpl();
6317         crs.RowSetMD = RowSetMD;
6318         crs.numRows = 1;
6319         crs.cursorPos = 0;
6320         crs.setTypeMap(this.getTypeMap());
6321 
6322         // make sure we don't get someone playing with these
6323         // %%% is this now necessary ???
6324         //crs.setReader(null);
6325         //crs.setWriter(null);
6326 
6327         Row orig = new Row(RowSetMD.getColumnCount(),
6328         getCurrentRow().getOrigRow());
6329 
6330         crs.rvh.add(orig);
6331 
6332         return (ResultSet)crs;
6333 
6334     }
6335 
6336     /**
6337      * Marks the current row in this rowset as being an original row.
6338      *
6339      * @throws SQLException if there is no current row
6340      * @see #getOriginalRow
6341      */
6342     public void setOriginalRow() throws SQLException {
6343         if (onInsertRow == true) {
6344             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
6345         }
6346 
6347         Row row = (Row)getCurrentRow();
6348         makeRowOriginal(row);
6349 
6350         // this can happen if deleted rows are being shown
6351         if (row.getDeleted() == true) {
6352             removeCurrentRow();
6353         }
6354     }
6355 
6356     /**
6357      * Makes the given row of this rowset the original row by clearing any
6358      * settings that mark the row as having been inserted, deleted, or updated.
6359      * This method is called internally by the methods
6360      * <code>setOriginalRow</code>
6361      * and <code>setOriginal</code>.
6362      *
6363      * @param row the row to be made the original row
6364      */
6365     private void makeRowOriginal(Row row) {
6366         if (row.getInserted() == true) {
6367             row.clearInserted();
6368         }
6369 
6370         if (row.getUpdated() == true) {
6371             row.moveCurrentToOrig();
6372         }
6373     }
6374 
6375     /**
6376      * Marks all rows in this rowset as being original rows. Any updates
6377      * made to the rows become the original values for the rowset.
6378      * Calls to the method <code>setOriginal</code> connot be reversed.
6379      *
6380      * @throws SQLException if an error occurs
6381      */
6382     public void setOriginal() throws SQLException {
6383         for (Iterator i = rvh.iterator(); i.hasNext();) {
6384             Row row = (Row)i.next();
6385             makeRowOriginal(row);
6386             // remove deleted rows from the collection.
6387             if (row.getDeleted() == true) {
6388                 i.remove();
6389                 --numRows;
6390             }
6391         }
6392         numDeleted = 0;
6393 
6394         // notify any listeners that the rowset has changed
6395         notifyRowSetChanged();
6396     }
6397 
6398     /**
6399      * Returns an identifier for the object (table) that was used to create this
6400      * rowset.
6401      *
6402      * @return a <code>String</code> object that identifies the table from
6403      *         which this <code>CachedRowSetImpl</code> object was derived
6404      * @throws SQLException if an error occurs
6405      */
6406     public String getTableName() throws SQLException {
6407         return tableName;
6408     }
6409 
6410     /**
6411      * Sets the identifier for the table from which this rowset was derived
6412      * to the given table name.
6413      *
6414      * @param tabName a <code>String</code> object that identifies the
6415      *          table from which this <code>CachedRowSetImpl</code> object
6416      *          was derived
6417      * @throws SQLException if an error occurs
6418      */
6419     public void setTableName(String tabName) throws SQLException {
6420         if (tabName == null)
6421             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.tablename").toString());
6422         else
6423             tableName = tabName;
6424     }
6425 
6426     /**
6427      * Returns the columns that make a key to uniquely identify a
6428      * row in this <code>CachedRowSetImpl</code> object.
6429      *
6430      * @return an array of column numbers that constitutes a primary
6431      *           key for this rowset. This array should be empty
6432      *           if no column is representitive of a primary key
6433      * @throws SQLException if the rowset is empty or no columns
6434      *           are designated as primary keys
6435      * @see #setKeyColumns
6436      */
6437     public int[] getKeyColumns() throws SQLException {
6438         return keyCols;
6439     }
6440 
6441 
6442     /**
6443      * Sets this <code>CachedRowSetImpl</code> object's
6444      * <code>keyCols</code> field with the given array of column
6445      * numbers, which forms a key for uniquely identifying a row
6446      * in this rowset.
6447      *
6448      * @param keys an array of <code>int</code> indicating the
6449      *        columns that form a primary key for this
6450      *        <code>CachedRowSetImpl</code> object; every
6451      *        element in the array must be greater than
6452      *        <code>0</code> and less than or equal to the number
6453      *        of columns in this rowset
6454      * @throws SQLException if any of the numbers in the
6455      *            given array is not valid for this rowset
6456      * @see #getKeyColumns
6457      */
6458     public void setKeyColumns(int [] keys) throws SQLException {
6459         int numCols = 0;
6460         if (RowSetMD != null) {
6461             numCols = RowSetMD.getColumnCount();
6462             if (keys.length > numCols)
6463                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.keycols").toString());
6464         }
6465         keyCols = new int[keys.length];
6466         for (int i = 0; i < keys.length; i++) {
6467             if (RowSetMD != null && (keys[i] <= 0 ||
6468             keys[i] > numCols)) {
6469                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcol").toString() +
6470                 keys[i]);
6471             }
6472             keyCols[i] = keys[i];
6473         }
6474     }
6475 
6476     /**
6477      * Sets the designated column in either the current row or the insert
6478      * row of this <code>CachedRowSetImpl</code> object with the given
6479      * <code>Ref</code> value.
6480      *
6481      * This method updates a column value in either the current row or
6482      * the insert row of this rowset, but it does not update the
6483      * database.  If the cursor is on a row in the rowset, the
6484      * method {@link #updateRow} must be called to update the database.
6485      * If the cursor is on the insert row, the method {@link #insertRow}
6486      * must be called, which will insert the new row into both this rowset
6487      * and the database. Both of these methods must be called before the
6488      * cursor moves to another row.
6489      *
6490      * @param columnIndex the first column is <code>1</code>, the second
6491      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6492      *        and equal to or less than the number of columns in this rowset
6493      * @param ref the new column <code>java.sql.Ref</code> value
6494      * @throws SQLException if (1) the given column index is out of bounds,
6495      *        (2) the cursor is not on one of this rowset's rows or its
6496      *        insert row, or (3) this rowset is
6497      *        <code>ResultSet.CONCUR_READ_ONLY</code>
6498      */
6499     public void updateRef(int columnIndex, java.sql.Ref ref) throws SQLException {
6500         // sanity check.
6501         checkIndex(columnIndex);
6502         // make sure the cursor is on a valid row
6503         checkCursor();
6504 
6505         // SerialClob will help in getting the byte array and storing it.
6506         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6507         // or through RowSetMetaData.locatorsUpdatorCopy()
6508         getCurrentRow().setColumnObject(columnIndex, new SerialRef(ref));
6509     }
6510 
6511     /**
6512      * Sets the designated column in either the current row or the insert
6513      * row of this <code>CachedRowSetImpl</code> object with the given
6514      * <code>double</code> value.
6515      *
6516      * This method updates a column value in either the current row or
6517      * the insert row of this rowset, but it does not update the
6518      * database.  If the cursor is on a row in the rowset, the
6519      * method {@link #updateRow} must be called to update the database.
6520      * If the cursor is on the insert row, the method {@link #insertRow}
6521      * must be called, which will insert the new row into both this rowset
6522      * and the database. Both of these methods must be called before the
6523      * cursor moves to another row.
6524      *
6525      * @param columnName a <code>String</code> object that must match the
6526      *        SQL name of a column in this rowset, ignoring case
6527      * @param ref the new column <code>java.sql.Ref</code> value
6528      * @throws SQLException if (1) the given column name does not match the
6529      *        name of a column in this rowset, (2) the cursor is not on
6530      *        one of this rowset's rows or its insert row, or (3) this
6531      *        rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6532      */
6533     public void updateRef(String columnName, java.sql.Ref ref) throws SQLException {
6534         updateRef(getColIdxByName(columnName), ref);
6535     }
6536 
6537     /**
6538      * Sets the designated column in either the current row or the insert
6539      * row of this <code>CachedRowSetImpl</code> object with the given
6540      * <code>double</code> value.
6541      *
6542      * This method updates a column value in either the current row or
6543      * the insert row of this rowset, but it does not update the
6544      * database.  If the cursor is on a row in the rowset, the
6545      * method {@link #updateRow} must be called to update the database.
6546      * If the cursor is on the insert row, the method {@link #insertRow}
6547      * must be called, which will insert the new row into both this rowset
6548      * and the database. Both of these methods must be called before the
6549      * cursor moves to another row.
6550      *
6551      * @param columnIndex the first column is <code>1</code>, the second
6552      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6553      *        and equal to or less than the number of columns in this rowset
6554      * @param c the new column <code>Clob</code> value
6555      * @throws SQLException if (1) the given column index is out of bounds,
6556      *        (2) the cursor is not on one of this rowset's rows or its
6557      *        insert row, or (3) this rowset is
6558      *        <code>ResultSet.CONCUR_READ_ONLY</code>
6559      */
6560     public void updateClob(int columnIndex, Clob c) throws SQLException {
6561         // sanity check.
6562         checkIndex(columnIndex);
6563         // make sure the cursor is on a valid row
6564         checkCursor();
6565 
6566         // SerialClob will help in getting the byte array and storing it.
6567         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6568         // or through RowSetMetaData.locatorsUpdatorCopy()
6569 
6570         if(dbmslocatorsUpdateCopy){
6571            getCurrentRow().setColumnObject(columnIndex, new SerialClob(c));
6572         }
6573         else{
6574            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.opnotsupp").toString());
6575         }
6576     }
6577 
6578     /**
6579      * Sets the designated column in either the current row or the insert
6580      * row of this <code>CachedRowSetImpl</code> object with the given
6581      * <code>double</code> value.
6582      *
6583      * This method updates a column value in either the current row or
6584      * the insert row of this rowset, but it does not update the
6585      * database.  If the cursor is on a row in the rowset, the
6586      * method {@link #updateRow} must be called to update the database.
6587      * If the cursor is on the insert row, the method {@link #insertRow}
6588      * must be called, which will insert the new row into both this rowset
6589      * and the database. Both of these methods must be called before the
6590      * cursor moves to another row.
6591      *
6592      * @param columnName a <code>String</code> object that must match the
6593      *        SQL name of a column in this rowset, ignoring case
6594      * @param c the new column <code>Clob</code> value
6595      * @throws SQLException if (1) the given column name does not match the
6596      *            name of a column in this rowset, (2) the cursor is not on
6597      *            one of this rowset's rows or its insert row, or (3) this
6598      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6599      */
6600     public void updateClob(String columnName, Clob c) throws SQLException {
6601         updateClob(getColIdxByName(columnName), c);
6602     }
6603 
6604     /**
6605      * Sets the designated column in either the current row or the insert
6606      * row of this <code>CachedRowSetImpl</code> object with the given
6607      * <code>java.sql.Blob</code> value.
6608      *
6609      * This method updates a column value in either the current row or
6610      * the insert row of this rowset, but it does not update the
6611      * database.  If the cursor is on a row in the rowset, the
6612      * method {@link #updateRow} must be called to update the database.
6613      * If the cursor is on the insert row, the method {@link #insertRow}
6614      * must be called, which will insert the new row into both this rowset
6615      * and the database. Both of these methods must be called before the
6616      * cursor moves to another row.
6617      *
6618      * @param columnIndex the first column is <code>1</code>, the second
6619      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6620      *        and equal to or less than the number of columns in this rowset
6621      * @param b the new column <code>Blob</code> value
6622      * @throws SQLException if (1) the given column index is out of bounds,
6623      *            (2) the cursor is not on one of this rowset's rows or its
6624      *            insert row, or (3) this rowset is
6625      *            <code>ResultSet.CONCUR_READ_ONLY</code>
6626      */
6627     public void updateBlob(int columnIndex, Blob b) throws SQLException {
6628         // sanity check.
6629         checkIndex(columnIndex);
6630         // make sure the cursor is on a valid row
6631         checkCursor();
6632 
6633         // SerialBlob will help in getting the byte array and storing it.
6634         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6635         // or through RowSetMetaData.locatorsUpdatorCopy()
6636 
6637         if(dbmslocatorsUpdateCopy){
6638            getCurrentRow().setColumnObject(columnIndex, new SerialBlob(b));
6639         }
6640         else{
6641            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.opnotsupp").toString());
6642         }
6643     }
6644 
6645     /**
6646      * Sets the designated column in either the current row or the insert
6647      * row of this <code>CachedRowSetImpl</code> object with the given
6648      * <code>java.sql.Blob </code> value.
6649      *
6650      * This method updates a column value in either the current row or
6651      * the insert row of this rowset, but it does not update the
6652      * database.  If the cursor is on a row in the rowset, the
6653      * method {@link #updateRow} must be called to update the database.
6654      * If the cursor is on the insert row, the method {@link #insertRow}
6655      * must be called, which will insert the new row into both this rowset
6656      * and the database. Both of these methods must be called before the
6657      * cursor moves to another row.
6658      *
6659      * @param columnName a <code>String</code> object that must match the
6660      *        SQL name of a column in this rowset, ignoring case
6661      * @param b the new column <code>Blob</code> value
6662      * @throws SQLException if (1) the given column name does not match the
6663      *            name of a column in this rowset, (2) the cursor is not on
6664      *            one of this rowset's rows or its insert row, or (3) this
6665      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6666      */
6667     public void updateBlob(String columnName, Blob b) throws SQLException {
6668         updateBlob(getColIdxByName(columnName), b);
6669     }
6670 
6671     /**
6672      * Sets the designated column in either the current row or the insert
6673      * row of this <code>CachedRowSetImpl</code> object with the given
6674      * <code>java.sql.Array</code> values.
6675      *
6676      * This method updates a column value in either the current row or
6677      * the insert row of this rowset, but it does not update the
6678      * database.  If the cursor is on a row in the rowset, the
6679      * method {@link #updateRow} must be called to update the database.
6680      * If the cursor is on the insert row, the method {@link #insertRow}
6681      * must be called, which will insert the new row into both this rowset
6682      * and the database. Both of these methods must be called before the
6683      * cursor moves to another row.
6684      *
6685      * @param columnIndex the first column is <code>1</code>, the second
6686      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6687      *        and equal to or less than the number of columns in this rowset
6688      * @param a the new column <code>Array</code> value
6689      * @throws SQLException if (1) the given column index is out of bounds,
6690      *            (2) the cursor is not on one of this rowset's rows or its
6691      *            insert row, or (3) this rowset is
6692      *            <code>ResultSet.CONCUR_READ_ONLY</code>
6693      */
6694     public void updateArray(int columnIndex, Array a) throws SQLException {
6695         // sanity check.
6696         checkIndex(columnIndex);
6697         // make sure the cursor is on a valid row
6698         checkCursor();
6699 
6700         // SerialArray will help in getting the byte array and storing it.
6701         // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6702         // or through RowSetMetaData.locatorsUpdatorCopy()
6703         getCurrentRow().setColumnObject(columnIndex, new SerialArray(a));
6704     }
6705 
6706     /**
6707      * Sets the designated column in either the current row or the insert
6708      * row of this <code>CachedRowSetImpl</code> object with the given
6709      * <code>java.sql.Array</code> value.
6710      *
6711      * This method updates a column value in either the current row or
6712      * the insert row of this rowset, but it does not update the
6713      * database.  If the cursor is on a row in the rowset, the
6714      * method {@link #updateRow} must be called to update the database.
6715      * If the cursor is on the insert row, the method {@link #insertRow}
6716      * must be called, which will insert the new row into both this rowset
6717      * and the database. Both of these methods must be called before the
6718      * cursor moves to another row.
6719      *
6720      * @param columnName a <code>String</code> object that must match the
6721      *        SQL name of a column in this rowset, ignoring case
6722      * @param a the new column <code>Array</code> value
6723      * @throws SQLException if (1) the given column name does not match the
6724      *            name of a column in this rowset, (2) the cursor is not on
6725      *            one of this rowset's rows or its insert row, or (3) this
6726      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6727      */
6728     public void updateArray(String columnName, Array a) throws SQLException {
6729         updateArray(getColIdxByName(columnName), a);
6730     }
6731 
6732 
6733     /**
6734      * Retrieves the value of the designated column in this
6735      * <code>CachedRowSetImpl</code> object as a <code>java.net.URL</code> object
6736      * in the Java programming language.
6737      *
6738      * @return a java.net.URL object containing the resource reference described by
6739      * the URL
6740      * @throws SQLException if (1) the given column index is out of bounds,
6741      * (2) the cursor is not on one of this rowset's rows or its
6742      * insert row, or (3) the designated column does not store an
6743      * SQL <code>DATALINK</code> value.
6744      * @see #getURL(String)
6745      */
6746     public java.net.URL getURL(int columnIndex) throws SQLException {
6747         //throw new SQLException("Operation not supported");
6748 
6749         java.net.URL value;
6750 
6751         // sanity check.
6752         checkIndex(columnIndex);
6753         // make sure the cursor is on a valid row
6754         checkCursor();
6755 
6756         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.DATALINK) {
6757             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
6758         }
6759 
6760         setLastValueNull(false);
6761         value = (java.net.URL)(getCurrentRow().getColumnObject(columnIndex));
6762 
6763         // check for SQL NULL
6764         if (value == null) {
6765             setLastValueNull(true);
6766             return null;
6767         }
6768 
6769         return value;
6770     }
6771 
6772     /**
6773      * Retrieves the value of the designated column in this
6774      * <code>CachedRowSetImpl</code> object as a <code>java.net.URL</code> object
6775      * in the Java programming language.
6776      *
6777      * @return a java.net.URL object containing the resource reference described by
6778      * the URL
6779      * @throws SQLException if (1) the given column name not the name of a column
6780      * in this rowset, or
6781      * (2) the cursor is not on one of this rowset's rows or its
6782      * insert row, or (3) the designated column does not store an
6783      * SQL <code>DATALINK</code> value.
6784      * @see #getURL(int)
6785      */
6786     public java.net.URL getURL(String columnName) throws SQLException {
6787         return getURL(getColIdxByName(columnName));
6788 
6789     }
6790 
6791     /**
6792      * The first warning reported by calls on this <code>CachedRowSetImpl</code>
6793      * object is returned. Subsequent <code>CachedRowSetImpl</code> warnings will
6794      * be chained to this <code>SQLWarning</code>. All <code>RowSetWarnings</code>
6795      * warnings are generated in the disconnected environment and remain a
6796      * seperate warning chain to that provided by the <code>getWarnings</code>
6797      * method.
6798      *
6799      * <P>The warning chain is automatically cleared each time a new
6800      * row is read.
6801      *
6802      * <P><B>Note:</B> This warning chain only covers warnings caused
6803      * by <code>CachedRowSet</code> (and their child interface)
6804      * methods. All <code>SQLWarnings</code> can be obtained using the
6805      * <code>getWarnings</code> method which tracks warnings generated
6806      * by the underlying JDBC driver.
6807      * @return the first SQLWarning or null
6808      *
6809      */
6810     public RowSetWarning getRowSetWarnings() {
6811         try {
6812             notifyCursorMoved();
6813         } catch (SQLException e) {} // mask exception
6814         return rowsetWarning;
6815     }
6816 
6817 
6818     /**
6819      * The function tries to isolate the tablename when only setCommand
6820      * is set and not setTablename is called provided there is only one table
6821      * name in the query else just leaves the setting of table name as such.
6822      * If setTablename is set later it will over ride this table name
6823      * value so retrieved.
6824      *
6825      * @return the tablename if only one table in query else return ""
6826      */
6827     private String buildTableName(String command) throws SQLException {
6828 
6829         // If we have a query from one table,
6830         // we set the table name implicitly
6831         // else user has to explicitly set the table name.
6832 
6833         int indexFrom, indexComma;
6834         String strTablename ="";
6835         command = command.trim();
6836 
6837         // Query can be a select, insert or  update
6838 
6839         if(command.toLowerCase().startsWith("select")) {
6840             // look for "from" keyword, after that look for a
6841             // comma after from. If comma is there don't set
6842             // table name else isolate table name.
6843 
6844             indexFrom = command.toLowerCase().indexOf("from");
6845             indexComma = command.indexOf(",", indexFrom);
6846 
6847             if(indexComma == -1) {
6848                 // implies only one table
6849                 strTablename = (command.substring(indexFrom+"from".length(),command.length())).trim();
6850 
6851                 String tabName = strTablename;
6852 
6853                 int idxWhere = tabName.toLowerCase().indexOf("where");
6854 
6855                 /**
6856                   * Adding the addtional check for conditions following the table name.
6857                   * If a condition is found truncate it.
6858                   **/
6859 
6860                 if(idxWhere != -1)
6861                 {
6862                    tabName = tabName.substring(0,idxWhere).trim();
6863                 }
6864 
6865                 strTablename = tabName;
6866 
6867             } else {
6868                 //strTablename="";
6869             }
6870 
6871         } else if(command.toLowerCase().startsWith("insert")) {
6872             //strTablename="";
6873         } else if(command.toLowerCase().startsWith("update")) {
6874             //strTablename="";
6875         }
6876         return strTablename;
6877     }
6878 
6879     /**
6880      * Commits all changes performed by the <code>acceptChanges()</code>
6881      * methods
6882      *
6883      * @see java.sql.Connection#commit
6884      */
6885     public void commit() throws SQLException {
6886         conn.commit();
6887     }
6888 
6889     /**
6890      * Rolls back all changes performed by the <code>acceptChanges()</code>
6891      * methods
6892      *
6893      * @see java.sql.Connection#rollback
6894      */
6895     public void rollback() throws SQLException {
6896         conn.rollback();
6897     }
6898 
6899     /**
6900      * Rolls back all changes performed by the <code>acceptChanges()</code>
6901      * to the last <code>Savepoint</code> transaction marker.
6902      *
6903      * @see java.sql.Connection#rollback(Savepoint)
6904      */
6905     public void rollback(Savepoint s) throws SQLException {
6906         conn.rollback(s);
6907     }
6908 
6909     /**
6910      * Unsets the designated parameter to the given int array.
6911      * This was set using <code>setMatchColumn</code>
6912      * as the column which will form the basis of the join.
6913      * <P>
6914      * The parameter value unset by this method should be same
6915      * as was set.
6916      *
6917      * @param columnIdxes the index into this rowset
6918      *        object's internal representation of parameter values
6919      * @throws SQLException if an error occurs or the
6920      *  parameter index is out of bounds or if the columnIdx is
6921      *  not the same as set using <code>setMatchColumn(int [])</code>
6922      */
6923     public void unsetMatchColumn(int[] columnIdxes) throws SQLException {
6924 
6925          int i_val;
6926          for( int j= 0 ;j < columnIdxes.length; j++) {
6927             i_val = (Integer.parseInt(iMatchColumns.get(j).toString()));
6928             if(columnIdxes[j] != i_val) {
6929                throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols").toString());
6930             }
6931          }
6932 
6933          for( int i = 0;i < columnIdxes.length ;i++) {
6934             iMatchColumns.set(i,Integer.valueOf(-1));
6935          }
6936     }
6937 
6938    /**
6939      * Unsets the designated parameter to the given String array.
6940      * This was set using <code>setMatchColumn</code>
6941      * as the column which will form the basis of the join.
6942      * <P>
6943      * The parameter value unset by this method should be same
6944      * as was set.
6945      *
6946      * @param columnIdxes the index into this rowset
6947      *        object's internal representation of parameter values
6948      * @throws SQLException if an error occurs or the
6949      *  parameter index is out of bounds or if the columnName is
6950      *  not the same as set using <code>setMatchColumn(String [])</code>
6951      */
6952     public void unsetMatchColumn(String[] columnIdxes) throws SQLException {
6953 
6954         for(int j = 0 ;j < columnIdxes.length; j++) {
6955            if( !columnIdxes[j].equals(strMatchColumns.get(j)) ){
6956               throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols").toString());
6957            }
6958         }
6959 
6960         for(int i = 0 ; i < columnIdxes.length; i++) {
6961            strMatchColumns.set(i,null);
6962         }
6963     }
6964 
6965     /**
6966      * Retrieves the column name as <code>String</code> array
6967      * that was set using <code>setMatchColumn(String [])</code>
6968      * for this rowset.
6969      *
6970      * @return a <code>String</code> array object that contains the column names
6971      *         for the rowset which has this the match columns
6972      *
6973      * @throws SQLException if an error occurs or column name is not set
6974      */
6975     public String[] getMatchColumnNames() throws SQLException {
6976 
6977         String []str_temp = new String[strMatchColumns.size()];
6978 
6979         if( strMatchColumns.get(0) == null) {
6980            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.setmatchcols").toString());
6981         }
6982 
6983         strMatchColumns.copyInto(str_temp);
6984         return str_temp;
6985     }
6986 
6987     /**
6988      * Retrieves the column id as <code>int</code> array that was set using
6989      * <code>setMatchColumn(int [])</code> for this rowset.
6990      *
6991      * @return a <code>int</code> array object that contains the column ids
6992      *         for the rowset which has this as the match columns.
6993      *
6994      * @throws SQLException if an error occurs or column index is not set
6995      */
6996     public int[] getMatchColumnIndexes() throws SQLException {
6997 
6998         Integer []int_temp = new Integer[iMatchColumns.size()];
6999         int [] i_temp = new int[iMatchColumns.size()];
7000         int i_val;
7001 
7002         i_val = ((Integer)iMatchColumns.get(0)).intValue();
7003 
7004         if( i_val == -1 ) {
7005            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.setmatchcols").toString());
7006         }
7007 
7008 
7009         iMatchColumns.copyInto(int_temp);
7010 
7011         for(int i = 0; i < int_temp.length; i++) {
7012            i_temp[i] = (int_temp[i]).intValue();
7013         }
7014 
7015         return i_temp;
7016     }
7017 
7018     /**
7019      * Sets the designated parameter to the given int array.
7020      * This forms the basis of the join for the
7021      * <code>JoinRowSet</code> as the column which will form the basis of the
7022      * join.
7023      * <P>
7024      * The parameter value set by this method is stored internally and
7025      * will be supplied as the appropriate parameter in this rowset's
7026      * command when the method <code>getMatchColumnIndexes</code> is called.
7027      *
7028      * @param columnIdxes the indexes into this rowset
7029      *        object's internal representation of parameter values; the
7030      *        first parameter is 0, the second is 1, and so on; must be
7031      *        <code>0</code> or greater
7032      * @throws SQLException if an error occurs or the
7033      *                         parameter index is out of bounds
7034      */
7035     public void setMatchColumn(int[] columnIdxes) throws SQLException {
7036 
7037         for(int j = 0 ; j < columnIdxes.length; j++) {
7038            if( columnIdxes[j] < 0 ) {
7039               throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols1").toString());
7040            }
7041         }
7042         for(int i = 0 ;i < columnIdxes.length; i++) {
7043            iMatchColumns.add(i,Integer.valueOf(columnIdxes[i]));
7044         }
7045     }
7046 
7047     /**
7048      * Sets the designated parameter to the given String array.
7049      *  This forms the basis of the join for the
7050      * <code>JoinRowSet</code> as the column which will form the basis of the
7051      * join.
7052      * <P>
7053      * The parameter value set by this method is stored internally and
7054      * will be supplied as the appropriate parameter in this rowset's
7055      * command when the method <code>getMatchColumn</code> is called.
7056      *
7057      * @param columnNames the name of the column into this rowset
7058      *        object's internal representation of parameter values
7059      * @throws SQLException if an error occurs or the
7060      *  parameter index is out of bounds
7061      */
7062     public void setMatchColumn(String[] columnNames) throws SQLException {
7063 
7064         for(int j = 0; j < columnNames.length; j++) {
7065            if( columnNames[j] == null || columnNames[j].equals("")) {
7066               throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols2").toString());
7067            }
7068         }
7069         for( int i = 0; i < columnNames.length; i++) {
7070            strMatchColumns.add(i,columnNames[i]);
7071         }
7072     }
7073 
7074 
7075     /**
7076      * Sets the designated parameter to the given <code>int</code>
7077      * object.  This forms the basis of the join for the
7078      * <code>JoinRowSet</code> as the column which will form the basis of the
7079      * join.
7080      * <P>
7081      * The parameter value set by this method is stored internally and
7082      * will be supplied as the appropriate parameter in this rowset's
7083      * command when the method <code>getMatchColumn</code> is called.
7084      *
7085      * @param columnIdx the index into this rowset
7086      *        object's internal representation of parameter values; the
7087      *        first parameter is 0, the second is 1, and so on; must be
7088      *        <code>0</code> or greater
7089      * @throws SQLException if an error occurs or the
7090      *                         parameter index is out of bounds
7091      */
7092     public void setMatchColumn(int columnIdx) throws SQLException {
7093         // validate, if col is ok to be set
7094         if(columnIdx < 0) {
7095             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols1").toString());
7096         } else {
7097             // set iMatchColumn
7098             iMatchColumns.set(0, Integer.valueOf(columnIdx));
7099             //strMatchColumn = null;
7100         }
7101     }
7102 
7103     /**
7104      * Sets the designated parameter to the given <code>String</code>
7105      * object.  This forms the basis of the join for the
7106      * <code>JoinRowSet</code> as the column which will form the basis of the
7107      * join.
7108      * <P>
7109      * The parameter value set by this method is stored internally and
7110      * will be supplied as the appropriate parameter in this rowset's
7111      * command when the method <code>getMatchColumn</code> is called.
7112      *
7113      * @param columnName the name of the column into this rowset
7114      *        object's internal representation of parameter values
7115      * @throws SQLException if an error occurs or the
7116      *  parameter index is out of bounds
7117      */
7118     public void setMatchColumn(String columnName) throws SQLException {
7119         // validate, if col is ok to be set
7120         if(columnName == null || (columnName= columnName.trim()).equals("") ) {
7121             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols2").toString());
7122         } else {
7123             // set strMatchColumn
7124             strMatchColumns.set(0, columnName);
7125             //iMatchColumn = -1;
7126         }
7127     }
7128 
7129     /**
7130      * Unsets the designated parameter to the given <code>int</code>
7131      * object.  This was set using <code>setMatchColumn</code>
7132      * as the column which will form the basis of the join.
7133      * <P>
7134      * The parameter value unset by this method should be same
7135      * as was set.
7136      *
7137      * @param columnIdx the index into this rowset
7138      *        object's internal representation of parameter values
7139      * @throws SQLException if an error occurs or the
7140      *  parameter index is out of bounds or if the columnIdx is
7141      *  not the same as set using <code>setMatchColumn(int)</code>
7142      */
7143     public void unsetMatchColumn(int columnIdx) throws SQLException {
7144         // check if we are unsetting the SAME column
7145         if(! iMatchColumns.get(0).equals(Integer.valueOf(columnIdx) )  ) {
7146             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch").toString());
7147         } else if(strMatchColumns.get(0) != null) {
7148             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch1").toString());
7149         } else {
7150                 // that is, we are unsetting it.
7151                iMatchColumns.set(0, Integer.valueOf(-1));
7152         }
7153     }
7154 
7155     /**
7156      * Unsets the designated parameter to the given <code>String</code>
7157      * object.  This was set using <code>setMatchColumn</code>
7158      * as the column which will form the basis of the join.
7159      * <P>
7160      * The parameter value unset by this method should be same
7161      * as was set.
7162      *
7163      * @param columnName the index into this rowset
7164      *        object's internal representation of parameter values
7165      * @throws SQLException if an error occurs or the
7166      *  parameter index is out of bounds or if the columnName is
7167      *  not the same as set using <code>setMatchColumn(String)</code>
7168      */
7169     public void unsetMatchColumn(String columnName) throws SQLException {
7170         // check if we are unsetting the same column
7171         columnName = columnName.trim();
7172 
7173         if(!((strMatchColumns.get(0)).equals(columnName))) {
7174             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch").toString());
7175         } else if( ((Integer)(iMatchColumns.get(0))).intValue() > 0) {
7176             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch2").toString());
7177         } else {
7178             strMatchColumns.set(0, null);   // that is, we are unsetting it.
7179         }
7180     }
7181 
7182     /**
7183      * Notifies registered listeners that a RowSet object in the given RowSetEvent
7184      * object has populated a number of additional rows. The <code>numRows</code> parameter
7185      * ensures that this event will only be fired every <code>numRow</code>.
7186      * <p>
7187      * The source of the event can be retrieved with the method event.getSource.
7188      *
7189      * @param event a <code>RowSetEvent</code> object that contains the
7190      *     <code>RowSet</code> object that is the source of the events
7191      * @param numRows when populating, the number of rows interval on which the
7192      *     <code>CachedRowSet</code> populated should fire; the default value
7193      *     is zero; cannot be less than <code>fetchSize</code> or zero
7194      */
7195     public void rowSetPopulated(RowSetEvent event, int numRows) throws SQLException {
7196 
7197         if( numRows < 0 || numRows < getFetchSize()) {
7198            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.numrows").toString());
7199         }
7200 
7201         if(size() % numRows == 0) {
7202             RowSetEvent event_temp = new RowSetEvent(this);
7203             event = event_temp;
7204             notifyRowSetChanged();
7205         }
7206     }
7207 
7208     /**
7209      * Populates this <code>CachedRowSet</code> object with data from
7210      * the given <code>ResultSet</code> object. While related to the <code>populate(ResultSet)</code>
7211      * method, an additional parameter is provided to allow starting position within
7212      * the <code>ResultSet</code> from where to populate the CachedRowSet
7213      * instance.
7214      *
7215      * This method is an alternative to the method <code>execute</code>
7216      * for filling the rowset with data.  The method <code>populate</code>
7217      * does not require that the properties needed by the method
7218      * <code>execute</code>, such as the <code>command</code> property,
7219      * be set. This is true because the method <code>populate</code>
7220      * is given the <code>ResultSet</code> object from
7221      * which to get data and thus does not need to use the properties
7222      * required for setting up a connection and executing this
7223      * <code>CachedRowSetImpl</code> object's command.
7224      * <P>
7225      * After populating this rowset with data, the method
7226      * <code>populate</code> sets the rowset's metadata and
7227      * then sends a <code>RowSetChangedEvent</code> object
7228      * to all registered listeners prior to returning.
7229      *
7230      * @param data the <code>ResultSet</code> object containing the data
7231      *             to be read into this <code>CachedRowSetImpl</code> object
7232      * @param start the integer specifing the position in the
7233      *        <code>ResultSet</code> object to popultate the
7234      *        <code>CachedRowSetImpl</code> object.
7235      * @throws SQLException if an error occurs; or the max row setting is
7236      *          violated while populating the RowSet.Also id the start position
7237      *          is negative.
7238      * @see #execute
7239      */
7240      public void populate(ResultSet data, int start) throws SQLException{
7241 
7242         int rowsFetched;
7243         Row currentRow;
7244         int numCols;
7245         int i;
7246         Map<String, Class<?>> map = getTypeMap();
7247         Object obj;
7248         int mRows;
7249 
7250         cursorPos = 0;
7251         if(populatecallcount == 0){
7252             if(start < 0){
7253                throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.startpos").toString());
7254             }
7255             if(getMaxRows() == 0){
7256                data.absolute(start);
7257                while(data.next()){
7258                    totalRows++;
7259                }
7260                totalRows++;
7261             }
7262             startPos = start;
7263         }
7264         populatecallcount = populatecallcount +1;
7265         resultSet = data;
7266         if((endPos - startPos) >= getMaxRows() && (getMaxRows() > 0)){
7267             endPos = prevEndPos;
7268             pagenotend = false;
7269             return;
7270         }
7271 
7272         if((maxRowsreached != getMaxRows() || maxRowsreached != totalRows) && pagenotend) {
7273            startPrev = start - getPageSize();
7274         }
7275 
7276         if( pageSize == 0){
7277            prevEndPos = endPos;
7278            endPos = start + getMaxRows() ;
7279         }
7280         else{
7281             prevEndPos = endPos;
7282             endPos = start + getPageSize();
7283         }
7284 
7285 
7286         if (start == 1){
7287             resultSet.beforeFirst();
7288         }
7289         else {
7290             resultSet.absolute(start -1);
7291         }
7292         if( pageSize == 0) {
7293            rvh = new Vector<Object>(getMaxRows());
7294 
7295         }
7296         else{
7297             rvh = new Vector<Object>(getPageSize());
7298         }
7299 
7300         if (data == null) {
7301             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.populate").toString());
7302         }
7303 
7304         // get the meta data for this ResultSet
7305         RSMD = data.getMetaData();
7306 
7307         // set up the metadata
7308         RowSetMD = new RowSetMetaDataImpl();
7309         initMetaData(RowSetMD, RSMD);
7310 
7311         // release the meta-data so that aren't tempted to use it.
7312         RSMD = null;
7313         numCols = RowSetMD.getColumnCount();
7314         mRows = this.getMaxRows();
7315         rowsFetched = 0;
7316         currentRow = null;
7317 
7318         if(!data.next() && mRows == 0){
7319             endPos = prevEndPos;
7320             pagenotend = false;
7321             return;
7322         }
7323 
7324         data.previous();
7325 
7326         while ( data.next()) {
7327 
7328             currentRow = new Row(numCols);
7329           if(pageSize == 0){
7330             if ( rowsFetched >= mRows && mRows > 0) {
7331                 rowsetWarning.setNextException(new SQLException("Populating rows "
7332                 + "setting has exceeded max row setting"));
7333                 break;
7334             }
7335           }
7336           else {
7337               if ( (rowsFetched >= pageSize) ||( maxRowsreached >= mRows && mRows > 0)) {
7338                 rowsetWarning.setNextException(new SQLException("Populating rows "
7339                 + "setting has exceeded max row setting"));
7340                 break;
7341             }
7342           }
7343 
7344             for ( i = 1; i <= numCols; i++) {
7345                 /*
7346                  * check if the user has set a map. If no map
7347                  * is set then use plain getObject. This lets
7348                  * us work with drivers that do not support
7349                  * getObject with a map in fairly sensible way
7350                  */
7351                 if (map == null) {
7352                     obj = data.getObject(i);
7353                 } else {
7354                     obj = data.getObject(i, map);
7355                 }
7356                 /*
7357                  * the following block checks for the various
7358                  * types that we have to serialize in order to
7359                  * store - right now only structs have been tested
7360                  */
7361                 if (obj instanceof Struct) {
7362                     obj = new SerialStruct((Struct)obj, map);
7363                 } else if (obj instanceof SQLData) {
7364                     obj = new SerialStruct((SQLData)obj, map);
7365                 } else if (obj instanceof Blob) {
7366                     obj = new SerialBlob((Blob)obj);
7367                 } else if (obj instanceof Clob) {
7368                     obj = new SerialClob((Clob)obj);
7369                 } else if (obj instanceof java.sql.Array) {
7370                     obj = new SerialArray((java.sql.Array)obj, map);
7371                 }
7372 
7373                 ((Row)currentRow).initColumnObject(i, obj);
7374             }
7375             rowsFetched++;
7376             maxRowsreached++;
7377             rvh.add(currentRow);
7378         }
7379         numRows = rowsFetched ;
7380         // Also rowsFetched should be equal to rvh.size()
7381         // notify any listeners that the rowset has changed
7382         notifyRowSetChanged();
7383 
7384      }
7385 
7386     /**
7387      * The nextPage gets the next page, that is a <code>CachedRowSetImpl</code> object
7388      * containing the number of rows specified by page size.
7389      * @return boolean value true indicating whether there are more pages to come and
7390      *         false indicating that this is the last page.
7391      * @throws SQLException if an error occurs or this called before calling populate.
7392      */
7393      public boolean nextPage() throws SQLException {
7394 
7395          if (populatecallcount == 0){
7396              throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.nextpage").toString());
7397          }
7398          // Fix for 6554186
7399          onFirstPage = false;
7400          if(callWithCon){
7401             crsReader.setStartPosition(endPos);
7402             crsReader.readData((RowSetInternal)this);
7403             resultSet = null;
7404          }
7405          else {
7406             populate(resultSet,endPos);
7407          }
7408          return pagenotend;
7409      }
7410 
7411     /**
7412      * This is the setter function for setting the size of the page, which specifies
7413      * how many rows have to be retrived at a time.
7414      *
7415      * @param size which is the page size
7416      * @throws SQLException if size is less than zero or greater than max rows.
7417      */
7418      public void setPageSize (int size) throws SQLException {
7419         if (size < 0) {
7420             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.pagesize").toString());
7421         }
7422         if (size > getMaxRows() && getMaxRows() != 0) {
7423             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.pagesize1").toString());
7424         }
7425         pageSize = size;
7426      }
7427 
7428     /**
7429      * This is the getter function for the size of the page.
7430      *
7431      * @return an integer that is the page size.
7432      */
7433     public int getPageSize() {
7434         return pageSize;
7435     }
7436 
7437 
7438     /**
7439      * Retrieves the data present in the page prior to the page from where it is
7440      * called.
7441      * @return boolean value true if it retrieves the previous page, flase if it
7442      *         is on the first page.
7443      * @throws SQLException if it is called before populate is called or ResultSet
7444      *         is of type <code>ResultSet.TYPE_FORWARD_ONLY</code> or if an error
7445      *         occurs.
7446      */
7447     public boolean previousPage() throws SQLException {
7448         int pS;
7449         int mR;
7450         int rem;
7451 
7452         pS = getPageSize();
7453         mR = maxRowsreached;
7454 
7455         if (populatecallcount == 0){
7456              throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.nextpage").toString());
7457          }
7458 
7459         if( !callWithCon){
7460            if(resultSet.getType() == ResultSet.TYPE_FORWARD_ONLY){
7461                throw new SQLException (resBundle.handleGetObject("cachedrowsetimpl.fwdonly").toString());
7462            }
7463         }
7464 
7465         pagenotend = true;
7466 
7467         if(startPrev < startPos ){
7468                 onFirstPage = true;
7469                return false;
7470             }
7471 
7472         if(onFirstPage){
7473             return false;
7474         }
7475 
7476         rem = mR % pS;
7477 
7478         if(rem == 0){
7479             maxRowsreached -= (2 * pS);
7480             if(callWithCon){
7481                 crsReader.setStartPosition(startPrev);
7482                 crsReader.readData((RowSetInternal)this);
7483                 resultSet = null;
7484             }
7485             else {
7486                populate(resultSet,startPrev);
7487             }
7488             return true;
7489         }
7490         else
7491         {
7492             maxRowsreached -= (pS + rem);
7493             if(callWithCon){
7494                 crsReader.setStartPosition(startPrev);
7495                 crsReader.readData((RowSetInternal)this);
7496                 resultSet = null;
7497             }
7498             else {
7499                populate(resultSet,startPrev);
7500             }
7501             return true;
7502         }
7503     }
7504 
7505     /**
7506      * Goes to the page number passed as the parameter
7507      * @param page , the page loaded on a call to this function
7508      * @return true if the page exists false otherwise
7509      * @throws SQLException if an error occurs
7510      */
7511     /*
7512     public boolean absolutePage(int page) throws SQLException{
7513 
7514         boolean isAbs = true, retVal = true;
7515         int counter;
7516 
7517         if( page <= 0 ){
7518             throw new SQLException("Absolute positoin is invalid");
7519         }
7520         counter = 0;
7521 
7522         firstPage();
7523         counter++;
7524         while((counter < page) && isAbs) {
7525             isAbs = nextPage();
7526             counter ++;
7527         }
7528 
7529         if( !isAbs && counter < page){
7530             retVal = false;
7531         }
7532         else if(counter == page){
7533             retVal = true;
7534         }
7535 
7536        return retVal;
7537     }
7538     */
7539 
7540 
7541     /**
7542      * Goes to the page number passed as the parameter  from the current page.
7543      * The parameter can take postive or negative value accordingly.
7544      * @param page , the page loaded on a call to this function
7545      * @return true if the page exists false otherwise
7546      * @throws SQLException if an error occurs
7547      */
7548     /*
7549     public boolean relativePage(int page) throws SQLException {
7550 
7551         boolean isRel = true,retVal = true;
7552         int counter;
7553 
7554         if(page > 0){
7555            counter  = 0;
7556            while((counter < page) && isRel){
7557               isRel = nextPage();
7558               counter++;
7559            }
7560 
7561            if(!isRel && counter < page){
7562                retVal = false;
7563            }
7564            else if( counter == page){
7565                retVal = true;
7566            }
7567            return retVal;
7568         }
7569         else {
7570             counter = page;
7571             isRel = true;
7572             while((counter < 0) && isRel){
7573                 isRel = previousPage();
7574                 counter++;
7575             }
7576 
7577             if( !isRel && counter < 0){
7578                 retVal = false;
7579             }
7580             else if(counter == 0){
7581                 retVal = true;
7582             }
7583             return retVal;
7584         }
7585     }
7586     */
7587 
7588      /**
7589      * Retrieves the first page of data as specified by the page size.
7590      * @return boolean value true if present on first page, false otherwise
7591      * @throws SQLException if it called before populate or ResultSet is of
7592      *         type <code>ResultSet.TYPE_FORWARD_ONLY</code> or an error occurs
7593      */
7594     /*
7595     public boolean firstPage() throws SQLException {
7596            if (populatecallcount == 0){
7597              throw new SQLException("Populate the data before calling ");
7598            }
7599            if( !callWithCon){
7600               if(resultSet.getType() == ResultSet.TYPE_FORWARD_ONLY) {
7601                   throw new SQLException("Result of type forward only");
7602               }
7603            }
7604            endPos = 0;
7605            maxRowsreached = 0;
7606            pagenotend = true;
7607            if(callWithCon){
7608                crsReader.setStartPosition(startPos);
7609                crsReader.readData((RowSetInternal)this);
7610                resultSet = null;
7611            }
7612            else {
7613               populate(resultSet,startPos);
7614            }
7615            onFirstPage = true;
7616            return onFirstPage;
7617     }
7618     */
7619 
7620     /**
7621      * Retrives the last page of data as specified by the page size.
7622      * @return boolean value tur if present on the last page, false otherwise
7623      * @throws SQLException if called before populate or if an error occurs.
7624      */
7625      /*
7626     public boolean lastPage() throws SQLException{
7627           int pS;
7628           int mR;
7629           int quo;
7630           int rem;
7631 
7632           pS = getPageSize();
7633           mR = getMaxRows();
7634 
7635           if(pS == 0){
7636               onLastPage = true;
7637               return onLastPage;
7638           }
7639 
7640           if(getMaxRows() == 0){
7641               mR = totalRows;
7642           }
7643 
7644           if (populatecallcount == 0){
7645              throw new SQLException("Populate the data before calling ");
7646          }
7647 
7648          onFirstPage = false;
7649 
7650          if((mR % pS) == 0){
7651              quo = mR / pS;
7652              int start = startPos + (pS * (quo - 1));
7653              maxRowsreached = mR - pS;
7654              if(callWithCon){
7655                  crsReader.setStartPosition(start);
7656                  crsReader.readData((RowSetInternal)this);
7657                  resultSet = null;
7658              }
7659              else {
7660                 populate(resultSet,start);
7661              }
7662              onLastPage = true;
7663              return onLastPage;
7664          }
7665         else {
7666               quo = mR /pS;
7667               rem = mR % pS;
7668               int start = startPos + (pS * quo);
7669              maxRowsreached = mR - (rem);
7670              if(callWithCon){
7671                  crsReader.setStartPosition(start);
7672                  crsReader.readData((RowSetInternal)this);
7673                  resultSet = null;
7674              }
7675              else {
7676                 populate(resultSet,start);
7677              }
7678              onLastPage = true;
7679              return onLastPage;
7680          }
7681     }
7682     */
7683 
7684    /**
7685      * Sets the status for the row on which the cursor is positioned. The insertFlag is used
7686      * to mention the toggle status for this row
7687      * @param insertFlag if it is true  - marks this row as inserted
7688      *                   if it is false - marks it as not a newly inserted row
7689      * @throws SQLException if an error occurs while doing this operation
7690      */
7691     public void setRowInserted(boolean insertFlag) throws SQLException {
7692 
7693         checkCursor();
7694 
7695         if(onInsertRow == true)
7696           throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
7697 
7698         if( insertFlag ) {
7699           ((Row)getCurrentRow()).setInserted();
7700         } else {
7701           ((Row)getCurrentRow()).clearInserted();
7702         }
7703     }
7704 
7705     /**
7706      * Retrieves the value of the designated <code>SQL XML</code> parameter as a
7707      * <code>SQLXML</code> object in the Java programming language.
7708      * @param columnIndex the first column is 1, the second is 2, ...
7709      * @return a SQLXML object that maps an SQL XML value
7710      * @throws SQLException if a database access error occurs
7711      * @since 6.0
7712      */
7713     public SQLXML getSQLXML(int columnIndex) throws SQLException {
7714         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7715     }
7716 
7717     /**
7718      * Retrieves the value of the designated <code>SQL XML</code> parameter as a
7719      * <code>SQLXML</code> object in the Java programming language.
7720      * @param colName the name of the column from which to retrieve the value
7721      * @return a SQLXML object that maps an SQL XML value
7722      * @throws SQLException if a database access error occurs
7723      */
7724     public SQLXML getSQLXML(String colName) throws SQLException {
7725         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7726     }
7727 
7728     /**
7729      * Retrieves the value of the designated column in the current row of this
7730      * <code>ResultSet</code> object as a java.sql.RowId object in the Java
7731      * programming language.
7732      *
7733      * @param columnIndex the first column is 1, the second 2, ...
7734      * @return the column value if the value is a SQL <code>NULL</code> the
7735      *     value returned is <code>null</code>
7736      * @throws SQLException if a database access error occurs
7737      * @since 6.0
7738      */
7739     public RowId getRowId(int columnIndex) throws SQLException {
7740         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7741     }
7742 
7743     /**
7744      * Retrieves the value of the designated column in the current row of this
7745      * <code>ResultSet</code> object as a java.sql.RowId object in the Java
7746      * programming language.
7747      *
7748      * @param columnName the name of the column
7749      * @return the column value if the value is a SQL <code>NULL</code> the
7750      *     value returned is <code>null</code>
7751      * @throws SQLException if a database access error occurs
7752      * @since 6.0
7753      */
7754     public RowId getRowId(String columnName) throws SQLException {
7755         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7756     }
7757 
7758     /**
7759      * Updates the designated column with a <code>RowId</code> value. The updater
7760      * methods are used to update column values in the current row or the insert
7761      * row. The updater methods do not update the underlying database; instead
7762      * the <code>updateRow<code> or <code>insertRow</code> methods are called
7763      * to update the database.
7764      *
7765      * @param columnIndex the first column is 1, the second 2, ...
7766      * @param x the column value
7767      * @throws SQLException if a database access occurs
7768      * @since 6.0
7769      */
7770     public void updateRowId(int columnIndex, RowId x) throws SQLException {
7771         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7772     }
7773 
7774     /**
7775      * Updates the designated column with a <code>RowId</code> value. The updater
7776      * methods are used to update column values in the current row or the insert
7777      * row. The updater methods do not update the underlying database; instead
7778      * the <code>updateRow<code> or <code>insertRow</code> methods are called
7779      * to update the database.
7780      *
7781      * @param columnName the name of the column
7782      * @param x the column value
7783      * @throws SQLException if a database access occurs
7784      * @since 6.0
7785      */
7786     public void updateRowId(String columnName, RowId x) throws SQLException {
7787         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7788     }
7789 
7790     /**
7791      * Retrieves the holdability of this ResultSet object
7792      * @return  either ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT
7793      * @throws SQLException if a database error occurs
7794      * @since 6.0
7795      */
7796     public int getHoldability() throws SQLException {
7797         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7798     }
7799 
7800     /**
7801      * Retrieves whether this ResultSet object has been closed. A ResultSet is closed if the
7802      * method close has been called on it, or if it is automatically closed.
7803      * @return true if this ResultSet object is closed; false if it is still open
7804      * @throws SQLException if a database access error occurs
7805      * @since 6.0
7806      */
7807     public boolean isClosed() throws SQLException {
7808         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7809     }
7810 
7811     /**
7812      * This method is used for updating columns that support National Character sets.
7813      * It can be used for updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
7814      * @param columnIndex the first column is 1, the second 2, ...
7815      * @param nString the value for the column to be updated
7816      * @throws SQLException if a database access error occurs
7817      * @since 6.0
7818      */
7819     public void updateNString(int columnIndex, String nString) throws SQLException {
7820         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7821     }
7822 
7823     /**
7824      * This method is used for updating columns that support National Character sets.
7825      * It can be used for updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
7826      * @param columnName name of the Column
7827      * @param nString the value for the column to be updated
7828      * @throws SQLException if a database access error occurs
7829      * @since 6.0
7830      */
7831     public void updateNString(String columnName, String nString) throws SQLException {
7832         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7833     }
7834 
7835 
7836     /*o
7837      * This method is used for updating SQL <code>NCLOB</code>  type that maps
7838      * to <code>java.sql.Types.NCLOB</code>
7839      * @param columnIndex the first column is 1, the second 2, ...
7840      * @param nClob the value for the column to be updated
7841      * @throws SQLException if a database access error occurs
7842      * @since 6.0
7843      */
7844     public void updateNClob(int columnIndex, NClob nClob) throws SQLException {
7845         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7846     }
7847 
7848     /**
7849      * This method is used for updating SQL <code>NCLOB</code>  type that maps
7850      * to <code>java.sql.Types.NCLOB</code>
7851      * @param columnName name of the column
7852      * @param nClob the value for the column to be updated
7853      * @throws SQLException if a database access error occurs
7854      * @since 6.0
7855      */
7856     public void updateNClob(String columnName, NClob nClob) throws SQLException {
7857        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7858     }
7859 
7860     /**
7861      * Retrieves the value of the designated column in the current row
7862      * of this <code>ResultSet</code> object as a <code>NClob</code> object
7863      * in the Java programming language.
7864      *
7865      * @param i the first column is 1, the second is 2, ...
7866      * @return a <code>NClob</code> object representing the SQL
7867      *         <code>NCLOB</code> value in the specified column
7868      * @exception SQLException if a database access error occurs
7869      * @since 6.0
7870      */
7871     public NClob getNClob(int i) throws SQLException {
7872         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7873     }
7874 
7875 
7876    /**
7877      * Retrieves the value of the designated column in the current row
7878      * of this <code>ResultSet</code> object as a <code>NClob</code> object
7879      * in the Java programming language.
7880      *
7881      * @param colName the name of the column from which to retrieve the value
7882      * @return a <code>NClob</code> object representing the SQL <code>NCLOB</code>
7883      * value in the specified column
7884      * @exception SQLException if a database access error occurs
7885      * @since 6.0
7886      */
7887     public NClob getNClob(String colName) throws SQLException {
7888         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7889     }
7890 
7891     public <T> T unwrap(java.lang.Class<T> iface) throws java.sql.SQLException {
7892         return null;
7893     }
7894 
7895     public boolean isWrapperFor(Class<?> interfaces) throws SQLException {
7896         return false;
7897     }
7898 
7899 
7900    /**
7901       * Sets the designated parameter to the given <code>java.sql.SQLXML</code> object. The driver converts this to an
7902       * SQL <code>XML</code> value when it sends it to the database.
7903       * @param parameterIndex index of the first parameter is 1, the second is 2, ...
7904       * @param xmlObject a <code>SQLXML</code> object that maps an SQL <code>XML</code> value
7905       * @throws SQLException if a database access error occurs
7906       * @since 1.6
7907       */
7908      public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
7909          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7910      }
7911 
7912    /**
7913      * Sets the designated parameter to the given <code>java.sql.SQLXML</code> object. The driver converts this to an
7914      * <code>SQL XML</code> value when it sends it to the database.
7915      * @param parameterName the name of the parameter
7916      * @param xmlObject a <code>SQLXML</code> object that maps an <code>SQL XML</code> value
7917      * @throws SQLException if a database access error occurs
7918      * @since 1.6
7919      */
7920     public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException {
7921          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7922      }
7923 
7924 
7925     /**
7926      * Sets the designated parameter to the given <code>java.sql.RowId</code> object. The
7927      * driver converts this to a SQL <code>ROWID</code> value when it sends it
7928      * to the database
7929      *
7930      * @param parameterIndex the first parameter is 1, the second is 2, ...
7931      * @param x the parameter value
7932      * @throws SQLException if a database access error occurs
7933      *
7934      * @since 1.6
7935      */
7936     public void setRowId(int parameterIndex, RowId x) throws SQLException {
7937          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7938      }
7939 
7940 
7941     /**
7942     * Sets the designated parameter to the given <code>java.sql.RowId</code> object. The
7943     * driver converts this to a SQL <code>ROWID</code> when it sends it to the
7944     * database.
7945     *
7946     * @param parameterName the name of the parameter
7947     * @param x the parameter value
7948     * @throws SQLException if a database access error occurs
7949     * @since 1.6
7950     */
7951    public void setRowId(String parameterName, RowId x) throws SQLException {
7952          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7953      }
7954 
7955 
7956     /**
7957      * Sets the designated parameter to a <code>Reader</code> object. The
7958      * <code>Reader</code> reads the data till end-of-file is reached. The
7959      * driver does the necessary conversion from Java character format to
7960      * the national character set in the database.
7961 
7962      * <P><B>Note:</B> This stream object can either be a standard
7963      * Java stream object or your own subclass that implements the
7964      * standard interface.
7965      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
7966      * it might be more efficient to use a version of
7967      * <code>setNCharacterStream</code> which takes a length parameter.
7968      *
7969      * @param parameterIndex of the first parameter is 1, the second is 2, ...
7970      * @param value the parameter value
7971      * @throws SQLException if the driver does not support national
7972      *         character sets;  if the driver can detect that a data conversion
7973      *  error could occur ; if a database access error occurs; or
7974      * this method is called on a closed <code>PreparedStatement</code>
7975      * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
7976      * @since 1.6
7977      */
7978      public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
7979         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
7980      }
7981 
7982 
7983     /**
7984     * Sets the designated parameter to a <code>java.sql.NClob</code> object. The object
7985     * implements the <code>java.sql.NClob</code> interface. This <code>NClob</code>
7986     * object maps to a SQL <code>NCLOB</code>.
7987     * @param parameterName the name of the column to be set
7988     * @param value the parameter value
7989     * @throws SQLException if the driver does not support national
7990     *         character sets;  if the driver can detect that a data conversion
7991     *  error could occur; or if a database access error occurs
7992     * @since 1.6
7993     */
7994     public void setNClob(String parameterName, NClob value) throws SQLException {
7995          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7996      }
7997 
7998 
7999   /**
8000      * Retrieves the value of the designated column in the current row
8001      * of this <code>ResultSet</code> object as a
8002      * <code>java.io.Reader</code> object.
8003      * It is intended for use when
8004      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8005      * and <code>LONGNVARCHAR</code> columns.
8006      *
8007      * @return a <code>java.io.Reader</code> object that contains the column
8008      * value; if the value is SQL <code>NULL</code>, the value returned is
8009      * <code>null</code> in the Java programming language.
8010      * @param columnIndex the first column is 1, the second is 2, ...
8011      * @exception SQLException if a database access error occurs
8012      * @since 1.6
8013      */
8014     public java.io.Reader getNCharacterStream(int columnIndex) throws SQLException {
8015        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8016      }
8017 
8018 
8019     /**
8020      * Retrieves the value of the designated column in the current row
8021      * of this <code>ResultSet</code> object as a
8022      * <code>java.io.Reader</code> object.
8023      * It is intended for use when
8024      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8025      * and <code>LONGNVARCHAR</code> columns.
8026      *
8027      * @param columnName the name of the column
8028      * @return a <code>java.io.Reader</code> object that contains the column
8029      * value; if the value is SQL <code>NULL</code>, the value returned is
8030      * <code>null</code> in the Java programming language
8031      * @exception SQLException if a database access error occurs
8032      * @since 1.6
8033      */
8034     public java.io.Reader getNCharacterStream(String columnName) throws SQLException {
8035        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8036      }
8037 
8038 
8039     /**
8040      * Updates the designated column with a <code>java.sql.SQLXML</code> value.
8041      * The updater
8042      * methods are used to update column values in the current row or the insert
8043      * row. The updater methods do not update the underlying database; instead
8044      * the <code>updateRow</code> or <code>insertRow</code> methods are called
8045      * to update the database.
8046      * @param columnIndex the first column is 1, the second 2, ...
8047      * @param xmlObject the value for the column to be updated
8048      * @throws SQLException if a database access error occurs
8049      * @since 1.6
8050      */
8051     public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException {
8052         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8053     }
8054 
8055     /**
8056      * Updates the designated column with a <code>java.sql.SQLXML</code> value.
8057      * The updater
8058      * methods are used to update column values in the current row or the insert
8059      * row. The updater methods do not update the underlying database; instead
8060      * the <code>updateRow</code> or <code>insertRow</code> methods are called
8061      * to update the database.
8062      *
8063      * @param columnName the name of the column
8064      * @param xmlObject the column value
8065      * @throws SQLException if a database access occurs
8066      * @since 1.6
8067      */
8068     public void updateSQLXML(String columnName, SQLXML xmlObject) throws SQLException {
8069         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8070     }
8071 
8072      /**
8073      * Retrieves the value of the designated column in the current row
8074      * of this <code>ResultSet</code> object as
8075      * a <code>String</code> in the Java programming language.
8076      * It is intended for use when
8077      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8078      * and <code>LONGNVARCHAR</code> columns.
8079      *
8080      * @param columnIndex the first column is 1, the second is 2, ...
8081      * @return the column value; if the value is SQL <code>NULL</code>, the
8082      * value returned is <code>null</code>
8083      * @exception SQLException if a database access error occurs
8084      * @since 1.6
8085      */
8086     public String getNString(int columnIndex) throws SQLException {
8087         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8088     }
8089 
8090     /**
8091      * Retrieves the value of the designated column in the current row
8092      * of this <code>ResultSet</code> object as
8093      * a <code>String</code> in the Java programming language.
8094      * It is intended for use when
8095      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8096      * and <code>LONGNVARCHAR</code> columns.
8097      *
8098      * @param columnName the SQL name of the column
8099      * @return the column value; if the value is SQL <code>NULL</code>, the
8100      * value returned is <code>null</code>
8101      * @exception SQLException if a database access error occurs
8102      * @since 1.6
8103      */
8104     public String getNString(String columnName) throws SQLException {
8105         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8106     }
8107 
8108      /**
8109        * Updates the designated column with a character stream value, which will
8110        * have the specified number of bytes. The driver does the necessary conversion
8111        * from Java character format to the national character set in the database.
8112        * It is intended for use when updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
8113        * The updater methods are used to update column values in the current row or
8114        * the insert row. The updater methods do not update the underlying database;
8115        * instead the updateRow or insertRow methods are called to update the database.
8116        *
8117        * @param columnIndex - the first column is 1, the second is 2, ...
8118        * @param x - the new column value
8119        * @param length - the length of the stream
8120        * @exception SQLException if a database access error occurs
8121        * @since 1.6
8122        */
8123        public void updateNCharacterStream(int columnIndex,
8124                             java.io.Reader x,
8125                             long length)
8126                             throws SQLException {
8127           throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8128        }
8129 
8130      /**
8131        * Updates the designated column with a character stream value, which will
8132        * have the specified number of bytes. The driver does the necessary conversion
8133        * from Java character format to the national character set in the database.
8134        * It is intended for use when updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
8135        * The updater methods are used to update column values in the current row or
8136        * the insert row. The updater methods do not update the underlying database;
8137        * instead the updateRow or insertRow methods are called to update the database.
8138        *
8139        * @param columnName - name of the Column
8140        * @param x - the new column value
8141        * @param length - the length of the stream
8142        * @exception SQLException if a database access error occurs
8143        * @since 1.6
8144        */
8145        public void updateNCharacterStream(String columnName,
8146                             java.io.Reader x,
8147                             long length)
8148                             throws SQLException {
8149           throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8150        }
8151 
8152      /**
8153      * Updates the designated column with a character stream value.   The
8154      * driver does the necessary conversion from Java character format to
8155      * the national character set in the database.
8156      * It is intended for use when
8157      * updating  <code>NCHAR</code>,<code>NVARCHAR</code>
8158      * and <code>LONGNVARCHAR</code> columns.
8159      *
8160      * The updater methods are used to update column values in the
8161      * current row or the insert row.  The updater methods do not
8162      * update the underlying database; instead the <code>updateRow</code> or
8163      * <code>insertRow</code> methods are called to update the database.
8164      *
8165      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8166      * it might be more efficient to use a version of
8167      * <code>updateNCharacterStream</code> which takes a length parameter.
8168      *
8169      * @param columnIndex the first column is 1, the second is 2, ...
8170      * @param x the new column value
8171      * @exception SQLException if a database access error occurs,
8172      * the result set concurrency is <code>CONCUR_READ_ONLY</code> or this method is called on a closed result set
8173      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8174      * this method
8175      * @since 1.6
8176      */
8177     public void updateNCharacterStream(int columnIndex,
8178                              java.io.Reader x) throws SQLException {
8179         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8180     }
8181 
8182     /**
8183      * Updates the designated column with a character stream value.  The
8184      * driver does the necessary conversion from Java character format to
8185      * the national character set in the database.
8186      * It is intended for use when
8187      * updating  <code>NCHAR</code>,<code>NVARCHAR</code>
8188      * and <code>LONGNVARCHAR</code> columns.
8189      *
8190      * The updater methods are used to update column values in the
8191      * current row or the insert row.  The updater methods do not
8192      * update the underlying database; instead the <code>updateRow</code> or
8193      * <code>insertRow</code> methods are called to update the database.
8194      *
8195      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8196      * it might be more efficient to use a version of
8197      * <code>updateNCharacterStream</code> which takes a length parameter.
8198      *
8199      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8200 bel is the name of the column
8201      * @param reader the <code>java.io.Reader</code> object containing
8202      *        the new column value
8203      * @exception SQLException if a database access error occurs,
8204      * the result set concurrency is <code>CONCUR_READ_ONLY</code> or this method is called on a closed result set
8205       * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8206      * this method
8207      * @since 1.6
8208      */
8209     public void updateNCharacterStream(String columnLabel,
8210                              java.io.Reader reader) throws SQLException {
8211         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8212     }
8213 
8214 //////////////////////////
8215 
8216     /**
8217      * Updates the designated column using the given input stream, which
8218      * will have the specified number of bytes.
8219      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8220      * parameter, it may be more practical to send it via a
8221      * <code>java.io.InputStream</code>. Data will be read from the stream
8222      * as needed until end-of-file is reached.  The JDBC driver will
8223      * do any necessary conversion from ASCII to the database char format.
8224      *
8225      * <P><B>Note:</B> This stream object can either be a standard
8226      * Java stream object or your own subclass that implements the
8227      * standard interface.
8228      * <p>
8229      * The updater methods are used to update column values in the
8230      * current row or the insert row.  The updater methods do not
8231      * update the underlying database; instead the <code>updateRow</code> or
8232      * <code>insertRow</code> methods are called to update the database.
8233      *
8234      * @param columnIndex the first column is 1, the second is 2, ...
8235      * @param inputStream An object that contains the data to set the parameter
8236      * value to.
8237      * @param length the number of bytes in the parameter data.
8238      * @exception SQLException if a database access error occurs,
8239      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8240      * or this method is called on a closed result set
8241      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8242      * this method
8243      * @since 1.6
8244      */
8245     public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException{
8246         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8247     }
8248 
8249     /**
8250      * Updates the designated column using the given input stream, which
8251      * will have the specified number of bytes.
8252      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8253      * parameter, it may be more practical to send it via a
8254      * <code>java.io.InputStream</code>. Data will be read from the stream
8255      * as needed until end-of-file is reached.  The JDBC driver will
8256      * do any necessary conversion from ASCII to the database char format.
8257      *
8258      * <P><B>Note:</B> This stream object can either be a standard
8259      * Java stream object or your own subclass that implements the
8260      * standard interface.
8261      * <p>
8262      * The updater methods are used to update column values in the
8263      * current row or the insert row.  The updater methods do not
8264      * update the underlying database; instead the <code>updateRow</code> or
8265      * <code>insertRow</code> methods are called to update the database.
8266      *
8267      * @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
8268      * @param inputStream An object that contains the data to set the parameter
8269      * value to.
8270      * @param length the number of bytes in the parameter data.
8271      * @exception SQLException if a database access error occurs,
8272      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8273      * or this method is called on a closed result set
8274      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8275      * this method
8276      * @since 1.6
8277      */
8278     public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException {
8279         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8280     }
8281 
8282     /**
8283      * Updates the designated column using the given input stream.
8284      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8285      * parameter, it may be more practical to send it via a
8286      * <code>java.io.InputStream</code>. Data will be read from the stream
8287      * as needed until end-of-file is reached.  The JDBC driver will
8288      * do any necessary conversion from ASCII to the database char format.
8289      *
8290      * <P><B>Note:</B> This stream object can either be a standard
8291      * Java stream object or your own subclass that implements the
8292      * standard interface.
8293      *
8294      *  <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8295      * it might be more efficient to use a version of
8296      * <code>updateBlob</code> which takes a length parameter.
8297      * <p>
8298      * The updater methods are used to update column values in the
8299      * current row or the insert row.  The updater methods do not
8300      * update the underlying database; instead the <code>updateRow</code> or
8301      * <code>insertRow</code> methods are called to update the database.
8302      *
8303      * @param columnIndex the first column is 1, the second is 2, ...
8304      * @param inputStream An object that contains the data to set the parameter
8305      * value to.
8306      * @exception SQLException if a database access error occurs,
8307      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8308      * or this method is called on a closed result set
8309      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8310      * this method
8311      * @since 1.6
8312      */
8313     public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException {
8314         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8315     }
8316 
8317     /**
8318      * Updates the designated column using the given input stream.
8319      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8320      * parameter, it may be more practical to send it via a
8321      * <code>java.io.InputStream</code>. Data will be read from the stream
8322      * as needed until end-of-file is reached.  The JDBC driver will
8323      * do any necessary conversion from ASCII to the database char format.
8324      *
8325      * <P><B>Note:</B> This stream object can either be a standard
8326      * Java stream object or your own subclass that implements the
8327      * standard interface.
8328      *   <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8329      * it might be more efficient to use a version of
8330      * <code>updateBlob</code> which takes a length parameter.
8331      * <p>
8332      * The updater methods are used to update column values in the
8333      * current row or the insert row.  The updater methods do not
8334      * update the underlying database; instead the <code>updateRow</code> or
8335      * <code>insertRow</code> methods are called to update the database.
8336      *
8337      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8338 bel is the name of the column
8339      * @param inputStream An object that contains the data to set the parameter
8340      * value to.
8341      * @exception SQLException if a database access error occurs,
8342      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8343      * or this method is called on a closed result set
8344      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8345      * this method
8346      * @since 1.6
8347      */
8348     public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException {
8349         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8350     }
8351 
8352     /**
8353      * Updates the designated column using the given <code>Reader</code>
8354      * object, which is the given number of characters long.
8355      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8356      * parameter, it may be more practical to send it via a
8357      * <code>java.io.Reader</code> object. The data will be read from the stream
8358      * as needed until end-of-file is reached.  The JDBC driver will
8359      * do any necessary conversion from UNICODE to the database char format.
8360      *
8361      * <P><B>Note:</B> This stream object can either be a standard
8362      * Java stream object or your own subclass that implements the
8363      * standard interface.
8364      * <p>
8365      * The updater methods are used to update column values in the
8366      * current row or the insert row.  The updater methods do not
8367      * update the underlying database; instead the <code>updateRow</code> or
8368      * <code>insertRow</code> methods are called to update the database.
8369      *
8370      * @param columnIndex the first column is 1, the second is 2, ...
8371      * @param reader An object that contains the data to set the parameter value to.
8372      * @param length the number of characters in the parameter data.
8373      * @exception SQLException if a database access error occurs,
8374      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8375      * or this method is called on a closed result set
8376      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8377      * this method
8378      * @since 1.6
8379      */
8380     public void updateClob(int columnIndex,  Reader reader, long length) throws SQLException {
8381         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8382     }
8383 
8384     /**
8385      * Updates the designated column using the given <code>Reader</code>
8386      * object, which is the given number of characters long.
8387      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8388      * parameter, it may be more practical to send it via a
8389      * <code>java.io.Reader</code> object. The data will be read from the stream
8390      * as needed until end-of-file is reached.  The JDBC driver will
8391      * do any necessary conversion from UNICODE to the database char format.
8392      *
8393      * <P><B>Note:</B> This stream object can either be a standard
8394      * Java stream object or your own subclass that implements the
8395      * standard interface.
8396      * <p>
8397      * The updater methods are used to update column values in the
8398      * current row or the insert row.  The updater methods do not
8399      * update the underlying database; instead the <code>updateRow</code> or
8400      * <code>insertRow</code> methods are called to update the database.
8401      *
8402      * @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
8403      * @param reader An object that contains the data to set the parameter value to.
8404      * @param length the number of characters in the parameter data.
8405      * @exception SQLException if a database access error occurs,
8406      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8407      * or this method is called on a closed result set
8408      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8409      * this method
8410      * @since 1.6
8411      */
8412     public void updateClob(String columnLabel,  Reader reader, long length) throws SQLException {
8413         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8414     }
8415 
8416    /**
8417      * Updates the designated column using the given <code>Reader</code>
8418      * object.
8419      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8420      * parameter, it may be more practical to send it via a
8421      * <code>java.io.Reader</code> object. The data will be read from the stream
8422      * as needed until end-of-file is reached.  The JDBC driver will
8423      * do any necessary conversion from UNICODE to the database char format.
8424      *
8425      * <P><B>Note:</B> This stream object can either be a standard
8426      * Java stream object or your own subclass that implements the
8427      * standard interface.
8428      *   <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8429      * it might be more efficient to use a version of
8430      * <code>updateClob</code> which takes a length parameter.
8431      * <p>
8432      * The updater methods are used to update column values in the
8433      * current row or the insert row.  The updater methods do not
8434      * update the underlying database; instead the <code>updateRow</code> or
8435      * <code>insertRow</code> methods are called to update the database.
8436      *
8437      * @param columnIndex the first column is 1, the second is 2, ...
8438      * @param reader An object that contains the data to set the parameter value to.
8439      * @exception SQLException if a database access error occurs,
8440      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8441      * or this method is called on a closed result set
8442      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8443      * this method
8444      * @since 1.6
8445      */
8446     public void updateClob(int columnIndex,  Reader reader) throws SQLException {
8447         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8448     }
8449 
8450     /**
8451      * Updates the designated column using the given <code>Reader</code>
8452      * object.
8453      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8454      * parameter, it may be more practical to send it via a
8455      * <code>java.io.Reader</code> object. The data will be read from the stream
8456      * as needed until end-of-file is reached.  The JDBC driver will
8457      * do any necessary conversion from UNICODE to the database char format.
8458      *
8459      * <P><B>Note:</B> This stream object can either be a standard
8460      * Java stream object or your own subclass that implements the
8461      * standard interface.
8462      *  <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8463      * it might be more efficient to use a version of
8464      * <code>updateClob</code> which takes a length parameter.
8465      * <p>
8466      * The updater methods are used to update column values in the
8467      * current row or the insert row.  The updater methods do not
8468      * update the underlying database; instead the <code>updateRow</code> or
8469      * <code>insertRow</code> methods are called to update the database.
8470      *
8471      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8472 bel is the name of the column
8473      * @param reader An object that contains the data to set the parameter value to.
8474      * @exception SQLException if a database access error occurs,
8475      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8476      * or this method is called on a closed result set
8477      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8478      * this method
8479      * @since 1.6
8480      */
8481     public void updateClob(String columnLabel,  Reader reader) throws SQLException {
8482         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8483     }
8484 
8485    /**
8486      * Updates the designated column using the given <code>Reader</code>
8487      * object, which is the given number of characters long.
8488      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8489      * parameter, it may be more practical to send it via a
8490      * <code>java.io.Reader</code> object. The data will be read from the stream
8491      * as needed until end-of-file is reached.  The JDBC driver will
8492      * do any necessary conversion from UNICODE to the database char format.
8493      *
8494      * <P><B>Note:</B> This stream object can either be a standard
8495      * Java stream object or your own subclass that implements the
8496      * standard interface.
8497      * <p>
8498      * The updater methods are used to update column values in the
8499      * current row or the insert row.  The updater methods do not
8500      * update the underlying database; instead the <code>updateRow</code> or
8501      * <code>insertRow</code> methods are called to update the database.
8502      *
8503      * @param columnIndex the first column is 1, the second 2, ...
8504      * @param reader An object that contains the data to set the parameter value to.
8505      * @param length the number of characters in the parameter data.
8506      * @throws SQLException if the driver does not support national
8507      *         character sets;  if the driver can detect that a data conversion
8508      *  error could occur; this method is called on a closed result set,
8509      * if a database access error occurs or
8510      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8511      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8512      * this method
8513      * @since 1.6
8514      */
8515     public void updateNClob(int columnIndex,  Reader reader, long length) throws SQLException {
8516         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8517     }
8518 
8519     /**
8520      * Updates the designated column using the given <code>Reader</code>
8521      * object, which is the given number of characters long.
8522      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8523      * parameter, it may be more practical to send it via a
8524      * <code>java.io.Reader</code> object. The data will be read from the stream
8525      * as needed until end-of-file is reached.  The JDBC driver will
8526      * do any necessary conversion from UNICODE to the database char format.
8527      *
8528      * <P><B>Note:</B> This stream object can either be a standard
8529      * Java stream object or your own subclass that implements the
8530      * standard interface.
8531      * <p>
8532      * The updater methods are used to update column values in the
8533      * current row or the insert row.  The updater methods do not
8534      * update the underlying database; instead the <code>updateRow</code> or
8535      * <code>insertRow</code> methods are called to update the database.
8536      *
8537      * @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
8538      * @param reader An object that contains the data to set the parameter value to.
8539      * @param length the number of characters in the parameter data.
8540      * @throws SQLException if the driver does not support national
8541      *         character sets;  if the driver can detect that a data conversion
8542      *  error could occur; this method is called on a closed result set;
8543      *  if a database access error occurs or
8544      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8545      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8546      * this method
8547      * @since 1.6
8548      */
8549     public void updateNClob(String columnLabel,  Reader reader, long length) throws SQLException {
8550         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8551     }
8552 
8553     /**
8554      * Updates the designated column using the given <code>Reader</code>
8555      * object.
8556      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8557      * parameter, it may be more practical to send it via a
8558      * <code>java.io.Reader</code> object. The data will be read from the stream
8559      * as needed until end-of-file is reached.  The JDBC driver will
8560      * do any necessary conversion from UNICODE to the database char format.
8561      *
8562      * <P><B>Note:</B> This stream object can either be a standard
8563      * Java stream object or your own subclass that implements the
8564      * standard interface.
8565      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8566      * it might be more efficient to use a version of
8567      * <code>updateNClob</code> which takes a length parameter.
8568      * <p>
8569      * The updater methods are used to update column values in the
8570      * current row or the insert row.  The updater methods do not
8571      * update the underlying database; instead the <code>updateRow</code> or
8572      * <code>insertRow</code> methods are called to update the database.
8573      *
8574      * @param columnIndex the first column is 1, the second 2, ...
8575      * @param reader An object that contains the data to set the parameter value to.
8576      * @throws SQLException if the driver does not support national
8577      *         character sets;  if the driver can detect that a data conversion
8578      *  error could occur; this method is called on a closed result set,
8579      * if a database access error occurs or
8580      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8581      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8582      * this method
8583      * @since 1.6
8584      */
8585     public void updateNClob(int columnIndex,  Reader reader) throws SQLException {
8586         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8587     }
8588 
8589     /**
8590      * Updates the designated column using the given <code>Reader</code>
8591      * object.
8592      * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8593      * parameter, it may be more practical to send it via a
8594      * <code>java.io.Reader</code> object. The data will be read from the stream
8595      * as needed until end-of-file is reached.  The JDBC driver will
8596      * do any necessary conversion from UNICODE to the database char format.
8597      *
8598      * <P><B>Note:</B> This stream object can either be a standard
8599      * Java stream object or your own subclass that implements the
8600      * standard interface.
8601      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8602      * it might be more efficient to use a version of
8603      * <code>updateNClob</code> which takes a length parameter.
8604      * <p>
8605      * The updater methods are used to update column values in the
8606      * current row or the insert row.  The updater methods do not
8607      * update the underlying database; instead the <code>updateRow</code> or
8608      * <code>insertRow</code> methods are called to update the database.
8609      *
8610      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8611 bel is the name of the column
8612      * @param reader An object that contains the data to set the parameter value to.
8613      * @throws SQLException if the driver does not support national
8614      *         character sets;  if the driver can detect that a data conversion
8615      *  error could occur; this method is called on a closed result set;
8616      *  if a database access error occurs or
8617      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8618      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8619      * this method
8620      * @since 1.6
8621      */
8622     public void updateNClob(String columnLabel,  Reader reader) throws SQLException {
8623         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8624     }
8625 
8626         /**
8627      * Updates the designated column with an ascii stream value, which will have
8628      * the specified number of bytes.
8629      * The updater methods are used to update column values in the
8630      * current row or the insert row.  The updater methods do not
8631      * update the underlying database; instead the <code>updateRow</code> or
8632      * <code>insertRow</code> methods are called to update the database.
8633      *
8634      * @param columnIndex the first column is 1, the second is 2, ...
8635      * @param x the new column value
8636      * @param length the length of the stream
8637      * @exception SQLException if a database access error occurs,
8638      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8639      * or this method is called on a closed result set
8640      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8641      * this method
8642      * @since 1.6
8643      */
8644     public void updateAsciiStream(int columnIndex,
8645                            java.io.InputStream x,
8646                            long length) throws SQLException {
8647 
8648     }
8649 
8650     /**
8651      * Updates the designated column with a binary stream value, which will have
8652      * the specified number of bytes.
8653      * The updater methods are used to update column values in the
8654      * current row or the insert row.  The updater methods do not
8655      * update the underlying database; instead the <code>updateRow</code> or
8656      * <code>insertRow</code> methods are called to update the database.
8657      *
8658      * @param columnIndex the first column is 1, the second is 2, ...
8659      * @param x the new column value
8660      * @param length the length of the stream
8661      * @exception SQLException if a database access error occurs,
8662      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8663      * or this method is called on a closed result set
8664      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8665      * this method
8666      * @since 1.6
8667      */
8668     public void updateBinaryStream(int columnIndex,
8669                             java.io.InputStream x,
8670                             long length) throws SQLException {
8671     }
8672 
8673     /**
8674      * Updates the designated column with a character stream value, which will have
8675      * the specified number of bytes.
8676      * The updater methods are used to update column values in the
8677      * current row or the insert row.  The updater methods do not
8678      * update the underlying database; instead the <code>updateRow</code> or
8679      * <code>insertRow</code> methods are called to update the database.
8680      *
8681      * @param columnIndex the first column is 1, the second is 2, ...
8682      * @param x the new column value
8683      * @param length the length of the stream
8684      * @exception SQLException if a database access error occurs,
8685      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8686      * or this method is called on a closed result set
8687      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8688      * this method
8689      * @since 1.6
8690      */
8691     public void updateCharacterStream(int columnIndex,
8692                              java.io.Reader x,
8693                              long length) throws SQLException {
8694         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8695     }
8696 
8697     /**
8698      * Updates the designated column with a character stream value, which will have
8699      * the specified number of bytes.
8700      * The updater methods are used to update column values in the
8701      * current row or the insert row.  The updater methods do not
8702      * update the underlying database; instead the <code>updateRow</code> or
8703      * <code>insertRow</code> methods are called to update the database.
8704      *
8705      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8706 bel is the name of the column
8707      * @param reader the <code>java.io.Reader</code> object containing
8708      *        the new column value
8709      * @param length the length of the stream
8710      * @exception SQLException if a database access error occurs,
8711      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8712      * or this method is called on a closed result set
8713      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8714      * this method
8715      * @since 1.6
8716      */
8717     public void updateCharacterStream(String columnLabel,
8718                              java.io.Reader reader,
8719                              long length) throws SQLException {
8720         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8721     }
8722      /**
8723      * Updates the designated column with an ascii stream value, which will have
8724      * the specified number of bytes..
8725      * The updater methods are used to update column values in the
8726      * current row or the insert row.  The updater methods do not
8727      * update the underlying database; instead the <code>updateRow</code> or
8728      * <code>insertRow</code> methods are called to update the database.
8729      *
8730      * @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
8731      * @param x the new column value
8732      * @param length the length of the stream
8733      * @exception SQLException if a database access error occurs,
8734      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8735      * or this method is called on a closed result set
8736      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8737      * this method
8738      * @since 1.6
8739      */
8740     public void updateAsciiStream(String columnLabel,
8741                            java.io.InputStream x,
8742                            long length) throws SQLException {
8743     }
8744 
8745     /**
8746      * Updates the designated column with a binary stream value, which will have
8747      * the specified number of bytes.
8748      * The updater methods are used to update column values in the
8749      * current row or the insert row.  The updater methods do not
8750      * update the underlying database; instead the <code>updateRow</code> or
8751      * <code>insertRow</code> methods are called to update the database.
8752      *
8753      * @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
8754      * @param x the new column value
8755      * @param length the length of the stream
8756      * @exception SQLException if a database access error occurs,
8757      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8758      * or this method is called on a closed result set
8759      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8760      * this method
8761      * @since 1.6
8762      */
8763     public void updateBinaryStream(String columnLabel,
8764                             java.io.InputStream x,
8765                             long length) throws SQLException {
8766     }
8767 
8768     /**
8769      * Updates the designated column with a binary stream value.
8770      * The updater methods are used to update column values in the
8771      * current row or the insert row.  The updater methods do not
8772      * update the underlying database; instead the <code>updateRow</code> or
8773      * <code>insertRow</code> methods are called to update the database.
8774      *
8775      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8776      * it might be more efficient to use a version of
8777      * <code>updateBinaryStream</code> which takes a length parameter.
8778      *
8779      * @param columnIndex the first column is 1, the second is 2, ...
8780      * @param x the new column value
8781      * @exception SQLException if a database access error occurs,
8782      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8783      * or this method is called on a closed result set
8784      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8785      * this method
8786      * @since 1.6
8787      */
8788     public void updateBinaryStream(int columnIndex,
8789                             java.io.InputStream x) throws SQLException {
8790         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8791     }
8792 
8793 
8794     /**
8795      * Updates the designated column with a binary stream value.
8796      * The updater methods are used to update column values in the
8797      * current row or the insert row.  The updater methods do not
8798      * update the underlying database; instead the <code>updateRow</code> or
8799      * <code>insertRow</code> methods are called to update the database.
8800      *
8801      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8802      * it might be more efficient to use a version of
8803      * <code>updateBinaryStream</code> which takes a length parameter.
8804      *
8805      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8806 bel is the name of the column
8807      * @param x the new column value
8808      * @exception SQLException if a database access error occurs,
8809      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8810      * or this method is called on a closed result set
8811      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8812      * this method
8813      * @since 1.6
8814      */
8815     public void updateBinaryStream(String columnLabel,
8816                             java.io.InputStream x) throws SQLException {
8817         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8818     }
8819 
8820     /**
8821      * Updates the designated column with a character stream value.
8822      * The updater methods are used to update column values in the
8823      * current row or the insert row.  The updater methods do not
8824      * update the underlying database; instead the <code>updateRow</code> or
8825      * <code>insertRow</code> methods are called to update the database.
8826      *
8827      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8828      * it might be more efficient to use a version of
8829      * <code>updateCharacterStream</code> which takes a length parameter.
8830      *
8831      * @param columnIndex the first column is 1, the second is 2, ...
8832      * @param x the new column value
8833      * @exception SQLException if a database access error occurs,
8834      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8835      * or this method is called on a closed result set
8836      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8837      * this method
8838      * @since 1.6
8839      */
8840     public void updateCharacterStream(int columnIndex,
8841                              java.io.Reader x) throws SQLException {
8842         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8843     }
8844 
8845     /**
8846      * Updates the designated column with a character stream value.
8847      * The updater methods are used to update column values in the
8848      * current row or the insert row.  The updater methods do not
8849      * update the underlying database; instead the <code>updateRow</code> or
8850      * <code>insertRow</code> methods are called to update the database.
8851      *
8852      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8853      * it might be more efficient to use a version of
8854      * <code>updateCharacterStream</code> which takes a length parameter.
8855      *
8856      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8857 bel is the name of the column
8858      * @param reader the <code>java.io.Reader</code> object containing
8859      *        the new column value
8860      * @exception SQLException if a database access error occurs,
8861      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8862      * or this method is called on a closed result set
8863      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8864      * this method
8865      * @since 1.6
8866      */
8867     public void updateCharacterStream(String columnLabel,
8868                              java.io.Reader reader) throws SQLException {
8869         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8870     }
8871 
8872     /**
8873      * Updates the designated column with an ascii stream value.
8874      * The updater methods are used to update column values in the
8875      * current row or the insert row.  The updater methods do not
8876      * update the underlying database; instead the <code>updateRow</code> or
8877      * <code>insertRow</code> methods are called to update the database.
8878      *
8879      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8880      * it might be more efficient to use a version of
8881      * <code>updateAsciiStream</code> which takes a length parameter.
8882      *
8883      * @param columnIndex the first column is 1, the second is 2, ...
8884      * @param x the new column value
8885      * @exception SQLException if a database access error occurs,
8886      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8887      * or this method is called on a closed result set
8888      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8889      * this method
8890      * @since 1.6
8891      */
8892     public void updateAsciiStream(int columnIndex,
8893                            java.io.InputStream x) throws SQLException {
8894         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8895     }
8896 
8897     /**
8898      * Updates the designated column with an ascii stream value.
8899      * The updater methods are used to update column values in the
8900      * current row or the insert row.  The updater methods do not
8901      * update the underlying database; instead the <code>updateRow</code> or
8902      * <code>insertRow</code> methods are called to update the database.
8903      *
8904      * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8905      * it might be more efficient to use a version of
8906      * <code>updateAsciiStream</code> which takes a length parameter.
8907      *
8908      * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8909 bel is the name of the column
8910      * @param x the new column value
8911      * @exception SQLException if a database access error occurs,
8912      * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8913      * or this method is called on a closed result set
8914      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8915      * this method
8916      * @since 1.6
8917      */
8918     public void updateAsciiStream(String columnLabel,
8919                            java.io.InputStream x) throws SQLException {
8920 
8921     }
8922 
8923    /**
8924   * Sets the designated parameter to the given <code>java.net.URL</code> value.
8925   * The driver converts this to an SQL <code>DATALINK</code> value
8926   * when it sends it to the database.
8927   *
8928   * @param parameterIndex the first parameter is 1, the second is 2, ...
8929   * @param x the <code>java.net.URL</code> object to be set
8930   * @exception SQLException if a database access error occurs or
8931   * this method is called on a closed <code>PreparedStatement</code>
8932   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
8933   * @since 1.4
8934   */
8935   public void setURL(int parameterIndex, java.net.URL x) throws SQLException{
8936         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8937    }
8938 
8939   /**
8940   * Sets the designated parameter to a <code>Reader</code> object.
8941   * This method differs from the <code>setCharacterStream (int, Reader)</code> method
8942   * because it informs the driver that the parameter value should be sent to
8943   * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
8944   * driver may have to do extra work to determine whether the parameter
8945   * data should be sent to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
8946   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8947   * it might be more efficient to use a version of
8948   * <code>setNClob</code> which takes a length parameter.
8949   *
8950   * @param parameterIndex index of the first parameter is 1, the second is 2, ...
8951   * @param reader An object that contains the data to set the parameter value to.
8952   * @throws SQLException if parameterIndex does not correspond to a parameter
8953   * marker in the SQL statement;
8954   * if the driver does not support national character sets;
8955   * if the driver can detect that a data conversion
8956   *  error could occur;  if a database access error occurs or
8957   * this method is called on a closed <code>PreparedStatement</code>
8958   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
8959   *
8960   * @since 1.6
8961   */
8962   public void setNClob(int parameterIndex, Reader reader)
8963     throws SQLException{
8964         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8965    }
8966 
8967   /**
8968   * Sets the designated parameter to a <code>Reader</code> object.  The <code>reader</code> must contain  the number
8969              * of characters specified by length otherwise a <code>SQLException</code> will be
8970             * generated when the <code>CallableStatement</code> is executed.
8971             * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
8972             * because it informs the driver that the parameter value should be sent to
8973             * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
8974             * driver may have to do extra work to determine whether the parameter
8975             * data should be send to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
8976             *
8977             * @param parameterName the name of the parameter to be set
8978             * @param reader An object that contains the data to set the parameter value to.
8979             * @param length the number of characters in the parameter data.
8980             * @throws SQLException if parameterIndex does not correspond to a parameter
8981             * marker in the SQL statement; if the length specified is less than zero;
8982             * if the driver does not support national
8983             *         character sets;  if the driver can detect that a data conversion
8984             *  error could occur; if a database access error occurs or
8985             * this method is called on a closed <code>CallableStatement</code>
8986             * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8987             * this method
8988             * @since 1.6
8989             */
8990             public void setNClob(String parameterName, Reader reader, long length)
8991     throws SQLException{
8992         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8993    }
8994 
8995 
8996  /**
8997   * Sets the designated parameter to a <code>Reader</code> object.
8998   * This method differs from the <code>setCharacterStream (int, Reader)</code> method
8999   * because it informs the driver that the parameter value should be sent to
9000   * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9001   * driver may have to do extra work to determine whether the parameter
9002   * data should be send to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
9003   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9004   * it might be more efficient to use a version of
9005   * <code>setNClob</code> which takes a length parameter.
9006   *
9007   * @param parameterName the name of the parameter
9008   * @param reader An object that contains the data to set the parameter value to.
9009   * @throws SQLException if the driver does not support national character sets;
9010   * if the driver can detect that a data conversion
9011   *  error could occur;  if a database access error occurs or
9012   * this method is called on a closed <code>CallableStatement</code>
9013   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9014   *
9015   * @since 1.6
9016   */
9017   public void setNClob(String parameterName, Reader reader)
9018     throws SQLException{
9019         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9020    }
9021 
9022 
9023     /**
9024      * Sets the designated parameter to a <code>Reader</code> object.  The reader must contain  the number
9025      * of characters specified by length otherwise a <code>SQLException</code> will be
9026      * generated when the <code>PreparedStatement</code> is executed.
9027      * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
9028      * because it informs the driver that the parameter value should be sent to
9029      * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9030      * driver may have to do extra work to determine whether the parameter
9031      * data should be sent to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
9032      * @param parameterIndex index of the first parameter is 1, the second is 2, ...
9033      * @param reader An object that contains the data to set the parameter value to.
9034      * @param length the number of characters in the parameter data.
9035      * @throws SQLException if parameterIndex does not correspond to a parameter
9036      * marker in the SQL statement; if the length specified is less than zero;
9037      * if the driver does not support national character sets;
9038      * if the driver can detect that a data conversion
9039      *  error could occur;  if a database access error occurs or
9040      * this method is called on a closed <code>PreparedStatement</code>
9041      * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9042      *
9043      * @since 1.6
9044      */
9045      public void setNClob(int parameterIndex, Reader reader, long length)
9046        throws SQLException{
9047         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9048    }
9049 
9050 
9051     /**
9052      * Sets the designated parameter to a <code>java.sql.NClob</code> object. The driver converts this to
9053 a
9054      * SQL <code>NCLOB</code> value when it sends it to the database.
9055      * @param parameterIndex of the first parameter is 1, the second is 2, ...
9056      * @param value the parameter value
9057      * @throws SQLException if the driver does not support national
9058      *         character sets;  if the driver can detect that a data conversion
9059      *  error could occur ; or if a database access error occurs
9060      * @since 1.6
9061      */
9062      public void setNClob(int parameterIndex, NClob value) throws SQLException{
9063         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9064    }
9065 
9066 
9067    /**
9068   * Sets the designated paramter to the given <code>String</code> object.
9069   * The driver converts this to a SQL <code>NCHAR</code> or
9070   * <code>NVARCHAR</code> or <code>LONGNVARCHAR</code> value
9071   * (depending on the argument's
9072   * size relative to the driver's limits on <code>NVARCHAR</code> values)
9073   * when it sends it to the database.
9074   *
9075   * @param parameterIndex of the first parameter is 1, the second is 2, ...
9076   * @param value the parameter value
9077   * @throws SQLException if the driver does not support national
9078   *         character sets;  if the driver can detect that a data conversion
9079   *  error could occur ; or if a database access error occurs
9080   * @since 1.6
9081   */
9082   public void setNString(int parameterIndex, String value) throws SQLException{
9083         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9084    }
9085 
9086 
9087  /**
9088   * Sets the designated paramter to the given <code>String</code> object.
9089   * The driver converts this to a SQL <code>NCHAR</code> or
9090   * <code>NVARCHAR</code> or <code>LONGNVARCHAR</code>
9091   * @param parameterName the name of the column to be set
9092   * @param value the parameter value
9093   * @throws SQLException if the driver does not support national
9094   *         character sets;  if the driver can detect that a data conversion
9095   *  error could occur; or if a database access error occurs
9096   * @since 1.6
9097   */
9098  public void setNString(String parameterName, String value)
9099          throws SQLException{
9100         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9101    }
9102 
9103 
9104  /**
9105   * Sets the designated parameter to a <code>Reader</code> object. The
9106   * <code>Reader</code> reads the data till end-of-file is reached. The
9107   * driver does the necessary conversion from Java character format to
9108   * the national character set in the database.
9109   * @param parameterIndex of the first parameter is 1, the second is 2, ...
9110   * @param value the parameter value
9111   * @param length the number of characters in the parameter data.
9112   * @throws SQLException if the driver does not support national
9113   *         character sets;  if the driver can detect that a data conversion
9114   *  error could occur ; or if a database access error occurs
9115   * @since 1.6
9116   */
9117   public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException{
9118         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9119    }
9120 
9121 
9122  /**
9123   * Sets the designated parameter to a <code>Reader</code> object. The
9124   * <code>Reader</code> reads the data till end-of-file is reached. The
9125   * driver does the necessary conversion from Java character format to
9126   * the national character set in the database.
9127   * @param parameterName the name of the column to be set
9128   * @param value the parameter value
9129   * @param length the number of characters in the parameter data.
9130   * @throws SQLException if the driver does not support national
9131   *         character sets;  if the driver can detect that a data conversion
9132   *  error could occur; or if a database access error occurs
9133   * @since 1.6
9134   */
9135  public void setNCharacterStream(String parameterName, Reader value, long length)
9136          throws SQLException{
9137         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9138    }
9139 
9140   /**
9141   * Sets the designated parameter to a <code>Reader</code> object. The
9142   * <code>Reader</code> reads the data till end-of-file is reached. The
9143   * driver does the necessary conversion from Java character format to
9144   * the national character set in the database.
9145 
9146   * <P><B>Note:</B> This stream object can either be a standard
9147   * Java stream object or your own subclass that implements the
9148   * standard interface.
9149   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9150   * it might be more efficient to use a version of
9151   * <code>setNCharacterStream</code> which takes a length parameter.
9152   *
9153   * @param parameterName the name of the parameter
9154   * @param value the parameter value
9155   * @throws SQLException if the driver does not support national
9156   *         character sets;  if the driver can detect that a data conversion
9157   *  error could occur ; if a database access error occurs; or
9158   * this method is called on a closed <code>CallableStatement</code>
9159   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9160   * @since 1.6
9161   */
9162   public void setNCharacterStream(String parameterName, Reader value) throws SQLException{
9163         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9164    }
9165 
9166   /**
9167     * Sets the designated parameter to the given <code>java.sql.Timestamp</code> value,
9168     * using the given <code>Calendar</code> object.  The driver uses
9169     * the <code>Calendar</code> object to construct an SQL <code>TIMESTAMP</code> value,
9170     * which the driver then sends to the database.  With a
9171     * a <code>Calendar</code> object, the driver can calculate the timestamp
9172     * taking into account a custom timezone.  If no
9173     * <code>Calendar</code> object is specified, the driver uses the default
9174     * timezone, which is that of the virtual machine running the application.
9175     *
9176     * @param parameterName the name of the parameter
9177     * @param x the parameter value
9178     * @param cal the <code>Calendar</code> object the driver will use
9179     *            to construct the timestamp
9180     * @exception SQLException if a database access error occurs or
9181     * this method is called on a closed <code>CallableStatement</code>
9182     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9183     * this method
9184     * @see #getTimestamp
9185     * @since 1.4
9186     */
9187     public void setTimestamp(String parameterName, java.sql.Timestamp x, Calendar cal)
9188        throws SQLException{
9189         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9190    }
9191 
9192     /**
9193     * Sets the designated parameter to a <code>Reader</code> object.  The <code>reader</code> must contain  the number
9194                * of characters specified by length otherwise a <code>SQLException</code> will be
9195                * generated when the <code>CallableStatement</code> is executed.
9196               * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
9197               * because it informs the driver that the parameter value should be sent to
9198               * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9199               * driver may have to do extra work to determine whether the parameter
9200               * data should be send to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9201               * @param parameterName the name of the parameter to be set
9202               * @param reader An object that contains the data to set the parameter value to.
9203               * @param length the number of characters in the parameter data.
9204               * @throws SQLException if parameterIndex does not correspond to a parameter
9205               * marker in the SQL statement; if the length specified is less than zero;
9206               * a database access error occurs or
9207               * this method is called on a closed <code>CallableStatement</code>
9208               * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9209               * this method
9210               *
9211               * @since 1.6
9212               */
9213       public  void setClob(String parameterName, Reader reader, long length)
9214       throws SQLException{
9215         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9216    }
9217 
9218 
9219   /**
9220     * Sets the designated parameter to the given <code>java.sql.Clob</code> object.
9221     * The driver converts this to an SQL <code>CLOB</code> value when it
9222     * sends it to the database.
9223     *
9224     * @param parameterName the name of the parameter
9225     * @param x a <code>Clob</code> object that maps an SQL <code>CLOB</code> value
9226     * @exception SQLException if a database access error occurs or
9227     * this method is called on a closed <code>CallableStatement</code>
9228     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9229     * this method
9230     * @since 1.6
9231     */
9232     public void setClob (String parameterName, Clob x) throws SQLException{
9233         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9234    }
9235 
9236 
9237  /**
9238     * Sets the designated parameter to a <code>Reader</code> object.
9239     * This method differs from the <code>setCharacterStream (int, Reader)</code> method
9240     * because it informs the driver that the parameter value should be sent to
9241     * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9242     * driver may have to do extra work to determine whether the parameter
9243     * data should be send to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9244     *
9245     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9246     * it might be more efficient to use a version of
9247     * <code>setClob</code> which takes a length parameter.
9248     *
9249     * @param parameterName the name of the parameter
9250     * @param reader An object that contains the data to set the parameter value to.
9251     * @throws SQLException if a database access error occurs or this method is called on
9252     * a closed <code>CallableStatement</code>
9253     *
9254     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9255     * @since 1.6
9256     */
9257     public void setClob(String parameterName, Reader reader)
9258       throws SQLException{
9259         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9260    }
9261 
9262 
9263  /**
9264     * Sets the designated parameter to the given <code>java.sql.Date</code> value
9265     * using the default time zone of the virtual machine that is running
9266     * the application.
9267     * The driver converts this
9268     * to an SQL <code>DATE</code> value when it sends it to the database.
9269     *
9270     * @param parameterName the name of the parameter
9271     * @param x the parameter value
9272     * @exception SQLException if a database access error occurs or
9273     * this method is called on a closed <code>CallableStatement</code>
9274     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9275     * this method
9276     * @see #getDate
9277     * @since 1.4
9278     */
9279     public void setDate(String parameterName, java.sql.Date x)
9280        throws SQLException{
9281         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9282    }
9283 
9284 
9285  /**
9286     * Sets the designated parameter to the given <code>java.sql.Date</code> value,
9287     * using the given <code>Calendar</code> object.  The driver uses
9288     * the <code>Calendar</code> object to construct an SQL <code>DATE</code> value,
9289     * which the driver then sends to the database.  With a
9290     * a <code>Calendar</code> object, the driver can calculate the date
9291     * taking into account a custom timezone.  If no
9292     * <code>Calendar</code> object is specified, the driver uses the default
9293     * timezone, which is that of the virtual machine running the application.
9294     *
9295     * @param parameterName the name of the parameter
9296     * @param x the parameter value
9297     * @param cal the <code>Calendar</code> object the driver will use
9298     *            to construct the date
9299     * @exception SQLException if a database access error occurs or
9300     * this method is called on a closed <code>CallableStatement</code>
9301     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9302     * this method
9303     * @see #getDate
9304     * @since 1.4
9305     */
9306    public void setDate(String parameterName, java.sql.Date x, Calendar cal)
9307        throws SQLException{
9308         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9309    }
9310 
9311 
9312  /**
9313     * Sets the designated parameter to the given <code>java.sql.Time</code> value.
9314     * The driver converts this
9315     * to an SQL <code>TIME</code> value when it sends it to the database.
9316     *
9317     * @param parameterName the name of the parameter
9318     * @param x the parameter value
9319     * @exception SQLException if a database access error occurs or
9320     * this method is called on a closed <code>CallableStatement</code>
9321     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9322     * this method
9323     * @see #getTime
9324     * @since 1.4
9325     */
9326    public void setTime(String parameterName, java.sql.Time x)
9327        throws SQLException{
9328         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9329    }
9330 
9331 
9332  /**
9333     * Sets the designated parameter to the given <code>java.sql.Time</code> value,
9334     * using the given <code>Calendar</code> object.  The driver uses
9335     * the <code>Calendar</code> object to construct an SQL <code>TIME</code> value,
9336     * which the driver then sends to the database.  With a
9337     * a <code>Calendar</code> object, the driver can calculate the time
9338     * taking into account a custom timezone.  If no
9339     * <code>Calendar</code> object is specified, the driver uses the default
9340     * timezone, which is that of the virtual machine running the application.
9341     *
9342     * @param parameterName the name of the parameter
9343     * @param x the parameter value
9344     * @param cal the <code>Calendar</code> object the driver will use
9345     *            to construct the time
9346     * @exception SQLException if a database access error occurs or
9347     * this method is called on a closed <code>CallableStatement</code>
9348     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9349     * this method
9350     * @see #getTime
9351     * @since 1.4
9352     */
9353    public void setTime(String parameterName, java.sql.Time x, Calendar cal)
9354        throws SQLException{
9355         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9356    }
9357 
9358    /**
9359    * Sets the designated parameter to a <code>Reader</code> object.
9360    * This method differs from the <code>setCharacterStream (int, Reader)</code> method
9361    * because it informs the driver that the parameter value should be sent to
9362    * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9363    * driver may have to do extra work to determine whether the parameter
9364    * data should be sent to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9365    *
9366    * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9367    * it might be more efficient to use a version of
9368    * <code>setClob</code> which takes a length parameter.
9369    *
9370    * @param parameterIndex index of the first parameter is 1, the second is 2, ...
9371    * @param reader An object that contains the data to set the parameter value to.
9372    * @throws SQLException if a database access error occurs, this method is called on
9373    * a closed <code>PreparedStatement</code>or if parameterIndex does not correspond to a parameter
9374    * marker in the SQL statement
9375    *
9376    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9377    * @since 1.6
9378    */
9379    public void setClob(int parameterIndex, Reader reader)
9380      throws SQLException{
9381         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9382    }
9383 
9384     /**
9385    * Sets the designated parameter to a <code>Reader</code> object.  The reader must contain  the number
9386    * of characters specified by length otherwise a <code>SQLException</code> will be
9387    * generated when the <code>PreparedStatement</code> is executed.
9388    *This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
9389    * because it informs the driver that the parameter value should be sent to
9390    * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9391    * driver may have to do extra work to determine whether the parameter
9392    * data should be sent to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9393    * @param parameterIndex index of the first parameter is 1, the second is 2, ...
9394    * @param reader An object that contains the data to set the parameter value to.
9395    * @param length the number of characters in the parameter data.
9396    * @throws SQLException if a database access error occurs, this method is called on
9397    * a closed <code>PreparedStatement</code>, if parameterIndex does not correspond to a parameter
9398    * marker in the SQL statement, or if the length specified is less than zero.
9399    *
9400    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9401    * @since 1.6
9402    */
9403    public void setClob(int parameterIndex, Reader reader, long length)
9404      throws SQLException{
9405         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9406    }
9407 
9408 
9409  /**
9410     * Sets the designated parameter to a <code>InputStream</code> object.  The inputstream must contain  the number
9411     * of characters specified by length otherwise a <code>SQLException</code> will be
9412     * generated when the <code>PreparedStatement</code> is executed.
9413     * This method differs from the <code>setBinaryStream (int, InputStream, int)</code>
9414     * method because it informs the driver that the parameter value should be
9415     * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9416     * the driver may have to do extra work to determine whether the parameter
9417     * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9418     * @param parameterIndex index of the first parameter is 1,
9419     * the second is 2, ...
9420     * @param inputStream An object that contains the data to set the parameter
9421     * value to.
9422     * @param length the number of bytes in the parameter data.
9423     * @throws SQLException if a database access error occurs,
9424     * this method is called on a closed <code>PreparedStatement</code>,
9425     * if parameterIndex does not correspond
9426     * to a parameter marker in the SQL statement,  if the length specified
9427     * is less than zero or if the number of bytes in the inputstream does not match
9428     * the specfied length.
9429     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9430     *
9431     * @since 1.6
9432     */
9433     public void setBlob(int parameterIndex, InputStream inputStream, long length)
9434        throws SQLException{
9435         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9436    }
9437 
9438 
9439  /**
9440     * Sets the designated parameter to a <code>InputStream</code> object.
9441     * This method differs from the <code>setBinaryStream (int, InputStream)</code>
9442     * method because it informs the driver that the parameter value should be
9443     * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9444     * the driver may have to do extra work to determine whether the parameter
9445     * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9446     *
9447     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9448     * it might be more efficient to use a version of
9449     * <code>setBlob</code> which takes a length parameter.
9450     *
9451     * @param parameterIndex index of the first parameter is 1,
9452     * the second is 2, ...
9453     * @param inputStream An object that contains the data to set the parameter
9454     * value to.
9455     * @throws SQLException if a database access error occurs,
9456     * this method is called on a closed <code>PreparedStatement</code> or
9457     * if parameterIndex does not correspond
9458     * to a parameter marker in the SQL statement,
9459     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9460     *
9461     * @since 1.6
9462     */
9463     public void setBlob(int parameterIndex, InputStream inputStream)
9464        throws SQLException{
9465         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9466    }
9467 
9468 
9469  /**
9470     * Sets the designated parameter to a <code>InputStream</code> object.  The <code>inputstream</code> must contain  the number
9471      * of characters specified by length, otherwise a <code>SQLException</code> will be
9472      * generated when the <code>CallableStatement</code> is executed.
9473      * This method differs from the <code>setBinaryStream (int, InputStream, int)</code>
9474      * method because it informs the driver that the parameter value should be
9475      * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9476      * the driver may have to do extra work to determine whether the parameter
9477      * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9478      *
9479      * @param parameterName the name of the parameter to be set
9480      * the second is 2, ...
9481      *
9482      * @param inputStream An object that contains the data to set the parameter
9483      * value to.
9484      * @param length the number of bytes in the parameter data.
9485      * @throws SQLException  if parameterIndex does not correspond
9486      * to a parameter marker in the SQL statement,  or if the length specified
9487      * is less than zero; if the number of bytes in the inputstream does not match
9488      * the specfied length; if a database access error occurs or
9489      * this method is called on a closed <code>CallableStatement</code>
9490      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9491      * this method
9492      *
9493      * @since 1.6
9494      */
9495      public void setBlob(String parameterName, InputStream inputStream, long length)
9496         throws SQLException{
9497         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9498    }
9499 
9500 
9501  /**
9502     * Sets the designated parameter to the given <code>java.sql.Blob</code> object.
9503     * The driver converts this to an SQL <code>BLOB</code> value when it
9504     * sends it to the database.
9505     *
9506     * @param parameterName the name of the parameter
9507     * @param x a <code>Blob</code> object that maps an SQL <code>BLOB</code> value
9508     * @exception SQLException if a database access error occurs or
9509     * this method is called on a closed <code>CallableStatement</code>
9510     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9511     * this method
9512     * @since 1.6
9513     */
9514    public void setBlob (String parameterName, Blob x) throws SQLException{
9515         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9516    }
9517 
9518 
9519  /**
9520     * Sets the designated parameter to a <code>InputStream</code> object.
9521     * This method differs from the <code>setBinaryStream (int, InputStream)</code>
9522     * method because it informs the driver that the parameter value should be
9523     * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9524     * the driver may have to do extra work to determine whether the parameter
9525     * data should be send to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9526     *
9527     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9528     * it might be more efficient to use a version of
9529     * <code>setBlob</code> which takes a length parameter.
9530     *
9531     * @param parameterName the name of the parameter
9532     * @param inputStream An object that contains the data to set the parameter
9533     * value to.
9534     * @throws SQLException if a database access error occurs or
9535     * this method is called on a closed <code>CallableStatement</code>
9536     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9537     *
9538     * @since 1.6
9539     */
9540     public void setBlob(String parameterName, InputStream inputStream)
9541        throws SQLException{
9542         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9543    }
9544 
9545     /**
9546     * Sets the value of the designated parameter with the given object. The second
9547     * argument must be an object type; for integral values, the
9548     * <code>java.lang</code> equivalent objects should be used.
9549     *
9550     * <p>The given Java object will be converted to the given targetSqlType
9551     * before being sent to the database.
9552     *
9553     * If the object has a custom mapping (is of a class implementing the
9554     * interface <code>SQLData</code>),
9555     * the JDBC driver should call the method <code>SQLData.writeSQL</code> to write it
9556     * to the SQL data stream.
9557     * If, on the other hand, the object is of a class implementing
9558     * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>,  <code>NClob</code>,
9559     *  <code>Struct</code>, <code>java.net.URL</code>,
9560     * or <code>Array</code>, the driver should pass it to the database as a
9561     * value of the corresponding SQL type.
9562     * <P>
9563     * Note that this method may be used to pass datatabase-
9564     * specific abstract data types.
9565     *
9566     * @param parameterName the name of the parameter
9567     * @param x the object containing the input parameter value
9568     * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
9569     * sent to the database. The scale argument may further qualify this type.
9570     * @param scale for java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types,
9571     *          this is the number of digits after the decimal point.  For all other
9572     *          types, this value will be ignored.
9573     * @exception SQLException if a database access error occurs or
9574     * this method is called on a closed <code>CallableStatement</code>
9575     * @exception SQLFeatureNotSupportedException if <code>targetSqlType</code> is
9576     * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,
9577     * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,
9578     * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,
9579     *  <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
9580     * or  <code>STRUCT</code> data type and the JDBC driver does not support
9581     * this data type
9582     * @see Types
9583     * @see #getObject
9584     * @since 1.4
9585     */
9586     public void setObject(String parameterName, Object x, int targetSqlType, int scale)
9587        throws SQLException{
9588         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9589    }
9590 
9591 
9592 
9593  /**
9594     * Sets the value of the designated parameter with the given object.
9595     * This method is like the method <code>setObject</code>
9596     * above, except that it assumes a scale of zero.
9597     *
9598     * @param parameterName the name of the parameter
9599     * @param x the object containing the input parameter value
9600     * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
9601     *                      sent to the database
9602     * @exception SQLException if a database access error occurs or
9603     * this method is called on a closed <code>CallableStatement</code>
9604     * @exception SQLFeatureNotSupportedException if <code>targetSqlType</code> is
9605     * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,
9606     * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,
9607     * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,
9608     *  <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
9609     * or  <code>STRUCT</code> data type and the JDBC driver does not support
9610     * this data type
9611     * @see #getObject
9612     * @since 1.4
9613     */
9614     public void setObject(String parameterName, Object x, int targetSqlType)
9615        throws SQLException{
9616         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9617    }
9618 
9619 
9620  /**
9621    * Sets the value of the designated parameter with the given object.
9622    * The second parameter must be of type <code>Object</code>; therefore, the
9623    * <code>java.lang</code> equivalent objects should be used for built-in types.
9624    *
9625    * <p>The JDBC specification specifies a standard mapping from
9626    * Java <code>Object</code> types to SQL types.  The given argument
9627    * will be converted to the corresponding SQL type before being
9628    * sent to the database.
9629    *
9630    * <p>Note that this method may be used to pass datatabase-
9631    * specific abstract data types, by using a driver-specific Java
9632    * type.
9633    *
9634    * If the object is of a class implementing the interface <code>SQLData</code>,
9635    * the JDBC driver should call the method <code>SQLData.writeSQL</code>
9636    * to write it to the SQL data stream.
9637    * If, on the other hand, the object is of a class implementing
9638    * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>,  <code>NClob</code>,
9639    *  <code>Struct</code>, <code>java.net.URL</code>,
9640    * or <code>Array</code>, the driver should pass it to the database as a
9641    * value of the corresponding SQL type.
9642    * <P>
9643    * This method throws an exception if there is an ambiguity, for example, if the
9644    * object is of a class implementing more than one of the interfaces named above.
9645    *
9646    * @param parameterName the name of the parameter
9647    * @param x the object containing the input parameter value
9648    * @exception SQLException if a database access error occurs,
9649    * this method is called on a closed <code>CallableStatement</code> or if the given
9650    *            <code>Object</code> parameter is ambiguous
9651    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9652    * this method
9653    * @see #getObject
9654    * @since 1.4
9655    */
9656    public void setObject(String parameterName, Object x) throws SQLException{
9657         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9658    }
9659 
9660     /**
9661     * Sets the designated parameter to the given input stream, which will have
9662     * the specified number of bytes.
9663     * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
9664     * parameter, it may be more practical to send it via a
9665     * <code>java.io.InputStream</code>. Data will be read from the stream
9666     * as needed until end-of-file is reached.  The JDBC driver will
9667     * do any necessary conversion from ASCII to the database char format.
9668     *
9669     * <P><B>Note:</B> This stream object can either be a standard
9670     * Java stream object or your own subclass that implements the
9671     * standard interface.
9672     *
9673     * @param parameterName the name of the parameter
9674     * @param x the Java input stream that contains the ASCII parameter value
9675     * @param length the number of bytes in the stream
9676     * @exception SQLException if a database access error occurs or
9677     * this method is called on a closed <code>CallableStatement</code>
9678     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9679     * this method
9680     * @since 1.4
9681     */
9682    public void setAsciiStream(String parameterName, java.io.InputStream x, int length)
9683        throws SQLException{
9684         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9685    }
9686 
9687 
9688  /**
9689     * Sets the designated parameter to the given input stream, which will have
9690     * the specified number of bytes.
9691     * When a very large binary value is input to a <code>LONGVARBINARY</code>
9692     * parameter, it may be more practical to send it via a
9693     * <code>java.io.InputStream</code> object. The data will be read from the stream
9694     * as needed until end-of-file is reached.
9695     *
9696     * <P><B>Note:</B> This stream object can either be a standard
9697     * Java stream object or your own subclass that implements the
9698     * standard interface.
9699     *
9700     * @param parameterName the name of the parameter
9701     * @param x the java input stream which contains the binary parameter value
9702     * @param length the number of bytes in the stream
9703     * @exception SQLException if a database access error occurs or
9704     * this method is called on a closed <code>CallableStatement</code>
9705     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9706     * this method
9707     * @since 1.4
9708     */
9709    public void setBinaryStream(String parameterName, java.io.InputStream x,
9710                         int length) throws SQLException{
9711         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9712    }
9713 
9714 
9715   /**
9716     * Sets the designated parameter to the given <code>Reader</code>
9717     * object, which is the given number of characters long.
9718     * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
9719     * parameter, it may be more practical to send it via a
9720     * <code>java.io.Reader</code> object. The data will be read from the stream
9721     * as needed until end-of-file is reached.  The JDBC driver will
9722     * do any necessary conversion from UNICODE to the database char format.
9723     *
9724     * <P><B>Note:</B> This stream object can either be a standard
9725     * Java stream object or your own subclass that implements the
9726     * standard interface.
9727     *
9728     * @param parameterName the name of the parameter
9729     * @param reader the <code>java.io.Reader</code> object that
9730     *        contains the UNICODE data used as the designated parameter
9731     * @param length the number of characters in the stream
9732     * @exception SQLException if a database access error occurs or
9733     * this method is called on a closed <code>CallableStatement</code>
9734     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9735     * this method
9736     * @since 1.4
9737     */
9738    public void setCharacterStream(String parameterName,
9739                            java.io.Reader reader,
9740                            int length) throws SQLException{
9741         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9742    }
9743 
9744 
9745   /**
9746    * Sets the designated parameter to the given input stream.
9747    * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
9748    * parameter, it may be more practical to send it via a
9749    * <code>java.io.InputStream</code>. Data will be read from the stream
9750    * as needed until end-of-file is reached.  The JDBC driver will
9751    * do any necessary conversion from ASCII to the database char format.
9752    *
9753    * <P><B>Note:</B> This stream object can either be a standard
9754    * Java stream object or your own subclass that implements the
9755    * standard interface.
9756    * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9757    * it might be more efficient to use a version of
9758    * <code>setAsciiStream</code> which takes a length parameter.
9759    *
9760    * @param parameterName the name of the parameter
9761    * @param x the Java input stream that contains the ASCII parameter value
9762    * @exception SQLException if a database access error occurs or
9763    * this method is called on a closed <code>CallableStatement</code>
9764    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9765      * @since 1.6
9766   */
9767   public void setAsciiStream(String parameterName, java.io.InputStream x)
9768           throws SQLException{
9769         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9770    }
9771 
9772 
9773  /**
9774     * Sets the designated parameter to the given input stream.
9775     * When a very large binary value is input to a <code>LONGVARBINARY</code>
9776     * parameter, it may be more practical to send it via a
9777     * <code>java.io.InputStream</code> object. The data will be read from the
9778     * stream as needed until end-of-file is reached.
9779     *
9780     * <P><B>Note:</B> This stream object can either be a standard
9781     * Java stream object or your own subclass that implements the
9782     * standard interface.
9783     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9784     * it might be more efficient to use a version of
9785     * <code>setBinaryStream</code> which takes a length parameter.
9786     *
9787     * @param parameterName the name of the parameter
9788     * @param x the java input stream which contains the binary parameter value
9789     * @exception SQLException if a database access error occurs or
9790     * this method is called on a closed <code>CallableStatement</code>
9791     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9792     * @since 1.6
9793     */
9794    public void setBinaryStream(String parameterName, java.io.InputStream x)
9795    throws SQLException{
9796         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9797    }
9798 
9799 
9800 
9801  /**
9802     * Sets the designated parameter to the given <code>Reader</code>
9803     * object.
9804     * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
9805     * parameter, it may be more practical to send it via a
9806     * <code>java.io.Reader</code> object. The data will be read from the stream
9807     * as needed until end-of-file is reached.  The JDBC driver will
9808     * do any necessary conversion from UNICODE to the database char format.
9809     *
9810     * <P><B>Note:</B> This stream object can either be a standard
9811     * Java stream object or your own subclass that implements the
9812     * standard interface.
9813     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9814     * it might be more efficient to use a version of
9815     * <code>setCharacterStream</code> which takes a length parameter.
9816     *
9817     * @param parameterName the name of the parameter
9818     * @param reader the <code>java.io.Reader</code> object that contains the
9819     *        Unicode data
9820     * @exception SQLException if a database access error occurs or
9821     * this method is called on a closed <code>CallableStatement</code>
9822     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9823     * @since 1.6
9824     */
9825    public void setCharacterStream(String parameterName,
9826                          java.io.Reader reader) throws SQLException{
9827         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9828    }
9829 
9830    /**
9831     * Sets the designated parameter to the given
9832     * <code>java.math.BigDecimal</code> value.
9833     * The driver converts this to an SQL <code>NUMERIC</code> value when
9834     * it sends it to the database.
9835     *
9836     * @param parameterName the name of the parameter
9837     * @param x the parameter value
9838     * @exception SQLException if a database access error occurs or
9839     * this method is called on a closed <code>CallableStatement</code>
9840     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9841     * this method
9842     * @see #getBigDecimal
9843     * @since 1.4
9844     */
9845    public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException{
9846         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9847    }
9848 
9849 
9850 
9851  /**
9852     * Sets the designated parameter to the given Java <code>String</code> value.
9853     * The driver converts this
9854     * to an SQL <code>VARCHAR</code> or <code>LONGVARCHAR</code> value
9855     * (depending on the argument's
9856     * size relative to the driver's limits on <code>VARCHAR</code> values)
9857     * when it sends it to the database.
9858     *
9859     * @param parameterName the name of the parameter
9860     * @param x the parameter value
9861     * @exception SQLException if a database access error occurs or
9862     * this method is called on a closed <code>CallableStatement</code>
9863     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9864     * this method
9865     * @see #getString
9866     * @since 1.4
9867     */
9868    public void setString(String parameterName, String x) throws SQLException{
9869         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9870    }
9871 
9872 
9873 
9874  /**
9875     * Sets the designated parameter to the given Java array of bytes.
9876     * The driver converts this to an SQL <code>VARBINARY</code> or
9877     * <code>LONGVARBINARY</code> (depending on the argument's size relative
9878     * to the driver's limits on <code>VARBINARY</code> values) when it sends
9879     * it to the database.
9880     *
9881     * @param parameterName the name of the parameter
9882     * @param x the parameter value
9883     * @exception SQLException if a database access error occurs or
9884     * this method is called on a closed <code>CallableStatement</code>
9885     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9886     * this method
9887     * @see #getBytes
9888     * @since 1.4
9889     */
9890    public void setBytes(String parameterName, byte x[]) throws SQLException{
9891         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9892    }
9893 
9894 
9895 
9896  /**
9897     * Sets the designated parameter to the given <code>java.sql.Timestamp</code> value.
9898     * The driver
9899     * converts this to an SQL <code>TIMESTAMP</code> value when it sends it to the
9900     * database.
9901     *
9902     * @param parameterName the name of the parameter
9903     * @param x the parameter value
9904     * @exception SQLException if a database access error occurs or
9905     * this method is called on a closed <code>CallableStatement</code>
9906     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9907     * this method
9908     * @see #getTimestamp
9909     * @since 1.4
9910     */
9911    public void setTimestamp(String parameterName, java.sql.Timestamp x)
9912        throws SQLException{
9913         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9914    }
9915 
9916     /**
9917     * Sets the designated parameter to SQL <code>NULL</code>.
9918     *
9919     * <P><B>Note:</B> You must specify the parameter's SQL type.
9920     *
9921     * @param parameterName the name of the parameter
9922     * @param sqlType the SQL type code defined in <code>java.sql.Types</code>
9923     * @exception SQLException if a database access error occurs or
9924     * this method is called on a closed <code>CallableStatement</code>
9925     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9926     * this method
9927     * @since 1.4
9928     */
9929    public void setNull(String parameterName, int sqlType) throws SQLException {
9930         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9931    }
9932 
9933 
9934  /**
9935     * Sets the designated parameter to SQL <code>NULL</code>.
9936     * This version of the method <code>setNull</code> should
9937     * be used for user-defined types and REF type parameters.  Examples
9938     * of user-defined types include: STRUCT, DISTINCT, JAVA_OBJECT, and
9939     * named array types.
9940     *
9941     * <P><B>Note:</B> To be portable, applications must give the
9942     * SQL type code and the fully-qualified SQL type name when specifying
9943     * a NULL user-defined or REF parameter.  In the case of a user-defined type
9944     * the name is the type name of the parameter itself.  For a REF
9945     * parameter, the name is the type name of the referenced type.  If
9946     * a JDBC driver does not need the type code or type name information,
9947     * it may ignore it.
9948     *
9949     * Although it is intended for user-defined and Ref parameters,
9950     * this method may be used to set a null parameter of any JDBC type.
9951     * If the parameter does not have a user-defined or REF type, the given
9952     * typeName is ignored.
9953     *
9954     *
9955     * @param parameterName the name of the parameter
9956     * @param sqlType a value from <code>java.sql.Types</code>
9957     * @param typeName the fully-qualified name of an SQL user-defined type;
9958     *        ignored if the parameter is not a user-defined type or
9959     *        SQL <code>REF</code> value
9960     * @exception SQLException if a database access error occurs or
9961     * this method is called on a closed <code>CallableStatement</code>
9962     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9963     * this method
9964     * @since 1.4
9965     */
9966    public void setNull (String parameterName, int sqlType, String typeName)
9967        throws SQLException{
9968         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9969    }
9970 
9971 
9972 
9973  /**
9974     * Sets the designated parameter to the given Java <code>boolean</code> value.
9975     * The driver converts this
9976     * to an SQL <code>BIT</code> or <code>BOOLEAN</code> value when it sends it to the database.
9977     *
9978     * @param parameterName the name of the parameter
9979     * @param x the parameter value
9980     * @exception SQLException if a database access error occurs or
9981     * this method is called on a closed <code>CallableStatement</code>
9982     * @see #getBoolean
9983     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9984     * this method
9985     * @since 1.4
9986     */
9987    public void setBoolean(String parameterName, boolean x) throws SQLException{
9988         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9989    }
9990 
9991 
9992 
9993  /**
9994     * Sets the designated parameter to the given Java <code>byte</code> value.
9995     * The driver converts this
9996     * to an SQL <code>TINYINT</code> value when it sends it to the database.
9997     *
9998     * @param parameterName the name of the parameter
9999     * @param x the parameter value
10000     * @exception SQLException if a database access error occurs or
10001     * this method is called on a closed <code>CallableStatement</code>
10002     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10003     * this method
10004     * @see #getByte
10005     * @since 1.4
10006     */
10007    public void setByte(String parameterName, byte x) throws SQLException{
10008         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10009    }
10010 
10011 
10012 
10013  /**
10014     * Sets the designated parameter to the given Java <code>short</code> value.
10015     * The driver converts this
10016     * to an SQL <code>SMALLINT</code> value when it sends it to the database.
10017     *
10018     * @param parameterName the name of the parameter
10019     * @param x the parameter value
10020     * @exception SQLException if a database access error occurs or
10021     * this method is called on a closed <code>CallableStatement</code>
10022     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10023     * this method
10024     * @see #getShort
10025     * @since 1.4
10026     */
10027    public void setShort(String parameterName, short x) throws SQLException{
10028         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10029    }
10030 
10031 
10032  /**
10033     * Sets the designated parameter to the given Java <code>int</code> value.
10034     * The driver converts this
10035     * to an SQL <code>INTEGER</code> value when it sends it to the database.
10036     *
10037     * @param parameterName the name of the parameter
10038     * @param x the parameter value
10039     * @exception SQLException if a database access error occurs or
10040     * this method is called on a closed <code>CallableStatement</code>
10041     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10042     * this method
10043     * @see #getInt
10044     * @since 1.4
10045     */
10046    public void setInt(String parameterName, int x) throws SQLException{
10047         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10048    }
10049 
10050 
10051  /**
10052     * Sets the designated parameter to the given Java <code>long</code> value.
10053     * The driver converts this
10054     * to an SQL <code>BIGINT</code> value when it sends it to the database.
10055     *
10056     * @param parameterName the name of the parameter
10057     * @param x the parameter value
10058     * @exception SQLException if a database access error occurs or
10059     * this method is called on a closed <code>CallableStatement</code>
10060     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10061     * this method
10062     * @see #getLong
10063     * @since 1.4
10064     */
10065    public void setLong(String parameterName, long x) throws SQLException{
10066         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10067    }
10068 
10069 
10070  /**
10071     * Sets the designated parameter to the given Java <code>float</code> value.
10072     * The driver converts this
10073     * to an SQL <code>FLOAT</code> value when it sends it to the database.
10074     *
10075     * @param parameterName the name of the parameter
10076     * @param x the parameter value
10077     * @exception SQLException if a database access error occurs or
10078     * this method is called on a closed <code>CallableStatement</code>
10079     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10080     * this method
10081     * @see #getFloat
10082     * @since 1.4
10083     */
10084    public void setFloat(String parameterName, float x) throws SQLException{
10085         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10086    }
10087 
10088 
10089  /**
10090     * Sets the designated parameter to the given Java <code>double</code> value.
10091     * The driver converts this
10092     * to an SQL <code>DOUBLE</code> value when it sends it to the database.
10093     *
10094     * @param parameterName the name of the parameter
10095     * @param x the parameter value
10096     * @exception SQLException if a database access error occurs or
10097     * this method is called on a closed <code>CallableStatement</code>
10098     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10099     * this method
10100     * @see #getDouble
10101     * @since 1.4
10102     */
10103    public void setDouble(String parameterName, double x) throws SQLException{
10104         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10105    }
10106 
10107    /**
10108      * This method re populates the resBundle
10109      * during the deserialization process
10110      *
10111      */
10112     private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
10113         // Default state initialization happens here
10114         ois.defaultReadObject();
10115         // Initialization of transient Res Bundle happens here .
10116         try {
10117            resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
10118         } catch(IOException ioe) {
10119             throw new RuntimeException(ioe);
10120         }
10121 
10122     }
10123 
10124     //------------------------- JDBC 4.1 -----------------------------------
10125     public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
10126         throw new SQLFeatureNotSupportedException("Not supported yet.");
10127     }
10128 
10129     public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
10130         throw new SQLFeatureNotSupportedException("Not supported yet.");
10131     }
10132 
10133     static final long serialVersionUID =1884577171200622428L;
10134 }