1/*
2 * Copyright (c) 2003, 2017, 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
26package com.sun.rowset;
27
28import java.sql.*;
29import javax.sql.*;
30import java.io.*;
31import java.math.*;
32import java.util.*;
33import java.text.*;
34import java.security.AccessController;
35import java.security.PrivilegedActionException;
36import java.security.PrivilegedExceptionAction;
37
38import javax.sql.rowset.*;
39import javax.sql.rowset.spi.*;
40import javax.sql.rowset.serial.*;
41import com.sun.rowset.internal.*;
42import com.sun.rowset.providers.*;
43import sun.reflect.misc.ReflectUtil;
44
45/**
46 * The standard implementation of the <code>CachedRowSet</code> interface.
47 *
48 * See interface definition for full behavior and implementation requirements.
49 * This reference implementation has made provision for a one-to-one write back
50 * facility and it is curremtly be possible to change the peristence provider
51 * during the life-time of any CachedRowSetImpl.
52 *
53 * @author Jonathan Bruce, Amit Handa
54 */
55
56public class CachedRowSetImpl extends BaseRowSet implements RowSet, RowSetInternal, Serializable, Cloneable, CachedRowSet {
57
58    /**
59     * The <code>SyncProvider</code> used by the CachedRowSet
60     */
61    private SyncProvider provider;
62
63    /**
64     * The <code>RowSetReaderImpl</code> object that is the reader
65     * for this rowset.  The method <code>execute</code> uses this
66     * reader as part of its implementation.
67     * @serial
68     */
69    private RowSetReader rowSetReader;
70
71    /**
72     * The <code>RowSetWriterImpl</code> object that is the writer
73     * for this rowset.  The method <code>acceptChanges</code> uses
74     * this writer as part of its implementation.
75     * @serial
76     */
77    private RowSetWriter rowSetWriter;
78
79    /**
80     * The <code>Connection</code> object that connects with this
81     * <code>CachedRowSetImpl</code> object's current underlying data source.
82     */
83    private transient Connection conn;
84
85    /**
86     * The <code>ResultSetMetaData</code> object that contains information
87     * about the columns in the <code>ResultSet</code> object that is the
88     * current source of data for this <code>CachedRowSetImpl</code> object.
89     */
90    private transient ResultSetMetaData RSMD;
91
92    /**
93     * The <code>RowSetMetaData</code> object that contains information about
94     * the columns in this <code>CachedRowSetImpl</code> object.
95     * @serial
96     */
97    private RowSetMetaDataImpl RowSetMD;
98
99    // Properties of this RowSet
100
101    /**
102     * An array containing the columns in this <code>CachedRowSetImpl</code>
103     * object that form a unique identifier for a row. This array
104     * is used by the writer.
105     * @serial
106     */
107    private int keyCols[];
108
109    /**
110     * The name of the table in the underlying database to which updates
111     * should be written.  This name is needed because most drivers
112     * do not return this information in a <code>ResultSetMetaData</code>
113     * object.
114     * @serial
115     */
116    private String tableName;
117
118    /**
119     * A <code>Vector</code> object containing the <code>Row</code>
120     * objects that comprise  this <code>CachedRowSetImpl</code> object.
121     * @serial
122     */
123    private Vector<Object> rvh;
124
125    /**
126     * The current position of the cursor in this <code>CachedRowSetImpl</code>
127     * object.
128     * @serial
129     */
130    private int cursorPos;
131
132    /**
133     * The current position of the cursor in this <code>CachedRowSetImpl</code>
134     * object not counting rows that have been deleted, if any.
135     * <P>
136     * For example, suppose that the cursor is on the last row of a rowset
137     * that started with five rows and subsequently had the second and third
138     * rows deleted. The <code>absolutePos</code> would be <code>3</code>,
139     * whereas the <code>cursorPos</code> would be <code>5</code>.
140     * @serial
141     */
142    private int absolutePos;
143
144    /**
145     * The number of deleted rows currently in this <code>CachedRowSetImpl</code>
146     * object.
147     * @serial
148     */
149    private int numDeleted;
150
151    /**
152     * The total number of rows currently in this <code>CachedRowSetImpl</code>
153     * object.
154     * @serial
155     */
156    private int numRows;
157
158    /**
159     * A special row used for constructing a new row. A new
160     * row is constructed by using <code>ResultSet.updateXXX</code>
161     * methods to insert column values into the insert row.
162     * @serial
163     */
164    private InsertRow insertRow;
165
166    /**
167     * A <code>boolean</code> indicating whether the cursor is
168     * currently on the insert row.
169     * @serial
170     */
171    private boolean onInsertRow;
172
173    /**
174     * The field that temporarily holds the last position of the
175     * cursor before it moved to the insert row, thus preserving
176     * the number of the current row to which the cursor may return.
177     * @serial
178     */
179    private int currentRow;
180
181    /**
182     * A <code>boolean</code> indicating whether the last value
183     * returned was an SQL <code>NULL</code>.
184     * @serial
185     */
186    private boolean lastValueNull;
187
188    /**
189     * A <code>SQLWarning</code> which logs on the warnings
190     */
191    private SQLWarning sqlwarn;
192
193    /**
194     * Used to track match column for JoinRowSet consumption
195     */
196    private String strMatchColumn ="";
197
198    /**
199     * Used to track match column for JoinRowSet consumption
200     */
201    private int iMatchColumn = -1;
202
203    /**
204     * A <code>RowSetWarning</code> which logs on the warnings
205     */
206    private RowSetWarning rowsetWarning;
207
208    /**
209     * The default SyncProvider for the RI CachedRowSetImpl
210     */
211    private String DEFAULT_SYNC_PROVIDER = "com.sun.rowset.providers.RIOptimisticProvider";
212
213    /**
214     * The boolean variable indicating locatorsUpdateValue
215     */
216    private boolean dbmslocatorsUpdateCopy;
217
218    /**
219     * The <code>ResultSet</code> object that is used to maintain the data when
220     * a ResultSet and start position are passed as parameters to the populate function
221     */
222    private transient ResultSet resultSet;
223
224    /**
225     * The integer value indicating the end position in the ResultSetwhere the picking
226     * up of rows for populating a CachedRowSet object was left off.
227     */
228    private int endPos;
229
230    /**
231     * The integer value indicating the end position in the ResultSetwhere the picking
232     * up of rows for populating a CachedRowSet object was left off.
233     */
234    private int prevEndPos;
235
236    /**
237     * The integer value indicating the position in the ResultSet, to populate the
238     * CachedRowSet object.
239     */
240    private int startPos;
241
242    /**
243     * The integer value indicating the position from where the page prior to this
244     * was populated.
245     */
246    private int startPrev;
247
248    /**
249     * The integer value indicating size of the page.
250     */
251    private int pageSize;
252
253    /**
254     * The integer value indicating number of rows that have been processed so far.
255     * Used for checking whether maxRows has been reached or not.
256     */
257    private int maxRowsreached;
258    /**
259     * The boolean value when true signifies that pages are still to follow and a
260     * false value indicates that this is the last page.
261     */
262    private boolean pagenotend = true;
263
264    /**
265     * The boolean value indicating whether this is the first page or not.
266     */
267    private boolean onFirstPage;
268
269    /**
270     * The boolean value indicating whether this is the last page or not.
271     */
272    private boolean onLastPage;
273
274    /**
275     * The integer value indicating how many times the populate function has been called.
276     */
277    private int populatecallcount;
278
279    /**
280     * The integer value indicating the total number of rows to be processed in the
281     * ResultSet object passed to the populate function.
282     */
283    private int totalRows;
284
285    /**
286     * The boolean value indicating how the CahedRowSet object has been populated for
287     * paging purpose. True indicates that connection parameter is passed.
288     */
289    private boolean callWithCon;
290
291    /**
292     * CachedRowSet reader object to read the data from the ResultSet when a connection
293     * parameter is passed to populate the CachedRowSet object for paging.
294     */
295    private CachedRowSetReader crsReader;
296
297    /**
298     * The Vector holding the Match Columns
299     */
300    private Vector<Integer> iMatchColumns;
301
302    /**
303     * The Vector that will hold the Match Column names.
304     */
305    private Vector<String> strMatchColumns;
306
307    /**
308     * Trigger that indicates whether the active SyncProvider is exposes the
309     * additional TransactionalWriter method
310     */
311    private boolean tXWriter = false;
312
313    /**
314     * The field object for a transactional RowSet writer
315     */
316    private TransactionalWriter tWriter = null;
317
318    protected transient JdbcRowSetResourceBundle resBundle;
319
320    private boolean updateOnInsert;
321
322
323
324    /**
325     * Constructs a new default <code>CachedRowSetImpl</code> object with
326     * the capacity to hold 100 rows. This new object has no metadata
327     * and has the following default values:
328     * <pre>
329     *     onInsertRow = false
330     *     insertRow = null
331     *     cursorPos = 0
332     *     numRows = 0
333     *     showDeleted = false
334     *     queryTimeout = 0
335     *     maxRows = 0
336     *     maxFieldSize = 0
337     *     rowSetType = ResultSet.TYPE_SCROLL_INSENSITIVE
338     *     concurrency = ResultSet.CONCUR_UPDATABLE
339     *     readOnly = false
340     *     isolation = Connection.TRANSACTION_READ_COMMITTED
341     *     escapeProcessing = true
342     *     onInsertRow = false
343     *     insertRow = null
344     *     cursorPos = 0
345     *     absolutePos = 0
346     *     numRows = 0
347     * </pre>
348     * A <code>CachedRowSetImpl</code> object is configured to use the default
349     * <code>RIOptimisticProvider</code> implementation to provide connectivity
350     * and synchronization capabilities to the set data source.
351     * <P>
352     * @throws SQLException if an error occurs
353     */
354    public CachedRowSetImpl() throws SQLException {
355
356        try {
357           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
358        } catch(IOException ioe) {
359            throw new RuntimeException(ioe);
360        }
361
362        // set the Reader, this maybe overridden latter
363        try {
364            provider = AccessController.doPrivileged(new PrivilegedExceptionAction<>() {
365                @Override
366                public SyncProvider run() throws SyncFactoryException {
367                    return SyncFactory.getInstance(DEFAULT_SYNC_PROVIDER);
368                }
369            }, null, new RuntimePermission("accessClassInPackage.com.sun.rowset.providers"));
370        } catch (PrivilegedActionException pae) {
371            throw (SyncFactoryException) pae.getException();
372        }
373
374        if (!(provider instanceof RIOptimisticProvider)) {
375            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidp").toString());
376        }
377
378        rowSetReader = (CachedRowSetReader)provider.getRowSetReader();
379        rowSetWriter = (CachedRowSetWriter)provider.getRowSetWriter();
380
381        // allocate the parameters collection
382        initParams();
383
384        initContainer();
385
386        // set up some default values
387        initProperties();
388
389        // insert row setup
390        onInsertRow = false;
391        insertRow = null;
392
393        // set the warninings
394        sqlwarn = new SQLWarning();
395        rowsetWarning = new RowSetWarning();
396
397    }
398
399    /**
400     * Provides a <code>CachedRowSetImpl</code> instance with the same default properties as
401     * as the zero parameter constructor.
402     * <pre>
403     *     onInsertRow = false
404     *     insertRow = null
405     *     cursorPos = 0
406     *     numRows = 0
407     *     showDeleted = false
408     *     queryTimeout = 0
409     *     maxRows = 0
410     *     maxFieldSize = 0
411     *     rowSetType = ResultSet.TYPE_SCROLL_INSENSITIVE
412     *     concurrency = ResultSet.CONCUR_UPDATABLE
413     *     readOnly = false
414     *     isolation = Connection.TRANSACTION_READ_COMMITTED
415     *     escapeProcessing = true
416     *     onInsertRow = false
417     *     insertRow = null
418     *     cursorPos = 0
419     *     absolutePos = 0
420     *     numRows = 0
421     * </pre>
422     *
423     * However, applications will have the means to specify at runtime the
424     * desired <code>SyncProvider</code> object.
425     * <p>
426     * For example, creating a <code>CachedRowSetImpl</code> object as follows ensures
427     * that a it is established with the <code>com.foo.provider.Impl</code> synchronization
428     * implementation providing the synchronization mechanism for this disconnected
429     * <code>RowSet</code> object.
430     * <pre>
431     *     Hashtable env = new Hashtable();
432     *     env.put(javax.sql.rowset.spi.SyncFactory.ROWSET_PROVIDER_NAME,
433     *         "com.foo.provider.Impl");
434     *     CachedRowSetImpl crs = new CachedRowSet(env);
435     * </pre>
436     * <p>
437     * Calling this constructor with a <code>null</code> parameter will
438     * cause the <code>SyncFactory</code> to provide the reference
439     * optimistic provider <code>com.sun.rowset.providers.RIOptimisticProvider</code>.
440     * <p>
441     * In addition, the following properties can be associated with the
442     * provider to assist in determining the choice of the synchronizaton
443     * provider such as:
444     * <ul>
445     * <li><code>ROWSET_SYNC_PROVIDER</code> - the property specifying the
446     * <code>SyncProvider</code> class name to be instantiated by the
447     * <code>SyncFacttory</code>
448     * <li><code>ROWSET_SYNC_VENDOR</code> - the property specifying the software
449     * vendor associated with a <code>SyncProvider</code> implementation.
450     * <li><code>ROWSET_SYNC_PROVIDER_VER</code> - the property specifying the
451     * version of the <code>SyncProvider</code> implementation provided by the
452     * software vendor.
453     * </ul>
454     * More specific detailes are available in the <code>SyncFactory</code>
455     * and <code>SyncProvider</code> specificiations later in this document.
456     * <p>
457     * @param env a <code>Hashtable</code> object with a list of desired
458     *        synchronization providers
459     * @throws SQLException if the requested provider cannot be found by the
460     * synchronization factory
461     * @see SyncProvider
462     */
463    public CachedRowSetImpl(@SuppressWarnings("rawtypes") Hashtable env) throws SQLException {
464
465
466        try {
467           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
468        } catch(IOException ioe) {
469            throw new RuntimeException(ioe);
470        }
471
472        if (env == null) {
473            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.nullhash").toString());
474        }
475
476        String providerName = (String)env.get(
477        javax.sql.rowset.spi.SyncFactory.ROWSET_SYNC_PROVIDER);
478
479        // set the Reader, this maybe overridden latter
480        provider =
481        SyncFactory.getInstance(providerName);
482
483        rowSetReader = provider.getRowSetReader();
484        rowSetWriter = provider.getRowSetWriter();
485
486        initParams(); // allocate the parameters collection
487        initContainer();
488        initProperties(); // set up some default values
489    }
490
491    /**
492     * Sets the <code>rvh</code> field to a new <code>Vector</code>
493     * object with a capacity of 100 and sets the
494     * <code>cursorPos</code> and <code>numRows</code> fields to zero.
495     */
496    private void initContainer() {
497
498        rvh = new Vector<Object>(100);
499        cursorPos = 0;
500        absolutePos = 0;
501        numRows = 0;
502        numDeleted = 0;
503    }
504
505    /**
506     * Sets the properties for this <code>CachedRowSetImpl</code> object to
507     * their default values. This method is called internally by the
508     * default constructor.
509     */
510
511    private void initProperties() throws SQLException {
512
513        if(resBundle == null) {
514            try {
515               resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
516            } catch(IOException ioe) {
517                throw new RuntimeException(ioe);
518            }
519        }
520        setShowDeleted(false);
521        setQueryTimeout(0);
522        setMaxRows(0);
523        setMaxFieldSize(0);
524        setType(ResultSet.TYPE_SCROLL_INSENSITIVE);
525        setConcurrency(ResultSet.CONCUR_UPDATABLE);
526        if((rvh.size() > 0) && (isReadOnly() == false))
527            setReadOnly(false);
528        else
529            setReadOnly(true);
530        setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
531        setEscapeProcessing(true);
532        //setTypeMap(null);
533        checkTransactionalWriter();
534
535        //Instantiating the vector for MatchColumns
536
537        iMatchColumns = new Vector<Integer>(10);
538        for(int i = 0; i < 10 ; i++) {
539           iMatchColumns.add(i, -1);
540        }
541
542        strMatchColumns = new Vector<String>(10);
543        for(int j = 0; j < 10; j++) {
544           strMatchColumns.add(j,null);
545        }
546    }
547
548    /**
549     * Determine whether the SyncProvider's writer implements the
550     * <code>TransactionalWriter<code> interface
551     */
552    private void checkTransactionalWriter() {
553        if (rowSetWriter != null) {
554            Class<?> c = rowSetWriter.getClass();
555            if (c != null) {
556                Class<?>[] theInterfaces = c.getInterfaces();
557                for (int i = 0; i < theInterfaces.length; i++) {
558                    if ((theInterfaces[i].getName()).indexOf("TransactionalWriter") > 0) {
559                        tXWriter = true;
560                        establishTransactionalWriter();
561                    }
562                }
563            }
564        }
565    }
566
567    /**
568     * Sets an private field to all transaction bounddaries to be set
569     */
570    private void establishTransactionalWriter() {
571        tWriter = (TransactionalWriter)provider.getRowSetWriter();
572    }
573
574    //-----------------------------------------------------------------------
575    // Properties
576    //-----------------------------------------------------------------------
577
578    /**
579     * Sets this <code>CachedRowSetImpl</code> object's command property
580     * to the given <code>String</code> object and clears the parameters,
581     * if any, that were set for the previous command.
582     * <P>
583     * The command property may not be needed
584     * if the rowset is produced by a data source, such as a spreadsheet,
585     * that does not support commands. Thus, this property is optional
586     * and may be <code>null</code>.
587     *
588     * @param cmd a <code>String</code> object containing an SQL query
589     *            that will be set as the command; may be <code>null</code>
590     * @throws SQLException if an error occurs
591     */
592    public void setCommand(String cmd) throws SQLException {
593
594        super.setCommand(cmd);
595
596        if(!buildTableName(cmd).equals("")) {
597            this.setTableName(buildTableName(cmd));
598        }
599    }
600
601
602    //---------------------------------------------------------------------
603    // Reading and writing data
604    //---------------------------------------------------------------------
605
606    /**
607     * Populates this <code>CachedRowSetImpl</code> object with data from
608     * the given <code>ResultSet</code> object.  This
609     * method is an alternative to the method <code>execute</code>
610     * for filling the rowset with data.  The method <code>populate</code>
611     * does not require that the properties needed by the method
612     * <code>execute</code>, such as the <code>command</code> property,
613     * be set. This is true because the method <code>populate</code>
614     * is given the <code>ResultSet</code> object from
615     * which to get data and thus does not need to use the properties
616     * required for setting up a connection and executing this
617     * <code>CachedRowSetImpl</code> object's command.
618     * <P>
619     * After populating this rowset with data, the method
620     * <code>populate</code> sets the rowset's metadata and
621     * then sends a <code>RowSetChangedEvent</code> object
622     * to all registered listeners prior to returning.
623     *
624     * @param data the <code>ResultSet</code> object containing the data
625     *             to be read into this <code>CachedRowSetImpl</code> object
626     * @throws SQLException if an error occurs; or the max row setting is
627     *          violated while populating the RowSet
628     * @see #execute
629     */
630
631     public void populate(ResultSet data) throws SQLException {
632        int rowsFetched;
633        Row currentRow;
634        int numCols;
635        int i;
636        Map<String, Class<?>> map = getTypeMap();
637        Object obj;
638        int mRows;
639
640        if (data == null) {
641            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.populate").toString());
642        }
643        this.resultSet = data;
644
645        // get the meta data for this ResultSet
646        RSMD = data.getMetaData();
647
648        // set up the metadata
649        RowSetMD = new RowSetMetaDataImpl();
650        initMetaData(RowSetMD, RSMD);
651
652        // release the meta-data so that aren't tempted to use it.
653        RSMD = null;
654        numCols = RowSetMD.getColumnCount();
655        mRows = this.getMaxRows();
656        rowsFetched = 0;
657        currentRow = null;
658
659        while ( data.next()) {
660
661            currentRow = new Row(numCols);
662
663            if ( rowsFetched > mRows && mRows > 0) {
664                rowsetWarning.setNextWarning(new RowSetWarning("Populating rows "
665                + "setting has exceeded max row setting"));
666            }
667            for ( i = 1; i <= numCols; i++) {
668                /*
669                 * check if the user has set a map. If no map
670                 * is set then use plain getObject. This lets
671                 * us work with drivers that do not support
672                 * getObject with a map in fairly sensible way
673                 */
674                if (map == null || map.isEmpty()) {
675                    obj = data.getObject(i);
676                } else {
677                    obj = data.getObject(i, map);
678                }
679                /*
680                 * the following block checks for the various
681                 * types that we have to serialize in order to
682                 * store - right now only structs have been tested
683                 */
684                if (obj instanceof Struct) {
685                    obj = new SerialStruct((Struct)obj, map);
686                } else if (obj instanceof SQLData) {
687                    obj = new SerialStruct((SQLData)obj, map);
688                } else if (obj instanceof Blob) {
689                    obj = new SerialBlob((Blob)obj);
690                } else if (obj instanceof Clob) {
691                    obj = new SerialClob((Clob)obj);
692                } else if (obj instanceof java.sql.Array) {
693                    if(map != null)
694                        obj = new SerialArray((java.sql.Array)obj, map);
695                    else
696                        obj = new SerialArray((java.sql.Array)obj);
697                }
698
699                currentRow.initColumnObject(i, obj);
700            }
701            rowsFetched++;
702            rvh.add(currentRow);
703        }
704
705        numRows = rowsFetched ;
706        // Also rowsFetched should be equal to rvh.size()
707
708        // notify any listeners that the rowset has changed
709        notifyRowSetChanged();
710
711
712    }
713
714    /**
715     * Initializes the given <code>RowSetMetaData</code> object with the values
716     * in the given <code>ResultSetMetaData</code> object.
717     *
718     * @param md the <code>RowSetMetaData</code> object for this
719     *           <code>CachedRowSetImpl</code> object, which will be set with
720     *           values from rsmd
721     * @param rsmd the <code>ResultSetMetaData</code> object from which new
722     *             values for md will be read
723     * @throws SQLException if an error occurs
724     */
725    private void initMetaData(RowSetMetaDataImpl md, ResultSetMetaData rsmd) throws SQLException {
726        int numCols = rsmd.getColumnCount();
727
728        md.setColumnCount(numCols);
729        for (int col=1; col <= numCols; col++) {
730            md.setAutoIncrement(col, rsmd.isAutoIncrement(col));
731            if(rsmd.isAutoIncrement(col))
732                updateOnInsert = true;
733            md.setCaseSensitive(col, rsmd.isCaseSensitive(col));
734            md.setCurrency(col, rsmd.isCurrency(col));
735            md.setNullable(col, rsmd.isNullable(col));
736            md.setSigned(col, rsmd.isSigned(col));
737            md.setSearchable(col, rsmd.isSearchable(col));
738             /*
739             * The PostgreSQL drivers sometimes return negative columnDisplaySize,
740             * which causes an exception to be thrown.  Check for it.
741             */
742            int size = rsmd.getColumnDisplaySize(col);
743            if (size < 0) {
744                size = 0;
745            }
746            md.setColumnDisplaySize(col, size);
747            md.setColumnLabel(col, rsmd.getColumnLabel(col));
748            md.setColumnName(col, rsmd.getColumnName(col));
749            md.setSchemaName(col, rsmd.getSchemaName(col));
750            /*
751             * Drivers return some strange values for precision, for non-numeric data, including reports of
752             * non-integer values; maybe we should check type, & set to 0 for non-numeric types.
753             */
754            int precision = rsmd.getPrecision(col);
755            if (precision < 0) {
756                precision = 0;
757            }
758            md.setPrecision(col, precision);
759
760            /*
761             * It seems, from a bug report, that a driver can sometimes return a negative
762             * value for scale.  javax.sql.rowset.RowSetMetaDataImpl will throw an exception
763             * if we attempt to set a negative value.  As such, we'll check for this case.
764             */
765            int scale = rsmd.getScale(col);
766            if (scale < 0) {
767                scale = 0;
768            }
769            md.setScale(col, scale);
770            md.setTableName(col, rsmd.getTableName(col));
771            md.setCatalogName(col, rsmd.getCatalogName(col));
772            md.setColumnType(col, rsmd.getColumnType(col));
773            md.setColumnTypeName(col, rsmd.getColumnTypeName(col));
774        }
775
776        if( conn != null){
777           // JDBC 4.0 mandates as does the Java EE spec that all DataBaseMetaData methods
778           // must be implemented, therefore, the previous fix for 5055528 is being backed out
779            dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy();
780        }
781    }
782
783    /**
784     * Populates this <code>CachedRowSetImpl</code> object with data,
785     * using the given connection to produce the result set from
786     * which data will be read.  A second form of this method,
787     * which takes no arguments, uses the values from this rowset's
788     * user, password, and either url or data source properties to
789     * create a new database connection. The form of <code>execute</code>
790     * that is given a connection ignores these properties.
791     *
792     * @param conn A standard JDBC <code>Connection</code> object that this
793     * <code>CachedRowSet</code> object can pass to a synchronization provider
794     * to establish a connection to the data source
795     * @throws SQLException if an invalid <code>Connection</code> is supplied
796     *           or an error occurs in establishing the connection to the
797     *           data source
798     * @see #populate
799     * @see java.sql.Connection
800     */
801    public void execute(Connection conn) throws SQLException {
802        // store the connection so the reader can find it.
803        setConnection(conn);
804
805        if(getPageSize() != 0){
806            crsReader = (CachedRowSetReader)provider.getRowSetReader();
807            crsReader.setStartPosition(1);
808            callWithCon = true;
809            crsReader.readData((RowSetInternal)this);
810        }
811
812        // Now call the current reader's readData method
813        else {
814           rowSetReader.readData((RowSetInternal)this);
815        }
816        RowSetMD = (RowSetMetaDataImpl)this.getMetaData();
817
818        if(conn != null){
819            // JDBC 4.0 mandates as does the Java EE spec that all DataBaseMetaData methods
820            // must be implemented, therefore, the previous fix for 5055528 is being backed out
821            dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy();
822        }
823
824    }
825
826    /**
827     * Sets this <code>CachedRowSetImpl</code> object's connection property
828     * to the given <code>Connection</code> object.  This method is called
829     * internally by the version of the method <code>execute</code> that takes a
830     * <code>Connection</code> object as an argument. The reader for this
831     * <code>CachedRowSetImpl</code> object can retrieve the connection stored
832     * in the rowset's connection property by calling its
833     * <code>getConnection</code> method.
834     *
835     * @param connection the <code>Connection</code> object that was passed in
836     *                   to the method <code>execute</code> and is to be stored
837     *                   in this <code>CachedRowSetImpl</code> object's connection
838     *                   property
839     */
840    private void setConnection (Connection connection) {
841        conn = connection;
842    }
843
844
845    /**
846     * Propagates all row update, insert, and delete changes to the
847     * underlying data source backing this <code>CachedRowSetImpl</code>
848     * object.
849     * <P>
850     * <b>Note</b>In the reference implementation an optimistic concurrency implementation
851     * is provided as a sample implementation of a the <code>SyncProvider</code>
852     * abstract class.
853     * <P>
854     * This method fails if any of the updates cannot be propagated back
855     * to the data source.  When it fails, the caller can assume that
856     * none of the updates are reflected in the data source.
857     * When an exception is thrown, the current row
858     * is set to the first "updated" row that resulted in an exception
859     * unless the row that caused the exception is a "deleted" row.
860     * In that case, when deleted rows are not shown, which is usually true,
861     * the current row is not affected.
862     * <P>
863     * If no <code>SyncProvider</code> is configured, the reference implementation
864     * leverages the <code>RIOptimisticProvider</code> available which provides the
865     * default and reference synchronization capabilities for disconnected
866     * <code>RowSets</code>.
867     *
868     * @throws SQLException if the cursor is on the insert row or the underlying
869     *          reference synchronization provider fails to commit the updates
870     *          to the datasource
871     * @throws SyncProviderException if an internal error occurs within the
872     *          <code>SyncProvider</code> instance during either during the
873     *          process or at any time when the <code>SyncProvider</code>
874     *          instance touches the data source.
875     * @see #acceptChanges(java.sql.Connection)
876     * @see javax.sql.RowSetWriter
877     * @see javax.sql.rowset.spi.SyncProvider
878     */
879    public void acceptChanges() throws SyncProviderException {
880        if (onInsertRow == true) {
881            throw new SyncProviderException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
882        }
883
884        int saveCursorPos = cursorPos;
885        boolean success = false;
886        boolean conflict = false;
887
888        try {
889            if (rowSetWriter != null) {
890                saveCursorPos = cursorPos;
891                conflict = rowSetWriter.writeData((RowSetInternal)this);
892                cursorPos = saveCursorPos;
893            }
894
895            if (tXWriter) {
896                // do commit/rollback's here
897                if (!conflict) {
898                    tWriter = (TransactionalWriter)rowSetWriter;
899                    tWriter.rollback();
900                    success = false;
901                } else {
902                    tWriter = (TransactionalWriter)rowSetWriter;
903                    if (tWriter instanceof CachedRowSetWriter) {
904                        ((CachedRowSetWriter)tWriter).commit(this, updateOnInsert);
905                    } else {
906                        tWriter.commit();
907                    }
908
909                    success = true;
910                }
911            }
912
913            if (success == true) {
914                setOriginal();
915            } else if (!(success) ) {
916                throw new SyncProviderException(resBundle.handleGetObject("cachedrowsetimpl.accfailed").toString());
917            }
918
919        } catch (SyncProviderException spe) {
920               throw spe;
921        } catch (SQLException e) {
922            e.printStackTrace();
923            throw new SyncProviderException(e.getMessage());
924        } catch (SecurityException e) {
925            throw new SyncProviderException(e.getMessage());
926        }
927    }
928
929    /**
930     * Propagates all row update, insert, and delete changes to the
931     * data source backing this <code>CachedRowSetImpl</code> object
932     * using the given <code>Connection</code> object.
933     * <P>
934     * The reference implementation <code>RIOptimisticProvider</code>
935     * modifies its synchronization to a write back function given
936     * the updated connection
937     * The reference implementation modifies its synchronization behaviour
938     * via the <code>SyncProvider</code> to ensure the synchronization
939     * occurs according to the updated JDBC <code>Connection</code>
940     * properties.
941     *
942     * @param con a standard JDBC <code>Connection</code> object
943     * @throws SQLException if the cursor is on the insert row or the underlying
944     *                   synchronization provider fails to commit the updates
945     *                   back to the data source
946     * @see #acceptChanges
947     * @see javax.sql.RowSetWriter
948     * @see javax.sql.rowset.spi.SyncFactory
949     * @see javax.sql.rowset.spi.SyncProvider
950     */
951    public void acceptChanges(Connection con) throws SyncProviderException{
952      setConnection(con);
953      acceptChanges();
954    }
955
956    /**
957     * Restores this <code>CachedRowSetImpl</code> object to its original state,
958     * that is, its state before the last set of changes.
959     * <P>
960     * Before returning, this method moves the cursor before the first row
961     * and sends a <code>rowSetChanged</code> event to all registered
962     * listeners.
963     * @throws SQLException if an error is occurs rolling back the RowSet
964     *           state to the definied original value.
965     * @see javax.sql.RowSetListener#rowSetChanged
966     */
967    public void restoreOriginal() throws SQLException {
968        Row currentRow;
969        for (Iterator<?> i = rvh.iterator(); i.hasNext();) {
970            currentRow = (Row)i.next();
971            if (currentRow.getInserted() == true) {
972                i.remove();
973                --numRows;
974            } else {
975                if (currentRow.getDeleted() == true) {
976                    currentRow.clearDeleted();
977                }
978                if (currentRow.getUpdated() == true) {
979                    currentRow.clearUpdated();
980                }
981            }
982        }
983        // move to before the first
984        cursorPos = 0;
985
986        // notify any listeners
987        notifyRowSetChanged();
988    }
989
990    /**
991     * Releases the current contents of this <code>CachedRowSetImpl</code>
992     * object and sends a <code>rowSetChanged</code> event object to all
993     * registered listeners.
994     *
995     * @throws SQLException if an error occurs flushing the contents of
996     *           RowSet.
997     * @see javax.sql.RowSetListener#rowSetChanged
998     */
999    public void release() throws SQLException {
1000        initContainer();
1001        notifyRowSetChanged();
1002    }
1003
1004    /**
1005     * Cancels deletion of the current row and notifies listeners that
1006     * a row has changed.
1007     * <P>
1008     * Note:  This method can be ignored if deleted rows are not being shown,
1009     * which is the normal case.
1010     *
1011     * @throws SQLException if the cursor is not on a valid row
1012     */
1013    public void undoDelete() throws SQLException {
1014        if (getShowDeleted() == false) {
1015            return;
1016        }
1017        // make sure we are on a row
1018        checkCursor();
1019
1020        // don't want this to happen...
1021        if (onInsertRow == true) {
1022            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1023        }
1024
1025        Row currentRow = (Row)getCurrentRow();
1026        if (currentRow.getDeleted() == true) {
1027            currentRow.clearDeleted();
1028            --numDeleted;
1029            notifyRowChanged();
1030        }
1031    }
1032
1033    /**
1034     * Immediately removes the current row from this
1035     * <code>CachedRowSetImpl</code> object if the row has been inserted, and
1036     * also notifies listeners the a row has changed.  An exception is thrown
1037     * if the row is not a row that has been inserted or the cursor is before
1038     * the first row, after the last row, or on the insert row.
1039     * <P>
1040     * This operation cannot be undone.
1041     *
1042     * @throws SQLException if an error occurs,
1043     *                         the cursor is not on a valid row,
1044     *                         or the row has not been inserted
1045     */
1046    public void undoInsert() throws SQLException {
1047        // make sure we are on a row
1048        checkCursor();
1049
1050        // don't want this to happen...
1051        if (onInsertRow == true) {
1052            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1053        }
1054
1055        Row currentRow = (Row)getCurrentRow();
1056        if (currentRow.getInserted() == true) {
1057            rvh.remove(cursorPos-1);
1058            --numRows;
1059            notifyRowChanged();
1060        } else {
1061            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.illegalop").toString());
1062        }
1063    }
1064
1065    /**
1066     * Immediately reverses the last update operation if the
1067     * row has been modified. This method can be
1068     * called to reverse updates on a all columns until all updates in a row have
1069     * been rolled back to their originating state since the last synchronization
1070     * (<code>acceptChanges</code>) or population. This method may also be called
1071     * while performing updates to the insert row.
1072     * <P>
1073     * {@code undoUpdate} may be called at any time during the life-time of a
1074     * rowset, however after a synchronization has occurs this method has no
1075     * affect until further modification to the RowSet data occurs.
1076     *
1077     * @throws SQLException if cursor is before the first row, after the last
1078     *     row in rowset.
1079     * @see #undoDelete
1080     * @see #undoInsert
1081     * @see java.sql.ResultSet#cancelRowUpdates
1082     */
1083    public void undoUpdate() throws SQLException {
1084        // if on insert row, cancel the insert row
1085        // make the insert row flag,
1086        // cursorPos back to the current row
1087        moveToCurrentRow();
1088
1089        // else if not on insert row
1090        // call undoUpdate or undoInsert
1091        undoDelete();
1092
1093        undoInsert();
1094
1095    }
1096
1097    //--------------------------------------------------------------------
1098    // Views
1099    //--------------------------------------------------------------------
1100
1101    /**
1102     * Returns a new <code>RowSet</code> object backed by the same data as
1103     * that of this <code>CachedRowSetImpl</code> object and sharing a set of cursors
1104     * with it. This allows cursors to interate over a shared set of rows, providing
1105     * multiple views of the underlying data.
1106     *
1107     * @return a <code>RowSet</code> object that is a copy of this <code>CachedRowSetImpl</code>
1108     * object and shares a set of cursors with it
1109     * @throws SQLException if an error occurs or cloning is
1110     *                         not supported
1111     * @see javax.sql.RowSetEvent
1112     * @see javax.sql.RowSetListener
1113     */
1114    public RowSet createShared() throws SQLException {
1115        RowSet clone;
1116        try {
1117            clone = (RowSet)clone();
1118        } catch (CloneNotSupportedException ex) {
1119            throw new SQLException(ex.getMessage());
1120        }
1121        return clone;
1122    }
1123
1124    /**
1125     * Returns a new <code>RowSet</code> object containing by the same data
1126     * as this <code>CachedRowSetImpl</code> object.  This method
1127     * differs from the method <code>createCopy</code> in that it throws a
1128     * <code>CloneNotSupportedException</code> object instead of an
1129     * <code>SQLException</code> object, as the method <code>createShared</code>
1130     * does.  This <code>clone</code>
1131     * method is called internally by the method <code>createShared</code>,
1132     * which catches the <code>CloneNotSupportedException</code> object
1133     * and in turn throws a new <code>SQLException</code> object.
1134     *
1135     * @return a copy of this <code>CachedRowSetImpl</code> object
1136     * @throws CloneNotSupportedException if an error occurs when
1137     * attempting to clone this <code>CachedRowSetImpl</code> object
1138     * @see #createShared
1139     */
1140    protected Object clone() throws CloneNotSupportedException  {
1141        return (super.clone());
1142    }
1143
1144    /**
1145     * Creates a <code>RowSet</code> object that is a deep copy of
1146     * this <code>CachedRowSetImpl</code> object's data, including
1147     * constraints.  Updates made
1148     * on a copy are not visible to the original rowset;
1149     * a copy of a rowset is completely independent from the original.
1150     * <P>
1151     * Making a copy saves the cost of creating an identical rowset
1152     * from first principles, which can be quite expensive.
1153     * For example, it can eliminate the need to query a
1154     * remote database server.
1155     * @return a new <code>CachedRowSet</code> object that is a deep copy
1156     *           of this <code>CachedRowSet</code> object and is
1157     *           completely independent from this <code>CachedRowSetImpl</code>
1158     *           object.
1159     * @throws SQLException if an error occurs in generating the copy of this
1160     *           of the <code>CachedRowSetImpl</code>
1161     * @see #createShared
1162     * @see javax.sql.RowSetEvent
1163     * @see javax.sql.RowSetListener
1164     */
1165    public CachedRowSet createCopy() throws SQLException {
1166        ObjectOutputStream out;
1167        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
1168        try {
1169            out = new ObjectOutputStream(bOut);
1170            out.writeObject(this);
1171        } catch (IOException ex) {
1172            throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1173        }
1174
1175        ObjectInputStream in;
1176
1177        try {
1178            ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
1179            in = new ObjectInputStream(bIn);
1180        } catch (StreamCorruptedException ex) {
1181            throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1182        } catch (IOException ex) {
1183            throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1184        }
1185
1186        try {
1187            //return ((CachedRowSet)(in.readObject()));
1188            CachedRowSetImpl crsTemp = (CachedRowSetImpl)in.readObject();
1189            crsTemp.resBundle = this.resBundle;
1190            return ((CachedRowSet)crsTemp);
1191
1192        } catch (ClassNotFoundException ex) {
1193            throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1194        } catch (OptionalDataException ex) {
1195            throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1196        } catch (IOException ex) {
1197            throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1198        }
1199    }
1200
1201    /**
1202     * Creates a <code>RowSet</code> object that is a copy of
1203     * this <code>CachedRowSetImpl</code> object's table structure
1204     * and the constraints only.
1205     * There will be no data in the object being returned.
1206     * Updates made on a copy are not visible to the original rowset.
1207     * <P>
1208     * This helps in getting the underlying XML schema which can
1209     * be used as the basis for populating a <code>WebRowSet</code>.
1210     *
1211     * @return a new <code>CachedRowSet</code> object that is a copy
1212     * of this <code>CachedRowSetImpl</code> object's schema and
1213     * retains all the constraints on the original rowset but contains
1214     * no data
1215     * @throws SQLException if an error occurs in generating the copy
1216     * of the <code>CachedRowSet</code> object
1217     * @see #createShared
1218     * @see #createCopy
1219     * @see #createCopyNoConstraints
1220     * @see javax.sql.RowSetEvent
1221     * @see javax.sql.RowSetListener
1222     */
1223    public CachedRowSet createCopySchema() throws SQLException {
1224        // Copy everything except data i.e all constraints
1225
1226        // Store the number of rows of "this"
1227        // and make numRows equals zero.
1228        // and make data also zero.
1229        int nRows = numRows;
1230        numRows = 0;
1231
1232        CachedRowSet crs = this.createCopy();
1233
1234        // reset this object back to number of rows.
1235        numRows = nRows;
1236
1237        return crs;
1238    }
1239
1240    /**
1241     * Creates a <code>CachedRowSet</code> object that is a copy of
1242     * this <code>CachedRowSetImpl</code> object's data only.
1243     * All constraints set in this object will not be there
1244     * in the returning object.  Updates made
1245     * on a copy are not visible to the original rowset.
1246     *
1247     * @return a new <code>CachedRowSet</code> object that is a deep copy
1248     * of this <code>CachedRowSetImpl</code> object and is
1249     * completely independent from this <code>CachedRowSetImpl</code> object
1250     * @throws SQLException if an error occurs in generating the copy of the
1251     * of the <code>CachedRowSet</code>
1252     * @see #createShared
1253     * @see #createCopy
1254     * @see #createCopySchema
1255     * @see javax.sql.RowSetEvent
1256     * @see javax.sql.RowSetListener
1257     */
1258    public CachedRowSet createCopyNoConstraints() throws SQLException {
1259        // Copy the whole data ONLY without any constraints.
1260        CachedRowSetImpl crs;
1261        crs = (CachedRowSetImpl)this.createCopy();
1262
1263        crs.initProperties();
1264        try {
1265            crs.unsetMatchColumn(crs.getMatchColumnIndexes());
1266        } catch(SQLException sqle) {
1267            //do nothing, if the setMatchColumn is not set.
1268        }
1269
1270        try {
1271            crs.unsetMatchColumn(crs.getMatchColumnNames());
1272        } catch(SQLException sqle) {
1273            //do nothing, if the setMatchColumn is not set.
1274        }
1275
1276        return crs;
1277    }
1278
1279    /**
1280     * Converts this <code>CachedRowSetImpl</code> object to a collection
1281     * of tables. The sample implementation utilitizes the <code>TreeMap</code>
1282     * collection type.
1283     * This class guarantees that the map will be in ascending key order,
1284     * sorted according to the natural order for the key's class.
1285     *
1286     * @return a <code>Collection</code> object consisting of tables,
1287     *         each of which is a copy of a row in this
1288     *         <code>CachedRowSetImpl</code> object
1289     * @throws SQLException if an error occurs in generating the collection
1290     * @see #toCollection(int)
1291     * @see #toCollection(String)
1292     * @see java.util.TreeMap
1293     */
1294    public Collection<?> toCollection() throws SQLException {
1295
1296        TreeMap<Integer, Object> tMap = new TreeMap<>();
1297
1298        for (int i = 0; i<numRows; i++) {
1299            tMap.put(i, rvh.get(i));
1300        }
1301
1302        return (tMap.values());
1303    }
1304
1305    /**
1306     * Returns the specified column of this <code>CachedRowSetImpl</code> object
1307     * as a <code>Collection</code> object.  This method makes a copy of the
1308     * column's data and utilitizes the <code>Vector</code> to establish the
1309     * collection. The <code>Vector</code> class implements a growable array
1310     * objects allowing the individual components to be accessed using an
1311     * an integer index similar to that of an array.
1312     *
1313     * @return a <code>Collection</code> object that contains the value(s)
1314     *         stored in the specified column of this
1315     *         <code>CachedRowSetImpl</code>
1316     *         object
1317     * @throws SQLException if an error occurs generated the collection; or
1318     *          an invalid column is provided.
1319     * @see #toCollection()
1320     * @see #toCollection(String)
1321     * @see java.util.Vector
1322     */
1323    public Collection<?> toCollection(int column) throws SQLException {
1324
1325        int nRows = numRows;
1326        Vector<Object> vec = new Vector<>(nRows);
1327
1328        // create a copy
1329        CachedRowSetImpl crsTemp;
1330        crsTemp = (CachedRowSetImpl) this.createCopy();
1331
1332        while(nRows!=0) {
1333            crsTemp.next();
1334            vec.add(crsTemp.getObject(column));
1335            nRows--;
1336        }
1337
1338        return (Collection)vec;
1339    }
1340
1341    /**
1342     * Returns the specified column of this <code>CachedRowSetImpl</code> object
1343     * as a <code>Collection</code> object.  This method makes a copy of the
1344     * column's data and utilitizes the <code>Vector</code> to establish the
1345     * collection. The <code>Vector</code> class implements a growable array
1346     * objects allowing the individual components to be accessed using an
1347     * an integer index similar to that of an array.
1348     *
1349     * @return a <code>Collection</code> object that contains the value(s)
1350     *         stored in the specified column of this
1351     *         <code>CachedRowSetImpl</code>
1352     *         object
1353     * @throws SQLException if an error occurs generated the collection; or
1354     *          an invalid column is provided.
1355     * @see #toCollection()
1356     * @see #toCollection(int)
1357     * @see java.util.Vector
1358     */
1359    public Collection<?> toCollection(String column) throws SQLException {
1360        return toCollection(getColIdxByName(column));
1361    }
1362
1363    //--------------------------------------------------------------------
1364    // Advanced features
1365    //--------------------------------------------------------------------
1366
1367
1368    /**
1369     * Returns the <code>SyncProvider</code> implementation being used
1370     * with this <code>CachedRowSetImpl</code> implementation rowset.
1371     *
1372     * @return the SyncProvider used by the rowset. If not provider was
1373     *          set when the rowset was instantiated, the reference
1374     *          implementation (default) provider is returned.
1375     * @throws SQLException if error occurs while return the
1376     *          <code>SyncProvider</code> instance.
1377     */
1378    public SyncProvider getSyncProvider() throws SQLException {
1379        return provider;
1380    }
1381
1382    /**
1383     * Sets the active <code>SyncProvider</code> and attempts to load
1384     * load the new provider using the <code>SyncFactory</code> SPI.
1385     *
1386     * @throws SQLException if an error occurs while resetting the
1387     *          <code>SyncProvider</code>.
1388     */
1389    public void setSyncProvider(String providerStr) throws SQLException {
1390        provider =
1391        SyncFactory.getInstance(providerStr);
1392
1393        rowSetReader = provider.getRowSetReader();
1394        rowSetWriter = provider.getRowSetWriter();
1395    }
1396
1397
1398    //-----------------
1399    // methods inherited from RowSet
1400    //-----------------
1401
1402
1403
1404
1405
1406
1407    //---------------------------------------------------------------------
1408    // Reading and writing data
1409    //---------------------------------------------------------------------
1410
1411    /**
1412     * Populates this <code>CachedRowSetImpl</code> object with data.
1413     * This form of the method uses the rowset's user, password, and url or
1414     * data source name properties to create a database
1415     * connection.  If properties that are needed
1416     * have not been set, this method will throw an exception.
1417     * <P>
1418     * Another form of this method uses an existing JDBC <code>Connection</code>
1419     * object instead of creating a new one; therefore, it ignores the
1420     * properties used for establishing a new connection.
1421     * <P>
1422     * The query specified by the command property is executed to create a
1423     * <code>ResultSet</code> object from which to retrieve data.
1424     * The current contents of the rowset are discarded, and the
1425     * rowset's metadata is also (re)set.  If there are outstanding updates,
1426     * they are also ignored.
1427     * <P>
1428     * The method <code>execute</code> closes any database connections that it
1429     * creates.
1430     *
1431     * @throws SQLException if an error occurs or the
1432     *                         necessary properties have not been set
1433     */
1434    public void execute() throws SQLException {
1435        execute(null);
1436    }
1437
1438
1439
1440    //-----------------------------------
1441    // Methods inherited from ResultSet
1442    //-----------------------------------
1443
1444    /**
1445     * Moves the cursor down one row from its current position and
1446     * returns <code>true</code> if the new cursor position is a
1447     * valid row.
1448     * The cursor for a new <code>ResultSet</code> object is initially
1449     * positioned before the first row. The first call to the method
1450     * <code>next</code> moves the cursor to the first row, making it
1451     * the current row; the second call makes the second row the
1452     * current row, and so on.
1453     *
1454     * <P>If an input stream from the previous row is open, it is
1455     * implicitly closed. The <code>ResultSet</code> object's warning
1456     * chain is cleared when a new row is read.
1457     *
1458     * @return <code>true</code> if the new current row is valid;
1459     *         <code>false</code> if there are no more rows
1460     * @throws SQLException if an error occurs or
1461     *            the cursor is not positioned in the rowset, before
1462     *            the first row, or after the last row
1463     */
1464    public boolean next() throws SQLException {
1465        /*
1466         * make sure things look sane. The cursor must be
1467         * positioned in the rowset or before first (0) or
1468         * after last (numRows + 1)
1469         */
1470        if (cursorPos < 0 || cursorPos >= numRows + 1) {
1471            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1472        }
1473        // now move and notify
1474        boolean ret = this.internalNext();
1475        notifyCursorMoved();
1476
1477        return ret;
1478    }
1479
1480    /**
1481     * Moves this <code>CachedRowSetImpl</code> object's cursor to the next
1482     * row and returns <code>true</code> if the cursor is still in the rowset;
1483     * returns <code>false</code> if the cursor has moved to the position after
1484     * the last row.
1485     * <P>
1486     * This method handles the cases where the cursor moves to a row that
1487     * has been deleted.
1488     * If this rowset shows deleted rows and the cursor moves to a row
1489     * that has been deleted, this method moves the cursor to the next
1490     * row until the cursor is on a row that has not been deleted.
1491     * <P>
1492     * The method <code>internalNext</code> is called by methods such as
1493     * <code>next</code>, <code>absolute</code>, and <code>relative</code>,
1494     * and, as its name implies, is only called internally.
1495     * <p>
1496     * This is a implementation only method and is not required as a standard
1497     * implementation of the <code>CachedRowSet</code> interface.
1498     *
1499     * @return <code>true</code> if the cursor is on a valid row in this
1500     *         rowset; <code>false</code> if it is after the last row
1501     * @throws SQLException if an error occurs
1502     */
1503    protected boolean internalNext() throws SQLException {
1504        boolean ret = false;
1505
1506        do {
1507            if (cursorPos < numRows) {
1508                ++cursorPos;
1509                ret = true;
1510            } else if (cursorPos == numRows) {
1511                // increment to after last
1512                ++cursorPos;
1513                ret = false;
1514                break;
1515            }
1516        } while ((getShowDeleted() == false) && (rowDeleted() == true));
1517
1518        /* each call to internalNext may increment cursorPos multiple
1519         * times however, the absolutePos only increments once per call.
1520         */
1521        if (ret == true)
1522            absolutePos++;
1523        else
1524            absolutePos = 0;
1525
1526        return ret;
1527    }
1528
1529    /**
1530     * Closes this <code>CachedRowSetImpl</code> objecy and releases any resources
1531     * it was using.
1532     *
1533     * @throws SQLException if an error occurs when releasing any resources in use
1534     * by this <code>CachedRowSetImpl</code> object
1535     */
1536    public void close() throws SQLException {
1537
1538        // close all data structures holding
1539        // the disconnected rowset
1540
1541        cursorPos = 0;
1542        absolutePos = 0;
1543        numRows = 0;
1544        numDeleted = 0;
1545
1546        // set all insert(s), update(s) & delete(s),
1547        // if at all, to their initial values.
1548        initProperties();
1549
1550        // clear the vector of it's present contents
1551        rvh.clear();
1552
1553        // this will make it eligible for gc
1554        // rvh = null;
1555    }
1556
1557    /**
1558     * Reports whether the last column read was SQL <code>NULL</code>.
1559     * Note that you must first call the method <code>getXXX</code>
1560     * on a column to try to read its value and then call the method
1561     * <code>wasNull</code> to determine whether the value was
1562     * SQL <code>NULL</code>.
1563     *
1564     * @return <code>true</code> if the value in the last column read
1565     *         was SQL <code>NULL</code>; <code>false</code> otherwise
1566     * @throws SQLException if an error occurs
1567     */
1568    public boolean wasNull() throws SQLException {
1569        return lastValueNull;
1570    }
1571
1572    /**
1573     * Sets the field <code>lastValueNull</code> to the given
1574     * <code>boolean</code> value.
1575     *
1576     * @param value <code>true</code> to indicate that the value of
1577     *        the last column read was SQL <code>NULL</code>;
1578     *        <code>false</code> to indicate that it was not
1579     */
1580    private void setLastValueNull(boolean value) {
1581        lastValueNull = value;
1582    }
1583
1584    // Methods for accessing results by column index
1585
1586    /**
1587     * Checks to see whether the given index is a valid column number
1588     * in this <code>CachedRowSetImpl</code> object and throws
1589     * an <code>SQLException</code> if it is not. The index is out of bounds
1590     * if it is less than <code>1</code> or greater than the number of
1591     * columns in this rowset.
1592     * <P>
1593     * This method is called internally by the <code>getXXX</code> and
1594     * <code>updateXXX</code> methods.
1595     *
1596     * @param idx the number of a column in this <code>CachedRowSetImpl</code>
1597     *            object; must be between <code>1</code> and the number of
1598     *            rows in this rowset
1599     * @throws SQLException if the given index is out of bounds
1600     */
1601    private void checkIndex(int idx) throws SQLException {
1602        if (idx < 1 || idx > RowSetMD.getColumnCount()) {
1603            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcol").toString());
1604        }
1605    }
1606
1607    /**
1608     * Checks to see whether the cursor for this <code>CachedRowSetImpl</code>
1609     * object is on a row in the rowset and throws an
1610     * <code>SQLException</code> if it is not.
1611     * <P>
1612     * This method is called internally by <code>getXXX</code> methods, by
1613     * <code>updateXXX</code> methods, and by methods that update, insert,
1614     * or delete a row or that cancel a row update, insert, or delete.
1615     *
1616     * @throws SQLException if the cursor for this <code>CachedRowSetImpl</code>
1617     *         object is not on a valid row
1618     */
1619    private void checkCursor() throws SQLException {
1620        if (isAfterLast() == true || isBeforeFirst() == true) {
1621            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1622        }
1623    }
1624
1625    /**
1626     * Returns the column number of the column with the given name in this
1627     * <code>CachedRowSetImpl</code> object.  This method throws an
1628     * <code>SQLException</code> if the given name is not the name of
1629     * one of the columns in this rowset.
1630     *
1631     * @param name a <code>String</code> object that is the name of a column in
1632     *              this <code>CachedRowSetImpl</code> object
1633     * @throws SQLException if the given name does not match the name of one of
1634     *         the columns in this rowset
1635     */
1636    private int getColIdxByName(String name) throws SQLException {
1637        RowSetMD = (RowSetMetaDataImpl)this.getMetaData();
1638        int cols = RowSetMD.getColumnCount();
1639
1640        for (int i=1; i <= cols; ++i) {
1641            String colName = RowSetMD.getColumnName(i);
1642            if (colName != null)
1643                if (name.equalsIgnoreCase(colName))
1644                    return (i);
1645                else
1646                    continue;
1647        }
1648        throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalcolnm").toString());
1649
1650    }
1651
1652    /**
1653     * Returns the insert row or the current row of this
1654     * <code>CachedRowSetImpl</code>object.
1655     *
1656     * @return the <code>Row</code> object on which this <code>CachedRowSetImpl</code>
1657     * objects's cursor is positioned
1658     */
1659    protected BaseRow getCurrentRow() {
1660        if (onInsertRow == true) {
1661            return (BaseRow)insertRow;
1662        } else {
1663            return (BaseRow)(rvh.get(cursorPos - 1));
1664        }
1665    }
1666
1667    /**
1668     * Removes the row on which the cursor is positioned.
1669     * <p>
1670     * This is a implementation only method and is not required as a standard
1671     * implementation of the <code>CachedRowSet</code> interface.
1672     *
1673     * @throws SQLException if the cursor is positioned on the insert
1674     *            row
1675     */
1676    protected void removeCurrentRow() {
1677        ((Row)getCurrentRow()).setDeleted();
1678        rvh.remove(cursorPos - 1);
1679        --numRows;
1680    }
1681
1682
1683    /**
1684     * Retrieves the value of the designated column in the current row
1685     * of this <code>CachedRowSetImpl</code> object as a
1686     * <code>String</code> object.
1687     *
1688     * @param columnIndex the first column is <code>1</code>, the second
1689     *        is <code>2</code>, and so on; must be <code>1</code> or larger
1690     *        and equal to or less than the number of columns in the rowset
1691     * @return the column value; if the value is SQL <code>NULL</code>, the
1692     *         result is <code>null</code>
1693     * @throws SQLException if (1) the given column index is out of bounds,
1694     * (2) the cursor is not on one of this rowset's rows or its
1695     * insert row, or (3) the designated column does not store an
1696     * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
1697     * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, <b>CHAR</b>, <b>VARCHAR</b></code>
1698     * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1699     * recommended return type.
1700     */
1701    public String getString(int columnIndex) throws SQLException {
1702        Object value;
1703
1704        // sanity check.
1705        checkIndex(columnIndex);
1706        // make sure the cursor is on a valid row
1707        checkCursor();
1708
1709        setLastValueNull(false);
1710        value = getCurrentRow().getColumnObject(columnIndex);
1711
1712        // check for SQL NULL
1713        if (value == null) {
1714            setLastValueNull(true);
1715            return null;
1716        }
1717
1718        return value.toString();
1719    }
1720
1721    /**
1722     * Retrieves the value of the designated column in the current row
1723     * of this <code>CachedRowSetImpl</code> object as a
1724     * <code>boolean</code> value.
1725     *
1726     * @param columnIndex the first column is <code>1</code>, the second
1727     *        is <code>2</code>, and so on; must be <code>1</code> or larger
1728     *        and equal to or less than the number of columns in the rowset
1729     * @return the column value as a <code>boolean</code> in the Java progamming language;
1730     *        if the value is SQL <code>NULL</code>, the result is <code>false</code>
1731     * @throws SQLException if (1) the given column index is out of bounds,
1732     *            (2) the cursor is not on one of this rowset's rows or its
1733     *            insert row, or (3) the designated column does not store an
1734     *            SQL <code>BOOLEAN</code> value
1735     * @see #getBoolean(String)
1736     */
1737    public boolean getBoolean(int columnIndex) throws SQLException {
1738        Object value;
1739
1740        // sanity check.
1741        checkIndex(columnIndex);
1742        // make sure the cursor is on a valid row
1743        checkCursor();
1744
1745        setLastValueNull(false);
1746        value = getCurrentRow().getColumnObject(columnIndex);
1747
1748        // check for SQL NULL
1749        if (value == null) {
1750            setLastValueNull(true);
1751            return false;
1752        }
1753
1754        // check for Boolean...
1755        if (value instanceof Boolean) {
1756            return ((Boolean)value).booleanValue();
1757        }
1758
1759        // convert to a Double and compare to zero
1760        try {
1761            return Double.compare(Double.parseDouble(value.toString()), 0) != 0;
1762        } catch (NumberFormatException ex) {
1763            throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.boolfail").toString(),
1764                  new Object[] {value.toString().trim(), columnIndex}));
1765        }
1766    }
1767
1768    /**
1769     * Retrieves the value of the designated column in the current row
1770     * of this <code>CachedRowSetImpl</code> object as a
1771     * <code>byte</code> value.
1772     *
1773     * @param columnIndex the first column is <code>1</code>, the second
1774     *        is <code>2</code>, and so on; must be <code>1</code> or larger
1775     *        and equal to or less than the number of columns in the rowset
1776     * @return the column value as a <code>byte</code> in the Java programming
1777     * language; if the value is SQL <code>NULL</code>, the result is <code>0</code>
1778     * @throws SQLException if (1) the given column index is out of bounds,
1779     *            (2) the cursor is not on one of this rowset's rows or its
1780     *            insert row, or (3) the designated column does not store an
1781     *            SQL <code><b>TINYINT</b>, SMALLINT, INTEGER, BIGINT, REAL,
1782     *            FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1783     *            or <code>LONGVARCHAR</code> value. The bold SQL type
1784     *            designates the recommended return type.
1785     * @see #getByte(String)
1786     */
1787    public byte getByte(int columnIndex) throws SQLException {
1788        Object value;
1789
1790        // sanity check.
1791        checkIndex(columnIndex);
1792        // make sure the cursor is on a valid row
1793        checkCursor();
1794
1795        setLastValueNull(false);
1796        value = getCurrentRow().getColumnObject(columnIndex);
1797
1798        // check for SQL NULL
1799        if (value == null) {
1800            setLastValueNull(true);
1801            return (byte)0;
1802        }
1803        try {
1804            return ((Byte.valueOf(value.toString())).byteValue());
1805        } catch (NumberFormatException ex) {
1806            throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.bytefail").toString(),
1807                  new Object[] {value.toString().trim(), columnIndex}));
1808        }
1809    }
1810
1811    /**
1812     * Retrieves the value of the designated column in the current row
1813     * of this <code>CachedRowSetImpl</code> object as a
1814     * <code>short</code> value.
1815     *
1816     * @param columnIndex the first column is <code>1</code>, the second
1817     *        is <code>2</code>, and so on; must be <code>1</code> or larger
1818     *        and equal to or less than the number of columns in the rowset
1819     * @return the column value; if the value is SQL <code>NULL</code>, the
1820     *         result is <code>0</code>
1821     * @throws SQLException if (1) the given column index is out of bounds,
1822     * (2) the cursor is not on one of this rowset's rows or its
1823     * insert row, or (3) the designated column does not store an
1824     * SQL <code>TINYINT, <b>SMALLINT</b>, INTEGER, BIGINT, REAL
1825     * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1826     * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1827     * recommended return type.
1828     * @see #getShort(String)
1829     */
1830    public short getShort(int columnIndex) throws SQLException {
1831        Object value;
1832
1833        // sanity check.
1834        checkIndex(columnIndex);
1835        // make sure the cursor is on a valid row
1836        checkCursor();
1837
1838        setLastValueNull(false);
1839        value = getCurrentRow().getColumnObject(columnIndex);
1840
1841        // check for SQL NULL
1842        if (value == null) {
1843            setLastValueNull(true);
1844            return (short)0;
1845        }
1846
1847        try {
1848            return ((Short.valueOf(value.toString().trim())).shortValue());
1849        } catch (NumberFormatException ex) {
1850            throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.shortfail").toString(),
1851                  new Object[] {value.toString().trim(), columnIndex}));
1852        }
1853    }
1854
1855    /**
1856     * Retrieves the value of the designated column in the current row
1857     * of this <code>CachedRowSetImpl</code> object as an
1858     * <code>int</code> value.
1859     *
1860     * @param columnIndex the first column is <code>1</code>, the second
1861     *        is <code>2</code>, and so on; must be <code>1</code> or larger
1862     *        and equal to or less than the number of columns in the rowset
1863     * @return the column value; if the value is SQL <code>NULL</code>, the
1864     *         result is <code>0</code>
1865     * @throws SQLException if (1) the given column index is out of bounds,
1866     * (2) the cursor is not on one of this rowset's rows or its
1867     * insert row, or (3) the designated column does not store an
1868     * SQL <code>TINYINT, SMALLINT, <b>INTEGER</b>, BIGINT, REAL
1869     * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1870     * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1871     * recommended return type.
1872     */
1873    public int getInt(int columnIndex) throws SQLException {
1874        Object value;
1875
1876        // sanity check.
1877        checkIndex(columnIndex);
1878        // make sure the cursor is on a valid row
1879        checkCursor();
1880
1881        setLastValueNull(false);
1882        value = getCurrentRow().getColumnObject(columnIndex);
1883
1884        // check for SQL NULL
1885        if (value == null) {
1886            setLastValueNull(true);
1887            return 0;
1888        }
1889
1890        try {
1891            return ((Integer.valueOf(value.toString().trim())).intValue());
1892        } catch (NumberFormatException ex) {
1893            throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.intfail").toString(),
1894                  new Object[] {value.toString().trim(), columnIndex}));
1895        }
1896    }
1897
1898    /**
1899     * Retrieves the value of the designated column in the current row
1900     * of this <code>CachedRowSetImpl</code> object as a
1901     * <code>long</code> value.
1902     *
1903     * @param columnIndex the first column is <code>1</code>, the second
1904     *        is <code>2</code>, and so on; must be <code>1</code> or larger
1905     *        and equal to or less than the number of columns in the rowset
1906     * @return the column value; if the value is SQL <code>NULL</code>, the
1907     *         result is <code>0</code>
1908     * @throws SQLException if (1) the given column index is out of bounds,
1909     * (2) the cursor is not on one of this rowset's rows or its
1910     * insert row, or (3) the designated column does not store an
1911     * SQL <code>TINYINT, SMALLINT, INTEGER, <b>BIGINT</b>, REAL
1912     * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1913     * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1914     * recommended return type.
1915     * @see #getLong(String)
1916     */
1917    public long getLong(int columnIndex) throws SQLException {
1918        Object value;
1919
1920        // sanity check.
1921        checkIndex(columnIndex);
1922        // make sure the cursor is on a valid row
1923        checkCursor();
1924
1925        setLastValueNull(false);
1926        value = getCurrentRow().getColumnObject(columnIndex);
1927
1928        // check for SQL NULL
1929        if (value == null) {
1930            setLastValueNull(true);
1931            return (long)0;
1932        }
1933        try {
1934            return ((Long.valueOf(value.toString().trim())).longValue());
1935        } catch (NumberFormatException ex) {
1936            throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.longfail").toString(),
1937                  new Object[] {value.toString().trim(), columnIndex}));
1938        }
1939    }
1940
1941    /**
1942     * Retrieves the value of the designated column in the current row
1943     * of this <code>CachedRowSetImpl</code> object as a
1944     * <code>float</code> value.
1945     *
1946     * @param columnIndex the first column is <code>1</code>, the second
1947     *        is <code>2</code>, and so on; must be <code>1</code> or larger
1948     *        and equal to or less than the number of columns in the rowset
1949     * @return the column value; if the value is SQL <code>NULL</code>, the
1950     *         result is <code>0</code>
1951     * @throws SQLException if (1) the given column index is out of bounds,
1952     * (2) the cursor is not on one of this rowset's rows or its
1953     * insert row, or (3) the designated column does not store an
1954     * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, <b>REAL</b>,
1955     * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1956     * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1957     * recommended return type.
1958     * @see #getFloat(String)
1959     */
1960    public float getFloat(int columnIndex) throws SQLException {
1961        Object value;
1962
1963        // sanity check.
1964        checkIndex(columnIndex);
1965        // make sure the cursor is on a valid row
1966        checkCursor();
1967
1968        setLastValueNull(false);
1969        value = getCurrentRow().getColumnObject(columnIndex);
1970
1971        // check for SQL NULL
1972        if (value == null) {
1973            setLastValueNull(true);
1974            return (float)0;
1975        }
1976        try {
1977            return Float.parseFloat(value.toString());
1978        } catch (NumberFormatException ex) {
1979            throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.floatfail").toString(),
1980                  new Object[] {value.toString().trim(), columnIndex}));
1981        }
1982    }
1983
1984    /**
1985     * Retrieves the value of the designated column in the current row
1986     * of this <code>CachedRowSetImpl</code> object as a
1987     * <code>double</code> value.
1988     *
1989     * @param columnIndex the first column is <code>1</code>, the second
1990     *        is <code>2</code>, and so on; must be <code>1</code> or larger
1991     *        and equal to or less than the number of columns in the rowset
1992     * @return the column value; if the value is SQL <code>NULL</code>, the
1993     *         result is <code>0</code>
1994     * @throws SQLException if (1) the given column index is out of bounds,
1995     * (2) the cursor is not on one of this rowset's rows or its
1996     * insert row, or (3) the designated column does not store an
1997     * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
1998     * <b>FLOAT</b>, <b>DOUBLE</b>, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1999     * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
2000     * recommended return type.
2001     * @see #getDouble(String)
2002     *
2003     */
2004    public double getDouble(int columnIndex) throws SQLException {
2005        Object value;
2006
2007        // sanity check.
2008        checkIndex(columnIndex);
2009        // make sure the cursor is on a valid row
2010        checkCursor();
2011
2012        setLastValueNull(false);
2013        value = getCurrentRow().getColumnObject(columnIndex);
2014
2015        // check for SQL NULL
2016        if (value == null) {
2017            setLastValueNull(true);
2018            return (double)0;
2019        }
2020        try {
2021            return Double.parseDouble(value.toString().trim());
2022        } catch (NumberFormatException ex) {
2023            throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.doublefail").toString(),
2024                  new Object[] {value.toString().trim(), columnIndex}));
2025        }
2026    }
2027
2028    /**
2029     * Retrieves the value of the designated column in the current row
2030     * of this <code>CachedRowSetImpl</code> object as a
2031     * <code>java.math.BigDecimal</code> object.
2032     * <P>
2033     * This method is deprecated; use the version of <code>getBigDecimal</code>
2034     * that does not take a scale parameter and returns a value with full
2035     * precision.
2036     *
2037     * @param columnIndex the first column is <code>1</code>, the second
2038     *        is <code>2</code>, and so on; must be <code>1</code> or larger
2039     *        and equal to or less than the number of columns in the rowset
2040     * @param scale the number of digits to the right of the decimal point in the
2041     *        value returned
2042     * @return the column value with the specified number of digits to the right
2043     *         of the decimal point; if the value is SQL <code>NULL</code>, the
2044     *         result is <code>null</code>
2045     * @throws SQLException if the given column index is out of bounds,
2046     *            the cursor is not on a valid row, or this method fails
2047     * @deprecated
2048     */
2049    @Deprecated
2050    public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
2051        Object value;
2052        BigDecimal bDecimal, retVal;
2053
2054        // sanity check.
2055        checkIndex(columnIndex);
2056        // make sure the cursor is on a valid row
2057        checkCursor();
2058
2059        setLastValueNull(false);
2060        value = getCurrentRow().getColumnObject(columnIndex);
2061
2062        // check for SQL NULL
2063        if (value == null) {
2064            setLastValueNull(true);
2065            return (new BigDecimal(0));
2066        }
2067
2068        bDecimal = this.getBigDecimal(columnIndex);
2069
2070        retVal = bDecimal.setScale(scale);
2071
2072        return retVal;
2073    }
2074
2075    /**
2076     * Retrieves the value of the designated column in the current row
2077     * of this <code>CachedRowSetImpl</code> object as a
2078     * <code>byte</code> array value.
2079     *
2080     * @param columnIndex the first column is <code>1</code>, the second
2081     *        is <code>2</code>, and so on; must be <code>1</code> or larger
2082     *        and equal to or less than the number of columns in the rowset
2083     * @return the column value as a <code>byte</code> array in the Java programming
2084     * language; if the value is SQL <code>NULL</code>, the
2085     * result is <code>null</code>
2086     *
2087     * @throws SQLException if (1) the given column index is out of bounds,
2088     * (2) the cursor is not on one of this rowset's rows or its
2089     * insert row, or (3) the designated column does not store an
2090     * SQL <code><b>BINARY</b>, <b>VARBINARY</b> or
2091     * LONGVARBINARY</code> value.
2092     * The bold SQL type designates the recommended return type.
2093     * @see #getBytes(String)
2094     */
2095    public byte[] getBytes(int columnIndex) throws SQLException {
2096        // sanity check.
2097        checkIndex(columnIndex);
2098        // make sure the cursor is on a valid row
2099        checkCursor();
2100
2101        if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
2102            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2103        }
2104
2105        return (byte[])(getCurrentRow().getColumnObject(columnIndex));
2106    }
2107
2108    /**
2109     * Retrieves the value of the designated column in the current row
2110     * of this <code>CachedRowSetImpl</code> object as a
2111     * <code>java.sql.Date</code> object.
2112     *
2113     * @param columnIndex the first column is <code>1</code>, the second
2114     *        is <code>2</code>, and so on; must be <code>1</code> or larger
2115     *        and equal to or less than the number of columns in the rowset
2116     * @return the column value as a <code>java.sql.Data</code> object; if
2117     *        the value is SQL <code>NULL</code>, the
2118     *        result is <code>null</code>
2119     * @throws SQLException if the given column index is out of bounds,
2120     *            the cursor is not on a valid row, or this method fails
2121     */
2122    public java.sql.Date getDate(int columnIndex) throws SQLException {
2123        Object value;
2124
2125        // sanity check.
2126        checkIndex(columnIndex);
2127        // make sure the cursor is on a valid row
2128        checkCursor();
2129
2130        setLastValueNull(false);
2131        value = getCurrentRow().getColumnObject(columnIndex);
2132
2133        // check for SQL NULL
2134        if (value == null) {
2135            setLastValueNull(true);
2136            return null;
2137        }
2138
2139        /*
2140         * The object coming back from the db could be
2141         * a date, a timestamp, or a char field variety.
2142         * If it's a date type return it, a timestamp
2143         * we turn into a long and then into a date,
2144         * char strings we try to parse. Yuck.
2145         */
2146        switch (RowSetMD.getColumnType(columnIndex)) {
2147            case java.sql.Types.DATE: {
2148                long sec = ((java.sql.Date)value).getTime();
2149                return new java.sql.Date(sec);
2150            }
2151            case java.sql.Types.TIMESTAMP: {
2152                long sec = ((java.sql.Timestamp)value).getTime();
2153                return new java.sql.Date(sec);
2154            }
2155            case java.sql.Types.CHAR:
2156            case java.sql.Types.VARCHAR:
2157            case java.sql.Types.LONGVARCHAR: {
2158                try {
2159                    DateFormat df = DateFormat.getDateInstance();
2160                    return ((java.sql.Date)(df.parse(value.toString())));
2161                } catch (ParseException ex) {
2162                    throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.datefail").toString(),
2163                        new Object[] {value.toString().trim(), columnIndex}));
2164                }
2165            }
2166            default: {
2167                throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.datefail").toString(),
2168                        new Object[] {value.toString().trim(), columnIndex}));
2169            }
2170        }
2171    }
2172
2173    /**
2174     * Retrieves the value of the designated column in the current row
2175     * of this <code>CachedRowSetImpl</code> object as a
2176     * <code>java.sql.Time</code> object.
2177     *
2178     * @param columnIndex the first column is <code>1</code>, the second
2179     *        is <code>2</code>, and so on; must be <code>1</code> or larger
2180     *        and equal to or less than the number of columns in the rowset
2181     * @return the column value; if the value is SQL <code>NULL</code>, the
2182     *         result is <code>null</code>
2183     * @throws SQLException if the given column index is out of bounds,
2184     *         the cursor is not on a valid row, or this method fails
2185     */
2186    public java.sql.Time getTime(int columnIndex) throws SQLException {
2187        Object value;
2188
2189        // sanity check.
2190        checkIndex(columnIndex);
2191        // make sure the cursor is on a valid row
2192        checkCursor();
2193
2194        setLastValueNull(false);
2195        value = getCurrentRow().getColumnObject(columnIndex);
2196
2197        // check for SQL NULL
2198        if (value == null) {
2199            setLastValueNull(true);
2200            return null;
2201        }
2202
2203        /*
2204         * The object coming back from the db could be
2205         * a date, a timestamp, or a char field variety.
2206         * If it's a date type return it, a timestamp
2207         * we turn into a long and then into a date,
2208         * char strings we try to parse. Yuck.
2209         */
2210        switch (RowSetMD.getColumnType(columnIndex)) {
2211            case java.sql.Types.TIME: {
2212                return (java.sql.Time)value;
2213            }
2214            case java.sql.Types.TIMESTAMP: {
2215                long sec = ((java.sql.Timestamp)value).getTime();
2216                return new java.sql.Time(sec);
2217            }
2218            case java.sql.Types.CHAR:
2219            case java.sql.Types.VARCHAR:
2220            case java.sql.Types.LONGVARCHAR: {
2221                try {
2222                    DateFormat tf = DateFormat.getTimeInstance();
2223                    return ((java.sql.Time)(tf.parse(value.toString())));
2224                } catch (ParseException ex) {
2225                    throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2226                        new Object[] {value.toString().trim(), columnIndex}));
2227                }
2228            }
2229            default: {
2230                throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2231                        new Object[] {value.toString().trim(), columnIndex}));
2232            }
2233        }
2234    }
2235
2236    /**
2237     * Retrieves the value of the designated column in the current row
2238     * of this <code>CachedRowSetImpl</code> object as a
2239     * <code>java.sql.Timestamp</code> object.
2240     *
2241     * @param columnIndex the first column is <code>1</code>, the second
2242     *        is <code>2</code>, and so on; must be <code>1</code> or larger
2243     *        and equal to or less than the number of columns in the rowset
2244     * @return the column value; if the value is SQL <code>NULL</code>, the
2245     *         result is <code>null</code>
2246     * @throws SQLException if the given column index is out of bounds,
2247     *            the cursor is not on a valid row, or this method fails
2248     */
2249    public java.sql.Timestamp getTimestamp(int columnIndex) throws SQLException {
2250        Object value;
2251
2252        // sanity check.
2253        checkIndex(columnIndex);
2254        // make sure the cursor is on a valid row
2255        checkCursor();
2256
2257        setLastValueNull(false);
2258        value = getCurrentRow().getColumnObject(columnIndex);
2259
2260        // check for SQL NULL
2261        if (value == null) {
2262            setLastValueNull(true);
2263            return null;
2264        }
2265
2266        /*
2267         * The object coming back from the db could be
2268         * a date, a timestamp, or a char field variety.
2269         * If it's a date type return it; a timestamp
2270         * we turn into a long and then into a date;
2271         * char strings we try to parse. Yuck.
2272         */
2273        switch (RowSetMD.getColumnType(columnIndex)) {
2274            case java.sql.Types.TIMESTAMP: {
2275                return (java.sql.Timestamp)value;
2276            }
2277            case java.sql.Types.TIME: {
2278                long sec = ((java.sql.Time)value).getTime();
2279                return new java.sql.Timestamp(sec);
2280            }
2281            case java.sql.Types.DATE: {
2282                long sec = ((java.sql.Date)value).getTime();
2283                return new java.sql.Timestamp(sec);
2284            }
2285            case java.sql.Types.CHAR:
2286            case java.sql.Types.VARCHAR:
2287            case java.sql.Types.LONGVARCHAR: {
2288                try {
2289                    DateFormat tf = DateFormat.getTimeInstance();
2290                    return ((java.sql.Timestamp)(tf.parse(value.toString())));
2291                } catch (ParseException ex) {
2292                    throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2293                        new Object[] {value.toString().trim(), columnIndex}));
2294                }
2295            }
2296            default: {
2297                throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2298                        new Object[] {value.toString().trim(), columnIndex}));
2299            }
2300        }
2301    }
2302
2303    /**
2304     * Retrieves the value of the designated column in the current row of this
2305     * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2306     * object.
2307     *
2308     * A column value can be retrieved as a stream of ASCII characters
2309     * and then read in chunks from the stream.  This method is particularly
2310     * suitable for retrieving large <code>LONGVARCHAR</code> values.  The JDBC
2311     * driver will do any necessary conversion from the database format into ASCII.
2312     *
2313     * <P><B>Note:</B> All the data in the returned stream must be
2314     * read prior to getting the value of any other column. The next
2315     * call to a get method implicitly closes the stream. . Also, a
2316     * stream may return <code>0</code> for <code>CachedRowSetImpl.available()</code>
2317     * whether there is data available or not.
2318     *
2319     * @param columnIndex the first column is <code>1</code>, the second
2320     *        is <code>2</code>, and so on; must be <code>1</code> or larger
2321     *        and equal to or less than the number of columns in this rowset
2322     * @return a Java input stream that delivers the database column value
2323     *         as a stream of one-byte ASCII characters.  If the value is SQL
2324     *         <code>NULL</code>, the result is <code>null</code>.
2325     * @throws SQLException if (1) the given column index is out of bounds,
2326     * (2) the cursor is not on one of this rowset's rows or its
2327     * insert row, or (3) the designated column does not store an
2328     * SQL <code>CHAR, VARCHAR</code>, <code><b>LONGVARCHAR</b></code>
2329     * <code>BINARY, VARBINARY</code> or <code>LONGVARBINARY</code> value. The
2330     * bold SQL type designates the recommended return types that this method is
2331     * used to retrieve.
2332     * @see #getAsciiStream(String)
2333     */
2334    public java.io.InputStream getAsciiStream(int columnIndex) throws SQLException {
2335        Object value;
2336
2337        // always free an old stream
2338        asciiStream = null;
2339
2340        // sanity check
2341        checkIndex(columnIndex);
2342        //make sure the cursor is on a vlid row
2343        checkCursor();
2344
2345        value =  getCurrentRow().getColumnObject(columnIndex);
2346        if (value == null) {
2347            lastValueNull = true;
2348            return null;
2349        }
2350
2351        try {
2352            if (isString(RowSetMD.getColumnType(columnIndex))) {
2353                asciiStream = new ByteArrayInputStream(((String)value).getBytes("ASCII"));
2354            } else {
2355                throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2356            }
2357        } catch (java.io.UnsupportedEncodingException ex) {
2358            throw new SQLException(ex.getMessage());
2359        }
2360
2361        return asciiStream;
2362    }
2363
2364    /**
2365     * A column value can be retrieved as a stream of Unicode characters
2366     * and then read in chunks from the stream.  This method is particularly
2367     * suitable for retrieving large LONGVARCHAR values.  The JDBC driver will
2368     * do any necessary conversion from the database format into Unicode.
2369     *
2370     * <P><B>Note:</B> All the data in the returned stream must be
2371     * read prior to getting the value of any other column. The next
2372     * call to a get method implicitly closes the stream. . Also, a
2373     * stream may return 0 for available() whether there is data
2374     * available or not.
2375     *
2376     * @param columnIndex the first column is <code>1</code>, the second
2377     *        is <code>2</code>, and so on; must be <code>1</code> or larger
2378     *        and equal to or less than the number of columns in this rowset
2379     * @return a Java input stream that delivers the database column value
2380     * as a stream of two byte Unicode characters.  If the value is SQL NULL
2381     * then the result is null.
2382     * @throws SQLException if an error occurs
2383     * @deprecated
2384     */
2385    @Deprecated
2386    public java.io.InputStream getUnicodeStream(int columnIndex) throws SQLException {
2387        // always free an old stream
2388        unicodeStream = null;
2389
2390        // sanity check.
2391        checkIndex(columnIndex);
2392        // make sure the cursor is on a valid row
2393        checkCursor();
2394
2395        if (isBinary(RowSetMD.getColumnType(columnIndex)) == false &&
2396        isString(RowSetMD.getColumnType(columnIndex)) == false) {
2397            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2398        }
2399
2400        Object value = getCurrentRow().getColumnObject(columnIndex);
2401        if (value == null) {
2402            lastValueNull = true;
2403            return null;
2404        }
2405
2406        unicodeStream = new StringBufferInputStream(value.toString());
2407
2408        return unicodeStream;
2409    }
2410
2411    /**
2412     * Retrieves the value of the designated column in the current row of this
2413     * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2414     * object.
2415     * <P>
2416     * A column value can be retrieved as a stream of uninterpreted bytes
2417     * and then read in chunks from the stream.  This method is particularly
2418     * suitable for retrieving large <code>LONGVARBINARY</code> values.
2419     *
2420     * <P><B>Note:</B> All the data in the returned stream must be
2421     * read prior to getting the value of any other column. The next
2422     * call to a get method implicitly closes the stream. Also, a
2423     * stream may return <code>0</code> for
2424     * <code>CachedRowSetImpl.available()</code> whether there is data
2425     * available or not.
2426     *
2427     * @param columnIndex the first column is <code>1</code>, the second
2428     * is <code>2</code>, and so on; must be <code>1</code> or larger
2429     * and equal to or less than the number of columns in the rowset
2430     * @return a Java input stream that delivers the database column value
2431     * as a stream of uninterpreted bytes.  If the value is SQL <code>NULL</code>
2432     * then the result is <code>null</code>.
2433     * @throws SQLException if (1) the given column index is out of bounds,
2434     * (2) the cursor is not on one of this rowset's rows or its
2435     * insert row, or (3) the designated column does not store an
2436     * SQL <code>BINARY, VARBINARY</code> or <code><b>LONGVARBINARY</b></code>
2437     * The bold type indicates the SQL type that this method is recommened
2438     * to retrieve.
2439     * @see #getBinaryStream(String)
2440     */
2441    public java.io.InputStream getBinaryStream(int columnIndex) throws SQLException {
2442
2443        // always free an old stream
2444        binaryStream = null;
2445
2446        // sanity check.
2447        checkIndex(columnIndex);
2448        // make sure the cursor is on a valid row
2449        checkCursor();
2450
2451        if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
2452            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2453        }
2454
2455        Object value = getCurrentRow().getColumnObject(columnIndex);
2456        if (value == null) {
2457            lastValueNull = true;
2458            return null;
2459        }
2460
2461        binaryStream = new ByteArrayInputStream((byte[])value);
2462
2463        return binaryStream;
2464
2465    }
2466
2467
2468    // Methods for accessing results by column name
2469
2470    /**
2471     * Retrieves the value stored in the designated column
2472     * of the current row as a <code>String</code> object.
2473     *
2474     * @param columnName a <code>String</code> object giving the SQL name of
2475     *        a column in this <code>CachedRowSetImpl</code> object
2476     * @return the column value; if the value is SQL <code>NULL</code>,
2477     *         the result is <code>null</code>
2478     * @throws SQLException if (1) the given column name is not the name of
2479     * a column in this rowset, (2) the cursor is not on one of
2480     * this rowset's rows or its insert row, or (3) the designated
2481     * column does not store an SQL {@code TINYINT, SMALLINT, INTEGER
2482     * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, }
2483     * <b>{@code CHAR, VARCHAR}</b> or
2484     * <b>{@code LONGVARCHAR}</b> value.
2485     * The bold SQL type designates the recommended return type.
2486     */
2487    public String getString(String columnName) throws SQLException {
2488        return getString(getColIdxByName(columnName));
2489    }
2490
2491    /**
2492     * Retrieves the value stored in the designated column
2493     * of the current row as a <code>boolean</code> value.
2494     *
2495     * @param columnName a <code>String</code> object giving the SQL name of
2496     *        a column in this <code>CachedRowSetImpl</code> object
2497     * @return the column value as a <code>boolean</code> in the Java programming
2498     *        language; if the value is SQL <code>NULL</code>,
2499     *        the result is <code>false</code>
2500     * @throws SQLException if (1) the given column name is not the name of
2501     *            a column in this rowset, (2) the cursor is not on one of
2502     *            this rowset's rows or its insert row, or (3) the designated
2503     *            column does not store an SQL <code>BOOLEAN</code> value
2504     * @see #getBoolean(int)
2505     */
2506    public boolean getBoolean(String columnName) throws SQLException {
2507        return getBoolean(getColIdxByName(columnName));
2508    }
2509
2510    /**
2511     * Retrieves the value stored in the designated column
2512     * of the current row as a <code>byte</code> value.
2513     *
2514     * @param columnName a <code>String</code> object giving the SQL name of
2515     *        a column in this <code>CachedRowSetImpl</code> object
2516     * @return the column value as a <code>byte</code> in the Java programming
2517     * language; if the value is SQL <code>NULL</code>, the result is <code>0</code>
2518     * @throws SQLException if (1) the given column name is not the name of
2519     * a column in this rowset, (2) the cursor is not on one of
2520     * this rowset's rows or its insert row, or (3) the designated
2521     * column does not store an SQL <code><B>TINYINT</B>, SMALLINT, INTEGER,
2522     * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2523     * VARCHAR</code> or <code>LONGVARCHAR</code> value. The
2524     * bold type designates the recommended return type
2525     */
2526    public byte getByte(String columnName) throws SQLException {
2527        return getByte(getColIdxByName(columnName));
2528    }
2529
2530    /**
2531     * Retrieves the value stored in the designated column
2532     * of the current row as a <code>short</code> value.
2533     *
2534     * @param columnName a <code>String</code> object giving the SQL name of
2535     *        a column in this <code>CachedRowSetImpl</code> object
2536     * @return the column value; if the value is SQL <code>NULL</code>,
2537     *         the result is <code>0</code>
2538     * @throws SQLException if (1) the given column name is not the name of
2539     * a column in this rowset, (2) the cursor is not on one of
2540     * this rowset's rows or its insert row, or (3) the designated
2541     * column does not store an SQL <code>TINYINT, <b>SMALLINT</b>, INTEGER
2542     * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2543     * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2544     * designates the recommended return type.
2545     * @see #getShort(int)
2546     */
2547    public short getShort(String columnName) throws SQLException {
2548        return getShort(getColIdxByName(columnName));
2549    }
2550
2551    /**
2552     * Retrieves the value stored in the designated column
2553     * of the current row as an <code>int</code> value.
2554     *
2555     * @param columnName a <code>String</code> object giving the SQL name of
2556     *        a column in this <code>CachedRowSetImpl</code> object
2557     * @return the column value; if the value is SQL <code>NULL</code>,
2558     *         the result is <code>0</code>
2559     * @throws SQLException if (1) the given column name is not the name
2560     * of a column in this rowset,
2561     * (2) the cursor is not on one of this rowset's rows or its
2562     * insert row, or (3) the designated column does not store an
2563     * SQL <code>TINYINT, SMALLINT, <b>INTEGER</b>, BIGINT, REAL
2564     * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
2565     * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
2566     * recommended return type.
2567     */
2568    public int getInt(String columnName) throws SQLException {
2569        return getInt(getColIdxByName(columnName));
2570    }
2571
2572    /**
2573     * Retrieves the value stored in the designated column
2574     * of the current row as a <code>long</code> value.
2575     *
2576     * @param columnName a <code>String</code> object giving the SQL name of
2577     *        a column in this <code>CachedRowSetImpl</code> object
2578     * @return the column value; if the value is SQL <code>NULL</code>,
2579     *         the result is <code>0</code>
2580     * @throws SQLException if (1) the given column name is not the name of
2581     * a column in this rowset, (2) the cursor is not on one of
2582     * this rowset's rows or its insert row, or (3) the designated
2583     * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2584     * <b>BIGINT</b>, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2585     * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2586     * designates the recommended return type.
2587     * @see #getLong(int)
2588     */
2589    public long getLong(String columnName) throws SQLException {
2590        return getLong(getColIdxByName(columnName));
2591    }
2592
2593    /**
2594     * Retrieves the value stored in the designated column
2595     * of the current row as a <code>float</code> value.
2596     *
2597     * @param columnName a <code>String</code> object giving the SQL name of
2598     *        a column in this <code>CachedRowSetImpl</code> object
2599     * @return the column value; if the value is SQL <code>NULL</code>,
2600     *         the result is <code>0</code>
2601     * @throws SQLException if (1) the given column name is not the name of
2602     * a column in this rowset, (2) the cursor is not on one of
2603     * this rowset's rows or its insert row, or (3) the designated
2604     * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2605     * BIGINT, <b>REAL</b>, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2606     * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2607     * designates the recommended return type.
2608     * @see #getFloat(String)
2609     */
2610    public float getFloat(String columnName) throws SQLException {
2611        return getFloat(getColIdxByName(columnName));
2612    }
2613
2614    /**
2615     * Retrieves the value stored in the designated column
2616     * of the current row of this <code>CachedRowSetImpl</code> object
2617     * as a <code>double</code> value.
2618     *
2619     * @param columnName a <code>String</code> object giving the SQL name of
2620     *        a column in this <code>CachedRowSetImpl</code> object
2621     * @return the column value; if the value is SQL <code>NULL</code>,
2622     *         the result is <code>0</code>
2623     * @throws SQLException if (1) the given column name is not the name of
2624     * a column in this rowset, (2) the cursor is not on one of
2625     * this rowset's rows or its insert row, or (3) the designated
2626     * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2627     * BIGINT, REAL, <b>FLOAT</b>, <b>DOUBLE</b>, DECIMAL, NUMERIC, BIT, CHAR,
2628     * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2629     * designates the recommended return types.
2630     * @see #getDouble(int)
2631     */
2632    public double getDouble(String columnName) throws SQLException {
2633        return getDouble(getColIdxByName(columnName));
2634    }
2635
2636    /**
2637     * Retrieves the value stored in the designated column
2638     * of the current row as a <code>java.math.BigDecimal</code> object.
2639     *
2640     * @param columnName a <code>String</code> object giving the SQL name of
2641     *        a column in this <code>CachedRowSetImpl</code> object
2642     * @param scale the number of digits to the right of the decimal point
2643     * @return a java.math.BugDecimal object with <code><i>scale</i></code>
2644     * number of digits to the right of the decimal point.
2645     * @throws SQLException if (1) the given column name is not the name of
2646     * a column in this rowset, (2) the cursor is not on one of
2647     * this rowset's rows or its insert row, or (3) the designated
2648     * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2649     * BIGINT, REAL, FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT CHAR,
2650     * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2651     * designates the recommended return type that this method is used to
2652     * retrieve.
2653     * @deprecated Use the <code>getBigDecimal(String columnName)</code>
2654     *             method instead
2655     */
2656    @Deprecated
2657    public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {
2658        return getBigDecimal(getColIdxByName(columnName), scale);
2659    }
2660
2661    /**
2662     * Retrieves the value stored in the designated column
2663     * of the current row as a <code>byte</code> array.
2664     * The bytes represent the raw values returned by the driver.
2665     *
2666     * @param columnName a <code>String</code> object giving the SQL name of
2667     *        a column in this <code>CachedRowSetImpl</code> object
2668     * @return the column value as a <code>byte</code> array in the Java programming
2669     * language; if the value is SQL <code>NULL</code>, the result is <code>null</code>
2670     * @throws SQLException if (1) the given column name is not the name of
2671     * a column in this rowset, (2) the cursor is not on one of
2672     * this rowset's rows or its insert row, or (3) the designated
2673     * column does not store an SQL <code><b>BINARY</b>, <b>VARBINARY</b>
2674     * </code> or <code>LONGVARBINARY</code> values
2675     * The bold SQL type designates the recommended return type.
2676     * @see #getBytes(int)
2677     */
2678    public byte[] getBytes(String columnName) throws SQLException {
2679        return getBytes(getColIdxByName(columnName));
2680    }
2681
2682    /**
2683     * Retrieves the value stored in the designated column
2684     * of the current row as a <code>java.sql.Date</code> object.
2685     *
2686     * @param columnName a <code>String</code> object giving the SQL name of
2687     *        a column in this <code>CachedRowSetImpl</code> object
2688     * @return the column value; if the value is SQL <code>NULL</code>,
2689     *         the result is <code>null</code>
2690     * @throws SQLException if (1) the given column name is not the name of
2691     *            a column in this rowset, (2) the cursor is not on one of
2692     *            this rowset's rows or its insert row, or (3) the designated
2693     *            column does not store an SQL <code>DATE</code> or
2694     *            <code>TIMESTAMP</code> value
2695     */
2696    public java.sql.Date getDate(String columnName) throws SQLException {
2697        return getDate(getColIdxByName(columnName));
2698    }
2699
2700    /**
2701     * Retrieves the value stored in the designated column
2702     * of the current row as a <code>java.sql.Time</code> object.
2703     *
2704     * @param columnName a <code>String</code> object giving the SQL name of
2705     *        a column in this <code>CachedRowSetImpl</code> object
2706     * @return the column value; if the value is SQL <code>NULL</code>,
2707     *         the result is <code>null</code>
2708     * @throws SQLException if the given column name does not match one of
2709     *            this rowset's column names or the cursor is not on one of
2710     *            this rowset's rows or its insert row
2711     */
2712    public java.sql.Time getTime(String columnName) throws SQLException {
2713        return getTime(getColIdxByName(columnName));
2714    }
2715
2716    /**
2717     * Retrieves the value stored in the designated column
2718     * of the current row as a <code>java.sql.Timestamp</code> object.
2719     *
2720     * @param columnName a <code>String</code> object giving the SQL name of
2721     *        a column in this <code>CachedRowSetImpl</code> object
2722     * @return the column value; if the value is SQL <code>NULL</code>,
2723     *         the result is <code>null</code>
2724     * @throws SQLException if the given column name does not match one of
2725     *            this rowset's column names or the cursor is not on one of
2726     *            this rowset's rows or its insert row
2727     */
2728    public java.sql.Timestamp getTimestamp(String columnName) throws SQLException {
2729        return getTimestamp(getColIdxByName(columnName));
2730    }
2731
2732    /**
2733     * Retrieves the value of the designated column in the current row of this
2734     * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2735     * object.
2736     *
2737     * A column value can be retrieved as a stream of ASCII characters
2738     * and then read in chunks from the stream. This method is particularly
2739     * suitable for retrieving large <code>LONGVARCHAR</code> values. The
2740     * <code>SyncProvider</code> will rely on the JDBC driver to do any necessary
2741     * conversion from the database format into ASCII format.
2742     *
2743     * <P><B>Note:</B> All the data in the returned stream must
2744     * be read prior to getting the value of any other column. The
2745     * next call to a <code>getXXX</code> method implicitly closes the stream.
2746     *
2747     * @param columnName a <code>String</code> object giving the SQL name of
2748     *        a column in this <code>CachedRowSetImpl</code> object
2749     * @return a Java input stream that delivers the database column value
2750     *         as a stream of one-byte ASCII characters.  If the value is SQL
2751     *         <code>NULL</code>, the result is <code>null</code>.
2752     * @throws SQLException if (1) the given column name is not the name of
2753     * a column in this rowset
2754     * (2) the cursor is not on one of this rowset's rows or its
2755     * insert row, or (3) the designated column does not store an
2756     * SQL <code>CHAR, VARCHAR</code>, <code><b>LONGVARCHAR</b></code>
2757     * <code>BINARY, VARBINARY</code> or <code>LONGVARBINARY</code> value. The
2758     * bold SQL type designates the recommended return types that this method is
2759     * used to retrieve.
2760     * @see #getAsciiStream(int)
2761     */
2762    public java.io.InputStream getAsciiStream(String columnName) throws SQLException {
2763        return getAsciiStream(getColIdxByName(columnName));
2764
2765    }
2766
2767    /**
2768     * A column value can be retrieved as a stream of Unicode characters
2769     * and then read in chunks from the stream.  This method is particularly
2770     * suitable for retrieving large <code>LONGVARCHAR</code> values.
2771     * The JDBC driver will do any necessary conversion from the database
2772     * format into Unicode.
2773     *
2774     * <P><B>Note:</B> All the data in the returned stream must
2775     * be read prior to getting the value of any other column. The
2776     * next call to a <code>getXXX</code> method implicitly closes the stream.
2777     *
2778     * @param columnName a <code>String</code> object giving the SQL name of
2779     *        a column in this <code>CachedRowSetImpl</code> object
2780     * @return a Java input stream that delivers the database column value
2781     *         as a stream of two-byte Unicode characters.  If the value is
2782     *         SQL <code>NULL</code>, the result is <code>null</code>.
2783     * @throws SQLException if the given column name does not match one of
2784     *            this rowset's column names or the cursor is not on one of
2785     *            this rowset's rows or its insert row
2786     * @deprecated use the method <code>getCharacterStream</code> instead
2787     */
2788    @Deprecated
2789    public java.io.InputStream getUnicodeStream(String columnName) throws SQLException {
2790        return getUnicodeStream(getColIdxByName(columnName));
2791    }
2792
2793    /**
2794     * Retrieves the value of the designated column in the current row of this
2795     * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2796     * object.
2797     * <P>
2798     * A column value can be retrieved as a stream of uninterpreted bytes
2799     * and then read in chunks from the stream.  This method is particularly
2800     * suitable for retrieving large <code>LONGVARBINARY</code> values.
2801     *
2802     * <P><B>Note:</B> All the data in the returned stream must be
2803     * read prior to getting the value of any other column. The next
2804     * call to a get method implicitly closes the stream. Also, a
2805     * stream may return <code>0</code> for <code>CachedRowSetImpl.available()</code>
2806     * whether there is data available or not.
2807     *
2808     * @param columnName a <code>String</code> object giving the SQL name of
2809     *        a column in this <code>CachedRowSetImpl</code> object
2810     * @return a Java input stream that delivers the database column value
2811     *         as a stream of uninterpreted bytes.  If the value is SQL
2812     *         <code>NULL</code>, the result is <code>null</code>.
2813     * @throws SQLException if (1) the given column name is unknown,
2814     * (2) the cursor is not on one of this rowset's rows or its
2815     * insert row, or (3) the designated column does not store an
2816     * SQL <code>BINARY, VARBINARY</code> or <code><b>LONGVARBINARY</b></code>
2817     * The bold type indicates the SQL type that this method is recommened
2818     * to retrieve.
2819     * @see #getBinaryStream(int)
2820     *
2821     */
2822    public java.io.InputStream getBinaryStream(String columnName) throws SQLException {
2823        return getBinaryStream(getColIdxByName(columnName));
2824    }
2825
2826
2827    // Advanced features:
2828
2829    /**
2830     * The first warning reported by calls on this <code>CachedRowSetImpl</code>
2831     * object is returned. Subsequent <code>CachedRowSetImpl</code> warnings will
2832     * be chained to this <code>SQLWarning</code>.
2833     *
2834     * <P>The warning chain is automatically cleared each time a new
2835     * row is read.
2836     *
2837     * <P><B>Note:</B> This warning chain only covers warnings caused
2838     * by <code>ResultSet</code> methods.  Any warning caused by statement
2839     * methods (such as reading OUT parameters) will be chained on the
2840     * <code>Statement</code> object.
2841     *
2842     * @return the first SQLWarning or null
2843     */
2844    public SQLWarning getWarnings() {
2845        return sqlwarn;
2846    }
2847
2848    /**
2849     * Clears all the warnings reporeted for the <code>CachedRowSetImpl</code>
2850     * object. After a call to this method, the <code>getWarnings</code> method
2851     * returns <code>null</code> until a new warning is reported for this
2852     * <code>CachedRowSetImpl</code> object.
2853     */
2854    public void clearWarnings() {
2855        sqlwarn = null;
2856    }
2857
2858    /**
2859     * Retrieves the name of the SQL cursor used by this
2860     * <code>CachedRowSetImpl</code> object.
2861     *
2862     * <P>In SQL, a result table is retrieved through a cursor that is
2863     * named. The current row of a <code>ResultSet</code> can be updated or deleted
2864     * using a positioned update/delete statement that references the
2865     * cursor name. To ensure that the cursor has the proper isolation
2866     * level to support an update operation, the cursor's <code>SELECT</code>
2867     * statement should be of the form <code>select for update</code>.
2868     * If the <code>for update</code> clause
2869     * is omitted, positioned updates may fail.
2870     *
2871     * <P>JDBC supports this SQL feature by providing the name of the
2872     * SQL cursor used by a <code>ResultSet</code> object. The current row
2873     * of a result set is also the current row of this SQL cursor.
2874     *
2875     * <P><B>Note:</B> If positioned updates are not supported, an
2876     * <code>SQLException</code> is thrown.
2877     *
2878     * @return the SQL cursor name for this <code>CachedRowSetImpl</code> object's
2879     *         cursor
2880     * @throws SQLException if an error occurs
2881     */
2882    public String getCursorName() throws SQLException {
2883        throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.posupdate").toString());
2884    }
2885
2886    /**
2887     * Retrieves a <code>ResultSetMetaData</code> object instance that
2888     * contains information about the <code>CachedRowSet</code> object.
2889     * However, applications should cast the returned object to a
2890     * <code>RowSetMetaData</code> interface implementation. In the
2891     * reference implementation, this cast can be done on the
2892     * <code>RowSetMetaDataImpl</code> class.
2893     * <P>
2894     * For example:
2895     * <pre>
2896     * CachedRowSet crs = new CachedRowSetImpl();
2897     * RowSetMetaDataImpl metaData =
2898     *     (RowSetMetaDataImpl)crs.getMetaData();
2899     * // Set the number of columns in the RowSet object for
2900     * // which this RowSetMetaDataImpl object was created to the
2901     * // given number.
2902     * metaData.setColumnCount(3);
2903     * crs.setMetaData(metaData);
2904     * </pre>
2905     *
2906     * @return the <code>ResultSetMetaData</code> object that describes this
2907     *         <code>CachedRowSetImpl</code> object's columns
2908     * @throws SQLException if an error occurs in generating the RowSet
2909     * meta data; or if the <code>CachedRowSetImpl</code> is empty.
2910     * @see javax.sql.RowSetMetaData
2911     */
2912    public ResultSetMetaData getMetaData() throws SQLException {
2913        return (ResultSetMetaData)RowSetMD;
2914    }
2915
2916
2917    /**
2918     * Retrieves the value of the designated column in the current row
2919     * of this <code>CachedRowSetImpl</code> object as an
2920     * <code>Object</code> value.
2921     * <P>
2922     * The type of the <code>Object</code> will be the default
2923     * Java object type corresponding to the column's SQL type,
2924     * following the mapping for built-in types specified in the JDBC 3.0
2925     * specification.
2926     * <P>
2927     * This method may also be used to read datatabase-specific
2928     * abstract data types.
2929     * <P>
2930     * This implementation of the method <code>getObject</code> extends its
2931     * behavior so that it gets the attributes of an SQL structured type
2932     * as an array of <code>Object</code> values.  This method also custom
2933     * maps SQL user-defined types to classes in the Java programming language.
2934     * When the specified column contains
2935     * a structured or distinct value, the behavior of this method is as
2936     * if it were a call to the method <code>getObject(columnIndex,
2937     * this.getStatement().getConnection().getTypeMap())</code>.
2938     *
2939     * @param columnIndex the first column is <code>1</code>, the second
2940     *        is <code>2</code>, and so on; must be <code>1</code> or larger
2941     *        and equal to or less than the number of columns in the rowset
2942     * @return a <code>java.lang.Object</code> holding the column value;
2943     *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
2944     * @throws SQLException if the given column index is out of bounds,
2945     *            the cursor is not on a valid row, or there is a problem getting
2946     *            the <code>Class</code> object for a custom mapping
2947     * @see #getObject(String)
2948     */
2949    public Object getObject(int columnIndex) throws SQLException {
2950        Object value;
2951        Map<String, Class<?>> map;
2952
2953        // sanity check.
2954        checkIndex(columnIndex);
2955        // make sure the cursor is on a valid row
2956        checkCursor();
2957
2958        setLastValueNull(false);
2959        value = getCurrentRow().getColumnObject(columnIndex);
2960
2961        // check for SQL NULL
2962        if (value == null) {
2963            setLastValueNull(true);
2964            return null;
2965        }
2966        if (value instanceof Struct) {
2967            Struct s = (Struct)value;
2968            map = getTypeMap();
2969            // look up the class in the map
2970            Class<?> c = map.get(s.getSQLTypeName());
2971            if (c != null) {
2972                // create new instance of the class
2973                SQLData obj = null;
2974                try {
2975                    ReflectUtil.checkPackageAccess(c);
2976                    @SuppressWarnings("deprecation")
2977                    Object tmp = c.newInstance();
2978                    obj = (SQLData) tmp;
2979                } catch(Exception ex) {
2980                    throw new SQLException("Unable to Instantiate: ", ex);
2981                }
2982                // get the attributes from the struct
2983                Object attribs[] = s.getAttributes(map);
2984                // create the SQLInput "stream"
2985                SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
2986                // read the values...
2987                obj.readSQL(sqlInput, s.getSQLTypeName());
2988                return (Object)obj;
2989            }
2990        }
2991        return value;
2992    }
2993
2994    /**
2995     * Retrieves the value of the designated column in the current row
2996     * of this <code>CachedRowSetImpl</code> object as an
2997     * <code>Object</code> value.
2998     * <P>
2999     * The type of the <code>Object</code> will be the default
3000     * Java object type corresponding to the column's SQL type,
3001     * following the mapping for built-in types specified in the JDBC 3.0
3002     * specification.
3003     * <P>
3004     * This method may also be used to read datatabase-specific
3005     * abstract data types.
3006     * <P>
3007     * This implementation of the method <code>getObject</code> extends its
3008     * behavior so that it gets the attributes of an SQL structured type
3009     * as an array of <code>Object</code> values.  This method also custom
3010     * maps SQL user-defined types to classes
3011     * in the Java programming language. When the specified column contains
3012     * a structured or distinct value, the behavior of this method is as
3013     * if it were a call to the method <code>getObject(columnIndex,
3014     * this.getStatement().getConnection().getTypeMap())</code>.
3015     *
3016     * @param columnName a <code>String</code> object that must match the
3017     *        SQL name of a column in this rowset, ignoring case
3018     * @return a <code>java.lang.Object</code> holding the column value;
3019     *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3020     * @throws SQLException if (1) the given column name does not match one of
3021     *            this rowset's column names, (2) the cursor is not
3022     *            on a valid row, or (3) there is a problem getting
3023     *            the <code>Class</code> object for a custom mapping
3024     * @see #getObject(int)
3025     */
3026    public Object getObject(String columnName) throws SQLException {
3027        return getObject(getColIdxByName(columnName));
3028    }
3029
3030    //----------------------------------------------------------------
3031
3032    /**
3033     * Maps the given column name for one of this <code>CachedRowSetImpl</code>
3034     * object's columns to its column number.
3035     *
3036     * @param columnName a <code>String</code> object that must match the
3037     *        SQL name of a column in this rowset, ignoring case
3038     * @return the column index of the given column name
3039     * @throws SQLException if the given column name does not match one
3040     *            of this rowset's column names
3041     */
3042    public int findColumn(String columnName) throws SQLException {
3043        return getColIdxByName(columnName);
3044    }
3045
3046
3047    //--------------------------JDBC 2.0-----------------------------------
3048
3049    //---------------------------------------------------------------------
3050    // Getter's and Setter's
3051    //---------------------------------------------------------------------
3052
3053    /**
3054     * Retrieves the value stored in the designated column
3055     * of the current row as a <code>java.io.Reader</code> object.
3056     *
3057     * <P><B>Note:</B> All the data in the returned stream must
3058     * be read prior to getting the value of any other column. The
3059     * next call to a <code>getXXX</code> method implicitly closes the stream.
3060     *
3061     * @param columnIndex the first column is <code>1</code>, the second
3062     *        is <code>2</code>, and so on; must be <code>1</code> or larger
3063     *        and equal to or less than the number of columns in the rowset
3064     * @return a Java character stream that delivers the database column value
3065     * as a stream of two-byte unicode characters in a
3066     * <code>java.io.Reader</code> object.  If the value is
3067     * SQL <code>NULL</code>, the result is <code>null</code>.
3068     * @throws SQLException if (1) the given column index is out of bounds,
3069     * (2) the cursor is not on one of this rowset's rows or its
3070     * insert row, or (3) the designated column does not store an
3071     * SQL <code>CHAR, VARCHAR, <b>LONGVARCHAR</b>, BINARY, VARBINARY</code> or
3072     * <code>LONGVARBINARY</code> value.
3073     * The bold SQL type designates the recommended return type.
3074     * @see #getCharacterStream(String)
3075     */
3076    public java.io.Reader getCharacterStream(int columnIndex) throws SQLException{
3077
3078        // sanity check.
3079        checkIndex(columnIndex);
3080        // make sure the cursor is on a valid row
3081        checkCursor();
3082
3083        if (isBinary(RowSetMD.getColumnType(columnIndex))) {
3084            Object value = getCurrentRow().getColumnObject(columnIndex);
3085            if (value == null) {
3086                lastValueNull = true;
3087                return null;
3088            }
3089            charStream = new InputStreamReader
3090            (new ByteArrayInputStream((byte[])value));
3091        } else if (isString(RowSetMD.getColumnType(columnIndex))) {
3092            Object value = getCurrentRow().getColumnObject(columnIndex);
3093            if (value == null) {
3094                lastValueNull = true;
3095                return null;
3096            }
3097            charStream = new StringReader(value.toString());
3098        } else {
3099            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
3100        }
3101
3102        return charStream;
3103    }
3104
3105    /**
3106     * Retrieves the value stored in the designated column
3107     * of the current row as a <code>java.io.Reader</code> object.
3108     *
3109     * <P><B>Note:</B> All the data in the returned stream must
3110     * be read prior to getting the value of any other column. The
3111     * next call to a <code>getXXX</code> method implicitly closes the stream.
3112     *
3113     * @param columnName a <code>String</code> object giving the SQL name of
3114     *        a column in this <code>CachedRowSetImpl</code> object
3115     * @return a Java input stream that delivers the database column value
3116     *         as a stream of two-byte Unicode characters.  If the value is
3117     *         SQL <code>NULL</code>, the result is <code>null</code>.
3118     * @throws SQLException if (1) the given column name is not the name of
3119     * a column in this rowset, (2) the cursor is not on one of
3120     * this rowset's rows or its insert row, or (3) the designated
3121     * column does not store an SQL <code>CHAR, VARCHAR, <b>LONGVARCHAR</b>,
3122     * BINARY, VARYBINARY</code> or <code>LONGVARBINARY</code> value.
3123     * The bold SQL type designates the recommended return type.
3124     */
3125    public java.io.Reader getCharacterStream(String columnName) throws SQLException {
3126        return getCharacterStream(getColIdxByName(columnName));
3127    }
3128
3129    /**
3130     * Retrieves the value of the designated column in the current row
3131     * of this <code>CachedRowSetImpl</code> object as a
3132     * <code>java.math.BigDecimal</code> object.
3133     *
3134     * @param columnIndex the first column is <code>1</code>, the second
3135     *        is <code>2</code>, and so on; must be <code>1</code> or larger
3136     *        and equal to or less than the number of columns in the rowset
3137     * @return a <code>java.math.BigDecimal</code> value with full precision;
3138     *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3139     * @throws SQLException if (1) the given column index is out of bounds,
3140     * (2) the cursor is not on one of this rowset's rows or its
3141     * insert row, or (3) the designated column does not store an
3142     * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
3143     * FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT, CHAR, VARCHAR</code>
3144     * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
3145     * recommended return types that this method is used to retrieve.
3146     * @see #getBigDecimal(String)
3147     */
3148    public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
3149        Object value;
3150
3151        // sanity check.
3152        checkIndex(columnIndex);
3153        // make sure the cursor is on a valid row
3154        checkCursor();
3155
3156        setLastValueNull(false);
3157        value = getCurrentRow().getColumnObject(columnIndex);
3158
3159        // check for SQL NULL
3160        if (value == null) {
3161            setLastValueNull(true);
3162            return null;
3163        }
3164        try {
3165            return (new BigDecimal(value.toString().trim()));
3166        } catch (NumberFormatException ex) {
3167            throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.doublefail").toString(),
3168                new Object[] {value.toString().trim(), columnIndex}));
3169        }
3170    }
3171
3172    /**
3173     * Retrieves the value of the designated column in the current row
3174     * of this <code>CachedRowSetImpl</code> object as a
3175     * <code>java.math.BigDecimal</code> object.
3176     *
3177     * @param columnName a <code>String</code> object that must match the
3178     *        SQL name of a column in this rowset, ignoring case
3179     * @return a <code>java.math.BigDecimal</code> value with full precision;
3180     *         if the value is SQL <code>NULL</code>, the result is <code>null</code>
3181     * @throws SQLException if (1) the given column name is not the name of
3182     * a column in this rowset, (2) the cursor is not on one of
3183     * this rowset's rows or its insert row, or (3) the designated
3184     * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
3185     * BIGINT, REAL, FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT CHAR,
3186     * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
3187     * designates the recommended return type that this method is used to
3188     * retrieve
3189     * @see #getBigDecimal(int)
3190     */
3191    public BigDecimal getBigDecimal(String columnName) throws SQLException {
3192        return getBigDecimal(getColIdxByName(columnName));
3193    }
3194
3195    //---------------------------------------------------------------------
3196    // Traversal/Positioning
3197    //---------------------------------------------------------------------
3198
3199    /**
3200     * Returns the number of rows in this <code>CachedRowSetImpl</code> object.
3201     *
3202     * @return number of rows in the rowset
3203     */
3204    public int size() {
3205        return numRows;
3206    }
3207
3208    /**
3209     * Indicates whether the cursor is before the first row in this
3210     * <code>CachedRowSetImpl</code> object.
3211     *
3212     * @return <code>true</code> if the cursor is before the first row;
3213     *         <code>false</code> otherwise or if the rowset contains no rows
3214     * @throws SQLException if an error occurs
3215     */
3216    public boolean isBeforeFirst() throws SQLException {
3217        if (cursorPos == 0 && numRows > 0) {
3218            return true;
3219        } else {
3220            return false;
3221        }
3222    }
3223
3224    /**
3225     * Indicates whether the cursor is after the last row in this
3226     * <code>CachedRowSetImpl</code> object.
3227     *
3228     * @return <code>true</code> if the cursor is after the last row;
3229     *         <code>false</code> otherwise or if the rowset contains no rows
3230     * @throws SQLException if an error occurs
3231     */
3232    public boolean isAfterLast() throws SQLException {
3233        if (cursorPos == numRows+1 && numRows > 0) {
3234            return true;
3235        } else {
3236            return false;
3237        }
3238    }
3239
3240    /**
3241     * Indicates whether the cursor is on the first row in this
3242     * <code>CachedRowSetImpl</code> object.
3243     *
3244     * @return <code>true</code> if the cursor is on the first row;
3245     *         <code>false</code> otherwise or if the rowset contains no rows
3246     * @throws SQLException if an error occurs
3247     */
3248    public boolean isFirst() throws SQLException {
3249        // this becomes nasty because of deletes.
3250        int saveCursorPos = cursorPos;
3251        int saveAbsoluteCursorPos = absolutePos;
3252        internalFirst();
3253        if (cursorPos == saveCursorPos) {
3254            return true;
3255        } else {
3256            cursorPos = saveCursorPos;
3257            absolutePos = saveAbsoluteCursorPos;
3258            return false;
3259        }
3260    }
3261
3262    /**
3263     * Indicates whether the cursor is on the last row in this
3264     * <code>CachedRowSetImpl</code> object.
3265     * <P>
3266     * Note: Calling the method <code>isLast</code> may be expensive
3267     * because the JDBC driver might need to fetch ahead one row in order
3268     * to determine whether the current row is the last row in this rowset.
3269     *
3270     * @return <code>true</code> if the cursor is on the last row;
3271     *         <code>false</code> otherwise or if this rowset contains no rows
3272     * @throws SQLException if an error occurs
3273     */
3274    public boolean isLast() throws SQLException {
3275        int saveCursorPos = cursorPos;
3276        int saveAbsoluteCursorPos = absolutePos;
3277        boolean saveShowDeleted = getShowDeleted();
3278        setShowDeleted(true);
3279        internalLast();
3280        if (cursorPos == saveCursorPos) {
3281            setShowDeleted(saveShowDeleted);
3282            return true;
3283        } else {
3284            setShowDeleted(saveShowDeleted);
3285            cursorPos = saveCursorPos;
3286            absolutePos = saveAbsoluteCursorPos;
3287            return false;
3288        }
3289    }
3290
3291    /**
3292     * Moves this <code>CachedRowSetImpl</code> object's cursor to the front of
3293     * the rowset, just before the first row. This method has no effect if
3294     * this rowset contains no rows.
3295     *
3296     * @throws SQLException if an error occurs or the type of this rowset
3297     *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3298     */
3299    public void beforeFirst() throws SQLException {
3300       if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3301            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.beforefirst").toString());
3302        }
3303        cursorPos = 0;
3304        absolutePos = 0;
3305        notifyCursorMoved();
3306    }
3307
3308    /**
3309     * Moves this <code>CachedRowSetImpl</code> object's cursor to the end of
3310     * the rowset, just after the last row. This method has no effect if
3311     * this rowset contains no rows.
3312     *
3313     * @throws SQLException if an error occurs
3314     */
3315    public void afterLast() throws SQLException {
3316        if (numRows > 0) {
3317            cursorPos = numRows + 1;
3318            absolutePos = 0;
3319            notifyCursorMoved();
3320        }
3321    }
3322
3323    /**
3324     * Moves this <code>CachedRowSetImpl</code> object's cursor to the first row
3325     * and returns <code>true</code> if the operation was successful.  This
3326     * method also notifies registered listeners that the cursor has moved.
3327     *
3328     * @return <code>true</code> if the cursor is on a valid row;
3329     *         <code>false</code> otherwise or if there are no rows in this
3330     *         <code>CachedRowSetImpl</code> object
3331     * @throws SQLException if the type of this rowset
3332     *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3333     */
3334    public boolean first() throws SQLException {
3335        if(getType() == ResultSet.TYPE_FORWARD_ONLY) {
3336            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.first").toString());
3337        }
3338
3339        // move and notify
3340        boolean ret = this.internalFirst();
3341        notifyCursorMoved();
3342
3343        return ret;
3344    }
3345
3346    /**
3347     * Moves this <code>CachedRowSetImpl</code> object's cursor to the first
3348     * row and returns <code>true</code> if the operation is successful.
3349     * <P>
3350     * This method is called internally by the methods <code>first</code>,
3351     * <code>isFirst</code>, and <code>absolute</code>.
3352     * It in turn calls the method <code>internalNext</code> in order to
3353     * handle the case where the first row is a deleted row that is not visible.
3354     * <p>
3355     * This is a implementation only method and is not required as a standard
3356     * implementation of the <code>CachedRowSet</code> interface.
3357     *
3358     * @return <code>true</code> if the cursor moved to the first row;
3359     *         <code>false</code> otherwise
3360     * @throws SQLException if an error occurs
3361     */
3362    protected boolean internalFirst() throws SQLException {
3363        boolean ret = false;
3364
3365        if (numRows > 0) {
3366            cursorPos = 1;
3367            if ((getShowDeleted() == false) && (rowDeleted() == true)) {
3368                ret = internalNext();
3369            } else {
3370                ret = true;
3371            }
3372        }
3373
3374        if (ret == true)
3375            absolutePos = 1;
3376        else
3377            absolutePos = 0;
3378
3379        return ret;
3380    }
3381
3382    /**
3383     * Moves this <code>CachedRowSetImpl</code> object's cursor to the last row
3384     * and returns <code>true</code> if the operation was successful.  This
3385     * method also notifies registered listeners that the cursor has moved.
3386     *
3387     * @return <code>true</code> if the cursor is on a valid row;
3388     *         <code>false</code> otherwise or if there are no rows in this
3389     *         <code>CachedRowSetImpl</code> object
3390     * @throws SQLException if the type of this rowset
3391     *            is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3392     */
3393    public boolean last() throws SQLException {
3394        if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3395            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.last").toString());
3396        }
3397
3398        // move and notify
3399        boolean ret = this.internalLast();
3400        notifyCursorMoved();
3401
3402        return ret;
3403    }
3404
3405    /**
3406     * Moves this <code>CachedRowSetImpl</code> object's cursor to the last
3407     * row and returns <code>true</code> if the operation is successful.
3408     * <P>
3409     * This method is called internally by the method <code>last</code>
3410     * when rows have been deleted and the deletions are not visible.
3411     * The method <code>internalLast</code> handles the case where the
3412     * last row is a deleted row that is not visible by in turn calling
3413     * the method <code>internalPrevious</code>.
3414     * <p>
3415     * This is a implementation only method and is not required as a standard
3416     * implementation of the <code>CachedRowSet</code> interface.
3417     *
3418     * @return <code>true</code> if the cursor moved to the last row;
3419     *         <code>false</code> otherwise
3420     * @throws SQLException if an error occurs
3421     */
3422    protected boolean internalLast() throws SQLException {
3423        boolean ret = false;
3424
3425        if (numRows > 0) {
3426            cursorPos = numRows;
3427            if ((getShowDeleted() == false) && (rowDeleted() == true)) {
3428                ret = internalPrevious();
3429            } else {
3430                ret = true;
3431            }
3432        }
3433        if (ret == true)
3434            absolutePos = numRows - numDeleted;
3435        else
3436            absolutePos = 0;
3437        return ret;
3438    }
3439
3440    /**
3441     * Returns the number of the current row in this <code>CachedRowSetImpl</code>
3442     * object. The first row is number 1, the second number 2, and so on.
3443     *
3444     * @return the number of the current row;  <code>0</code> if there is no
3445     *         current row
3446     * @throws SQLException if an error occurs; or if the <code>CacheRowSetImpl</code>
3447     *         is empty
3448     */
3449    public int getRow() throws SQLException {
3450        // are we on a valid row? Valid rows are between first and last
3451        if (numRows > 0 &&
3452        cursorPos > 0 &&
3453        cursorPos < (numRows + 1) &&
3454        (getShowDeleted() == false && rowDeleted() == false)) {
3455            return absolutePos;
3456        } else if (getShowDeleted() == true) {
3457            return cursorPos;
3458        } else {
3459            return 0;
3460        }
3461    }
3462
3463    /**
3464     * Moves this <code>CachedRowSetImpl</code> object's cursor to the row number
3465     * specified.
3466     *
3467     * <p>If the number is positive, the cursor moves to an absolute row with
3468     * respect to the beginning of the rowset.  The first row is row 1, the second
3469     * is row 2, and so on.  For example, the following command, in which
3470     * <code>crs</code> is a <code>CachedRowSetImpl</code> object, moves the cursor
3471     * to the fourth row, starting from the beginning of the rowset.
3472     * <PRE><code>
3473     *
3474     *    crs.absolute(4);
3475     *
3476     * </code> </PRE>
3477     * <P>
3478     * If the number is negative, the cursor moves to an absolute row position
3479     * with respect to the end of the rowset.  For example, calling
3480     * <code>absolute(-1)</code> positions the cursor on the last row,
3481     * <code>absolute(-2)</code> moves it on the next-to-last row, and so on.
3482     * If the <code>CachedRowSetImpl</code> object <code>crs</code> has five rows,
3483     * the following command moves the cursor to the fourth-to-last row, which
3484     * in the case of a  rowset with five rows, is also the second row, counting
3485     * from the beginning.
3486     * <PRE><code>
3487     *
3488     *    crs.absolute(-4);
3489     *
3490     * </code> </PRE>
3491     *
3492     * If the number specified is larger than the number of rows, the cursor
3493     * will move to the position after the last row. If the number specified
3494     * would move the cursor one or more rows before the first row, the cursor
3495     * moves to the position before the first row.
3496     * <P>
3497     * Note: Calling <code>absolute(1)</code> is the same as calling the
3498     * method <code>first()</code>.  Calling <code>absolute(-1)</code> is the
3499     * same as calling <code>last()</code>.
3500     *
3501     * @param row a positive number to indicate the row, starting row numbering from
3502     *        the first row, which is <code>1</code>; a negative number to indicate
3503     *        the row, starting row numbering from the last row, which is
3504     *        <code>-1</code>; it must not be <code>0</code>
3505     * @return <code>true</code> if the cursor is on the rowset; <code>false</code>
3506     *         otherwise
3507     * @throws SQLException if the given cursor position is <code>0</code> or the
3508     *            type of this rowset is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3509     */
3510    public boolean absolute( int row ) throws SQLException {
3511        if (row == 0 || getType() == ResultSet.TYPE_FORWARD_ONLY) {
3512            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.absolute").toString());
3513        }
3514
3515        if (row > 0) { // we are moving foward
3516            if (row > numRows) {
3517                // fell off the end
3518                afterLast();
3519                return false;
3520            } else {
3521                if (absolutePos <= 0)
3522                    internalFirst();
3523            }
3524        } else { // we are moving backward
3525            if (cursorPos + row < 0) {
3526                // fell off the front
3527                beforeFirst();
3528                return false;
3529            } else {
3530                if (absolutePos >= 0)
3531                    internalLast();
3532            }
3533        }
3534
3535        // Now move towards the absolute row that we're looking for
3536        while (absolutePos != row) {
3537            if (absolutePos < row) {
3538                if (!internalNext())
3539                    break;
3540            }
3541            else {
3542                if (!internalPrevious())
3543                    break;
3544            }
3545        }
3546
3547        notifyCursorMoved();
3548
3549        if (isAfterLast() || isBeforeFirst()) {
3550            return false;
3551        } else {
3552            return true;
3553        }
3554    }
3555
3556    /**
3557     * Moves the cursor the specified number of rows from the current
3558     * position, with a positive number moving it forward and a
3559     * negative number moving it backward.
3560     * <P>
3561     * If the number is positive, the cursor moves the specified number of
3562     * rows toward the end of the rowset, starting at the current row.
3563     * For example, the following command, in which
3564     * <code>crs</code> is a <code>CachedRowSetImpl</code> object with 100 rows,
3565     * moves the cursor forward four rows from the current row.  If the
3566     * current row is 50, the cursor would move to row 54.
3567     * <PRE><code>
3568     *
3569     *    crs.relative(4);
3570     *
3571     * </code> </PRE>
3572     * <P>
3573     * If the number is negative, the cursor moves back toward the beginning
3574     * the specified number of rows, starting at the current row.
3575     * For example, calling the method
3576     * <code>absolute(-1)</code> positions the cursor on the last row,
3577     * <code>absolute(-2)</code> moves it on the next-to-last row, and so on.
3578     * If the <code>CachedRowSetImpl</code> object <code>crs</code> has five rows,
3579     * the following command moves the cursor to the fourth-to-last row, which
3580     * in the case of a  rowset with five rows, is also the second row
3581     * from the beginning.
3582     * <PRE><code>
3583     *
3584     *    crs.absolute(-4);
3585     *
3586     * </code> </PRE>
3587     *
3588     * If the number specified is larger than the number of rows, the cursor
3589     * will move to the position after the last row. If the number specified
3590     * would move the cursor one or more rows before the first row, the cursor
3591     * moves to the position before the first row. In both cases, this method
3592     * throws an <code>SQLException</code>.
3593     * <P>
3594     * Note: Calling <code>absolute(1)</code> is the same as calling the
3595     * method <code>first()</code>.  Calling <code>absolute(-1)</code> is the
3596     * same as calling <code>last()</code>.  Calling <code>relative(0)</code>
3597     * is valid, but it does not change the cursor position.
3598     *
3599     * @param rows an <code>int</code> indicating the number of rows to move
3600     *             the cursor, starting at the current row; a positive number
3601     *             moves the cursor forward; a negative number moves the cursor
3602     *             backward; must not move the cursor past the valid
3603     *             rows
3604     * @return <code>true</code> if the cursor is on a row in this
3605     *         <code>CachedRowSetImpl</code> object; <code>false</code>
3606     *         otherwise
3607     * @throws SQLException if there are no rows in this rowset, the cursor is
3608     *         positioned either before the first row or after the last row, or
3609     *         the rowset is type <code>ResultSet.TYPE_FORWARD_ONLY</code>
3610     */
3611    public boolean relative(int rows) throws SQLException {
3612        if (numRows == 0 || isBeforeFirst() ||
3613        isAfterLast() || getType() == ResultSet.TYPE_FORWARD_ONLY) {
3614            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.relative").toString());
3615        }
3616
3617        if (rows == 0) {
3618            return true;
3619        }
3620
3621        if (rows > 0) { // we are moving forward
3622            if (cursorPos + rows > numRows) {
3623                // fell off the end
3624                afterLast();
3625            } else {
3626                for (int i=0; i < rows; i++) {
3627                    if (!internalNext())
3628                        break;
3629                }
3630            }
3631        } else { // we are moving backward
3632            if (cursorPos + rows < 0) {
3633                // fell off the front
3634                beforeFirst();
3635            } else {
3636                for (int i=rows; i < 0; i++) {
3637                    if (!internalPrevious())
3638                        break;
3639                }
3640            }
3641        }
3642        notifyCursorMoved();
3643
3644        if (isAfterLast() || isBeforeFirst()) {
3645            return false;
3646        } else {
3647            return true;
3648        }
3649    }
3650
3651    /**
3652     * Moves this <code>CachedRowSetImpl</code> object's cursor to the
3653     * previous row and returns <code>true</code> if the cursor is on
3654     * a valid row or <code>false</code> if it is not.
3655     * This method also notifies all listeners registered with this
3656     * <code>CachedRowSetImpl</code> object that its cursor has moved.
3657     * <P>
3658     * Note: calling the method <code>previous()</code> is not the same
3659     * as calling the method <code>relative(-1)</code>.  This is true
3660     * because it is possible to call <code>previous()</code> from the insert
3661     * row, from after the last row, or from the current row, whereas
3662     * <code>relative</code> may only be called from the current row.
3663     * <P>
3664     * The method <code>previous</code> may used in a <code>while</code>
3665     * loop to iterate through a rowset starting after the last row
3666     * and moving toward the beginning. The loop ends when <code>previous</code>
3667     * returns <code>false</code>, meaning that there are no more rows.
3668     * For example, the following code fragment retrieves all the data in
3669     * the <code>CachedRowSetImpl</code> object <code>crs</code>, which has
3670     * three columns.  Note that the cursor must initially be positioned
3671     * after the last row so that the first call to the method
3672     * <code>previous</code> places the cursor on the last line.
3673     * <PRE> <code>
3674     *
3675     *     crs.afterLast();
3676     *     while (previous()) {
3677     *         String name = crs.getString(1);
3678     *         int age = crs.getInt(2);
3679     *         short ssn = crs.getShort(3);
3680     *         System.out.println(name + "   " + age + "   " + ssn);
3681     *     }
3682     *
3683     * </code> </PRE>
3684     * This method throws an <code>SQLException</code> if the cursor is not
3685     * on a row in the rowset, before the first row, or after the last row.
3686     *
3687     * @return <code>true</code> if the cursor is on a valid row;
3688     *         <code>false</code> if it is before the first row or after the
3689     *         last row
3690     * @throws SQLException if the cursor is not on a valid position or the
3691     *           type of this rowset is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3692     */
3693    public boolean previous() throws SQLException {
3694        if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3695            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.last").toString());
3696        }
3697        /*
3698         * make sure things look sane. The cursor must be
3699         * positioned in the rowset or before first (0) or
3700         * after last (numRows + 1)
3701         */
3702        if (cursorPos < 0 || cursorPos > numRows + 1) {
3703            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
3704        }
3705        // move and notify
3706        boolean ret = this.internalPrevious();
3707        notifyCursorMoved();
3708
3709        return ret;
3710    }
3711
3712    /**
3713     * Moves the cursor to the previous row in this <code>CachedRowSetImpl</code>
3714     * object, skipping past deleted rows that are not visible; returns
3715     * <code>true</code> if the cursor is on a row in this rowset and
3716     * <code>false</code> when the cursor goes before the first row.
3717     * <P>
3718     * This method is called internally by the method <code>previous</code>.
3719     * <P>
3720     * This is a implementation only method and is not required as a standard
3721     * implementation of the <code>CachedRowSet</code> interface.
3722     *
3723     * @return <code>true</code> if the cursor is on a row in this rowset;
3724     *         <code>false</code> when the cursor reaches the position before
3725     *         the first row
3726     * @throws SQLException if an error occurs
3727     */
3728    protected boolean internalPrevious() throws SQLException {
3729        boolean ret = false;
3730
3731        do {
3732            if (cursorPos > 1) {
3733                --cursorPos;
3734                ret = true;
3735            } else if (cursorPos == 1) {
3736                // decrement to before first
3737                --cursorPos;
3738                ret = false;
3739                break;
3740            }
3741        } while ((getShowDeleted() == false) && (rowDeleted() == true));
3742
3743        /*
3744         * Each call to internalPrevious may move the cursor
3745         * over multiple rows, the absolute position moves one row
3746         */
3747        if (ret == true)
3748            --absolutePos;
3749        else
3750            absolutePos = 0;
3751
3752        return ret;
3753    }
3754
3755
3756    //---------------------------------------------------------------------
3757    // Updates
3758    //---------------------------------------------------------------------
3759
3760    /**
3761     * Indicates whether the current row of this <code>CachedRowSetImpl</code>
3762     * object has been updated.  The value returned
3763     * depends on whether this rowset can detect updates: <code>false</code>
3764     * will always be returned if it does not detect updates.
3765     *
3766     * @return <code>true</code> if the row has been visibly updated
3767     *         by the owner or another and updates are detected;
3768     *         <code>false</code> otherwise
3769     * @throws SQLException if the cursor is on the insert row or not
3770     *            not on a valid row
3771     *
3772     * @see DatabaseMetaData#updatesAreDetected
3773     */
3774    public boolean rowUpdated() throws SQLException {
3775        // make sure the cursor is on a valid row
3776        checkCursor();
3777        if (onInsertRow == true) {
3778            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3779        }
3780        return(((Row)getCurrentRow()).getUpdated());
3781    }
3782
3783    /**
3784     * Indicates whether the designated column of the current row of
3785     * this <code>CachedRowSetImpl</code> object has been updated. The
3786     * value returned depends on whether this rowset can detcted updates:
3787     * <code>false</code> will always be returned if it does not detect updates.
3788     *
3789     * @param idx the index identifier of the column that may be have been updated.
3790     * @return <code>true</code> is the designated column has been updated
3791     * and the rowset detects updates; <code>false</code> if the rowset has not
3792     * been updated or the rowset does not detect updates
3793     * @throws SQLException if the cursor is on the insert row or not
3794     *          on a valid row
3795     * @see DatabaseMetaData#updatesAreDetected
3796     */
3797    public boolean columnUpdated(int idx) throws SQLException {
3798        // make sure the cursor is on a valid row
3799        checkCursor();
3800        if (onInsertRow == true) {
3801            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3802        }
3803        return (((Row)getCurrentRow()).getColUpdated(idx - 1));
3804    }
3805
3806    /**
3807     * Indicates whether the designated column of the current row of
3808     * this <code>CachedRowSetImpl</code> object has been updated. The
3809     * value returned depends on whether this rowset can detcted updates:
3810     * <code>false</code> will always be returned if it does not detect updates.
3811     *
3812     * @param columnName the <code>String</code> column name column that may be have
3813     * been updated.
3814     * @return <code>true</code> is the designated column has been updated
3815     * and the rowset detects updates; <code>false</code> if the rowset has not
3816     * been updated or the rowset does not detect updates
3817     * @throws SQLException if the cursor is on the insert row or not
3818     *          on a valid row
3819     * @see DatabaseMetaData#updatesAreDetected
3820     */
3821    public boolean columnUpdated(String columnName) throws SQLException {
3822        return columnUpdated(getColIdxByName(columnName));
3823    }
3824
3825    /**
3826     * Indicates whether the current row has been inserted.  The value returned
3827     * depends on whether or not the rowset can detect visible inserts.
3828     *
3829     * @return <code>true</code> if a row has been inserted and inserts are detected;
3830     *         <code>false</code> otherwise
3831     * @throws SQLException if the cursor is on the insert row or not
3832     *            not on a valid row
3833     *
3834     * @see DatabaseMetaData#insertsAreDetected
3835     */
3836    public boolean rowInserted() throws SQLException {
3837        // make sure the cursor is on a valid row
3838        checkCursor();
3839        if (onInsertRow == true) {
3840            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3841        }
3842        return(((Row)getCurrentRow()).getInserted());
3843    }
3844
3845    /**
3846     * Indicates whether the current row has been deleted.  A deleted row
3847     * may leave a visible "hole" in a rowset.  This method can be used to
3848     * detect such holes if the rowset can detect deletions. This method
3849     * will always return <code>false</code> if this rowset cannot detect
3850     * deletions.
3851     *
3852     * @return <code>true</code> if (1)the current row is blank, indicating that
3853     *         the row has been deleted, and (2)deletions are detected;
3854     *         <code>false</code> otherwise
3855     * @throws SQLException if the cursor is on a valid row in this rowset
3856     * @see DatabaseMetaData#deletesAreDetected
3857     */
3858    public boolean rowDeleted() throws SQLException {
3859        // make sure the cursor is on a valid row
3860
3861        if (isAfterLast() == true ||
3862        isBeforeFirst() == true ||
3863        onInsertRow == true) {
3864
3865            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
3866        }
3867        return(((Row)getCurrentRow()).getDeleted());
3868    }
3869
3870    /**
3871     * Indicates whether the given SQL data type is a numberic type.
3872     *
3873     * @param type one of the constants from <code>java.sql.Types</code>
3874     * @return <code>true</code> if the given type is <code>NUMERIC</code>,'
3875     *         <code>DECIMAL</code>, <code>BIT</code>, <code>TINYINT</code>,
3876     *         <code>SMALLINT</code>, <code>INTEGER</code>, <code>BIGINT</code>,
3877     *         <code>REAL</code>, <code>DOUBLE</code>, or <code>FLOAT</code>;
3878     *         <code>false</code> otherwise
3879     */
3880    private boolean isNumeric(int type) {
3881        switch (type) {
3882            case java.sql.Types.NUMERIC:
3883            case java.sql.Types.DECIMAL:
3884            case java.sql.Types.BIT:
3885            case java.sql.Types.TINYINT:
3886            case java.sql.Types.SMALLINT:
3887            case java.sql.Types.INTEGER:
3888            case java.sql.Types.BIGINT:
3889            case java.sql.Types.REAL:
3890            case java.sql.Types.DOUBLE:
3891            case java.sql.Types.FLOAT:
3892                return true;
3893            default:
3894                return false;
3895        }
3896    }
3897
3898    /**
3899     * Indicates whether the given SQL data type is a string type.
3900     *
3901     * @param type one of the constants from <code>java.sql.Types</code>
3902     * @return <code>true</code> if the given type is <code>CHAR</code>,'
3903     *         <code>VARCHAR</code>, or <code>LONGVARCHAR</code>;
3904     *         <code>false</code> otherwise
3905     */
3906    private boolean isString(int type) {
3907        switch (type) {
3908            case java.sql.Types.CHAR:
3909            case java.sql.Types.VARCHAR:
3910            case java.sql.Types.LONGVARCHAR:
3911                return true;
3912            default:
3913                return false;
3914        }
3915    }
3916
3917    /**
3918     * Indicates whether the given SQL data type is a binary type.
3919     *
3920     * @param type one of the constants from <code>java.sql.Types</code>
3921     * @return <code>true</code> if the given type is <code>BINARY</code>,'
3922     *         <code>VARBINARY</code>, or <code>LONGVARBINARY</code>;
3923     *         <code>false</code> otherwise
3924     */
3925    private boolean isBinary(int type) {
3926        switch (type) {
3927            case java.sql.Types.BINARY:
3928            case java.sql.Types.VARBINARY:
3929            case java.sql.Types.LONGVARBINARY:
3930                return true;
3931            default:
3932                return false;
3933        }
3934    }
3935
3936    /**
3937     * Indicates whether the given SQL data type is a temporal type.
3938     * This method is called internally by the conversion methods
3939     * <code>convertNumeric</code> and <code>convertTemporal</code>.
3940     *
3941     * @param type one of the constants from <code>java.sql.Types</code>
3942     * @return <code>true</code> if the given type is <code>DATE</code>,
3943     *         <code>TIME</code>, or <code>TIMESTAMP</code>;
3944     *         <code>false</code> otherwise
3945     */
3946    private boolean isTemporal(int type) {
3947        switch (type) {
3948            case java.sql.Types.DATE:
3949            case java.sql.Types.TIME:
3950            case java.sql.Types.TIMESTAMP:
3951                return true;
3952            default:
3953                return false;
3954        }
3955    }
3956
3957    /**
3958     * Indicates whether the given SQL data type is a boolean type.
3959     * This method is called internally by the conversion methods
3960     * <code>convertNumeric</code> and <code>convertBoolean</code>.
3961     *
3962     * @param type one of the constants from <code>java.sql.Types</code>
3963     * @return <code>true</code> if the given type is <code>BIT</code>,
3964     *         , or <code>BOOLEAN</code>;
3965     *         <code>false</code> otherwise
3966     */
3967    private boolean isBoolean(int type) {
3968        switch (type) {
3969            case java.sql.Types.BIT:
3970            case java.sql.Types.BOOLEAN:
3971                return true;
3972            default:
3973                return false;
3974        }
3975    }
3976
3977
3978    /**
3979     * Converts the given <code>Object</code> in the Java programming language
3980     * to the standard mapping for the specified SQL target data type.
3981     * The conversion must be to a string or numeric type, but there are no
3982     * restrictions on the type to be converted.  If the source type and target
3983     * type are the same, the given object is simply returned.
3984     *
3985     * @param srcObj the <code>Object</code> in the Java programming language
3986     *               that is to be converted to the target type
3987     * @param srcType the data type that is the standard mapping in SQL of the
3988     *                object to be converted; must be one of the constants in
3989     *                <code>java.sql.Types</code>
3990     * @param trgType the SQL data type to which to convert the given object;
3991     *                must be one of the following constants in
3992     *                <code>java.sql.Types</code>: <code>NUMERIC</code>,
3993     *         <code>DECIMAL</code>, <code>BIT</code>, <code>TINYINT</code>,
3994     *         <code>SMALLINT</code>, <code>INTEGER</code>, <code>BIGINT</code>,
3995     *         <code>REAL</code>, <code>DOUBLE</code>, <code>FLOAT</code>,
3996     *         <code>VARCHAR</code>, <code>LONGVARCHAR</code>, or <code>CHAR</code>
3997     * @return an <code>Object</code> value.that is
3998     *         the standard object mapping for the target SQL type
3999     * @throws SQLException if the given target type is not one of the string or
4000     *         numeric types in <code>java.sql.Types</code>
4001     */
4002    private Object convertNumeric(Object srcObj, int srcType,
4003    int trgType) throws SQLException {
4004
4005        if (srcType == trgType) {
4006            return srcObj;
4007        }
4008
4009        if (isNumeric(trgType) == false && isString(trgType) == false) {
4010            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4011        }
4012
4013        try {
4014            switch (trgType) {
4015                case java.sql.Types.BIT:
4016                    Integer i = Integer.valueOf(srcObj.toString().trim());
4017                    return i.equals(0) ?
4018                    Boolean.valueOf(false) :
4019                        Boolean.valueOf(true);
4020                case java.sql.Types.TINYINT:
4021                    return Byte.valueOf(srcObj.toString().trim());
4022                case java.sql.Types.SMALLINT:
4023                    return Short.valueOf(srcObj.toString().trim());
4024                case java.sql.Types.INTEGER:
4025                    return Integer.valueOf(srcObj.toString().trim());
4026                case java.sql.Types.BIGINT:
4027                    return Long.valueOf(srcObj.toString().trim());
4028                case java.sql.Types.NUMERIC:
4029                case java.sql.Types.DECIMAL:
4030                    return new BigDecimal(srcObj.toString().trim());
4031                case java.sql.Types.REAL:
4032                case java.sql.Types.FLOAT:
4033                    return Float.valueOf(srcObj.toString().trim());
4034                case java.sql.Types.DOUBLE:
4035                    return Double.valueOf(srcObj.toString().trim());
4036                case java.sql.Types.CHAR:
4037                case java.sql.Types.VARCHAR:
4038                case java.sql.Types.LONGVARCHAR:
4039                    return srcObj.toString();
4040                default:
4041                    throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString()+ trgType);
4042            }
4043        } catch (NumberFormatException ex) {
4044            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4045        }
4046    }
4047
4048    /**
4049     * Converts the given <code>Object</code> in the Java programming language
4050     * to the standard object mapping for the specified SQL target data type.
4051     * The conversion must be to a string or temporal type, and there are also
4052     * restrictions on the type to be converted.
4053     * <P>
4054     * <TABLE ALIGN="CENTER" BORDER CELLPADDING=10 BORDERCOLOR="#0000FF"
4055     * <CAPTION ALIGN="CENTER"><B>Parameters and Return Values</B></CAPTION>
4056     * <TR>
4057     *   <TD><B>Source SQL Type</B>
4058     *   <TD><B>Target SQL Type</B>
4059     *   <TD><B>Object Returned</B>
4060     * </TR>
4061     * <TR>
4062     *   <TD><code>TIMESTAMP</code>
4063     *   <TD><code>DATE</code>
4064     *   <TD><code>java.sql.Date</code>
4065     * </TR>
4066     * <TR>
4067     *   <TD><code>TIMESTAMP</code>
4068     *   <TD><code>TIME</code>
4069     *   <TD><code>java.sql.Time</code>
4070     * </TR>
4071     * <TR>
4072     *   <TD><code>TIME</code>
4073     *   <TD><code>TIMESTAMP</code>
4074     *   <TD><code>java.sql.Timestamp</code>
4075     * </TR>
4076     * <TR>
4077     *   <TD><code>DATE</code>, <code>TIME</code>, or <code>TIMESTAMP</code>
4078     *   <TD><code>CHAR</code>, <code>VARCHAR</code>, or <code>LONGVARCHAR</code>
4079     *   <TD><code>java.lang.String</code>
4080     * </TR>
4081     * </TABLE>
4082     * <P>
4083     * If the source type and target type are the same,
4084     * the given object is simply returned.
4085     *
4086     * @param srcObj the <code>Object</code> in the Java programming language
4087     *               that is to be converted to the target type
4088     * @param srcType the data type that is the standard mapping in SQL of the
4089     *                object to be converted; must be one of the constants in
4090     *                <code>java.sql.Types</code>
4091     * @param trgType the SQL data type to which to convert the given object;
4092     *                must be one of the following constants in
4093     *                <code>java.sql.Types</code>: <code>DATE</code>,
4094     *         <code>TIME</code>, <code>TIMESTAMP</code>, <code>CHAR</code>,
4095     *         <code>VARCHAR</code>, or <code>LONGVARCHAR</code>
4096     * @return an <code>Object</code> value.that is
4097     *         the standard object mapping for the target SQL type
4098     * @throws SQLException if the given target type is not one of the string or
4099     *         temporal types in <code>java.sql.Types</code>
4100     */
4101    private Object convertTemporal(Object srcObj,
4102    int srcType, int trgType) throws SQLException {
4103
4104        if (srcType == trgType) {
4105            return srcObj;
4106        }
4107
4108        if (isNumeric(trgType) == true ||
4109        (isString(trgType) == false && isTemporal(trgType) == false)) {
4110            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4111        }
4112
4113        try {
4114            switch (trgType) {
4115                case java.sql.Types.DATE:
4116                    if (srcType == java.sql.Types.TIMESTAMP) {
4117                        return new java.sql.Date(((java.sql.Timestamp)srcObj).getTime());
4118                    } else {
4119                        throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4120                    }
4121                case java.sql.Types.TIMESTAMP:
4122                    if (srcType == java.sql.Types.TIME) {
4123                        return new Timestamp(((java.sql.Time)srcObj).getTime());
4124                    } else {
4125                        return new Timestamp(((java.sql.Date)srcObj).getTime());
4126                    }
4127                case java.sql.Types.TIME:
4128                    if (srcType == java.sql.Types.TIMESTAMP) {
4129                        return new Time(((java.sql.Timestamp)srcObj).getTime());
4130                    } else {
4131                        throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4132                    }
4133                case java.sql.Types.CHAR:
4134                case java.sql.Types.VARCHAR:
4135                case java.sql.Types.LONGVARCHAR:
4136                    return srcObj.toString();
4137                default:
4138                    throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4139            }
4140        } catch (NumberFormatException ex) {
4141            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4142        }
4143
4144    }
4145
4146    /**
4147     * Converts the given <code>Object</code> in the Java programming language
4148     * to the standard mapping for the specified SQL target data type.
4149     * The conversion must be to a string or numeric type, but there are no
4150     * restrictions on the type to be converted.  If the source type and target
4151     * type are the same, the given object is simply returned.
4152     *
4153     * @param srcObj the <code>Object</code> in the Java programming language
4154     *               that is to be converted to the target type
4155     * @param srcType the data type that is the standard mapping in SQL of the
4156     *                object to be converted; must be one of the constants in
4157     *                <code>java.sql.Types</code>
4158     * @param trgType the SQL data type to which to convert the given object;
4159     *                must be one of the following constants in
4160     *                <code>java.sql.Types</code>: <code>BIT</code>,
4161     *         or <code>BOOLEAN</code>
4162     * @return an <code>Object</code> value.that is
4163     *         the standard object mapping for the target SQL type
4164     * @throws SQLException if the given target type is not one of the Boolean
4165     *         types in <code>java.sql.Types</code>
4166     */
4167    private Object convertBoolean(Object srcObj, int srcType,
4168    int trgType) throws SQLException {
4169
4170        if (srcType == trgType) {
4171            return srcObj;
4172        }
4173
4174        if (isNumeric(trgType) == true ||
4175        (isString(trgType) == false && isBoolean(trgType) == false)) {
4176            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4177        }
4178
4179
4180        try {
4181            switch (trgType) {
4182                case java.sql.Types.BIT:
4183                    Integer i = Integer.valueOf(srcObj.toString().trim());
4184                    return i.equals(0) ?
4185                    Boolean.valueOf(false) :
4186                        Boolean.valueOf(true);
4187                case java.sql.Types.BOOLEAN:
4188                    return Boolean.valueOf(srcObj.toString().trim());
4189                default:
4190                    throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString()+ trgType);
4191            }
4192        } catch (NumberFormatException ex) {
4193            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4194        }
4195    }
4196
4197    /**
4198     * Sets the designated nullable column in the current row or the
4199     * insert row of this <code>CachedRowSetImpl</code> object with
4200     * <code>null</code> value.
4201     * <P>
4202     * This method updates a column value in the current row or the insert
4203     * row of this rowset; however, another method must be called to complete
4204     * the update process. If the cursor is on a row in the rowset, the
4205     * method {@link #updateRow} must be called to mark the row as updated
4206     * and to notify listeners that the row has changed.
4207     * If the cursor is on the insert row, the method {@link #insertRow}
4208     * must be called to insert the new row into this rowset and to notify
4209     * listeners that a row has changed.
4210     * <P>
4211     * In order to propagate updates in this rowset to the underlying
4212     * data source, an application must call the method {@link #acceptChanges}
4213     * after it calls either <code>updateRow</code> or <code>insertRow</code>.
4214     *
4215     * @param columnIndex the first column is <code>1</code>, the second
4216     *        is <code>2</code>, and so on; must be <code>1</code> or larger
4217     *        and equal to or less than the number of columns in this rowset
4218     * @throws SQLException if (1) the given column index is out of bounds,
4219     *            (2) the cursor is not on one of this rowset's rows or its
4220     *            insert row, or (3) this rowset is
4221     *            <code>ResultSet.CONCUR_READ_ONLY</code>
4222     */
4223    public void updateNull(int columnIndex) throws SQLException {
4224        // sanity check.
4225        checkIndex(columnIndex);
4226        // make sure the cursor is on a valid row
4227        checkCursor();
4228
4229        BaseRow row = getCurrentRow();
4230        row.setColumnObject(columnIndex, null);
4231
4232    }
4233
4234    /**
4235     * Sets the designated column in either the current row or the insert
4236     * row of this <code>CachedRowSetImpl</code> object with the given
4237     * <code>boolean</code> value.
4238     * <P>
4239     * This method updates a column value in the current row or the insert
4240     * row of this rowset, but it does not update the database.
4241     * If the cursor is on a row in the rowset, the
4242     * method {@link #updateRow} must be called to update the database.
4243     * If the cursor is on the insert row, the method {@link #insertRow}
4244     * must be called, which will insert the new row into both this rowset
4245     * and the database. Both of these methods must be called before the
4246     * cursor moves to another row.
4247     *
4248     * @param columnIndex the first column is <code>1</code>, the second
4249     *        is <code>2</code>, and so on; must be <code>1</code> or larger
4250     *        and equal to or less than the number of columns in this rowset
4251     * @param x the new column value
4252     * @throws SQLException if (1) the given column index is out of bounds,
4253     *            (2) the cursor is not on one of this rowset's rows or its
4254     *            insert row, or (3) this rowset is
4255     *            <code>ResultSet.CONCUR_READ_ONLY</code>
4256     */
4257    public void updateBoolean(int columnIndex, boolean x) throws SQLException {
4258        // sanity check.
4259        checkIndex(columnIndex);
4260        // make sure the cursor is on a valid row
4261        checkCursor();
4262        Object obj = convertBoolean(Boolean.valueOf(x),
4263        java.sql.Types.BIT,
4264        RowSetMD.getColumnType(columnIndex));
4265
4266        getCurrentRow().setColumnObject(columnIndex, obj);
4267    }
4268
4269    /**
4270     * Sets the designated column in either the current row or the insert
4271     * row of this <code>CachedRowSetImpl</code> object with the given
4272     * <code>byte</code> value.
4273     * <P>
4274     * This method updates a column value in the current row or the insert
4275     * row of this rowset, but it does not update the database.
4276     * If the cursor is on a row in the rowset, the
4277     * method {@link #updateRow} must be called to update the database.
4278     * If the cursor is on the insert row, the method {@link #insertRow}
4279     * must be called, which will insert the new row into both this rowset
4280     * and the database. Both of these methods must be called before the
4281     * cursor moves to another row.
4282     *
4283     * @param columnIndex the first column is <code>1</code>, the second
4284     *        is <code>2</code>, and so on; must be <code>1</code> or larger
4285     *        and equal to or less than the number of columns in this rowset
4286     * @param x the new column value
4287     * @throws SQLException if (1) the given column index is out of bounds,
4288     *            (2) the cursor is not on one of this rowset's rows or its
4289     *            insert row, or (3) this rowset is
4290     *            <code>ResultSet.CONCUR_READ_ONLY</code>
4291     */
4292    public void updateByte(int columnIndex, byte x) throws SQLException {
4293        // sanity check.
4294        checkIndex(columnIndex);
4295        // make sure the cursor is on a valid row
4296        checkCursor();
4297
4298        Object obj = convertNumeric(Byte.valueOf(x),
4299        java.sql.Types.TINYINT,
4300        RowSetMD.getColumnType(columnIndex));
4301
4302        getCurrentRow().setColumnObject(columnIndex, obj);
4303    }
4304
4305    /**
4306     * Sets the designated column in either the current row or the insert
4307     * row of this <code>CachedRowSetImpl</code> object with the given
4308     * <code>short</code> value.
4309     * <P>
4310     * This method updates a column value in the current row or the insert
4311     * row of this rowset, but it does not update the database.
4312     * If the cursor is on a row in the rowset, the
4313     * method {@link #updateRow} must be called to update the database.
4314     * If the cursor is on the insert row, the method {@link #insertRow}
4315     * must be called, which will insert the new row into both this rowset
4316     * and the database. Both of these methods must be called before the
4317     * cursor moves to another row.
4318     *
4319     * @param columnIndex the first column is <code>1</code>, the second
4320     *        is <code>2</code>, and so on; must be <code>1</code> or larger
4321     *        and equal to or less than the number of columns in this rowset
4322     * @param x the new column value
4323     * @throws SQLException if (1) the given column index is out of bounds,
4324     *            (2) the cursor is not on one of this rowset's rows or its
4325     *            insert row, or (3) this rowset is
4326     *            <code>ResultSet.CONCUR_READ_ONLY</code>
4327     */
4328    public void updateShort(int columnIndex, short x) throws SQLException {
4329        // sanity check.
4330        checkIndex(columnIndex);
4331        // make sure the cursor is on a valid row
4332        checkCursor();
4333
4334        Object obj = convertNumeric(Short.valueOf(x),
4335        java.sql.Types.SMALLINT,
4336        RowSetMD.getColumnType(columnIndex));
4337
4338        getCurrentRow().setColumnObject(columnIndex, obj);
4339    }
4340
4341    /**
4342     * Sets the designated column in either the current row or the insert
4343     * row of this <code>CachedRowSetImpl</code> object with the given
4344     * <code>int</code> value.
4345     * <P>
4346     * This method updates a column value in the current row or the insert
4347     * row of this rowset, but it does not update the database.
4348     * If the cursor is on a row in the rowset, the
4349     * method {@link #updateRow} must be called to update the database.
4350     * If the cursor is on the insert row, the method {@link #insertRow}
4351     * must be called, which will insert the new row into both this rowset
4352     * and the database. Both of these methods must be called before the
4353     * cursor moves to another row.
4354     *
4355     * @param columnIndex the first column is <code>1</code>, the second
4356     *        is <code>2</code>, and so on; must be <code>1</code> or larger
4357     *        and equal to or less than the number of columns in this rowset
4358     * @param x the new column value
4359     * @throws SQLException if (1) the given column index is out of bounds,
4360     *            (2) the cursor is not on one of this rowset's rows or its
4361     *            insert row, or (3) this rowset is
4362     *            <code>ResultSet.CONCUR_READ_ONLY</code>
4363     */
4364    public void updateInt(int columnIndex, int x) throws SQLException {
4365        // sanity check.
4366        checkIndex(columnIndex);
4367        // make sure the cursor is on a valid row
4368        checkCursor();
4369        Object obj = convertNumeric(x,
4370        java.sql.Types.INTEGER,
4371        RowSetMD.getColumnType(columnIndex));
4372
4373        getCurrentRow().setColumnObject(columnIndex, obj);
4374    }
4375
4376    /**
4377     * Sets the designated column in either the current row or the insert
4378     * row of this <code>CachedRowSetImpl</code> object with the given
4379     * <code>long</code> value.
4380     * <P>
4381     * This method updates a column value in the current row or the insert
4382     * row of this rowset, but it does not update the database.
4383     * If the cursor is on a row in the rowset, the
4384     * method {@link #updateRow} must be called to update the database.
4385     * If the cursor is on the insert row, the method {@link #insertRow}
4386     * must be called, which will insert the new row into both this rowset
4387     * and the database. Both of these methods must be called before the
4388     * cursor moves to another row.
4389     *
4390     * @param columnIndex the first column is <code>1</code>, the second
4391     *        is <code>2</code>, and so on; must be <code>1</code> or larger
4392     *        and equal to or less than the number of columns in this rowset
4393     * @param x the new column value
4394     * @throws SQLException if (1) the given column index is out of bounds,
4395     *            (2) the cursor is not on one of this rowset's rows or its
4396     *            insert row, or (3) this rowset is
4397     *            <code>ResultSet.CONCUR_READ_ONLY</code>
4398     */
4399    public void updateLong(int columnIndex, long x) throws SQLException {
4400        // sanity check.
4401        checkIndex(columnIndex);
4402        // make sure the cursor is on a valid row
4403        checkCursor();
4404
4405        Object obj = convertNumeric(Long.valueOf(x),
4406        java.sql.Types.BIGINT,
4407        RowSetMD.getColumnType(columnIndex));
4408
4409        getCurrentRow().setColumnObject(columnIndex, obj);
4410
4411    }
4412
4413    /**
4414     * Sets the designated column in either the current row or the insert
4415     * row of this <code>CachedRowSetImpl</code> object with the given
4416     * <code>float</code> value.
4417     * <P>
4418     * This method updates a column value in the current row or the insert
4419     * row of this rowset, but it does not update the database.
4420     * If the cursor is on a row in the rowset, the
4421     * method {@link #updateRow} must be called to update the database.
4422     * If the cursor is on the insert row, the method {@link #insertRow}
4423     * must be called, which will insert the new row into both this rowset
4424     * and the database. Both of these methods must be called before the
4425     * cursor moves to another row.
4426     *
4427     * @param columnIndex the first column is <code>1</code>, the second
4428     *        is <code>2</code>, and so on; must be <code>1</code> or larger
4429     *        and equal to or less than the number of columns in this rowset
4430     * @param x the new column value
4431     * @throws SQLException if (1) the given column index is out of bounds,
4432     *            (2) the cursor is not on one of this rowset's rows or its
4433     *            insert row, or (3) this rowset is
4434     *            <code>ResultSet.CONCUR_READ_ONLY</code>
4435     */
4436    public void updateFloat(int columnIndex, float x) throws SQLException {
4437        // sanity check.
4438        checkIndex(columnIndex);
4439        // make sure the cursor is on a valid row
4440        checkCursor();
4441
4442        Object obj = convertNumeric(Float.valueOf(x),
4443        java.sql.Types.REAL,
4444        RowSetMD.getColumnType(columnIndex));
4445
4446        getCurrentRow().setColumnObject(columnIndex, obj);
4447    }
4448
4449    /**
4450     * Sets the designated column in either the current row or the insert
4451     * row of this <code>CachedRowSetImpl</code> object with the given
4452     * <code>double</code> value.
4453     *
4454     * This method updates a column value in either the current row or
4455     * the insert row of this rowset, but it does not update the
4456     * database.  If the cursor is on a row in the rowset, the
4457     * method {@link #updateRow} must be called to update the database.
4458     * If the cursor is on the insert row, the method {@link #insertRow}
4459     * must be called, which will insert the new row into both this rowset
4460     * and the database. Both of these methods must be called before the
4461     * cursor moves to another row.
4462     *
4463     * @param columnIndex the first column is <code>1</code>, the second
4464     *        is <code>2</code>, and so on; must be <code>1</code> or larger
4465     *        and equal to or less than the number of columns in this rowset
4466     * @param x the new column value
4467     * @throws SQLException if (1) the given column index is out of bounds,
4468     *            (2) the cursor is not on one of this rowset's rows or its
4469     *            insert row, or (3) this rowset is
4470     *            <code>ResultSet.CONCUR_READ_ONLY</code>
4471     */
4472    public void updateDouble(int columnIndex, double x) throws SQLException {
4473        // sanity check.
4474        checkIndex(columnIndex);
4475        // make sure the cursor is on a valid row
4476        checkCursor();
4477        Object obj = convertNumeric(Double.valueOf(x),
4478        java.sql.Types.DOUBLE,
4479        RowSetMD.getColumnType(columnIndex));
4480
4481        getCurrentRow().setColumnObject(columnIndex, obj);
4482    }
4483
4484    /**
4485     * Sets the designated column in either the current row or the insert
4486     * row of this <code>CachedRowSetImpl</code> object with the given
4487     * <code>java.math.BigDecimal</code> object.
4488     * <P>
4489     * This method updates a column value in the current row or the insert
4490     * row of this rowset, but it does not update the database.
4491     * If the cursor is on a row in the rowset, the
4492     * method {@link #updateRow} must be called to update the database.
4493     * If the cursor is on the insert row, the method {@link #insertRow}
4494     * must be called, which will insert the new row into both this rowset
4495     * and the database. Both of these methods must be called before the
4496     * cursor moves to another row.
4497     *
4498     * @param columnIndex the first column is <code>1</code>, the second
4499     *        is <code>2</code>, and so on; must be <code>1</code> or larger
4500     *        and equal to or less than the number of columns in this rowset
4501     * @param x the new column value
4502     * @throws SQLException if (1) the given column index is out of bounds,
4503     *            (2) the cursor is not on one of this rowset's rows or its
4504     *            insert row, or (3) this rowset is
4505     *            <code>ResultSet.CONCUR_READ_ONLY</code>
4506     */
4507    public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {
4508        // sanity check.
4509        checkIndex(columnIndex);
4510        // make sure the cursor is on a valid row
4511        checkCursor();
4512
4513        Object obj = convertNumeric(x,
4514        java.sql.Types.NUMERIC,
4515        RowSetMD.getColumnType(columnIndex));
4516
4517        getCurrentRow().setColumnObject(columnIndex, obj);
4518    }
4519
4520    /**
4521     * Sets the designated column in either the current row or the insert
4522     * row of this <code>CachedRowSetImpl</code> object with the given
4523     * <code>String</code> object.
4524     * <P>
4525     * This method updates a column value in either the current row or
4526     * the insert row of this rowset, but it does not update the
4527     * database.  If the cursor is on a row in the rowset, the
4528     * method {@link #updateRow} must be called to mark the row as updated.
4529     * If the cursor is on the insert row, the method {@link #insertRow}
4530     * must be called to insert the new row into this rowset and mark it
4531     * as inserted. Both of these methods must be called before the
4532     * cursor moves to another row.
4533     * <P>
4534     * The method <code>acceptChanges</code> must be called if the
4535     * updated values are to be written back to the underlying database.
4536     *
4537     * @param columnIndex the first column is <code>1</code>, the second
4538     *        is <code>2</code>, and so on; must be <code>1</code> or larger
4539     *        and equal to or less than the number of columns in this rowset
4540     * @param x the new column value
4541     * @throws SQLException if (1) the given column index is out of bounds,
4542     *            (2) the cursor is not on one of this rowset's rows or its
4543     *            insert row, or (3) this rowset is
4544     *            <code>ResultSet.CONCUR_READ_ONLY</code>
4545     */
4546    public void updateString(int columnIndex, String x) throws SQLException {
4547        // sanity check.
4548        checkIndex(columnIndex);
4549        // make sure the cursor is on a valid row
4550        checkCursor();
4551
4552        getCurrentRow().setColumnObject(columnIndex, x);
4553    }
4554
4555    /**
4556     * Sets the designated column in either the current row or the insert
4557     * row of this <code>CachedRowSetImpl</code> object with the given
4558     * <code>byte</code> array.
4559     *
4560     * This method updates a column value in either the current row or
4561     * the insert row of this rowset, but it does not update the
4562     * database.  If the cursor is on a row in the rowset, the
4563     * method {@link #updateRow} must be called to update the database.
4564     * If the cursor is on the insert row, the method {@link #insertRow}
4565     * must be called, which will insert the new row into both this rowset
4566     * and the database. Both of these methods must be called before the
4567     * cursor moves to another row.
4568     *
4569     * @param columnIndex the first column is <code>1</code>, the second
4570     *        is <code>2</code>, and so on; must be <code>1</code> or larger
4571     *        and equal to or less than the number of columns in this rowset
4572     * @param x the new column value
4573     * @throws SQLException if (1) the given column index is out of bounds,
4574     *            (2) the cursor is not on one of this rowset's rows or its
4575     *            insert row, or (3) this rowset is
4576     *            <code>ResultSet.CONCUR_READ_ONLY</code>
4577     */
4578    public void updateBytes(int columnIndex, byte x[]) throws SQLException {
4579        // sanity check.
4580        checkIndex(columnIndex);
4581        // make sure the cursor is on a valid row
4582        checkCursor();
4583
4584        if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4585            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4586        }
4587
4588        getCurrentRow().setColumnObject(columnIndex, x);
4589    }
4590
4591    /**
4592     * Sets the designated column in either the current row or the insert
4593     * row of this <code>CachedRowSetImpl</code> object with the given
4594     * <code>Date</code> object.
4595     *
4596     * This method updates a column value in either the current row or
4597     * the insert row of this rowset, but it does not update the
4598     * database.  If the cursor is on a row in the rowset, the
4599     * method {@link #updateRow} must be called to update the database.
4600     * If the cursor is on the insert row, the method {@link #insertRow}
4601     * must be called, which will insert the new row into both this rowset
4602     * and the database. Both of these methods must be called before the
4603     * cursor moves to another row.
4604     *
4605     * @param columnIndex the first column is <code>1</code>, the second
4606     *        is <code>2</code>, and so on; must be <code>1</code> or larger
4607     *        and equal to or less than the number of columns in this rowset
4608     * @param x the new column value
4609     * @throws SQLException if (1) the given column index is out of bounds,
4610     *            (2) the cursor is not on one of this rowset's rows or its
4611     *            insert row, (3) the type of the designated column is not
4612     *            an SQL <code>DATE</code> or <code>TIMESTAMP</code>, or
4613     *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4614     */
4615    public void updateDate(int columnIndex, java.sql.Date x) throws SQLException {
4616        // sanity check.
4617        checkIndex(columnIndex);
4618        // make sure the cursor is on a valid row
4619        checkCursor();
4620
4621        Object obj = convertTemporal(x,
4622        java.sql.Types.DATE,
4623        RowSetMD.getColumnType(columnIndex));
4624
4625        getCurrentRow().setColumnObject(columnIndex, obj);
4626    }
4627
4628    /**
4629     * Sets the designated column in either the current row or the insert
4630     * row of this <code>CachedRowSetImpl</code> object with the given
4631     * <code>Time</code> object.
4632     *
4633     * This method updates a column value in either the current row or
4634     * the insert row of this rowset, but it does not update the
4635     * database.  If the cursor is on a row in the rowset, the
4636     * method {@link #updateRow} must be called to update the database.
4637     * If the cursor is on the insert row, the method {@link #insertRow}
4638     * must be called, which will insert the new row into both this rowset
4639     * and the database. Both of these methods must be called before the
4640     * cursor moves to another row.
4641     *
4642     * @param columnIndex the first column is <code>1</code>, the second
4643     *        is <code>2</code>, and so on; must be <code>1</code> or larger
4644     *        and equal to or less than the number of columns in this rowset
4645     * @param x the new column value
4646     * @throws SQLException if (1) the given column index is out of bounds,
4647     *            (2) the cursor is not on one of this rowset's rows or its
4648     *            insert row, (3) the type of the designated column is not
4649     *            an SQL <code>TIME</code> or <code>TIMESTAMP</code>, or
4650     *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4651     */
4652    public void updateTime(int columnIndex, java.sql.Time x) throws SQLException {
4653        // sanity check.
4654        checkIndex(columnIndex);
4655        // make sure the cursor is on a valid row
4656        checkCursor();
4657
4658        Object obj = convertTemporal(x,
4659        java.sql.Types.TIME,
4660        RowSetMD.getColumnType(columnIndex));
4661
4662        getCurrentRow().setColumnObject(columnIndex, obj);
4663    }
4664
4665    /**
4666     * Sets the designated column in either the current row or the insert
4667     * row of this <code>CachedRowSetImpl</code> object with the given
4668     * <code>Timestamp</code> object.
4669     *
4670     * This method updates a column value in either the current row or
4671     * the insert row of this rowset, but it does not update the
4672     * database.  If the cursor is on a row in the rowset, the
4673     * method {@link #updateRow} must be called to update the database.
4674     * If the cursor is on the insert row, the method {@link #insertRow}
4675     * must be called, which will insert the new row into both this rowset
4676     * and the database. Both of these methods must be called before the
4677     * cursor moves to another row.
4678     *
4679     * @param columnIndex the first column is <code>1</code>, the second
4680     *        is <code>2</code>, and so on; must be <code>1</code> or larger
4681     *        and equal to or less than the number of columns in this rowset
4682     * @param x the new column value
4683     * @throws SQLException if (1) the given column index is out of bounds,
4684     *            (2) the cursor is not on one of this rowset's rows or its
4685     *            insert row, (3) the type of the designated column is not
4686     *            an SQL <code>DATE</code>, <code>TIME</code>, or
4687     *            <code>TIMESTAMP</code>, or (4) this rowset is
4688     *            <code>ResultSet.CONCUR_READ_ONLY</code>
4689     */
4690    public void updateTimestamp(int columnIndex, java.sql.Timestamp x) throws SQLException {
4691        // sanity check.
4692        checkIndex(columnIndex);
4693        // make sure the cursor is on a valid row
4694        checkCursor();
4695
4696        Object obj = convertTemporal(x,
4697        java.sql.Types.TIMESTAMP,
4698        RowSetMD.getColumnType(columnIndex));
4699
4700        getCurrentRow().setColumnObject(columnIndex, obj);
4701    }
4702
4703    /**
4704     * Sets the designated column in either the current row or the insert
4705     * row of this <code>CachedRowSetImpl</code> object with the given
4706     * ASCII stream value.
4707     * <P>
4708     * This method updates a column value in either the current row or
4709     * the insert row of this rowset, but it does not update the
4710     * database.  If the cursor is on a row in the rowset, the
4711     * method {@link #updateRow} must be called to update the database.
4712     * If the cursor is on the insert row, the method {@link #insertRow}
4713     * must be called, which will insert the new row into both this rowset
4714     * and the database. Both of these methods must be called before the
4715     * cursor moves to another row.
4716     *
4717     * @param columnIndex the first column is <code>1</code>, the second
4718     *        is <code>2</code>, and so on; must be <code>1</code> or larger
4719     *        and equal to or less than the number of columns in this rowset
4720     * @param x the new column value
4721     * @param length the number of one-byte ASCII characters in the stream
4722     * @throws SQLException if this method is invoked
4723     */
4724    public void updateAsciiStream(int columnIndex, java.io.InputStream x, int length) throws SQLException {
4725        // sanity Check
4726        checkIndex(columnIndex);
4727        // make sure the cursor is on a valid row
4728        checkCursor();
4729
4730
4731        if (isString(RowSetMD.getColumnType(columnIndex)) == false &&
4732        isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4733            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4734        }
4735
4736        byte buf[] = new byte[length];
4737        try {
4738            int charsRead = 0;
4739            do {
4740                charsRead += x.read(buf, charsRead, length - charsRead);
4741            } while (charsRead != length);
4742            //Changed the condition check to check for length instead of -1
4743        } catch (java.io.IOException ex) {
4744            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.asciistream").toString());
4745        }
4746        String str = new String(buf);
4747
4748        getCurrentRow().setColumnObject(columnIndex, str);
4749
4750    }
4751
4752    /**
4753     * Sets the designated column in either the current row or the insert
4754     * row of this <code>CachedRowSetImpl</code> object with the given
4755     * <code>java.io.InputStream</code> object.
4756     * <P>
4757     * This method updates a column value in either the current row or
4758     * the insert row of this rowset, but it does not update the
4759     * database.  If the cursor is on a row in the rowset, the
4760     * method {@link #updateRow} must be called to update the database.
4761     * If the cursor is on the insert row, the method {@link #insertRow}
4762     * must be called, which will insert the new row into both this rowset
4763     * and the database. Both of these methods must be called before the
4764     * cursor moves to another row.
4765     *
4766     * @param columnIndex the first column is <code>1</code>, the second
4767     *        is <code>2</code>, and so on; must be <code>1</code> or larger
4768     *        and equal to or less than the number of columns in this rowset
4769     * @param x the new column value; must be a <code>java.io.InputStream</code>
4770     *          containing <code>BINARY</code>, <code>VARBINARY</code>, or
4771     *          <code>LONGVARBINARY</code> data
4772     * @param length the length of the stream in bytes
4773     * @throws SQLException if (1) the given column index is out of bounds,
4774     *            (2) the cursor is not on one of this rowset's rows or its
4775     *            insert row, (3) the data in the stream is not binary, or
4776     *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4777     */
4778    public void updateBinaryStream(int columnIndex, java.io.InputStream x,int length) throws SQLException {
4779        // sanity Check
4780        checkIndex(columnIndex);
4781        // make sure the cursor is on a valid row
4782        checkCursor();
4783
4784        if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4785            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4786        }
4787
4788        byte buf[] = new byte[length];
4789        try {
4790            int bytesRead = 0;
4791            do {
4792                bytesRead += x.read(buf, bytesRead, length - bytesRead);
4793            } while (bytesRead != -1);
4794        } catch (java.io.IOException ex) {
4795            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.binstream").toString());
4796        }
4797
4798        getCurrentRow().setColumnObject(columnIndex, buf);
4799    }
4800
4801    /**
4802     * Sets the designated column in either the current row or the insert
4803     * row of this <code>CachedRowSetImpl</code> object with the given
4804     * <code>java.io.Reader</code> object.
4805     * <P>
4806     * This method updates a column value in either the current row or
4807     * the insert row of this rowset, but it does not update the
4808     * database.  If the cursor is on a row in the rowset, the
4809     * method {@link #updateRow} must be called to update the database.
4810     * If the cursor is on the insert row, the method {@link #insertRow}
4811     * must be called, which will insert the new row into both this rowset
4812     * and the database. Both of these methods must be called before the
4813     * cursor moves to another row.
4814     *
4815     * @param columnIndex the first column is <code>1</code>, the second
4816     *        is <code>2</code>, and so on; must be <code>1</code> or larger
4817     *        and equal to or less than the number of columns in this rowset
4818     * @param x the new column value; must be a <code>java.io.Reader</code>
4819     *          containing <code>BINARY</code>, <code>VARBINARY</code>,
4820     *          <code>LONGVARBINARY</code>, <code>CHAR</code>, <code>VARCHAR</code>,
4821     *          or <code>LONGVARCHAR</code> data
4822     * @param length the length of the stream in characters
4823     * @throws SQLException if (1) the given column index is out of bounds,
4824     *            (2) the cursor is not on one of this rowset's rows or its
4825     *            insert row, (3) the data in the stream is not a binary or
4826     *            character type, or (4) this rowset is
4827     *            <code>ResultSet.CONCUR_READ_ONLY</code>
4828     */
4829    public void updateCharacterStream(int columnIndex, java.io.Reader x, int length) throws SQLException {
4830        // sanity Check
4831        checkIndex(columnIndex);
4832        // make sure the cursor is on a valid row
4833        checkCursor();
4834
4835        if (isString(RowSetMD.getColumnType(columnIndex)) == false &&
4836        isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4837            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4838        }
4839
4840        char buf[] = new char[length];
4841        try {
4842            int charsRead = 0;
4843            do {
4844                charsRead += x.read(buf, charsRead, length - charsRead);
4845            } while (charsRead != length);
4846            //Changed the condition checking to check for length instead of -1
4847        } catch (java.io.IOException ex) {
4848            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.binstream").toString());
4849        }
4850        String str = new String(buf);
4851
4852        getCurrentRow().setColumnObject(columnIndex, str);
4853    }
4854
4855    /**
4856     * Sets the designated column in either the current row or the insert
4857     * row of this <code>CachedRowSetImpl</code> object with the given
4858     * <code>Object</code> value.  The <code>scale</code> parameter indicates
4859     * the number of digits to the right of the decimal point and is ignored
4860     * if the new column value is not a type that will be mapped to an SQL
4861     * <code>DECIMAL</code> or <code>NUMERIC</code> value.
4862     * <P>
4863     * This method updates a column value in either the current row or
4864     * the insert row of this rowset, but it does not update the
4865     * database.  If the cursor is on a row in the rowset, the
4866     * method {@link #updateRow} must be called to update the database.
4867     * If the cursor is on the insert row, the method {@link #insertRow}
4868     * must be called, which will insert the new row into both this rowset
4869     * and the database. Both of these methods must be called before the
4870     * cursor moves to another row.
4871     *
4872     * @param columnIndex the first column is <code>1</code>, the second
4873     *        is <code>2</code>, and so on; must be <code>1</code> or larger
4874     *        and equal to or less than the number of columns in this rowset
4875     * @param x the new column value
4876     * @param scale the number of digits to the right of the decimal point (for
4877     *              <code>DECIMAL</code> and <code>NUMERIC</code> types only)
4878     * @throws SQLException if (1) the given column index is out of bounds,
4879     *            (2) the cursor is not on one of this rowset's rows or its
4880     *            insert row, or (3) this rowset is
4881     *            <code>ResultSet.CONCUR_READ_ONLY</code>
4882     */
4883    public void updateObject(int columnIndex, Object x, int scale) throws SQLException {
4884        // sanity check.
4885        checkIndex(columnIndex);
4886        // make sure the cursor is on a valid row
4887        checkCursor();
4888
4889        int type = RowSetMD.getColumnType(columnIndex);
4890        if (type == Types.DECIMAL || type == Types.NUMERIC) {
4891            ((java.math.BigDecimal)x).setScale(scale);
4892        }
4893        getCurrentRow().setColumnObject(columnIndex, x);
4894    }
4895
4896    /**
4897     * Sets the designated column in either the current row or the insert
4898     * row of this <code>CachedRowSetImpl</code> object with the given
4899     * <code>Object</code> value.
4900     * <P>
4901     * This method updates a column value in either the current row or
4902     * the insert row of this rowset, but it does not update the
4903     * database.  If the cursor is on a row in the rowset, the
4904     * method {@link #updateRow} must be called to update the database.
4905     * If the cursor is on the insert row, the method {@link #insertRow}
4906     * must be called, which will insert the new row into both this rowset
4907     * and the database. Both of these methods must be called before the
4908     * cursor moves to another row.
4909     *
4910     * @param columnIndex the first column is <code>1</code>, the second
4911     *        is <code>2</code>, and so on; must be <code>1</code> or larger
4912     *        and equal to or less than the number of columns in this rowset
4913     * @param x the new column value
4914     * @throws SQLException if (1) the given column index is out of bounds,
4915     *            (2) the cursor is not on one of this rowset's rows or its
4916     *            insert row, or (3) this rowset is
4917     *            <code>ResultSet.CONCUR_READ_ONLY</code>
4918     */
4919    public void updateObject(int columnIndex, Object x) throws SQLException {
4920        // sanity check.
4921        checkIndex(columnIndex);
4922        // make sure the cursor is on a valid row
4923        checkCursor();
4924
4925        getCurrentRow().setColumnObject(columnIndex, x);
4926    }
4927
4928    /**
4929     * Sets the designated nullable column in the current row or the
4930     * insert row of this <code>CachedRowSetImpl</code> object with
4931     * <code>null</code> value.
4932     * <P>
4933     * This method updates a column value in the current row or the insert
4934     * row of this rowset, but it does not update the database.
4935     * If the cursor is on a row in the rowset, the
4936     * method {@link #updateRow} must be called to update the database.
4937     * If the cursor is on the insert row, the method {@link #insertRow}
4938     * must be called, which will insert the new row into both this rowset
4939     * and the database.
4940     *
4941     * @param columnName a <code>String</code> object that must match the
4942     *        SQL name of a column in this rowset, ignoring case
4943     * @throws SQLException if (1) the given column name does not match the
4944     *            name of a column in this rowset, (2) the cursor is not on
4945     *            one of this rowset's rows or its insert row, or (3) this
4946     *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4947     */
4948    public void updateNull(String columnName) throws SQLException {
4949        updateNull(getColIdxByName(columnName));
4950    }
4951
4952    /**
4953     * Sets the designated column in either the current row or the insert
4954     * row of this <code>CachedRowSetImpl</code> object with the given
4955     * <code>boolean</code> value.
4956     * <P>
4957     * This method updates a column value in the current row or the insert
4958     * row of this rowset, but it does not update the database.
4959     * If the cursor is on a row in the rowset, the
4960     * method {@link #updateRow} must be called to update the database.
4961     * If the cursor is on the insert row, the method {@link #insertRow}
4962     * must be called, which will insert the new row into both this rowset
4963     * and the database. Both of these methods must be called before the
4964     * cursor moves to another row.
4965     *
4966     * @param columnName a <code>String</code> object that must match the
4967     *        SQL name of a column in this rowset, ignoring case
4968     * @param x the new column value
4969     * @throws SQLException if (1) the given column name does not match the
4970     *            name of a column in this rowset, (2) the cursor is not on
4971     *            one of this rowset's rows or its insert row, or (3) this
4972     *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4973     */
4974    public void updateBoolean(String columnName, boolean x) throws SQLException {
4975        updateBoolean(getColIdxByName(columnName), x);
4976    }
4977
4978    /**
4979     * Sets the designated column in either the current row or the insert
4980     * row of this <code>CachedRowSetImpl</code> object with the given
4981     * <code>byte</code> value.
4982     * <P>
4983     * This method updates a column value in the current row or the insert
4984     * row of this rowset, but it does not update the database.
4985     * If the cursor is on a row in the rowset, the
4986     * method {@link #updateRow} must be called to update the database.
4987     * If the cursor is on the insert row, the method {@link #insertRow}
4988     * must be called, which will insert the new row into both this rowset
4989     * and the database. Both of these methods must be called before the
4990     * cursor moves to another row.
4991     *
4992     * @param columnName a <code>String</code> object that must match the
4993     *        SQL name of a column in this rowset, ignoring case
4994     * @param x the new column value
4995     * @throws SQLException if (1) the given column name does not match the
4996     *            name of a column in this rowset, (2) the cursor is not on
4997     *            one of this rowset's rows or its insert row, or (3) this
4998     *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4999     */
5000    public void updateByte(String columnName, byte x) throws SQLException {
5001        updateByte(getColIdxByName(columnName), x);
5002    }
5003
5004    /**
5005     * Sets the designated column in either the current row or the insert
5006     * row of this <code>CachedRowSetImpl</code> object with the given
5007     * <code>short</code> value.
5008     * <P>
5009     * This method updates a column value in the current row or the insert
5010     * row of this rowset, but it does not update the database.
5011     * If the cursor is on a row in the rowset, the
5012     * method {@link #updateRow} must be called to update the database.
5013     * If the cursor is on the insert row, the method {@link #insertRow}
5014     * must be called, which will insert the new row into both this rowset
5015     * and the database. Both of these methods must be called before the
5016     * cursor moves to another row.
5017     *
5018     * @param columnName a <code>String</code> object that must match the
5019     *        SQL name of a column in this rowset, ignoring case
5020     * @param x the new column value
5021     * @throws SQLException if (1) the given column name does not match the
5022     *            name of a column in this rowset, (2) the cursor is not on
5023     *            one of this rowset's rows or its insert row, or (3) this
5024     *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5025     */
5026    public void updateShort(String columnName, short x) throws SQLException {
5027        updateShort(getColIdxByName(columnName), x);
5028    }
5029
5030    /**
5031     * Sets the designated column in either the current row or the insert
5032     * row of this <code>CachedRowSetImpl</code> object with the given
5033     * <code>int</code> value.
5034     * <P>
5035     * This method updates a column value in the current row or the insert
5036     * row of this rowset, but it does not update the database.
5037     * If the cursor is on a row in the rowset, the
5038     * method {@link #updateRow} must be called to update the database.
5039     * If the cursor is on the insert row, the method {@link #insertRow}
5040     * must be called, which will insert the new row into both this rowset
5041     * and the database. Both of these methods must be called before the
5042     * cursor moves to another row.
5043     *
5044     * @param columnName a <code>String</code> object that must match the
5045     *        SQL name of a column in this rowset, ignoring case
5046     * @param x the new column value
5047     * @throws SQLException if (1) the given column name does not match the
5048     *            name of a column in this rowset, (2) the cursor is not on
5049     *            one of this rowset's rows or its insert row, or (3) this
5050     *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5051     */
5052    public void updateInt(String columnName, int x) throws SQLException {
5053        updateInt(getColIdxByName(columnName), x);
5054    }
5055
5056    /**
5057     * Sets the designated column in either the current row or the insert
5058     * row of this <code>CachedRowSetImpl</code> object with the given
5059     * <code>long</code> value.
5060     * <P>
5061     * This method updates a column value in the current row or the insert
5062     * row of this rowset, but it does not update the database.
5063     * If the cursor is on a row in the rowset, the
5064     * method {@link #updateRow} must be called to update the database.
5065     * If the cursor is on the insert row, the method {@link #insertRow}
5066     * must be called, which will insert the new row into both this rowset
5067     * and the database. Both of these methods must be called before the
5068     * cursor moves to another row.
5069     *
5070     * @param columnName a <code>String</code> object that must match the
5071     *        SQL name of a column in this rowset, ignoring case
5072     * @param x the new column value
5073     * @throws SQLException if (1) the given column name does not match the
5074     *            name of a column in this rowset, (2) the cursor is not on
5075     *            one of this rowset's rows or its insert row, or (3) this
5076     *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5077     */
5078    public void updateLong(String columnName, long x) throws SQLException {
5079        updateLong(getColIdxByName(columnName), x);
5080    }
5081
5082    /**
5083     * Sets the designated column in either the current row or the insert
5084     * row of this <code>CachedRowSetImpl</code> object with the given
5085     * <code>float</code> value.
5086     * <P>
5087     * This method updates a column value in the current row or the insert
5088     * row of this rowset, but it does not update the database.
5089     * If the cursor is on a row in the rowset, the
5090     * method {@link #updateRow} must be called to update the database.
5091     * If the cursor is on the insert row, the method {@link #insertRow}
5092     * must be called, which will insert the new row into both this rowset
5093     * and the database. Both of these methods must be called before the
5094     * cursor moves to another row.
5095     *
5096     * @param columnName a <code>String</code> object that must match the
5097     *        SQL name of a column in this rowset, ignoring case
5098     * @param x the new column value
5099     * @throws SQLException if (1) the given column name does not match the
5100     *            name of a column in this rowset, (2) the cursor is not on
5101     *            one of this rowset's rows or its insert row, or (3) this
5102     *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5103     */
5104    public void updateFloat(String columnName, float x) throws SQLException {
5105        updateFloat(getColIdxByName(columnName), x);
5106    }
5107
5108    /**
5109     * Sets the designated column in either the current row or the insert
5110     * row of this <code>CachedRowSetImpl</code> object with the given
5111     * <code>double</code> value.
5112     *
5113     * This method updates a column value in either the current row or
5114     * the insert row of this rowset, but it does not update the
5115     * database.  If the cursor is on a row in the rowset, the
5116     * method {@link #updateRow} must be called to update the database.
5117     * If the cursor is on the insert row, the method {@link #insertRow}
5118     * must be called, which will insert the new row into both this rowset
5119     * and the database. Both of these methods must be called before the
5120     * cursor moves to another row.
5121     *
5122     * @param columnName a <code>String</code> object that must match the
5123     *        SQL name of a column in this rowset, ignoring case
5124     * @param x the new column value
5125     * @throws SQLException if (1) the given column name does not match the
5126     *            name of a column in this rowset, (2) the cursor is not on
5127     *            one of this rowset's rows or its insert row, or (3) this
5128     *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5129     */
5130    public void updateDouble(String columnName, double x) throws SQLException {
5131        updateDouble(getColIdxByName(columnName), x);
5132    }
5133
5134    /**
5135     * Sets the designated column in either the current row or the insert
5136     * row of this <code>CachedRowSetImpl</code> object with the given
5137     * <code>java.math.BigDecimal</code> object.
5138     * <P>
5139     * This method updates a column value in the current row or the insert
5140     * row of this rowset, but it does not update the database.
5141     * If the cursor is on a row in the rowset, the
5142     * method {@link #updateRow} must be called to update the database.
5143     * If the cursor is on the insert row, the method {@link #insertRow}
5144     * must be called, which will insert the new row into both this rowset
5145     * and the database. Both of these methods must be called before the
5146     * cursor moves to another row.
5147     *
5148     * @param columnName a <code>String</code> object that must match the
5149     *        SQL name of a column in this rowset, ignoring case
5150     * @param x the new column value
5151     * @throws SQLException if (1) the given column name does not match the
5152     *            name of a column in this rowset, (2) the cursor is not on
5153     *            one of this rowset's rows or its insert row, or (3) this
5154     *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5155     */
5156    public void updateBigDecimal(String columnName, BigDecimal x) throws SQLException {
5157        updateBigDecimal(getColIdxByName(columnName), x);
5158    }
5159
5160    /**
5161     * Sets the designated column in either the current row or the insert
5162     * row of this <code>CachedRowSetImpl</code> object with the given
5163     * <code>String</code> object.
5164     *
5165     * This method updates a column value in either the current row or
5166     * the insert row of this rowset, but it does not update the
5167     * database.  If the cursor is on a row in the rowset, the
5168     * method {@link #updateRow} must be called to update the database.
5169     * If the cursor is on the insert row, the method {@link #insertRow}
5170     * must be called, which will insert the new row into both this rowset
5171     * and the database. Both of these methods must be called before the
5172     * cursor moves to another row.
5173     *
5174     * @param columnName a <code>String</code> object that must match the
5175     *        SQL name of a column in this rowset, ignoring case
5176     * @param x the new column value
5177     * @throws SQLException if (1) the given column name does not match the
5178     *            name of a column in this rowset, (2) the cursor is not on
5179     *            one of this rowset's rows or its insert row, or (3) this
5180     *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5181     */
5182    public void updateString(String columnName, String x) throws SQLException {
5183        updateString(getColIdxByName(columnName), x);
5184    }
5185
5186    /**
5187     * Sets the designated column in either the current row or the insert
5188     * row of this <code>CachedRowSetImpl</code> object with the given
5189     * <code>byte</code> array.
5190     *
5191     * This method updates a column value in either the current row or
5192     * the insert row of this rowset, but it does not update the
5193     * database.  If the cursor is on a row in the rowset, the
5194     * method {@link #updateRow} must be called to update the database.
5195     * If the cursor is on the insert row, the method {@link #insertRow}
5196     * must be called, which will insert the new row into both this rowset
5197     * and the database. Both of these methods must be called before the
5198     * cursor moves to another row.
5199     *
5200     * @param columnName a <code>String</code> object that must match the
5201     *        SQL name of a column in this rowset, ignoring case
5202     * @param x the new column value
5203     * @throws SQLException if (1) the given column name does not match the
5204     *            name of a column in this rowset, (2) the cursor is not on
5205     *            one of this rowset's rows or its insert row, or (3) this
5206     *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5207     */
5208    public void updateBytes(String columnName, byte x[]) throws SQLException {
5209        updateBytes(getColIdxByName(columnName), x);
5210    }
5211
5212    /**
5213     * Sets the designated column in either the current row or the insert
5214     * row of this <code>CachedRowSetImpl</code> object with the given
5215     * <code>Date</code> object.
5216     *
5217     * This method updates a column value in either the current row or
5218     * the insert row of this rowset, but it does not update the
5219     * database.  If the cursor is on a row in the rowset, the
5220     * method {@link #updateRow} must be called to update the database.
5221     * If the cursor is on the insert row, the method {@link #insertRow}
5222     * must be called, which will insert the new row into both this rowset
5223     * and the database. Both of these methods must be called before the
5224     * cursor moves to another row.
5225     *
5226     * @param columnName a <code>String</code> object that must match the
5227     *        SQL name of a column in this rowset, ignoring case
5228     * @param x the new column value
5229     * @throws SQLException if (1) the given column name does not match the
5230     *            name of a column in this rowset, (2) the cursor is not on
5231     *            one of this rowset's rows or its insert row, (3) the type
5232     *            of the designated column is not an SQL <code>DATE</code> or
5233     *            <code>TIMESTAMP</code>, or (4) this rowset is
5234     *            <code>ResultSet.CONCUR_READ_ONLY</code>
5235     */
5236    public void updateDate(String columnName, java.sql.Date x) throws SQLException {
5237        updateDate(getColIdxByName(columnName), x);
5238    }
5239
5240    /**
5241     * Sets the designated column in either the current row or the insert
5242     * row of this <code>CachedRowSetImpl</code> object with the given
5243     * <code>Time</code> object.
5244     *
5245     * This method updates a column value in either the current row or
5246     * the insert row of this rowset, but it does not update the
5247     * database.  If the cursor is on a row in the rowset, the
5248     * method {@link #updateRow} must be called to update the database.
5249     * If the cursor is on the insert row, the method {@link #insertRow}
5250     * must be called, which will insert the new row into both this rowset
5251     * and the database. Both of these methods must be called before the
5252     * cursor moves to another row.
5253     *
5254     * @param columnName a <code>String</code> object that must match the
5255     *        SQL name of a column in this rowset, ignoring case
5256     * @param x the new column value
5257     * @throws SQLException if (1) the given column name does not match the
5258     *            name of a column in this rowset, (2) the cursor is not on
5259     *            one of this rowset's rows or its insert row, (3) the type
5260     *            of the designated column is not an SQL <code>TIME</code> or
5261     *            <code>TIMESTAMP</code>, or (4) this rowset is
5262     *            <code>ResultSet.CONCUR_READ_ONLY</code>
5263     */
5264    public void updateTime(String columnName, java.sql.Time x) throws SQLException {
5265        updateTime(getColIdxByName(columnName), x);
5266    }
5267
5268    /**
5269     * Sets the designated column in either the current row or the insert
5270     * row of this <code>CachedRowSetImpl</code> object with the given
5271     * <code>Timestamp</code> object.
5272     *
5273     * This method updates a column value in either the current row or
5274     * the insert row of this rowset, but it does not update the
5275     * database.  If the cursor is on a row in the rowset, the
5276     * method {@link #updateRow} must be called to update the database.
5277     * If the cursor is on the insert row, the method {@link #insertRow}
5278     * must be called, which will insert the new row into both this rowset
5279     * and the database. Both of these methods must be called before the
5280     * cursor moves to another row.
5281     *
5282     * @param columnName a <code>String</code> object that must match the
5283     *        SQL name of a column in this rowset, ignoring case
5284     * @param x the new column value
5285     * @throws SQLException if the given column index is out of bounds or
5286     *            the cursor is not on one of this rowset's rows or its
5287     *            insert row
5288     * @throws SQLException if (1) the given column name does not match the
5289     *            name of a column in this rowset, (2) the cursor is not on
5290     *            one of this rowset's rows or its insert row, (3) the type
5291     *            of the designated column is not an SQL <code>DATE</code>,
5292     *            <code>TIME</code>, or <code>TIMESTAMP</code>, or (4) this
5293     *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5294     */
5295    public void updateTimestamp(String columnName, java.sql.Timestamp x) throws SQLException {
5296        updateTimestamp(getColIdxByName(columnName), x);
5297    }
5298
5299    /**
5300     * Sets the designated column in either the current row or the insert
5301     * row of this <code>CachedRowSetImpl</code> object with the given
5302     * ASCII stream value.
5303     * <P>
5304     * This method updates a column value in either the current row or
5305     * the insert row of this rowset, but it does not update the
5306     * database.  If the cursor is on a row in the rowset, the
5307     * method {@link #updateRow} must be called to update the database.
5308     * If the cursor is on the insert row, the method {@link #insertRow}
5309     * must be called, which will insert the new row into both this rowset
5310     * and the database. Both of these methods must be called before the
5311     * cursor moves to another row.
5312     *
5313     * @param columnName a <code>String</code> object that must match the
5314     *        SQL name of a column in this rowset, ignoring case
5315     * @param x the new column value
5316     * @param length the number of one-byte ASCII characters in the stream
5317     */
5318    public void updateAsciiStream(String columnName,
5319    java.io.InputStream x,
5320    int length) throws SQLException {
5321        updateAsciiStream(getColIdxByName(columnName), x, length);
5322    }
5323
5324    /**
5325     * Sets the designated column in either the current row or the insert
5326     * row of this <code>CachedRowSetImpl</code> object with the given
5327     * <code>java.io.InputStream</code> object.
5328     * <P>
5329     * This method updates a column value in either the current row or
5330     * the insert row of this rowset, but it does not update the
5331     * database.  If the cursor is on a row in the rowset, the
5332     * method {@link #updateRow} must be called to update the database.
5333     * If the cursor is on the insert row, the method {@link #insertRow}
5334     * must be called, which will insert the new row into both this rowset
5335     * and the database. Both of these methods must be called before the
5336     * cursor moves to another row.
5337     *
5338     * @param columnName a <code>String</code> object that must match the
5339     *        SQL name of a column in this rowset, ignoring case
5340     * @param x the new column value; must be a <code>java.io.InputStream</code>
5341     *          containing <code>BINARY</code>, <code>VARBINARY</code>, or
5342     *          <code>LONGVARBINARY</code> data
5343     * @param length the length of the stream in bytes
5344     * @throws SQLException if (1) the given column name does not match the
5345     *            name of a column in this rowset, (2) the cursor is not on
5346     *            one of this rowset's rows or its insert row, (3) the data
5347     *            in the stream is not binary, or (4) this rowset is
5348     *            <code>ResultSet.CONCUR_READ_ONLY</code>
5349     */
5350    public void updateBinaryStream(String columnName, java.io.InputStream x, int length) throws SQLException {
5351        updateBinaryStream(getColIdxByName(columnName), x, length);
5352    }
5353
5354    /**
5355     * Sets the designated column in either the current row or the insert
5356     * row of this <code>CachedRowSetImpl</code> object with the given
5357     * <code>java.io.Reader</code> object.
5358     * <P>
5359     * This method updates a column value in either the current row or
5360     * the insert row of this rowset, but it does not update the
5361     * database.  If the cursor is on a row in the rowset, the
5362     * method {@link #updateRow} must be called to update the database.
5363     * If the cursor is on the insert row, the method {@link #insertRow}
5364     * must be called, which will insert the new row into both this rowset
5365     * and the database. Both of these methods must be called before the
5366     * cursor moves to another row.
5367     *
5368     * @param columnName a <code>String</code> object that must match the
5369     *        SQL name of a column in this rowset, ignoring case
5370     * @param reader the new column value; must be a
5371     * <code>java.io.Reader</code> containing <code>BINARY</code>,
5372     * <code>VARBINARY</code>, <code>LONGVARBINARY</code>, <code>CHAR</code>,
5373     * <code>VARCHAR</code>, or <code>LONGVARCHAR</code> data
5374     * @param length the length of the stream in characters
5375     * @throws SQLException if (1) the given column name does not match the
5376     *            name of a column in this rowset, (2) the cursor is not on
5377     *            one of this rowset's rows or its insert row, (3) the data
5378     *            in the stream is not a binary or character type, or (4) this
5379     *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5380     */
5381    public void updateCharacterStream(String columnName,
5382    java.io.Reader reader,
5383    int length) throws SQLException {
5384        updateCharacterStream(getColIdxByName(columnName), reader, length);
5385    }
5386
5387    /**
5388     * Sets the designated column in either the current row or the insert
5389     * row of this <code>CachedRowSetImpl</code> object with the given
5390     * <code>Object</code> value.  The <code>scale</code> parameter
5391     * indicates the number of digits to the right of the decimal point
5392     * and is ignored if the new column value is not a type that will be
5393     *  mapped to an SQL <code>DECIMAL</code> or <code>NUMERIC</code> value.
5394     * <P>
5395     * This method updates a column value in either the current row or
5396     * the insert row of this rowset, but it does not update the
5397     * database.  If the cursor is on a row in the rowset, the
5398     * method {@link #updateRow} must be called to update the database.
5399     * If the cursor is on the insert row, the method {@link #insertRow}
5400     * must be called, which will insert the new row into both this rowset
5401     * and the database. Both of these methods must be called before the
5402     * cursor moves to another row.
5403     *
5404     * @param columnName a <code>String</code> object that must match the
5405     *        SQL name of a column in this rowset, ignoring case
5406     * @param x the new column value
5407     * @param scale the number of digits to the right of the decimal point (for
5408     *              <code>DECIMAL</code> and <code>NUMERIC</code> types only)
5409     * @throws SQLException if (1) the given column name does not match the
5410     *            name of a column in this rowset, (2) the cursor is not on
5411     *            one of this rowset's rows or its insert row, or (3) this
5412     *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5413     */
5414    public void updateObject(String columnName, Object x, int scale) throws SQLException {
5415        updateObject(getColIdxByName(columnName), x, scale);
5416    }
5417
5418    /**
5419     * Sets the designated column in either the current row or the insert
5420     * row of this <code>CachedRowSetImpl</code> object with the given
5421     * <code>Object</code> value.
5422     * <P>
5423     * This method updates a column value in either the current row or
5424     * the insert row of this rowset, but it does not update the
5425     * database.  If the cursor is on a row in the rowset, the
5426     * method {@link #updateRow} must be called to update the database.
5427     * If the cursor is on the insert row, the method {@link #insertRow}
5428     * must be called, which will insert the new row into both this rowset
5429     * and the database. Both of these methods must be called before the
5430     * cursor moves to another row.
5431     *
5432     * @param columnName a <code>String</code> object that must match the
5433     *        SQL name of a column in this rowset, ignoring case
5434     * @param x the new column value
5435     * @throws SQLException if (1) the given column name does not match the
5436     *            name of a column in this rowset, (2) the cursor is not on
5437     *            one of this rowset's rows or its insert row, or (3) this
5438     *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5439     */
5440    public void updateObject(String columnName, Object x) throws SQLException {
5441        updateObject(getColIdxByName(columnName), x);
5442    }
5443
5444    /**
5445     * Inserts the contents of this <code>CachedRowSetImpl</code> object's insert
5446     * row into this rowset immediately following the current row.
5447     * If the current row is the
5448     * position after the last row or before the first row, the new row will
5449     * be inserted at the end of the rowset.  This method also notifies
5450     * listeners registered with this rowset that the row has changed.
5451     * <P>
5452     * The cursor must be on the insert row when this method is called.
5453     *
5454     * @throws SQLException if (1) the cursor is not on the insert row,
5455     *            (2) one or more of the non-nullable columns in the insert
5456     *            row has not been given a value, or (3) this rowset is
5457     *            <code>ResultSet.CONCUR_READ_ONLY</code>
5458     */
5459    public void insertRow() throws SQLException {
5460        int pos;
5461
5462        if (onInsertRow == false ||
5463            insertRow.isCompleteRow(RowSetMD) == false) {
5464                throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.failedins").toString());
5465        }
5466        // Added the setting of parameters that are passed
5467        // to setXXX methods after an empty CRS Object is
5468        // created through RowSetMetaData object
5469        Object [] toInsert = getParams();
5470
5471        for(int i = 0;i < toInsert.length; i++) {
5472          insertRow.setColumnObject(i+1,toInsert[i]);
5473        }
5474
5475        Row insRow = new Row(RowSetMD.getColumnCount(),
5476        insertRow.getOrigRow());
5477        insRow.setInserted();
5478        /*
5479         * The new row is inserted into the RowSet
5480         * immediately following the current row.
5481         *
5482         * If we are afterlast then the rows are
5483         * inserted at the end.
5484         */
5485        if (currentRow >= numRows || currentRow < 0) {
5486            pos = numRows;
5487        } else {
5488            pos = currentRow;
5489        }
5490
5491        rvh.add(pos, insRow);
5492        ++numRows;
5493        // notify the listeners that the row changed.
5494        notifyRowChanged();
5495    }
5496
5497    /**
5498     * Marks the current row of this <code>CachedRowSetImpl</code> object as
5499     * updated and notifies listeners registered with this rowset that the
5500     * row has changed.
5501     * <P>
5502     * This method  cannot be called when the cursor is on the insert row, and
5503     * it should be called before the cursor moves to another row.  If it is
5504     * called after the cursor moves to another row, this method has no effect,
5505     * and the updates made before the cursor moved will be lost.
5506     *
5507     * @throws SQLException if the cursor is on the insert row or this
5508     *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
5509     */
5510    public void updateRow() throws SQLException {
5511        // make sure we aren't on the insert row
5512        if (onInsertRow == true) {
5513            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.updateins").toString());
5514        }
5515
5516        ((Row)getCurrentRow()).setUpdated();
5517
5518        // notify the listeners that the row changed.
5519        notifyRowChanged();
5520    }
5521
5522    /**
5523     * Deletes the current row from this <code>CachedRowSetImpl</code> object and
5524     * notifies listeners registered with this rowset that a row has changed.
5525     * This method cannot be called when the cursor is on the insert row.
5526     * <P>
5527     * This method marks the current row as deleted, but it does not delete
5528     * the row from the underlying data source.  The method
5529     * <code>acceptChanges</code> must be called to delete the row in
5530     * the data source.
5531     *
5532     * @throws SQLException if (1) this method is called when the cursor
5533     *            is on the insert row, before the first row, or after the
5534     *            last row or (2) this rowset is
5535     *            <code>ResultSet.CONCUR_READ_ONLY</code>
5536     */
5537    public void deleteRow() throws SQLException {
5538        // make sure the cursor is on a valid row
5539        checkCursor();
5540
5541        ((Row)getCurrentRow()).setDeleted();
5542        ++numDeleted;
5543
5544        // notify the listeners that the row changed.
5545        notifyRowChanged();
5546    }
5547
5548    /**
5549     * Sets the current row with its original value and marks the row as
5550     * not updated, thus undoing any changes made to the row since the
5551     * last call to the methods <code>updateRow</code> or <code>deleteRow</code>.
5552     * This method should be called only when the cursor is on a row in
5553     * this rowset.
5554     *
5555     * @throws SQLException if the cursor is on the insert row, before the
5556     *            first row, or after the last row
5557     */
5558    public void refreshRow() throws SQLException {
5559        // make sure we are on a row
5560        checkCursor();
5561
5562        // don't want this to happen...
5563        if (onInsertRow == true) {
5564            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
5565        }
5566
5567        Row currentRow = (Row)getCurrentRow();
5568        // just undo any changes made to this row.
5569        currentRow.clearUpdated();
5570
5571    }
5572
5573    /**
5574     * Rolls back any updates made to the current row of this
5575     * <code>CachedRowSetImpl</code> object and notifies listeners that
5576     * a row has changed.  To have an effect, this method
5577     * must be called after an <code>updateXXX</code> method has been
5578     * called and before the method <code>updateRow</code> has been called.
5579     * If no updates have been made or the method <code>updateRow</code>
5580     * has already been called, this method has no effect.
5581     *
5582     * @throws SQLException if the cursor is on the insert row, before the
5583     *            first row, or after the last row
5584     */
5585    public void cancelRowUpdates() throws SQLException {
5586        // make sure we are on a row
5587        checkCursor();
5588
5589        // don't want this to happen...
5590        if (onInsertRow == true) {
5591            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
5592        }
5593
5594        Row currentRow = (Row)getCurrentRow();
5595        if (currentRow.getUpdated() == true) {
5596            currentRow.clearUpdated();
5597            notifyRowChanged();
5598        }
5599    }
5600
5601    /**
5602     * Moves the cursor for this <code>CachedRowSetImpl</code> object
5603     * to the insert row.  The current row in the rowset is remembered
5604     * while the cursor is on the insert row.
5605     * <P>
5606     * The insert row is a special row associated with an updatable
5607     * rowset.  It is essentially a buffer where a new row may
5608     * be constructed by calling the appropriate <code>updateXXX</code>
5609     * methods to assign a value to each column in the row.  A complete
5610     * row must be constructed; that is, every column that is not nullable
5611     * must be assigned a value.  In order for the new row to become part
5612     * of this rowset, the method <code>insertRow</code> must be called
5613     * before the cursor is moved back to the rowset.
5614     * <P>
5615     * Only certain methods may be invoked while the cursor is on the insert
5616     * row; many methods throw an exception if they are called while the
5617     * cursor is there.  In addition to the <code>updateXXX</code>
5618     * and <code>insertRow</code> methods, only the <code>getXXX</code> methods
5619     * may be called when the cursor is on the insert row.  A <code>getXXX</code>
5620     * method should be called on a column only after an <code>updateXXX</code>
5621     * method has been called on that column; otherwise, the value returned is
5622     * undetermined.
5623     *
5624     * @throws SQLException if this <code>CachedRowSetImpl</code> object is
5625     *            <code>ResultSet.CONCUR_READ_ONLY</code>
5626     */
5627    public void moveToInsertRow() throws SQLException {
5628        if (getConcurrency() == ResultSet.CONCUR_READ_ONLY) {
5629            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins").toString());
5630        }
5631        if (insertRow == null) {
5632            if (RowSetMD == null)
5633                throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins1").toString());
5634            int numCols = RowSetMD.getColumnCount();
5635            if (numCols > 0) {
5636                insertRow = new InsertRow(numCols);
5637            } else {
5638                throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.movetoins2").toString());
5639            }
5640        }
5641        onInsertRow = true;
5642        // %%% setCurrentRow called in BaseRow
5643
5644        currentRow = cursorPos;
5645        cursorPos = -1;
5646
5647        insertRow.initInsertRow();
5648    }
5649
5650    /**
5651     * Moves the cursor for this <code>CachedRowSetImpl</code> object to
5652     * the current row.  The current row is the row the cursor was on
5653     * when the method <code>moveToInsertRow</code> was called.
5654     * <P>
5655     * Calling this method has no effect unless it is called while the
5656     * cursor is on the insert row.
5657     *
5658     * @throws SQLException if an error occurs
5659     */
5660    public void moveToCurrentRow() throws SQLException {
5661        if (onInsertRow == false) {
5662            return;
5663        } else {
5664            cursorPos = currentRow;
5665            onInsertRow = false;
5666        }
5667    }
5668
5669    /**
5670     * Returns <code>null</code>.
5671     *
5672     * @return <code>null</code>
5673     * @throws SQLException if an error occurs
5674     */
5675    public Statement getStatement() throws SQLException {
5676        return null;
5677    }
5678
5679    /**
5680     * Retrieves the value of the designated column in this
5681     * <code>CachedRowSetImpl</code> object as an <code>Object</code> in
5682     * the Java programming language, using the given
5683     * <code>java.util.Map</code> object to custom map the value if
5684     * appropriate.
5685     *
5686     * @param columnIndex the first column is <code>1</code>, the second
5687     *        is <code>2</code>, and so on; must be <code>1</code> or larger
5688     *        and equal to or less than the number of columns in this rowset
5689     * @param map a <code>java.util.Map</code> object showing the mapping
5690     *            from SQL type names to classes in the Java programming
5691     *            language
5692     * @return an <code>Object</code> representing the SQL value
5693     * @throws SQLException if the given column index is out of bounds or
5694     *            the cursor is not on one of this rowset's rows or its
5695     *            insert row
5696     */
5697     public Object getObject(int columnIndex,
5698                             java.util.Map<String,Class<?>> map)
5699         throws SQLException
5700     {
5701        Object value;
5702
5703        // sanity check.
5704        checkIndex(columnIndex);
5705        // make sure the cursor is on a valid row
5706        checkCursor();
5707
5708        setLastValueNull(false);
5709        value = getCurrentRow().getColumnObject(columnIndex);
5710
5711        // check for SQL NULL
5712        if (value == null) {
5713            setLastValueNull(true);
5714            return null;
5715        }
5716        if (value instanceof Struct) {
5717            Struct s = (Struct)value;
5718
5719            // look up the class in the map
5720            Class<?> c = map.get(s.getSQLTypeName());
5721            if (c != null) {
5722                // create new instance of the class
5723                SQLData obj = null;
5724                try {
5725                    ReflectUtil.checkPackageAccess(c);
5726                    @SuppressWarnings("deprecation")
5727                    Object tmp = c.newInstance();
5728                    obj = (SQLData) tmp;
5729                } catch(Exception ex) {
5730                    throw new SQLException("Unable to Instantiate: ", ex);
5731                }
5732                // get the attributes from the struct
5733                Object attribs[] = s.getAttributes(map);
5734                // create the SQLInput "stream"
5735                SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
5736                // read the values...
5737                obj.readSQL(sqlInput, s.getSQLTypeName());
5738                return (Object)obj;
5739            }
5740        }
5741        return value;
5742    }
5743
5744    /**
5745     * Retrieves the value of the designated column in this
5746     * <code>CachedRowSetImpl</code> object as a <code>Ref</code> object
5747     * in the Java programming language.
5748     *
5749     * @param columnIndex the first column is <code>1</code>, the second
5750     *        is <code>2</code>, and so on; must be <code>1</code> or larger
5751     *        and equal to or less than the number of columns in this rowset
5752     * @return a <code>Ref</code> object representing an SQL<code> REF</code> value
5753     * @throws SQLException if (1) the given column index is out of bounds,
5754     *            (2) the cursor is not on one of this rowset's rows or its
5755     *            insert row, or (3) the designated column does not store an
5756     *            SQL <code>REF</code> value
5757     * @see #getRef(String)
5758     */
5759    public Ref getRef(int columnIndex) throws SQLException {
5760        Ref value;
5761
5762        // sanity check.
5763        checkIndex(columnIndex);
5764        // make sure the cursor is on a valid row
5765        checkCursor();
5766
5767        if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.REF) {
5768            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5769        }
5770
5771        setLastValueNull(false);
5772        value = (Ref)(getCurrentRow().getColumnObject(columnIndex));
5773
5774        // check for SQL NULL
5775        if (value == null) {
5776            setLastValueNull(true);
5777            return null;
5778        }
5779
5780        return value;
5781    }
5782
5783    /**
5784     * Retrieves the value of the designated column in this
5785     * <code>CachedRowSetImpl</code> object as a <code>Blob</code> object
5786     * in the Java programming language.
5787     *
5788     * @param columnIndex the first column is <code>1</code>, the second
5789     *        is <code>2</code>, and so on; must be <code>1</code> or larger
5790     *        and equal to or less than the number of columns in this rowset
5791     * @return a <code>Blob</code> object representing an SQL <code>BLOB</code> value
5792     * @throws SQLException if (1) the given column index is out of bounds,
5793     *            (2) the cursor is not on one of this rowset's rows or its
5794     *            insert row, or (3) the designated column does not store an
5795     *            SQL <code>BLOB</code> value
5796     * @see #getBlob(String)
5797     */
5798    public Blob getBlob(int columnIndex) throws SQLException {
5799        Blob value;
5800
5801        // sanity check.
5802        checkIndex(columnIndex);
5803        // make sure the cursor is on a valid row
5804        checkCursor();
5805
5806        if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.BLOB) {
5807            System.out.println(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.type").toString(), RowSetMD.getColumnType(columnIndex)));
5808            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5809        }
5810
5811        setLastValueNull(false);
5812        value = (Blob)(getCurrentRow().getColumnObject(columnIndex));
5813
5814        // check for SQL NULL
5815        if (value == null) {
5816            setLastValueNull(true);
5817            return null;
5818        }
5819
5820        return value;
5821    }
5822
5823    /**
5824     * Retrieves the value of the designated column in this
5825     * <code>CachedRowSetImpl</code> object as a <code>Clob</code> object
5826     * in the Java programming language.
5827     *
5828     * @param columnIndex the first column is <code>1</code>, the second
5829     *        is <code>2</code>, and so on; must be <code>1</code> or larger
5830     *        and equal to or less than the number of columns in this rowset
5831     * @return a <code>Clob</code> object representing an SQL <code>CLOB</code> value
5832     * @throws SQLException if (1) the given column index is out of bounds,
5833     *            (2) the cursor is not on one of this rowset's rows or its
5834     *            insert row, or (3) the designated column does not store an
5835     *            SQL <code>CLOB</code> value
5836     * @see #getClob(String)
5837     */
5838    public Clob getClob(int columnIndex) throws SQLException {
5839        Clob value;
5840
5841        // sanity check.
5842        checkIndex(columnIndex);
5843        // make sure the cursor is on a valid row
5844        checkCursor();
5845
5846        if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.CLOB) {
5847            System.out.println(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.type").toString(), RowSetMD.getColumnType(columnIndex)));
5848            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5849        }
5850
5851        setLastValueNull(false);
5852        value = (Clob)(getCurrentRow().getColumnObject(columnIndex));
5853
5854        // check for SQL NULL
5855        if (value == null) {
5856            setLastValueNull(true);
5857            return null;
5858        }
5859
5860        return value;
5861    }
5862
5863    /**
5864     * Retrieves the value of the designated column in this
5865     * <code>CachedRowSetImpl</code> object as an <code>Array</code> object
5866     * in the Java programming language.
5867     *
5868     * @param columnIndex the first column is <code>1</code>, the second
5869     *        is <code>2</code>, and so on; must be <code>1</code> or larger
5870     *        and equal to or less than the number of columns in this rowset
5871     * @return an <code>Array</code> object representing an SQL
5872     *         <code>ARRAY</code> value
5873     * @throws SQLException if (1) the given column index is out of bounds,
5874     *            (2) the cursor is not on one of this rowset's rows or its
5875     *            insert row, or (3) the designated column does not store an
5876     *            SQL <code>ARRAY</code> value
5877     * @see #getArray(String)
5878     */
5879    public Array getArray(int columnIndex) throws SQLException {
5880        java.sql.Array value;
5881
5882        // sanity check.
5883        checkIndex(columnIndex);
5884        // make sure the cursor is on a valid row
5885        checkCursor();
5886
5887        if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.ARRAY) {
5888            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
5889        }
5890
5891        setLastValueNull(false);
5892        value = (java.sql.Array)(getCurrentRow().getColumnObject(columnIndex));
5893
5894        // check for SQL NULL
5895        if (value == null) {
5896            setLastValueNull(true);
5897            return null;
5898        }
5899
5900        return value;
5901    }
5902
5903    /**
5904     * Retrieves the value of the designated column in this
5905     * <code>CachedRowSetImpl</code> object as an <code>Object</code> in
5906     * the Java programming language, using the given
5907     * <code>java.util.Map</code> object to custom map the value if
5908     * appropriate.
5909     *
5910     * @param columnName a <code>String</code> object that must match the
5911     *        SQL name of a column in this rowset, ignoring case
5912     * @param map a <code>java.util.Map</code> object showing the mapping
5913     *        from SQL type names to classes in the Java programming
5914     *        language
5915     * @return an <code>Object</code> representing the SQL value
5916     * @throws SQLException if the given column name is not the name of
5917     *         a column in this rowset or the cursor is not on one of
5918     *         this rowset's rows or its insert row
5919     */
5920    public Object getObject(String columnName,
5921                            java.util.Map<String,Class<?>> map)
5922    throws SQLException {
5923        return getObject(getColIdxByName(columnName), map);
5924    }
5925
5926    /**
5927     * Retrieves the value of the designated column in this
5928     * <code>CachedRowSetImpl</code> object as a <code>Ref</code> object
5929     * in the Java programming language.
5930     *
5931     * @param colName a <code>String</code> object that must match the
5932     *        SQL name of a column in this rowset, ignoring case
5933     * @return a <code>Ref</code> object representing an SQL<code> REF</code> value
5934     * @throws SQLException  if (1) the given column name is not the name of
5935     *            a column in this rowset, (2) the cursor is not on one of
5936     *            this rowset's rows or its insert row, or (3) the column value
5937     *            is not an SQL <code>REF</code> value
5938     * @see #getRef(int)
5939     */
5940    public Ref getRef(String colName) throws SQLException {
5941        return getRef(getColIdxByName(colName));
5942    }
5943
5944    /**
5945     * Retrieves the value of the designated column in this
5946     * <code>CachedRowSetImpl</code> object as a <code>Blob</code> object
5947     * in the Java programming language.
5948     *
5949     * @param colName a <code>String</code> object that must match the
5950     *        SQL name of a column in this rowset, ignoring case
5951     * @return a <code>Blob</code> object representing an SQL <code>BLOB</code> value
5952     * @throws SQLException if (1) the given column name is not the name of
5953     *            a column in this rowset, (2) the cursor is not on one of
5954     *            this rowset's rows or its insert row, or (3) the designated
5955     *            column does not store an SQL <code>BLOB</code> value
5956     * @see #getBlob(int)
5957     */
5958    public Blob getBlob(String colName) throws SQLException {
5959        return getBlob(getColIdxByName(colName));
5960    }
5961
5962    /**
5963     * Retrieves the value of the designated column in this
5964     * <code>CachedRowSetImpl</code> object as a <code>Clob</code> object
5965     * in the Java programming language.
5966     *
5967     * @param colName a <code>String</code> object that must match the
5968     *        SQL name of a column in this rowset, ignoring case
5969     * @return a <code>Clob</code> object representing an SQL
5970     *         <code>CLOB</code> value
5971     * @throws SQLException if (1) the given column name is not the name of
5972     *            a column in this rowset, (2) the cursor is not on one of
5973     *            this rowset's rows or its insert row, or (3) the designated
5974     *            column does not store an SQL <code>CLOB</code> value
5975     * @see #getClob(int)
5976     */
5977    public Clob getClob(String colName) throws SQLException {
5978        return getClob(getColIdxByName(colName));
5979    }
5980
5981    /**
5982     * Retrieves the value of the designated column in this
5983     * <code>CachedRowSetImpl</code> object as an <code>Array</code> object
5984     * in the Java programming langugage.
5985     *
5986     * @param colName a <code>String</code> object that must match the
5987     *        SQL name of a column in this rowset, ignoring case
5988     * @return an <code>Array</code> object representing an SQL
5989     *         <code>ARRAY</code> value
5990     * @throws SQLException if (1) the given column name is not the name of
5991     *            a column in this rowset, (2) the cursor is not on one of
5992     *            this rowset's rows or its insert row, or (3) the designated
5993     *            column does not store an SQL <code>ARRAY</code> value
5994     * @see #getArray(int)
5995     */
5996    public Array getArray(String colName) throws SQLException {
5997        return getArray(getColIdxByName(colName));
5998    }
5999
6000    /**
6001     * Retrieves the value of the designated column in the current row
6002     * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Date</code>
6003     * object, using the given <code>Calendar</code> object to construct an
6004     * appropriate millisecond value for the date.
6005     *
6006     * @param columnIndex the first column is <code>1</code>, the second
6007     *        is <code>2</code>, and so on; must be <code>1</code> or larger
6008     *        and equal to or less than the number of columns in the rowset
6009     * @param cal the <code>java.util.Calendar</code> object to use in
6010     *            constructing the date
6011     * @return the column value; if the value is SQL <code>NULL</code>,
6012     *         the result is <code>null</code>
6013     * @throws SQLException if (1) the given column name is not the name of
6014     *            a column in this rowset, (2) the cursor is not on one of
6015     *            this rowset's rows or its insert row, or (3) the designated
6016     *            column does not store an SQL <code>DATE</code> or
6017     *            <code>TIMESTAMP</code> value
6018     */
6019    public java.sql.Date getDate(int columnIndex, Calendar cal) throws SQLException {
6020        Object value;
6021
6022        // sanity check.
6023        checkIndex(columnIndex);
6024        // make sure the cursor is on a valid row
6025        checkCursor();
6026
6027        setLastValueNull(false);
6028        value = getCurrentRow().getColumnObject(columnIndex);
6029
6030        // check for SQL NULL
6031        if (value == null) {
6032            setLastValueNull(true);
6033            return null;
6034        }
6035
6036        value = convertTemporal(value,
6037        RowSetMD.getColumnType(columnIndex),
6038        java.sql.Types.DATE);
6039
6040        // create a default calendar
6041        Calendar defaultCal = Calendar.getInstance();
6042        // set this Calendar to the time we have
6043        defaultCal.setTime((java.util.Date)value);
6044
6045        /*
6046         * Now we can pull the pieces of the date out
6047         * of the default calendar and put them into
6048         * the user provided calendar
6049         */
6050        cal.set(Calendar.YEAR, defaultCal.get(Calendar.YEAR));
6051        cal.set(Calendar.MONTH, defaultCal.get(Calendar.MONTH));
6052        cal.set(Calendar.DAY_OF_MONTH, defaultCal.get(Calendar.DAY_OF_MONTH));
6053
6054        /*
6055         * This looks a little odd but it is correct -
6056         * Calendar.getTime() returns a Date...
6057         */
6058        return new java.sql.Date(cal.getTime().getTime());
6059    }
6060
6061    /**
6062     * Retrieves the value of the designated column in the current row
6063     * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Date</code>
6064     * object, using the given <code>Calendar</code> object to construct an
6065     * appropriate millisecond value for the date.
6066     *
6067     * @param columnName a <code>String</code> object that must match the
6068     *        SQL name of a column in this rowset, ignoring case
6069     * @param cal the <code>java.util.Calendar</code> object to use in
6070     *            constructing the date
6071     * @return the column value; if the value is SQL <code>NULL</code>,
6072     *         the result is <code>null</code>
6073     * @throws SQLException if (1) the given column name is not the name of
6074     *            a column in this rowset, (2) the cursor is not on one of
6075     *            this rowset's rows or its insert row, or (3) the designated
6076     *            column does not store an SQL <code>DATE</code> or
6077     *            <code>TIMESTAMP</code> value
6078     */
6079    public java.sql.Date getDate(String columnName, Calendar cal) throws SQLException {
6080        return getDate(getColIdxByName(columnName), cal);
6081    }
6082
6083    /**
6084     * Retrieves the value of the designated column in the current row
6085     * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Time</code>
6086     * object, using the given <code>Calendar</code> object to construct an
6087     * appropriate millisecond value for the date.
6088     *
6089     * @param columnIndex the first column is <code>1</code>, the second
6090     *        is <code>2</code>, and so on; must be <code>1</code> or larger
6091     *        and equal to or less than the number of columns in the rowset
6092     * @param cal the <code>java.util.Calendar</code> object to use in
6093     *            constructing the date
6094     * @return the column value; if the value is SQL <code>NULL</code>,
6095     *         the result is <code>null</code>
6096     * @throws SQLException if (1) the given column name is not the name of
6097     *            a column in this rowset, (2) the cursor is not on one of
6098     *            this rowset's rows or its insert row, or (3) the designated
6099     *            column does not store an SQL <code>TIME</code> or
6100     *            <code>TIMESTAMP</code> value
6101     */
6102    public java.sql.Time getTime(int columnIndex, Calendar cal) throws SQLException {
6103        Object value;
6104
6105        // sanity check.
6106        checkIndex(columnIndex);
6107        // make sure the cursor is on a valid row
6108        checkCursor();
6109
6110        setLastValueNull(false);
6111        value = getCurrentRow().getColumnObject(columnIndex);
6112
6113        // check for SQL NULL
6114        if (value == null) {
6115            setLastValueNull(true);
6116            return null;
6117        }
6118
6119        value = convertTemporal(value,
6120        RowSetMD.getColumnType(columnIndex),
6121        java.sql.Types.TIME);
6122
6123        // create a default calendar
6124        Calendar defaultCal = Calendar.getInstance();
6125        // set the time in the default calendar
6126        defaultCal.setTime((java.util.Date)value);
6127
6128        /*
6129         * Now we can pull the pieces of the date out
6130         * of the default calendar and put them into
6131         * the user provided calendar
6132         */
6133        cal.set(Calendar.HOUR_OF_DAY, defaultCal.get(Calendar.HOUR_OF_DAY));
6134        cal.set(Calendar.MINUTE, defaultCal.get(Calendar.MINUTE));
6135        cal.set(Calendar.SECOND, defaultCal.get(Calendar.SECOND));
6136
6137        return new java.sql.Time(cal.getTime().getTime());
6138    }
6139
6140    /**
6141     * Retrieves the value of the designated column in the current row
6142     * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Time</code>
6143     * object, using the given <code>Calendar</code> object to construct an
6144     * appropriate millisecond value for the date.
6145     *
6146     * @param columnName a <code>String</code> object that must match the
6147     *        SQL name of a column in this rowset, ignoring case
6148     * @param cal the <code>java.util.Calendar</code> object to use in
6149     *            constructing the date
6150     * @return the column value; if the value is SQL <code>NULL</code>,
6151     *         the result is <code>null</code>
6152     * @throws SQLException if (1) the given column name is not the name of
6153     *            a column in this rowset, (2) the cursor is not on one of
6154     *            this rowset's rows or its insert row, or (3) the designated
6155     *            column does not store an SQL <code>TIME</code> or
6156     *            <code>TIMESTAMP</code> value
6157     */
6158    public java.sql.Time getTime(String columnName, Calendar cal) throws SQLException {
6159        return getTime(getColIdxByName(columnName), cal);
6160    }
6161
6162    /**
6163     * Retrieves the value of the designated column in the current row
6164     * of this <code>CachedRowSetImpl</code> object as a <code>java.sql.Timestamp</code>
6165     * object, using the given <code>Calendar</code> object to construct an
6166     * appropriate millisecond value for the date.
6167     *
6168     * @param columnIndex the first column is <code>1</code>, the second
6169     *        is <code>2</code>, and so on; must be <code>1</code> or larger
6170     *        and equal to or less than the number of columns in the rowset
6171     * @param cal the <code>java.util.Calendar</code> object to use in
6172     *            constructing the date
6173     * @return the column value; if the value is SQL <code>NULL</code>,
6174     *         the result is <code>null</code>
6175     * @throws SQLException if (1) the given column name is not the name of
6176     *            a column in this rowset, (2) the cursor is not on one of
6177     *            this rowset's rows or its insert row, or (3) the designated
6178     *            column does not store an SQL <code>TIME</code> or
6179     *            <code>TIMESTAMP</code> value
6180     */
6181    public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
6182        Object value;
6183
6184        // sanity check.
6185        checkIndex(columnIndex);
6186        // make sure the cursor is on a valid row
6187        checkCursor();
6188
6189        setLastValueNull(false);
6190        value = getCurrentRow().getColumnObject(columnIndex);
6191
6192        // check for SQL NULL
6193        if (value == null) {
6194            setLastValueNull(true);
6195            return null;
6196        }
6197
6198        value = convertTemporal(value,
6199        RowSetMD.getColumnType(columnIndex),
6200        java.sql.Types.TIMESTAMP);
6201
6202        // create a default calendar
6203        Calendar defaultCal = Calendar.getInstance();
6204        // set the time in the default calendar
6205        defaultCal.setTime((java.util.Date)value);
6206
6207        /*
6208         * Now we can pull the pieces of the date out
6209         * of the default calendar and put them into
6210         * the user provided calendar
6211         */
6212        cal.set(Calendar.YEAR, defaultCal.get(Calendar.YEAR));
6213        cal.set(Calendar.MONTH, defaultCal.get(Calendar.MONTH));
6214        cal.set(Calendar.DAY_OF_MONTH, defaultCal.get(Calendar.DAY_OF_MONTH));
6215        cal.set(Calendar.HOUR_OF_DAY, defaultCal.get(Calendar.HOUR_OF_DAY));
6216        cal.set(Calendar.MINUTE, defaultCal.get(Calendar.MINUTE));
6217        cal.set(Calendar.SECOND, defaultCal.get(Calendar.SECOND));
6218
6219        return new java.sql.Timestamp(cal.getTime().getTime());
6220    }
6221
6222    /**
6223     * Retrieves the value of the designated column in the current row
6224     * of this <code>CachedRowSetImpl</code> object as a
6225     * <code>java.sql.Timestamp</code> object, using the given
6226     * <code>Calendar</code> object to construct an appropriate
6227     * millisecond value for the date.
6228     *
6229     * @param columnName a <code>String</code> object that must match the
6230     *        SQL name of a column in this rowset, ignoring case
6231     * @param cal the <code>java.util.Calendar</code> object to use in
6232     *            constructing the date
6233     * @return the column value; if the value is SQL <code>NULL</code>,
6234     *         the result is <code>null</code>
6235     * @throws SQLException if (1) the given column name is not the name of
6236     *            a column in this rowset, (2) the cursor is not on one of
6237     *            this rowset's rows or its insert row, or (3) the designated
6238     *            column does not store an SQL <code>DATE</code>,
6239     *            <code>TIME</code>, or <code>TIMESTAMP</code> value
6240     */
6241    public java.sql.Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException {
6242        return getTimestamp(getColIdxByName(columnName), cal);
6243    }
6244
6245    /*
6246     * RowSetInternal Interface
6247     */
6248
6249    /**
6250     * Retrieves the <code>Connection</code> object passed to this
6251     * <code>CachedRowSetImpl</code> object.  This connection may be
6252     * used to populate this rowset with data or to write data back
6253     * to its underlying data source.
6254     *
6255     * @return the <code>Connection</code> object passed to this rowset;
6256     *         may be <code>null</code> if there is no connection
6257     * @throws SQLException if an error occurs
6258     */
6259    public Connection getConnection() throws SQLException{
6260        return conn;
6261    }
6262
6263    /**
6264     * Sets the metadata for this <code>CachedRowSetImpl</code> object
6265     * with the given <code>RowSetMetaData</code> object.
6266     *
6267     * @param md a <code>RowSetMetaData</code> object instance containing
6268     *            metadata about the columsn in the rowset
6269     * @throws SQLException if invalid meta data is supplied to the
6270     *            rowset
6271     */
6272    public void setMetaData(RowSetMetaData md) throws SQLException {
6273        RowSetMD =(RowSetMetaDataImpl) md;
6274    }
6275
6276    /**
6277     * Returns a result set containing the original value of the rowset. The
6278     * original value is the state of the <code>CachedRowSetImpl</code> after the
6279     * last population or synchronization (whichever occurred most recently) with
6280     * the data source.
6281     * <p>
6282     * The cursor is positioned before the first row in the result set.
6283     * Only rows contained in the result set returned by <code>getOriginal()</code>
6284     * are said to have an original value.
6285     *
6286     * @return the original result set of the rowset
6287     * @throws SQLException if an error occurs produce the
6288     *           <code>ResultSet</code> object
6289     */
6290    public ResultSet getOriginal() throws SQLException {
6291        CachedRowSetImpl crs = new CachedRowSetImpl();
6292        crs.RowSetMD = RowSetMD;
6293        crs.numRows = numRows;
6294        crs.cursorPos = 0;
6295
6296        // make sure we don't get someone playing with these
6297        // %%% is this now necessary ???
6298        //crs.setReader(null);
6299        //crs.setWriter(null);
6300        int colCount = RowSetMD.getColumnCount();
6301        Row orig;
6302
6303        for (Iterator<?> i = rvh.iterator(); i.hasNext();) {
6304            orig = new Row(colCount, ((Row)i.next()).getOrigRow());
6305            crs.rvh.add(orig);
6306        }
6307        return (ResultSet)crs;
6308    }
6309
6310    /**
6311     * Returns a result set containing the original value of the current
6312     * row only.
6313     * The original value is the state of the <code>CachedRowSetImpl</code> after
6314     * the last population or synchronization (whichever occurred most recently)
6315     * with the data source.
6316     *
6317     * @return the original result set of the row
6318     * @throws SQLException if there is no current row
6319     * @see #setOriginalRow
6320     */
6321    public ResultSet getOriginalRow() throws SQLException {
6322        CachedRowSetImpl crs = new CachedRowSetImpl();
6323        crs.RowSetMD = RowSetMD;
6324        crs.numRows = 1;
6325        crs.cursorPos = 0;
6326        crs.setTypeMap(this.getTypeMap());
6327
6328        // make sure we don't get someone playing with these
6329        // %%% is this now necessary ???
6330        //crs.setReader(null);
6331        //crs.setWriter(null);
6332
6333        Row orig = new Row(RowSetMD.getColumnCount(),
6334        getCurrentRow().getOrigRow());
6335
6336        crs.rvh.add(orig);
6337
6338        return (ResultSet)crs;
6339
6340    }
6341
6342    /**
6343     * Marks the current row in this rowset as being an original row.
6344     *
6345     * @throws SQLException if there is no current row
6346     * @see #getOriginalRow
6347     */
6348    public void setOriginalRow() throws SQLException {
6349        if (onInsertRow == true) {
6350            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
6351        }
6352
6353        Row row = (Row)getCurrentRow();
6354        makeRowOriginal(row);
6355
6356        // this can happen if deleted rows are being shown
6357        if (row.getDeleted() == true) {
6358            removeCurrentRow();
6359        }
6360    }
6361
6362    /**
6363     * Makes the given row of this rowset the original row by clearing any
6364     * settings that mark the row as having been inserted, deleted, or updated.
6365     * This method is called internally by the methods
6366     * <code>setOriginalRow</code>
6367     * and <code>setOriginal</code>.
6368     *
6369     * @param row the row to be made the original row
6370     */
6371    private void makeRowOriginal(Row row) {
6372        if (row.getInserted() == true) {
6373            row.clearInserted();
6374        }
6375
6376        if (row.getUpdated() == true) {
6377            row.moveCurrentToOrig();
6378        }
6379    }
6380
6381    /**
6382     * Marks all rows in this rowset as being original rows. Any updates
6383     * made to the rows become the original values for the rowset.
6384     * Calls to the method <code>setOriginal</code> connot be reversed.
6385     *
6386     * @throws SQLException if an error occurs
6387     */
6388    public void setOriginal() throws SQLException {
6389        for (Iterator<?> i = rvh.iterator(); i.hasNext();) {
6390            Row row = (Row)i.next();
6391            makeRowOriginal(row);
6392            // remove deleted rows from the collection.
6393            if (row.getDeleted() == true) {
6394                i.remove();
6395                --numRows;
6396            }
6397        }
6398        numDeleted = 0;
6399
6400        // notify any listeners that the rowset has changed
6401        notifyRowSetChanged();
6402    }
6403
6404    /**
6405     * Returns an identifier for the object (table) that was used to create this
6406     * rowset.
6407     *
6408     * @return a <code>String</code> object that identifies the table from
6409     *         which this <code>CachedRowSetImpl</code> object was derived
6410     * @throws SQLException if an error occurs
6411     */
6412    public String getTableName() throws SQLException {
6413        return tableName;
6414    }
6415
6416    /**
6417     * Sets the identifier for the table from which this rowset was derived
6418     * to the given table name.
6419     *
6420     * @param tabName a <code>String</code> object that identifies the
6421     *          table from which this <code>CachedRowSetImpl</code> object
6422     *          was derived
6423     * @throws SQLException if an error occurs
6424     */
6425    public void setTableName(String tabName) throws SQLException {
6426        if (tabName == null)
6427            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.tablename").toString());
6428        else
6429            tableName = tabName;
6430    }
6431
6432    /**
6433     * Returns the columns that make a key to uniquely identify a
6434     * row in this <code>CachedRowSetImpl</code> object.
6435     *
6436     * @return an array of column numbers that constitutes a primary
6437     *           key for this rowset. This array should be empty
6438     *           if no column is representitive of a primary key
6439     * @throws SQLException if the rowset is empty or no columns
6440     *           are designated as primary keys
6441     * @see #setKeyColumns
6442     */
6443    public int[] getKeyColumns() throws SQLException {
6444        int[]keyColumns  = this.keyCols;
6445        return (keyColumns == null) ? null : Arrays.copyOf(keyColumns, keyColumns.length);
6446    }
6447
6448
6449    /**
6450     * Sets this <code>CachedRowSetImpl</code> object's
6451     * <code>keyCols</code> field with the given array of column
6452     * numbers, which forms a key for uniquely identifying a row
6453     * in this rowset.
6454     *
6455     * @param keys an array of <code>int</code> indicating the
6456     *        columns that form a primary key for this
6457     *        <code>CachedRowSetImpl</code> object; every
6458     *        element in the array must be greater than
6459     *        <code>0</code> and less than or equal to the number
6460     *        of columns in this rowset
6461     * @throws SQLException if any of the numbers in the
6462     *            given array is not valid for this rowset
6463     * @see #getKeyColumns
6464     */
6465    public void setKeyColumns(int [] keys) throws SQLException {
6466        int numCols = 0;
6467        if (RowSetMD != null) {
6468            numCols = RowSetMD.getColumnCount();
6469            if (keys.length > numCols)
6470                throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.keycols").toString());
6471        }
6472        keyCols = new int[keys.length];
6473        for (int i = 0; i < keys.length; i++) {
6474            if (RowSetMD != null && (keys[i] <= 0 ||
6475            keys[i] > numCols)) {
6476                throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcol").toString() +
6477                keys[i]);
6478            }
6479            keyCols[i] = keys[i];
6480        }
6481    }
6482
6483    /**
6484     * Sets the designated column in either the current row or the insert
6485     * row of this <code>CachedRowSetImpl</code> object with the given
6486     * <code>Ref</code> value.
6487     *
6488     * This method updates a column value in either the current row or
6489     * the insert row of this rowset, but it does not update the
6490     * database.  If the cursor is on a row in the rowset, the
6491     * method {@link #updateRow} must be called to update the database.
6492     * If the cursor is on the insert row, the method {@link #insertRow}
6493     * must be called, which will insert the new row into both this rowset
6494     * and the database. Both of these methods must be called before the
6495     * cursor moves to another row.
6496     *
6497     * @param columnIndex the first column is <code>1</code>, the second
6498     *        is <code>2</code>, and so on; must be <code>1</code> or larger
6499     *        and equal to or less than the number of columns in this rowset
6500     * @param ref the new column <code>java.sql.Ref</code> value
6501     * @throws SQLException if (1) the given column index is out of bounds,
6502     *        (2) the cursor is not on one of this rowset's rows or its
6503     *        insert row, or (3) this rowset is
6504     *        <code>ResultSet.CONCUR_READ_ONLY</code>
6505     */
6506    public void updateRef(int columnIndex, java.sql.Ref ref) throws SQLException {
6507        // sanity check.
6508        checkIndex(columnIndex);
6509        // make sure the cursor is on a valid row
6510        checkCursor();
6511
6512        // SerialClob will help in getting the byte array and storing it.
6513        // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6514        // or through RowSetMetaData.locatorsUpdatorCopy()
6515        getCurrentRow().setColumnObject(columnIndex, new SerialRef(ref));
6516    }
6517
6518    /**
6519     * Sets the designated column in either the current row or the insert
6520     * row of this <code>CachedRowSetImpl</code> object with the given
6521     * <code>double</code> value.
6522     *
6523     * This method updates a column value in either the current row or
6524     * the insert row of this rowset, but it does not update the
6525     * database.  If the cursor is on a row in the rowset, the
6526     * method {@link #updateRow} must be called to update the database.
6527     * If the cursor is on the insert row, the method {@link #insertRow}
6528     * must be called, which will insert the new row into both this rowset
6529     * and the database. Both of these methods must be called before the
6530     * cursor moves to another row.
6531     *
6532     * @param columnName a <code>String</code> object that must match the
6533     *        SQL name of a column in this rowset, ignoring case
6534     * @param ref the new column <code>java.sql.Ref</code> value
6535     * @throws SQLException if (1) the given column name does not match the
6536     *        name of a column in this rowset, (2) the cursor is not on
6537     *        one of this rowset's rows or its insert row, or (3) this
6538     *        rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6539     */
6540    public void updateRef(String columnName, java.sql.Ref ref) throws SQLException {
6541        updateRef(getColIdxByName(columnName), ref);
6542    }
6543
6544    /**
6545     * Sets the designated column in either the current row or the insert
6546     * row of this <code>CachedRowSetImpl</code> object with the given
6547     * <code>double</code> value.
6548     *
6549     * This method updates a column value in either the current row or
6550     * the insert row of this rowset, but it does not update the
6551     * database.  If the cursor is on a row in the rowset, the
6552     * method {@link #updateRow} must be called to update the database.
6553     * If the cursor is on the insert row, the method {@link #insertRow}
6554     * must be called, which will insert the new row into both this rowset
6555     * and the database. Both of these methods must be called before the
6556     * cursor moves to another row.
6557     *
6558     * @param columnIndex the first column is <code>1</code>, the second
6559     *        is <code>2</code>, and so on; must be <code>1</code> or larger
6560     *        and equal to or less than the number of columns in this rowset
6561     * @param c the new column <code>Clob</code> value
6562     * @throws SQLException if (1) the given column index is out of bounds,
6563     *        (2) the cursor is not on one of this rowset's rows or its
6564     *        insert row, or (3) this rowset is
6565     *        <code>ResultSet.CONCUR_READ_ONLY</code>
6566     */
6567    public void updateClob(int columnIndex, Clob c) throws SQLException {
6568        // sanity check.
6569        checkIndex(columnIndex);
6570        // make sure the cursor is on a valid row
6571        checkCursor();
6572
6573        // SerialClob will help in getting the byte array and storing it.
6574        // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6575        // or through RowSetMetaData.locatorsUpdatorCopy()
6576
6577        if(dbmslocatorsUpdateCopy){
6578           getCurrentRow().setColumnObject(columnIndex, new SerialClob(c));
6579        }
6580        else{
6581           throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.opnotsupp").toString());
6582        }
6583    }
6584
6585    /**
6586     * Sets the designated column in either the current row or the insert
6587     * row of this <code>CachedRowSetImpl</code> object with the given
6588     * <code>double</code> value.
6589     *
6590     * This method updates a column value in either the current row or
6591     * the insert row of this rowset, but it does not update the
6592     * database.  If the cursor is on a row in the rowset, the
6593     * method {@link #updateRow} must be called to update the database.
6594     * If the cursor is on the insert row, the method {@link #insertRow}
6595     * must be called, which will insert the new row into both this rowset
6596     * and the database. Both of these methods must be called before the
6597     * cursor moves to another row.
6598     *
6599     * @param columnName a <code>String</code> object that must match the
6600     *        SQL name of a column in this rowset, ignoring case
6601     * @param c the new column <code>Clob</code> value
6602     * @throws SQLException if (1) the given column name does not match the
6603     *            name of a column in this rowset, (2) the cursor is not on
6604     *            one of this rowset's rows or its insert row, or (3) this
6605     *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6606     */
6607    public void updateClob(String columnName, Clob c) throws SQLException {
6608        updateClob(getColIdxByName(columnName), c);
6609    }
6610
6611    /**
6612     * Sets the designated column in either the current row or the insert
6613     * row of this <code>CachedRowSetImpl</code> object with the given
6614     * <code>java.sql.Blob</code> value.
6615     *
6616     * This method updates a column value in either the current row or
6617     * the insert row of this rowset, but it does not update the
6618     * database.  If the cursor is on a row in the rowset, the
6619     * method {@link #updateRow} must be called to update the database.
6620     * If the cursor is on the insert row, the method {@link #insertRow}
6621     * must be called, which will insert the new row into both this rowset
6622     * and the database. Both of these methods must be called before the
6623     * cursor moves to another row.
6624     *
6625     * @param columnIndex the first column is <code>1</code>, the second
6626     *        is <code>2</code>, and so on; must be <code>1</code> or larger
6627     *        and equal to or less than the number of columns in this rowset
6628     * @param b the new column <code>Blob</code> value
6629     * @throws SQLException if (1) the given column index is out of bounds,
6630     *            (2) the cursor is not on one of this rowset's rows or its
6631     *            insert row, or (3) this rowset is
6632     *            <code>ResultSet.CONCUR_READ_ONLY</code>
6633     */
6634    public void updateBlob(int columnIndex, Blob b) throws SQLException {
6635        // sanity check.
6636        checkIndex(columnIndex);
6637        // make sure the cursor is on a valid row
6638        checkCursor();
6639
6640        // SerialBlob will help in getting the byte array and storing it.
6641        // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6642        // or through RowSetMetaData.locatorsUpdatorCopy()
6643
6644        if(dbmslocatorsUpdateCopy){
6645           getCurrentRow().setColumnObject(columnIndex, new SerialBlob(b));
6646        }
6647        else{
6648           throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.opnotsupp").toString());
6649        }
6650    }
6651
6652    /**
6653     * Sets the designated column in either the current row or the insert
6654     * row of this <code>CachedRowSetImpl</code> object with the given
6655     * <code>java.sql.Blob </code> value.
6656     *
6657     * This method updates a column value in either the current row or
6658     * the insert row of this rowset, but it does not update the
6659     * database.  If the cursor is on a row in the rowset, the
6660     * method {@link #updateRow} must be called to update the database.
6661     * If the cursor is on the insert row, the method {@link #insertRow}
6662     * must be called, which will insert the new row into both this rowset
6663     * and the database. Both of these methods must be called before the
6664     * cursor moves to another row.
6665     *
6666     * @param columnName a <code>String</code> object that must match the
6667     *        SQL name of a column in this rowset, ignoring case
6668     * @param b the new column <code>Blob</code> value
6669     * @throws SQLException if (1) the given column name does not match the
6670     *            name of a column in this rowset, (2) the cursor is not on
6671     *            one of this rowset's rows or its insert row, or (3) this
6672     *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6673     */
6674    public void updateBlob(String columnName, Blob b) throws SQLException {
6675        updateBlob(getColIdxByName(columnName), b);
6676    }
6677
6678    /**
6679     * Sets the designated column in either the current row or the insert
6680     * row of this <code>CachedRowSetImpl</code> object with the given
6681     * <code>java.sql.Array</code> values.
6682     *
6683     * This method updates a column value in either the current row or
6684     * the insert row of this rowset, but it does not update the
6685     * database.  If the cursor is on a row in the rowset, the
6686     * method {@link #updateRow} must be called to update the database.
6687     * If the cursor is on the insert row, the method {@link #insertRow}
6688     * must be called, which will insert the new row into both this rowset
6689     * and the database. Both of these methods must be called before the
6690     * cursor moves to another row.
6691     *
6692     * @param columnIndex the first column is <code>1</code>, the second
6693     *        is <code>2</code>, and so on; must be <code>1</code> or larger
6694     *        and equal to or less than the number of columns in this rowset
6695     * @param a the new column <code>Array</code> value
6696     * @throws SQLException if (1) the given column index is out of bounds,
6697     *            (2) the cursor is not on one of this rowset's rows or its
6698     *            insert row, or (3) this rowset is
6699     *            <code>ResultSet.CONCUR_READ_ONLY</code>
6700     */
6701    public void updateArray(int columnIndex, Array a) throws SQLException {
6702        // sanity check.
6703        checkIndex(columnIndex);
6704        // make sure the cursor is on a valid row
6705        checkCursor();
6706
6707        // SerialArray will help in getting the byte array and storing it.
6708        // We need to be checking DatabaseMetaData.locatorsUpdatorCopy()
6709        // or through RowSetMetaData.locatorsUpdatorCopy()
6710        getCurrentRow().setColumnObject(columnIndex, new SerialArray(a));
6711    }
6712
6713    /**
6714     * Sets the designated column in either the current row or the insert
6715     * row of this <code>CachedRowSetImpl</code> object with the given
6716     * <code>java.sql.Array</code> value.
6717     *
6718     * This method updates a column value in either the current row or
6719     * the insert row of this rowset, but it does not update the
6720     * database.  If the cursor is on a row in the rowset, the
6721     * method {@link #updateRow} must be called to update the database.
6722     * If the cursor is on the insert row, the method {@link #insertRow}
6723     * must be called, which will insert the new row into both this rowset
6724     * and the database. Both of these methods must be called before the
6725     * cursor moves to another row.
6726     *
6727     * @param columnName a <code>String</code> object that must match the
6728     *        SQL name of a column in this rowset, ignoring case
6729     * @param a the new column <code>Array</code> value
6730     * @throws SQLException if (1) the given column name does not match the
6731     *            name of a column in this rowset, (2) the cursor is not on
6732     *            one of this rowset's rows or its insert row, or (3) this
6733     *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
6734     */
6735    public void updateArray(String columnName, Array a) throws SQLException {
6736        updateArray(getColIdxByName(columnName), a);
6737    }
6738
6739
6740    /**
6741     * Retrieves the value of the designated column in this
6742     * <code>CachedRowSetImpl</code> object as a <code>java.net.URL</code> object
6743     * in the Java programming language.
6744     *
6745     * @return a java.net.URL object containing the resource reference described by
6746     * the URL
6747     * @throws SQLException if (1) the given column index is out of bounds,
6748     * (2) the cursor is not on one of this rowset's rows or its
6749     * insert row, or (3) the designated column does not store an
6750     * SQL <code>DATALINK</code> value.
6751     * @see #getURL(String)
6752     */
6753    public java.net.URL getURL(int columnIndex) throws SQLException {
6754        //throw new SQLException("Operation not supported");
6755
6756        java.net.URL value;
6757
6758        // sanity check.
6759        checkIndex(columnIndex);
6760        // make sure the cursor is on a valid row
6761        checkCursor();
6762
6763        if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.DATALINK) {
6764            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
6765        }
6766
6767        setLastValueNull(false);
6768        value = (java.net.URL)(getCurrentRow().getColumnObject(columnIndex));
6769
6770        // check for SQL NULL
6771        if (value == null) {
6772            setLastValueNull(true);
6773            return null;
6774        }
6775
6776        return value;
6777    }
6778
6779    /**
6780     * Retrieves the value of the designated column in this
6781     * <code>CachedRowSetImpl</code> object as a <code>java.net.URL</code> object
6782     * in the Java programming language.
6783     *
6784     * @return a java.net.URL object containing the resource reference described by
6785     * the URL
6786     * @throws SQLException if (1) the given column name not the name of a column
6787     * in this rowset, or
6788     * (2) the cursor is not on one of this rowset's rows or its
6789     * insert row, or (3) the designated column does not store an
6790     * SQL <code>DATALINK</code> value.
6791     * @see #getURL(int)
6792     */
6793    public java.net.URL getURL(String columnName) throws SQLException {
6794        return getURL(getColIdxByName(columnName));
6795
6796    }
6797
6798    /**
6799     * The first warning reported by calls on this <code>CachedRowSetImpl</code>
6800     * object is returned. Subsequent <code>CachedRowSetImpl</code> warnings will
6801     * be chained to this <code>SQLWarning</code>. All <code>RowSetWarnings</code>
6802     * warnings are generated in the disconnected environment and remain a
6803     * seperate warning chain to that provided by the <code>getWarnings</code>
6804     * method.
6805     *
6806     * <P>The warning chain is automatically cleared each time a new
6807     * row is read.
6808     *
6809     * <P><B>Note:</B> This warning chain only covers warnings caused
6810     * by <code>CachedRowSet</code> (and their child interface)
6811     * methods. All <code>SQLWarnings</code> can be obtained using the
6812     * <code>getWarnings</code> method which tracks warnings generated
6813     * by the underlying JDBC driver.
6814     * @return the first SQLWarning or null
6815     *
6816     */
6817    public RowSetWarning getRowSetWarnings() {
6818        try {
6819            notifyCursorMoved();
6820        } catch (SQLException e) {} // mask exception
6821        return rowsetWarning;
6822    }
6823
6824
6825    /**
6826     * The function tries to isolate the tablename when only setCommand
6827     * is set and not setTablename is called provided there is only one table
6828     * name in the query else just leaves the setting of table name as such.
6829     * If setTablename is set later it will over ride this table name
6830     * value so retrieved.
6831     *
6832     * @return the tablename if only one table in query else return ""
6833     */
6834    private String buildTableName(String command) throws SQLException {
6835
6836        // If we have a query from one table,
6837        // we set the table name implicitly
6838        // else user has to explicitly set the table name.
6839
6840        int indexFrom, indexComma;
6841        String strTablename ="";
6842        command = command.trim();
6843
6844        // Query can be a select, insert or  update
6845
6846        if(command.toLowerCase().startsWith("select")) {
6847            // look for "from" keyword, after that look for a
6848            // comma after from. If comma is there don't set
6849            // table name else isolate table name.
6850
6851            indexFrom = command.toLowerCase().indexOf("from");
6852            indexComma = command.indexOf(',', indexFrom);
6853
6854            if(indexComma == -1) {
6855                // implies only one table
6856                strTablename = (command.substring(indexFrom+"from".length(),command.length())).trim();
6857
6858                String tabName = strTablename;
6859
6860                int idxWhere = tabName.toLowerCase().indexOf("where");
6861
6862                /**
6863                  * Adding the addtional check for conditions following the table name.
6864                  * If a condition is found truncate it.
6865                  **/
6866
6867                if(idxWhere != -1)
6868                {
6869                   tabName = tabName.substring(0,idxWhere).trim();
6870                }
6871
6872                strTablename = tabName;
6873
6874            } else {
6875                //strTablename="";
6876            }
6877
6878        } else if(command.toLowerCase().startsWith("insert")) {
6879            //strTablename="";
6880        } else if(command.toLowerCase().startsWith("update")) {
6881            //strTablename="";
6882        }
6883        return strTablename;
6884    }
6885
6886    /**
6887     * Commits all changes performed by the <code>acceptChanges()</code>
6888     * methods
6889     *
6890     * @see java.sql.Connection#commit
6891     */
6892    public void commit() throws SQLException {
6893        conn.commit();
6894    }
6895
6896    /**
6897     * Rolls back all changes performed by the <code>acceptChanges()</code>
6898     * methods
6899     *
6900     * @see java.sql.Connection#rollback
6901     */
6902    public void rollback() throws SQLException {
6903        conn.rollback();
6904    }
6905
6906    /**
6907     * Rolls back all changes performed by the <code>acceptChanges()</code>
6908     * to the last <code>Savepoint</code> transaction marker.
6909     *
6910     * @see java.sql.Connection#rollback(Savepoint)
6911     */
6912    public void rollback(Savepoint s) throws SQLException {
6913        conn.rollback(s);
6914    }
6915
6916    /**
6917     * Unsets the designated parameter to the given int array.
6918     * This was set using <code>setMatchColumn</code>
6919     * as the column which will form the basis of the join.
6920     * <P>
6921     * The parameter value unset by this method should be same
6922     * as was set.
6923     *
6924     * @param columnIdxes the index into this rowset
6925     *        object's internal representation of parameter values
6926     * @throws SQLException if an error occurs or the
6927     *  parameter index is out of bounds or if the columnIdx is
6928     *  not the same as set using <code>setMatchColumn(int [])</code>
6929     */
6930    public void unsetMatchColumn(int[] columnIdxes) throws SQLException {
6931
6932         int i_val;
6933         for( int j= 0 ;j < columnIdxes.length; j++) {
6934            i_val = (Integer.parseInt(iMatchColumns.get(j).toString()));
6935            if(columnIdxes[j] != i_val) {
6936               throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols").toString());
6937            }
6938         }
6939
6940         for( int i = 0;i < columnIdxes.length ;i++) {
6941            iMatchColumns.set(i, -1);
6942         }
6943    }
6944
6945   /**
6946     * Unsets the designated parameter to the given String array.
6947     * This was set using <code>setMatchColumn</code>
6948     * as the column which will form the basis of the join.
6949     * <P>
6950     * The parameter value unset by this method should be same
6951     * as was set.
6952     *
6953     * @param columnIdxes the index into this rowset
6954     *        object's internal representation of parameter values
6955     * @throws SQLException if an error occurs or the
6956     *  parameter index is out of bounds or if the columnName is
6957     *  not the same as set using <code>setMatchColumn(String [])</code>
6958     */
6959    public void unsetMatchColumn(String[] columnIdxes) throws SQLException {
6960
6961        for(int j = 0 ;j < columnIdxes.length; j++) {
6962           if( !columnIdxes[j].equals(strMatchColumns.get(j)) ){
6963              throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols").toString());
6964           }
6965        }
6966
6967        for(int i = 0 ; i < columnIdxes.length; i++) {
6968           strMatchColumns.set(i,null);
6969        }
6970    }
6971
6972    /**
6973     * Retrieves the column name as <code>String</code> array
6974     * that was set using <code>setMatchColumn(String [])</code>
6975     * for this rowset.
6976     *
6977     * @return a <code>String</code> array object that contains the column names
6978     *         for the rowset which has this the match columns
6979     *
6980     * @throws SQLException if an error occurs or column name is not set
6981     */
6982    public String[] getMatchColumnNames() throws SQLException {
6983
6984        String []str_temp = new String[strMatchColumns.size()];
6985
6986        if( strMatchColumns.get(0) == null) {
6987           throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.setmatchcols").toString());
6988        }
6989
6990        strMatchColumns.copyInto(str_temp);
6991        return str_temp;
6992    }
6993
6994    /**
6995     * Retrieves the column id as <code>int</code> array that was set using
6996     * <code>setMatchColumn(int [])</code> for this rowset.
6997     *
6998     * @return a <code>int</code> array object that contains the column ids
6999     *         for the rowset which has this as the match columns.
7000     *
7001     * @throws SQLException if an error occurs or column index is not set
7002     */
7003    public int[] getMatchColumnIndexes() throws SQLException {
7004
7005        Integer []int_temp = new Integer[iMatchColumns.size()];
7006        int [] i_temp = new int[iMatchColumns.size()];
7007        int i_val;
7008
7009        i_val = iMatchColumns.get(0);
7010
7011        if( i_val == -1 ) {
7012           throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.setmatchcols").toString());
7013        }
7014
7015
7016        iMatchColumns.copyInto(int_temp);
7017
7018        for(int i = 0; i < int_temp.length; i++) {
7019           i_temp[i] = (int_temp[i]).intValue();
7020        }
7021
7022        return i_temp;
7023    }
7024
7025    /**
7026     * Sets the designated parameter to the given int array.
7027     * This forms the basis of the join for the
7028     * <code>JoinRowSet</code> as the column which will form the basis of the
7029     * join.
7030     * <P>
7031     * The parameter value set by this method is stored internally and
7032     * will be supplied as the appropriate parameter in this rowset's
7033     * command when the method <code>getMatchColumnIndexes</code> is called.
7034     *
7035     * @param columnIdxes the indexes into this rowset
7036     *        object's internal representation of parameter values; the
7037     *        first parameter is 0, the second is 1, and so on; must be
7038     *        <code>0</code> or greater
7039     * @throws SQLException if an error occurs or the
7040     *                         parameter index is out of bounds
7041     */
7042    public void setMatchColumn(int[] columnIdxes) throws SQLException {
7043
7044        for(int j = 0 ; j < columnIdxes.length; j++) {
7045           if( columnIdxes[j] < 0 ) {
7046              throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols1").toString());
7047           }
7048        }
7049        for(int i = 0 ;i < columnIdxes.length; i++) {
7050           iMatchColumns.add(i,columnIdxes[i]);
7051        }
7052    }
7053
7054    /**
7055     * Sets the designated parameter to the given String array.
7056     *  This forms the basis of the join for the
7057     * <code>JoinRowSet</code> as the column which will form the basis of the
7058     * join.
7059     * <P>
7060     * The parameter value set by this method is stored internally and
7061     * will be supplied as the appropriate parameter in this rowset's
7062     * command when the method <code>getMatchColumn</code> is called.
7063     *
7064     * @param columnNames the name of the column into this rowset
7065     *        object's internal representation of parameter values
7066     * @throws SQLException if an error occurs or the
7067     *  parameter index is out of bounds
7068     */
7069    public void setMatchColumn(String[] columnNames) throws SQLException {
7070
7071        for(int j = 0; j < columnNames.length; j++) {
7072           if( columnNames[j] == null || columnNames[j].equals("")) {
7073              throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols2").toString());
7074           }
7075        }
7076        for( int i = 0; i < columnNames.length; i++) {
7077           strMatchColumns.add(i,columnNames[i]);
7078        }
7079    }
7080
7081
7082    /**
7083     * Sets the designated parameter to the given <code>int</code>
7084     * object.  This forms the basis of the join for the
7085     * <code>JoinRowSet</code> as the column which will form the basis of the
7086     * join.
7087     * <P>
7088     * The parameter value set by this method is stored internally and
7089     * will be supplied as the appropriate parameter in this rowset's
7090     * command when the method <code>getMatchColumn</code> is called.
7091     *
7092     * @param columnIdx the index into this rowset
7093     *        object's internal representation of parameter values; the
7094     *        first parameter is 0, the second is 1, and so on; must be
7095     *        <code>0</code> or greater
7096     * @throws SQLException if an error occurs or the
7097     *                         parameter index is out of bounds
7098     */
7099    public void setMatchColumn(int columnIdx) throws SQLException {
7100        // validate, if col is ok to be set
7101        if(columnIdx < 0) {
7102            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols1").toString());
7103        } else {
7104            // set iMatchColumn
7105            iMatchColumns.set(0, columnIdx);
7106            //strMatchColumn = null;
7107        }
7108    }
7109
7110    /**
7111     * Sets the designated parameter to the given <code>String</code>
7112     * object.  This forms the basis of the join for the
7113     * <code>JoinRowSet</code> as the column which will form the basis of the
7114     * join.
7115     * <P>
7116     * The parameter value set by this method is stored internally and
7117     * will be supplied as the appropriate parameter in this rowset's
7118     * command when the method <code>getMatchColumn</code> is called.
7119     *
7120     * @param columnName the name of the column into this rowset
7121     *        object's internal representation of parameter values
7122     * @throws SQLException if an error occurs or the
7123     *  parameter index is out of bounds
7124     */
7125    public void setMatchColumn(String columnName) throws SQLException {
7126        // validate, if col is ok to be set
7127        if(columnName == null || (columnName= columnName.trim()).equals("") ) {
7128            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols2").toString());
7129        } else {
7130            // set strMatchColumn
7131            strMatchColumns.set(0, columnName);
7132            //iMatchColumn = -1;
7133        }
7134    }
7135
7136    /**
7137     * Unsets the designated parameter to the given <code>int</code>
7138     * object.  This was set using <code>setMatchColumn</code>
7139     * as the column which will form the basis of the join.
7140     * <P>
7141     * The parameter value unset by this method should be same
7142     * as was set.
7143     *
7144     * @param columnIdx the index into this rowset
7145     *        object's internal representation of parameter values
7146     * @throws SQLException if an error occurs or the
7147     *  parameter index is out of bounds or if the columnIdx is
7148     *  not the same as set using <code>setMatchColumn(int)</code>
7149     */
7150    public void unsetMatchColumn(int columnIdx) throws SQLException {
7151        // check if we are unsetting the SAME column
7152        if(! iMatchColumns.get(0).equals(Integer.valueOf(columnIdx) )  ) {
7153            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch").toString());
7154        } else if(strMatchColumns.get(0) != null) {
7155            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch1").toString());
7156        } else {
7157                // that is, we are unsetting it.
7158               iMatchColumns.set(0, -1);
7159        }
7160    }
7161
7162    /**
7163     * Unsets the designated parameter to the given <code>String</code>
7164     * object.  This was set using <code>setMatchColumn</code>
7165     * as the column which will form the basis of the join.
7166     * <P>
7167     * The parameter value unset by this method should be same
7168     * as was set.
7169     *
7170     * @param columnName the index into this rowset
7171     *        object's internal representation of parameter values
7172     * @throws SQLException if an error occurs or the
7173     *  parameter index is out of bounds or if the columnName is
7174     *  not the same as set using <code>setMatchColumn(String)</code>
7175     */
7176    public void unsetMatchColumn(String columnName) throws SQLException {
7177        // check if we are unsetting the same column
7178        columnName = columnName.trim();
7179
7180        if(!((strMatchColumns.get(0)).equals(columnName))) {
7181            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch").toString());
7182        } else if(iMatchColumns.get(0) > 0) {
7183            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch2").toString());
7184        } else {
7185            strMatchColumns.set(0, null);   // that is, we are unsetting it.
7186        }
7187    }
7188
7189    /**
7190     * Notifies registered listeners that a RowSet object in the given RowSetEvent
7191     * object has populated a number of additional rows. The <code>numRows</code> parameter
7192     * ensures that this event will only be fired every <code>numRow</code>.
7193     * <p>
7194     * The source of the event can be retrieved with the method event.getSource.
7195     *
7196     * @param event a <code>RowSetEvent</code> object that contains the
7197     *     <code>RowSet</code> object that is the source of the events
7198     * @param numRows when populating, the number of rows interval on which the
7199     *     <code>CachedRowSet</code> populated should fire; the default value
7200     *     is zero; cannot be less than <code>fetchSize</code> or zero
7201     */
7202    public void rowSetPopulated(RowSetEvent event, int numRows) throws SQLException {
7203
7204        if( numRows < 0 || numRows < getFetchSize()) {
7205           throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.numrows").toString());
7206        }
7207
7208        if(size() % numRows == 0) {
7209            RowSetEvent event_temp = new RowSetEvent(this);
7210            event = event_temp;
7211            notifyRowSetChanged();
7212        }
7213    }
7214
7215    /**
7216     * Populates this <code>CachedRowSet</code> object with data from
7217     * the given <code>ResultSet</code> object. While related to the <code>populate(ResultSet)</code>
7218     * method, an additional parameter is provided to allow starting position within
7219     * the <code>ResultSet</code> from where to populate the CachedRowSet
7220     * instance.
7221     *
7222     * This method is an alternative to the method <code>execute</code>
7223     * for filling the rowset with data.  The method <code>populate</code>
7224     * does not require that the properties needed by the method
7225     * <code>execute</code>, such as the <code>command</code> property,
7226     * be set. This is true because the method <code>populate</code>
7227     * is given the <code>ResultSet</code> object from
7228     * which to get data and thus does not need to use the properties
7229     * required for setting up a connection and executing this
7230     * <code>CachedRowSetImpl</code> object's command.
7231     * <P>
7232     * After populating this rowset with data, the method
7233     * <code>populate</code> sets the rowset's metadata and
7234     * then sends a <code>RowSetChangedEvent</code> object
7235     * to all registered listeners prior to returning.
7236     *
7237     * @param data the <code>ResultSet</code> object containing the data
7238     *             to be read into this <code>CachedRowSetImpl</code> object
7239     * @param start the integer specifing the position in the
7240     *        <code>ResultSet</code> object to popultate the
7241     *        <code>CachedRowSetImpl</code> object.
7242     * @throws SQLException if an error occurs; or the max row setting is
7243     *          violated while populating the RowSet.Also id the start position
7244     *          is negative.
7245     * @see #execute
7246     */
7247     public void populate(ResultSet data, int start) throws SQLException{
7248
7249        int rowsFetched;
7250        Row currentRow;
7251        int numCols;
7252        int i;
7253        Map<String, Class<?>> map = getTypeMap();
7254        Object obj;
7255        int mRows;
7256
7257        cursorPos = 0;
7258        if(populatecallcount == 0){
7259            if(start < 0){
7260               throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.startpos").toString());
7261            }
7262            if(getMaxRows() == 0){
7263               data.absolute(start);
7264               while(data.next()){
7265                   totalRows++;
7266               }
7267               totalRows++;
7268            }
7269            startPos = start;
7270        }
7271        populatecallcount = populatecallcount +1;
7272        resultSet = data;
7273        if((endPos - startPos) >= getMaxRows() && (getMaxRows() > 0)){
7274            endPos = prevEndPos;
7275            pagenotend = false;
7276            return;
7277        }
7278
7279        if((maxRowsreached != getMaxRows() || maxRowsreached != totalRows) && pagenotend) {
7280           startPrev = start - getPageSize();
7281        }
7282
7283        if( pageSize == 0){
7284           prevEndPos = endPos;
7285           endPos = start + getMaxRows() ;
7286        }
7287        else{
7288            prevEndPos = endPos;
7289            endPos = start + getPageSize();
7290        }
7291
7292
7293        if (start == 1){
7294            resultSet.beforeFirst();
7295        }
7296        else {
7297            resultSet.absolute(start -1);
7298        }
7299        if( pageSize == 0) {
7300           rvh = new Vector<Object>(getMaxRows());
7301
7302        }
7303        else{
7304            rvh = new Vector<Object>(getPageSize());
7305        }
7306
7307        if (data == null) {
7308            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.populate").toString());
7309        }
7310
7311        // get the meta data for this ResultSet
7312        RSMD = data.getMetaData();
7313
7314        // set up the metadata
7315        RowSetMD = new RowSetMetaDataImpl();
7316        initMetaData(RowSetMD, RSMD);
7317
7318        // release the meta-data so that aren't tempted to use it.
7319        RSMD = null;
7320        numCols = RowSetMD.getColumnCount();
7321        mRows = this.getMaxRows();
7322        rowsFetched = 0;
7323        currentRow = null;
7324
7325        if(!data.next() && mRows == 0){
7326            endPos = prevEndPos;
7327            pagenotend = false;
7328            return;
7329        }
7330
7331        data.previous();
7332
7333        while ( data.next()) {
7334
7335            currentRow = new Row(numCols);
7336          if(pageSize == 0){
7337            if ( rowsFetched >= mRows && mRows > 0) {
7338                rowsetWarning.setNextException(new SQLException("Populating rows "
7339                + "setting has exceeded max row setting"));
7340                break;
7341            }
7342          }
7343          else {
7344              if ( (rowsFetched >= pageSize) ||( maxRowsreached >= mRows && mRows > 0)) {
7345                rowsetWarning.setNextException(new SQLException("Populating rows "
7346                + "setting has exceeded max row setting"));
7347                break;
7348            }
7349          }
7350
7351            for ( i = 1; i <= numCols; i++) {
7352                /*
7353                 * check if the user has set a map. If no map
7354                 * is set then use plain getObject. This lets
7355                 * us work with drivers that do not support
7356                 * getObject with a map in fairly sensible way
7357                 */
7358                if (map == null) {
7359                    obj = data.getObject(i);
7360                } else {
7361                    obj = data.getObject(i, map);
7362                }
7363                /*
7364                 * the following block checks for the various
7365                 * types that we have to serialize in order to
7366                 * store - right now only structs have been tested
7367                 */
7368                if (obj instanceof Struct) {
7369                    obj = new SerialStruct((Struct)obj, map);
7370                } else if (obj instanceof SQLData) {
7371                    obj = new SerialStruct((SQLData)obj, map);
7372                } else if (obj instanceof Blob) {
7373                    obj = new SerialBlob((Blob)obj);
7374                } else if (obj instanceof Clob) {
7375                    obj = new SerialClob((Clob)obj);
7376                } else if (obj instanceof java.sql.Array) {
7377                    obj = new SerialArray((java.sql.Array)obj, map);
7378                }
7379
7380                currentRow.initColumnObject(i, obj);
7381            }
7382            rowsFetched++;
7383            maxRowsreached++;
7384            rvh.add(currentRow);
7385        }
7386        numRows = rowsFetched ;
7387        // Also rowsFetched should be equal to rvh.size()
7388        // notify any listeners that the rowset has changed
7389        notifyRowSetChanged();
7390
7391     }
7392
7393    /**
7394     * The nextPage gets the next page, that is a <code>CachedRowSetImpl</code> object
7395     * containing the number of rows specified by page size.
7396     * @return boolean value true indicating whether there are more pages to come and
7397     *         false indicating that this is the last page.
7398     * @throws SQLException if an error occurs or this called before calling populate.
7399     */
7400     public boolean nextPage() throws SQLException {
7401
7402         if (populatecallcount == 0){
7403             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.nextpage").toString());
7404         }
7405         // Fix for 6554186
7406         onFirstPage = false;
7407         if(callWithCon){
7408            crsReader.setStartPosition(endPos);
7409            crsReader.readData((RowSetInternal)this);
7410            resultSet = null;
7411         }
7412         else {
7413            populate(resultSet,endPos);
7414         }
7415         return pagenotend;
7416     }
7417
7418    /**
7419     * This is the setter function for setting the size of the page, which specifies
7420     * how many rows have to be retrived at a time.
7421     *
7422     * @param size which is the page size
7423     * @throws SQLException if size is less than zero or greater than max rows.
7424     */
7425     public void setPageSize (int size) throws SQLException {
7426        if (size < 0) {
7427            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.pagesize").toString());
7428        }
7429        if (size > getMaxRows() && getMaxRows() != 0) {
7430            throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.pagesize1").toString());
7431        }
7432        pageSize = size;
7433     }
7434
7435    /**
7436     * This is the getter function for the size of the page.
7437     *
7438     * @return an integer that is the page size.
7439     */
7440    public int getPageSize() {
7441        return pageSize;
7442    }
7443
7444
7445    /**
7446     * Retrieves the data present in the page prior to the page from where it is
7447     * called.
7448     * @return boolean value true if it retrieves the previous page, flase if it
7449     *         is on the first page.
7450     * @throws SQLException if it is called before populate is called or ResultSet
7451     *         is of type <code>ResultSet.TYPE_FORWARD_ONLY</code> or if an error
7452     *         occurs.
7453     */
7454    public boolean previousPage() throws SQLException {
7455        int pS;
7456        int mR;
7457        int rem;
7458
7459        pS = getPageSize();
7460        mR = maxRowsreached;
7461
7462        if (populatecallcount == 0){
7463             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.nextpage").toString());
7464         }
7465
7466        if( !callWithCon){
7467           if(resultSet.getType() == ResultSet.TYPE_FORWARD_ONLY){
7468               throw new SQLException (resBundle.handleGetObject("cachedrowsetimpl.fwdonly").toString());
7469           }
7470        }
7471
7472        pagenotend = true;
7473
7474        if(startPrev < startPos ){
7475                onFirstPage = true;
7476               return false;
7477            }
7478
7479        if(onFirstPage){
7480            return false;
7481        }
7482
7483        rem = mR % pS;
7484
7485        if(rem == 0){
7486            maxRowsreached -= (2 * pS);
7487            if(callWithCon){
7488                crsReader.setStartPosition(startPrev);
7489                crsReader.readData((RowSetInternal)this);
7490                resultSet = null;
7491            }
7492            else {
7493               populate(resultSet,startPrev);
7494            }
7495            return true;
7496        }
7497        else
7498        {
7499            maxRowsreached -= (pS + rem);
7500            if(callWithCon){
7501                crsReader.setStartPosition(startPrev);
7502                crsReader.readData((RowSetInternal)this);
7503                resultSet = null;
7504            }
7505            else {
7506               populate(resultSet,startPrev);
7507            }
7508            return true;
7509        }
7510    }
7511
7512    /**
7513     * Goes to the page number passed as the parameter
7514     * @param page , the page loaded on a call to this function
7515     * @return true if the page exists false otherwise
7516     * @throws SQLException if an error occurs
7517     */
7518    /*
7519    public boolean absolutePage(int page) throws SQLException{
7520
7521        boolean isAbs = true, retVal = true;
7522        int counter;
7523
7524        if( page <= 0 ){
7525            throw new SQLException("Absolute positoin is invalid");
7526        }
7527        counter = 0;
7528
7529        firstPage();
7530        counter++;
7531        while((counter < page) && isAbs) {
7532            isAbs = nextPage();
7533            counter ++;
7534        }
7535
7536        if( !isAbs && counter < page){
7537            retVal = false;
7538        }
7539        else if(counter == page){
7540            retVal = true;
7541        }
7542
7543       return retVal;
7544    }
7545    */
7546
7547
7548    /**
7549     * Goes to the page number passed as the parameter  from the current page.
7550     * The parameter can take postive or negative value accordingly.
7551     * @param page , the page loaded on a call to this function
7552     * @return true if the page exists false otherwise
7553     * @throws SQLException if an error occurs
7554     */
7555    /*
7556    public boolean relativePage(int page) throws SQLException {
7557
7558        boolean isRel = true,retVal = true;
7559        int counter;
7560
7561        if(page > 0){
7562           counter  = 0;
7563           while((counter < page) && isRel){
7564              isRel = nextPage();
7565              counter++;
7566           }
7567
7568           if(!isRel && counter < page){
7569               retVal = false;
7570           }
7571           else if( counter == page){
7572               retVal = true;
7573           }
7574           return retVal;
7575        }
7576        else {
7577            counter = page;
7578            isRel = true;
7579            while((counter < 0) && isRel){
7580                isRel = previousPage();
7581                counter++;
7582            }
7583
7584            if( !isRel && counter < 0){
7585                retVal = false;
7586            }
7587            else if(counter == 0){
7588                retVal = true;
7589            }
7590            return retVal;
7591        }
7592    }
7593    */
7594
7595     /**
7596     * Retrieves the first page of data as specified by the page size.
7597     * @return boolean value true if present on first page, false otherwise
7598     * @throws SQLException if it called before populate or ResultSet is of
7599     *         type <code>ResultSet.TYPE_FORWARD_ONLY</code> or an error occurs
7600     */
7601    /*
7602    public boolean firstPage() throws SQLException {
7603           if (populatecallcount == 0){
7604             throw new SQLException("Populate the data before calling ");
7605           }
7606           if( !callWithCon){
7607              if(resultSet.getType() == ResultSet.TYPE_FORWARD_ONLY) {
7608                  throw new SQLException("Result of type forward only");
7609              }
7610           }
7611           endPos = 0;
7612           maxRowsreached = 0;
7613           pagenotend = true;
7614           if(callWithCon){
7615               crsReader.setStartPosition(startPos);
7616               crsReader.readData((RowSetInternal)this);
7617               resultSet = null;
7618           }
7619           else {
7620              populate(resultSet,startPos);
7621           }
7622           onFirstPage = true;
7623           return onFirstPage;
7624    }
7625    */
7626
7627    /**
7628     * Retrives the last page of data as specified by the page size.
7629     * @return boolean value tur if present on the last page, false otherwise
7630     * @throws SQLException if called before populate or if an error occurs.
7631     */
7632     /*
7633    public boolean lastPage() throws SQLException{
7634          int pS;
7635          int mR;
7636          int quo;
7637          int rem;
7638
7639          pS = getPageSize();
7640          mR = getMaxRows();
7641
7642          if(pS == 0){
7643              onLastPage = true;
7644              return onLastPage;
7645          }
7646
7647          if(getMaxRows() == 0){
7648              mR = totalRows;
7649          }
7650
7651          if (populatecallcount == 0){
7652             throw new SQLException("Populate the data before calling ");
7653         }
7654
7655         onFirstPage = false;
7656
7657         if((mR % pS) == 0){
7658             quo = mR / pS;
7659             int start = startPos + (pS * (quo - 1));
7660             maxRowsreached = mR - pS;
7661             if(callWithCon){
7662                 crsReader.setStartPosition(start);
7663                 crsReader.readData((RowSetInternal)this);
7664                 resultSet = null;
7665             }
7666             else {
7667                populate(resultSet,start);
7668             }
7669             onLastPage = true;
7670             return onLastPage;
7671         }
7672        else {
7673              quo = mR /pS;
7674              rem = mR % pS;
7675              int start = startPos + (pS * quo);
7676             maxRowsreached = mR - (rem);
7677             if(callWithCon){
7678                 crsReader.setStartPosition(start);
7679                 crsReader.readData((RowSetInternal)this);
7680                 resultSet = null;
7681             }
7682             else {
7683                populate(resultSet,start);
7684             }
7685             onLastPage = true;
7686             return onLastPage;
7687         }
7688    }
7689    */
7690
7691   /**
7692     * Sets the status for the row on which the cursor is positioned. The insertFlag is used
7693     * to mention the toggle status for this row
7694     * @param insertFlag if it is true  - marks this row as inserted
7695     *                   if it is false - marks it as not a newly inserted row
7696     * @throws SQLException if an error occurs while doing this operation
7697     */
7698    public void setRowInserted(boolean insertFlag) throws SQLException {
7699
7700        checkCursor();
7701
7702        if(onInsertRow == true)
7703          throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
7704
7705        if( insertFlag ) {
7706          ((Row)getCurrentRow()).setInserted();
7707        } else {
7708          ((Row)getCurrentRow()).clearInserted();
7709        }
7710    }
7711
7712    /**
7713     * Retrieves the value of the designated <code>SQL XML</code> parameter as a
7714     * <code>SQLXML</code> object in the Java programming language.
7715     * @param columnIndex the first column is 1, the second is 2, ...
7716     * @return a SQLXML object that maps an SQL XML value
7717     * @throws SQLException if a database access error occurs
7718     * @since 1.6
7719     */
7720    public SQLXML getSQLXML(int columnIndex) throws SQLException {
7721        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7722    }
7723
7724    /**
7725     * Retrieves the value of the designated <code>SQL XML</code> parameter as a
7726     * <code>SQLXML</code> object in the Java programming language.
7727     * @param colName the name of the column from which to retrieve the value
7728     * @return a SQLXML object that maps an SQL XML value
7729     * @throws SQLException if a database access error occurs
7730     */
7731    public SQLXML getSQLXML(String colName) throws SQLException {
7732        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7733    }
7734
7735    /**
7736     * Retrieves the value of the designated column in the current row of this
7737     * <code>ResultSet</code> object as a java.sql.RowId object in the Java
7738     * programming language.
7739     *
7740     * @param columnIndex the first column is 1, the second 2, ...
7741     * @return the column value if the value is a SQL <code>NULL</code> the
7742     *     value returned is <code>null</code>
7743     * @throws SQLException if a database access error occurs
7744     * @since 1.6
7745     */
7746    public RowId getRowId(int columnIndex) throws SQLException {
7747        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7748    }
7749
7750    /**
7751     * Retrieves the value of the designated column in the current row of this
7752     * <code>ResultSet</code> object as a java.sql.RowId object in the Java
7753     * programming language.
7754     *
7755     * @param columnName the name of the column
7756     * @return the column value if the value is a SQL <code>NULL</code> the
7757     *     value returned is <code>null</code>
7758     * @throws SQLException if a database access error occurs
7759     * @since 1.6
7760     */
7761    public RowId getRowId(String columnName) throws SQLException {
7762        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7763    }
7764
7765    /**
7766     * Updates the designated column with a <code>RowId</code> value. The updater
7767     * methods are used to update column values in the current row or the insert
7768     * row. The updater methods do not update the underlying database; instead
7769     * the {@code updateRow} or {@code insertRow} methods are called
7770     * to update the database.
7771     *
7772     * @param columnIndex the first column is 1, the second 2, ...
7773     * @param x the column value
7774     * @throws SQLException if a database access occurs
7775     * @since 1.6
7776     */
7777    public void updateRowId(int columnIndex, RowId x) throws SQLException {
7778        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7779    }
7780
7781    /**
7782     * Updates the designated column with a <code>RowId</code> value. The updater
7783     * methods are used to update column values in the current row or the insert
7784     * row. The updater methods do not update the underlying database; instead
7785     * the {@code updateRow} or {@code insertRow} methods are called
7786     * to update the database.
7787     *
7788     * @param columnName the name of the column
7789     * @param x the column value
7790     * @throws SQLException if a database access occurs
7791     * @since 1.6
7792     */
7793    public void updateRowId(String columnName, RowId x) throws SQLException {
7794        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7795    }
7796
7797    /**
7798     * Retrieves the holdability of this ResultSet object
7799     * @return  either ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT
7800     * @throws SQLException if a database error occurs
7801     * @since 1.6
7802     */
7803    public int getHoldability() throws SQLException {
7804        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7805    }
7806
7807    /**
7808     * Retrieves whether this ResultSet object has been closed. A ResultSet is closed if the
7809     * method close has been called on it, or if it is automatically closed.
7810     * @return true if this ResultSet object is closed; false if it is still open
7811     * @throws SQLException if a database access error occurs
7812     * @since 1.6
7813     */
7814    public boolean isClosed() throws SQLException {
7815        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7816    }
7817
7818    /**
7819     * This method is used for updating columns that support National Character sets.
7820     * It can be used for updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
7821     * @param columnIndex the first column is 1, the second 2, ...
7822     * @param nString the value for the column to be updated
7823     * @throws SQLException if a database access error occurs
7824     * @since 1.6
7825     */
7826    public void updateNString(int columnIndex, String nString) throws SQLException {
7827        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7828    }
7829
7830    /**
7831     * This method is used for updating columns that support National Character sets.
7832     * It can be used for updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
7833     * @param columnName name of the Column
7834     * @param nString the value for the column to be updated
7835     * @throws SQLException if a database access error occurs
7836     * @since 1.6
7837     */
7838    public void updateNString(String columnName, String nString) throws SQLException {
7839        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7840    }
7841
7842
7843    /*o
7844     * This method is used for updating SQL <code>NCLOB</code>  type that maps
7845     * to <code>java.sql.Types.NCLOB</code>
7846     * @param columnIndex the first column is 1, the second 2, ...
7847     * @param nClob the value for the column to be updated
7848     * @throws SQLException if a database access error occurs
7849     * @since 1.6
7850     */
7851    public void updateNClob(int columnIndex, NClob nClob) throws SQLException {
7852        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7853    }
7854
7855    /**
7856     * This method is used for updating SQL <code>NCLOB</code>  type that maps
7857     * to <code>java.sql.Types.NCLOB</code>
7858     * @param columnName name of the column
7859     * @param nClob the value for the column to be updated
7860     * @throws SQLException if a database access error occurs
7861     * @since 1.6
7862     */
7863    public void updateNClob(String columnName, NClob nClob) throws SQLException {
7864       throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7865    }
7866
7867    /**
7868     * Retrieves the value of the designated column in the current row
7869     * of this <code>ResultSet</code> object as a <code>NClob</code> object
7870     * in the Java programming language.
7871     *
7872     * @param i the first column is 1, the second is 2, ...
7873     * @return a <code>NClob</code> object representing the SQL
7874     *         <code>NCLOB</code> value in the specified column
7875     * @exception SQLException if a database access error occurs
7876     * @since 1.6
7877     */
7878    public NClob getNClob(int i) throws SQLException {
7879        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7880    }
7881
7882
7883   /**
7884     * Retrieves the value of the designated column in the current row
7885     * of this <code>ResultSet</code> object as a <code>NClob</code> object
7886     * in the Java programming language.
7887     *
7888     * @param colName the name of the column from which to retrieve the value
7889     * @return a <code>NClob</code> object representing the SQL <code>NCLOB</code>
7890     * value in the specified column
7891     * @exception SQLException if a database access error occurs
7892     * @since 1.6
7893     */
7894    public NClob getNClob(String colName) throws SQLException {
7895        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7896    }
7897
7898    public <T> T unwrap(java.lang.Class<T> iface) throws java.sql.SQLException {
7899        return null;
7900    }
7901
7902    public boolean isWrapperFor(Class<?> interfaces) throws SQLException {
7903        return false;
7904    }
7905
7906
7907   /**
7908      * Sets the designated parameter to the given <code>java.sql.SQLXML</code> object. The driver converts this to an
7909      * SQL <code>XML</code> value when it sends it to the database.
7910      * @param parameterIndex index of the first parameter is 1, the second is 2, ...
7911      * @param xmlObject a <code>SQLXML</code> object that maps an SQL <code>XML</code> value
7912      * @throws SQLException if a database access error occurs
7913      * @since 1.6
7914      */
7915     public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
7916         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7917     }
7918
7919   /**
7920     * Sets the designated parameter to the given <code>java.sql.SQLXML</code> object. The driver converts this to an
7921     * <code>SQL XML</code> value when it sends it to the database.
7922     * @param parameterName the name of the parameter
7923     * @param xmlObject a <code>SQLXML</code> object that maps an <code>SQL XML</code> value
7924     * @throws SQLException if a database access error occurs
7925     * @since 1.6
7926     */
7927    public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException {
7928         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7929     }
7930
7931
7932    /**
7933     * Sets the designated parameter to the given <code>java.sql.RowId</code> object. The
7934     * driver converts this to a SQL <code>ROWID</code> value when it sends it
7935     * to the database
7936     *
7937     * @param parameterIndex the first parameter is 1, the second is 2, ...
7938     * @param x the parameter value
7939     * @throws SQLException if a database access error occurs
7940     *
7941     * @since 1.6
7942     */
7943    public void setRowId(int parameterIndex, RowId x) throws SQLException {
7944         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7945     }
7946
7947
7948    /**
7949    * Sets the designated parameter to the given <code>java.sql.RowId</code> object. The
7950    * driver converts this to a SQL <code>ROWID</code> when it sends it to the
7951    * database.
7952    *
7953    * @param parameterName the name of the parameter
7954    * @param x the parameter value
7955    * @throws SQLException if a database access error occurs
7956    * @since 1.6
7957    */
7958   public void setRowId(String parameterName, RowId x) throws SQLException {
7959         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
7960     }
7961
7962
7963    /**
7964     * Sets the designated parameter to a <code>Reader</code> object. The
7965     * <code>Reader</code> reads the data till end-of-file is reached. The
7966     * driver does the necessary conversion from Java character format to
7967     * the national character set in the database.
7968
7969     * <P><B>Note:</B> This stream object can either be a standard
7970     * Java stream object or your own subclass that implements the
7971     * standard interface.
7972     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
7973     * it might be more efficient to use a version of
7974     * <code>setNCharacterStream</code> which takes a length parameter.
7975     *
7976     * @param parameterIndex of the first parameter is 1, the second is 2, ...
7977     * @param value the parameter value
7978     * @throws SQLException if the driver does not support national
7979     *         character sets;  if the driver can detect that a data conversion
7980     *  error could occur ; if a database access error occurs; or
7981     * this method is called on a closed <code>PreparedStatement</code>
7982     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
7983     * @since 1.6
7984     */
7985     public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
7986        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
7987     }
7988
7989
7990    /**
7991    * Sets the designated parameter to a <code>java.sql.NClob</code> object. The object
7992    * implements the <code>java.sql.NClob</code> interface. This <code>NClob</code>
7993    * object maps to a SQL <code>NCLOB</code>.
7994    * @param parameterName the name of the column to be set
7995    * @param value the parameter value
7996    * @throws SQLException if the driver does not support national
7997    *         character sets;  if the driver can detect that a data conversion
7998    *  error could occur; or if a database access error occurs
7999    * @since 1.6
8000    */
8001    public void setNClob(String parameterName, NClob value) throws SQLException {
8002         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8003     }
8004
8005
8006  /**
8007     * Retrieves the value of the designated column in the current row
8008     * of this <code>ResultSet</code> object as a
8009     * <code>java.io.Reader</code> object.
8010     * It is intended for use when
8011     * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8012     * and <code>LONGNVARCHAR</code> columns.
8013     *
8014     * @return a <code>java.io.Reader</code> object that contains the column
8015     * value; if the value is SQL <code>NULL</code>, the value returned is
8016     * <code>null</code> in the Java programming language.
8017     * @param columnIndex the first column is 1, the second is 2, ...
8018     * @exception SQLException if a database access error occurs
8019     * @since 1.6
8020     */
8021    public java.io.Reader getNCharacterStream(int columnIndex) throws SQLException {
8022       throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8023     }
8024
8025
8026    /**
8027     * Retrieves the value of the designated column in the current row
8028     * of this <code>ResultSet</code> object as a
8029     * <code>java.io.Reader</code> object.
8030     * It is intended for use when
8031     * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8032     * and <code>LONGNVARCHAR</code> columns.
8033     *
8034     * @param columnName the name of the column
8035     * @return a <code>java.io.Reader</code> object that contains the column
8036     * value; if the value is SQL <code>NULL</code>, the value returned is
8037     * <code>null</code> in the Java programming language
8038     * @exception SQLException if a database access error occurs
8039     * @since 1.6
8040     */
8041    public java.io.Reader getNCharacterStream(String columnName) throws SQLException {
8042       throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8043     }
8044
8045
8046    /**
8047     * Updates the designated column with a <code>java.sql.SQLXML</code> value.
8048     * The updater
8049     * methods are used to update column values in the current row or the insert
8050     * row. The updater methods do not update the underlying database; instead
8051     * the <code>updateRow</code> or <code>insertRow</code> methods are called
8052     * to update the database.
8053     * @param columnIndex the first column is 1, the second 2, ...
8054     * @param xmlObject the value for the column to be updated
8055     * @throws SQLException if a database access error occurs
8056     * @since 1.6
8057     */
8058    public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException {
8059        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8060    }
8061
8062    /**
8063     * Updates the designated column with a <code>java.sql.SQLXML</code> value.
8064     * The updater
8065     * methods are used to update column values in the current row or the insert
8066     * row. The updater methods do not update the underlying database; instead
8067     * the <code>updateRow</code> or <code>insertRow</code> methods are called
8068     * to update the database.
8069     *
8070     * @param columnName the name of the column
8071     * @param xmlObject the column value
8072     * @throws SQLException if a database access occurs
8073     * @since 1.6
8074     */
8075    public void updateSQLXML(String columnName, SQLXML xmlObject) throws SQLException {
8076        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8077    }
8078
8079     /**
8080     * Retrieves the value of the designated column in the current row
8081     * of this <code>ResultSet</code> object as
8082     * a <code>String</code> in the Java programming language.
8083     * It is intended for use when
8084     * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8085     * and <code>LONGNVARCHAR</code> columns.
8086     *
8087     * @param columnIndex the first column is 1, the second is 2, ...
8088     * @return the column value; if the value is SQL <code>NULL</code>, the
8089     * value returned is <code>null</code>
8090     * @exception SQLException if a database access error occurs
8091     * @since 1.6
8092     */
8093    public String getNString(int columnIndex) throws SQLException {
8094        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8095    }
8096
8097    /**
8098     * Retrieves the value of the designated column in the current row
8099     * of this <code>ResultSet</code> object as
8100     * a <code>String</code> in the Java programming language.
8101     * It is intended for use when
8102     * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
8103     * and <code>LONGNVARCHAR</code> columns.
8104     *
8105     * @param columnName the SQL name of the column
8106     * @return the column value; if the value is SQL <code>NULL</code>, the
8107     * value returned is <code>null</code>
8108     * @exception SQLException if a database access error occurs
8109     * @since 1.6
8110     */
8111    public String getNString(String columnName) throws SQLException {
8112        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8113    }
8114
8115     /**
8116       * Updates the designated column with a character stream value, which will
8117       * have the specified number of bytes. The driver does the necessary conversion
8118       * from Java character format to the national character set in the database.
8119       * It is intended for use when updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
8120       * The updater methods are used to update column values in the current row or
8121       * the insert row. The updater methods do not update the underlying database;
8122       * instead the updateRow or insertRow methods are called to update the database.
8123       *
8124       * @param columnIndex - the first column is 1, the second is 2, ...
8125       * @param x - the new column value
8126       * @param length - the length of the stream
8127       * @exception SQLException if a database access error occurs
8128       * @since 1.6
8129       */
8130       public void updateNCharacterStream(int columnIndex,
8131                            java.io.Reader x,
8132                            long length)
8133                            throws SQLException {
8134          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8135       }
8136
8137     /**
8138       * Updates the designated column with a character stream value, which will
8139       * have the specified number of bytes. The driver does the necessary conversion
8140       * from Java character format to the national character set in the database.
8141       * It is intended for use when updating NCHAR,NVARCHAR and LONGNVARCHAR columns.
8142       * The updater methods are used to update column values in the current row or
8143       * the insert row. The updater methods do not update the underlying database;
8144       * instead the updateRow or insertRow methods are called to update the database.
8145       *
8146       * @param columnName - name of the Column
8147       * @param x - the new column value
8148       * @param length - the length of the stream
8149       * @exception SQLException if a database access error occurs
8150       * @since 1.6
8151       */
8152       public void updateNCharacterStream(String columnName,
8153                            java.io.Reader x,
8154                            long length)
8155                            throws SQLException {
8156          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString());
8157       }
8158
8159     /**
8160     * Updates the designated column with a character stream value.   The
8161     * driver does the necessary conversion from Java character format to
8162     * the national character set in the database.
8163     * It is intended for use when
8164     * updating  <code>NCHAR</code>,<code>NVARCHAR</code>
8165     * and <code>LONGNVARCHAR</code> columns.
8166     *
8167     * The updater methods are used to update column values in the
8168     * current row or the insert row.  The updater methods do not
8169     * update the underlying database; instead the <code>updateRow</code> or
8170     * <code>insertRow</code> methods are called to update the database.
8171     *
8172     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8173     * it might be more efficient to use a version of
8174     * <code>updateNCharacterStream</code> which takes a length parameter.
8175     *
8176     * @param columnIndex the first column is 1, the second is 2, ...
8177     * @param x the new column value
8178     * @exception SQLException if a database access error occurs,
8179     * the result set concurrency is <code>CONCUR_READ_ONLY</code> or this method is called on a closed result set
8180     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8181     * this method
8182     * @since 1.6
8183     */
8184    public void updateNCharacterStream(int columnIndex,
8185                             java.io.Reader x) throws SQLException {
8186        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8187    }
8188
8189    /**
8190     * Updates the designated column with a character stream value.  The
8191     * driver does the necessary conversion from Java character format to
8192     * the national character set in the database.
8193     * It is intended for use when
8194     * updating  <code>NCHAR</code>,<code>NVARCHAR</code>
8195     * and <code>LONGNVARCHAR</code> columns.
8196     *
8197     * The updater methods are used to update column values in the
8198     * current row or the insert row.  The updater methods do not
8199     * update the underlying database; instead the <code>updateRow</code> or
8200     * <code>insertRow</code> methods are called to update the database.
8201     *
8202     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8203     * it might be more efficient to use a version of
8204     * <code>updateNCharacterStream</code> which takes a length parameter.
8205     *
8206     * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8207bel is the name of the column
8208     * @param reader the <code>java.io.Reader</code> object containing
8209     *        the new column value
8210     * @exception SQLException if a database access error occurs,
8211     * the result set concurrency is <code>CONCUR_READ_ONLY</code> or this method is called on a closed result set
8212      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8213     * this method
8214     * @since 1.6
8215     */
8216    public void updateNCharacterStream(String columnLabel,
8217                             java.io.Reader reader) throws SQLException {
8218        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8219    }
8220
8221//////////////////////////
8222
8223    /**
8224     * Updates the designated column using the given input stream, which
8225     * will have the specified number of bytes.
8226     * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8227     * parameter, it may be more practical to send it via a
8228     * <code>java.io.InputStream</code>. Data will be read from the stream
8229     * as needed until end-of-file is reached.  The JDBC driver will
8230     * do any necessary conversion from ASCII to the database char format.
8231     *
8232     * <P><B>Note:</B> This stream object can either be a standard
8233     * Java stream object or your own subclass that implements the
8234     * standard interface.
8235     * <p>
8236     * The updater methods are used to update column values in the
8237     * current row or the insert row.  The updater methods do not
8238     * update the underlying database; instead the <code>updateRow</code> or
8239     * <code>insertRow</code> methods are called to update the database.
8240     *
8241     * @param columnIndex the first column is 1, the second is 2, ...
8242     * @param inputStream An object that contains the data to set the parameter
8243     * value to.
8244     * @param length the number of bytes in the parameter data.
8245     * @exception SQLException if a database access error occurs,
8246     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8247     * or this method is called on a closed result set
8248     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8249     * this method
8250     * @since 1.6
8251     */
8252    public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException{
8253        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8254    }
8255
8256    /**
8257     * Updates the designated column using the given input stream, which
8258     * will have the specified number of bytes.
8259     * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8260     * parameter, it may be more practical to send it via a
8261     * <code>java.io.InputStream</code>. Data will be read from the stream
8262     * as needed until end-of-file is reached.  The JDBC driver will
8263     * do any necessary conversion from ASCII to the database char format.
8264     *
8265     * <P><B>Note:</B> This stream object can either be a standard
8266     * Java stream object or your own subclass that implements the
8267     * standard interface.
8268     * <p>
8269     * The updater methods are used to update column values in the
8270     * current row or the insert row.  The updater methods do not
8271     * update the underlying database; instead the <code>updateRow</code> or
8272     * <code>insertRow</code> methods are called to update the database.
8273     *
8274     * @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
8275     * @param inputStream An object that contains the data to set the parameter
8276     * value to.
8277     * @param length the number of bytes in the parameter data.
8278     * @exception SQLException if a database access error occurs,
8279     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8280     * or this method is called on a closed result set
8281     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8282     * this method
8283     * @since 1.6
8284     */
8285    public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException {
8286        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8287    }
8288
8289    /**
8290     * Updates the designated column using the given input stream.
8291     * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8292     * parameter, it may be more practical to send it via a
8293     * <code>java.io.InputStream</code>. Data will be read from the stream
8294     * as needed until end-of-file is reached.  The JDBC driver will
8295     * do any necessary conversion from ASCII to the database char format.
8296     *
8297     * <P><B>Note:</B> This stream object can either be a standard
8298     * Java stream object or your own subclass that implements the
8299     * standard interface.
8300     *
8301     *  <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8302     * it might be more efficient to use a version of
8303     * <code>updateBlob</code> which takes a length parameter.
8304     * <p>
8305     * The updater methods are used to update column values in the
8306     * current row or the insert row.  The updater methods do not
8307     * update the underlying database; instead the <code>updateRow</code> or
8308     * <code>insertRow</code> methods are called to update the database.
8309     *
8310     * @param columnIndex the first column is 1, the second is 2, ...
8311     * @param inputStream An object that contains the data to set the parameter
8312     * value to.
8313     * @exception SQLException if a database access error occurs,
8314     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8315     * or this method is called on a closed result set
8316     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8317     * this method
8318     * @since 1.6
8319     */
8320    public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException {
8321        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8322    }
8323
8324    /**
8325     * Updates the designated column using the given input stream.
8326     * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
8327     * parameter, it may be more practical to send it via a
8328     * <code>java.io.InputStream</code>. Data will be read from the stream
8329     * as needed until end-of-file is reached.  The JDBC driver will
8330     * do any necessary conversion from ASCII to the database char format.
8331     *
8332     * <P><B>Note:</B> This stream object can either be a standard
8333     * Java stream object or your own subclass that implements the
8334     * standard interface.
8335     *   <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8336     * it might be more efficient to use a version of
8337     * <code>updateBlob</code> which takes a length parameter.
8338     * <p>
8339     * The updater methods are used to update column values in the
8340     * current row or the insert row.  The updater methods do not
8341     * update the underlying database; instead the <code>updateRow</code> or
8342     * <code>insertRow</code> methods are called to update the database.
8343     *
8344     * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8345bel is the name of the column
8346     * @param inputStream An object that contains the data to set the parameter
8347     * value to.
8348     * @exception SQLException if a database access error occurs,
8349     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8350     * or this method is called on a closed result set
8351     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8352     * this method
8353     * @since 1.6
8354     */
8355    public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException {
8356        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8357    }
8358
8359    /**
8360     * Updates the designated column using the given <code>Reader</code>
8361     * object, which is the given number of characters long.
8362     * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8363     * parameter, it may be more practical to send it via a
8364     * <code>java.io.Reader</code> object. The data will be read from the stream
8365     * as needed until end-of-file is reached.  The JDBC driver will
8366     * do any necessary conversion from UNICODE to the database char format.
8367     *
8368     * <P><B>Note:</B> This stream object can either be a standard
8369     * Java stream object or your own subclass that implements the
8370     * standard interface.
8371     * <p>
8372     * The updater methods are used to update column values in the
8373     * current row or the insert row.  The updater methods do not
8374     * update the underlying database; instead the <code>updateRow</code> or
8375     * <code>insertRow</code> methods are called to update the database.
8376     *
8377     * @param columnIndex the first column is 1, the second is 2, ...
8378     * @param reader An object that contains the data to set the parameter value to.
8379     * @param length the number of characters in the parameter data.
8380     * @exception SQLException if a database access error occurs,
8381     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8382     * or this method is called on a closed result set
8383     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8384     * this method
8385     * @since 1.6
8386     */
8387    public void updateClob(int columnIndex,  Reader reader, long length) throws SQLException {
8388        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8389    }
8390
8391    /**
8392     * Updates the designated column using the given <code>Reader</code>
8393     * object, which is the given number of characters long.
8394     * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8395     * parameter, it may be more practical to send it via a
8396     * <code>java.io.Reader</code> object. The data will be read from the stream
8397     * as needed until end-of-file is reached.  The JDBC driver will
8398     * do any necessary conversion from UNICODE to the database char format.
8399     *
8400     * <P><B>Note:</B> This stream object can either be a standard
8401     * Java stream object or your own subclass that implements the
8402     * standard interface.
8403     * <p>
8404     * The updater methods are used to update column values in the
8405     * current row or the insert row.  The updater methods do not
8406     * update the underlying database; instead the <code>updateRow</code> or
8407     * <code>insertRow</code> methods are called to update the database.
8408     *
8409     * @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
8410     * @param reader An object that contains the data to set the parameter value to.
8411     * @param length the number of characters in the parameter data.
8412     * @exception SQLException if a database access error occurs,
8413     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8414     * or this method is called on a closed result set
8415     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8416     * this method
8417     * @since 1.6
8418     */
8419    public void updateClob(String columnLabel,  Reader reader, long length) throws SQLException {
8420        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8421    }
8422
8423   /**
8424     * Updates the designated column using the given <code>Reader</code>
8425     * object.
8426     * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8427     * parameter, it may be more practical to send it via a
8428     * <code>java.io.Reader</code> object. The data will be read from the stream
8429     * as needed until end-of-file is reached.  The JDBC driver will
8430     * do any necessary conversion from UNICODE to the database char format.
8431     *
8432     * <P><B>Note:</B> This stream object can either be a standard
8433     * Java stream object or your own subclass that implements the
8434     * standard interface.
8435     *   <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8436     * it might be more efficient to use a version of
8437     * <code>updateClob</code> which takes a length parameter.
8438     * <p>
8439     * The updater methods are used to update column values in the
8440     * current row or the insert row.  The updater methods do not
8441     * update the underlying database; instead the <code>updateRow</code> or
8442     * <code>insertRow</code> methods are called to update the database.
8443     *
8444     * @param columnIndex the first column is 1, the second is 2, ...
8445     * @param reader An object that contains the data to set the parameter value to.
8446     * @exception SQLException if a database access error occurs,
8447     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8448     * or this method is called on a closed result set
8449     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8450     * this method
8451     * @since 1.6
8452     */
8453    public void updateClob(int columnIndex,  Reader reader) throws SQLException {
8454        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8455    }
8456
8457    /**
8458     * Updates the designated column using the given <code>Reader</code>
8459     * object.
8460     * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8461     * parameter, it may be more practical to send it via a
8462     * <code>java.io.Reader</code> object. The data will be read from the stream
8463     * as needed until end-of-file is reached.  The JDBC driver will
8464     * do any necessary conversion from UNICODE to the database char format.
8465     *
8466     * <P><B>Note:</B> This stream object can either be a standard
8467     * Java stream object or your own subclass that implements the
8468     * standard interface.
8469     *  <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8470     * it might be more efficient to use a version of
8471     * <code>updateClob</code> which takes a length parameter.
8472     * <p>
8473     * The updater methods are used to update column values in the
8474     * current row or the insert row.  The updater methods do not
8475     * update the underlying database; instead the <code>updateRow</code> or
8476     * <code>insertRow</code> methods are called to update the database.
8477     *
8478     * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8479bel is the name of the column
8480     * @param reader An object that contains the data to set the parameter value to.
8481     * @exception SQLException if a database access error occurs,
8482     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8483     * or this method is called on a closed result set
8484     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8485     * this method
8486     * @since 1.6
8487     */
8488    public void updateClob(String columnLabel,  Reader reader) throws SQLException {
8489        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8490    }
8491
8492   /**
8493     * Updates the designated column using the given <code>Reader</code>
8494     * object, which is the given number of characters long.
8495     * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8496     * parameter, it may be more practical to send it via a
8497     * <code>java.io.Reader</code> object. The data will be read from the stream
8498     * as needed until end-of-file is reached.  The JDBC driver will
8499     * do any necessary conversion from UNICODE to the database char format.
8500     *
8501     * <P><B>Note:</B> This stream object can either be a standard
8502     * Java stream object or your own subclass that implements the
8503     * standard interface.
8504     * <p>
8505     * The updater methods are used to update column values in the
8506     * current row or the insert row.  The updater methods do not
8507     * update the underlying database; instead the <code>updateRow</code> or
8508     * <code>insertRow</code> methods are called to update the database.
8509     *
8510     * @param columnIndex the first column is 1, the second 2, ...
8511     * @param reader An object that contains the data to set the parameter value to.
8512     * @param length the number of characters in the parameter data.
8513     * @throws SQLException if the driver does not support national
8514     *         character sets;  if the driver can detect that a data conversion
8515     *  error could occur; this method is called on a closed result set,
8516     * if a database access error occurs or
8517     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8518     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8519     * this method
8520     * @since 1.6
8521     */
8522    public void updateNClob(int columnIndex,  Reader reader, long length) throws SQLException {
8523        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8524    }
8525
8526    /**
8527     * Updates the designated column using the given <code>Reader</code>
8528     * object, which is the given number of characters long.
8529     * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8530     * parameter, it may be more practical to send it via a
8531     * <code>java.io.Reader</code> object. The data will be read from the stream
8532     * as needed until end-of-file is reached.  The JDBC driver will
8533     * do any necessary conversion from UNICODE to the database char format.
8534     *
8535     * <P><B>Note:</B> This stream object can either be a standard
8536     * Java stream object or your own subclass that implements the
8537     * standard interface.
8538     * <p>
8539     * The updater methods are used to update column values in the
8540     * current row or the insert row.  The updater methods do not
8541     * update the underlying database; instead the <code>updateRow</code> or
8542     * <code>insertRow</code> methods are called to update the database.
8543     *
8544     * @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
8545     * @param reader An object that contains the data to set the parameter value to.
8546     * @param length the number of characters in the parameter data.
8547     * @throws SQLException if the driver does not support national
8548     *         character sets;  if the driver can detect that a data conversion
8549     *  error could occur; this method is called on a closed result set;
8550     *  if a database access error occurs or
8551     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8552     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8553     * this method
8554     * @since 1.6
8555     */
8556    public void updateNClob(String columnLabel,  Reader reader, long length) throws SQLException {
8557        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8558    }
8559
8560    /**
8561     * Updates the designated column using the given <code>Reader</code>
8562     * object.
8563     * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8564     * parameter, it may be more practical to send it via a
8565     * <code>java.io.Reader</code> object. The data will be read from the stream
8566     * as needed until end-of-file is reached.  The JDBC driver will
8567     * do any necessary conversion from UNICODE to the database char format.
8568     *
8569     * <P><B>Note:</B> This stream object can either be a standard
8570     * Java stream object or your own subclass that implements the
8571     * standard interface.
8572     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8573     * it might be more efficient to use a version of
8574     * <code>updateNClob</code> which takes a length parameter.
8575     * <p>
8576     * The updater methods are used to update column values in the
8577     * current row or the insert row.  The updater methods do not
8578     * update the underlying database; instead the <code>updateRow</code> or
8579     * <code>insertRow</code> methods are called to update the database.
8580     *
8581     * @param columnIndex the first column is 1, the second 2, ...
8582     * @param reader An object that contains the data to set the parameter value to.
8583     * @throws SQLException if the driver does not support national
8584     *         character sets;  if the driver can detect that a data conversion
8585     *  error could occur; this method is called on a closed result set,
8586     * if a database access error occurs or
8587     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8588     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8589     * this method
8590     * @since 1.6
8591     */
8592    public void updateNClob(int columnIndex,  Reader reader) throws SQLException {
8593        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8594    }
8595
8596    /**
8597     * Updates the designated column using the given <code>Reader</code>
8598     * object.
8599     * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
8600     * parameter, it may be more practical to send it via a
8601     * <code>java.io.Reader</code> object. The data will be read from the stream
8602     * as needed until end-of-file is reached.  The JDBC driver will
8603     * do any necessary conversion from UNICODE to the database char format.
8604     *
8605     * <P><B>Note:</B> This stream object can either be a standard
8606     * Java stream object or your own subclass that implements the
8607     * standard interface.
8608     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8609     * it might be more efficient to use a version of
8610     * <code>updateNClob</code> which takes a length parameter.
8611     * <p>
8612     * The updater methods are used to update column values in the
8613     * current row or the insert row.  The updater methods do not
8614     * update the underlying database; instead the <code>updateRow</code> or
8615     * <code>insertRow</code> methods are called to update the database.
8616     *
8617     * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8618bel is the name of the column
8619     * @param reader An object that contains the data to set the parameter value to.
8620     * @throws SQLException if the driver does not support national
8621     *         character sets;  if the driver can detect that a data conversion
8622     *  error could occur; this method is called on a closed result set;
8623     *  if a database access error occurs or
8624     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8625     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8626     * this method
8627     * @since 1.6
8628     */
8629    public void updateNClob(String columnLabel,  Reader reader) throws SQLException {
8630        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8631    }
8632
8633        /**
8634     * Updates the designated column with an ascii stream value, which will have
8635     * the specified number of bytes.
8636     * The updater methods are used to update column values in the
8637     * current row or the insert row.  The updater methods do not
8638     * update the underlying database; instead the <code>updateRow</code> or
8639     * <code>insertRow</code> methods are called to update the database.
8640     *
8641     * @param columnIndex the first column is 1, the second is 2, ...
8642     * @param x the new column value
8643     * @param length the length of the stream
8644     * @exception SQLException if a database access error occurs,
8645     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8646     * or this method is called on a closed result set
8647     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8648     * this method
8649     * @since 1.6
8650     */
8651    public void updateAsciiStream(int columnIndex,
8652                           java.io.InputStream x,
8653                           long length) throws SQLException {
8654
8655    }
8656
8657    /**
8658     * Updates the designated column with a binary stream value, which will have
8659     * the specified number of bytes.
8660     * The updater methods are used to update column values in the
8661     * current row or the insert row.  The updater methods do not
8662     * update the underlying database; instead the <code>updateRow</code> or
8663     * <code>insertRow</code> methods are called to update the database.
8664     *
8665     * @param columnIndex the first column is 1, the second is 2, ...
8666     * @param x the new column value
8667     * @param length the length of the stream
8668     * @exception SQLException if a database access error occurs,
8669     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8670     * or this method is called on a closed result set
8671     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8672     * this method
8673     * @since 1.6
8674     */
8675    public void updateBinaryStream(int columnIndex,
8676                            java.io.InputStream x,
8677                            long length) throws SQLException {
8678    }
8679
8680    /**
8681     * Updates the designated column with a character stream value, which will have
8682     * the specified number of bytes.
8683     * The updater methods are used to update column values in the
8684     * current row or the insert row.  The updater methods do not
8685     * update the underlying database; instead the <code>updateRow</code> or
8686     * <code>insertRow</code> methods are called to update the database.
8687     *
8688     * @param columnIndex the first column is 1, the second is 2, ...
8689     * @param x the new column value
8690     * @param length the length of the stream
8691     * @exception SQLException if a database access error occurs,
8692     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8693     * or this method is called on a closed result set
8694     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8695     * this method
8696     * @since 1.6
8697     */
8698    public void updateCharacterStream(int columnIndex,
8699                             java.io.Reader x,
8700                             long length) throws SQLException {
8701        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8702    }
8703
8704    /**
8705     * Updates the designated column with a character stream value, which will have
8706     * the specified number of bytes.
8707     * The updater methods are used to update column values in the
8708     * current row or the insert row.  The updater methods do not
8709     * update the underlying database; instead the <code>updateRow</code> or
8710     * <code>insertRow</code> methods are called to update the database.
8711     *
8712     * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8713bel is the name of the column
8714     * @param reader the <code>java.io.Reader</code> object containing
8715     *        the new column value
8716     * @param length the length of the stream
8717     * @exception SQLException if a database access error occurs,
8718     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8719     * or this method is called on a closed result set
8720     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8721     * this method
8722     * @since 1.6
8723     */
8724    public void updateCharacterStream(String columnLabel,
8725                             java.io.Reader reader,
8726                             long length) throws SQLException {
8727        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8728    }
8729     /**
8730     * Updates the designated column with an ascii stream value, which will have
8731     * the specified number of bytes..
8732     * The updater methods are used to update column values in the
8733     * current row or the insert row.  The updater methods do not
8734     * update the underlying database; instead the <code>updateRow</code> or
8735     * <code>insertRow</code> methods are called to update the database.
8736     *
8737     * @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
8738     * @param x the new column value
8739     * @param length the length of the stream
8740     * @exception SQLException if a database access error occurs,
8741     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8742     * or this method is called on a closed result set
8743     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8744     * this method
8745     * @since 1.6
8746     */
8747    public void updateAsciiStream(String columnLabel,
8748                           java.io.InputStream x,
8749                           long length) throws SQLException {
8750    }
8751
8752    /**
8753     * Updates the designated column with a binary stream value, which will have
8754     * the specified number of bytes.
8755     * The updater methods are used to update column values in the
8756     * current row or the insert row.  The updater methods do not
8757     * update the underlying database; instead the <code>updateRow</code> or
8758     * <code>insertRow</code> methods are called to update the database.
8759     *
8760     * @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
8761     * @param x the new column value
8762     * @param length the length of the stream
8763     * @exception SQLException if a database access error occurs,
8764     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8765     * or this method is called on a closed result set
8766     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8767     * this method
8768     * @since 1.6
8769     */
8770    public void updateBinaryStream(String columnLabel,
8771                            java.io.InputStream x,
8772                            long length) throws SQLException {
8773    }
8774
8775    /**
8776     * Updates the designated column with a binary stream value.
8777     * The updater methods are used to update column values in the
8778     * current row or the insert row.  The updater methods do not
8779     * update the underlying database; instead the <code>updateRow</code> or
8780     * <code>insertRow</code> methods are called to update the database.
8781     *
8782     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8783     * it might be more efficient to use a version of
8784     * <code>updateBinaryStream</code> which takes a length parameter.
8785     *
8786     * @param columnIndex the first column is 1, the second is 2, ...
8787     * @param x the new column value
8788     * @exception SQLException if a database access error occurs,
8789     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8790     * or this method is called on a closed result set
8791     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8792     * this method
8793     * @since 1.6
8794     */
8795    public void updateBinaryStream(int columnIndex,
8796                            java.io.InputStream x) throws SQLException {
8797        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8798    }
8799
8800
8801    /**
8802     * Updates the designated column with a binary stream value.
8803     * The updater methods are used to update column values in the
8804     * current row or the insert row.  The updater methods do not
8805     * update the underlying database; instead the <code>updateRow</code> or
8806     * <code>insertRow</code> methods are called to update the database.
8807     *
8808     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8809     * it might be more efficient to use a version of
8810     * <code>updateBinaryStream</code> which takes a length parameter.
8811     *
8812     * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8813bel is the name of the column
8814     * @param x the new column value
8815     * @exception SQLException if a database access error occurs,
8816     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8817     * or this method is called on a closed result set
8818     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8819     * this method
8820     * @since 1.6
8821     */
8822    public void updateBinaryStream(String columnLabel,
8823                            java.io.InputStream x) throws SQLException {
8824        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8825    }
8826
8827    /**
8828     * Updates the designated column with a character stream value.
8829     * The updater methods are used to update column values in the
8830     * current row or the insert row.  The updater methods do not
8831     * update the underlying database; instead the <code>updateRow</code> or
8832     * <code>insertRow</code> methods are called to update the database.
8833     *
8834     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8835     * it might be more efficient to use a version of
8836     * <code>updateCharacterStream</code> which takes a length parameter.
8837     *
8838     * @param columnIndex the first column is 1, the second is 2, ...
8839     * @param x the new column value
8840     * @exception SQLException if a database access error occurs,
8841     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8842     * or this method is called on a closed result set
8843     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8844     * this method
8845     * @since 1.6
8846     */
8847    public void updateCharacterStream(int columnIndex,
8848                             java.io.Reader x) throws SQLException {
8849        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8850    }
8851
8852    /**
8853     * Updates the designated column with a character stream value.
8854     * The updater methods are used to update column values in the
8855     * current row or the insert row.  The updater methods do not
8856     * update the underlying database; instead the <code>updateRow</code> or
8857     * <code>insertRow</code> methods are called to update the database.
8858     *
8859     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8860     * it might be more efficient to use a version of
8861     * <code>updateCharacterStream</code> which takes a length parameter.
8862     *
8863     * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8864bel is the name of the column
8865     * @param reader the <code>java.io.Reader</code> object containing
8866     *        the new column value
8867     * @exception SQLException if a database access error occurs,
8868     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8869     * or this method is called on a closed result set
8870     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8871     * this method
8872     * @since 1.6
8873     */
8874    public void updateCharacterStream(String columnLabel,
8875                             java.io.Reader reader) throws SQLException {
8876        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8877    }
8878
8879    /**
8880     * Updates the designated column with an ascii stream value.
8881     * The updater methods are used to update column values in the
8882     * current row or the insert row.  The updater methods do not
8883     * update the underlying database; instead the <code>updateRow</code> or
8884     * <code>insertRow</code> methods are called to update the database.
8885     *
8886     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8887     * it might be more efficient to use a version of
8888     * <code>updateAsciiStream</code> which takes a length parameter.
8889     *
8890     * @param columnIndex the first column is 1, the second is 2, ...
8891     * @param x the new column value
8892     * @exception SQLException if a database access error occurs,
8893     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8894     * or this method is called on a closed result set
8895     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8896     * this method
8897     * @since 1.6
8898     */
8899    public void updateAsciiStream(int columnIndex,
8900                           java.io.InputStream x) throws SQLException {
8901        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8902    }
8903
8904    /**
8905     * Updates the designated column with an ascii stream value.
8906     * The updater methods are used to update column values in the
8907     * current row or the insert row.  The updater methods do not
8908     * update the underlying database; instead the <code>updateRow</code> or
8909     * <code>insertRow</code> methods are called to update the database.
8910     *
8911     * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8912     * it might be more efficient to use a version of
8913     * <code>updateAsciiStream</code> which takes a length parameter.
8914     *
8915     * @param columnLabel the label for the column specified with the SQL AS clause.  If the SQL AS clause was not specified, then the la
8916bel is the name of the column
8917     * @param x the new column value
8918     * @exception SQLException if a database access error occurs,
8919     * the result set concurrency is <code>CONCUR_READ_ONLY</code>
8920     * or this method is called on a closed result set
8921     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8922     * this method
8923     * @since 1.6
8924     */
8925    public void updateAsciiStream(String columnLabel,
8926                           java.io.InputStream x) throws SQLException {
8927
8928    }
8929
8930   /**
8931  * Sets the designated parameter to the given <code>java.net.URL</code> value.
8932  * The driver converts this to an SQL <code>DATALINK</code> value
8933  * when it sends it to the database.
8934  *
8935  * @param parameterIndex the first parameter is 1, the second is 2, ...
8936  * @param x the <code>java.net.URL</code> object to be set
8937  * @exception SQLException if a database access error occurs or
8938  * this method is called on a closed <code>PreparedStatement</code>
8939  * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
8940  * @since 1.4
8941  */
8942  public void setURL(int parameterIndex, java.net.URL x) throws SQLException{
8943        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8944   }
8945
8946  /**
8947  * Sets the designated parameter to a <code>Reader</code> object.
8948  * This method differs from the <code>setCharacterStream (int, Reader)</code> method
8949  * because it informs the driver that the parameter value should be sent to
8950  * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
8951  * driver may have to do extra work to determine whether the parameter
8952  * data should be sent to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
8953  * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
8954  * it might be more efficient to use a version of
8955  * <code>setNClob</code> which takes a length parameter.
8956  *
8957  * @param parameterIndex index of the first parameter is 1, the second is 2, ...
8958  * @param reader An object that contains the data to set the parameter value to.
8959  * @throws SQLException if parameterIndex does not correspond to a parameter
8960  * marker in the SQL statement;
8961  * if the driver does not support national character sets;
8962  * if the driver can detect that a data conversion
8963  *  error could occur;  if a database access error occurs or
8964  * this method is called on a closed <code>PreparedStatement</code>
8965  * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
8966  *
8967  * @since 1.6
8968  */
8969  public void setNClob(int parameterIndex, Reader reader)
8970    throws SQLException{
8971        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
8972   }
8973
8974  /**
8975  * Sets the designated parameter to a <code>Reader</code> object.  The <code>reader</code> must contain  the number
8976             * of characters specified by length otherwise a <code>SQLException</code> will be
8977            * generated when the <code>CallableStatement</code> is executed.
8978            * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
8979            * because it informs the driver that the parameter value should be sent to
8980            * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
8981            * driver may have to do extra work to determine whether the parameter
8982            * data should be send to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
8983            *
8984            * @param parameterName the name of the parameter to be set
8985            * @param reader An object that contains the data to set the parameter value to.
8986            * @param length the number of characters in the parameter data.
8987            * @throws SQLException if parameterIndex does not correspond to a parameter
8988            * marker in the SQL statement; if the length specified is less than zero;
8989            * if the driver does not support national
8990            *         character sets;  if the driver can detect that a data conversion
8991            *  error could occur; if a database access error occurs or
8992            * this method is called on a closed <code>CallableStatement</code>
8993            * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
8994            * this method
8995            * @since 1.6
8996            */
8997            public void setNClob(String parameterName, Reader reader, long length)
8998    throws SQLException{
8999        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9000   }
9001
9002
9003 /**
9004  * Sets the designated parameter to a <code>Reader</code> object.
9005  * This method differs from the <code>setCharacterStream (int, Reader)</code> method
9006  * because it informs the driver that the parameter value should be sent to
9007  * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9008  * driver may have to do extra work to determine whether the parameter
9009  * data should be send to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
9010  * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9011  * it might be more efficient to use a version of
9012  * <code>setNClob</code> which takes a length parameter.
9013  *
9014  * @param parameterName the name of the parameter
9015  * @param reader An object that contains the data to set the parameter value to.
9016  * @throws SQLException if the driver does not support national character sets;
9017  * if the driver can detect that a data conversion
9018  *  error could occur;  if a database access error occurs or
9019  * this method is called on a closed <code>CallableStatement</code>
9020  * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9021  *
9022  * @since 1.6
9023  */
9024  public void setNClob(String parameterName, Reader reader)
9025    throws SQLException{
9026        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9027   }
9028
9029
9030    /**
9031     * Sets the designated parameter to a <code>Reader</code> object.  The reader must contain  the number
9032     * of characters specified by length otherwise a <code>SQLException</code> will be
9033     * generated when the <code>PreparedStatement</code> is executed.
9034     * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
9035     * because it informs the driver that the parameter value should be sent to
9036     * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9037     * driver may have to do extra work to determine whether the parameter
9038     * data should be sent to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
9039     * @param parameterIndex index of the first parameter is 1, the second is 2, ...
9040     * @param reader An object that contains the data to set the parameter value to.
9041     * @param length the number of characters in the parameter data.
9042     * @throws SQLException if parameterIndex does not correspond to a parameter
9043     * marker in the SQL statement; if the length specified is less than zero;
9044     * if the driver does not support national character sets;
9045     * if the driver can detect that a data conversion
9046     *  error could occur;  if a database access error occurs or
9047     * this method is called on a closed <code>PreparedStatement</code>
9048     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9049     *
9050     * @since 1.6
9051     */
9052     public void setNClob(int parameterIndex, Reader reader, long length)
9053       throws SQLException{
9054        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9055   }
9056
9057
9058    /**
9059     * Sets the designated parameter to a <code>java.sql.NClob</code> object. The driver converts this to
9060a
9061     * SQL <code>NCLOB</code> value when it sends it to the database.
9062     * @param parameterIndex of the first parameter is 1, the second is 2, ...
9063     * @param value the parameter value
9064     * @throws SQLException if the driver does not support national
9065     *         character sets;  if the driver can detect that a data conversion
9066     *  error could occur ; or if a database access error occurs
9067     * @since 1.6
9068     */
9069     public void setNClob(int parameterIndex, NClob value) throws SQLException{
9070        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9071   }
9072
9073
9074   /**
9075  * Sets the designated parameter to the given <code>String</code> object.
9076  * The driver converts this to a SQL <code>NCHAR</code> or
9077  * <code>NVARCHAR</code> or <code>LONGNVARCHAR</code> value
9078  * (depending on the argument's
9079  * size relative to the driver's limits on <code>NVARCHAR</code> values)
9080  * when it sends it to the database.
9081  *
9082  * @param parameterIndex of the first parameter is 1, the second is 2, ...
9083  * @param value the parameter value
9084  * @throws SQLException if the driver does not support national
9085  *         character sets;  if the driver can detect that a data conversion
9086  *  error could occur ; or if a database access error occurs
9087  * @since 1.6
9088  */
9089  public void setNString(int parameterIndex, String value) throws SQLException{
9090        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9091   }
9092
9093
9094 /**
9095  * Sets the designated parameter to the given <code>String</code> object.
9096  * The driver converts this to a SQL <code>NCHAR</code> or
9097  * <code>NVARCHAR</code> or <code>LONGNVARCHAR</code>
9098  * @param parameterName the name of the column to be set
9099  * @param value the parameter value
9100  * @throws SQLException if the driver does not support national
9101  *         character sets;  if the driver can detect that a data conversion
9102  *  error could occur; or if a database access error occurs
9103  * @since 1.6
9104  */
9105 public void setNString(String parameterName, String value)
9106         throws SQLException{
9107        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9108   }
9109
9110
9111 /**
9112  * Sets the designated parameter to a <code>Reader</code> object. The
9113  * <code>Reader</code> reads the data till end-of-file is reached. The
9114  * driver does the necessary conversion from Java character format to
9115  * the national character set in the database.
9116  * @param parameterIndex of the first parameter is 1, the second is 2, ...
9117  * @param value the parameter value
9118  * @param length the number of characters in the parameter data.
9119  * @throws SQLException if the driver does not support national
9120  *         character sets;  if the driver can detect that a data conversion
9121  *  error could occur ; or if a database access error occurs
9122  * @since 1.6
9123  */
9124  public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException{
9125        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9126   }
9127
9128
9129 /**
9130  * Sets the designated parameter to a <code>Reader</code> object. The
9131  * <code>Reader</code> reads the data till end-of-file is reached. The
9132  * driver does the necessary conversion from Java character format to
9133  * the national character set in the database.
9134  * @param parameterName the name of the column to be set
9135  * @param value the parameter value
9136  * @param length the number of characters in the parameter data.
9137  * @throws SQLException if the driver does not support national
9138  *         character sets;  if the driver can detect that a data conversion
9139  *  error could occur; or if a database access error occurs
9140  * @since 1.6
9141  */
9142 public void setNCharacterStream(String parameterName, Reader value, long length)
9143         throws SQLException{
9144        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9145   }
9146
9147  /**
9148  * Sets the designated parameter to a <code>Reader</code> object. The
9149  * <code>Reader</code> reads the data till end-of-file is reached. The
9150  * driver does the necessary conversion from Java character format to
9151  * the national character set in the database.
9152
9153  * <P><B>Note:</B> This stream object can either be a standard
9154  * Java stream object or your own subclass that implements the
9155  * standard interface.
9156  * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9157  * it might be more efficient to use a version of
9158  * <code>setNCharacterStream</code> which takes a length parameter.
9159  *
9160  * @param parameterName the name of the parameter
9161  * @param value the parameter value
9162  * @throws SQLException if the driver does not support national
9163  *         character sets;  if the driver can detect that a data conversion
9164  *  error could occur ; if a database access error occurs; or
9165  * this method is called on a closed <code>CallableStatement</code>
9166  * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9167  * @since 1.6
9168  */
9169  public void setNCharacterStream(String parameterName, Reader value) throws SQLException{
9170        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9171   }
9172
9173  /**
9174    * Sets the designated parameter to the given <code>java.sql.Timestamp</code> value,
9175    * using the given <code>Calendar</code> object.  The driver uses
9176    * the <code>Calendar</code> object to construct an SQL <code>TIMESTAMP</code> value,
9177    * which the driver then sends to the database.  With a
9178    * a <code>Calendar</code> object, the driver can calculate the timestamp
9179    * taking into account a custom timezone.  If no
9180    * <code>Calendar</code> object is specified, the driver uses the default
9181    * timezone, which is that of the virtual machine running the application.
9182    *
9183    * @param parameterName the name of the parameter
9184    * @param x the parameter value
9185    * @param cal the <code>Calendar</code> object the driver will use
9186    *            to construct the timestamp
9187    * @exception SQLException if a database access error occurs or
9188    * this method is called on a closed <code>CallableStatement</code>
9189    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9190    * this method
9191    * @see #getTimestamp
9192    * @since 1.4
9193    */
9194    public void setTimestamp(String parameterName, java.sql.Timestamp x, Calendar cal)
9195       throws SQLException{
9196        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9197   }
9198
9199    /**
9200    * Sets the designated parameter to a <code>Reader</code> object.  The <code>reader</code> must contain  the number
9201               * of characters specified by length otherwise a <code>SQLException</code> will be
9202               * generated when the <code>CallableStatement</code> is executed.
9203              * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
9204              * because it informs the driver that the parameter value should be sent to
9205              * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9206              * driver may have to do extra work to determine whether the parameter
9207              * data should be send to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9208              * @param parameterName the name of the parameter to be set
9209              * @param reader An object that contains the data to set the parameter value to.
9210              * @param length the number of characters in the parameter data.
9211              * @throws SQLException if parameterIndex does not correspond to a parameter
9212              * marker in the SQL statement; if the length specified is less than zero;
9213              * a database access error occurs or
9214              * this method is called on a closed <code>CallableStatement</code>
9215              * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9216              * this method
9217              *
9218              * @since 1.6
9219              */
9220      public  void setClob(String parameterName, Reader reader, long length)
9221      throws SQLException{
9222        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9223   }
9224
9225
9226  /**
9227    * Sets the designated parameter to the given <code>java.sql.Clob</code> object.
9228    * The driver converts this to an SQL <code>CLOB</code> value when it
9229    * sends it to the database.
9230    *
9231    * @param parameterName the name of the parameter
9232    * @param x a <code>Clob</code> object that maps an SQL <code>CLOB</code> value
9233    * @exception SQLException if a database access error occurs or
9234    * this method is called on a closed <code>CallableStatement</code>
9235    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9236    * this method
9237    * @since 1.6
9238    */
9239    public void setClob (String parameterName, Clob x) throws SQLException{
9240        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9241   }
9242
9243
9244 /**
9245    * Sets the designated parameter to a <code>Reader</code> object.
9246    * This method differs from the <code>setCharacterStream (int, Reader)</code> method
9247    * because it informs the driver that the parameter value should be sent to
9248    * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9249    * driver may have to do extra work to determine whether the parameter
9250    * data should be send to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9251    *
9252    * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9253    * it might be more efficient to use a version of
9254    * <code>setClob</code> which takes a length parameter.
9255    *
9256    * @param parameterName the name of the parameter
9257    * @param reader An object that contains the data to set the parameter value to.
9258    * @throws SQLException if a database access error occurs or this method is called on
9259    * a closed <code>CallableStatement</code>
9260    *
9261    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9262    * @since 1.6
9263    */
9264    public void setClob(String parameterName, Reader reader)
9265      throws SQLException{
9266        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9267   }
9268
9269
9270 /**
9271    * Sets the designated parameter to the given <code>java.sql.Date</code> value
9272    * using the default time zone of the virtual machine that is running
9273    * the application.
9274    * The driver converts this
9275    * to an SQL <code>DATE</code> value when it sends it to the database.
9276    *
9277    * @param parameterName the name of the parameter
9278    * @param x the parameter value
9279    * @exception SQLException if a database access error occurs or
9280    * this method is called on a closed <code>CallableStatement</code>
9281    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9282    * this method
9283    * @see #getDate
9284    * @since 1.4
9285    */
9286    public void setDate(String parameterName, java.sql.Date x)
9287       throws SQLException{
9288        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9289   }
9290
9291
9292 /**
9293    * Sets the designated parameter to the given <code>java.sql.Date</code> value,
9294    * using the given <code>Calendar</code> object.  The driver uses
9295    * the <code>Calendar</code> object to construct an SQL <code>DATE</code> value,
9296    * which the driver then sends to the database.  With a
9297    * a <code>Calendar</code> object, the driver can calculate the date
9298    * taking into account a custom timezone.  If no
9299    * <code>Calendar</code> object is specified, the driver uses the default
9300    * timezone, which is that of the virtual machine running the application.
9301    *
9302    * @param parameterName the name of the parameter
9303    * @param x the parameter value
9304    * @param cal the <code>Calendar</code> object the driver will use
9305    *            to construct the date
9306    * @exception SQLException if a database access error occurs or
9307    * this method is called on a closed <code>CallableStatement</code>
9308    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9309    * this method
9310    * @see #getDate
9311    * @since 1.4
9312    */
9313   public void setDate(String parameterName, java.sql.Date x, Calendar cal)
9314       throws SQLException{
9315        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9316   }
9317
9318
9319 /**
9320    * Sets the designated parameter to the given <code>java.sql.Time</code> value.
9321    * The driver converts this
9322    * to an SQL <code>TIME</code> value when it sends it to the database.
9323    *
9324    * @param parameterName the name of the parameter
9325    * @param x the parameter value
9326    * @exception SQLException if a database access error occurs or
9327    * this method is called on a closed <code>CallableStatement</code>
9328    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9329    * this method
9330    * @see #getTime
9331    * @since 1.4
9332    */
9333   public void setTime(String parameterName, java.sql.Time x)
9334       throws SQLException{
9335        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9336   }
9337
9338
9339 /**
9340    * Sets the designated parameter to the given <code>java.sql.Time</code> value,
9341    * using the given <code>Calendar</code> object.  The driver uses
9342    * the <code>Calendar</code> object to construct an SQL <code>TIME</code> value,
9343    * which the driver then sends to the database.  With a
9344    * a <code>Calendar</code> object, the driver can calculate the time
9345    * taking into account a custom timezone.  If no
9346    * <code>Calendar</code> object is specified, the driver uses the default
9347    * timezone, which is that of the virtual machine running the application.
9348    *
9349    * @param parameterName the name of the parameter
9350    * @param x the parameter value
9351    * @param cal the <code>Calendar</code> object the driver will use
9352    *            to construct the time
9353    * @exception SQLException if a database access error occurs or
9354    * this method is called on a closed <code>CallableStatement</code>
9355    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9356    * this method
9357    * @see #getTime
9358    * @since 1.4
9359    */
9360   public void setTime(String parameterName, java.sql.Time x, Calendar cal)
9361       throws SQLException{
9362        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9363   }
9364
9365   /**
9366   * Sets the designated parameter to a <code>Reader</code> object.
9367   * This method differs from the <code>setCharacterStream (int, Reader)</code> method
9368   * because it informs the driver that the parameter value should be sent to
9369   * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9370   * driver may have to do extra work to determine whether the parameter
9371   * data should be sent to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9372   *
9373   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9374   * it might be more efficient to use a version of
9375   * <code>setClob</code> which takes a length parameter.
9376   *
9377   * @param parameterIndex index of the first parameter is 1, the second is 2, ...
9378   * @param reader An object that contains the data to set the parameter value to.
9379   * @throws SQLException if a database access error occurs, this method is called on
9380   * a closed <code>PreparedStatement</code>or if parameterIndex does not correspond to a parameter
9381   * marker in the SQL statement
9382   *
9383   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9384   * @since 1.6
9385   */
9386   public void setClob(int parameterIndex, Reader reader)
9387     throws SQLException{
9388        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9389   }
9390
9391    /**
9392   * Sets the designated parameter to a <code>Reader</code> object.  The reader must contain  the number
9393   * of characters specified by length otherwise a <code>SQLException</code> will be
9394   * generated when the <code>PreparedStatement</code> is executed.
9395   *This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
9396   * because it informs the driver that the parameter value should be sent to
9397   * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
9398   * driver may have to do extra work to determine whether the parameter
9399   * data should be sent to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
9400   * @param parameterIndex index of the first parameter is 1, the second is 2, ...
9401   * @param reader An object that contains the data to set the parameter value to.
9402   * @param length the number of characters in the parameter data.
9403   * @throws SQLException if a database access error occurs, this method is called on
9404   * a closed <code>PreparedStatement</code>, if parameterIndex does not correspond to a parameter
9405   * marker in the SQL statement, or if the length specified is less than zero.
9406   *
9407   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9408   * @since 1.6
9409   */
9410   public void setClob(int parameterIndex, Reader reader, long length)
9411     throws SQLException{
9412        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9413   }
9414
9415
9416 /**
9417    * Sets the designated parameter to a <code>InputStream</code> object.  The inputstream must contain  the number
9418    * of characters specified by length otherwise a <code>SQLException</code> will be
9419    * generated when the <code>PreparedStatement</code> is executed.
9420    * This method differs from the <code>setBinaryStream (int, InputStream, int)</code>
9421    * method because it informs the driver that the parameter value should be
9422    * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9423    * the driver may have to do extra work to determine whether the parameter
9424    * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9425    * @param parameterIndex index of the first parameter is 1,
9426    * the second is 2, ...
9427    * @param inputStream An object that contains the data to set the parameter
9428    * value to.
9429    * @param length the number of bytes in the parameter data.
9430    * @throws SQLException if a database access error occurs,
9431    * this method is called on a closed <code>PreparedStatement</code>,
9432    * if parameterIndex does not correspond
9433    * to a parameter marker in the SQL statement,  if the length specified
9434    * is less than zero or if the number of bytes in the inputstream does not match
9435    * the specified length.
9436    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9437    *
9438    * @since 1.6
9439    */
9440    public void setBlob(int parameterIndex, InputStream inputStream, long length)
9441       throws SQLException{
9442        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9443   }
9444
9445
9446 /**
9447    * Sets the designated parameter to a <code>InputStream</code> object.
9448    * This method differs from the <code>setBinaryStream (int, InputStream)</code>
9449    * method because it informs the driver that the parameter value should be
9450    * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9451    * the driver may have to do extra work to determine whether the parameter
9452    * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9453    *
9454    * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9455    * it might be more efficient to use a version of
9456    * <code>setBlob</code> which takes a length parameter.
9457    *
9458    * @param parameterIndex index of the first parameter is 1,
9459    * the second is 2, ...
9460    * @param inputStream An object that contains the data to set the parameter
9461    * value to.
9462    * @throws SQLException if a database access error occurs,
9463    * this method is called on a closed <code>PreparedStatement</code> or
9464    * if parameterIndex does not correspond
9465    * to a parameter marker in the SQL statement,
9466    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9467    *
9468    * @since 1.6
9469    */
9470    public void setBlob(int parameterIndex, InputStream inputStream)
9471       throws SQLException{
9472        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9473   }
9474
9475
9476 /**
9477    * Sets the designated parameter to a <code>InputStream</code> object.  The <code>inputstream</code> must contain  the number
9478     * of characters specified by length, otherwise a <code>SQLException</code> will be
9479     * generated when the <code>CallableStatement</code> is executed.
9480     * This method differs from the <code>setBinaryStream (int, InputStream, int)</code>
9481     * method because it informs the driver that the parameter value should be
9482     * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9483     * the driver may have to do extra work to determine whether the parameter
9484     * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9485     *
9486     * @param parameterName the name of the parameter to be set
9487     * the second is 2, ...
9488     *
9489     * @param inputStream An object that contains the data to set the parameter
9490     * value to.
9491     * @param length the number of bytes in the parameter data.
9492     * @throws SQLException  if parameterIndex does not correspond
9493     * to a parameter marker in the SQL statement,  or if the length specified
9494     * is less than zero; if the number of bytes in the inputstream does not match
9495     * the specified length; if a database access error occurs or
9496     * this method is called on a closed <code>CallableStatement</code>
9497     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9498     * this method
9499     *
9500     * @since 1.6
9501     */
9502     public void setBlob(String parameterName, InputStream inputStream, long length)
9503        throws SQLException{
9504        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9505   }
9506
9507
9508 /**
9509    * Sets the designated parameter to the given <code>java.sql.Blob</code> object.
9510    * The driver converts this to an SQL <code>BLOB</code> value when it
9511    * sends it to the database.
9512    *
9513    * @param parameterName the name of the parameter
9514    * @param x a <code>Blob</code> object that maps an SQL <code>BLOB</code> value
9515    * @exception SQLException if a database access error occurs or
9516    * this method is called on a closed <code>CallableStatement</code>
9517    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9518    * this method
9519    * @since 1.6
9520    */
9521   public void setBlob (String parameterName, Blob x) throws SQLException{
9522        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9523   }
9524
9525
9526 /**
9527    * Sets the designated parameter to a <code>InputStream</code> object.
9528    * This method differs from the <code>setBinaryStream (int, InputStream)</code>
9529    * method because it informs the driver that the parameter value should be
9530    * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
9531    * the driver may have to do extra work to determine whether the parameter
9532    * data should be send to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
9533    *
9534    * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9535    * it might be more efficient to use a version of
9536    * <code>setBlob</code> which takes a length parameter.
9537    *
9538    * @param parameterName the name of the parameter
9539    * @param inputStream An object that contains the data to set the parameter
9540    * value to.
9541    * @throws SQLException if a database access error occurs or
9542    * this method is called on a closed <code>CallableStatement</code>
9543    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9544    *
9545    * @since 1.6
9546    */
9547    public void setBlob(String parameterName, InputStream inputStream)
9548       throws SQLException{
9549        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9550   }
9551
9552    /**
9553    * Sets the value of the designated parameter with the given object. The second
9554    * argument must be an object type; for integral values, the
9555    * <code>java.lang</code> equivalent objects should be used.
9556    *
9557    * <p>The given Java object will be converted to the given targetSqlType
9558    * before being sent to the database.
9559    *
9560    * If the object has a custom mapping (is of a class implementing the
9561    * interface <code>SQLData</code>),
9562    * the JDBC driver should call the method <code>SQLData.writeSQL</code> to write it
9563    * to the SQL data stream.
9564    * If, on the other hand, the object is of a class implementing
9565    * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>,  <code>NClob</code>,
9566    *  <code>Struct</code>, <code>java.net.URL</code>,
9567    * or <code>Array</code>, the driver should pass it to the database as a
9568    * value of the corresponding SQL type.
9569    * <P>
9570    * Note that this method may be used to pass datatabase-
9571    * specific abstract data types.
9572    *
9573    * @param parameterName the name of the parameter
9574    * @param x the object containing the input parameter value
9575    * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
9576    * sent to the database. The scale argument may further qualify this type.
9577    * @param scale for java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types,
9578    *          this is the number of digits after the decimal point.  For all other
9579    *          types, this value will be ignored.
9580    * @exception SQLException if a database access error occurs or
9581    * this method is called on a closed <code>CallableStatement</code>
9582    * @exception SQLFeatureNotSupportedException if <code>targetSqlType</code> is
9583    * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,
9584    * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,
9585    * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,
9586    *  <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
9587    * or  <code>STRUCT</code> data type and the JDBC driver does not support
9588    * this data type
9589    * @see Types
9590    * @see #getObject
9591    * @since 1.4
9592    */
9593    public void setObject(String parameterName, Object x, int targetSqlType, int scale)
9594       throws SQLException{
9595        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9596   }
9597
9598
9599
9600 /**
9601    * Sets the value of the designated parameter with the given object.
9602    * This method is like the method <code>setObject</code>
9603    * above, except that it assumes a scale of zero.
9604    *
9605    * @param parameterName the name of the parameter
9606    * @param x the object containing the input parameter value
9607    * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
9608    *                      sent to the database
9609    * @exception SQLException if a database access error occurs or
9610    * this method is called on a closed <code>CallableStatement</code>
9611    * @exception SQLFeatureNotSupportedException if <code>targetSqlType</code> is
9612    * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,
9613    * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,
9614    * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,
9615    *  <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
9616    * or  <code>STRUCT</code> data type and the JDBC driver does not support
9617    * this data type
9618    * @see #getObject
9619    * @since 1.4
9620    */
9621    public void setObject(String parameterName, Object x, int targetSqlType)
9622       throws SQLException{
9623        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9624   }
9625
9626
9627 /**
9628   * Sets the value of the designated parameter with the given object.
9629   * The second parameter must be of type <code>Object</code>; therefore, the
9630   * <code>java.lang</code> equivalent objects should be used for built-in types.
9631   *
9632   * <p>The JDBC specification specifies a standard mapping from
9633   * Java <code>Object</code> types to SQL types.  The given argument
9634   * will be converted to the corresponding SQL type before being
9635   * sent to the database.
9636   *
9637   * <p>Note that this method may be used to pass datatabase-
9638   * specific abstract data types, by using a driver-specific Java
9639   * type.
9640   *
9641   * If the object is of a class implementing the interface <code>SQLData</code>,
9642   * the JDBC driver should call the method <code>SQLData.writeSQL</code>
9643   * to write it to the SQL data stream.
9644   * If, on the other hand, the object is of a class implementing
9645   * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>,  <code>NClob</code>,
9646   *  <code>Struct</code>, <code>java.net.URL</code>,
9647   * or <code>Array</code>, the driver should pass it to the database as a
9648   * value of the corresponding SQL type.
9649   * <P>
9650   * This method throws an exception if there is an ambiguity, for example, if the
9651   * object is of a class implementing more than one of the interfaces named above.
9652   *
9653   * @param parameterName the name of the parameter
9654   * @param x the object containing the input parameter value
9655   * @exception SQLException if a database access error occurs,
9656   * this method is called on a closed <code>CallableStatement</code> or if the given
9657   *            <code>Object</code> parameter is ambiguous
9658   * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9659   * this method
9660   * @see #getObject
9661   * @since 1.4
9662   */
9663   public void setObject(String parameterName, Object x) throws SQLException{
9664        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9665   }
9666
9667    /**
9668    * Sets the designated parameter to the given input stream, which will have
9669    * the specified number of bytes.
9670    * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
9671    * parameter, it may be more practical to send it via a
9672    * <code>java.io.InputStream</code>. Data will be read from the stream
9673    * as needed until end-of-file is reached.  The JDBC driver will
9674    * do any necessary conversion from ASCII to the database char format.
9675    *
9676    * <P><B>Note:</B> This stream object can either be a standard
9677    * Java stream object or your own subclass that implements the
9678    * standard interface.
9679    *
9680    * @param parameterName the name of the parameter
9681    * @param x the Java input stream that contains the ASCII parameter value
9682    * @param length the number of bytes in the stream
9683    * @exception SQLException if a database access error occurs or
9684    * this method is called on a closed <code>CallableStatement</code>
9685    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9686    * this method
9687    * @since 1.4
9688    */
9689   public void setAsciiStream(String parameterName, java.io.InputStream x, int length)
9690       throws SQLException{
9691        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9692   }
9693
9694
9695 /**
9696    * Sets the designated parameter to the given input stream, which will have
9697    * the specified number of bytes.
9698    * When a very large binary value is input to a <code>LONGVARBINARY</code>
9699    * parameter, it may be more practical to send it via a
9700    * <code>java.io.InputStream</code> object. The data will be read from the stream
9701    * as needed until end-of-file is reached.
9702    *
9703    * <P><B>Note:</B> This stream object can either be a standard
9704    * Java stream object or your own subclass that implements the
9705    * standard interface.
9706    *
9707    * @param parameterName the name of the parameter
9708    * @param x the java input stream which contains the binary parameter value
9709    * @param length the number of bytes in the stream
9710    * @exception SQLException if a database access error occurs or
9711    * this method is called on a closed <code>CallableStatement</code>
9712    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9713    * this method
9714    * @since 1.4
9715    */
9716   public void setBinaryStream(String parameterName, java.io.InputStream x,
9717                        int length) throws SQLException{
9718        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9719   }
9720
9721
9722  /**
9723    * Sets the designated parameter to the given <code>Reader</code>
9724    * object, which is the given number of characters long.
9725    * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
9726    * parameter, it may be more practical to send it via a
9727    * <code>java.io.Reader</code> object. The data will be read from the stream
9728    * as needed until end-of-file is reached.  The JDBC driver will
9729    * do any necessary conversion from UNICODE to the database char format.
9730    *
9731    * <P><B>Note:</B> This stream object can either be a standard
9732    * Java stream object or your own subclass that implements the
9733    * standard interface.
9734    *
9735    * @param parameterName the name of the parameter
9736    * @param reader the <code>java.io.Reader</code> object that
9737    *        contains the UNICODE data used as the designated parameter
9738    * @param length the number of characters in the stream
9739    * @exception SQLException if a database access error occurs or
9740    * this method is called on a closed <code>CallableStatement</code>
9741    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9742    * this method
9743    * @since 1.4
9744    */
9745   public void setCharacterStream(String parameterName,
9746                           java.io.Reader reader,
9747                           int length) throws SQLException{
9748        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9749   }
9750
9751
9752  /**
9753   * Sets the designated parameter to the given input stream.
9754   * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
9755   * parameter, it may be more practical to send it via a
9756   * <code>java.io.InputStream</code>. Data will be read from the stream
9757   * as needed until end-of-file is reached.  The JDBC driver will
9758   * do any necessary conversion from ASCII to the database char format.
9759   *
9760   * <P><B>Note:</B> This stream object can either be a standard
9761   * Java stream object or your own subclass that implements the
9762   * standard interface.
9763   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9764   * it might be more efficient to use a version of
9765   * <code>setAsciiStream</code> which takes a length parameter.
9766   *
9767   * @param parameterName the name of the parameter
9768   * @param x the Java input stream that contains the ASCII parameter value
9769   * @exception SQLException if a database access error occurs or
9770   * this method is called on a closed <code>CallableStatement</code>
9771   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9772     * @since 1.6
9773  */
9774  public void setAsciiStream(String parameterName, java.io.InputStream x)
9775          throws SQLException{
9776        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9777   }
9778
9779
9780 /**
9781    * Sets the designated parameter to the given input stream.
9782    * When a very large binary value is input to a <code>LONGVARBINARY</code>
9783    * parameter, it may be more practical to send it via a
9784    * <code>java.io.InputStream</code> object. The data will be read from the
9785    * stream as needed until end-of-file is reached.
9786    *
9787    * <P><B>Note:</B> This stream object can either be a standard
9788    * Java stream object or your own subclass that implements the
9789    * standard interface.
9790    * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9791    * it might be more efficient to use a version of
9792    * <code>setBinaryStream</code> which takes a length parameter.
9793    *
9794    * @param parameterName the name of the parameter
9795    * @param x the java input stream which contains the binary parameter value
9796    * @exception SQLException if a database access error occurs or
9797    * this method is called on a closed <code>CallableStatement</code>
9798    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9799    * @since 1.6
9800    */
9801   public void setBinaryStream(String parameterName, java.io.InputStream x)
9802   throws SQLException{
9803        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9804   }
9805
9806
9807
9808 /**
9809    * Sets the designated parameter to the given <code>Reader</code>
9810    * object.
9811    * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
9812    * parameter, it may be more practical to send it via a
9813    * <code>java.io.Reader</code> object. The data will be read from the stream
9814    * as needed until end-of-file is reached.  The JDBC driver will
9815    * do any necessary conversion from UNICODE to the database char format.
9816    *
9817    * <P><B>Note:</B> This stream object can either be a standard
9818    * Java stream object or your own subclass that implements the
9819    * standard interface.
9820    * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
9821    * it might be more efficient to use a version of
9822    * <code>setCharacterStream</code> which takes a length parameter.
9823    *
9824    * @param parameterName the name of the parameter
9825    * @param reader the <code>java.io.Reader</code> object that contains the
9826    *        Unicode data
9827    * @exception SQLException if a database access error occurs or
9828    * this method is called on a closed <code>CallableStatement</code>
9829    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
9830    * @since 1.6
9831    */
9832   public void setCharacterStream(String parameterName,
9833                         java.io.Reader reader) throws SQLException{
9834        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9835   }
9836
9837   /**
9838    * Sets the designated parameter to the given
9839    * <code>java.math.BigDecimal</code> value.
9840    * The driver converts this to an SQL <code>NUMERIC</code> value when
9841    * it sends it to the database.
9842    *
9843    * @param parameterName the name of the parameter
9844    * @param x the parameter value
9845    * @exception SQLException if a database access error occurs or
9846    * this method is called on a closed <code>CallableStatement</code>
9847    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9848    * this method
9849    * @see #getBigDecimal
9850    * @since 1.4
9851    */
9852   public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException{
9853        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9854   }
9855
9856
9857
9858 /**
9859    * Sets the designated parameter to the given Java <code>String</code> value.
9860    * The driver converts this
9861    * to an SQL <code>VARCHAR</code> or <code>LONGVARCHAR</code> value
9862    * (depending on the argument's
9863    * size relative to the driver's limits on <code>VARCHAR</code> values)
9864    * when it sends it to the database.
9865    *
9866    * @param parameterName the name of the parameter
9867    * @param x the parameter value
9868    * @exception SQLException if a database access error occurs or
9869    * this method is called on a closed <code>CallableStatement</code>
9870    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9871    * this method
9872    * @see #getString
9873    * @since 1.4
9874    */
9875   public void setString(String parameterName, String x) throws SQLException{
9876        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9877   }
9878
9879
9880
9881 /**
9882    * Sets the designated parameter to the given Java array of bytes.
9883    * The driver converts this to an SQL <code>VARBINARY</code> or
9884    * <code>LONGVARBINARY</code> (depending on the argument's size relative
9885    * to the driver's limits on <code>VARBINARY</code> values) when it sends
9886    * it to the database.
9887    *
9888    * @param parameterName the name of the parameter
9889    * @param x the parameter value
9890    * @exception SQLException if a database access error occurs or
9891    * this method is called on a closed <code>CallableStatement</code>
9892    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9893    * this method
9894    * @see #getBytes
9895    * @since 1.4
9896    */
9897   public void setBytes(String parameterName, byte x[]) throws SQLException{
9898        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9899   }
9900
9901
9902
9903 /**
9904    * Sets the designated parameter to the given <code>java.sql.Timestamp</code> value.
9905    * The driver
9906    * converts this to an SQL <code>TIMESTAMP</code> value when it sends it to the
9907    * database.
9908    *
9909    * @param parameterName the name of the parameter
9910    * @param x the parameter value
9911    * @exception SQLException if a database access error occurs or
9912    * this method is called on a closed <code>CallableStatement</code>
9913    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9914    * this method
9915    * @see #getTimestamp
9916    * @since 1.4
9917    */
9918   public void setTimestamp(String parameterName, java.sql.Timestamp x)
9919       throws SQLException{
9920        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9921   }
9922
9923    /**
9924    * Sets the designated parameter to SQL <code>NULL</code>.
9925    *
9926    * <P><B>Note:</B> You must specify the parameter's SQL type.
9927    *
9928    * @param parameterName the name of the parameter
9929    * @param sqlType the SQL type code defined in <code>java.sql.Types</code>
9930    * @exception SQLException if a database access error occurs or
9931    * this method is called on a closed <code>CallableStatement</code>
9932    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9933    * this method
9934    * @since 1.4
9935    */
9936   public void setNull(String parameterName, int sqlType) throws SQLException {
9937        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9938   }
9939
9940
9941 /**
9942    * Sets the designated parameter to SQL <code>NULL</code>.
9943    * This version of the method <code>setNull</code> should
9944    * be used for user-defined types and REF type parameters.  Examples
9945    * of user-defined types include: STRUCT, DISTINCT, JAVA_OBJECT, and
9946    * named array types.
9947    *
9948    * <P><B>Note:</B> To be portable, applications must give the
9949    * SQL type code and the fully-qualified SQL type name when specifying
9950    * a NULL user-defined or REF parameter.  In the case of a user-defined type
9951    * the name is the type name of the parameter itself.  For a REF
9952    * parameter, the name is the type name of the referenced type.  If
9953    * a JDBC driver does not need the type code or type name information,
9954    * it may ignore it.
9955    *
9956    * Although it is intended for user-defined and Ref parameters,
9957    * this method may be used to set a null parameter of any JDBC type.
9958    * If the parameter does not have a user-defined or REF type, the given
9959    * typeName is ignored.
9960    *
9961    *
9962    * @param parameterName the name of the parameter
9963    * @param sqlType a value from <code>java.sql.Types</code>
9964    * @param typeName the fully-qualified name of an SQL user-defined type;
9965    *        ignored if the parameter is not a user-defined type or
9966    *        SQL <code>REF</code> value
9967    * @exception SQLException if a database access error occurs or
9968    * this method is called on a closed <code>CallableStatement</code>
9969    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9970    * this method
9971    * @since 1.4
9972    */
9973   public void setNull (String parameterName, int sqlType, String typeName)
9974       throws SQLException{
9975        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9976   }
9977
9978
9979
9980 /**
9981    * Sets the designated parameter to the given Java <code>boolean</code> value.
9982    * The driver converts this
9983    * to an SQL <code>BIT</code> or <code>BOOLEAN</code> value when it sends it to the database.
9984    *
9985    * @param parameterName the name of the parameter
9986    * @param x the parameter value
9987    * @exception SQLException if a database access error occurs or
9988    * this method is called on a closed <code>CallableStatement</code>
9989    * @see #getBoolean
9990    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
9991    * this method
9992    * @since 1.4
9993    */
9994   public void setBoolean(String parameterName, boolean x) throws SQLException{
9995        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
9996   }
9997
9998
9999
10000 /**
10001    * Sets the designated parameter to the given Java <code>byte</code> value.
10002    * The driver converts this
10003    * to an SQL <code>TINYINT</code> value when it sends it to the database.
10004    *
10005    * @param parameterName the name of the parameter
10006    * @param x the parameter value
10007    * @exception SQLException if a database access error occurs or
10008    * this method is called on a closed <code>CallableStatement</code>
10009    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10010    * this method
10011    * @see #getByte
10012    * @since 1.4
10013    */
10014   public void setByte(String parameterName, byte x) throws SQLException{
10015        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10016   }
10017
10018
10019
10020 /**
10021    * Sets the designated parameter to the given Java <code>short</code> value.
10022    * The driver converts this
10023    * to an SQL <code>SMALLINT</code> value when it sends it to the database.
10024    *
10025    * @param parameterName the name of the parameter
10026    * @param x the parameter value
10027    * @exception SQLException if a database access error occurs or
10028    * this method is called on a closed <code>CallableStatement</code>
10029    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10030    * this method
10031    * @see #getShort
10032    * @since 1.4
10033    */
10034   public void setShort(String parameterName, short x) throws SQLException{
10035        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10036   }
10037
10038
10039 /**
10040    * Sets the designated parameter to the given Java <code>int</code> value.
10041    * The driver converts this
10042    * to an SQL <code>INTEGER</code> value when it sends it to the database.
10043    *
10044    * @param parameterName the name of the parameter
10045    * @param x the parameter value
10046    * @exception SQLException if a database access error occurs or
10047    * this method is called on a closed <code>CallableStatement</code>
10048    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10049    * this method
10050    * @see #getInt
10051    * @since 1.4
10052    */
10053   public void setInt(String parameterName, int x) throws SQLException{
10054        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10055   }
10056
10057
10058 /**
10059    * Sets the designated parameter to the given Java <code>long</code> value.
10060    * The driver converts this
10061    * to an SQL <code>BIGINT</code> value when it sends it to the database.
10062    *
10063    * @param parameterName the name of the parameter
10064    * @param x the parameter value
10065    * @exception SQLException if a database access error occurs or
10066    * this method is called on a closed <code>CallableStatement</code>
10067    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10068    * this method
10069    * @see #getLong
10070    * @since 1.4
10071    */
10072   public void setLong(String parameterName, long x) throws SQLException{
10073        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10074   }
10075
10076
10077 /**
10078    * Sets the designated parameter to the given Java <code>float</code> value.
10079    * The driver converts this
10080    * to an SQL <code>FLOAT</code> value when it sends it to the database.
10081    *
10082    * @param parameterName the name of the parameter
10083    * @param x the parameter value
10084    * @exception SQLException if a database access error occurs or
10085    * this method is called on a closed <code>CallableStatement</code>
10086    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10087    * this method
10088    * @see #getFloat
10089    * @since 1.4
10090    */
10091   public void setFloat(String parameterName, float x) throws SQLException{
10092        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10093   }
10094
10095
10096 /**
10097    * Sets the designated parameter to the given Java <code>double</code> value.
10098    * The driver converts this
10099    * to an SQL <code>DOUBLE</code> value when it sends it to the database.
10100    *
10101    * @param parameterName the name of the parameter
10102    * @param x the parameter value
10103    * @exception SQLException if a database access error occurs or
10104    * this method is called on a closed <code>CallableStatement</code>
10105    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
10106    * this method
10107    * @see #getDouble
10108    * @since 1.4
10109    */
10110   public void setDouble(String parameterName, double x) throws SQLException{
10111        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString());
10112   }
10113
10114   /**
10115     * This method re populates the resBundle
10116     * during the deserialization process
10117     *
10118     */
10119    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
10120        // Default state initialization happens here
10121        ois.defaultReadObject();
10122        // Initialization of transient Res Bundle happens here .
10123        try {
10124           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
10125        } catch(IOException ioe) {
10126            throw new RuntimeException(ioe);
10127        }
10128
10129    }
10130
10131    //------------------------- JDBC 4.1 -----------------------------------
10132    public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
10133        throw new SQLFeatureNotSupportedException("Not supported yet.");
10134    }
10135
10136    public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
10137        throw new SQLFeatureNotSupportedException("Not supported yet.");
10138    }
10139
10140    static final long serialVersionUID =1884577171200622428L;
10141}
10142