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     public void acceptChanges() throws SyncProviderException {
 869         if (onInsertRow == true) {
 870             throw new SyncProviderException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
 871         }
 872 
 873         int saveCursorPos = cursorPos;
 874         boolean success = false;
 875         boolean conflict = false;
 876 
 877         try {
 878             if (rowSetWriter != null) {
 879                 saveCursorPos = cursorPos;
 880                 conflict = rowSetWriter.writeData((RowSetInternal)this);
 881                 cursorPos = saveCursorPos;
 882             }
 883 
 884             if ((tXWriter) && this.COMMIT_ON_ACCEPT_CHANGES) {
 885                 // do commit/rollback's here
 886                 if (!conflict) {
 887                     tWriter = (TransactionalWriter)rowSetWriter;
 888                     tWriter.rollback();
 889                     success = false;
 890                 } else {
 891                     tWriter = (TransactionalWriter)rowSetWriter;
 892                     if (tWriter instanceof CachedRowSetWriter) {
 893                         ((CachedRowSetWriter)tWriter).commit(this, updateOnInsert);
 894                     } else {
 895                         tWriter.commit();
 896                     }
 897 
 898                     success = true;
 899                 }
 900             }
 901 
 902             if (success == true) {
 903                 setOriginal();
 904             } else if (!(success) && !(this.COMMIT_ON_ACCEPT_CHANGES)) {
 905                 throw new SyncProviderException(resBundle.handleGetObject("cachedrowsetimpl.accfailed").toString());
 906             }
 907 
 908         } catch (SyncProviderException spe) {
 909                throw spe;
 910         } catch (SQLException e) {
 911             e.printStackTrace();
 912             throw new SyncProviderException(e.getMessage());
 913         } catch (SecurityException e) {
 914             throw new SyncProviderException(e.getMessage());
 915         }
 916     }
 917 
 918     /**
 919      * Propagates all row update, insert, and delete changes to the
 920      * data source backing this <code>CachedRowSetImpl</code> object
 921      * using the given <code>Connection</code> object.
 922      * <P>
 923      * The reference implementation <code>RIOptimisticProvider</code>
 924      * modifies its synchronization to a write back function given
 925      * the updated connection
 926      * The reference implementation modifies its synchronization behaviour
 927      * via the <code>SyncProvider</code> to ensure the synchronization
 928      * occurs according to the updated JDBC <code>Connection</code>
 929      * properties.
 930      *
 931      * @param con a standard JDBC <code>Connection</code> object
 932      * @throws SQLException if the cursor is on the insert row or the underlying
 933      *                   synchronization provider fails to commit the updates
 934      *                   back to the data source
 935      * @see #acceptChanges
 936      * @see javax.sql.RowSetWriter
 937      * @see javax.sql.rowset.spi.SyncFactory
 938      * @see javax.sql.rowset.spi.SyncProvider
 939      */
 940     public void acceptChanges(Connection con) throws SyncProviderException{
 941 
 942       setConnection(con);
 943       acceptChanges();
 944 
 945     }
 946 
 947     /**
 948      * Restores this <code>CachedRowSetImpl</code> object to its original state,
 949      * that is, its state before the last set of changes.
 950      * <P>
 951      * Before returning, this method moves the cursor before the first row
 952      * and sends a <code>rowSetChanged</code> event to all registered
 953      * listeners.
 954      * @throws SQLException if an error is occurs rolling back the RowSet
 955      *           state to the definied original value.
 956      * @see javax.sql.RowSetListener#rowSetChanged
 957      */
 958     public void restoreOriginal() throws SQLException {
 959         Row currentRow;
 960         for (Iterator i = rvh.iterator(); i.hasNext();) {
 961             currentRow = (Row)i.next();
 962             if (currentRow.getInserted() == true) {
 963                 i.remove();
 964                 --numRows;
 965             } else {
 966                 if (currentRow.getDeleted() == true) {
 967                     currentRow.clearDeleted();
 968                 }
 969                 if (currentRow.getUpdated() == true) {
 970                     currentRow.clearUpdated();
 971                 }
 972             }
 973         }
 974         // move to before the first
 975         cursorPos = 0;
 976 
 977         // notify any listeners
 978         notifyRowSetChanged();
 979     }
 980 
 981     /**
 982      * Releases the current contents of this <code>CachedRowSetImpl</code>
 983      * object and sends a <code>rowSetChanged</code> event object to all
 984      * registered listeners.
 985      *
 986      * @throws SQLException if an error occurs flushing the contents of
 987      *           RowSet.
 988      * @see javax.sql.RowSetListener#rowSetChanged
 989      */
 990     public void release() throws SQLException {
 991         initContainer();
 992         notifyRowSetChanged();
 993     }
 994 
 995     /**
 996      * Cancels deletion of the current row and notifies listeners that
 997      * a row has changed.
 998      * <P>
 999      * Note:  This method can be ignored if deleted rows are not being shown,
1000      * which is the normal case.
1001      *
1002      * @throws SQLException if the cursor is not on a valid row
1003      */
1004     public void undoDelete() throws SQLException {
1005         if (getShowDeleted() == false) {
1006             return;
1007         }
1008         // make sure we are on a row
1009         checkCursor();
1010 
1011         // don't want this to happen...
1012         if (onInsertRow == true) {
1013             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1014         }
1015 
1016         Row currentRow = (Row)getCurrentRow();
1017         if (currentRow.getDeleted() == true) {
1018             currentRow.clearDeleted();
1019             --numDeleted;
1020             notifyRowChanged();
1021         }
1022     }
1023 
1024     /**
1025      * Immediately removes the current row from this
1026      * <code>CachedRowSetImpl</code> object if the row has been inserted, and
1027      * also notifies listeners the a row has changed.  An exception is thrown
1028      * if the row is not a row that has been inserted or the cursor is before
1029      * the first row, after the last row, or on the insert row.
1030      * <P>
1031      * This operation cannot be undone.
1032      *
1033      * @throws SQLException if an error occurs,
1034      *                         the cursor is not on a valid row,
1035      *                         or the row has not been inserted
1036      */
1037     public void undoInsert() throws SQLException {
1038         // make sure we are on a row
1039         checkCursor();
1040 
1041         // don't want this to happen...
1042         if (onInsertRow == true) {
1043             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1044         }
1045 
1046         Row currentRow = (Row)getCurrentRow();
1047         if (currentRow.getInserted() == true) {
1048             rvh.remove(cursorPos-1);
1049             --numRows;
1050             notifyRowChanged();
1051         } else {
1052             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.illegalop").toString());
1053         }
1054     }
1055 
1056     /**
1057      * Immediately reverses the last update operation if the
1058      * row has been modified. This method can be
1059      * called to reverse updates on a all columns until all updates in a row have
1060      * been rolled back to their originating state since the last synchronization
1061      * (<code>acceptChanges</code>) or population. This method may also be called
1062      * while performing updates to the insert row.
1063      * <P>
1064      * <code>undoUpdate</code may be called at any time during the life-time of a
1065      * rowset, however after a synchronization has occurs this method has no
1066      * affect until further modification to the RowSet data occurs.
1067      *
1068      * @throws SQLException if cursor is before the first row, after the last
1069      *     row in rowset.
1070      * @see #undoDelete
1071      * @see #undoInsert
1072      * @see java.sql.ResultSet#cancelRowUpdates
1073      */
1074     public void undoUpdate() throws SQLException {
1075         // if on insert row, cancel the insert row
1076         // make the insert row flag,
1077         // cursorPos back to the current row
1078         moveToCurrentRow();
1079 
1080         // else if not on insert row
1081         // call undoUpdate or undoInsert
1082         undoDelete();
1083 
1084         undoInsert();
1085 
1086     }
1087 
1088     //--------------------------------------------------------------------
1089     // Views
1090     //--------------------------------------------------------------------
1091 
1092     /**
1093      * Returns a new <code>RowSet</code> object backed by the same data as
1094      * that of this <code>CachedRowSetImpl</code> object and sharing a set of cursors
1095      * with it. This allows cursors to interate over a shared set of rows, providing
1096      * multiple views of the underlying data.
1097      *
1098      * @return a <code>RowSet</code> object that is a copy of this <code>CachedRowSetImpl</code>
1099      * object and shares a set of cursors with it
1100      * @throws SQLException if an error occurs or cloning is
1101      *                         not supported
1102      * @see javax.sql.RowSetEvent
1103      * @see javax.sql.RowSetListener
1104      */
1105     public RowSet createShared() throws SQLException {
1106         RowSet clone;
1107         try {
1108             clone = (RowSet)clone();
1109         } catch (CloneNotSupportedException ex) {
1110             throw new SQLException(ex.getMessage());
1111         }
1112         return clone;
1113     }
1114 
1115     /**
1116      * Returns a new <code>RowSet</code> object containing by the same data
1117      * as this <code>CachedRowSetImpl</code> object.  This method
1118      * differs from the method <code>createCopy</code> in that it throws a
1119      * <code>CloneNotSupportedException</code> object instead of an
1120      * <code>SQLException</code> object, as the method <code>createShared</code>
1121      * does.  This <code>clone</code>
1122      * method is called internally by the method <code>createShared</code>,
1123      * which catches the <code>CloneNotSupportedException</code> object
1124      * and in turn throws a new <code>SQLException</code> object.
1125      *
1126      * @return a copy of this <code>CachedRowSetImpl</code> object
1127      * @throws CloneNotSupportedException if an error occurs when
1128      * attempting to clone this <code>CachedRowSetImpl</code> object
1129      * @see #createShared
1130      */
1131     protected Object clone() throws CloneNotSupportedException  {
1132         return (super.clone());
1133     }
1134 
1135     /**
1136      * Creates a <code>RowSet</code> object that is a deep copy of
1137      * this <code>CachedRowSetImpl</code> object's data, including
1138      * constraints.  Updates made
1139      * on a copy are not visible to the original rowset;
1140      * a copy of a rowset is completely independent from the original.
1141      * <P>
1142      * Making a copy saves the cost of creating an identical rowset
1143      * from first principles, which can be quite expensive.
1144      * For example, it can eliminate the need to query a
1145      * remote database server.
1146      * @return a new <code>CachedRowSet</code> object that is a deep copy
1147      *           of this <code>CachedRowSet</code> object and is
1148      *           completely independent from this <code>CachedRowSetImpl</code>
1149      *           object.
1150      * @throws SQLException if an error occurs in generating the copy of this
1151      *           of the <code>CachedRowSetImpl</code>
1152      * @see #createShared
1153      * @see javax.sql.RowSetEvent
1154      * @see javax.sql.RowSetListener
1155      */
1156     public CachedRowSet createCopy() throws SQLException {
1157         ObjectOutputStream out;
1158         ByteArrayOutputStream bOut = new ByteArrayOutputStream();
1159         try {
1160             out = new ObjectOutputStream(bOut);
1161             out.writeObject(this);
1162         } catch (IOException ex) {
1163             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1164         }
1165 
1166         ObjectInputStream in;
1167 
1168         try {
1169             ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
1170             in = new ObjectInputStream(bIn);
1171         } catch (StreamCorruptedException ex) {
1172             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1173         } catch (IOException ex) {
1174             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1175         }
1176 
1177         try {
1178             //return ((CachedRowSet)(in.readObject()));
1179             CachedRowSetImpl crsTemp = (CachedRowSetImpl)in.readObject();
1180             crsTemp.resBundle = this.resBundle;
1181             return ((CachedRowSet)crsTemp);
1182 
1183         } catch (ClassNotFoundException ex) {
1184             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1185         } catch (OptionalDataException ex) {
1186             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1187         } catch (IOException ex) {
1188             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1189         }
1190     }
1191 
1192     /**
1193      * Creates a <code>RowSet</code> object that is a copy of
1194      * this <code>CachedRowSetImpl</code> object's table structure
1195      * and the constraints only.
1196      * There will be no data in the object being returned.
1197      * Updates made on a copy are not visible to the original rowset.
1198      * <P>
1199      * This helps in getting the underlying XML schema which can
1200      * be used as the basis for populating a <code>WebRowSet</code>.
1201      *
1202      * @return a new <code>CachedRowSet</code> object that is a copy
1203      * of this <code>CachedRowSetImpl</code> object's schema and
1204      * retains all the constraints on the original rowset but contains
1205      * no data
1206      * @throws SQLException if an error occurs in generating the copy
1207      * of the <code>CachedRowSet</code> object
1208      * @see #createShared
1209      * @see #createCopy
1210      * @see #createCopyNoConstraints
1211      * @see javax.sql.RowSetEvent
1212      * @see javax.sql.RowSetListener
1213      */
1214     public CachedRowSet createCopySchema() throws SQLException {
1215         // Copy everything except data i.e all constraints
1216 
1217         // Store the number of rows of "this"
1218         // and make numRows equals zero.
1219         // and make data also zero.
1220         int nRows = numRows;
1221         numRows = 0;
1222 
1223         CachedRowSet crs = this.createCopy();
1224 
1225         // reset this object back to number of rows.
1226         numRows = nRows;
1227 
1228         return crs;
1229     }
1230 
1231     /**
1232      * Creates a <code>CachedRowSet</code> object that is a copy of
1233      * this <code>CachedRowSetImpl</code> object's data only.
1234      * All constraints set in this object will not be there
1235      * in the returning object.  Updates made
1236      * on a copy are not visible to the original rowset.
1237      *
1238      * @return a new <code>CachedRowSet</code> object that is a deep copy
1239      * of this <code>CachedRowSetImpl</code> object and is
1240      * completely independent from this <code>CachedRowSetImpl</code> object
1241      * @throws SQLException if an error occurs in generating the copy of the
1242      * of the <code>CachedRowSet</code>
1243      * @see #createShared
1244      * @see #createCopy
1245      * @see #createCopySchema
1246      * @see javax.sql.RowSetEvent
1247      * @see javax.sql.RowSetListener
1248      */
1249     public CachedRowSet createCopyNoConstraints() throws SQLException {
1250         // Copy the whole data ONLY without any constraints.
1251         CachedRowSetImpl crs;
1252         crs = (CachedRowSetImpl)this.createCopy();
1253 
1254         crs.initProperties();
1255         try {
1256             crs.unsetMatchColumn(crs.getMatchColumnIndexes());
1257         } catch(SQLException sqle) {
1258             //do nothing, if the setMatchColumn is not set.
1259         }
1260 
1261         try {
1262             crs.unsetMatchColumn(crs.getMatchColumnNames());
1263         } catch(SQLException sqle) {
1264             //do nothing, if the setMatchColumn is not set.
1265         }
1266 
1267         return crs;
1268     }
1269 
1270     /**
1271      * Converts this <code>CachedRowSetImpl</code> object to a collection
1272      * of tables. The sample implementation utilitizes the <code>TreeMap</code>
1273      * collection type.
1274      * This class guarantees that the map will be in ascending key order,
1275      * sorted according to the natural order for the key's class.
1276      *
1277      * @return a <code>Collection</code> object consisting of tables,
1278      *         each of which is a copy of a row in this
1279      *         <code>CachedRowSetImpl</code> object
1280      * @throws SQLException if an error occurs in generating the collection
1281      * @see #toCollection(int)
1282      * @see #toCollection(String)
1283      * @see java.util.TreeMap
1284      */
1285     public Collection<?> toCollection() throws SQLException {
1286 
1287         TreeMap<Integer, Object> tMap = new TreeMap<>();
1288 
1289         for (int i = 0; i<numRows; i++) {
1290             tMap.put(Integer.valueOf(i), rvh.get(i));
1291         }
1292 
1293         return (tMap.values());
1294     }
1295 
1296     /**
1297      * Returns the specified column of this <code>CachedRowSetImpl</code> object
1298      * as a <code>Collection</code> object.  This method makes a copy of the
1299      * column's data and utilitizes the <code>Vector</code> to establish the
1300      * collection. The <code>Vector</code> class implements a growable array
1301      * objects allowing the individual components to be accessed using an
1302      * an integer index similar to that of an array.
1303      *
1304      * @return a <code>Collection</code> object that contains the value(s)
1305      *         stored in the specified column of this
1306      *         <code>CachedRowSetImpl</code>
1307      *         object
1308      * @throws SQLException if an error occurs generated the collection; or
1309      *          an invalid column is provided.
1310      * @see #toCollection()
1311      * @see #toCollection(String)
1312      * @see java.util.Vector
1313      */
1314     public Collection<?> toCollection(int column) throws SQLException {
1315 
1316         int nRows = numRows;
1317         Vector<Object> vec = new Vector<>(nRows);
1318 
1319         // create a copy
1320         CachedRowSetImpl crsTemp;
1321         crsTemp = (CachedRowSetImpl) this.createCopy();
1322 
1323         while(nRows!=0) {
1324             crsTemp.next();
1325             vec.add(crsTemp.getObject(column));
1326             nRows--;
1327         }
1328 
1329         return (Collection)vec;
1330     }
1331 
1332     /**
1333      * Returns the specified column of this <code>CachedRowSetImpl</code> object
1334      * as a <code>Collection</code> object.  This method makes a copy of the
1335      * column's data and utilitizes the <code>Vector</code> to establish the
1336      * collection. The <code>Vector</code> class implements a growable array
1337      * objects allowing the individual components to be accessed using an
1338      * an integer index similar to that of an array.
1339      *
1340      * @return a <code>Collection</code> object that contains the value(s)
1341      *         stored in the specified column of this
1342      *         <code>CachedRowSetImpl</code>
1343      *         object
1344      * @throws SQLException if an error occurs generated the collection; or
1345      *          an invalid column is provided.
1346      * @see #toCollection()
1347      * @see #toCollection(int)
1348      * @see java.util.Vector
1349      */
1350     public Collection<?> toCollection(String column) throws SQLException {
1351         return toCollection(getColIdxByName(column));
1352     }
1353 
1354     //--------------------------------------------------------------------
1355     // Advanced features
1356     //--------------------------------------------------------------------
1357 
1358 
1359     /**
1360      * Returns the <code>SyncProvider</code> implementation being used
1361      * with this <code>CachedRowSetImpl</code> implementation rowset.
1362      *
1363      * @return the SyncProvider used by the rowset. If not provider was
1364      *          set when the rowset was instantiated, the reference
1365      *          implementation (default) provider is returned.
1366      * @throws SQLException if error occurs while return the
1367      *          <code>SyncProvider</code> instance.
1368      */
1369     public SyncProvider getSyncProvider() throws SQLException {
1370         return provider;
1371     }
1372 
1373     /**
1374      * Sets the active <code>SyncProvider</code> and attempts to load
1375      * load the new provider using the <code>SyncFactory</code> SPI.
1376      *
1377      * @throws SQLException if an error occurs while resetting the
1378      *          <code>SyncProvider</code>.
1379      */
1380     public void setSyncProvider(String providerStr) throws SQLException {
1381         provider =
1382         (SyncProvider)SyncFactory.getInstance(providerStr);
1383 
1384         rowSetReader = provider.getRowSetReader();
1385         rowSetWriter = provider.getRowSetWriter();
1386     }
1387 
1388 
1389     //-----------------
1390     // methods inherited from RowSet
1391     //-----------------
1392 
1393 
1394 
1395 
1396 
1397 
1398     //---------------------------------------------------------------------
1399     // Reading and writing data
1400     //---------------------------------------------------------------------
1401 
1402     /**
1403      * Populates this <code>CachedRowSetImpl</code> object with data.
1404      * This form of the method uses the rowset's user, password, and url or
1405      * data source name properties to create a database
1406      * connection.  If properties that are needed
1407      * have not been set, this method will throw an exception.
1408      * <P>
1409      * Another form of this method uses an existing JDBC <code>Connection</code>
1410      * object instead of creating a new one; therefore, it ignores the
1411      * properties used for establishing a new connection.
1412      * <P>
1413      * The query specified by the command property is executed to create a
1414      * <code>ResultSet</code> object from which to retrieve data.
1415      * The current contents of the rowset are discarded, and the
1416      * rowset's metadata is also (re)set.  If there are outstanding updates,
1417      * they are also ignored.
1418      * <P>
1419      * The method <code>execute</code> closes any database connections that it
1420      * creates.
1421      *
1422      * @throws SQLException if an error occurs or the
1423      *                         necessary properties have not been set
1424      */
1425     public void execute() throws SQLException {
1426         execute(null);
1427     }
1428 
1429 
1430 
1431     //-----------------------------------
1432     // Methods inherited from ResultSet
1433     //-----------------------------------
1434 
1435     /**
1436      * Moves the cursor down one row from its current position and
1437      * returns <code>true</code> if the new cursor position is a
1438      * valid row.
1439      * The cursor for a new <code>ResultSet</code> object is initially
1440      * positioned before the first row. The first call to the method
1441      * <code>next</code> moves the cursor to the first row, making it
1442      * the current row; the second call makes the second row the
1443      * current row, and so on.
1444      *
1445      * <P>If an input stream from the previous row is open, it is
1446      * implicitly closed. The <code>ResultSet</code> object's warning
1447      * chain is cleared when a new row is read.
1448      *
1449      * @return <code>true</code> if the new current row is valid;
1450      *         <code>false</code> if there are no more rows
1451      * @throws SQLException if an error occurs or
1452      *            the cursor is not positioned in the rowset, before
1453      *            the first row, or after the last row
1454      */
1455     public boolean next() throws SQLException {
1456         /*
1457          * make sure things look sane. The cursor must be
1458          * positioned in the rowset or before first (0) or
1459          * after last (numRows + 1)
1460          */
1461         if (cursorPos < 0 || cursorPos >= numRows + 1) {
1462             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1463         }
1464         // now move and notify
1465         boolean ret = this.internalNext();
1466         notifyCursorMoved();
1467 
1468         return ret;
1469     }
1470 
1471     /**
1472      * Moves this <code>CachedRowSetImpl</code> object's cursor to the next
1473      * row and returns <code>true</code> if the cursor is still in the rowset;
1474      * returns <code>false</code> if the cursor has moved to the position after
1475      * the last row.
1476      * <P>
1477      * This method handles the cases where the cursor moves to a row that
1478      * has been deleted.
1479      * If this rowset shows deleted rows and the cursor moves to a row
1480      * that has been deleted, this method moves the cursor to the next
1481      * row until the cursor is on a row that has not been deleted.
1482      * <P>
1483      * The method <code>internalNext</code> is called by methods such as
1484      * <code>next</code>, <code>absolute</code>, and <code>relative</code>,
1485      * and, as its name implies, is only called internally.
1486      * <p>
1487      * This is a implementation only method and is not required as a standard
1488      * implementation of the <code>CachedRowSet</code> interface.
1489      *
1490      * @return <code>true</code> if the cursor is on a valid row in this
1491      *         rowset; <code>false</code> if it is after the last row
1492      * @throws SQLException if an error occurs
1493      */
1494     protected boolean internalNext() throws SQLException {
1495         boolean ret = false;
1496 
1497         do {
1498             if (cursorPos < numRows) {
1499                 ++cursorPos;
1500                 ret = true;
1501             } else if (cursorPos == numRows) {
1502                 // increment to after last
1503                 ++cursorPos;
1504                 ret = false;
1505                 break;
1506             }
1507         } while ((getShowDeleted() == false) && (rowDeleted() == true));
1508 
1509         /* each call to internalNext may increment cursorPos multiple
1510          * times however, the absolutePos only increments once per call.
1511          */
1512         if (ret == true)
1513             absolutePos++;
1514         else
1515             absolutePos = 0;
1516 
1517         return ret;
1518     }
1519 
1520     /**
1521      * Closes this <code>CachedRowSetImpl</code> objecy and releases any resources
1522      * it was using.
1523      *
1524      * @throws SQLException if an error occurs when releasing any resources in use
1525      * by this <code>CachedRowSetImpl</code> object
1526      */
1527     public void close() throws SQLException {
1528 
1529         // close all data structures holding
1530         // the disconnected rowset
1531 
1532         cursorPos = 0;
1533         absolutePos = 0;
1534         numRows = 0;
1535         numDeleted = 0;
1536 
1537         // set all insert(s), update(s) & delete(s),
1538         // if at all, to their initial values.
1539         initProperties();
1540 
1541         // clear the vector of it's present contents
1542         rvh.clear();
1543 
1544         // this will make it eligible for gc
1545         // rvh = null;
1546     }
1547 
1548     /**
1549      * Reports whether the last column read was SQL <code>NULL</code>.
1550      * Note that you must first call the method <code>getXXX</code>
1551      * on a column to try to read its value and then call the method
1552      * <code>wasNull</code> to determine whether the value was
1553      * SQL <code>NULL</code>.
1554      *
1555      * @return <code>true</code> if the value in the last column read
1556      *         was SQL <code>NULL</code>; <code>false</code> otherwise
1557      * @throws SQLException if an error occurs
1558      */
1559     public boolean wasNull() throws SQLException {
1560         return lastValueNull;
1561     }
1562 
1563     /**
1564      * Sets the field <code>lastValueNull</code> to the given
1565      * <code>boolean</code> value.
1566      *
1567      * @param value <code>true</code> to indicate that the value of
1568      *        the last column read was SQL <code>NULL</code>;
1569      *        <code>false</code> to indicate that it was not
1570      */
1571     private void setLastValueNull(boolean value) {
1572         lastValueNull = value;
1573     }
1574 
1575     // Methods for accessing results by column index
1576 
1577     /**
1578      * Checks to see whether the given index is a valid column number
1579      * in this <code>CachedRowSetImpl</code> object and throws
1580      * an <code>SQLException</code> if it is not. The index is out of bounds
1581      * if it is less than <code>1</code> or greater than the number of
1582      * columns in this rowset.
1583      * <P>
1584      * This method is called internally by the <code>getXXX</code> and
1585      * <code>updateXXX</code> methods.
1586      *
1587      * @param idx the number of a column in this <code>CachedRowSetImpl</code>
1588      *            object; must be between <code>1</code> and the number of
1589      *            rows in this rowset
1590      * @throws SQLException if the given index is out of bounds
1591      */
1592     private void checkIndex(int idx) throws SQLException {
1593         if (idx < 1 || idx > RowSetMD.getColumnCount()) {
1594             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcol").toString());
1595         }
1596     }
1597 
1598     /**
1599      * Checks to see whether the cursor for this <code>CachedRowSetImpl</code>
1600      * object is on a row in the rowset and throws an
1601      * <code>SQLException</code> if it is not.
1602      * <P>
1603      * This method is called internally by <code>getXXX</code> methods, by
1604      * <code>updateXXX</code> methods, and by methods that update, insert,
1605      * or delete a row or that cancel a row update, insert, or delete.
1606      *
1607      * @throws SQLException if the cursor for this <code>CachedRowSetImpl</code>
1608      *         object is not on a valid row
1609      */
1610     private void checkCursor() throws SQLException {
1611         if (isAfterLast() == true || isBeforeFirst() == true) {
1612             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1613         }
1614     }
1615 
1616     /**
1617      * Returns the column number of the column with the given name in this
1618      * <code>CachedRowSetImpl</code> object.  This method throws an
1619      * <code>SQLException</code> if the given name is not the name of
1620      * one of the columns in this rowset.
1621      *
1622      * @param name a <code>String</code> object that is the name of a column in
1623      *              this <code>CachedRowSetImpl</code> object
1624      * @throws SQLException if the given name does not match the name of one of
1625      *         the columns in this rowset
1626      */
1627     private int getColIdxByName(String name) throws SQLException {
1628         RowSetMD = (RowSetMetaDataImpl)this.getMetaData();
1629         int cols = RowSetMD.getColumnCount();
1630 
1631         for (int i=1; i <= cols; ++i) {
1632             String colName = RowSetMD.getColumnName(i);
1633             if (colName != null)
1634                 if (name.equalsIgnoreCase(colName))
1635                     return (i);
1636                 else
1637                     continue;
1638         }
1639         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalcolnm").toString());
1640 
1641     }
1642 
1643     /**
1644      * Returns the insert row or the current row of this
1645      * <code>CachedRowSetImpl</code>object.
1646      *
1647      * @return the <code>Row</code> object on which this <code>CachedRowSetImpl</code>
1648      * objects's cursor is positioned
1649      */
1650     protected BaseRow getCurrentRow() {
1651         if (onInsertRow == true) {
1652             return (BaseRow)insertRow;
1653         } else {
1654             return (BaseRow)(rvh.get(cursorPos - 1));
1655         }
1656     }
1657 
1658     /**
1659      * Removes the row on which the cursor is positioned.
1660      * <p>
1661      * This is a implementation only method and is not required as a standard
1662      * implementation of the <code>CachedRowSet</code> interface.
1663      *
1664      * @throws SQLException if the cursor is positioned on the insert
1665      *            row
1666      */
1667     protected void removeCurrentRow() {
1668         ((Row)getCurrentRow()).setDeleted();
1669         rvh.remove(cursorPos);
1670         --numRows;
1671     }
1672 
1673 
1674     /**
1675      * Retrieves the value of the designated column in the current row
1676      * of this <code>CachedRowSetImpl</code> object as a
1677      * <code>String</code> object.
1678      *
1679      * @param columnIndex the first column is <code>1</code>, the second
1680      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1681      *        and equal to or less than the number of columns in the rowset
1682      * @return the column value; if the value is SQL <code>NULL</code>, the
1683      *         result is <code>null</code>
1684      * @throws SQLException if (1) the given column index is out of bounds,
1685      * (2) the cursor is not on one of this rowset's rows or its
1686      * insert row, or (3) the designated column does not store an
1687      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
1688      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, <b>CHAR</b>, <b>VARCHAR</b></code>
1689      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1690      * recommended return type.
1691      */
1692     public String getString(int columnIndex) throws SQLException {
1693         Object value;
1694 
1695         // sanity check.
1696         checkIndex(columnIndex);
1697         // make sure the cursor is on a valid row
1698         checkCursor();
1699 
1700         setLastValueNull(false);
1701         value = getCurrentRow().getColumnObject(columnIndex);
1702 
1703         // check for SQL NULL
1704         if (value == null) {
1705             setLastValueNull(true);
1706             return null;
1707         }
1708 
1709         return value.toString();
1710     }
1711 
1712     /**
1713      * Retrieves the value of the designated column in the current row
1714      * of this <code>CachedRowSetImpl</code> object as a
1715      * <code>boolean</code> value.
1716      *
1717      * @param columnIndex the first column is <code>1</code>, the second
1718      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1719      *        and equal to or less than the number of columns in the rowset
1720      * @return the column value as a <code>boolean</code> in the Java progamming language;
1721      *        if the value is SQL <code>NULL</code>, the result is <code>false</code>
1722      * @throws SQLException if (1) the given column index is out of bounds,
1723      *            (2) the cursor is not on one of this rowset's rows or its
1724      *            insert row, or (3) the designated column does not store an
1725      *            SQL <code>BOOLEAN</code> value
1726      * @see #getBoolean(String)
1727      */
1728     public boolean getBoolean(int columnIndex) throws SQLException {
1729         Object value;
1730 
1731         // sanity check.
1732         checkIndex(columnIndex);
1733         // make sure the cursor is on a valid row
1734         checkCursor();
1735 
1736         setLastValueNull(false);
1737         value = getCurrentRow().getColumnObject(columnIndex);
1738 
1739         // check for SQL NULL
1740         if (value == null) {
1741             setLastValueNull(true);
1742             return false;
1743         }
1744 
1745         // check for Boolean...
1746         if (value instanceof Boolean) {
1747             return ((Boolean)value).booleanValue();
1748         }
1749 
1750         // convert to a Double and compare to zero
1751         try {
1752             Double d = new Double(value.toString());
1753             if (d.compareTo(new Double((double)0)) == 0) {
1754                 return false;
1755             } else {
1756                 return true;
1757             }
1758         } catch (NumberFormatException ex) {
1759             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.boolfail").toString(),
1760                   new Object[] {value.toString().trim(), columnIndex}));
1761         }
1762     }
1763 
1764     /**
1765      * Retrieves the value of the designated column in the current row
1766      * of this <code>CachedRowSetImpl</code> object as a
1767      * <code>byte</code> value.
1768      *
1769      * @param columnIndex the first column is <code>1</code>, the second
1770      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1771      *        and equal to or less than the number of columns in the rowset
1772      * @return the column value as a <code>byte</code> in the Java programming
1773      * language; if the value is SQL <code>NULL</code>, the result is <code>0</code>
1774      * @throws SQLException if (1) the given column index is out of bounds,
1775      *            (2) the cursor is not on one of this rowset's rows or its
1776      *            insert row, or (3) the designated column does not store an
1777      *            SQL <code><b>TINYINT</b>, SMALLINT, INTEGER, BIGINT, REAL,
1778      *            FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1779      *            or <code>LONGVARCHAR</code> value. The bold SQL type
1780      *            designates the recommended return type.
1781      * @see #getByte(String)
1782      */
1783     public byte getByte(int columnIndex) throws SQLException {
1784         Object value;
1785 
1786         // sanity check.
1787         checkIndex(columnIndex);
1788         // make sure the cursor is on a valid row
1789         checkCursor();
1790 
1791         setLastValueNull(false);
1792         value = getCurrentRow().getColumnObject(columnIndex);
1793 
1794         // check for SQL NULL
1795         if (value == null) {
1796             setLastValueNull(true);
1797             return (byte)0;
1798         }
1799         try {
1800             return ((Byte.valueOf(value.toString())).byteValue());
1801         } catch (NumberFormatException ex) {
1802             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.bytefail").toString(),
1803                   new Object[] {value.toString().trim(), columnIndex}));
1804         }
1805     }
1806 
1807     /**
1808      * Retrieves the value of the designated column in the current row
1809      * of this <code>CachedRowSetImpl</code> object as a
1810      * <code>short</code> value.
1811      *
1812      * @param columnIndex the first column is <code>1</code>, the second
1813      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1814      *        and equal to or less than the number of columns in the rowset
1815      * @return the column value; if the value is SQL <code>NULL</code>, the
1816      *         result is <code>0</code>
1817      * @throws SQLException if (1) the given column index is out of bounds,
1818      * (2) the cursor is not on one of this rowset's rows or its
1819      * insert row, or (3) the designated column does not store an
1820      * SQL <code>TINYINT, <b>SMALLINT</b>, INTEGER, BIGINT, REAL
1821      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1822      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1823      * recommended return type.
1824      * @see #getShort(String)
1825      */
1826     public short getShort(int columnIndex) throws SQLException {
1827         Object value;
1828 
1829         // sanity check.
1830         checkIndex(columnIndex);
1831         // make sure the cursor is on a valid row
1832         checkCursor();
1833 
1834         setLastValueNull(false);
1835         value = getCurrentRow().getColumnObject(columnIndex);
1836 
1837         // check for SQL NULL
1838         if (value == null) {
1839             setLastValueNull(true);
1840             return (short)0;
1841         }
1842 
1843         try {
1844             return ((Short.valueOf(value.toString().trim())).shortValue());
1845         } catch (NumberFormatException ex) {
1846             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.shortfail").toString(),
1847                   new Object[] {value.toString().trim(), columnIndex}));
1848         }
1849     }
1850 
1851     /**
1852      * Retrieves the value of the designated column in the current row
1853      * of this <code>CachedRowSetImpl</code> object as an
1854      * <code>int</code> value.
1855      *
1856      * @param columnIndex the first column is <code>1</code>, the second
1857      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1858      *        and equal to or less than the number of columns in the rowset
1859      * @return the column value; if the value is SQL <code>NULL</code>, the
1860      *         result is <code>0</code>
1861      * @throws SQLException if (1) the given column index is out of bounds,
1862      * (2) the cursor is not on one of this rowset's rows or its
1863      * insert row, or (3) the designated column does not store an
1864      * SQL <code>TINYINT, SMALLINT, <b>INTEGER</b>, BIGINT, REAL
1865      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1866      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1867      * recommended return type.
1868      */
1869     public int getInt(int columnIndex) throws SQLException {
1870         Object value;
1871 
1872         // sanity check.
1873         checkIndex(columnIndex);
1874         // make sure the cursor is on a valid row
1875         checkCursor();
1876 
1877         setLastValueNull(false);
1878         value = getCurrentRow().getColumnObject(columnIndex);
1879 
1880         // check for SQL NULL
1881         if (value == null) {
1882             setLastValueNull(true);
1883             return (int)0;
1884         }
1885 
1886         try {
1887             return ((Integer.valueOf(value.toString().trim())).intValue());
1888         } catch (NumberFormatException ex) {
1889             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.intfail").toString(),
1890                   new Object[] {value.toString().trim(), columnIndex}));
1891         }
1892     }
1893 
1894     /**
1895      * Retrieves the value of the designated column in the current row
1896      * of this <code>CachedRowSetImpl</code> object as a
1897      * <code>long</code> value.
1898      *
1899      * @param columnIndex the first column is <code>1</code>, the second
1900      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1901      *        and equal to or less than the number of columns in the rowset
1902      * @return the column value; if the value is SQL <code>NULL</code>, the
1903      *         result is <code>0</code>
1904      * @throws SQLException if (1) the given column index is out of bounds,
1905      * (2) the cursor is not on one of this rowset's rows or its
1906      * insert row, or (3) the designated column does not store an
1907      * SQL <code>TINYINT, SMALLINT, INTEGER, <b>BIGINT</b>, REAL
1908      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1909      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1910      * recommended return type.
1911      * @see #getLong(String)
1912      */
1913     public long getLong(int columnIndex) throws SQLException {
1914         Object value;
1915 
1916         // sanity check.
1917         checkIndex(columnIndex);
1918         // make sure the cursor is on a valid row
1919         checkCursor();
1920 
1921         setLastValueNull(false);
1922         value = getCurrentRow().getColumnObject(columnIndex);
1923 
1924         // check for SQL NULL
1925         if (value == null) {
1926             setLastValueNull(true);
1927             return (long)0;
1928         }
1929         try {
1930             return ((Long.valueOf(value.toString().trim())).longValue());
1931         } catch (NumberFormatException ex) {
1932             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.longfail").toString(),
1933                   new Object[] {value.toString().trim(), columnIndex}));
1934         }
1935     }
1936 
1937     /**
1938      * Retrieves the value of the designated column in the current row
1939      * of this <code>CachedRowSetImpl</code> object as a
1940      * <code>float</code> value.
1941      *
1942      * @param columnIndex the first column is <code>1</code>, the second
1943      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1944      *        and equal to or less than the number of columns in the rowset
1945      * @return the column value; if the value is SQL <code>NULL</code>, the
1946      *         result is <code>0</code>
1947      * @throws SQLException if (1) the given column index is out of bounds,
1948      * (2) the cursor is not on one of this rowset's rows or its
1949      * insert row, or (3) the designated column does not store an
1950      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, <b>REAL</b>,
1951      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1952      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1953      * recommended return type.
1954      * @see #getFloat(String)
1955      */
1956     public float getFloat(int columnIndex) throws SQLException {
1957         Object value;
1958 
1959         // sanity check.
1960         checkIndex(columnIndex);
1961         // make sure the cursor is on a valid row
1962         checkCursor();
1963 
1964         setLastValueNull(false);
1965         value = getCurrentRow().getColumnObject(columnIndex);
1966 
1967         // check for SQL NULL
1968         if (value == null) {
1969             setLastValueNull(true);
1970             return (float)0;
1971         }
1972         try {
1973             return ((new Float(value.toString())).floatValue());
1974         } catch (NumberFormatException ex) {
1975             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.floatfail").toString(),
1976                   new Object[] {value.toString().trim(), columnIndex}));
1977         }
1978     }
1979 
1980     /**
1981      * Retrieves the value of the designated column in the current row
1982      * of this <code>CachedRowSetImpl</code> object as a
1983      * <code>double</code> value.
1984      *
1985      * @param columnIndex the first column is <code>1</code>, the second
1986      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1987      *        and equal to or less than the number of columns in the rowset
1988      * @return the column value; if the value is SQL <code>NULL</code>, the
1989      *         result is <code>0</code>
1990      * @throws SQLException if (1) the given column index is out of bounds,
1991      * (2) the cursor is not on one of this rowset's rows or its
1992      * insert row, or (3) the designated column does not store an
1993      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
1994      * <b>FLOAT</b>, <b>DOUBLE</b>, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1995      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1996      * recommended return type.
1997      * @see #getDouble(String)
1998      *
1999      */
2000     public double getDouble(int columnIndex) throws SQLException {
2001         Object value;
2002 
2003         // sanity check.
2004         checkIndex(columnIndex);
2005         // make sure the cursor is on a valid row
2006         checkCursor();
2007 
2008         setLastValueNull(false);
2009         value = getCurrentRow().getColumnObject(columnIndex);
2010 
2011         // check for SQL NULL
2012         if (value == null) {
2013             setLastValueNull(true);
2014             return (double)0;
2015         }
2016         try {
2017             return ((new Double(value.toString().trim())).doubleValue());
2018         } catch (NumberFormatException ex) {
2019             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.doublefail").toString(),
2020                   new Object[] {value.toString().trim(), columnIndex}));
2021         }
2022     }
2023 
2024     /**
2025      * Retrieves the value of the designated column in the current row
2026      * of this <code>CachedRowSetImpl</code> object as a
2027      * <code>java.math.BigDecimal</code> object.
2028      * <P>
2029      * This method is deprecated; use the version of <code>getBigDecimal</code>
2030      * that does not take a scale parameter and returns a value with full
2031      * precision.
2032      *
2033      * @param columnIndex the first column is <code>1</code>, the second
2034      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2035      *        and equal to or less than the number of columns in the rowset
2036      * @param scale the number of digits to the right of the decimal point in the
2037      *        value returned
2038      * @return the column value with the specified number of digits to the right
2039      *         of the decimal point; if the value is SQL <code>NULL</code>, the
2040      *         result is <code>null</code>
2041      * @throws SQLException if the given column index is out of bounds,
2042      *            the cursor is not on a valid row, or this method fails
2043      * @deprecated
2044      */
2045     public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
2046         Object value;
2047         BigDecimal bDecimal, retVal;
2048 
2049         // sanity check.
2050         checkIndex(columnIndex);
2051         // make sure the cursor is on a valid row
2052         checkCursor();
2053 
2054         setLastValueNull(false);
2055         value = getCurrentRow().getColumnObject(columnIndex);
2056 
2057         // check for SQL NULL
2058         if (value == null) {
2059             setLastValueNull(true);
2060             return (new BigDecimal(0));
2061         }
2062 
2063         bDecimal = this.getBigDecimal(columnIndex);
2064 
2065         retVal = bDecimal.setScale(scale);
2066 
2067         return retVal;
2068     }
2069 
2070     /**
2071      * Retrieves the value of the designated column in the current row
2072      * of this <code>CachedRowSetImpl</code> object as a
2073      * <code>byte</code> array value.
2074      *
2075      * @param columnIndex the first column is <code>1</code>, the second
2076      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2077      *        and equal to or less than the number of columns in the rowset
2078      * @return the column value as a <code>byte</code> array in the Java programming
2079      * language; if the value is SQL <code>NULL</code>, the
2080      * result is <code>null</code>
2081      *
2082      * @throws SQLException if (1) the given column index is out of bounds,
2083      * (2) the cursor is not on one of this rowset's rows or its
2084      * insert row, or (3) the designated column does not store an
2085      * SQL <code><b>BINARY</b>, <b>VARBINARY</b> or
2086      * LONGVARBINARY</code> value.
2087      * The bold SQL type designates the recommended return type.
2088      * @see #getBytes(String)
2089      */
2090     public byte[] getBytes(int columnIndex) throws SQLException {
2091         // sanity check.
2092         checkIndex(columnIndex);
2093         // make sure the cursor is on a valid row
2094         checkCursor();
2095 
2096         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
2097             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2098         }
2099 
2100         return (byte[])(getCurrentRow().getColumnObject(columnIndex));
2101     }
2102 
2103     /**
2104      * Retrieves the value of the designated column in the current row
2105      * of this <code>CachedRowSetImpl</code> object as a
2106      * <code>java.sql.Date</code> object.
2107      *
2108      * @param columnIndex the first column is <code>1</code>, the second
2109      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2110      *        and equal to or less than the number of columns in the rowset
2111      * @return the column value as a <code>java.sql.Data</code> object; if
2112      *        the value is SQL <code>NULL</code>, the
2113      *        result is <code>null</code>
2114      * @throws SQLException if the given column index is out of bounds,
2115      *            the cursor is not on a valid row, or this method fails
2116      */
2117     public java.sql.Date getDate(int columnIndex) throws SQLException {
2118         Object value;
2119 
2120         // sanity check.
2121         checkIndex(columnIndex);
2122         // make sure the cursor is on a valid row
2123         checkCursor();
2124 
2125         setLastValueNull(false);
2126         value = getCurrentRow().getColumnObject(columnIndex);
2127 
2128         // check for SQL NULL
2129         if (value == null) {
2130             setLastValueNull(true);
2131             return null;
2132         }
2133 
2134         /*
2135          * The object coming back from the db could be
2136          * a date, a timestamp, or a char field variety.
2137          * If it's a date type return it, a timestamp
2138          * we turn into a long and then into a date,
2139          * char strings we try to parse. Yuck.
2140          */
2141         switch (RowSetMD.getColumnType(columnIndex)) {
2142             case java.sql.Types.DATE: {
2143                 long sec = ((java.sql.Date)value).getTime();
2144                 return new java.sql.Date(sec);
2145             }
2146             case java.sql.Types.TIMESTAMP: {
2147                 long sec = ((java.sql.Timestamp)value).getTime();
2148                 return new java.sql.Date(sec);
2149             }
2150             case java.sql.Types.CHAR:
2151             case java.sql.Types.VARCHAR:
2152             case java.sql.Types.LONGVARCHAR: {
2153                 try {
2154                     DateFormat df = DateFormat.getDateInstance();
2155                     return ((java.sql.Date)(df.parse(value.toString())));
2156                 } catch (ParseException ex) {
2157                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.datefail").toString(),
2158                         new Object[] {value.toString().trim(), columnIndex}));
2159                 }
2160             }
2161             default: {
2162                 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.datefail").toString(),
2163                         new Object[] {value.toString().trim(), columnIndex}));
2164             }
2165         }
2166     }
2167 
2168     /**
2169      * Retrieves the value of the designated column in the current row
2170      * of this <code>CachedRowSetImpl</code> object as a
2171      * <code>java.sql.Time</code> object.
2172      *
2173      * @param columnIndex the first column is <code>1</code>, the second
2174      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2175      *        and equal to or less than the number of columns in the rowset
2176      * @return the column value; if the value is SQL <code>NULL</code>, the
2177      *         result is <code>null</code>
2178      * @throws SQLException if the given column index is out of bounds,
2179      *         the cursor is not on a valid row, or this method fails
2180      */
2181     public java.sql.Time getTime(int columnIndex) throws SQLException {
2182         Object value;
2183 
2184         // sanity check.
2185         checkIndex(columnIndex);
2186         // make sure the cursor is on a valid row
2187         checkCursor();
2188 
2189         setLastValueNull(false);
2190         value = getCurrentRow().getColumnObject(columnIndex);
2191 
2192         // check for SQL NULL
2193         if (value == null) {
2194             setLastValueNull(true);
2195             return null;
2196         }
2197 
2198         /*
2199          * The object coming back from the db could be
2200          * a date, a timestamp, or a char field variety.
2201          * If it's a date type return it, a timestamp
2202          * we turn into a long and then into a date,
2203          * char strings we try to parse. Yuck.
2204          */
2205         switch (RowSetMD.getColumnType(columnIndex)) {
2206             case java.sql.Types.TIME: {
2207                 return (java.sql.Time)value;
2208             }
2209             case java.sql.Types.TIMESTAMP: {
2210                 long sec = ((java.sql.Timestamp)value).getTime();
2211                 return new java.sql.Time(sec);
2212             }
2213             case java.sql.Types.CHAR:
2214             case java.sql.Types.VARCHAR:
2215             case java.sql.Types.LONGVARCHAR: {
2216                 try {
2217                     DateFormat tf = DateFormat.getTimeInstance();
2218                     return ((java.sql.Time)(tf.parse(value.toString())));
2219                 } catch (ParseException ex) {
2220                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2221                         new Object[] {value.toString().trim(), columnIndex}));
2222                 }
2223             }
2224             default: {
2225                 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2226                         new Object[] {value.toString().trim(), columnIndex}));
2227             }
2228         }
2229     }
2230 
2231     /**
2232      * Retrieves the value of the designated column in the current row
2233      * of this <code>CachedRowSetImpl</code> object as a
2234      * <code>java.sql.Timestamp</code> object.
2235      *
2236      * @param columnIndex the first column is <code>1</code>, the second
2237      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2238      *        and equal to or less than the number of columns in the rowset
2239      * @return the column value; if the value is SQL <code>NULL</code>, the
2240      *         result is <code>null</code>
2241      * @throws SQLException if the given column index is out of bounds,
2242      *            the cursor is not on a valid row, or this method fails
2243      */
2244     public java.sql.Timestamp getTimestamp(int columnIndex) throws SQLException {
2245         Object value;
2246 
2247         // sanity check.
2248         checkIndex(columnIndex);
2249         // make sure the cursor is on a valid row
2250         checkCursor();
2251 
2252         setLastValueNull(false);
2253         value = getCurrentRow().getColumnObject(columnIndex);
2254 
2255         // check for SQL NULL
2256         if (value == null) {
2257             setLastValueNull(true);
2258             return null;
2259         }
2260 
2261         /*
2262          * The object coming back from the db could be
2263          * a date, a timestamp, or a char field variety.
2264          * If it's a date type return it; a timestamp
2265          * we turn into a long and then into a date;
2266          * char strings we try to parse. Yuck.
2267          */
2268         switch (RowSetMD.getColumnType(columnIndex)) {
2269             case java.sql.Types.TIMESTAMP: {
2270                 return (java.sql.Timestamp)value;
2271             }
2272             case java.sql.Types.TIME: {
2273                 long sec = ((java.sql.Time)value).getTime();
2274                 return new java.sql.Timestamp(sec);
2275             }
2276             case java.sql.Types.DATE: {
2277                 long sec = ((java.sql.Date)value).getTime();
2278                 return new java.sql.Timestamp(sec);
2279             }
2280             case java.sql.Types.CHAR:
2281             case java.sql.Types.VARCHAR:
2282             case java.sql.Types.LONGVARCHAR: {
2283                 try {
2284                     DateFormat tf = DateFormat.getTimeInstance();
2285                     return ((java.sql.Timestamp)(tf.parse(value.toString())));
2286                 } catch (ParseException ex) {
2287                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2288                         new Object[] {value.toString().trim(), columnIndex}));
2289                 }
2290             }
2291             default: {
2292                 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2293                         new Object[] {value.toString().trim(), columnIndex}));
2294             }
2295         }
2296     }
2297 
2298     /**
2299      * Retrieves the value of the designated column in the current row of this
2300      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2301      * object.
2302      *
2303      * A column value can be retrieved as a stream of ASCII characters
2304      * and then read in chunks from the stream.  This method is particularly
2305      * suitable for retrieving large <code>LONGVARCHAR</code> values.  The JDBC
2306      * driver will do any necessary conversion from the database format into ASCII.
2307      *
2308      * <P><B>Note:</B> All the data in the returned stream must be
2309      * read prior to getting the value of any other column. The next
2310      * call to a get method implicitly closes the stream. . Also, a
2311      * stream may return <code>0</code> for <code>CachedRowSetImpl.available()</code>
2312      * whether there is data available or not.
2313      *
2314      * @param columnIndex the first column is <code>1</code>, the second
2315      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2316      *        and equal to or less than the number of columns in this rowset
2317      * @return a Java input stream that delivers the database column value
2318      *         as a stream of one-byte ASCII characters.  If the value is SQL
2319      *         <code>NULL</code>, the result is <code>null</code>.
2320      * @throws SQLException if (1) the given column index is out of bounds,
2321      * (2) the cursor is not on one of this rowset's rows or its
2322      * insert row, or (3) the designated column does not store an
2323      * SQL <code>CHAR, VARCHAR</code>, <code><b>LONGVARCHAR</b></code>
2324      * <code>BINARY, VARBINARY</code> or <code>LONGVARBINARY</code> value. The
2325      * bold SQL type designates the recommended return types that this method is
2326      * used to retrieve.
2327      * @see #getAsciiStream(String)
2328      */
2329     public java.io.InputStream getAsciiStream(int columnIndex) throws SQLException {
2330         Object value;
2331 
2332         // always free an old stream
2333         asciiStream = null;
2334 
2335         // sanity check
2336         checkIndex(columnIndex);
2337         //make sure the cursor is on a vlid row
2338         checkCursor();
2339 
2340         value =  getCurrentRow().getColumnObject(columnIndex);
2341         if (value == null) {
2342             lastValueNull = true;
2343             return null;
2344         }
2345 
2346         try {
2347             if (isString(RowSetMD.getColumnType(columnIndex))) {
2348                 asciiStream = new ByteArrayInputStream(((String)value).getBytes("ASCII"));
2349             } else {
2350                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2351             }
2352         } catch (java.io.UnsupportedEncodingException ex) {
2353             throw new SQLException(ex.getMessage());
2354         }
2355 
2356         return (java.io.InputStream)asciiStream;
2357     }
2358 
2359     /**
2360      * A column value can be retrieved as a stream of Unicode characters
2361      * and then read in chunks from the stream.  This method is particularly
2362      * suitable for retrieving large LONGVARCHAR values.  The JDBC driver will
2363      * do any necessary conversion from the database format into Unicode.
2364      *
2365      * <P><B>Note:</B> All the data in the returned stream must be
2366      * read prior to getting the value of any other column. The next
2367      * call to a get method implicitly closes the stream. . Also, a
2368      * stream may return 0 for available() whether there is data
2369      * available or not.
2370      *
2371      * @param columnIndex the first column is <code>1</code>, the second
2372      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2373      *        and equal to or less than the number of columns in this rowset
2374      * @return a Java input stream that delivers the database column value
2375      * as a stream of two byte Unicode characters.  If the value is SQL NULL
2376      * then the result is null.
2377      * @throws SQLException if an error occurs
2378      * @deprecated
2379      */
2380     public java.io.InputStream getUnicodeStream(int columnIndex) throws SQLException {
2381         // always free an old stream
2382         unicodeStream = null;
2383 
2384         // sanity check.
2385         checkIndex(columnIndex);
2386         // make sure the cursor is on a valid row
2387         checkCursor();
2388 
2389         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false &&
2390         isString(RowSetMD.getColumnType(columnIndex)) == false) {
2391             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2392         }
2393 
2394         Object value = getCurrentRow().getColumnObject(columnIndex);
2395         if (value == null) {
2396             lastValueNull = true;
2397             return null;
2398         }
2399 
2400         unicodeStream = new StringBufferInputStream(value.toString());
2401 
2402         return (java.io.InputStream)unicodeStream;
2403     }
2404 
2405     /**
2406      * Retrieves the value of the designated column in the current row of this
2407      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2408      * object.
2409      * <P>
2410      * A column value can be retrieved as a stream of uninterpreted bytes
2411      * and then read in chunks from the stream.  This method is particularly
2412      * suitable for retrieving large <code>LONGVARBINARY</code> values.
2413      *
2414      * <P><B>Note:</B> All the data in the returned stream must be
2415      * read prior to getting the value of any other column. The next
2416      * call to a get method implicitly closes the stream. Also, a
2417      * stream may return <code>0</code> for
2418      * <code>CachedRowSetImpl.available()</code> whether there is data
2419      * available or not.
2420      *
2421      * @param columnIndex the first column is <code>1</code>, the second
2422      * is <code>2</code>, and so on; must be <code>1</code> or larger
2423      * and equal to or less than the number of columns in the rowset
2424      * @return a Java input stream that delivers the database column value
2425      * as a stream of uninterpreted bytes.  If the value is SQL <code>NULL</code>
2426      * then the result is <code>null</code>.
2427      * @throws SQLException if (1) the given column index is out of bounds,
2428      * (2) the cursor is not on one of this rowset's rows or its
2429      * insert row, or (3) the designated column does not store an
2430      * SQL <code>BINARY, VARBINARY</code> or <code><b>LONGVARBINARY</b></code>
2431      * The bold type indicates the SQL type that this method is recommened
2432      * to retrieve.
2433      * @see #getBinaryStream(String)
2434      */
2435     public java.io.InputStream getBinaryStream(int columnIndex) throws SQLException {
2436 
2437         // always free an old stream
2438         binaryStream = null;
2439 
2440         // sanity check.
2441         checkIndex(columnIndex);
2442         // make sure the cursor is on a valid row
2443         checkCursor();
2444 
2445         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
2446             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2447         }
2448 
2449         Object value = getCurrentRow().getColumnObject(columnIndex);
2450         if (value == null) {
2451             lastValueNull = true;
2452             return null;
2453         }
2454 
2455         binaryStream = new ByteArrayInputStream((byte[])value);
2456 
2457         return (java.io.InputStream)binaryStream;
2458 
2459     }
2460 
2461 
2462     // Methods for accessing results by column name
2463 
2464     /**
2465      * Retrieves the value stored in the designated column
2466      * of the current row as a <code>String</code> object.
2467      *
2468      * @param columnName a <code>String</code> object giving the SQL name of
2469      *        a column in this <code>CachedRowSetImpl</code> object
2470      * @return the column value; if the value is SQL <code>NULL</code>,
2471      *         the result is <code>null</code>
2472      * @throws SQLException if (1) the given column name is not the name of
2473      * a column in this rowset, (2) the cursor is not on one of
2474      * this rowset's rows or its insert row, or (3) the designated
2475      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2476      * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, <b>CHAR</b>,
2477      * <b>VARCHAR</b></code> or <code>LONGVARCHAR<</code> value. The bold SQL type
2478      * designates the recommended return type.
2479      */
2480     public String getString(String columnName) throws SQLException {
2481         return getString(getColIdxByName(columnName));
2482     }
2483 
2484     /**
2485      * Retrieves the value stored in the designated column
2486      * of the current row as a <code>boolean</code> value.
2487      *
2488      * @param columnName a <code>String</code> object giving the SQL name of
2489      *        a column in this <code>CachedRowSetImpl</code> object
2490      * @return the column value as a <code>boolean</code> in the Java programming
2491      *        language; if the value is SQL <code>NULL</code>,
2492      *        the result is <code>false</code>
2493      * @throws SQLException if (1) the given column name is not the name of
2494      *            a column in this rowset, (2) the cursor is not on one of
2495      *            this rowset's rows or its insert row, or (3) the designated
2496      *            column does not store an SQL <code>BOOLEAN</code> value
2497      * @see #getBoolean(int)
2498      */
2499     public boolean getBoolean(String columnName) throws SQLException {
2500         return getBoolean(getColIdxByName(columnName));
2501     }
2502 
2503     /**
2504      * Retrieves the value stored in the designated column
2505      * of the current row as a <code>byte</code> value.
2506      *
2507      * @param columnName a <code>String</code> object giving the SQL name of
2508      *        a column in this <code>CachedRowSetImpl</code> object
2509      * @return the column value as a <code>byte</code> in the Java programming
2510      * language; if the value is SQL <code>NULL</code>, the result is <code>0</code>
2511      * @throws SQLException if (1) the given column name is not the name of
2512      * a column in this rowset, (2) the cursor is not on one of
2513      * this rowset's rows or its insert row, or (3) the designated
2514      * column does not store an SQL <code><B>TINYINT</B>, SMALLINT, INTEGER,
2515      * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2516      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The
2517      * bold type designates the recommended return type
2518      */
2519     public byte getByte(String columnName) throws SQLException {
2520         return getByte(getColIdxByName(columnName));
2521     }
2522 
2523     /**
2524      * Retrieves the value stored in the designated column
2525      * of the current row as a <code>short</code> value.
2526      *
2527      * @param columnName a <code>String</code> object giving the SQL name of
2528      *        a column in this <code>CachedRowSetImpl</code> object
2529      * @return the column value; if the value is SQL <code>NULL</code>,
2530      *         the result is <code>0</code>
2531      * @throws SQLException if (1) the given column name is not the name of
2532      * a column in this rowset, (2) the cursor is not on one of
2533      * this rowset's rows or its insert row, or (3) the designated
2534      * column does not store an SQL <code>TINYINT, <b>SMALLINT</b>, INTEGER
2535      * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2536      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2537      * designates the recommended return type.
2538      * @see #getShort(int)
2539      */
2540     public short getShort(String columnName) throws SQLException {
2541         return getShort(getColIdxByName(columnName));
2542     }
2543 
2544     /**
2545      * Retrieves the value stored in the designated column
2546      * of the current row as an <code>int</code> value.
2547      *
2548      * @param columnName a <code>String</code> object giving the SQL name of
2549      *        a column in this <code>CachedRowSetImpl</code> object
2550      * @return the column value; if the value is SQL <code>NULL</code>,
2551      *         the result is <code>0</code>
2552      * @throws SQLException if (1) the given column name is not the name
2553      * of a column in this rowset,
2554      * (2) the cursor is not on one of this rowset's rows or its
2555      * insert row, or (3) the designated column does not store an
2556      * SQL <code>TINYINT, SMALLINT, <b>INTEGER</b>, BIGINT, REAL
2557      * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
2558      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
2559      * recommended return type.
2560      */
2561     public int getInt(String columnName) throws SQLException {
2562         return getInt(getColIdxByName(columnName));
2563     }
2564 
2565     /**
2566      * Retrieves the value stored in the designated column
2567      * of the current row as a <code>long</code> value.
2568      *
2569      * @param columnName a <code>String</code> object giving the SQL name of
2570      *        a column in this <code>CachedRowSetImpl</code> object
2571      * @return the column value; if the value is SQL <code>NULL</code>,
2572      *         the result is <code>0</code>
2573      * @throws SQLException if (1) the given column name is not the name of
2574      * a column in this rowset, (2) the cursor is not on one of
2575      * this rowset's rows or its insert row, or (3) the designated
2576      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2577      * <b>BIGINT</b>, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2578      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2579      * designates the recommended return type.
2580      * @see #getLong(int)
2581      */
2582     public long getLong(String columnName) throws SQLException {
2583         return getLong(getColIdxByName(columnName));
2584     }
2585 
2586     /**
2587      * Retrieves the value stored in the designated column
2588      * of the current row as a <code>float</code> value.
2589      *
2590      * @param columnName a <code>String</code> object giving the SQL name of
2591      *        a column in this <code>CachedRowSetImpl</code> object
2592      * @return the column value; if the value is SQL <code>NULL</code>,
2593      *         the result is <code>0</code>
2594      * @throws SQLException if (1) the given column name is not the name of
2595      * a column in this rowset, (2) the cursor is not on one of
2596      * this rowset's rows or its insert row, or (3) the designated
2597      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2598      * BIGINT, <b>REAL</b>, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2599      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2600      * designates the recommended return type.
2601      * @see #getFloat(String)
2602      */
2603     public float getFloat(String columnName) throws SQLException {
2604         return getFloat(getColIdxByName(columnName));
2605     }
2606 
2607     /**
2608      * Retrieves the value stored in the designated column
2609      * of the current row of this <code>CachedRowSetImpl</code> object
2610      * as a <code>double</code> value.
2611      *
2612      * @param columnName a <code>String</code> object giving the SQL name of
2613      *        a column in this <code>CachedRowSetImpl</code> object
2614      * @return the column value; if the value is SQL <code>NULL</code>,
2615      *         the result is <code>0</code>
2616      * @throws SQLException if (1) the given column name is not the name of
2617      * a column in this rowset, (2) the cursor is not on one of
2618      * this rowset's rows or its insert row, or (3) the designated
2619      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2620      * BIGINT, REAL, <b>FLOAT</b>, <b>DOUBLE</b>, DECIMAL, NUMERIC, BIT, CHAR,
2621      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2622      * designates the recommended return types.
2623      * @see #getDouble(int)
2624      */
2625     public double getDouble(String columnName) throws SQLException {
2626         return getDouble(getColIdxByName(columnName));
2627     }
2628 
2629     /**
2630      * Retrieves the value stored in the designated column
2631      * of the current row as a <code>java.math.BigDecimal</code> object.
2632      *
2633      * @param columnName a <code>String</code> object giving the SQL name of
2634      *        a column in this <code>CachedRowSetImpl</code> object
2635      * @param scale the number of digits to the right of the decimal point
2636      * @return a java.math.BugDecimal object with <code><i>scale</i></code>
2637      * number of digits to the right of the decimal point.
2638      * @throws SQLException if (1) the given column name is not the name of
2639      * a column in this rowset, (2) the cursor is not on one of
2640      * this rowset's rows or its insert row, or (3) the designated
2641      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2642      * BIGINT, REAL, FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT CHAR,
2643      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2644      * designates the recommended return type that this method is used to
2645      * retrieve.
2646      * @deprecated Use the <code>getBigDecimal(String columnName)</code>
2647      *             method instead
2648      */
2649     public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {
2650         return getBigDecimal(getColIdxByName(columnName), scale);
2651     }
2652 
2653     /**
2654      * Retrieves the value stored in the designated column
2655      * of the current row as a <code>byte</code> array.
2656      * The bytes represent the raw values returned by the driver.
2657      *
2658      * @param columnName a <code>String</code> object giving the SQL name of
2659      *        a column in this <code>CachedRowSetImpl</code> object
2660      * @return the column value as a <code>byte</code> array in the Java programming
2661      * language; if the value is SQL <code>NULL</code>, the result is <code>null</code>
2662      * @throws SQLException if (1) the given column name is not the name of
2663      * a column in this rowset, (2) the cursor is not on one of
2664      * this rowset's rows or its insert row, or (3) the designated
2665      * column does not store an SQL <code><b>BINARY</b>, <b>VARBINARY</b>
2666      * </code> or <code>LONGVARBINARY</code> values
2667      * The bold SQL type designates the recommended return type.
2668      * @see #getBytes(int)
2669      */
2670     public byte[] getBytes(String columnName) throws SQLException {
2671         return getBytes(getColIdxByName(columnName));
2672     }
2673 
2674     /**
2675      * Retrieves the value stored in the designated column
2676      * of the current row as a <code>java.sql.Date</code> object.
2677      *
2678      * @param columnName a <code>String</code> object giving the SQL name of
2679      *        a column in this <code>CachedRowSetImpl</code> object
2680      * @return the column value; if the value is SQL <code>NULL</code>,
2681      *         the result is <code>null</code>
2682      * @throws SQLException if (1) the given column name is not the name of
2683      *            a column in this rowset, (2) the cursor is not on one of
2684      *            this rowset's rows or its insert row, or (3) the designated
2685      *            column does not store an SQL <code>DATE</code> or
2686      *            <code>TIMESTAMP</code> value
2687      */
2688     public java.sql.Date getDate(String columnName) throws SQLException {
2689         return getDate(getColIdxByName(columnName));
2690     }
2691 
2692     /**
2693      * Retrieves the value stored in the designated column
2694      * of the current row as a <code>java.sql.Time</code> object.
2695      *
2696      * @param columnName a <code>String</code> object giving the SQL name of
2697      *        a column in this <code>CachedRowSetImpl</code> object
2698      * @return the column value; if the value is SQL <code>NULL</code>,
2699      *         the result is <code>null</code>
2700      * @throws SQLException if the given column name does not match one of
2701      *            this rowset's column names or the cursor is not on one of
2702      *            this rowset's rows or its insert row
2703      */
2704     public java.sql.Time getTime(String columnName) throws SQLException {
2705         return getTime(getColIdxByName(columnName));
2706     }
2707 
2708     /**
2709      * Retrieves the value stored in the designated column
2710      * of the current row as a <code>java.sql.Timestamp</code> object.
2711      *
2712      * @param columnName a <code>String</code> object giving the SQL name of
2713      *        a column in this <code>CachedRowSetImpl</code> object
2714      * @return the column value; if the value is SQL <code>NULL</code>,
2715      *         the result is <code>null</code>
2716      * @throws SQLException if the given column name does not match one of
2717      *            this rowset's column names or the cursor is not on one of
2718      *            this rowset's rows or its insert row
2719      */
2720     public java.sql.Timestamp getTimestamp(String columnName) throws SQLException {
2721         return getTimestamp(getColIdxByName(columnName));
2722     }
2723 
2724     /**
2725      * Retrieves the value of the designated column in the current row of this
2726      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2727      * object.
2728      *
2729      * A column value can be retrieved as a stream of ASCII characters
2730      * and then read in chunks from the stream. This method is particularly
2731      * suitable for retrieving large <code>LONGVARCHAR</code> values. The
2732      * <code>SyncProvider</code> will rely on the JDBC driver to do any necessary
2733      * conversion from the database format into ASCII format.
2734      *
2735      * <P><B>Note:</B> All the data in the returned stream must
2736      * be read prior to getting the value of any other column. The
2737      * next call to a <code>getXXX</code> method implicitly closes the stream.
2738      *
2739      * @param columnName a <code>String</code> object giving the SQL name of
2740      *        a column in this <code>CachedRowSetImpl</code> object
2741      * @return a Java input stream that delivers the database column value
2742      *         as a stream of one-byte ASCII characters.  If the value is SQL
2743      *         <code>NULL</code>, the result is <code>null</code>.
2744      * @throws SQLException if (1) the given column name is not the name of
2745      * a column in this rowset
2746      * (2) the cursor is not on one of this rowset's rows or its
2747      * insert row, or (3) the designated column does not store an
2748      * SQL <code>CHAR, VARCHAR</code>, <code><b>LONGVARCHAR</b></code>
2749      * <code>BINARY, VARBINARY</code> or <code>LONGVARBINARY</code> value. The
2750      * bold SQL type designates the recommended return types that this method is
2751      * used to retrieve.
2752      * @see #getAsciiStream(int)
2753      */
2754     public java.io.InputStream getAsciiStream(String columnName) throws SQLException {
2755         return getAsciiStream(getColIdxByName(columnName));
2756 
2757     }
2758 
2759     /**
2760      * A column value can be retrieved as a stream of Unicode characters
2761      * and then read in chunks from the stream.  This method is particularly
2762      * suitable for retrieving large <code>LONGVARCHAR</code> values.
2763      * The JDBC driver will do any necessary conversion from the database
2764      * format into Unicode.
2765      *
2766      * <P><B>Note:</B> All the data in the returned stream must
2767      * be read prior to getting the value of any other column. The
2768      * next call to a <code>getXXX</code> method implicitly closes the stream.
2769      *
2770      * @param columnName a <code>String</code> object giving the SQL name of
2771      *        a column in this <code>CachedRowSetImpl</code> object
2772      * @return a Java input stream that delivers the database column value
2773      *         as a stream of two-byte Unicode characters.  If the value is
2774      *         SQL <code>NULL</code>, the result is <code>null</code>.
2775      * @throws SQLException if the given column name does not match one of
2776      *            this rowset's column names or the cursor is not on one of
2777      *            this rowset's rows or its insert row
2778      * @deprecated use the method <code>getCharacterStream</code> instead
2779      */
2780     public java.io.InputStream getUnicodeStream(String columnName) throws SQLException {
2781         return getUnicodeStream(getColIdxByName(columnName));
2782     }
2783 
2784     /**
2785      * Retrieves the value of the designated column in the current row of this
2786      * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2787      * object.
2788      * <P>
2789      * A column value can be retrieved as a stream of uninterpreted bytes
2790      * and then read in chunks from the stream.  This method is particularly
2791      * suitable for retrieving large <code>LONGVARBINARY</code> values.
2792      *
2793      * <P><B>Note:</B> All the data in the returned stream must be
2794      * read prior to getting the value of any other column. The next
2795      * call to a get method implicitly closes the stream. Also, a
2796      * stream may return <code>0</code> for <code>CachedRowSetImpl.available()</code>
2797      * whether there is data available or not.
2798      *
2799      * @param columnName a <code>String</code> object giving the SQL name of
2800      *        a column in this <code>CachedRowSetImpl</code> object
2801      * @return a Java input stream that delivers the database column value
2802      *         as a stream of uninterpreted bytes.  If the value is SQL
2803      *         <code>NULL</code>, the result is <code>null</code>.
2804      * @throws SQLException if (1) the given column name is unknown,
2805      * (2) the cursor is not on one of this rowset's rows or its
2806      * insert row, or (3) the designated column does not store an
2807      * SQL <code>BINARY, VARBINARY</code> or <code><b>LONGVARBINARY</b></code>
2808      * The bold type indicates the SQL type that this method is recommened
2809      * to retrieve.
2810      * @see #getBinaryStream(int)
2811      *
2812      */
2813     public java.io.InputStream getBinaryStream(String columnName) throws SQLException {
2814         return getBinaryStream(getColIdxByName(columnName));
2815     }
2816 
2817 
2818     // Advanced features:
2819 
2820     /**
2821      * The first warning reported by calls on this <code>CachedRowSetImpl</code>
2822      * object is returned. Subsequent <code>CachedRowSetImpl</code> warnings will
2823      * be chained to this <code>SQLWarning</code>.
2824      *
2825      * <P>The warning chain is automatically cleared each time a new
2826      * row is read.
2827      *
2828      * <P><B>Note:</B> This warning chain only covers warnings caused
2829      * by <code>ResultSet</code> methods.  Any warning caused by statement
2830      * methods (such as reading OUT parameters) will be chained on the
2831      * <code>Statement</code> object.
2832      *
2833      * @return the first SQLWarning or null
2834      */
2835     public SQLWarning getWarnings() {
2836         return sqlwarn;
2837     }
2838 
2839     /**
2840      * Clears all the warnings reporeted for the <code>CachedRowSetImpl</code>
2841      * object. After a call to this method, the <code>getWarnings</code> method
2842      * returns <code>null</code> until a new warning is reported for this
2843      * <code>CachedRowSetImpl</code> object.
2844      */
2845     public void clearWarnings() {
2846         sqlwarn = null;
2847     }
2848 
2849     /**
2850      * Retrieves the name of the SQL cursor used by this
2851      * <code>CachedRowSetImpl</code> object.
2852      *
2853      * <P>In SQL, a result table is retrieved through a cursor that is
2854      * named. The current row of a <code>ResultSet</code> can be updated or deleted
2855      * using a positioned update/delete statement that references the
2856      * cursor name. To ensure that the cursor has the proper isolation
2857      * level to support an update operation, the cursor's <code>SELECT</code>
2858      * statement should be of the form <code>select for update</code>.
2859      * If the <code>for update</code> clause
2860      * is omitted, positioned updates may fail.
2861      *
2862      * <P>JDBC supports this SQL feature by providing the name of the
2863      * SQL cursor used by a <code>ResultSet</code> object. The current row
2864      * of a result set is also the current row of this SQL cursor.
2865      *
2866      * <P><B>Note:</B> If positioned updates are not supported, an
2867      * <code>SQLException</code> is thrown.
2868      *
2869      * @return the SQL cursor name for this <code>CachedRowSetImpl</code> object's
2870      *         cursor
2871      * @throws SQLException if an error occurs
2872      */
2873     public String getCursorName() throws SQLException {
2874         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.posupdate").toString());
2875     }
2876 
2877     /**
2878      * Retrieves a <code>ResultSetMetaData</code> object instance that
2879      * contains information about the <code>CachedRowSet</code> object.
2880      * However, applications should cast the returned object to a
2881      * <code>RowSetMetaData</code> interface implementation. In the
2882      * reference implementation, this cast can be done on the
2883      * <code>RowSetMetaDataImpl</code> class.
2884      * <P>
2885      * For example:
2886      * <pre>
2887      * CachedRowSet crs = new CachedRowSetImpl();
2888      * RowSetMetaDataImpl metaData =
2889      *     (RowSetMetaDataImpl)crs.getMetaData();
2890      * // Set the number of columns in the RowSet object for
2891      * // which this RowSetMetaDataImpl object was created to the
2892      * // given number.
2893      * metaData.setColumnCount(3);
2894      * crs.setMetaData(metaData);
2895      * </pre>
2896      *
2897      * @return the <code>ResultSetMetaData</code> object that describes this
2898      *         <code>CachedRowSetImpl</code> object's columns
2899      * @throws SQLException if an error occurs in generating the RowSet
2900      * meta data; or if the <code>CachedRowSetImpl</code> is empty.
2901      * @see javax.sql.RowSetMetaData
2902      */
2903     public ResultSetMetaData getMetaData() throws SQLException {
2904         return (ResultSetMetaData)RowSetMD;
2905     }
2906 
2907 
2908     /**
2909      * Retrieves the value of the designated column in the current row
2910      * of this <code>CachedRowSetImpl</code> object as an
2911      * <code>Object</code> value.
2912      * <P>
2913      * The type of the <code>Object</code> will be the default
2914      * Java object type corresponding to the column's SQL type,
2915      * following the mapping for built-in types specified in the JDBC 3.0
2916      * specification.
2917      * <P>
2918      * This method may also be used to read datatabase-specific
2919      * abstract data types.
2920      * <P>
2921      * This implementation of the method <code>getObject</code> extends its
2922      * behavior so that it gets the attributes of an SQL structured type
2923      * as an array of <code>Object</code> values.  This method also custom
2924      * maps SQL user-defined types to classes in the Java programming language.
2925      * When the specified column contains
2926      * a structured or distinct value, the behavior of this method is as
2927      * if it were a call to the method <code>getObject(columnIndex,
2928      * this.getStatement().getConnection().getTypeMap())</code>.
2929      *
2930      * @param columnIndex the first column is <code>1</code>, the second
2931      *        is <code>2</code>, and so on; must be <code>1</code> or larger
2932      *        and equal to or less than the number of columns in the rowset
2933      * @return a <code>java.lang.Object</code> holding the column value;
2934      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
2935      * @throws SQLException if the given column index is out of bounds,
2936      *            the cursor is not on a valid row, or there is a problem getting
2937      *            the <code>Class</code> object for a custom mapping
2938      * @see #getObject(String)
2939      */
2940     public Object getObject(int columnIndex) throws SQLException {
2941         Object value;
2942         Map<String, Class<?>> map;
2943 
2944         // sanity check.
2945         checkIndex(columnIndex);
2946         // make sure the cursor is on a valid row
2947         checkCursor();
2948 
2949         setLastValueNull(false);
2950         value = getCurrentRow().getColumnObject(columnIndex);
2951 
2952         // check for SQL NULL
2953         if (value == null) {
2954             setLastValueNull(true);
2955             return null;
2956         }
2957         if (value instanceof Struct) {
2958             Struct s = (Struct)value;
2959             map = getTypeMap();
2960             // look up the class in the map
2961             Class c = (Class)map.get(s.getSQLTypeName());
2962             if (c != null) {
2963                 // create new instance of the class
2964                 SQLData obj = null;
2965                 try {
2966                     obj = (SQLData)c.newInstance();
2967                 } catch (java.lang.InstantiationException ex) {
2968                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
2969                     ex.getMessage()));
2970                 } catch (java.lang.IllegalAccessException ex) {
2971                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
2972                     ex.getMessage()));
2973                 }
2974                 // get the attributes from the struct
2975                 Object attribs[] = s.getAttributes(map);
2976                 // create the SQLInput "stream"
2977                 SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
2978                 // read the values...
2979                 obj.readSQL(sqlInput, s.getSQLTypeName());
2980                 return (Object)obj;
2981             }
2982         }
2983         return value;
2984     }
2985 
2986     /**
2987      * Retrieves the value of the designated column in the current row
2988      * of this <code>CachedRowSetImpl</code> object as an
2989      * <code>Object</code> value.
2990      * <P>
2991      * The type of the <code>Object</code> will be the default
2992      * Java object type corresponding to the column's SQL type,
2993      * following the mapping for built-in types specified in the JDBC 3.0
2994      * specification.
2995      * <P>
2996      * This method may also be used to read datatabase-specific
2997      * abstract data types.
2998      * <P>
2999      * This implementation of the method <code>getObject</code> extends its
3000      * behavior so that it gets the attributes of an SQL structured type
3001      * as an array of <code>Object</code> values.  This method also custom
3002      * maps SQL user-defined types to classes
3003      * in the Java programming language. When the specified column contains
3004      * a structured or distinct value, the behavior of this method is as
3005      * if it were a call to the method <code>getObject(columnIndex,
3006      * this.getStatement().getConnection().getTypeMap())</code>.
3007      *
3008      * @param columnName a <code>String</code> object that must match the
3009      *        SQL name of a column in this rowset, ignoring case
3010      * @return a <code>java.lang.Object</code> holding the column value;
3011      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3012      * @throws SQLException if (1) the given column name does not match one of
3013      *            this rowset's column names, (2) the cursor is not
3014      *            on a valid row, or (3) there is a problem getting
3015      *            the <code>Class</code> object for a custom mapping
3016      * @see #getObject(int)
3017      */
3018     public Object getObject(String columnName) throws SQLException {
3019         return getObject(getColIdxByName(columnName));
3020     }
3021 
3022     //----------------------------------------------------------------
3023 
3024     /**
3025      * Maps the given column name for one of this <code>CachedRowSetImpl</code>
3026      * object's columns to its column number.
3027      *
3028      * @param columnName a <code>String</code> object that must match the
3029      *        SQL name of a column in this rowset, ignoring case
3030      * @return the column index of the given column name
3031      * @throws SQLException if the given column name does not match one
3032      *            of this rowset's column names
3033      */
3034     public int findColumn(String columnName) throws SQLException {
3035         return getColIdxByName(columnName);
3036     }
3037 
3038 
3039     //--------------------------JDBC 2.0-----------------------------------
3040 
3041     //---------------------------------------------------------------------
3042     // Getter's and Setter's
3043     //---------------------------------------------------------------------
3044 
3045     /**
3046      * Retrieves the value stored in the designated column
3047      * of the current row as a <code>java.io.Reader</code> object.
3048      *
3049      * <P><B>Note:</B> All the data in the returned stream must
3050      * be read prior to getting the value of any other column. The
3051      * next call to a <code>getXXX</code> method implicitly closes the stream.
3052      *
3053      * @param columnIndex the first column is <code>1</code>, the second
3054      *        is <code>2</code>, and so on; must be <code>1</code> or larger
3055      *        and equal to or less than the number of columns in the rowset
3056      * @return a Java character stream that delivers the database column value
3057      * as a stream of two-byte unicode characters in a
3058      * <code>java.io.Reader</code> object.  If the value is
3059      * SQL <code>NULL</code>, the result is <code>null</code>.
3060      * @throws SQLException if (1) the given column index is out of bounds,
3061      * (2) the cursor is not on one of this rowset's rows or its
3062      * insert row, or (3) the designated column does not store an
3063      * SQL <code>CHAR, VARCHAR, <b>LONGVARCHAR</b>, BINARY, VARBINARY</code> or
3064      * <code>LONGVARBINARY</code> value.
3065      * The bold SQL type designates the recommended return type.
3066      * @see #getCharacterStream(String)
3067      */
3068     public java.io.Reader getCharacterStream(int columnIndex) throws SQLException{
3069 
3070         // sanity check.
3071         checkIndex(columnIndex);
3072         // make sure the cursor is on a valid row
3073         checkCursor();
3074 
3075         if (isBinary(RowSetMD.getColumnType(columnIndex))) {
3076             Object value = getCurrentRow().getColumnObject(columnIndex);
3077             if (value == null) {
3078                 lastValueNull = true;
3079                 return null;
3080             }
3081             charStream = new InputStreamReader
3082             (new ByteArrayInputStream((byte[])value));
3083         } else if (isString(RowSetMD.getColumnType(columnIndex))) {
3084             Object value = getCurrentRow().getColumnObject(columnIndex);
3085             if (value == null) {
3086                 lastValueNull = true;
3087                 return null;
3088             }
3089             charStream = new StringReader(value.toString());
3090         } else {
3091             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
3092         }
3093 
3094         return (java.io.Reader)charStream;
3095     }
3096 
3097     /**
3098      * Retrieves the value stored in the designated column
3099      * of the current row as a <code>java.io.Reader</code> object.
3100      *
3101      * <P><B>Note:</B> All the data in the returned stream must
3102      * be read prior to getting the value of any other column. The
3103      * next call to a <code>getXXX</code> method implicitly closes the stream.
3104      *
3105      * @param columnName a <code>String</code> object giving the SQL name of
3106      *        a column in this <code>CachedRowSetImpl</code> object
3107      * @return a Java input stream that delivers the database column value
3108      *         as a stream of two-byte Unicode characters.  If the value is
3109      *         SQL <code>NULL</code>, the result is <code>null</code>.
3110      * @throws SQLException if (1) the given column name is not the name of
3111      * a column in this rowset, (2) the cursor is not on one of
3112      * this rowset's rows or its insert row, or (3) the designated
3113      * column does not store an SQL <code>CHAR, VARCHAR, <b>LONGVARCHAR</b>,
3114      * BINARY, VARYBINARY</code> or <code>LONGVARBINARY</code> value.
3115      * The bold SQL type designates the recommended return type.
3116      */
3117     public java.io.Reader getCharacterStream(String columnName) throws SQLException {
3118         return getCharacterStream(getColIdxByName(columnName));
3119     }
3120 
3121     /**
3122      * Retrieves the value of the designated column in the current row
3123      * of this <code>CachedRowSetImpl</code> object as a
3124      * <code>java.math.BigDecimal</code> object.
3125      *
3126      * @param columnIndex the first column is <code>1</code>, the second
3127      *        is <code>2</code>, and so on; must be <code>1</code> or larger
3128      *        and equal to or less than the number of columns in the rowset
3129      * @return a <code>java.math.BigDecimal</code> value with full precision;
3130      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3131      * @throws SQLException if (1) the given column index is out of bounds,
3132      * (2) the cursor is not on one of this rowset's rows or its
3133      * insert row, or (3) the designated column does not store an
3134      * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
3135      * FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT, CHAR, VARCHAR</code>
3136      * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
3137      * recommended return types that this method is used to retrieve.
3138      * @see #getBigDecimal(String)
3139      */
3140     public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
3141         Object value;
3142 
3143         // sanity check.
3144         checkIndex(columnIndex);
3145         // make sure the cursor is on a valid row
3146         checkCursor();
3147 
3148         setLastValueNull(false);
3149         value = getCurrentRow().getColumnObject(columnIndex);
3150 
3151         // check for SQL NULL
3152         if (value == null) {
3153             setLastValueNull(true);
3154             return null;
3155         }
3156         try {
3157             return (new BigDecimal(value.toString().trim()));
3158         } catch (NumberFormatException ex) {
3159             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.doublefail").toString(),
3160                 new Object[] {value.toString().trim(), columnIndex}));
3161         }
3162     }
3163 
3164     /**
3165      * Retrieves the value of the designated column in the current row
3166      * of this <code>CachedRowSetImpl</code> object as a
3167      * <code>java.math.BigDecimal</code> object.
3168      *
3169      * @param columnName a <code>String</code> object that must match the
3170      *        SQL name of a column in this rowset, ignoring case
3171      * @return a <code>java.math.BigDecimal</code> value with full precision;
3172      *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3173      * @throws SQLException if (1) the given column name is not the name of
3174      * a column in this rowset, (2) the cursor is not on one of
3175      * this rowset's rows or its insert row, or (3) the designated
3176      * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
3177      * BIGINT, REAL, FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT CHAR,
3178      * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
3179      * designates the recommended return type that this method is used to
3180      * retrieve
3181      * @see #getBigDecimal(int)
3182      */
3183     public BigDecimal getBigDecimal(String columnName) throws SQLException {
3184         return getBigDecimal(getColIdxByName(columnName));
3185     }
3186 
3187     //---------------------------------------------------------------------
3188     // Traversal/Positioning
3189     //---------------------------------------------------------------------
3190 
3191     /**
3192      * Returns the number of rows in this <code>CachedRowSetImpl</code> object.
3193      *
3194      * @return number of rows in the rowset
3195      */
3196     public int size() {
3197         return numRows;
3198     }
3199 
3200     /**
3201      * Indicates whether the cursor is before the first row in this
3202      * <code>CachedRowSetImpl</code> object.
3203      *
3204      * @return <code>true</code> if the cursor is before the first row;
3205      *         <code>false</code> otherwise or if the rowset contains no rows
3206      * @throws SQLException if an error occurs
3207      */
3208     public boolean isBeforeFirst() throws SQLException {
3209         if (cursorPos == 0 && numRows > 0) {
3210             return true;
3211         } else {
3212             return false;
3213         }
3214     }
3215 
3216     /**
3217      * Indicates whether the cursor is after the last row in this
3218      * <code>CachedRowSetImpl</code> object.
3219      *
3220      * @return <code>true</code> if the cursor is after the last row;
3221      *         <code>false</code> otherwise or if the rowset contains no rows
3222      * @throws SQLException if an error occurs
3223      */
3224     public boolean isAfterLast() throws SQLException {
3225         if (cursorPos == numRows+1 && numRows > 0) {
3226             return true;
3227         } else {
3228             return false;
3229         }
3230     }
3231 
3232     /**
3233      * Indicates whether the cursor is on the first row in this
3234      * <code>CachedRowSetImpl</code> object.
3235      *
3236      * @return <code>true</code> if the cursor is on the first row;
3237      *         <code>false</code> otherwise or if the rowset contains no rows
3238      * @throws SQLException if an error occurs
3239      */
3240     public boolean isFirst() throws SQLException {
3241         // this becomes nasty because of deletes.
3242         int saveCursorPos = cursorPos;
3243         int saveAbsoluteCursorPos = absolutePos;
3244         internalFirst();
3245         if (cursorPos == saveCursorPos) {
3246             return true;
3247         } else {
3248             cursorPos = saveCursorPos;
3249             absolutePos = saveAbsoluteCursorPos;
3250             return false;
3251         }
3252     }
3253 
3254     /**
3255      * Indicates whether the cursor is on the last row in this
3256      * <code>CachedRowSetImpl</code> object.
3257      * <P>
3258      * Note: Calling the method <code>isLast</code> may be expensive
3259      * because the JDBC driver might need to fetch ahead one row in order
3260      * to determine whether the current row is the last row in this rowset.
3261      *
3262      * @return <code>true</code> if the cursor is on the last row;
3263      *         <code>false</code> otherwise or if this rowset contains no rows
3264      * @throws SQLException if an error occurs
3265      */
3266     public boolean isLast() throws SQLException {
3267         int saveCursorPos = cursorPos;
3268         int saveAbsoluteCursorPos = absolutePos;
3269         boolean saveShowDeleted = getShowDeleted();
3270         setShowDeleted(true);
3271         internalLast();
3272         if (cursorPos == saveCursorPos) {
3273             setShowDeleted(saveShowDeleted);
3274             return true;
3275         } else {
3276             setShowDeleted(saveShowDeleted);
3277             cursorPos = saveCursorPos;
3278             absolutePos = saveAbsoluteCursorPos;
3279             return false;
3280         }
3281     }
3282 
3283     /**
3284      * Moves this <code>CachedRowSetImpl</code> object's cursor to the front of
3285      * the rowset, just before the first row. This method has no effect if
3286      * this rowset contains no rows.
3287      *
3288      * @throws SQLException if an error occurs or the type of this rowset
3289      *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3290      */
3291     public void beforeFirst() throws SQLException {
3292        if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3293             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.beforefirst").toString());
3294         }
3295         cursorPos = 0;
3296         absolutePos = 0;
3297         notifyCursorMoved();
3298     }
3299 
3300     /**
3301      * Moves this <code>CachedRowSetImpl</code> object's cursor to the end of
3302      * the rowset, just after the last row. This method has no effect if
3303      * this rowset contains no rows.
3304      *
3305      * @throws SQLException if an error occurs
3306      */
3307     public void afterLast() throws SQLException {
3308         if (numRows > 0) {
3309             cursorPos = numRows + 1;
3310             absolutePos = 0;
3311             notifyCursorMoved();
3312         }
3313     }
3314 
3315     /**
3316      * Moves this <code>CachedRowSetImpl</code> object's cursor to the first row
3317      * and returns <code>true</code> if the operation was successful.  This
3318      * method also notifies registered listeners that the cursor has moved.
3319      *
3320      * @return <code>true</code> if the cursor is on a valid row;
3321      *         <code>false</code> otherwise or if there are no rows in this
3322      *         <code>CachedRowSetImpl</code> object
3323      * @throws SQLException if the type of this rowset
3324      *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3325      */
3326     public boolean first() throws SQLException {
3327         if(getType() == ResultSet.TYPE_FORWARD_ONLY) {
3328             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.first").toString());
3329         }
3330 
3331         // move and notify
3332         boolean ret = this.internalFirst();
3333         notifyCursorMoved();
3334 
3335         return ret;
3336     }
3337 
3338     /**
3339      * Moves this <code>CachedRowSetImpl</code> object's cursor to the first
3340      * row and returns <code>true</code> if the operation is successful.
3341      * <P>
3342      * This method is called internally by the methods <code>first</code>,
3343      * <code>isFirst</code>, and <code>absolute</code>.
3344      * It in turn calls the method <code>internalNext</code> in order to
3345      * handle the case where the first row is a deleted row that is not visible.
3346      * <p>
3347      * This is a implementation only method and is not required as a standard
3348      * implementation of the <code>CachedRowSet</code> interface.
3349      *
3350      * @return <code>true</code> if the cursor moved to the first row;
3351      *         <code>false</code> otherwise
3352      * @throws SQLException if an error occurs
3353      */
3354     protected boolean internalFirst() throws SQLException {
3355         boolean ret = false;
3356 
3357         if (numRows > 0) {
3358             cursorPos = 1;
3359             if ((getShowDeleted() == false) && (rowDeleted() == true)) {
3360                 ret = internalNext();
3361             } else {
3362                 ret = true;
3363             }
3364         }
3365 
3366         if (ret == true)
3367             absolutePos = 1;
3368         else
3369             absolutePos = 0;
3370 
3371         return ret;
3372     }
3373 
3374     /**
3375      * Moves this <code>CachedRowSetImpl</code> object's cursor to the last row
3376      * and returns <code>true</code> if the operation was successful.  This
3377      * method also notifies registered listeners that the cursor has moved.
3378      *
3379      * @return <code>true</code> if the cursor is on a valid row;
3380      *         <code>false</code> otherwise or if there are no rows in this
3381      *         <code>CachedRowSetImpl</code> object
3382      * @throws SQLException if the type of this rowset
3383      *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3384      */
3385     public boolean last() throws SQLException {
3386         if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3387             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.last").toString());
3388         }
3389 
3390         // move and notify
3391         boolean ret = this.internalLast();
3392         notifyCursorMoved();
3393 
3394         return ret;
3395     }
3396 
3397     /**
3398      * Moves this <code>CachedRowSetImpl</code> object's cursor to the last
3399      * row and returns <code>true</code> if the operation is successful.
3400      * <P>
3401      * This method is called internally by the method <code>last</code>
3402      * when rows have been deleted and the deletions are not visible.
3403      * The method <code>internalLast</code> handles the case where the
3404      * last row is a deleted row that is not visible by in turn calling
3405      * the method <code>internalPrevious</code>.
3406      * <p>
3407      * This is a implementation only method and is not required as a standard
3408      * implementation of the <code>CachedRowSet</code> interface.
3409      *
3410      * @return <code>true</code> if the cursor moved to the last row;
3411      *         <code>false</code> otherwise
3412      * @throws SQLException if an error occurs
3413      */
3414     protected boolean internalLast() throws SQLException {
3415         boolean ret = false;
3416 
3417         if (numRows > 0) {
3418             cursorPos = numRows;
3419             if ((getShowDeleted() == false) && (rowDeleted() == true)) {
3420                 ret = internalPrevious();
3421             } else {
3422                 ret = true;
3423             }
3424         }
3425         if (ret == true)
3426             absolutePos = numRows - numDeleted;
3427         else
3428             absolutePos = 0;
3429         return ret;
3430     }
3431 
3432     /**
3433      * Returns the number of the current row in this <code>CachedRowSetImpl</code>
3434      * object. The first row is number 1, the second number 2, and so on.
3435      *
3436      * @return the number of the current row;  <code>0</code> if there is no
3437      *         current row
3438      * @throws SQLException if an error occurs; or if the <code>CacheRowSetImpl</code>
3439      *         is empty
3440      */
3441     public int getRow() throws SQLException {
3442         // are we on a valid row? Valid rows are between first and last
3443         if (numRows > 0 &&
3444         cursorPos > 0 &&
3445         cursorPos < (numRows + 1) &&
3446         (getShowDeleted() == false && rowDeleted() == false)) {
3447             return absolutePos;
3448         } else if (getShowDeleted() == true) {
3449             return cursorPos;
3450         } else {
3451             return 0;
3452         }
3453     }
3454 
3455     /**
3456      * Moves this <code>CachedRowSetImpl</code> object's cursor to the row number
3457      * specified.
3458      *
3459      * <p>If the number is positive, the cursor moves to an absolute row with
3460      * respect to the beginning of the rowset.  The first row is row 1, the second
3461      * is row 2, and so on.  For example, the following command, in which
3462      * <code>crs</code> is a <code>CachedRowSetImpl</code> object, moves the cursor
3463      * to the fourth row, starting from the beginning of the rowset.
3464      * <PRE><code>
3465      *
3466      *    crs.absolute(4);
3467      *
3468      * </code> </PRE>
3469      * <P>
3470      * If the number is negative, the cursor moves to an absolute row position
3471      * with respect to the end of the rowset.  For example, calling
3472      * <code>absolute(-1)</code> positions the cursor on the last row,
3473      * <code>absolute(-2)</code> moves it on the next-to-last row, and so on.
3474      * If the <code>CachedRowSetImpl</code> object <code>crs</code> has five rows,
3475      * the following command moves the cursor to the fourth-to-last row, which
3476      * in the case of a  rowset with five rows, is also the second row, counting
3477      * from the beginning.
3478      * <PRE><code>
3479      *
3480      *    crs.absolute(-4);
3481      *
3482      * </code> </PRE>
3483      *
3484      * If the number specified is larger than the number of rows, the cursor
3485      * will move to the position after the last row. If the number specified
3486      * would move the cursor one or more rows before the first row, the cursor
3487      * moves to the position before the first row.
3488      * <P>
3489      * Note: Calling <code>absolute(1)</code> is the same as calling the
3490      * method <code>first()</code>.  Calling <code>absolute(-1)</code> is the
3491      * same as calling <code>last()</code>.
3492      *
3493      * @param row a positive number to indicate the row, starting row numbering from
3494      *        the first row, which is <code>1</code>; a negative number to indicate
3495      *        the row, starting row numbering from the last row, which is
3496      *        <code>-1</code>; it must not be <code>0</code>
3497      * @return <code>true</code> if the cursor is on the rowset; <code>false</code>
3498      *         otherwise
3499      * @throws SQLException if the given cursor position is <code>0</code> or the
3500      *            type of this rowset is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3501      */
3502     public boolean absolute( int row ) throws SQLException {
3503         if (row == 0 || getType() == ResultSet.TYPE_FORWARD_ONLY) {
3504             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.absolute").toString());
3505         }
3506 
3507         if (row > 0) { // we are moving foward
3508             if (row > numRows) {
3509                 // fell off the end
3510                 afterLast();
3511                 return false;
3512             } else {
3513                 if (absolutePos <= 0)
3514                     internalFirst();
3515             }
3516         } else { // we are moving backward
3517             if (cursorPos + row < 0) {
3518                 // fell off the front
3519                 beforeFirst();
3520                 return false;
3521             } else {
3522                 if (absolutePos >= 0)
3523                     internalLast();
3524             }
3525         }
3526 
3527         // Now move towards the absolute row that we're looking for
3528         while (absolutePos != row) {
3529             if (absolutePos < row) {
3530                 if (!internalNext())
3531                     break;
3532             }
3533             else {
3534                 if (!internalPrevious())
3535                     break;
3536             }
3537         }
3538 
3539         notifyCursorMoved();
3540 
3541         if (isAfterLast() || isBeforeFirst()) {
3542             return false;
3543         } else {
3544             return true;
3545         }
3546     }
3547 
3548     /**
3549      * Moves the cursor the specified number of rows from the current
3550      * position, with a positive number moving it forward and a
3551      * negative number moving it backward.
3552      * <P>
3553      * If the number is positive, the cursor moves the specified number of
3554      * rows toward the end of the rowset, starting at the current row.
3555      * For example, the following command, in which
3556      * <code>crs</code> is a <code>CachedRowSetImpl</code> object with 100 rows,
3557      * moves the cursor forward four rows from the current row.  If the
3558      * current row is 50, the cursor would move to row 54.
3559      * <PRE><code>
3560      *
3561      *    crs.relative(4);
3562      *
3563      * </code> </PRE>
3564      * <P>
3565      * If the number is negative, the cursor moves back toward the beginning
3566      * the specified number of rows, starting at the current row.
3567      * For example, calling the method
3568      * <code>absolute(-1)</code> positions the cursor on the last row,
3569      * <code>absolute(-2)</code> moves it on the next-to-last row, and so on.
3570      * If the <code>CachedRowSetImpl</code> object <code>crs</code> has five rows,
3571      * the following command moves the cursor to the fourth-to-last row, which
3572      * in the case of a  rowset with five rows, is also the second row
3573      * from the beginning.
3574      * <PRE><code>
3575      *
3576      *    crs.absolute(-4);
3577      *
3578      * </code> </PRE>
3579      *
3580      * If the number specified is larger than the number of rows, the cursor
3581      * will move to the position after the last row. If the number specified
3582      * would move the cursor one or more rows before the first row, the cursor
3583      * moves to the position before the first row. In both cases, this method
3584      * throws an <code>SQLException</code>.
3585      * <P>
3586      * Note: Calling <code>absolute(1)</code> is the same as calling the
3587      * method <code>first()</code>.  Calling <code>absolute(-1)</code> is the
3588      * same as calling <code>last()</code>.  Calling <code>relative(0)</code>
3589      * is valid, but it does not change the cursor position.
3590      *
3591      * @param rows an <code>int</code> indicating the number of rows to move
3592      *             the cursor, starting at the current row; a positive number
3593      *             moves the cursor forward; a negative number moves the cursor
3594      *             backward; must not move the cursor past the valid
3595      *             rows
3596      * @return <code>true</code> if the cursor is on a row in this
3597      *         <code>CachedRowSetImpl</code> object; <code>false</code>
3598      *         otherwise
3599      * @throws SQLException if there are no rows in this rowset, the cursor is
3600      *         positioned either before the first row or after the last row, or
3601      *         the rowset is type <code>ResultSet.TYPE_FORWARD_ONLY</code>
3602      */
3603     public boolean relative(int rows) throws SQLException {
3604         if (numRows == 0 || isBeforeFirst() ||
3605         isAfterLast() || getType() == ResultSet.TYPE_FORWARD_ONLY) {
3606             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.relative").toString());
3607         }
3608 
3609         if (rows == 0) {
3610             return true;
3611         }
3612 
3613         if (rows > 0) { // we are moving forward
3614             if (cursorPos + rows > numRows) {
3615                 // fell off the end
3616                 afterLast();
3617             } else {
3618                 for (int i=0; i < rows; i++) {
3619                     if (!internalNext())
3620                         break;
3621                 }
3622             }
3623         } else { // we are moving backward
3624             if (cursorPos + rows < 0) {
3625                 // fell off the front
3626                 beforeFirst();
3627             } else {
3628                 for (int i=rows; i < 0; i++) {
3629                     if (!internalPrevious())
3630                         break;
3631                 }
3632             }
3633         }
3634         notifyCursorMoved();
3635 
3636         if (isAfterLast() || isBeforeFirst()) {
3637             return false;
3638         } else {
3639             return true;
3640         }
3641     }
3642 
3643     /**
3644      * Moves this <code>CachedRowSetImpl</code> object's cursor to the
3645      * previous row and returns <code>true</code> if the cursor is on
3646      * a valid row or <code>false</code> if it is not.
3647      * This method also notifies all listeners registered with this
3648      * <code>CachedRowSetImpl</code> object that its cursor has moved.
3649      * <P>
3650      * Note: calling the method <code>previous()</code> is not the same
3651      * as calling the method <code>relative(-1)</code>.  This is true
3652      * because it is possible to call <code>previous()</code> from the insert
3653      * row, from after the last row, or from the current row, whereas
3654      * <code>relative</code> may only be called from the current row.
3655      * <P>
3656      * The method <code>previous</code> may used in a <code>while</code>
3657      * loop to iterate through a rowset starting after the last row
3658      * and moving toward the beginning. The loop ends when <code>previous</code>
3659      * returns <code>false</code>, meaning that there are no more rows.
3660      * For example, the following code fragment retrieves all the data in
3661      * the <code>CachedRowSetImpl</code> object <code>crs</code>, which has
3662      * three columns.  Note that the cursor must initially be positioned
3663      * after the last row so that the first call to the method
3664      * <code>previous</code> places the cursor on the last line.
3665      * <PRE> <code>
3666      *
3667      *     crs.afterLast();
3668      *     while (previous()) {
3669      *         String name = crs.getString(1);
3670      *         int age = crs.getInt(2);
3671      *         short ssn = crs.getShort(3);
3672      *         System.out.println(name + "   " + age + "   " + ssn);
3673      *     }
3674      *
3675      * </code> </PRE>
3676      * This method throws an <code>SQLException</code> if the cursor is not
3677      * on a row in the rowset, before the first row, or after the last row.
3678      *
3679      * @return <code>true</code> if the cursor is on a valid row;
3680      *         <code>false</code> if it is before the first row or after the
3681      *         last row
3682      * @throws SQLException if the cursor is not on a valid position or the
3683      *           type of this rowset is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3684      */
3685     public boolean previous() throws SQLException {
3686         if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3687             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.last").toString());
3688         }
3689         /*
3690          * make sure things look sane. The cursor must be
3691          * positioned in the rowset or before first (0) or
3692          * after last (numRows + 1)
3693          */
3694         if (cursorPos < 0 || cursorPos > numRows + 1) {
3695             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
3696         }
3697         // move and notify
3698         boolean ret = this.internalPrevious();
3699         notifyCursorMoved();
3700 
3701         return ret;
3702     }
3703 
3704     /**
3705      * Moves the cursor to the previous row in this <code>CachedRowSetImpl</code>
3706      * object, skipping past deleted rows that are not visible; returns
3707      * <code>true</code> if the cursor is on a row in this rowset and
3708      * <code>false</code> when the cursor goes before the first row.
3709      * <P>
3710      * This method is called internally by the method <code>previous</code>.
3711      * <P>
3712      * This is a implementation only method and is not required as a standard
3713      * implementation of the <code>CachedRowSet</code> interface.
3714      *
3715      * @return <code>true</code> if the cursor is on a row in this rowset;
3716      *         <code>false</code> when the cursor reaches the position before
3717      *         the first row
3718      * @throws SQLException if an error occurs
3719      */
3720     protected boolean internalPrevious() throws SQLException {
3721         boolean ret = false;
3722 
3723         do {
3724             if (cursorPos > 1) {
3725                 --cursorPos;
3726                 ret = true;
3727             } else if (cursorPos == 1) {
3728                 // decrement to before first
3729                 --cursorPos;
3730                 ret = false;
3731                 break;
3732             }
3733         } while ((getShowDeleted() == false) && (rowDeleted() == true));
3734 
3735         /*
3736          * Each call to internalPrevious may move the cursor
3737          * over multiple rows, the absolute postion moves one one row
3738          */
3739         if (ret == true)
3740             --absolutePos;
3741         else
3742             absolutePos = 0;
3743 
3744         return ret;
3745     }
3746 
3747 
3748     //---------------------------------------------------------------------
3749     // Updates
3750     //---------------------------------------------------------------------
3751 
3752     /**
3753      * Indicates whether the current row of this <code>CachedRowSetImpl</code>
3754      * object has been updated.  The value returned
3755      * depends on whether this rowset can detect updates: <code>false</code>
3756      * will always be returned if it does not detect updates.
3757      *
3758      * @return <code>true</code> if the row has been visibly updated
3759      *         by the owner or another and updates are detected;
3760      *         <code>false</code> otherwise
3761      * @throws SQLException if the cursor is on the insert row or not
3762      *            not on a valid row
3763      *
3764      * @see DatabaseMetaData#updatesAreDetected
3765      */
3766     public boolean rowUpdated() throws SQLException {
3767         // make sure the cursor is on a valid row
3768         checkCursor();
3769         if (onInsertRow == true) {
3770             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3771         }
3772         return(((Row)getCurrentRow()).getUpdated());
3773     }
3774 
3775     /**
3776      * Indicates whether the designated column of the current row of
3777      * this <code>CachedRowSetImpl</code> object has been updated. The
3778      * value returned depends on whether this rowset can detcted updates:
3779      * <code>false</code> will always be returned if it does not detect updates.
3780      *
3781      * @param idx the index identifier of the column that may be have been updated.
3782      * @return <code>true</code> is the designated column has been updated
3783      * and the rowset detects updates; <code>false</code> if the rowset has not
3784      * been updated or the rowset does not detect updates
3785      * @throws SQLException if the cursor is on the insert row or not
3786      *          on a valid row
3787      * @see DatabaseMetaData#updatesAreDetected
3788      */
3789     public boolean columnUpdated(int idx) throws SQLException {
3790         // make sure the cursor is on a valid row
3791         checkCursor();
3792         if (onInsertRow == true) {
3793             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3794         }
3795         return (((Row)getCurrentRow()).getColUpdated(idx - 1));
3796     }
3797 
3798     /**
3799      * Indicates whether the designated column of the current row of
3800      * this <code>CachedRowSetImpl</code> object has been updated. The
3801      * value returned depends on whether this rowset can detcted updates:
3802      * <code>false</code> will always be returned if it does not detect updates.
3803      *
3804      * @param columnName the <code>String</code> column name column that may be have
3805      * been updated.
3806      * @return <code>true</code> is the designated column has been updated
3807      * and the rowset detects updates; <code>false</code> if the rowset has not
3808      * been updated or the rowset does not detect updates
3809      * @throws SQLException if the cursor is on the insert row or not
3810      *          on a valid row
3811      * @see DatabaseMetaData#updatesAreDetected
3812      */
3813     public boolean columnUpdated(String columnName) throws SQLException {
3814         return columnUpdated(getColIdxByName(columnName));
3815     }
3816 
3817     /**
3818      * Indicates whether the current row has been inserted.  The value returned
3819      * depends on whether or not the rowset can detect visible inserts.
3820      *
3821      * @return <code>true</code> if a row has been inserted and inserts are detected;
3822      *         <code>false</code> otherwise
3823      * @throws SQLException if the cursor is on the insert row or not
3824      *            not on a valid row
3825      *
3826      * @see DatabaseMetaData#insertsAreDetected
3827      */
3828     public boolean rowInserted() throws SQLException {
3829         // make sure the cursor is on a valid row
3830         checkCursor();
3831         if (onInsertRow == true) {
3832             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3833         }
3834         return(((Row)getCurrentRow()).getInserted());
3835     }
3836 
3837     /**
3838      * Indicates whether the current row has been deleted.  A deleted row
3839      * may leave a visible "hole" in a rowset.  This method can be used to
3840      * detect such holes if the rowset can detect deletions. This method
3841      * will always return <code>false</code> if this rowset cannot detect
3842      * deletions.
3843      *
3844      * @return <code>true</code> if (1)the current row is blank, indicating that
3845      *         the row has been deleted, and (2)deletions are detected;
3846      *         <code>false</code> otherwise
3847      * @throws SQLException if the cursor is on a valid row in this rowset
3848      * @see DatabaseMetaData#deletesAreDetected
3849      */
3850     public boolean rowDeleted() throws SQLException {
3851         // make sure the cursor is on a valid row
3852 
3853         if (isAfterLast() == true ||
3854         isBeforeFirst() == true ||
3855         onInsertRow == true) {
3856 
3857             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
3858         }
3859         return(((Row)getCurrentRow()).getDeleted());
3860     }
3861 
3862     /**
3863      * Indicates whether the given SQL data type is a numberic type.
3864      *
3865      * @param type one of the constants from <code>java.sql.Types</code>
3866      * @return <code>true</code> if the given type is <code>NUMERIC</code>,'
3867      *         <code>DECIMAL</code>, <code>BIT</code>, <code>TINYINT</code>,
3868      *         <code>SMALLINT</code>, <code>INTEGER</code>, <code>BIGINT</code>,
3869      *         <code>REAL</code>, <code>DOUBLE</code>, or <code>FLOAT</code>;
3870      *         <code>false</code> otherwise
3871      */
3872     private boolean isNumeric(int type) {
3873         switch (type) {
3874             case java.sql.Types.NUMERIC:
3875             case java.sql.Types.DECIMAL:
3876             case java.sql.Types.BIT:
3877             case java.sql.Types.TINYINT:
3878             case java.sql.Types.SMALLINT:
3879             case java.sql.Types.INTEGER:
3880             case java.sql.Types.BIGINT:
3881             case java.sql.Types.REAL:
3882             case java.sql.Types.DOUBLE:
3883             case java.sql.Types.FLOAT:
3884                 return true;
3885             default:
3886                 return false;
3887         }
3888     }
3889 
3890     /**
3891      * Indicates whether the given SQL data type is a string type.
3892      *
3893      * @param type one of the constants from <code>java.sql.Types</code>
3894      * @return <code>true</code> if the given type is <code>CHAR</code>,'
3895      *         <code>VARCHAR</code>, or <code>LONGVARCHAR</code>;
3896      *         <code>false</code> otherwise
3897      */
3898     private boolean isString(int type) {
3899         switch (type) {
3900             case java.sql.Types.CHAR:
3901             case java.sql.Types.VARCHAR:
3902             case java.sql.Types.LONGVARCHAR:
3903                 return true;
3904             default:
3905                 return false;
3906         }
3907     }
3908 
3909     /**
3910      * Indicates whether the given SQL data type is a binary type.
3911      *
3912      * @param type one of the constants from <code>java.sql.Types</code>
3913      * @return <code>true</code> if the given type is <code>BINARY</code>,'
3914      *         <code>VARBINARY</code>, or <code>LONGVARBINARY</code>;
3915      *         <code>false</code> otherwise
3916      */
3917     private boolean isBinary(int type) {
3918         switch (type) {
3919             case java.sql.Types.BINARY:
3920             case java.sql.Types.VARBINARY:
3921             case java.sql.Types.LONGVARBINARY:
3922                 return true;
3923             default:
3924                 return false;
3925         }
3926     }
3927 
3928     /**
3929      * Indicates whether the given SQL data type is a temporal type.
3930      * This method is called internally by the conversion methods
3931      * <code>convertNumeric</code> and <code>convertTemporal</code>.
3932      *
3933      * @param type one of the constants from <code>java.sql.Types</code>
3934      * @return <code>true</code> if the given type is <code>DATE</code>,
3935      *         <code>TIME</code>, or <code>TIMESTAMP</code>;
3936      *         <code>false</code> otherwise
3937      */
3938     private boolean isTemporal(int type) {
3939         switch (type) {
3940             case java.sql.Types.DATE:
3941             case java.sql.Types.TIME:
3942             case java.sql.Types.TIMESTAMP:
3943                 return true;
3944             default:
3945                 return false;
3946         }
3947     }
3948 
3949     /**
3950      * Indicates whether the given SQL data type is a boolean type.
3951      * This method is called internally by the conversion methods
3952      * <code>convertNumeric</code> and <code>convertBoolean</code>.
3953      *
3954      * @param type one of the constants from <code>java.sql.Types</code>
3955      * @return <code>true</code> if the given type is <code>BIT</code>,
3956      *         , or <code>BOOLEAN</code>;
3957      *         <code>false</code> otherwise
3958      */
3959     private boolean isBoolean(int type) {
3960         switch (type) {
3961             case java.sql.Types.BIT:
3962             case java.sql.Types.BOOLEAN:
3963                 return true;
3964             default:
3965                 return false;
3966         }
3967     }
3968 
3969 
3970     /**
3971      * Converts the given <code>Object</code> in the Java programming language
3972      * to the standard mapping for the specified SQL target data type.
3973      * The conversion must be to a string or numeric type, but there are no
3974      * restrictions on the type to be converted.  If the source type and target
3975      * type are the same, the given object is simply returned.
3976      *
3977      * @param srcObj the <code>Object</code> in the Java programming language
3978      *               that is to be converted to the target type
3979      * @param srcType the data type that is the standard mapping in SQL of the
3980      *                object to be converted; must be one of the constants in
3981      *                <code>java.sql.Types</code>
3982      * @param trgType the SQL data type to which to convert the given object;
3983      *                must be one of the following constants in
3984      *                <code>java.sql.Types</code>: <code>NUMERIC</code>,
3985      *         <code>DECIMAL</code>, <code>BIT</code>, <code>TINYINT</code>,
3986      *         <code>SMALLINT</code>, <code>INTEGER</code>, <code>BIGINT</code>,
3987      *         <code>REAL</code>, <code>DOUBLE</code>, <code>FLOAT</code>,
3988      *         <code>VARCHAR</code>, <code>LONGVARCHAR</code>, or <code>CHAR</code>
3989      * @return an <code>Object</code> value.that is
3990      *         the standard object mapping for the target SQL type
3991      * @throws SQLException if the given target type is not one of the string or
3992      *         numeric types in <code>java.sql.Types</code>
3993      */
3994     private Object convertNumeric(Object srcObj, int srcType,
3995     int trgType) throws SQLException {
3996 
3997         if (srcType == trgType) {
3998             return srcObj;
3999         }
4000 
4001         if (isNumeric(trgType) == false && isString(trgType) == false) {
4002             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4003         }
4004 
4005         try {
4006             switch (trgType) {
4007                 case java.sql.Types.BIT:
4008                     Integer i = Integer.valueOf(srcObj.toString().trim());
4009                     return i.equals(Integer.valueOf((int)0)) ?
4010                     Boolean.valueOf(false) :
4011                         Boolean.valueOf(true);
4012                 case java.sql.Types.TINYINT:
4013                     return Byte.valueOf(srcObj.toString().trim());
4014                 case java.sql.Types.SMALLINT:
4015                     return Short.valueOf(srcObj.toString().trim());
4016                 case java.sql.Types.INTEGER:
4017                     return Integer.valueOf(srcObj.toString().trim());
4018                 case java.sql.Types.BIGINT:
4019                     return Long.valueOf(srcObj.toString().trim());
4020                 case java.sql.Types.NUMERIC:
4021                 case java.sql.Types.DECIMAL:
4022                     return new BigDecimal(srcObj.toString().trim());
4023                 case java.sql.Types.REAL:
4024                 case java.sql.Types.FLOAT:
4025                     return new Float(srcObj.toString().trim());
4026                 case java.sql.Types.DOUBLE:
4027                     return new Double(srcObj.toString().trim());
4028                 case java.sql.Types.CHAR:
4029                 case java.sql.Types.VARCHAR:
4030                 case java.sql.Types.LONGVARCHAR:
4031                     return srcObj.toString();
4032                 default:
4033                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString()+ trgType);
4034             }
4035         } catch (NumberFormatException ex) {
4036             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4037         }
4038     }
4039 
4040     /**
4041      * Converts the given <code>Object</code> in the Java programming language
4042      * to the standard object mapping for the specified SQL target data type.
4043      * The conversion must be to a string or temporal type, and there are also
4044      * restrictions on the type to be converted.
4045      * <P>
4046      * <TABLE ALIGN="CENTER" BORDER CELLPADDING=10 BORDERCOLOR="#0000FF"
4047      * <CAPTION ALIGN="CENTER"><B>Parameters and Return Values</B></CAPTION>
4048      * <TR>
4049      *   <TD><B>Source SQL Type</B>
4050      *   <TD><B>Target SQL Type</B>
4051      *   <TD><B>Object Returned</B>
4052      * </TR>
4053      * <TR>
4054      *   <TD><code>TIMESTAMP</code>
4055      *   <TD><code>DATE</code>
4056      *   <TD><code>java.sql.Date</code>
4057      * </TR>
4058      * <TR>
4059      *   <TD><code>TIMESTAMP</code>
4060      *   <TD><code>TIME</code>
4061      *   <TD><code>java.sql.Time</code>
4062      * </TR>
4063      * <TR>
4064      *   <TD><code>TIME</code>
4065      *   <TD><code>TIMESTAMP</code>
4066      *   <TD><code>java.sql.Timestamp</code>
4067      * </TR>
4068      * <TR>
4069      *   <TD><code>DATE</code>, <code>TIME</code>, or <code>TIMESTAMP</code>
4070      *   <TD><code>CHAR</code>, <code>VARCHAR</code>, or <code>LONGVARCHAR</code>
4071      *   <TD><code>java.lang.String</code>
4072      * </TR>
4073      * </TABLE>
4074      * <P>
4075      * If the source type and target type are the same,
4076      * the given object is simply returned.
4077      *
4078      * @param srcObj the <code>Object</code> in the Java programming language
4079      *               that is to be converted to the target type
4080      * @param srcType the data type that is the standard mapping in SQL of the
4081      *                object to be converted; must be one of the constants in
4082      *                <code>java.sql.Types</code>
4083      * @param trgType the SQL data type to which to convert the given object;
4084      *                must be one of the following constants in
4085      *                <code>java.sql.Types</code>: <code>DATE</code>,
4086      *         <code>TIME</code>, <code>TIMESTAMP</code>, <code>CHAR</code>,
4087      *         <code>VARCHAR</code>, or <code>LONGVARCHAR</code>
4088      * @return an <code>Object</code> value.that is
4089      *         the standard object mapping for the target SQL type
4090      * @throws SQLException if the given target type is not one of the string or
4091      *         temporal types in <code>java.sql.Types</code>
4092      */
4093     private Object convertTemporal(Object srcObj,
4094     int srcType, int trgType) throws SQLException {
4095 
4096         if (srcType == trgType) {
4097             return srcObj;
4098         }
4099 
4100         if (isNumeric(trgType) == true ||
4101         (isString(trgType) == false && isTemporal(trgType) == false)) {
4102             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4103         }
4104 
4105         try {
4106             switch (trgType) {
4107                 case java.sql.Types.DATE:
4108                     if (srcType == java.sql.Types.TIMESTAMP) {
4109                         return new java.sql.Date(((java.sql.Timestamp)srcObj).getTime());
4110                     } else {
4111                         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4112                     }
4113                 case java.sql.Types.TIMESTAMP:
4114                     if (srcType == java.sql.Types.TIME) {
4115                         return new Timestamp(((java.sql.Time)srcObj).getTime());
4116                     } else {
4117                         return new Timestamp(((java.sql.Date)srcObj).getTime());
4118                     }
4119                 case java.sql.Types.TIME:
4120                     if (srcType == java.sql.Types.TIMESTAMP) {
4121                         return new Time(((java.sql.Timestamp)srcObj).getTime());
4122                     } else {
4123                         throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4124                     }
4125                 case java.sql.Types.CHAR:
4126                 case java.sql.Types.VARCHAR:
4127                 case java.sql.Types.LONGVARCHAR:
4128                     return srcObj.toString();
4129                 default:
4130                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4131             }
4132         } catch (NumberFormatException ex) {
4133             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4134         }
4135 
4136     }
4137 
4138     /**
4139      * Converts the given <code>Object</code> in the Java programming language
4140      * to the standard mapping for the specified SQL target data type.
4141      * The conversion must be to a string or numeric type, but there are no
4142      * restrictions on the type to be converted.  If the source type and target
4143      * type are the same, the given object is simply returned.
4144      *
4145      * @param srcObj the <code>Object</code> in the Java programming language
4146      *               that is to be converted to the target type
4147      * @param srcType the data type that is the standard mapping in SQL of the
4148      *                object to be converted; must be one of the constants in
4149      *                <code>java.sql.Types</code>
4150      * @param trgType the SQL data type to which to convert the given object;
4151      *                must be one of the following constants in
4152      *                <code>java.sql.Types</code>: <code>BIT</code>,
4153      *         or <code>BOOLEAN</code>
4154      * @return an <code>Object</code> value.that is
4155      *         the standard object mapping for the target SQL type
4156      * @throws SQLException if the given target type is not one of the Boolean
4157      *         types in <code>java.sql.Types</code>
4158      */
4159     private Object convertBoolean(Object srcObj, int srcType,
4160     int trgType) throws SQLException {
4161 
4162         if (srcType == trgType) {
4163             return srcObj;
4164         }
4165 
4166         if (isNumeric(trgType) == true ||
4167         (isString(trgType) == false && isBoolean(trgType) == false)) {
4168             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4169         }
4170 
4171 
4172         try {
4173             switch (trgType) {
4174                 case java.sql.Types.BIT:
4175                     Integer i = Integer.valueOf(srcObj.toString().trim());
4176                     return i.equals(Integer.valueOf((int)0)) ?
4177                     Boolean.valueOf(false) :
4178                         Boolean.valueOf(true);
4179                 case java.sql.Types.BOOLEAN:
4180                     return Boolean.valueOf(srcObj.toString().trim());
4181                 default:
4182                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString()+ trgType);
4183             }
4184         } catch (NumberFormatException ex) {
4185             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4186         }
4187     }
4188 
4189     /**
4190      * Sets the designated nullable column in the current row or the
4191      * insert row of this <code>CachedRowSetImpl</code> object with
4192      * <code>null</code> value.
4193      * <P>
4194      * This method updates a column value in the current row or the insert
4195      * row of this rowset; however, another method must be called to complete
4196      * the update process. If the cursor is on a row in the rowset, the
4197      * method {@link #updateRow} must be called to mark the row as updated
4198      * and to notify listeners that the row has changed.
4199      * If the cursor is on the insert row, the method {@link #insertRow}
4200      * must be called to insert the new row into this rowset and to notify
4201      * listeners that a row has changed.
4202      * <P>
4203      * In order to propagate updates in this rowset to the underlying
4204      * data source, an application must call the method {@link #acceptChanges}
4205      * after it calls either <code>updateRow</code> or <code>insertRow</code>.
4206      *
4207      * @param columnIndex the first column is <code>1</code>, the second
4208      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4209      *        and equal to or less than the number of columns in this rowset
4210      * @throws SQLException if (1) the given column index is out of bounds,
4211      *            (2) the cursor is not on one of this rowset's rows or its
4212      *            insert row, or (3) this rowset is
4213      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4214      */
4215     public void updateNull(int columnIndex) throws SQLException {
4216         // sanity check.
4217         checkIndex(columnIndex);
4218         // make sure the cursor is on a valid row
4219         checkCursor();
4220 
4221         BaseRow row = getCurrentRow();
4222         row.setColumnObject(columnIndex, null);
4223 
4224     }
4225 
4226     /**
4227      * Sets the designated column in either the current row or the insert
4228      * row of this <code>CachedRowSetImpl</code> object with the given
4229      * <code>boolean</code> value.
4230      * <P>
4231      * This method updates a column value in the current row or the insert
4232      * row of this rowset, but it does not update the database.
4233      * If the cursor is on a row in the rowset, the
4234      * method {@link #updateRow} must be called to update the database.
4235      * If the cursor is on the insert row, the method {@link #insertRow}
4236      * must be called, which will insert the new row into both this rowset
4237      * and the database. Both of these methods must be called before the
4238      * cursor moves to another row.
4239      *
4240      * @param columnIndex the first column is <code>1</code>, the second
4241      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4242      *        and equal to or less than the number of columns in this rowset
4243      * @param x the new column value
4244      * @throws SQLException if (1) the given column index is out of bounds,
4245      *            (2) the cursor is not on one of this rowset's rows or its
4246      *            insert row, or (3) this rowset is
4247      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4248      */
4249     public void updateBoolean(int columnIndex, boolean x) throws SQLException {
4250         // sanity check.
4251         checkIndex(columnIndex);
4252         // make sure the cursor is on a valid row
4253         checkCursor();
4254         Object obj = convertBoolean(Boolean.valueOf(x),
4255         java.sql.Types.BIT,
4256         RowSetMD.getColumnType(columnIndex));
4257 
4258         getCurrentRow().setColumnObject(columnIndex, obj);
4259     }
4260 
4261     /**
4262      * Sets the designated column in either the current row or the insert
4263      * row of this <code>CachedRowSetImpl</code> object with the given
4264      * <code>byte</code> value.
4265      * <P>
4266      * This method updates a column value in the current row or the insert
4267      * row of this rowset, but it does not update the database.
4268      * If the cursor is on a row in the rowset, the
4269      * method {@link #updateRow} must be called to update the database.
4270      * If the cursor is on the insert row, the method {@link #insertRow}
4271      * must be called, which will insert the new row into both this rowset
4272      * and the database. Both of these methods must be called before the
4273      * cursor moves to another row.
4274      *
4275      * @param columnIndex the first column is <code>1</code>, the second
4276      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4277      *        and equal to or less than the number of columns in this rowset
4278      * @param x the new column value
4279      * @throws SQLException if (1) the given column index is out of bounds,
4280      *            (2) the cursor is not on one of this rowset's rows or its
4281      *            insert row, or (3) this rowset is
4282      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4283      */
4284     public void updateByte(int columnIndex, byte x) throws SQLException {
4285         // sanity check.
4286         checkIndex(columnIndex);
4287         // make sure the cursor is on a valid row
4288         checkCursor();
4289 
4290         Object obj = convertNumeric(Byte.valueOf(x),
4291         java.sql.Types.TINYINT,
4292         RowSetMD.getColumnType(columnIndex));
4293 
4294         getCurrentRow().setColumnObject(columnIndex, obj);
4295     }
4296 
4297     /**
4298      * Sets the designated column in either the current row or the insert
4299      * row of this <code>CachedRowSetImpl</code> object with the given
4300      * <code>short</code> value.
4301      * <P>
4302      * This method updates a column value in the current row or the insert
4303      * row of this rowset, but it does not update the database.
4304      * If the cursor is on a row in the rowset, the
4305      * method {@link #updateRow} must be called to update the database.
4306      * If the cursor is on the insert row, the method {@link #insertRow}
4307      * must be called, which will insert the new row into both this rowset
4308      * and the database. Both of these methods must be called before the
4309      * cursor moves to another row.
4310      *
4311      * @param columnIndex the first column is <code>1</code>, the second
4312      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4313      *        and equal to or less than the number of columns in this rowset
4314      * @param x the new column value
4315      * @throws SQLException if (1) the given column index is out of bounds,
4316      *            (2) the cursor is not on one of this rowset's rows or its
4317      *            insert row, or (3) this rowset is
4318      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4319      */
4320     public void updateShort(int columnIndex, short x) throws SQLException {
4321         // sanity check.
4322         checkIndex(columnIndex);
4323         // make sure the cursor is on a valid row
4324         checkCursor();
4325 
4326         Object obj = convertNumeric(Short.valueOf(x),
4327         java.sql.Types.SMALLINT,
4328         RowSetMD.getColumnType(columnIndex));
4329 
4330         getCurrentRow().setColumnObject(columnIndex, obj);
4331     }
4332 
4333     /**
4334      * Sets the designated column in either the current row or the insert
4335      * row of this <code>CachedRowSetImpl</code> object with the given
4336      * <code>int</code> value.
4337      * <P>
4338      * This method updates a column value in the current row or the insert
4339      * row of this rowset, but it does not update the database.
4340      * If the cursor is on a row in the rowset, the
4341      * method {@link #updateRow} must be called to update the database.
4342      * If the cursor is on the insert row, the method {@link #insertRow}
4343      * must be called, which will insert the new row into both this rowset
4344      * and the database. Both of these methods must be called before the
4345      * cursor moves to another row.
4346      *
4347      * @param columnIndex the first column is <code>1</code>, the second
4348      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4349      *        and equal to or less than the number of columns in this rowset
4350      * @param x the new column value
4351      * @throws SQLException if (1) the given column index is out of bounds,
4352      *            (2) the cursor is not on one of this rowset's rows or its
4353      *            insert row, or (3) this rowset is
4354      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4355      */
4356     public void updateInt(int columnIndex, int x) throws SQLException {
4357         // sanity check.
4358         checkIndex(columnIndex);
4359         // make sure the cursor is on a valid row
4360         checkCursor();
4361         Object obj = convertNumeric(Integer.valueOf(x),
4362         java.sql.Types.INTEGER,
4363         RowSetMD.getColumnType(columnIndex));
4364 
4365         getCurrentRow().setColumnObject(columnIndex, obj);
4366     }
4367 
4368     /**
4369      * Sets the designated column in either the current row or the insert
4370      * row of this <code>CachedRowSetImpl</code> object with the given
4371      * <code>long</code> value.
4372      * <P>
4373      * This method updates a column value in the current row or the insert
4374      * row of this rowset, but it does not update the database.
4375      * If the cursor is on a row in the rowset, the
4376      * method {@link #updateRow} must be called to update the database.
4377      * If the cursor is on the insert row, the method {@link #insertRow}
4378      * must be called, which will insert the new row into both this rowset
4379      * and the database. Both of these methods must be called before the
4380      * cursor moves to another row.
4381      *
4382      * @param columnIndex the first column is <code>1</code>, the second
4383      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4384      *        and equal to or less than the number of columns in this rowset
4385      * @param x the new column value
4386      * @throws SQLException if (1) the given column index is out of bounds,
4387      *            (2) the cursor is not on one of this rowset's rows or its
4388      *            insert row, or (3) this rowset is
4389      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4390      */
4391     public void updateLong(int columnIndex, long x) throws SQLException {
4392         // sanity check.
4393         checkIndex(columnIndex);
4394         // make sure the cursor is on a valid row
4395         checkCursor();
4396 
4397         Object obj = convertNumeric(Long.valueOf(x),
4398         java.sql.Types.BIGINT,
4399         RowSetMD.getColumnType(columnIndex));
4400 
4401         getCurrentRow().setColumnObject(columnIndex, obj);
4402 
4403     }
4404 
4405     /**
4406      * Sets the designated column in either the current row or the insert
4407      * row of this <code>CachedRowSetImpl</code> object with the given
4408      * <code>float</code> value.
4409      * <P>
4410      * This method updates a column value in the current row or the insert
4411      * row of this rowset, but it does not update the database.
4412      * If the cursor is on a row in the rowset, the
4413      * method {@link #updateRow} must be called to update the database.
4414      * If the cursor is on the insert row, the method {@link #insertRow}
4415      * must be called, which will insert the new row into both this rowset
4416      * and the database. Both of these methods must be called before the
4417      * cursor moves to another row.
4418      *
4419      * @param columnIndex the first column is <code>1</code>, the second
4420      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4421      *        and equal to or less than the number of columns in this rowset
4422      * @param x the new column value
4423      * @throws SQLException if (1) the given column index is out of bounds,
4424      *            (2) the cursor is not on one of this rowset's rows or its
4425      *            insert row, or (3) this rowset is
4426      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4427      */
4428     public void updateFloat(int columnIndex, float x) throws SQLException {
4429         // sanity check.
4430         checkIndex(columnIndex);
4431         // make sure the cursor is on a valid row
4432         checkCursor();
4433 
4434         Object obj = convertNumeric(new Float(x),
4435         java.sql.Types.REAL,
4436         RowSetMD.getColumnType(columnIndex));
4437 
4438         getCurrentRow().setColumnObject(columnIndex, obj);
4439     }
4440 
4441     /**
4442      * Sets the designated column in either the current row or the insert
4443      * row of this <code>CachedRowSetImpl</code> object with the given
4444      * <code>double</code> value.
4445      *
4446      * This method updates a column value in either the current row or
4447      * the insert row of this rowset, but it does not update the
4448      * database.  If the cursor is on a row in the rowset, the
4449      * method {@link #updateRow} must be called to update the database.
4450      * If the cursor is on the insert row, the method {@link #insertRow}
4451      * must be called, which will insert the new row into both this rowset
4452      * and the database. Both of these methods must be called before the
4453      * cursor moves to another row.
4454      *
4455      * @param columnIndex the first column is <code>1</code>, the second
4456      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4457      *        and equal to or less than the number of columns in this rowset
4458      * @param x the new column value
4459      * @throws SQLException if (1) the given column index is out of bounds,
4460      *            (2) the cursor is not on one of this rowset's rows or its
4461      *            insert row, or (3) this rowset is
4462      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4463      */
4464     public void updateDouble(int columnIndex, double x) throws SQLException {
4465         // sanity check.
4466         checkIndex(columnIndex);
4467         // make sure the cursor is on a valid row
4468         checkCursor();
4469         Object obj = convertNumeric(new Double(x),
4470         java.sql.Types.DOUBLE,
4471         RowSetMD.getColumnType(columnIndex));
4472 
4473         getCurrentRow().setColumnObject(columnIndex, obj);
4474     }
4475 
4476     /**
4477      * Sets the designated column in either the current row or the insert
4478      * row of this <code>CachedRowSetImpl</code> object with the given
4479      * <code>java.math.BigDecimal</code> object.
4480      * <P>
4481      * This method updates a column value in the current row or the insert
4482      * row of this rowset, but it does not update the database.
4483      * If the cursor is on a row in the rowset, the
4484      * method {@link #updateRow} must be called to update the database.
4485      * If the cursor is on the insert row, the method {@link #insertRow}
4486      * must be called, which will insert the new row into both this rowset
4487      * and the database. Both of these methods must be called before the
4488      * cursor moves to another row.
4489      *
4490      * @param columnIndex the first column is <code>1</code>, the second
4491      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4492      *        and equal to or less than the number of columns in this rowset
4493      * @param x the new column value
4494      * @throws SQLException if (1) the given column index is out of bounds,
4495      *            (2) the cursor is not on one of this rowset's rows or its
4496      *            insert row, or (3) this rowset is
4497      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4498      */
4499     public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {
4500         // sanity check.
4501         checkIndex(columnIndex);
4502         // make sure the cursor is on a valid row
4503         checkCursor();
4504 
4505         Object obj = convertNumeric(x,
4506         java.sql.Types.NUMERIC,
4507         RowSetMD.getColumnType(columnIndex));
4508 
4509         getCurrentRow().setColumnObject(columnIndex, obj);
4510     }
4511 
4512     /**
4513      * Sets the designated column in either the current row or the insert
4514      * row of this <code>CachedRowSetImpl</code> object with the given
4515      * <code>String</code> object.
4516      * <P>
4517      * This method updates a column value in either the current row or
4518      * the insert row of this rowset, but it does not update the
4519      * database.  If the cursor is on a row in the rowset, the
4520      * method {@link #updateRow} must be called to mark the row as updated.
4521      * If the cursor is on the insert row, the method {@link #insertRow}
4522      * must be called to insert the new row into this rowset and mark it
4523      * as inserted. Both of these methods must be called before the
4524      * cursor moves to another row.
4525      * <P>
4526      * The method <code>acceptChanges</code> must be called if the
4527      * updated values are to be written back to the underlying database.
4528      *
4529      * @param columnIndex the first column is <code>1</code>, the second
4530      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4531      *        and equal to or less than the number of columns in this rowset
4532      * @param x the new column value
4533      * @throws SQLException if (1) the given column index is out of bounds,
4534      *            (2) the cursor is not on one of this rowset's rows or its
4535      *            insert row, or (3) this rowset is
4536      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4537      */
4538     public void updateString(int columnIndex, String x) throws SQLException {
4539         // sanity check.
4540         checkIndex(columnIndex);
4541         // make sure the cursor is on a valid row
4542         checkCursor();
4543 
4544         getCurrentRow().setColumnObject(columnIndex, x);
4545     }
4546 
4547     /**
4548      * Sets the designated column in either the current row or the insert
4549      * row of this <code>CachedRowSetImpl</code> object with the given
4550      * <code>byte</code> array.
4551      *
4552      * This method updates a column value in either the current row or
4553      * the insert row of this rowset, but it does not update the
4554      * database.  If the cursor is on a row in the rowset, the
4555      * method {@link #updateRow} must be called to update the database.
4556      * If the cursor is on the insert row, the method {@link #insertRow}
4557      * must be called, which will insert the new row into both this rowset
4558      * and the database. Both of these methods must be called before the
4559      * cursor moves to another row.
4560      *
4561      * @param columnIndex the first column is <code>1</code>, the second
4562      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4563      *        and equal to or less than the number of columns in this rowset
4564      * @param x the new column value
4565      * @throws SQLException if (1) the given column index is out of bounds,
4566      *            (2) the cursor is not on one of this rowset's rows or its
4567      *            insert row, or (3) this rowset is
4568      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4569      */
4570     public void updateBytes(int columnIndex, byte x[]) throws SQLException {
4571         // sanity check.
4572         checkIndex(columnIndex);
4573         // make sure the cursor is on a valid row
4574         checkCursor();
4575 
4576         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4577             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4578         }
4579 
4580         getCurrentRow().setColumnObject(columnIndex, x);
4581     }
4582 
4583     /**
4584      * Sets the designated column in either the current row or the insert
4585      * row of this <code>CachedRowSetImpl</code> object with the given
4586      * <code>Date</code> object.
4587      *
4588      * This method updates a column value in either the current row or
4589      * the insert row of this rowset, but it does not update the
4590      * database.  If the cursor is on a row in the rowset, the
4591      * method {@link #updateRow} must be called to update the database.
4592      * If the cursor is on the insert row, the method {@link #insertRow}
4593      * must be called, which will insert the new row into both this rowset
4594      * and the database. Both of these methods must be called before the
4595      * cursor moves to another row.
4596      *
4597      * @param columnIndex the first column is <code>1</code>, the second
4598      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4599      *        and equal to or less than the number of columns in this rowset
4600      * @param x the new column value
4601      * @throws SQLException if (1) the given column index is out of bounds,
4602      *            (2) the cursor is not on one of this rowset's rows or its
4603      *            insert row, (3) the type of the designated column is not
4604      *            an SQL <code>DATE</code> or <code>TIMESTAMP</code>, or
4605      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4606      */
4607     public void updateDate(int columnIndex, java.sql.Date x) throws SQLException {
4608         // sanity check.
4609         checkIndex(columnIndex);
4610         // make sure the cursor is on a valid row
4611         checkCursor();
4612 
4613         Object obj = convertTemporal(x,
4614         java.sql.Types.DATE,
4615         RowSetMD.getColumnType(columnIndex));
4616 
4617         getCurrentRow().setColumnObject(columnIndex, obj);
4618     }
4619 
4620     /**
4621      * Sets the designated column in either the current row or the insert
4622      * row of this <code>CachedRowSetImpl</code> object with the given
4623      * <code>Time</code> object.
4624      *
4625      * This method updates a column value in either the current row or
4626      * the insert row of this rowset, but it does not update the
4627      * database.  If the cursor is on a row in the rowset, the
4628      * method {@link #updateRow} must be called to update the database.
4629      * If the cursor is on the insert row, the method {@link #insertRow}
4630      * must be called, which will insert the new row into both this rowset
4631      * and the database. Both of these methods must be called before the
4632      * cursor moves to another row.
4633      *
4634      * @param columnIndex the first column is <code>1</code>, the second
4635      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4636      *        and equal to or less than the number of columns in this rowset
4637      * @param x the new column value
4638      * @throws SQLException if (1) the given column index is out of bounds,
4639      *            (2) the cursor is not on one of this rowset's rows or its
4640      *            insert row, (3) the type of the designated column is not
4641      *            an SQL <code>TIME</code> or <code>TIMESTAMP</code>, or
4642      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4643      */
4644     public void updateTime(int columnIndex, java.sql.Time x) throws SQLException {
4645         // sanity check.
4646         checkIndex(columnIndex);
4647         // make sure the cursor is on a valid row
4648         checkCursor();
4649 
4650         Object obj = convertTemporal(x,
4651         java.sql.Types.TIME,
4652         RowSetMD.getColumnType(columnIndex));
4653 
4654         getCurrentRow().setColumnObject(columnIndex, obj);
4655     }
4656 
4657     /**
4658      * Sets the designated column in either the current row or the insert
4659      * row of this <code>CachedRowSetImpl</code> object with the given
4660      * <code>Timestamp</code> object.
4661      *
4662      * This method updates a column value in either the current row or
4663      * the insert row of this rowset, but it does not update the
4664      * database.  If the cursor is on a row in the rowset, the
4665      * method {@link #updateRow} must be called to update the database.
4666      * If the cursor is on the insert row, the method {@link #insertRow}
4667      * must be called, which will insert the new row into both this rowset
4668      * and the database. Both of these methods must be called before the
4669      * cursor moves to another row.
4670      *
4671      * @param columnIndex the first column is <code>1</code>, the second
4672      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4673      *        and equal to or less than the number of columns in this rowset
4674      * @param x the new column value
4675      * @throws SQLException if (1) the given column index is out of bounds,
4676      *            (2) the cursor is not on one of this rowset's rows or its
4677      *            insert row, (3) the type of the designated column is not
4678      *            an SQL <code>DATE</code>, <code>TIME</code>, or
4679      *            <code>TIMESTAMP</code>, or (4) this rowset is
4680      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4681      */
4682     public void updateTimestamp(int columnIndex, java.sql.Timestamp x) throws SQLException {
4683         // sanity check.
4684         checkIndex(columnIndex);
4685         // make sure the cursor is on a valid row
4686         checkCursor();
4687 
4688         Object obj = convertTemporal(x,
4689         java.sql.Types.TIMESTAMP,
4690         RowSetMD.getColumnType(columnIndex));
4691 
4692         getCurrentRow().setColumnObject(columnIndex, obj);
4693     }
4694 
4695     /**
4696      * Sets the designated column in either the current row or the insert
4697      * row of this <code>CachedRowSetImpl</code> object with the given
4698      * ASCII stream value.
4699      * <P>
4700      * This method updates a column value in either the current row or
4701      * the insert row of this rowset, but it does not update the
4702      * database.  If the cursor is on a row in the rowset, the
4703      * method {@link #updateRow} must be called to update the database.
4704      * If the cursor is on the insert row, the method {@link #insertRow}
4705      * must be called, which will insert the new row into both this rowset
4706      * and the database. Both of these methods must be called before the
4707      * cursor moves to another row.
4708      *
4709      * @param columnIndex the first column is <code>1</code>, the second
4710      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4711      *        and equal to or less than the number of columns in this rowset
4712      * @param x the new column value
4713      * @param length the number of one-byte ASCII characters in the stream
4714      * @throws SQLException if this method is invoked
4715      */
4716     public void updateAsciiStream(int columnIndex, java.io.InputStream x, int length) throws SQLException {
4717         // sanity Check
4718         checkIndex(columnIndex);
4719         // make sure the cursor is on a valid row
4720         checkCursor();
4721 
4722 
4723         if (isString(RowSetMD.getColumnType(columnIndex)) == false &&
4724         isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4725             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4726         }
4727 
4728         byte buf[] = new byte[length];
4729         try {
4730             int charsRead = 0;
4731             do {
4732                 charsRead += x.read(buf, charsRead, length - charsRead);
4733             } while (charsRead != length);
4734             //Changed the condition check to check for length instead of -1
4735         } catch (java.io.IOException ex) {
4736             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.asciistream").toString());
4737         }
4738         String str = new String(buf);
4739 
4740         getCurrentRow().setColumnObject(columnIndex, str);
4741 
4742     }
4743 
4744     /**
4745      * Sets the designated column in either the current row or the insert
4746      * row of this <code>CachedRowSetImpl</code> object with the given
4747      * <code>java.io.InputStream</code> object.
4748      * <P>
4749      * This method updates a column value in either the current row or
4750      * the insert row of this rowset, but it does not update the
4751      * database.  If the cursor is on a row in the rowset, the
4752      * method {@link #updateRow} must be called to update the database.
4753      * If the cursor is on the insert row, the method {@link #insertRow}
4754      * must be called, which will insert the new row into both this rowset
4755      * and the database. Both of these methods must be called before the
4756      * cursor moves to another row.
4757      *
4758      * @param columnIndex the first column is <code>1</code>, the second
4759      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4760      *        and equal to or less than the number of columns in this rowset
4761      * @param x the new column value; must be a <code>java.io.InputStream</code>
4762      *          containing <code>BINARY</code>, <code>VARBINARY</code>, or
4763      *          <code>LONGVARBINARY</code> data
4764      * @param length the length of the stream in bytes
4765      * @throws SQLException if (1) the given column index is out of bounds,
4766      *            (2) the cursor is not on one of this rowset's rows or its
4767      *            insert row, (3) the data in the stream is not binary, or
4768      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4769      */
4770     public void updateBinaryStream(int columnIndex, java.io.InputStream x,int length) throws SQLException {
4771         // sanity Check
4772         checkIndex(columnIndex);
4773         // make sure the cursor is on a valid row
4774         checkCursor();
4775 
4776         if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4777             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4778         }
4779 
4780         byte buf[] = new byte[length];
4781         try {
4782             int bytesRead = 0;
4783             do {
4784                 bytesRead += x.read(buf, bytesRead, length - bytesRead);
4785             } while (bytesRead != -1);
4786         } catch (java.io.IOException ex) {
4787             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.binstream").toString());
4788         }
4789 
4790         getCurrentRow().setColumnObject(columnIndex, buf);
4791     }
4792 
4793     /**
4794      * Sets the designated column in either the current row or the insert
4795      * row of this <code>CachedRowSetImpl</code> object with the given
4796      * <code>java.io.Reader</code> object.
4797      * <P>
4798      * This method updates a column value in either the current row or
4799      * the insert row of this rowset, but it does not update the
4800      * database.  If the cursor is on a row in the rowset, the
4801      * method {@link #updateRow} must be called to update the database.
4802      * If the cursor is on the insert row, the method {@link #insertRow}
4803      * must be called, which will insert the new row into both this rowset
4804      * and the database. Both of these methods must be called before the
4805      * cursor moves to another row.
4806      *
4807      * @param columnIndex the first column is <code>1</code>, the second
4808      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4809      *        and equal to or less than the number of columns in this rowset
4810      * @param x the new column value; must be a <code>java.io.Reader</code>
4811      *          containing <code>BINARY</code>, <code>VARBINARY</code>,
4812      *          <code>LONGVARBINARY</code>, <code>CHAR</code>, <code>VARCHAR</code>,
4813      *          or <code>LONGVARCHAR</code> data
4814      * @param length the length of the stream in characters
4815      * @throws SQLException if (1) the given column index is out of bounds,
4816      *            (2) the cursor is not on one of this rowset's rows or its
4817      *            insert row, (3) the data in the stream is not a binary or
4818      *            character type, or (4) this rowset is
4819      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4820      */
4821     public void updateCharacterStream(int columnIndex, java.io.Reader x, int length) throws SQLException {
4822         // sanity Check
4823         checkIndex(columnIndex);
4824         // make sure the cursor is on a valid row
4825         checkCursor();
4826 
4827         if (isString(RowSetMD.getColumnType(columnIndex)) == false &&
4828         isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4829             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4830         }
4831 
4832         char buf[] = new char[length];
4833         try {
4834             int charsRead = 0;
4835             do {
4836                 charsRead += x.read(buf, charsRead, length - charsRead);
4837             } while (charsRead != length);
4838             //Changed the condition checking to check for length instead of -1
4839         } catch (java.io.IOException ex) {
4840             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.binstream").toString());
4841         }
4842         String str = new String(buf);
4843 
4844         getCurrentRow().setColumnObject(columnIndex, str);
4845     }
4846 
4847     /**
4848      * Sets the designated column in either the current row or the insert
4849      * row of this <code>CachedRowSetImpl</code> object with the given
4850      * <code>Object</code> value.  The <code>scale</code> parameter indicates
4851      * the number of digits to the right of the decimal point and is ignored
4852      * if the new column value is not a type that will be mapped to an SQL
4853      * <code>DECIMAL</code> or <code>NUMERIC</code> value.
4854      * <P>
4855      * This method updates a column value in either the current row or
4856      * the insert row of this rowset, but it does not update the
4857      * database.  If the cursor is on a row in the rowset, the
4858      * method {@link #updateRow} must be called to update the database.
4859      * If the cursor is on the insert row, the method {@link #insertRow}
4860      * must be called, which will insert the new row into both this rowset
4861      * and the database. Both of these methods must be called before the
4862      * cursor moves to another row.
4863      *
4864      * @param columnIndex the first column is <code>1</code>, the second
4865      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4866      *        and equal to or less than the number of columns in this rowset
4867      * @param x the new column value
4868      * @param scale the number of digits to the right of the decimal point (for
4869      *              <code>DECIMAL</code> and <code>NUMERIC</code> types only)
4870      * @throws SQLException if (1) the given column index is out of bounds,
4871      *            (2) the cursor is not on one of this rowset's rows or its
4872      *            insert row, or (3) this rowset is
4873      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4874      */
4875     public void updateObject(int columnIndex, Object x, int scale) throws SQLException {
4876         // sanity check.
4877         checkIndex(columnIndex);
4878         // make sure the cursor is on a valid row
4879         checkCursor();
4880 
4881         int type = RowSetMD.getColumnType(columnIndex);
4882         if (type == Types.DECIMAL || type == Types.NUMERIC) {
4883             ((java.math.BigDecimal)x).setScale(scale);
4884         }
4885         getCurrentRow().setColumnObject(columnIndex, x);
4886     }
4887 
4888     /**
4889      * Sets the designated column in either the current row or the insert
4890      * row of this <code>CachedRowSetImpl</code> object with the given
4891      * <code>Object</code> value.
4892      * <P>
4893      * This method updates a column value in either the current row or
4894      * the insert row of this rowset, but it does not update the
4895      * database.  If the cursor is on a row in the rowset, the
4896      * method {@link #updateRow} must be called to update the database.
4897      * If the cursor is on the insert row, the method {@link #insertRow}
4898      * must be called, which will insert the new row into both this rowset
4899      * and the database. Both of these methods must be called before the
4900      * cursor moves to another row.
4901      *
4902      * @param columnIndex the first column is <code>1</code>, the second
4903      *        is <code>2</code>, and so on; must be <code>1</code> or larger
4904      *        and equal to or less than the number of columns in this rowset
4905      * @param x the new column value
4906      * @throws SQLException if (1) the given column index is out of bounds,
4907      *            (2) the cursor is not on one of this rowset's rows or its
4908      *            insert row, or (3) this rowset is
4909      *            <code>ResultSet.CONCUR_READ_ONLY</code>
4910      */
4911     public void updateObject(int columnIndex, Object x) throws SQLException {
4912         // sanity check.
4913         checkIndex(columnIndex);
4914         // make sure the cursor is on a valid row
4915         checkCursor();
4916 
4917         getCurrentRow().setColumnObject(columnIndex, x);
4918     }
4919 
4920     /**
4921      * Sets the designated nullable column in the current row or the
4922      * insert row of this <code>CachedRowSetImpl</code> object with
4923      * <code>null</code> value.
4924      * <P>
4925      * This method updates a column value in the current row or the insert
4926      * row of this rowset, but it does not update the database.
4927      * If the cursor is on a row in the rowset, the
4928      * method {@link #updateRow} must be called to update the database.
4929      * If the cursor is on the insert row, the method {@link #insertRow}
4930      * must be called, which will insert the new row into both this rowset
4931      * and the database.
4932      *
4933      * @param columnName a <code>String</code> object that must match the
4934      *        SQL name of a column in this rowset, ignoring case
4935      * @throws SQLException if (1) the given column name does not match the
4936      *            name of a column in this rowset, (2) the cursor is not on
4937      *            one of this rowset's rows or its insert row, or (3) this
4938      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4939      */
4940     public void updateNull(String columnName) throws SQLException {
4941         updateNull(getColIdxByName(columnName));
4942     }
4943 
4944     /**
4945      * Sets the designated column in either the current row or the insert
4946      * row of this <code>CachedRowSetImpl</code> object with the given
4947      * <code>boolean</code> value.
4948      * <P>
4949      * This method updates a column value in the current row or the insert
4950      * row of this rowset, but it does not update the database.
4951      * If the cursor is on a row in the rowset, the
4952      * method {@link #updateRow} must be called to update the database.
4953      * If the cursor is on the insert row, the method {@link #insertRow}
4954      * must be called, which will insert the new row into both this rowset
4955      * and the database. Both of these methods must be called before the
4956      * cursor moves to another row.
4957      *
4958      * @param columnName a <code>String</code> object that must match the
4959      *        SQL name of a column in this rowset, ignoring case
4960      * @param x the new column value
4961      * @throws SQLException if (1) the given column name does not match the
4962      *            name of a column in this rowset, (2) the cursor is not on
4963      *            one of this rowset's rows or its insert row, or (3) this
4964      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4965      */
4966     public void updateBoolean(String columnName, boolean x) throws SQLException {
4967         updateBoolean(getColIdxByName(columnName), x);
4968     }
4969 
4970     /**
4971      * Sets the designated column in either the current row or the insert
4972      * row of this <code>CachedRowSetImpl</code> object with the given
4973      * <code>byte</code> value.
4974      * <P>
4975      * This method updates a column value in the current row or the insert
4976      * row of this rowset, but it does not update the database.
4977      * If the cursor is on a row in the rowset, the
4978      * method {@link #updateRow} must be called to update the database.
4979      * If the cursor is on the insert row, the method {@link #insertRow}
4980      * must be called, which will insert the new row into both this rowset
4981      * and the database. Both of these methods must be called before the
4982      * cursor moves to another row.
4983      *
4984      * @param columnName a <code>String</code> object that must match the
4985      *        SQL name of a column in this rowset, ignoring case
4986      * @param x the new column value
4987      * @throws SQLException if (1) the given column name does not match the
4988      *            name of a column in this rowset, (2) the cursor is not on
4989      *            one of this rowset's rows or its insert row, or (3) this
4990      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4991      */
4992     public void updateByte(String columnName, byte x) throws SQLException {
4993         updateByte(getColIdxByName(columnName), x);
4994     }
4995 
4996     /**
4997      * Sets the designated column in either the current row or the insert
4998      * row of this <code>CachedRowSetImpl</code> object with the given
4999      * <code>short</code> value.
5000      * <P>
5001      * This method updates a column value in the current row or the insert
5002      * row of this rowset, but it does not update the database.
5003      * If the cursor is on a row in the rowset, the
5004      * method {@link #updateRow} must be called to update the database.
5005      * If the cursor is on the insert row, the method {@link #insertRow}
5006      * must be called, which will insert the new row into both this rowset
5007      * and the database. Both of these methods must be called before the
5008      * cursor moves to another row.
5009      *
5010      * @param columnName a <code>String</code> object that must match the
5011      *        SQL name of a column in this rowset, ignoring case
5012      * @param x the new column value
5013      * @throws SQLException if (1) the given column name does not match the
5014      *            name of a column in this rowset, (2) the cursor is not on
5015      *            one of this rowset's rows or its insert row, or (3) this
5016      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5017      */
5018     public void updateShort(String columnName, short x) throws SQLException {
5019         updateShort(getColIdxByName(columnName), x);
5020     }
5021 
5022     /**
5023      * Sets the designated column in either the current row or the insert
5024      * row of this <code>CachedRowSetImpl</code> object with the given
5025      * <code>int</code> value.
5026      * <P>
5027      * This method updates a column value in the current row or the insert
5028      * row of this rowset, but it does not update the database.
5029      * If the cursor is on a row in the rowset, the
5030      * method {@link #updateRow} must be called to update the database.
5031      * If the cursor is on the insert row, the method {@link #insertRow}
5032      * must be called, which will insert the new row into both this rowset
5033      * and the database. Both of these methods must be called before the
5034      * cursor moves to another row.
5035      *
5036      * @param columnName a <code>String</code> object that must match the
5037      *        SQL name of a column in this rowset, ignoring case
5038      * @param x the new column value
5039      * @throws SQLException if (1) the given column name does not match the
5040      *            name of a column in this rowset, (2) the cursor is not on
5041      *            one of this rowset's rows or its insert row, or (3) this
5042      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5043      */
5044     public void updateInt(String columnName, int x) throws SQLException {
5045         updateInt(getColIdxByName(columnName), x);
5046     }
5047 
5048     /**
5049      * Sets the designated column in either the current row or the insert
5050      * row of this <code>CachedRowSetImpl</code> object with the given
5051      * <code>long</code> value.
5052      * <P>
5053      * This method updates a column value in the current row or the insert
5054      * row of this rowset, but it does not update the database.
5055      * If the cursor is on a row in the rowset, the
5056      * method {@link #updateRow} must be called to update the database.
5057      * If the cursor is on the insert row, the method {@link #insertRow}
5058      * must be called, which will insert the new row into both this rowset
5059      * and the database. Both of these methods must be called before the
5060      * cursor moves to another row.
5061      *
5062      * @param columnName a <code>String</code> object that must match the
5063      *        SQL name of a column in this rowset, ignoring case
5064      * @param x the new column value
5065      * @throws SQLException if (1) the given column name does not match the
5066      *            name of a column in this rowset, (2) the cursor is not on
5067      *            one of this rowset's rows or its insert row, or (3) this
5068      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5069      */
5070     public void updateLong(String columnName, long x) throws SQLException {
5071         updateLong(getColIdxByName(columnName), x);
5072     }
5073 
5074     /**
5075      * Sets the designated column in either the current row or the insert
5076      * row of this <code>CachedRowSetImpl</code> object with the given
5077      * <code>float</code> value.
5078      * <P>
5079      * This method updates a column value in the current row or the insert
5080      * row of this rowset, but it does not update the database.
5081      * If the cursor is on a row in the rowset, the
5082      * method {@link #updateRow} must be called to update the database.
5083      * If the cursor is on the insert row, the method {@link #insertRow}
5084      * must be called, which will insert the new row into both this rowset
5085      * and the database. Both of these methods must be called before the
5086      * cursor moves to another row.
5087      *
5088      * @param columnName a <code>String</code> object that must match the
5089      *        SQL name of a column in this rowset, ignoring case
5090      * @param x the new column value
5091      * @throws SQLException if (1) the given column name does not match the
5092      *            name of a column in this rowset, (2) the cursor is not on
5093      *            one of this rowset's rows or its insert row, or (3) this
5094      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5095      */
5096     public void updateFloat(String columnName, float x) throws SQLException {
5097         updateFloat(getColIdxByName(columnName), x);
5098     }
5099 
5100     /**
5101      * Sets the designated column in either the current row or the insert
5102      * row of this <code>CachedRowSetImpl</code> object with the given
5103      * <code>double</code> value.
5104      *
5105      * This method updates a column value in either the current row or
5106      * the insert row of this rowset, but it does not update the
5107      * database.  If the cursor is on a row in the rowset, the
5108      * method {@link #updateRow} must be called to update the database.
5109      * If the cursor is on the insert row, the method {@link #insertRow}
5110      * must be called, which will insert the new row into both this rowset
5111      * and the database. Both of these methods must be called before the
5112      * cursor moves to another row.
5113      *
5114      * @param columnName a <code>String</code> object that must match the
5115      *        SQL name of a column in this rowset, ignoring case
5116      * @param x the new column value
5117      * @throws SQLException if (1) the given column name does not match the
5118      *            name of a column in this rowset, (2) the cursor is not on
5119      *            one of this rowset's rows or its insert row, or (3) this
5120      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5121      */
5122     public void updateDouble(String columnName, double x) throws SQLException {
5123         updateDouble(getColIdxByName(columnName), x);
5124     }
5125 
5126     /**
5127      * Sets the designated column in either the current row or the insert
5128      * row of this <code>CachedRowSetImpl</code> object with the given
5129      * <code>java.math.BigDecimal</code> object.
5130      * <P>
5131      * This method updates a column value in the current row or the insert
5132      * row of this rowset, but it does not update the database.
5133      * If the cursor is on a row in the rowset, the
5134      * method {@link #updateRow} must be called to update the database.
5135      * If the cursor is on the insert row, the method {@link #insertRow}
5136      * must be called, which will insert the new row into both this rowset
5137      * and the database. Both of these methods must be called before the
5138      * cursor moves to another row.
5139      *
5140      * @param columnName a <code>String</code> object that must match the
5141      *        SQL name of a column in this rowset, ignoring case
5142      * @param x the new column value
5143      * @throws SQLException if (1) the given column name does not match the
5144      *            name of a column in this rowset, (2) the cursor is not on
5145      *            one of this rowset's rows or its insert row, or (3) this
5146      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5147      */
5148     public void updateBigDecimal(String columnName, BigDecimal x) throws SQLException {
5149         updateBigDecimal(getColIdxByName(columnName), x);
5150     }
5151 
5152     /**
5153      * Sets the designated column in either the current row or the insert
5154      * row of this <code>CachedRowSetImpl</code> object with the given
5155      * <code>String</code> object.
5156      *
5157      * This method updates a column value in either the current row or
5158      * the insert row of this rowset, but it does not update the
5159      * database.  If the cursor is on a row in the rowset, the
5160      * method {@link #updateRow} must be called to update the database.
5161      * If the cursor is on the insert row, the method {@link #insertRow}
5162      * must be called, which will insert the new row into both this rowset
5163      * and the database. Both of these methods must be called before the
5164      * cursor moves to another row.
5165      *
5166      * @param columnName a <code>String</code> object that must match the
5167      *        SQL name of a column in this rowset, ignoring case
5168      * @param x the new column value
5169      * @throws SQLException if (1) the given column name does not match the
5170      *            name of a column in this rowset, (2) the cursor is not on
5171      *            one of this rowset's rows or its insert row, or (3) this
5172      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5173      */
5174     public void updateString(String columnName, String x) throws SQLException {
5175         updateString(getColIdxByName(columnName), x);
5176     }
5177 
5178     /**
5179      * Sets the designated column in either the current row or the insert
5180      * row of this <code>CachedRowSetImpl</code> object with the given
5181      * <code>byte</code> array.
5182      *
5183      * This method updates a column value in either the current row or
5184      * the insert row of this rowset, but it does not update the
5185      * database.  If the cursor is on a row in the rowset, the
5186      * method {@link #updateRow} must be called to update the database.
5187      * If the cursor is on the insert row, the method {@link #insertRow}
5188      * must be called, which will insert the new row into both this rowset
5189      * and the database. Both of these methods must be called before the
5190      * cursor moves to another row.
5191      *
5192      * @param columnName a <code>String</code> object that must match the
5193      *        SQL name of a column in this rowset, ignoring case
5194      * @param x the new column value
5195      * @throws SQLException if (1) the given column name does not match the
5196      *            name of a column in this rowset, (2) the cursor is not on
5197      *            one of this rowset's rows or its insert row, or (3) this
5198      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5199      */
5200     public void updateBytes(String columnName, byte x[]) throws SQLException {
5201         updateBytes(getColIdxByName(columnName), x);
5202     }
5203 
5204     /**
5205      * Sets the designated column in either the current row or the insert
5206      * row of this <code>CachedRowSetImpl</code> object with the given
5207      * <code>Date</code> object.
5208      *
5209      * This method updates a column value in either the current row or
5210      * the insert row of this rowset, but it does not update the
5211      * database.  If the cursor is on a row in the rowset, the
5212      * method {@link #updateRow} must be called to update the database.
5213      * If the cursor is on the insert row, the method {@link #insertRow}
5214      * must be called, which will insert the new row into both this rowset
5215      * and the database. Both of these methods must be called before the
5216      * cursor moves to another row.
5217      *
5218      * @param columnName a <code>String</code> object that must match the
5219      *        SQL name of a column in this rowset, ignoring case
5220      * @param x the new column value
5221      * @throws SQLException if (1) the given column name does not match the
5222      *            name of a column in this rowset, (2) the cursor is not on
5223      *            one of this rowset's rows or its insert row, (3) the type
5224      *            of the designated column is not an SQL <code>DATE</code> or
5225      *            <code>TIMESTAMP</code>, or (4) this rowset is
5226      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5227      */
5228     public void updateDate(String columnName, java.sql.Date x) throws SQLException {
5229         updateDate(getColIdxByName(columnName), x);
5230     }
5231 
5232     /**
5233      * Sets the designated column in either the current row or the insert
5234      * row of this <code>CachedRowSetImpl</code> object with the given
5235      * <code>Time</code> object.
5236      *
5237      * This method updates a column value in either the current row or
5238      * the insert row of this rowset, but it does not update the
5239      * database.  If the cursor is on a row in the rowset, the
5240      * method {@link #updateRow} must be called to update the database.
5241      * If the cursor is on the insert row, the method {@link #insertRow}
5242      * must be called, which will insert the new row into both this rowset
5243      * and the database. Both of these methods must be called before the
5244      * cursor moves to another row.
5245      *
5246      * @param columnName a <code>String</code> object that must match the
5247      *        SQL name of a column in this rowset, ignoring case
5248      * @param x the new column value
5249      * @throws SQLException if (1) the given column name does not match the
5250      *            name of a column in this rowset, (2) the cursor is not on
5251      *            one of this rowset's rows or its insert row, (3) the type
5252      *            of the designated column is not an SQL <code>TIME</code> or
5253      *            <code>TIMESTAMP</code>, or (4) this rowset is
5254      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5255      */
5256     public void updateTime(String columnName, java.sql.Time x) throws SQLException {
5257         updateTime(getColIdxByName(columnName), x);
5258     }
5259 
5260     /**
5261      * Sets the designated column in either the current row or the insert
5262      * row of this <code>CachedRowSetImpl</code> object with the given
5263      * <code>Timestamp</code> object.
5264      *
5265      * This method updates a column value in either the current row or
5266      * the insert row of this rowset, but it does not update the
5267      * database.  If the cursor is on a row in the rowset, the
5268      * method {@link #updateRow} must be called to update the database.
5269      * If the cursor is on the insert row, the method {@link #insertRow}
5270      * must be called, which will insert the new row into both this rowset
5271      * and the database. Both of these methods must be called before the
5272      * cursor moves to another row.
5273      *
5274      * @param columnName a <code>String</code> object that must match the
5275      *        SQL name of a column in this rowset, ignoring case
5276      * @param x the new column value
5277      * @throws SQLException if the given column index is out of bounds or
5278      *            the cursor is not on one of this rowset's rows or its
5279      *            insert row
5280      * @throws SQLException if (1) the given column name does not match the
5281      *            name of a column in this rowset, (2) the cursor is not on
5282      *            one of this rowset's rows or its insert row, (3) the type
5283      *            of the designated column is not an SQL <code>DATE</code>,
5284      *            <code>TIME</code>, or <code>TIMESTAMP</code>, or (4) this
5285      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5286      */
5287     public void updateTimestamp(String columnName, java.sql.Timestamp x) throws SQLException {
5288         updateTimestamp(getColIdxByName(columnName), x);
5289     }
5290 
5291     /**
5292      * Sets the designated column in either the current row or the insert
5293      * row of this <code>CachedRowSetImpl</code> object with the given
5294      * ASCII stream value.
5295      * <P>
5296      * This method updates a column value in either the current row or
5297      * the insert row of this rowset, but it does not update the
5298      * database.  If the cursor is on a row in the rowset, the
5299      * method {@link #updateRow} must be called to update the database.
5300      * If the cursor is on the insert row, the method {@link #insertRow}
5301      * must be called, which will insert the new row into both this rowset
5302      * and the database. Both of these methods must be called before the
5303      * cursor moves to another row.
5304      *
5305      * @param columnName a <code>String</code> object that must match the
5306      *        SQL name of a column in this rowset, ignoring case
5307      * @param x the new column value
5308      * @param length the number of one-byte ASCII characters in the stream
5309      */
5310     public void updateAsciiStream(String columnName,
5311     java.io.InputStream x,
5312     int length) throws SQLException {
5313         updateAsciiStream(getColIdxByName(columnName), x, length);
5314     }
5315 
5316     /**
5317      * Sets the designated column in either the current row or the insert
5318      * row of this <code>CachedRowSetImpl</code> object with the given
5319      * <code>java.io.InputStream</code> object.
5320      * <P>
5321      * This method updates a column value in either the current row or
5322      * the insert row of this rowset, but it does not update the
5323      * database.  If the cursor is on a row in the rowset, the
5324      * method {@link #updateRow} must be called to update the database.
5325      * If the cursor is on the insert row, the method {@link #insertRow}
5326      * must be called, which will insert the new row into both this rowset
5327      * and the database. Both of these methods must be called before the
5328      * cursor moves to another row.
5329      *
5330      * @param columnName a <code>String</code> object that must match the
5331      *        SQL name of a column in this rowset, ignoring case
5332      * @param x the new column value; must be a <code>java.io.InputStream</code>
5333      *          containing <code>BINARY</code>, <code>VARBINARY</code>, or
5334      *          <code>LONGVARBINARY</code> data
5335      * @param length the length of the stream in bytes
5336      * @throws SQLException if (1) the given column name does not match the
5337      *            name of a column in this rowset, (2) the cursor is not on
5338      *            one of this rowset's rows or its insert row, (3) the data
5339      *            in the stream is not binary, or (4) this rowset is
5340      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5341      */
5342     public void updateBinaryStream(String columnName, java.io.InputStream x, int length) throws SQLException {
5343         updateBinaryStream(getColIdxByName(columnName), x, length);
5344     }
5345 
5346     /**
5347      * Sets the designated column in either the current row or the insert
5348      * row of this <code>CachedRowSetImpl</code> object with the given
5349      * <code>java.io.Reader</code> object.
5350      * <P>
5351      * This method updates a column value in either the current row or
5352      * the insert row of this rowset, but it does not update the
5353      * database.  If the cursor is on a row in the rowset, the
5354      * method {@link #updateRow} must be called to update the database.
5355      * If the cursor is on the insert row, the method {@link #insertRow}
5356      * must be called, which will insert the new row into both this rowset
5357      * and the database. Both of these methods must be called before the
5358      * cursor moves to another row.
5359      *
5360      * @param columnName a <code>String</code> object that must match the
5361      *        SQL name of a column in this rowset, ignoring case
5362      * @param reader the new column value; must be a
5363      * <code>java.io.Reader</code> containing <code>BINARY</code>,
5364      * <code>VARBINARY</code>, <code>LONGVARBINARY</code>, <code>CHAR</code>,
5365      * <code>VARCHAR</code>, or <code>LONGVARCHAR</code> data
5366      * @param length the length of the stream in characters
5367      * @throws SQLException if (1) the given column name does not match the
5368      *            name of a column in this rowset, (2) the cursor is not on
5369      *            one of this rowset's rows or its insert row, (3) the data
5370      *            in the stream is not a binary or character type, or (4) this
5371      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5372      */
5373     public void updateCharacterStream(String columnName,
5374     java.io.Reader reader,
5375     int length) throws SQLException {
5376         updateCharacterStream(getColIdxByName(columnName), reader, length);
5377     }
5378 
5379     /**
5380      * Sets the designated column in either the current row or the insert
5381      * row of this <code>CachedRowSetImpl</code> object with the given
5382      * <code>Object</code> value.  The <code>scale</code> parameter
5383      * indicates the number of digits to the right of the decimal point
5384      * and is ignored if the new column value is not a type that will be
5385      *  mapped to an SQL <code>DECIMAL</code> or <code>NUMERIC</code> value.
5386      * <P>
5387      * This method updates a column value in either the current row or
5388      * the insert row of this rowset, but it does not update the
5389      * database.  If the cursor is on a row in the rowset, the
5390      * method {@link #updateRow} must be called to update the database.
5391      * If the cursor is on the insert row, the method {@link #insertRow}
5392      * must be called, which will insert the new row into both this rowset
5393      * and the database. Both of these methods must be called before the
5394      * cursor moves to another row.
5395      *
5396      * @param columnName a <code>String</code> object that must match the
5397      *        SQL name of a column in this rowset, ignoring case
5398      * @param x the new column value
5399      * @param scale the number of digits to the right of the decimal point (for
5400      *              <code>DECIMAL</code> and <code>NUMERIC</code> types only)
5401      * @throws SQLException if (1) the given column name does not match the
5402      *            name of a column in this rowset, (2) the cursor is not on
5403      *            one of this rowset's rows or its insert row, or (3) this
5404      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5405      */
5406     public void updateObject(String columnName, Object x, int scale) throws SQLException {
5407         updateObject(getColIdxByName(columnName), x, scale);
5408     }
5409 
5410     /**
5411      * Sets the designated column in either the current row or the insert
5412      * row of this <code>CachedRowSetImpl</code> object with the given
5413      * <code>Object</code> value.
5414      * <P>
5415      * This method updates a column value in either the current row or
5416      * the insert row of this rowset, but it does not update the
5417      * database.  If the cursor is on a row in the rowset, the
5418      * method {@link #updateRow} must be called to update the database.
5419      * If the cursor is on the insert row, the method {@link #insertRow}
5420      * must be called, which will insert the new row into both this rowset
5421      * and the database. Both of these methods must be called before the
5422      * cursor moves to another row.
5423      *
5424      * @param columnName a <code>String</code> object that must match the
5425      *        SQL name of a column in this rowset, ignoring case
5426      * @param x the new column value
5427      * @throws SQLException if (1) the given column name does not match the
5428      *            name of a column in this rowset, (2) the cursor is not on
5429      *            one of this rowset's rows or its insert row, or (3) this
5430      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5431      */
5432     public void updateObject(String columnName, Object x) throws SQLException {
5433         updateObject(getColIdxByName(columnName), x);
5434     }
5435 
5436     /**
5437      * Inserts the contents of this <code>CachedRowSetImpl</code> object's insert
5438      * row into this rowset immediately following the current row.
5439      * If the current row is the
5440      * position after the last row or before the first row, the new row will
5441      * be inserted at the end of the rowset.  This method also notifies
5442      * listeners registered with this rowset that the row has changed.
5443      * <P>
5444      * The cursor must be on the insert row when this method is called.
5445      *
5446      * @throws SQLException if (1) the cursor is not on the insert row,
5447      *            (2) one or more of the non-nullable columns in the insert
5448      *            row has not been given a value, or (3) this rowset is
5449      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5450      */
5451     public void insertRow() throws SQLException {
5452         int pos;
5453 
5454         if (onInsertRow == false ||
5455             insertRow.isCompleteRow(RowSetMD) == false) {
5456                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.failedins").toString());
5457         }
5458         // Added the setting of parameters that are passed
5459         // to setXXX methods after an empty CRS Object is
5460         // created through RowSetMetaData object
5461         Object [] toInsert = getParams();
5462 
5463         for(int i = 0;i < toInsert.length; i++) {
5464           insertRow.setColumnObject(i+1,toInsert[i]);
5465         }
5466 
5467         Row insRow = new Row(RowSetMD.getColumnCount(),
5468         insertRow.getOrigRow());
5469         insRow.setInserted();
5470         /*
5471          * The new row is inserted into the RowSet
5472          * immediately following the current row.
5473          *
5474          * If we are afterlast then the rows are
5475          * inserted at the end.
5476          */
5477         if (currentRow >= numRows || currentRow < 0) {
5478             pos = numRows;
5479         } else {
5480             pos = currentRow;
5481         }
5482 
5483         rvh.add(pos, insRow);
5484         ++numRows;
5485         // notify the listeners that the row changed.
5486         notifyRowChanged();
5487     }
5488 
5489     /**
5490      * Marks the current row of this <code>CachedRowSetImpl</code> object as
5491      * updated and notifies listeners registered with this rowset that the
5492      * row has changed.
5493      * <P>
5494      * This method  cannot be called when the cursor is on the insert row, and
5495      * it should be called before the cursor moves to another row.  If it is
5496      * called after the cursor moves to another row, this method has no effect,
5497      * and the updates made before the cursor moved will be lost.
5498      *
5499      * @throws SQLException if the cursor is on the insert row or this
5500      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5501      */
5502     public void updateRow() throws SQLException {
5503         // make sure we aren't on the insert row
5504         if (onInsertRow == true) {
5505             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.updateins").toString());
5506         }
5507 
5508         ((Row)getCurrentRow()).setUpdated();
5509 
5510         // notify the listeners that the row changed.
5511         notifyRowChanged();
5512     }
5513 
5514     /**
5515      * Deletes the current row from this <code>CachedRowSetImpl</code> object and
5516      * notifies listeners registered with this rowset that a row has changed.
5517      * This method cannot be called when the cursor is on the insert row.
5518      * <P>
5519      * This method marks the current row as deleted, but it does not delete
5520      * the row from the underlying data source.  The method
5521      * <code>acceptChanges</code> must be called to delete the row in
5522      * the data source.
5523      *
5524      * @throws SQLException if (1) this method is called when the cursor
5525      *            is on the insert row, before the first row, or after the
5526      *            last row or (2) this rowset is
5527      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5528      */
5529     public void deleteRow() throws SQLException {
5530         // make sure the cursor is on a valid row
5531         checkCursor();
5532 
5533         ((Row)getCurrentRow()).setDeleted();
5534         ++numDeleted;
5535 
5536         // notify the listeners that the row changed.
5537         notifyRowChanged();
5538     }
5539 
5540     /**
5541      * Sets the current row with its original value and marks the row as
5542      * not updated, thus undoing any changes made to the row since the
5543      * last call to the methods <code>updateRow</code> or <code>deleteRow</code>.
5544      * This method should be called only when the cursor is on a row in
5545      * this rowset.
5546      *
5547      * @throws SQLException if the cursor is on the insert row, before the
5548      *            first row, or after the last row
5549      */
5550     public void refreshRow() throws SQLException {
5551         // make sure we are on a row
5552         checkCursor();
5553 
5554         // don't want this to happen...
5555         if (onInsertRow == true) {
5556             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
5557         }
5558 
5559         Row currentRow = (Row)getCurrentRow();
5560         // just undo any changes made to this row.
5561         currentRow.clearUpdated();
5562 
5563     }
5564 
5565     /**
5566      * Rolls back any updates made to the current row of this
5567      * <code>CachedRowSetImpl</code> object and notifies listeners that
5568      * a row has changed.  To have an effect, this method
5569      * must be called after an <code>updateXXX</code> method has been
5570      * called and before the method <code>updateRow</code> has been called.
5571      * If no updates have been made or the method <code>updateRow</code>
5572      * has already been called, this method has no effect.
5573      *
5574      * @throws SQLException if the cursor is on the insert row, before the
5575      *            first row, or after the last row
5576      */
5577     public void cancelRowUpdates() throws SQLException {
5578         // make sure we are on a row
5579         checkCursor();
5580 
5581         // don't want this to happen...
5582         if (onInsertRow == true) {
5583             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
5584         }
5585 
5586         Row currentRow = (Row)getCurrentRow();
5587         if (currentRow.getUpdated() == true) {
5588             currentRow.clearUpdated();
5589             notifyRowChanged();
5590         }
5591     }
5592 
5593     /**
5594      * Moves the cursor for this <code>CachedRowSetImpl</code> object
5595      * to the insert row.  The current row in the rowset is remembered
5596      * while the cursor is on the insert row.
5597      * <P>
5598      * The insert row is a special row associated with an updatable
5599      * rowset.  It is essentially a buffer where a new row may
5600      * be constructed by calling the appropriate <code>updateXXX</code>
5601      * methods to assign a value to each column in the row.  A complete
5602      * row must be constructed; that is, every column that is not nullable
5603      * must be assigned a value.  In order for the new row to become part
5604      * of this rowset, the method <code>insertRow</code> must be called
5605      * before the cursor is moved back to the rowset.
5606      * <P>
5607      * Only certain methods may be invoked while the cursor is on the insert
5608      * row; many methods throw an exception if they are called while the
5609      * cursor is there.  In addition to the <code>updateXXX</code>
5610      * and <code>insertRow</code> methods, only the <code>getXXX</code> methods
5611      * may be called when the cursor is on the insert row.  A <code>getXXX</code>
5612      * method should be called on a column only after an <code>updateXXX</code>
5613      * method has been called on that column; otherwise, the value returned is
5614      * undetermined.
5615      *
5616      * @throws SQLException if this <code>CachedRowSetImpl</code> object is
5617      *            <code>ResultSet.CONCUR_READ_ONLY</code>
5618      */
5619     public void moveToInsertRow() throws SQLException {
5620         if (getConcurrency() == ResultSet.CONCUR_READ_ONLY) {
5621             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins").toString());
5622         }
5623         if (insertRow == null) {
5624             if (RowSetMD == null)
5625                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins1").toString());
5626             int numCols = RowSetMD.getColumnCount();
5627             if (numCols > 0) {
5628                 insertRow = new InsertRow(numCols);
5629             } else {
5630                 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins2").toString());
5631             }
5632         }
5633         onInsertRow = true;
5634         // %%% setCurrentRow called in BaseRow
5635 
5636         currentRow = cursorPos;
5637         cursorPos = -1;
5638 
5639         insertRow.initInsertRow();
5640     }
5641 
5642     /**
5643      * Moves the cursor for this <code>CachedRowSetImpl</code> object to
5644      * the current row.  The current row is the row the cursor was on
5645      * when the method <code>moveToInsertRow</code> was called.
5646      * <P>
5647      * Calling this method has no effect unless it is called while the
5648      * cursor is on the insert row.
5649      *
5650      * @throws SQLException if an error occurs
5651      */
5652     public void moveToCurrentRow() throws SQLException {
5653         if (onInsertRow == false) {
5654             return;
5655         } else {
5656             cursorPos = currentRow;
5657             onInsertRow = false;
5658         }
5659     }
5660 
5661     /**
5662      * Returns <code>null</code>.
5663      *
5664      * @return <code>null</code>
5665      * @throws SQLException if an error occurs
5666      */
5667     public Statement getStatement() throws SQLException {
5668         return null;
5669     }
5670 
5671     /**
5672      * Retrieves the value of the designated column in this
5673      * <code>CachedRowSetImpl</code> object as an <code>Object</code> in
5674      * the Java programming language, using the given
5675      * <code>java.util.Map</code> object to custom map the value if
5676      * appropriate.
5677      *
5678      * @param columnIndex the first column is <code>1</code>, the second
5679      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5680      *        and equal to or less than the number of columns in this rowset
5681      * @param map a <code>java.util.Map</code> object showing the mapping
5682      *            from SQL type names to classes in the Java programming
5683      *            language
5684      * @return an <code>Object</code> representing the SQL value
5685      * @throws SQLException if the given column index is out of bounds or
5686      *            the cursor is not on one of this rowset's rows or its
5687      *            insert row
5688      */
5689      public Object getObject(int columnIndex,
5690                              java.util.Map<String,Class<?>> map)
5691          throws SQLException
5692      {
5693         Object value;
5694 
5695         // sanity check.
5696         checkIndex(columnIndex);
5697         // make sure the cursor is on a valid row
5698         checkCursor();
5699 
5700         setLastValueNull(false);
5701         value = getCurrentRow().getColumnObject(columnIndex);
5702 
5703         // check for SQL NULL
5704         if (value == null) {
5705             setLastValueNull(true);
5706             return null;
5707         }
5708         if (value instanceof Struct) {
5709             Struct s = (Struct)value;
5710 
5711             // look up the class in the map
5712             Class c = (Class)map.get(s.getSQLTypeName());
5713             if (c != null) {
5714                 // create new instance of the class
5715                 SQLData obj = null;
5716                 try {
5717                     obj = (SQLData)c.newInstance();
5718                 } catch (java.lang.InstantiationException ex) {
5719                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
5720                     ex.getMessage()));
5721                 } catch (java.lang.IllegalAccessException ex) {
5722                     throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
5723                     ex.getMessage()));
5724                 }
5725                 // get the attributes from the struct
5726                 Object attribs[] = s.getAttributes(map);
5727                 // create the SQLInput "stream"
5728                 SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
5729                 // read the values...
5730                 obj.readSQL(sqlInput, s.getSQLTypeName());
5731                 return (Object)obj;
5732             }
5733         }
5734         return value;
5735     }
5736 
5737     /**
5738      * Retrieves the value of the designated column in this
5739      * <code>CachedRowSetImpl</code> object as a <code>Ref</code> object
5740      * in the Java programming language.
5741      *
5742      * @param columnIndex the first column is <code>1</code>, the second
5743      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5744      *        and equal to or less than the number of columns in this rowset
5745      * @return a <code>Ref</code> object representing an SQL<code> REF</code> value
5746      * @throws SQLException if (1) the given column index is out of bounds,
5747      *            (2) the cursor is not on one of this rowset's rows or its
5748      *            insert row, or (3) the designated column does not store an
5749      *            SQL <code>REF</code> value
5750      * @see #getRef(String)
5751      */
5752     public Ref getRef(int columnIndex) throws SQLException {
5753         Ref value;
5754 
5755         // sanity check.
5756         checkIndex(columnIndex);
5757         // make sure the cursor is on a valid row
5758         checkCursor();
5759 
5760         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.REF) {
5761             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5762         }
5763 
5764         setLastValueNull(false);
5765         value = (Ref)(getCurrentRow().getColumnObject(columnIndex));
5766 
5767         // check for SQL NULL
5768         if (value == null) {
5769             setLastValueNull(true);
5770             return null;
5771         }
5772 
5773         return value;
5774     }
5775 
5776     /**
5777      * Retrieves the value of the designated column in this
5778      * <code>CachedRowSetImpl</code> object as a <code>Blob</code> object
5779      * in the Java programming language.
5780      *
5781      * @param columnIndex the first column is <code>1</code>, the second
5782      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5783      *        and equal to or less than the number of columns in this rowset
5784      * @return a <code>Blob</code> object representing an SQL <code>BLOB</code> value
5785      * @throws SQLException if (1) the given column index is out of bounds,
5786      *            (2) the cursor is not on one of this rowset's rows or its
5787      *            insert row, or (3) the designated column does not store an
5788      *            SQL <code>BLOB</code> value
5789      * @see #getBlob(String)
5790      */
5791     public Blob getBlob(int columnIndex) throws SQLException {
5792         Blob value;
5793 
5794         // sanity check.
5795         checkIndex(columnIndex);
5796         // make sure the cursor is on a valid row
5797         checkCursor();
5798 
5799         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.BLOB) {
5800             System.out.println(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.type").toString(), RowSetMD.getColumnType(columnIndex)));
5801             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5802         }
5803 
5804         setLastValueNull(false);
5805         value = (Blob)(getCurrentRow().getColumnObject(columnIndex));
5806 
5807         // check for SQL NULL
5808         if (value == null) {
5809             setLastValueNull(true);
5810             return null;
5811         }
5812 
5813         return value;
5814     }
5815 
5816     /**
5817      * Retrieves the value of the designated column in this
5818      * <code>CachedRowSetImpl</code> object as a <code>Clob</code> object
5819      * in the Java programming language.
5820      *
5821      * @param columnIndex the first column is <code>1</code>, the second
5822      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5823      *        and equal to or less than the number of columns in this rowset
5824      * @return a <code>Clob</code> object representing an SQL <code>CLOB</code> value
5825      * @throws SQLException if (1) the given column index is out of bounds,
5826      *            (2) the cursor is not on one of this rowset's rows or its
5827      *            insert row, or (3) the designated column does not store an
5828      *            SQL <code>CLOB</code> value
5829      * @see #getClob(String)
5830      */
5831     public Clob getClob(int columnIndex) throws SQLException {
5832         Clob value;
5833 
5834         // sanity check.
5835         checkIndex(columnIndex);
5836         // make sure the cursor is on a valid row
5837         checkCursor();
5838 
5839         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.CLOB) {
5840             System.out.println(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.type").toString(), RowSetMD.getColumnType(columnIndex)));
5841             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5842         }
5843 
5844         setLastValueNull(false);
5845         value = (Clob)(getCurrentRow().getColumnObject(columnIndex));
5846 
5847         // check for SQL NULL
5848         if (value == null) {
5849             setLastValueNull(true);
5850             return null;
5851         }
5852 
5853         return value;
5854     }
5855 
5856     /**
5857      * Retrieves the value of the designated column in this
5858      * <code>CachedRowSetImpl</code> object as an <code>Array</code> object
5859      * in the Java programming language.
5860      *
5861      * @param columnIndex the first column is <code>1</code>, the second
5862      *        is <code>2</code>, and so on; must be <code>1</code> or larger
5863      *        and equal to or less than the number of columns in this rowset
5864      * @return an <code>Array</code> object representing an SQL
5865      *         <code>ARRAY</code> value
5866      * @throws SQLException if (1) the given column index is out of bounds,
5867      *            (2) the cursor is not on one of this rowset's rows or its
5868      *            insert row, or (3) the designated column does not store an
5869      *            SQL <code>ARRAY</code> value
5870      * @see #getArray(String)
5871      */
5872     public Array getArray(int columnIndex) throws SQLException {
5873         java.sql.Array value;
5874 
5875         // sanity check.
5876         checkIndex(columnIndex);
5877         // make sure the cursor is on a valid row
5878         checkCursor();
5879 
5880         if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.ARRAY) {
5881             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5882         }
5883 
5884         setLastValueNull(false);
5885         value = (java.sql.Array)(getCurrentRow().getColumnObject(columnIndex));
5886 
5887         // check for SQL NULL
5888         if (value == null) {
5889             setLastValueNull(true);
5890             return null;
5891         }
5892 
5893         return value;
5894     }
5895 
5896     /**
5897      * Retrieves the value of the designated column in this
5898      * <code>CachedRowSetImpl</code> object as an <code>Object</code> in
5899      * the Java programming language, using the given
5900      * <code>java.util.Map</code> object to custom map the value if
5901      * appropriate.
5902      *
5903      * @param columnName a <code>String</code> object that must match the
5904      *        SQL name of a column in this rowset, ignoring case
5905      * @param map a <code>java.util.Map</code> object showing the mapping
5906      *        from SQL type names to classes in the Java programming
5907      *        language
5908      * @return an <code>Object</code> representing the SQL value
5909      * @throws SQLException if the given column name is not the name of
5910      *         a column in this rowset or the cursor is not on one of
5911      *         this rowset's rows or its insert row
5912      */
5913     public Object getObject(String columnName,
5914                             java.util.Map<String,Class<?>> map)
5915     throws SQLException {
5916         return getObject(getColIdxByName(columnName), map);
5917     }
5918 
5919     /**
5920      * Retrieves the value of the designated column in this
5921      * <code>CachedRowSetImpl</code> object as a <code>Ref</code> object
5922      * in the Java programming language.
5923      *
5924      * @param colName a <code>String</code> object that must match the
5925      *        SQL name of a column in this rowset, ignoring case
5926      * @return a <code>Ref</code> object representing an SQL<code> REF</code> value
5927      * @throws SQLException  if (1) the given column name is not the name of
5928      *            a column in this rowset, (2) the cursor is not on one of
5929      *            this rowset's rows or its insert row, or (3) the column value
5930      *            is not an SQL <code>REF</code> value
5931      * @see #getRef(int)
5932      */
5933     public Ref getRef(String colName) throws SQLException {
5934         return getRef(getColIdxByName(colName));
5935     }
5936 
5937     /**
5938      * Retrieves the value of the designated column in this
5939      * <code>CachedRowSetImpl</code> object as a <code>Blob</code> object
5940      * in the Java programming language.
5941      *
5942      * @param colName a <code>String</code> object that must match the
5943      *        SQL name of a column in this rowset, ignoring case
5944      * @return a <code>Blob</code> object representing an SQL <code>BLOB</code> value
5945      * @throws SQLException if (1) the given column name is not the name of
5946      *            a column in this rowset, (2) the cursor is not on one of
5947      *            this rowset's rows or its insert row, or (3) the designated
5948      *            column does not store an SQL <code>BLOB</code> value
5949      * @see #getBlob(int)
5950      */
5951     public Blob getBlob(String colName) throws SQLException {
5952         return getBlob(getColIdxByName(colName));
5953     }
5954 
5955     /**
5956      * Retrieves the value of the designated column in this
5957      * <code>CachedRowSetImpl</code> object as a <code>Clob</code> object
5958      * in the Java programming language.
5959      *
5960      * @param colName a <code>String</code> object that must match the
5961      *        SQL name of a column in this rowset, ignoring case
5962      * @return a <code>Clob</code> object representing an SQL
5963      *         <code>CLOB</code> value
5964      * @throws SQLException if (1) the given column name is not the name of
5965      *            a column in this rowset, (2) the cursor is not on one of
5966      *            this rowset's rows or its insert row, or (3) the designated
5967      *            column does not store an SQL <code>CLOB</code> value
5968      * @see #getClob(int)
5969      */
5970     public Clob getClob(String colName) throws SQLException {
5971         return getClob(getColIdxByName(colName));
5972     }
5973 
5974     /**
5975      * Retrieves the value of the designated column in this
5976      * <code>CachedRowSetImpl</code> object as an <code>Array</code> object
5977      * in the Java programming langugage.
5978      *
5979      * @param colName a <code>String</code> object that must match the
5980      *        SQL name of a column in this rowset, ignoring case
5981      * @return an <code>Array</code> object representing an SQL
5982      *         <code>ARRAY</code> value
5983      * @throws SQLException if (1) the given column name is not the name of
5984      *            a column in this rowset, (2) the cursor is not on one of
5985      *            this rowset's rows or its insert row, or (3) the designated
5986      *            column does not store an SQL <code>ARRAY</code> value
5987      * @see #getArray(int)
5988      */
5989     public Array getArray(String colName) throws SQLException {
5990         return getArray(getColIdxByName(colName));
5991     }
5992 
5993     /**
5994      * Retrieves the value of the designated column in the current row
5995      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Date</code>
5996      * object, using the given <code>Calendar</code> object to construct an
5997      * appropriate millisecond value for the date.
5998      *
5999      * @param columnIndex the first column is <code>1</code>, the second
6000      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6001      *        and equal to or less than the number of columns in the rowset
6002      * @param cal the <code>java.util.Calendar</code> object to use in
6003      *            constructing the date
6004      * @return the column value; if the value is SQL <code>NULL</code>,
6005      *         the result is <code>null</code>
6006      * @throws SQLException if (1) the given column name is not the name of
6007      *            a column in this rowset, (2) the cursor is not on one of
6008      *            this rowset's rows or its insert row, or (3) the designated
6009      *            column does not store an SQL <code>DATE</code> or
6010      *            <code>TIMESTAMP</code> value
6011      */
6012     public java.sql.Date getDate(int columnIndex, Calendar cal) throws SQLException {
6013         Object value;
6014 
6015         // sanity check.
6016         checkIndex(columnIndex);
6017         // make sure the cursor is on a valid row
6018         checkCursor();
6019 
6020         setLastValueNull(false);
6021         value = getCurrentRow().getColumnObject(columnIndex);
6022 
6023         // check for SQL NULL
6024         if (value == null) {
6025             setLastValueNull(true);
6026             return null;
6027         }
6028 
6029         value = convertTemporal(value,
6030         RowSetMD.getColumnType(columnIndex),
6031         java.sql.Types.DATE);
6032 
6033         // create a default calendar
6034         Calendar defaultCal = Calendar.getInstance();
6035         // set this Calendar to the time we have
6036         defaultCal.setTime((java.util.Date)value);
6037 
6038         /*
6039          * Now we can pull the pieces of the date out
6040          * of the default calendar and put them into
6041          * the user provided calendar
6042          */
6043         cal.set(Calendar.YEAR, defaultCal.get(Calendar.YEAR));
6044         cal.set(Calendar.MONTH, defaultCal.get(Calendar.MONTH));
6045         cal.set(Calendar.DAY_OF_MONTH, defaultCal.get(Calendar.DAY_OF_MONTH));
6046 
6047         /*
6048          * This looks a little odd but it is correct -
6049          * Calendar.getTime() returns a Date...
6050          */
6051         return new java.sql.Date(cal.getTime().getTime());
6052     }
6053 
6054     /**
6055      * Retrieves the value of the designated column in the current row
6056      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Date</code>
6057      * object, using the given <code>Calendar</code> object to construct an
6058      * appropriate millisecond value for the date.
6059      *
6060      * @param columnName a <code>String</code> object that must match the
6061      *        SQL name of a column in this rowset, ignoring case
6062      * @param cal the <code>java.util.Calendar</code> object to use in
6063      *            constructing the date
6064      * @return the column value; if the value is SQL <code>NULL</code>,
6065      *         the result is <code>null</code>
6066      * @throws SQLException if (1) the given column name is not the name of
6067      *            a column in this rowset, (2) the cursor is not on one of
6068      *            this rowset's rows or its insert row, or (3) the designated
6069      *            column does not store an SQL <code>DATE</code> or
6070      *            <code>TIMESTAMP</code> value
6071      */
6072     public java.sql.Date getDate(String columnName, Calendar cal) throws SQLException {
6073         return getDate(getColIdxByName(columnName), cal);
6074     }
6075 
6076     /**
6077      * Retrieves the value of the designated column in the current row
6078      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Time</code>
6079      * object, using the given <code>Calendar</code> object to construct an
6080      * appropriate millisecond value for the date.
6081      *
6082      * @param columnIndex the first column is <code>1</code>, the second
6083      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6084      *        and equal to or less than the number of columns in the rowset
6085      * @param cal the <code>java.util.Calendar</code> object to use in
6086      *            constructing the date
6087      * @return the column value; if the value is SQL <code>NULL</code>,
6088      *         the result is <code>null</code>
6089      * @throws SQLException if (1) the given column name is not the name of
6090      *            a column in this rowset, (2) the cursor is not on one of
6091      *            this rowset's rows or its insert row, or (3) the designated
6092      *            column does not store an SQL <code>TIME</code> or
6093      *            <code>TIMESTAMP</code> value
6094      */
6095     public java.sql.Time getTime(int columnIndex, Calendar cal) throws SQLException {
6096         Object value;
6097 
6098         // sanity check.
6099         checkIndex(columnIndex);
6100         // make sure the cursor is on a valid row
6101         checkCursor();
6102 
6103         setLastValueNull(false);
6104         value = getCurrentRow().getColumnObject(columnIndex);
6105 
6106         // check for SQL NULL
6107         if (value == null) {
6108             setLastValueNull(true);
6109             return null;
6110         }
6111 
6112         value = convertTemporal(value,
6113         RowSetMD.getColumnType(columnIndex),
6114         java.sql.Types.TIME);
6115 
6116         // create a default calendar
6117         Calendar defaultCal = Calendar.getInstance();
6118         // set the time in the default calendar
6119         defaultCal.setTime((java.util.Date)value);
6120 
6121         /*
6122          * Now we can pull the pieces of the date out
6123          * of the default calendar and put them into
6124          * the user provided calendar
6125          */
6126         cal.set(Calendar.HOUR_OF_DAY, defaultCal.get(Calendar.HOUR_OF_DAY));
6127         cal.set(Calendar.MINUTE, defaultCal.get(Calendar.MINUTE));
6128         cal.set(Calendar.SECOND, defaultCal.get(Calendar.SECOND));
6129 
6130         return new java.sql.Time(cal.getTime().getTime());
6131     }
6132 
6133     /**
6134      * Retrieves the value of the designated column in the current row
6135      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Time</code>
6136      * object, using the given <code>Calendar</code> object to construct an
6137      * appropriate millisecond value for the date.
6138      *
6139      * @param columnName a <code>String</code> object that must match the
6140      *        SQL name of a column in this rowset, ignoring case
6141      * @param cal the <code>java.util.Calendar</code> object to use in
6142      *            constructing the date
6143      * @return the column value; if the value is SQL <code>NULL</code>,
6144      *         the result is <code>null</code>
6145      * @throws SQLException if (1) the given column name is not the name of
6146      *            a column in this rowset, (2) the cursor is not on one of
6147      *            this rowset's rows or its insert row, or (3) the designated
6148      *            column does not store an SQL <code>TIME</code> or
6149      *            <code>TIMESTAMP</code> value
6150      */
6151     public java.sql.Time getTime(String columnName, Calendar cal) throws SQLException {
6152         return getTime(getColIdxByName(columnName), cal);
6153     }
6154 
6155     /**
6156      * Retrieves the value of the designated column in the current row
6157      * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Timestamp</code>
6158      * object, using the given <code>Calendar</code> object to construct an
6159      * appropriate millisecond value for the date.
6160      *
6161      * @param columnIndex the first column is <code>1</code>, the second
6162      *        is <code>2</code>, and so on; must be <code>1</code> or larger
6163      *        and equal to or less than the number of columns in the rowset
6164      * @param cal the <code>java.util.Calendar</code> object to use in
6165      *            constructing the date
6166      * @return the column value; if the value is SQL <code>NULL</code>,
6167      *         the result is <code>null</code>
6168      * @throws SQLException if (1) the given column name is not the name of
6169      *            a column in this rowset, (2) the cursor is not on one of
6170      *            this rowset's rows or its insert row, or (3) the designated
6171      *            column does not store an SQL <code>TIME</code> or
6172      *            <code>TIMESTAMP</code> value
6173      */
6174     public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
6175         Object value;
6176 
6177         // sanity check.
6178         checkIndex(columnIndex);
6179         // make sure the cursor is on a valid row
6180         checkCursor();
6181 
6182         setLastValueNull(false);
6183         value = getCurrentRow().getColumnObject(columnIndex);
6184 
6185         // check for SQL NULL
6186         if (value == null) {
6187             setLastValueNull(true);
6188             return null;
6189         }
6190 
6191         value = convertTemporal(value,
6192         RowSetMD.getColumnType(columnIndex),
6193         java.sql.Types.TIMESTAMP);
6194 
6195         // create a default calendar
6196         Calendar defaultCal = Calendar.getInstance();
6197         // set the time in the default calendar
6198         defaultCal.setTime((java.util.Date)value);
6199 
6200         /*
6201          * Now we can pull the pieces of the date out
6202          * of the default calendar and put them into
6203          * the user provided calendar
6204          */
6205         cal.set(Calendar.YEAR, defaultCal.get(Calendar.YEAR));
6206         cal.set(Calendar.MONTH, defaultCal.get(Calendar.MONTH));
6207         cal.set(Calendar.DAY_OF_MONTH, defaultCal.get(Calendar.DAY_OF_MONTH));
6208         cal.set(Calendar.HOUR_OF_DAY, defaultCal.get(Calendar.HOUR_OF_DAY));
6209         cal.set(Calendar.MINUTE, defaultCal.get(Calendar.MINUTE));
6210         cal.set(Calendar.SECOND, defaultCal.get(Calendar.SECOND));
6211 
6212         return new java.sql.Timestamp(cal.getTime().getTime());
6213     }
6214 
6215     /**
6216      * Retrieves the value of the designated column in the current row
6217      * of this <code>CachedRowSetImpl</code> object as a
6218      * <code>java.sql.Timestamp</code> object, using the given
6219      * <code>Calendar</code> object to construct an appropriate
6220      * millisecond value for the date.
6221      *
6222      * @param columnName a <code>String</code> object that must match the
6223      *        SQL name of a column in this rowset, ignoring case
6224      * @param cal the <code>java.util.Calendar</code> object to use in
6225      *            constructing the date
6226      * @return the column value; if the value is SQL <code>NULL</code>,
6227      *         the result is <code>null</code>
6228      * @throws SQLException if (1) the given column name is not the name of
6229      *            a column in this rowset, (2) the cursor is not on one of
6230      *            this rowset's rows or its insert row, or (3) the designated
6231      *            column does not store an SQL <code>DATE</code>,
6232      *            <code>TIME</code>, or <code>TIMESTAMP</code> value
6233      */
6234     public java.sql.Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException {
6235         return getTimestamp(getColIdxByName(columnName), cal);
6236     }
6237 
6238     /*
6239      * RowSetInternal Interface
6240      */
6241 
6242     /**
6243      * Retrieves the <code>Connection</code> object passed to this
6244      * <code>CachedRowSetImpl</code> object.  This connection may be
6245      * used to populate this rowset with data or to write data back
6246      * to its underlying data source.
6247      *
6248      * @return the <code>Connection</code> object passed to this rowset;
6249      *         may be <code>null</code> if there is no connection
6250      * @throws SQLException if an error occurs
6251      */
6252     public Connection getConnection() throws SQLException{
6253         return conn;
6254     }
6255 
6256     /**
6257      * Sets the metadata for this <code>CachedRowSetImpl</code> object
6258      * with the given <code>RowSetMetaData</code> object.
6259      *
6260      * @param md a <code>RowSetMetaData</code> object instance containing
6261      *            metadata about the columsn in the rowset
6262      * @throws SQLException if invalid meta data is supplied to the
6263      *            rowset
6264      */
6265     public void setMetaData(RowSetMetaData md) throws SQLException {
6266         RowSetMD =(RowSetMetaDataImpl) md;
6267     }
6268 
6269     /**
6270      * Returns a result set containing the original value of the rowset. The
6271      * original value is the state of the <code>CachedRowSetImpl</code> after the
6272      * last population or synchronization (whichever occured most recently) with
6273      * the data source.
6274      * <p>
6275      * The cursor is positioned before the first row in the result set.
6276      * Only rows contained in the result set returned by <code>getOriginal()</code>
6277      * are said to have an original value.
6278      *
6279      * @return the original result set of the rowset
6280      * @throws SQLException if an error occurs produce the
6281      *           <code>ResultSet</code> object
6282      */
6283     public ResultSet getOriginal() throws SQLException {
6284         CachedRowSetImpl crs = new CachedRowSetImpl();
6285         crs.RowSetMD = RowSetMD;
6286         crs.numRows = numRows;
6287         crs.cursorPos = 0;
6288 
6289         // make sure we don't get someone playing with these
6290         // %%% is this now necessary ???
6291         //crs.setReader(null);
6292         //crs.setWriter(null);
6293         int colCount = RowSetMD.getColumnCount();
6294         Row orig;
6295 
6296         for (Iterator i = rvh.iterator(); i.hasNext();) {
6297             orig = new Row(colCount, ((Row)i.next()).getOrigRow());
6298             crs.rvh.add(orig);
6299         }
6300         return (ResultSet)crs;
6301     }
6302 
6303     /**
6304      * Returns a result set containing the original value of the current
6305      * row only.
6306      * The original value is the state of the <code>CachedRowSetImpl</code> after
6307      * the last population or synchronization (whichever occured most recently)
6308      * with the data source.
6309      *
6310      * @return the original result set of the row
6311      * @throws SQLException if there is no current row
6312      * @see #setOriginalRow
6313      */
6314     public ResultSet getOriginalRow() throws SQLException {
6315         CachedRowSetImpl crs = new CachedRowSetImpl();
6316         crs.RowSetMD = RowSetMD;
6317         crs.numRows = 1;
6318         crs.cursorPos = 0;
6319         crs.setTypeMap(this.getTypeMap());
6320 
6321         // make sure we don't get someone playing with these
6322         // %%% is this now necessary ???
6323         //crs.setReader(null);
6324         //crs.setWriter(null);
6325 
6326         Row orig = new Row(RowSetMD.getColumnCount(),
6327         getCurrentRow().getOrigRow());
6328 
6329         crs.rvh.add(orig);
6330 
6331         return (ResultSet)crs;
6332 
6333     }
6334 
6335     /**
6336      * Marks the current row in this rowset as being an original row.
6337      *
6338      * @throws SQLException if there is no current row
6339      * @see #getOriginalRow
6340      */
6341     public void setOriginalRow() throws SQLException {
6342         if (onInsertRow == true) {
6343             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
6344         }
6345 
6346         Row row = (Row)getCurrentRow();
6347         makeRowOriginal(row);
6348 
6349         // this can happen if deleted rows are being shown
6350         if (row.getDeleted() == true) {
6351             removeCurrentRow();
6352             --numRows;
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 }