/*
 * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package javax.sql.rowset;

import java.sql.*;
import javax.sql.*;
import java.util.*;
import java.io.*;
import java.math.*;
import java.io.Serializable;

import javax.sql.rowset.serial.*;

/**
 * An abstract class providing a <code>RowSet</code> object with its basic functionality.
 * The basic functions include having properties and sending event notifications,
 * which all JavaBeans<sup><font size=-2>TM</font></sup> components must implement.
 * <P>
 * <h3>1.0 Overview</h3>
 * The <code>BaseRowSet</code> class provides the core functionality
 * for all <code>RowSet</code> implementations,
 * and all standard implementations <b>may</b> use this class in combination with
 * one or more <code>RowSet</code> interfaces in order to provide a standard
 * vendor-specific implementation.  To clarify, all implementations must implement
 * at least one of the <code>RowSet</code> interfaces (<code>JdbcRowSet</code>,
 * <code>CachedRowSet</code>, <code>JoinRowSet</code>, <code>FilteredRowSet</code>,
 * or <code>WebRowSet</code>). This means that any implementation that extends
 * the <code>BaseRowSet</code> class must also implement one of the <code>RowSet</code>
 * interfaces.
 * <p>
 * The <code>BaseRowSet</code> class provides the following:
 * <p>
 * <UL>
 * <LI><b>Properties</b>
 *     <ul>
 *     <li>Fields for storing current properties
 *     <li>Methods for getting and setting properties
 *     </ul>
 *  <p>
 * <LI><b>Event notification</b>
 * <P>
 * <LI><b>A complete set of setter methods</b> for setting the parameters in a
 *      <code>RowSet</code> object's command
 *  <p>
 * <LI> <b>Streams</b>
 *  <ul>
 *  <li>Fields for storing stream instances
 *  <li>Constants for indicating the type of a stream
 *  </ul>
 *  <p>
 * </UL>
 *
 * <h3>2.0 Setting Properties</h3>
 * All rowsets maintain a set of properties, which will usually be set using
 * a tool.  The number and kinds of properties a rowset has will vary,
 * depending on what the <code>RowSet</code> implementation does and how it gets
 * its data.  For example,
 * rowsets that get their data from a <code>ResultSet</code> object need to
 * set the properties that are required for making a database connection.
 * If a <code>RowSet</code> object uses the <code>DriverManager</code> facility to make a
 * connection, it needs to set a property for the JDBC URL that identifies the
 * appropriate driver, and it needs to set the properties that give the
 * user name and password.
 * If, on the other hand, the rowset uses a <code>DataSource</code> object
 * to make the connection, which is the preferred method, it does not need to
 * set the property for the JDBC URL.  Instead, it needs to set the property
 * for the logical name of the data source along with the properties for
 * the user name and password.
 * <P>
 * NOTE:  In order to use a <code>DataSource</code> object for making a
 * connection, the <code>DataSource</code> object must have been registered
 * with a naming service that uses the Java Naming and Directory
 * Interface<sup><font size=-2>TM</font></sup> (JNDI) API.  This registration
 * is usually done by a person acting in the capacity of a system administrator.
 * <P>
 * <h3>3.0 Setting the Command and Its Parameters</h3>
 * When a rowset gets its data from a relational database, it executes a command (a query)
 * that produces a <code>ResultSet</code> object.  This query is the command that is set
 * for the <code>RowSet</code> object's command property.  The rowset populates itself with data by reading the
 * data from the <code>ResultSet</code> object into itself. If the query
 * contains placeholders for values to be set, the <code>BaseRowSet</code> setter methods
 * are used to set these values. All setter methods allow these values to be set
 * to <code>null</code> if required.
 * <P>
 * The following code fragment illustrates how the
 * <code>CachedRowSet</code><sup><font size=-2>TM</font></sup>
 * object <code>crs</code> might have its command property set.  Note that if a
 * tool is used to set properties, this is the code that the tool would use.
 * <PRE>
 *    crs.setCommand("SELECT FIRST_NAME, LAST_NAME, ADDRESS FROM CUSTOMERS" +
 *                   "WHERE CREDIT_LIMIT > ? AND REGION = ?");
 * </PRE>
 * <P>
 * In this example, the values for <code>CREDIT_LIMIT</code> and
 * <code>REGION</code> are placeholder parameters, which are indicated with a
 * question mark (?).  The first question mark is placeholder parameter number
 * <code>1</code>, the second question mark is placeholder parameter number
 * <code>2</code>, and so on.  Any placeholder parameters must be set with
 * values before the query can be executed. To set these
 * placeholder parameters, the <code>BaseRowSet</code> class provides a set of setter
 * methods, similar to those provided by the <code>PreparedStatement</code>
 * interface, for setting values of each data type.  A <code>RowSet</code> object stores the
 * parameter values internally, and its <code>execute</code> method uses them internally
 * to set values for the placeholder parameters
 * before it sends the command to the DBMS to be executed.
 * <P>
 * The following code fragment demonstrates
 * setting the two parameters in the query from the previous example.
 * <PRE>
 *    crs.setInt(1, 5000);
 *    crs.setString(2, "West");
 * </PRE>
 * If the <code>execute</code> method is called at this point, the query
 * sent to the DBMS will be:
 * <PRE>
 *    "SELECT FIRST_NAME, LAST_NAME, ADDRESS FROM CUSTOMERS" +
 *                   "WHERE CREDIT_LIMIT > 5000 AND REGION = 'West'"
 * </PRE>
 * NOTE: Setting <code>Array</code>, <code>Clob</code>, <code>Blob</code> and
 * <code>Ref</code> objects as a command parameter, stores these values as
 * <code>SerialArray</code>, <code>SerialClob</code>, <code>SerialBlob</code>
 * and <code>SerialRef</code> objects respectively.
 *
 * <h3>4.0 Handling of Parameters Behind the Scenes</h3>
 *
 * NOTE: The <code>BaseRowSet</code> class provides two kinds of setter methods,
 * those that set properties and those that set placeholder parameters. The setter
 * methods discussed in this section are those that set placeholder parameters.
 * <P>
 * The placeholder parameters set with the <code>BaseRowSet</code> setter methods
 * are stored as objects in an internal <code>Hashtable</code> object.
 * Primitives are stored as their <code>Object</code> type. For example, <code>byte</code>
 * is stored as <code>Byte</code> object, and <code>int</code> is stored as
 * an <code>Integer</code> object.
 * When the method <code>execute</code> is called, the values in the
 * <code>Hashtable</code> object are substituted for the appropriate placeholder
 * parameters in the command.
 * <P)>
 * A call to the method <code>getParams</code> returns the values stored in the
 * <code>Hashtable</code> object as an array of <code>Object</code> instances.
 * An element in this array may be a simple <code>Object</code> instance or an
 * array (which is a type of <code>Object</code>). The particular setter method used
 * determines whether an element in this array is an <code>Object</code> or an array.
 * <P>
 * The majority of methods for setting placeholder parameters take two parameters,
 *  with the first parameter
 * indicating which placeholder parameter is to be set, and the second parameter
 * giving the value to be set.  Methods such as <code>getInt</code>,
 * <code>getString</code>, <code>getBoolean</code>, and <code>getLong</code> fall into
 * this category.  After these methods have been called, a call to the method
 * <code>getParams</code> will return an array with the values that have been set. Each
 * element in the array is an <code>Object</code> instance representing the
 * values that have been set. The order of these values in the array is determined by the
 * <code>int</code> (the first parameter) passed to the setter method. The values in the
 * array are the values (the second parameter) passed to the setter method.
 * In other words, the first element in the array is the value
 * to be set for the first placeholder parameter in the <code>RowSet</code> object's
 * command. The second element is the value to
 * be set for the second placeholder parameter, and so on.
 * <P>
 * Several setter methods send the driver and DBMS information beyond the value to be set.
 * When the method <code>getParams</code> is called after one of these setter methods has
 * been used, the elements in the array will themselves be arrays to accommodate the
 * additional information. In this category, the method <code>setNull</code> is a special case
 * because one version takes only
 * two parameters (<code>setNull(int parameterIndex, int SqlType)</code>). Nevertheless,
 * it requires
 * an array to contain the information that will be passed to the driver and DBMS.  The first
 * element in this array is the value to be set, which is <code>null</code>, and the
 * second element is the <code>int</code> supplied for <i>sqlType</i>, which
 * indicates the type of SQL value that is being set to <code>null</code>. This information
 * is needed by some DBMSs and is therefore required in order to ensure that applications
 * are portable.
 * The other version is intended to be used when the value to be set to <code>null</code>
 * is a user-defined type. It takes three parameters
 * (<code>setNull(int parameterIndex, int sqlType, String typeName)</code>) and also
 * requires an array to contain the information to be passed to the driver and DBMS.
 * The first two elements in this array are the same as for the first version of
 * <code>setNull</code>.  The third element, <i>typeName</i>, gives the SQL name of
 * the user-defined type. As is true with the other setter methods, the number of the
 * placeholder parameter to be set is indicated by an element's position in the array
 * returned by <code>getParams</code>.  So, for example, if the parameter
 * supplied to <code>setNull</code> is <code>2</code>, the second element in the array
 * returned by <code>getParams</code> will be an array of two or three elements.
 * <P>
 * Some methods, such as <code>setObject</code> and <code>setDate</code> have versions
 * that take more than two parameters, with the extra parameters giving information
 * to the driver or the DBMS. For example, the methods <code>setDate</code>,
 * <code>setTime</code>, and <code>setTimestamp</code> can take a <code>Calendar</code>
 * object as their third parameter.  If the DBMS does not store time zone information,
 * the drivern uses the <code>Calendar</code> object to construct the <code>Date</code>,
 * <code>Time</code>, or <code>Timestamp</code> object being set. As is true with other
 * methods that provide additional information, the element in the array returned
 * by <code>getParams</code> is an array instead of a simple <code>Object</code> instance.
 * <P>
 * The methods <code>setAsciiStream</code>, <code>setBinaryStream</code>,
 * <code>setCharacterStream</code>, and <code>setUnicodeStream</code> (which is
 * deprecated, so applications should use <code>getCharacterStream</code> instead)
 * take three parameters, so for them, the element in the array returned by
 * <code>getParams</code> is also an array.  What is different about these setter
 * methods is that in addition to the information provided by parameters, the array contains
 * one of the <code>BaseRowSet</code> constants indicating the type of stream being set.
* <p>
* NOTE: The method <code>getParams</code> is called internally by
* <code>RowSet</code> implementations extending this class; it is not normally called by an
* application programmer directly.
*
* <h3>5.0 Event Notification</h3>
* The <code>BaseRowSet</code> class provides the event notification
* mechanism for rowsets.  It contains the field
* <code>listeners</code>, methods for adding and removing listeners, and
* methods for notifying listeners of changes.
* <P>
* A listener is an object that has implemented the <code>RowSetListener</code> interface.
* If it has been added to a <code>RowSet</code> object's list of listeners, it will be notified
*  when an event occurs on that <code>RowSet</code> object.  Each listener's
* implementation of the <code>RowSetListener</code> methods defines what that object
* will do when it is notified that an event has occurred.
* <P>
* There are three possible events for a <code>RowSet</code> object:
* <OL>
* <LI>the cursor moves
* <LI>an individual row is changed (updated, deleted, or inserted)
* <LI>the contents of the entire <code>RowSet</code> object  are changed
* </OL>
* <P>
* The <code>BaseRowSet</code> method used for the notification indicates the
* type of event that has occurred.  For example, the method
* <code>notifyRowChanged</code> indicates that a row has been updated,
* deleted, or inserted.  Each of the notification methods creates a
* <code>RowSetEvent</code> object, which is supplied to the listener in order to
* identify the <code>RowSet</code> object on which the event occurred.
* What the listener does with this information, which may be nothing, depends on how it was
* implemented.
* <p>
* <h3>6.0 Default Behavior</h3>
* A default <code>BaseRowSet</code> object is initialized with many starting values.
*
* The following is true of a default <code>RowSet</code> instance that extends
* the <code>BaseRowSet</code> class:
* <UL>
*   <LI>Has a scrollable cursor and does not show changes
*       made by others.
*   <LI>Is updatable.
*   <LI>Does not show rows that have been deleted.
*   <LI>Has no time limit for how long a driver may take to
*       execute the <code>RowSet</code> object's command.
*   <LI>Has no limit for the number of rows it may contain.
*   <LI>Has no limit for the number of bytes a column may contain. NOTE: This
*   limit applies only to columns that hold values of the
*   following types:  <code>BINARY</code>, <code>VARBINARY</code>,
*   <code>LONGVARBINARY</code>, <code>CHAR</code>, <code>VARCHAR</code>,
*   and <code>LONGVARCHAR</code>.
*   <LI>Will not see uncommitted data (make "dirty" reads).
*   <LI>Has escape processing turned on.
*   <LI>Has its connection's type map set to <code>null</code>.
*   <LI>Has an empty <code>Vector</code> object for storing the values set
*       for the placeholder parameters in the <code>RowSet</code> object's command.
* </UL>
* <p>
* If other values are desired, an application must set the property values
* explicitly. For example, the following line of code sets the maximum number
* of rows for the <code>CachedRowSet</code> object <i>crs</i> to 500.
* <PRE>
*    crs.setMaxRows(500);
* </PRE>
* Methods implemented in extensions of this <code>BaseRowSet</code> class <b>must</b> throw an
* <code>SQLException</code> object for any violation of the defined assertions.  Also, if the
* extending class overrides and reimplements any <code>BaseRowSet</code> method and encounters
* connectivity or underlying data source issues, that method <b>may</b> in addition throw an
* <code>SQLException</code> object for that reason.
*/

public abstract class BaseRowSet implements Serializable, Cloneable {

/**
 * A constant indicating to a <code>RowSetReaderImpl</code> object
 * that a given parameter is a Unicode stream. This
 * <code>RowSetReaderImpl</code> object is provided as an extension of the
 * <code>SyncProvider</code> abstract class defined in the
 * <code>SyncFactory</code> static factory SPI mechanism.
 */
public static final int UNICODE_STREAM_PARAM = 0;

/**
 * A constant indicating to a <code>RowSetReaderImpl</code> object
 * that a given parameter is a binary stream. A
 * <code>RowSetReaderImpl</code> object is provided as an extension of the
 * <code>SyncProvider</code> abstract class defined in the
 * <code>SyncFactory</code> static factory SPI mechanism.
 */
public static final int BINARY_STREAM_PARAM = 1;

/**
 * A constant indicating to a <code>RowSetReaderImpl</code> object
 * that a given parameter is an ASCII stream. A
 * <code>RowSetReaderImpl</code> object is provided as an extension of the
 * <code>SyncProvider</code> abstract class defined in the
 * <code>SyncFactory</code> static factory SPI mechanism.
 */
public static final int ASCII_STREAM_PARAM = 2;

    /**
     * The <code>InputStream</code> object that will be
     * returned by the method <code>getBinaryStream</code>, which is
     * specified in the <code>ResultSet</code> interface.
     * @serial
     */
    protected java.io.InputStream binaryStream;

    /**
     * The <code>InputStream</code> object that will be
     * returned by the method <code>getUnicodeStream</code>,
     * which is specified in the <code>ResultSet</code> interface.
     * @serial
     */
    protected java.io.InputStream unicodeStream;

    /**
     * The <code>InputStream</code> object that will be
     * returned by the method <code>getAsciiStream</code>,
     * which is specified in the <code>ResultSet</code> interface.
     * @serial
     */
    protected java.io.InputStream asciiStream;

    /**
     * The <code>Reader</code> object that will be
     * returned by the method <code>getCharacterStream</code>,
     * which is specified in the <code>ResultSet</code> interface.
     * @serial
     */
    protected java.io.Reader charStream;

    /**
     * The query that will be sent to the DBMS for execution when the
     * method <code>execute</code> is called.
     * @serial
     */
    private String command;

    /**
     * The JDBC URL the reader, writer, or both supply to the method
     * <code>DriverManager.getConnection</code> when the
     * <code>DriverManager</code> is used to get a connection.
     * <P>
     * The JDBC URL identifies the driver to be used to make the conndection.
     * This URL can be found in the documentation supplied by the driver
     * vendor.
     * @serial
     */
    private String URL;

    /**
     * The logical name of the data source that the reader/writer should use
     * in order to retrieve a <code>DataSource</code> object from a Java
     * Directory and Naming Interface (JNDI) naming service.
     * @serial
     */
    private String dataSource;

    /**
     * The user name the reader, writer, or both supply to the method
     * <code>DriverManager.getConnection</code> when the
     * <code>DriverManager</code> is used to get a connection.
     * @serial
     */
    private transient String username;

    /**
     * The password the reader, writer, or both supply to the method
     * <code>DriverManager.getConnection</code> when the
     * <code>DriverManager</code> is used to get a connection.
     * @serial
     */
    private transient String password;

    /**
     * A constant indicating the type of this JDBC <code>RowSet</code>
     * object. It must be one of the following <code>ResultSet</code>
     * constants:  <code>TYPE_FORWARD_ONLY</code>,
     * <code>TYPE_SCROLL_INSENSITIVE</code>, or
     * <code>TYPE_SCROLL_SENSITIVE</code>.
     * @serial
     */
    private int rowSetType = ResultSet.TYPE_SCROLL_INSENSITIVE;

    /**
     * A <code>boolean</code> indicating whether deleted rows are visible in this
     * JDBC <code>RowSet</code> object .
     * @serial
     */
    private boolean showDeleted = false; // default is false

    /**
     * The maximum number of seconds the driver
     * will wait for a command to execute.  This limit applies while
     * this JDBC <code>RowSet</code> object is connected to its data
     * source, that is, while it is populating itself with
     * data and while it is writing data back to the data source.
     * @serial
     */
    private int queryTimeout = 0; // default is no timeout

    /**
     * The maximum number of rows the reader should read.
     * @serial
     */
    private int maxRows = 0; // default is no limit

    /**
     * The maximum field size the reader should read.
     * @serial
     */
    private int maxFieldSize = 0; // default is no limit

    /**
     * A constant indicating the concurrency of this JDBC <code>RowSet</code>
     * object. It must be one of the following <code>ResultSet</code>
     * constants: <code>CONCUR_READ_ONLY</code> or
     * <code>CONCUR_UPDATABLE</code>.
     * @serial
     */
    private int concurrency = ResultSet.CONCUR_UPDATABLE;

    /**
     * A <code>boolean</code> indicating whether this JDBC <code>RowSet</code>
     * object is read-only.  <code>true</code> indicates that it is read-only;
     * <code>false</code> that it is writable.
     * @serial
     */
    private boolean readOnly;

    /**
     * A <code>boolean</code> indicating whether the reader for this
     * JDBC <code>RowSet</code> object should perform escape processing.
     * <code>true</code> means that escape processing is turned on;
     * <code>false</code> that it is not. The default is <code>true</code>.
     * @serial
     */
    private boolean escapeProcessing;

    /**
     * A constant indicating the isolation level of the connection
     * for this JDBC <code>RowSet</code> object . It must be one of
     * the following <code>Connection</code> constants:
     * <code>TRANSACTION_NONE</code>,
     * <code>TRANSACTION_READ_UNCOMMITTED</code>,
     * <code>TRANSACTION_READ_COMMITTED</code>,
     * <code>TRANSACTION_REPEATABLE_READ</code> or
     * <code>TRANSACTION_SERIALIZABLE</code>.
     * @serial
     */
    private int isolation;

    /**
     * A constant used as a hint to the driver that indicates the direction in
     * which data from this JDBC <code>RowSet</code> object  is going
     * to be fetched. The following <code>ResultSet</code> constants are
     * possible values:
     * <code>FETCH_FORWARD</code>,
     * <code>FETCH_REVERSE</code>,
     * <code>FETCH_UNKNOWN</code>.
     * <P>
     * Unused at this time.
     * @serial
     */
    private int fetchDir = ResultSet.FETCH_FORWARD; // default fetch direction

    /**
     * A hint to the driver that indicates the expected number of rows
     * in this JDBC <code>RowSet</code> object .
     * <P>
     * Unused at this time.
     * @serial
     */
    private int fetchSize = 0; // default fetchSize

    /**
     * The <code>java.util.Map</code> object that contains entries mapping
     * SQL type names to classes in the Java programming language for the
     * custom mapping of user-defined types.
     * @serial
     */
    private Map map;

    /**
     * A <code>Vector</code> object that holds the list of listeners
     * that have registered with this <code>RowSet</code> object.
     * @serial
     */
    private Vector listeners;

    /**
     * A <code>Vector</code> object that holds the parameters set
     * for this <code>RowSet</code> object's current command.
     * @serial
     */
    private Hashtable params; // could be transient?

    /**
     * Constructs a new <code>BaseRowSet</code> object initialized with
     * a default <code>Vector</code> object for its <code>listeners</code>
     * field. The other default values with which it is initialized are listed
     * in Section 6.0 of the class comment for this class.
     */
    public BaseRowSet() {
        // allocate the listeners collection
        listeners = new Vector();
    }

    /**
     * Performs the necessary internal configurations and initializations
     * to allow any JDBC <code>RowSet</code> implementation to start using
     * the standard facilities provided by a <code>BaseRowSet</code>
     * instance. This method <b>should</b> be called after the <code>RowSet</code> object
     * has been instantiated to correctly initialize all parameters. This method
     * <b>should</b> never be called by an application, but is called from with
     * a <code>RowSet</code> implementation extending this class.
     */
    protected void initParams() {
        params = new Hashtable();
    }

    //--------------------------------------------------------------------
    // Events
    //--------------------------------------------------------------------

    /**
    * The listener will be notified whenever an event occurs on this <code>RowSet</code>
    * object.
    * <P>
    * A listener might, for example, be a table or graph that needs to
    * be updated in order to accurately reflect the current state of
    * the <code>RowSet</code> object.
    * <p>
    * <b>Note</b>: if the <code>RowSetListener</code> object is
    * <code>null</code>, this method silently discards the <code>null</code>
    * value and does not add a null reference to the set of listeners.
    * <p>
    * <b>Note</b>: if the listener is already set, and the new <code>RowSetListerner</code>
    * instance is added to the set of listeners already registered to receive
    * event notifications from this <code>RowSet</code>.
    *
    * @param listener an object that has implemented the
    *     <code>javax.sql.RowSetListener</code> interface and wants to be notified
    *     of any events that occur on this <code>RowSet</code> object; May be
    *     null.
    * @see #removeRowSetListener
    */
    public void addRowSetListener(RowSetListener listener) {
        listeners.add(listener);
    }

    /**
    * Removes the designated object from this <code>RowSet</code> object's list of listeners.
    * If the given argument is not a registered listener, this method
    * does nothing.
    *
    *  <b>Note</b>: if the <code>RowSetListener</code> object is
    * <code>null</code>, this method silently discards the <code>null</code>
    * value.
    *
    * @param listener a <code>RowSetListener</code> object that is on the list
    *        of listeners for this <code>RowSet</code> object
    * @see #addRowSetListener
    */
    public void removeRowSetListener(RowSetListener listener) {
        listeners.remove(listener);
    }

    /**
     * Determine if instance of this class extends the RowSet interface.
     */
    private void checkforRowSetInterface() throws SQLException {
        if ((this instanceof javax.sql.RowSet) == false) {
            throw new SQLException("The class extending abstract class BaseRowSet " +
                "must implement javax.sql.RowSet or one of it's sub-interfaces.");
        }
    }

    /**
    * Notifies all of the listeners registered with this
    * <code>RowSet</code> object that its cursor has moved.
    * <P>
    * When an application calls a method to move the cursor,
    * that method moves the cursor and then calls this method
    * internally. An application <b>should</b> never invoke
    * this method directly.
    *
    * @throws SQLException if the class extending the <code>BaseRowSet</code>
    *     abstract class does not implement the <code>RowSet</code> interface or
    *     one of it's sub-interfaces.
    */
    protected void notifyCursorMoved() throws SQLException {
        checkforRowSetInterface();
        if (listeners.isEmpty() == false) {
            RowSetEvent event = new RowSetEvent((RowSet)this);
            for (Iterator i = listeners.iterator(); i.hasNext(); ) {
                ((RowSetListener)i.next()).cursorMoved(event);
            }
        }
    }

    /**
    * Notifies all of the listeners registered with this <code>RowSet</code> object that
    * one of its rows has changed.
    * <P>
    * When an application calls a method that changes a row, such as
    * the <code>CachedRowSet</code> methods <code>insertRow</code>,
    * <code>updateRow</code>, or <code>deleteRow</code>,
    * that method calls <code>notifyRowChanged</code>
    * internally. An application <b>should</b> never invoke
    * this method directly.
    *
    * @throws SQLException if the class extending the <code>BaseRowSet</code>
    *     abstract class does not implement the <code>RowSet</code> interface or
    *     one of it's sub-interfaces.
    */
    protected void notifyRowChanged() throws SQLException {
        checkforRowSetInterface();
        if (listeners.isEmpty() == false) {
                RowSetEvent event = new RowSetEvent((RowSet)this);
                for (Iterator i = listeners.iterator(); i.hasNext(); ) {
                        ((RowSetListener)i.next()).rowChanged(event);
                }
        }
    }

   /**
    * Notifies all of the listeners registered with this <code>RowSet</code>
    * object that its entire contents have changed.
    * <P>
    * When an application calls methods that change the entire contents
    * of the <code>RowSet</code> object, such as the <code>CachedRowSet</code> methods
    * <code>execute</code>, <code>populate</code>, <code>restoreOriginal</code>,
    * or <code>release</code>, that method calls <code>notifyRowSetChanged</code>
    * internally (either directly or indirectly). An application <b>should</b>
    * never invoke this method directly.
    *
    * @throws SQLException if the class extending the <code>BaseRowSet</code>
    *     abstract class does not implement the <code>RowSet</code> interface or
    *     one of it's sub-interfaces.
    */
    protected void notifyRowSetChanged() throws SQLException {
        checkforRowSetInterface();
        if (listeners.isEmpty() == false) {
                RowSetEvent event = new RowSetEvent((RowSet)this);
                for (Iterator i = listeners.iterator(); i.hasNext(); ) {
                        ((RowSetListener)i.next()).rowSetChanged(event);
                }
        }
}

    /**
     * Retrieves the SQL query that is the command for this
     * <code>RowSet</code> object. The command property contains the query that
     * will be executed to populate this <code>RowSet</code> object.
     * <P>
     * The SQL query returned by this method is used by <code>RowSet</code> methods
     * such as <code>execute</code> and <code>populate</code>, which may be implemented
     * by any class that extends the <code>BaseRowSet</code> abstract class and
     * implements one or more of the standard JSR-114 <code>RowSet</code>
     * interfaces.
     * <P>
     * The command is used by the <code>RowSet</code> object's
     * reader to obtain a <code>ResultSet</code> object.  The reader then
     * reads the data from the <code>ResultSet</code> object and uses it to
     * to populate this <code>RowSet</code> object.
     * <P>
     * The default value for the <code>command</code> property is <code>null</code>.
     *
     * @return the <code>String</code> that is the value for this
     *         <code>RowSet</code> object's <code>command</code> property;
     *         may be <code>null</code>
     * @see #setCommand
     */
    public String getCommand() {
        return command;
    }

    /**
     * Sets this <code>RowSet</code> object's <code>command</code> property to
     * the given <code>String</code> object and clears the parameters, if any,
     * that were set for the previous command.
     * <P>
     * The <code>command</code> property may not be needed if the <code>RowSet</code>
     * object gets its data from a source that does not support commands,
     * such as a spreadsheet or other tabular file.
     * Thus, this property is optional and may be <code>null</code>.
     *
     * @param cmd a <code>String</code> object containing an SQL query
     *            that will be set as this <code>RowSet</code> object's command
     *            property; may be <code>null</code> but may not be an empty string
     * @throws SQLException if an empty string is provided as the command value
     * @see #getCommand
     */
    public void setCommand(String cmd) throws SQLException {
        // cmd equal to null or
        // cmd with length 0 (implies url =="")
        // are not independent events.

        if(cmd == null) {
           command = null;
        } else if (cmd.length() == 0) {
            throw new SQLException("Invalid command string detected. " +
            "Cannot be of length less than 0");
        } else {
            // "unbind" any parameters from any previous command.
            if(params == null){
                 throw new SQLException("Set initParams() before setCommand");
            }
            params.clear();
            command = new String(cmd);
        }

    }

    /**
     * Retrieves the JDBC URL that this <code>RowSet</code> object's
     * <code>javax.sql.Reader</code> object uses to make a connection
     * with a relational database using a JDBC technology-enabled driver.
     *<P>
     * The <code>Url</code> property will be <code>null</code> if the underlying data
     * source is a non-SQL data source, such as a spreadsheet or an XML
     * data source.
     *
     * @return a <code>String</code> object that contains the JDBC URL
     *         used to establish the connection for this <code>RowSet</code>
     *         object; may be <code>null</code> (default value) if not set
     * @throws SQLException if an error occurs retrieving the URL value
     * @see #setUrl
     */
    public String getUrl() throws SQLException {
        return URL;
    }

    /**
     * Sets the Url property for this <code>RowSet</code> object
     * to the given <code>String</code> object and sets the dataSource name
     * property to <code>null</code>. The Url property is a
     * JDBC URL that is used when
     * the connection is created using a JDBC technology-enabled driver
     * ("JDBC driver") and the <code>DriverManager</code>.
     * The correct JDBC URL for the specific driver to be used can be found
     * in the driver documentation.  Although there are guidelines for for how
     * a JDBC URL is formed,
     * a driver vendor can specify any <code>String</code> object except
     * one with a length of <code>0</code> (an empty string).
     * <P>
     * Setting the Url property is optional if connections are established using
     * a <code>DataSource</code> object instead of the <code>DriverManager</code>.
     * The driver will use either the URL property or the
     * dataSourceName property to create a connection, whichever was
     * specified most recently. If an application uses a JDBC URL, it
     * must load a JDBC driver that accepts the JDBC URL before it uses the
     * <code>RowSet</code> object to connect to a database.  The <code>RowSet</code>
     * object will use the URL internally to create a database connection in order
     * to read or write data.
     *
     * @param url a <code>String</code> object that contains the JDBC URL
     *     that will be used to establish the connection to a database for this
     *     <code>RowSet</code> object; may be <code>null</code> but must not
     *     be an empty string
     * @throws SQLException if an error occurs setting the Url property or the
     *     parameter supplied is a string with a length of <code>0</code> (an
     *     empty string)
     * @see #getUrl
     */
    public void setUrl(String url) throws SQLException {
        if(url == null) {
           url = null;
        } else if (url.length() < 1) {
            throw new SQLException("Invalid url string detected. " +
            "Cannot be of length less than 1");
        } else {
            URL = new String(url);
        }

        dataSource = null;

    }

    /**
     * Returns the logical name that when supplied to a naming service
     * that uses the Java Naming and Directory Interface (JNDI) API, will
     * retrieve a <code>javax.sql.DataSource</code> object. This
     * <code>DataSource</code> object can be used to establish a connection
     * to the data source that it represents.
     * <P>
     * Users should set either the url or the data source name property.
     * The driver will use the property set most recently to establish a
     * connection.
     *
     * @return a <code>String</code> object that identifies the
     *         <code>DataSource</code> object to be used for making a
     *         connection; if no logical name has been set, <code>null</code>
     *         is returned.
     * @see #setDataSourceName
     */
    public String getDataSourceName() {
        return dataSource;
    }


    /**
     * Sets the <code>DataSource</code> name property for this <code>RowSet</code>
     * object to the given logical name and sets this <code>RowSet</code> object's
     * Url property to <code>null</code>. The name must have been bound to a
     * <code>DataSource</code> object in a JNDI naming service so that an
     * application can do a lookup using that name to retrieve the
     * <code>DataSource</code> object bound to it. The <code>DataSource</code>
     * object can then be used to establish a connection to the data source it
     * represents.
     * <P>
     * Users should set either the Url property or the dataSourceName property.
     * If both properties are set, the driver will use the property set most recently.
     *
     * @param name a <code>String</code> object with the name that can be supplied
     *     to a naming service based on JNDI technology to retrieve the
     *     <code>DataSource</code> object that can be used to get a connection;
     *     may be <code>null</code> but must not be an empty string
     * @throws SQLException if an empty string is provided as the <code>DataSource</code>
     *    name
     * @see #getDataSourceName
     */
    public void setDataSourceName(String name) throws SQLException {

        if (name == null) {
            dataSource = null;
        } else if (name.equals("")) {
           throw new SQLException("DataSource name cannot be empty string");
        } else {
           dataSource = new String(name);
        }

        URL = null;
    }

    /**
     * Returns the user name used to create a database connection.  Because it
     * is not serialized, the username property is set at runtime before
     * calling the method <code>execute</code>.
     *
     * @return the <code>String</code> object containing the user name that
     *         is supplied to the data source to create a connection; may be
     *         <code>null</code> (default value) if not set
     * @see #setUsername
     */
    public String getUsername() {
        return username;
    }

    /**
     * Sets the username property for this <code>RowSet</code> object
     * to the given user name. Because it
     * is not serialized, the username property is set at run time before
     * calling the method <code>execute</code>.
     *
     * @param name the <code>String</code> object containing the user name that
     *     is supplied to the data source to create a connection. It may be null.
     * @see #getUsername
     */
    public void setUsername(String name) {
        if(name == null)
        {
           username = null;
        } else {
           username = new String(name);
        }
    }

    /**
     * Returns the password used to create a database connection for this
     * <code>RowSet</code> object.  Because the password property is not
     * serialized, it is set at run time before calling the method
     * <code>execute</code>. The default value is <code>null</code>
     *
     * @return the <code>String</code> object that represents the password
     *         that must be supplied to the database to create a connection
     * @see #setPassword
     */
    public String getPassword() {
        return password;
    }

    /**
     * Sets the password used to create a database connection for this
     * <code>RowSet</code> object to the given <code>String</code>
     * object.  Because the password property is not
     * serialized, it is set at run time before calling the method
     * <code>execute</code>.
     *
     * @param pass the <code>String</code> object that represents the password
     *     that is supplied to the database to create a connection. It may be
     *     null.
     * @see #getPassword
     */
    public void setPassword(String pass) {
        if(pass == null)
        {
           password = null;
        } else {
           password = new String(pass);
        }
    }

    /**
     * Sets the type for this <code>RowSet</code> object to the specified type.
     * The default type is <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>.
     *
     * @param type one of the following constants:
     *             <code>ResultSet.TYPE_FORWARD_ONLY</code>,
     *             <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
     *             <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
     * @throws SQLException if the parameter supplied is not one of the
     *         following constants:
     *          <code>ResultSet.TYPE_FORWARD_ONLY</code> or
     *          <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>
     *          <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
     * @see #getConcurrency
     * @see #getType
     */
    public void setType(int type) throws SQLException {

        if ((type != ResultSet.TYPE_FORWARD_ONLY) &&
           (type != ResultSet.TYPE_SCROLL_INSENSITIVE) &&
           (type != ResultSet.TYPE_SCROLL_SENSITIVE)) {
                throw new SQLException("Invalid type of RowSet set. Must be either " +
                "ResultSet.TYPE_FORWARD_ONLY or ResultSet.TYPE_SCROLL_INSENSITIVE " +
                "or ResultSet.TYPE_SCROLL_SENSITIVE.");
        }
        this.rowSetType = type;
    }

    /**
     * Returns the type of this <code>RowSet</code> object. The type is initially
     * determined by the statement that created the <code>RowSet</code> object.
     * The <code>RowSet</code> object can call the method
     * <code>setType</code> at any time to change its
     * type.  The default is <code>TYPE_SCROLL_INSENSITIVE</code>.
     *
     * @return the type of this JDBC <code>RowSet</code>
     *         object, which must be one of the following:
     *         <code>ResultSet.TYPE_FORWARD_ONLY</code>,
     *         <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
     *         <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
     * @throws SQLException if an error occurs getting the type of
     *     of this <code>RowSet</code> object
     * @see #setType
     */
    public int getType() throws SQLException {
        return rowSetType;
    }

    /**
     * Sets the concurrency for this <code>RowSet</code> object to
     * the specified concurrency. The default concurrency for any <code>RowSet</code>
     * object (connected or disconnected) is <code>ResultSet.CONCUR_UPDATABLE</code>,
     * but this method may be called at any time to change the concurrency.
     * <P>
     * @param concurrency one of the following constants:
     *                    <code>ResultSet.CONCUR_READ_ONLY</code> or
     *                    <code>ResultSet.CONCUR_UPDATABLE</code>
     * @throws SQLException if the parameter supplied is not one of the
     *         following constants:
     *          <code>ResultSet.CONCUR_UPDATABLE</code> or
     *          <code>ResultSet.CONCUR_READ_ONLY</code>
     * @see #getConcurrency
     * @see #isReadOnly
     */
    public void setConcurrency(int concurrency) throws SQLException {

        if((concurrency != ResultSet.CONCUR_READ_ONLY) &&
           (concurrency != ResultSet.CONCUR_UPDATABLE)) {
                throw new SQLException("Invalid concurrency set. Must be either " +
                "ResultSet.CONCUR_READ_ONLY or ResultSet.CONCUR_UPDATABLE.");
        }
        this.concurrency = concurrency;
    }

    /**
     * Returns a <code>boolean</code> indicating whether this
     * <code>RowSet</code> object is read-only.
     * Any attempts to update a read-only <code>RowSet</code> object will result in an
     * <code>SQLException</code> being thrown. By default,
     * rowsets are updatable if updates are possible.
     *
     * @return <code>true</code> if this <code>RowSet</code> object
     *         cannot be updated; <code>false</code> otherwise
     * @see #setConcurrency
     * @see #setReadOnly
     */
    public boolean isReadOnly() {
        return readOnly;
    };

    /**
     * Sets this <code>RowSet</code> object's readOnly  property to the given <code>boolean</code>.
     *
     * @param value <code>true</code> to indicate that this
     *              <code>RowSet</code> object is read-only;
     *              <code>false</code> to indicate that it is updatable
     */
    public void setReadOnly(boolean value) {
        readOnly = value;
    }

    /**
     * Returns the transaction isolation property for this
     * <code>RowSet</code> object's connection. This property represents
     * the transaction isolation level requested for use in transactions.
     * <P>
     * For <code>RowSet</code> implementations such as
     * the <code>CachedRowSet</code> that operate in a disconnected environment,
     * the <code>SyncProvider</code> object
     * offers complementary locking and data integrity options. The
     * options described below are pertinent only to connected <code>RowSet</code>
     * objects (<code>JdbcRowSet</code> objects).
     *
     * @return one of the following constants:
     *         <code>Connection.TRANSACTION_NONE</code>,
     *         <code>Connection.TRANSACTION_READ_UNCOMMITTED</code>,
     *         <code>Connection.TRANSACTION_READ_COMMITTED</code>,
     *         <code>Connection.TRANSACTION_REPEATABLE_READ</code>, or
     *         <code>Connection.TRANSACTION_SERIALIZABLE</code>
     * @see javax.sql.rowset.spi.SyncFactory
     * @see javax.sql.rowset.spi.SyncProvider
     * @see #setTransactionIsolation

     */
    public int getTransactionIsolation() {
        return isolation;
    };

    /**
     * Sets the transaction isolation property for this JDBC <code>RowSet</code> object to the given
     * constant. The DBMS will use this transaction isolation level for
     * transactions if it can.
     * <p>
     * For <code>RowSet</code> implementations such as
     * the <code>CachedRowSet</code> that operate in a disconnected environment,
     * the <code>SyncProvider</code> object being used
     * offers complementary locking and data integrity options. The
     * options described below are pertinent only to connected <code>RowSet</code>
     * objects (<code>JdbcRowSet</code> objects).
     *
     * @param level one of the following constants, listed in ascending order:
     *              <code>Connection.TRANSACTION_NONE</code>,
     *              <code>Connection.TRANSACTION_READ_UNCOMMITTED</code>,
     *              <code>Connection.TRANSACTION_READ_COMMITTED</code>,
     *              <code>Connection.TRANSACTION_REPEATABLE_READ</code>, or
     *              <code>Connection.TRANSACTION_SERIALIZABLE</code>
     * @throws SQLException if the given parameter is not one of the Connection
     *          constants
     * @see javax.sql.rowset.spi.SyncFactory
     * @see javax.sql.rowset.spi.SyncProvider
     * @see #getTransactionIsolation
     */
    public void setTransactionIsolation(int level) throws SQLException {
        if ((level != Connection.TRANSACTION_NONE) &&
           (level != Connection.TRANSACTION_READ_COMMITTED) &&
           (level != Connection.TRANSACTION_READ_UNCOMMITTED) &&
           (level != Connection.TRANSACTION_REPEATABLE_READ) &&
           (level != Connection.TRANSACTION_SERIALIZABLE))
            {
                throw new SQLException("Invalid transaction isolation set. Must " +
                "be either " +
                "Connection.TRANSACTION_NONE or " +
                "Connection.TRANSACTION_READ_UNCOMMITTED or " +
                "Connection.TRANSACTION_READ_COMMITTED or " +
                "Connection.RRANSACTION_REPEATABLE_READ or " +
                "Connection.TRANSACTION_SERIALIZABLE");
            }
        this.isolation = level;
    }

    /**
     * Retrieves the type map associated with the <code>Connection</code>
     * object for this <code>RowSet</code> object.
     * <P>
     * Drivers that support the JDBC 3.0 API will create
     * <code>Connection</code> objects with an associated type map.
     * This type map, which is initially empty, can contain one or more
     * fully-qualified SQL names and <code>Class</code> objects indicating
     * the class to which the named SQL value will be mapped. The type mapping
     * specified in the connection's type map is used for custom type mapping
     * when no other type map supersedes it.
     * <p>
     * If a type map is explicitly supplied to a method that can perform
     * custom mapping, that type map supersedes the connection's type map.
     *
     * @return the <code>java.util.Map</code> object that is the type map
     *         for this <code>RowSet</code> object's connection
     */
    public java.util.Map<String,Class<?>> getTypeMap() {
        return map;
    }

    /**
     * Installs the given <code>java.util.Map</code> object as the type map
     * associated with the <code>Connection</code> object for this
     * <code>RowSet</code> object.  The custom mapping indicated in
     * this type map will be used unless a different type map is explicitly
     * supplied to a method, in which case the type map supplied will be used.
     *
     * @param map a <code>java.util.Map</code> object that contains the
     *     mapping from SQL type names for user defined types (UDT) to classes in
     *     the Java programming language.  Each entry in the <code>Map</code>
     *     object consists of the fully qualified SQL name of a UDT and the
     *     <code>Class</code> object for the <code>SQLData</code> implementation
     *     of that UDT. May be <code>null</code>.
     */
    public void setTypeMap(java.util.Map<String,Class<?>> map) {
        this.map = map;
    }

    /**
     * Retrieves the maximum number of bytes that can be used for a column
     * value in this <code>RowSet</code> object.
     * This limit applies only to columns that hold values of the
     * following types:  <code>BINARY</code>, <code>VARBINARY</code>,
     * <code>LONGVARBINARY</code>, <code>CHAR</code>, <code>VARCHAR</code>,
     * and <code>LONGVARCHAR</code>.  If the limit is exceeded, the excess
     * data is silently discarded.
     *
     * @return an <code>int</code> indicating the current maximum column size
     *     limit; zero means that there is no limit
     * @throws SQLException if an error occurs internally determining the
     *    maximum limit of the column size
     */
    public int getMaxFieldSize() throws SQLException {
        return maxFieldSize;
    }

    /**
     * Sets the maximum number of bytes that can be used for a column
     * value in this <code>RowSet</code> object to the given number.
     * This limit applies only to columns that hold values of the
     * following types:  <code>BINARY</code>, <code>VARBINARY</code>,
     * <code>LONGVARBINARY</code>, <code>CHAR</code>, <code>VARCHAR</code>,
     * and <code>LONGVARCHAR</code>.  If the limit is exceeded, the excess
     * data is silently discarded. For maximum portability, it is advisable to
     * use values greater than 256.
     *
     * @param max an <code>int</code> indicating the new maximum column size
     *     limit; zero means that there is no limit
     * @throws SQLException if (1) an error occurs internally setting the
     *     maximum limit of the column size or (2) a size of less than 0 is set
     */
    public void setMaxFieldSize(int max) throws SQLException {
        if (max < 0) {
            throw new SQLException("Invalid max field size set. Cannot be of " +
            "value: " + max);
        }
        maxFieldSize = max;
    }

    /**
     * Retrieves the maximum number of rows that this <code>RowSet</code> object may contain. If
     * this limit is exceeded, the excess rows are silently dropped.
     *
     * @return an <code>int</code> indicating the current maximum number of
     *     rows; zero means that there is no limit
     * @throws SQLException if an error occurs internally determining the
     *     maximum limit of rows that a <code>Rowset</code> object can contain
     */
    public int getMaxRows() throws SQLException {
        return maxRows;
    }

    /**
     * Sets the maximum number of rows that this <code>RowSet</code> object may contain to
     * the given number. If this limit is exceeded, the excess rows are
     * silently dropped.
     *
     * @param max an <code>int</code> indicating the current maximum number
     *     of rows; zero means that there is no limit
     * @throws SQLException if an error occurs internally setting the
     *     maximum limit on the number of rows that a JDBC <code>RowSet</code> object
     *     can contain; or if <i>max</i> is less than <code>0</code>; or
     *     if <i>max</i> is less than the <code>fetchSize</code> of the
     *     <code>RowSet</code>
     */
    public void setMaxRows(int max) throws SQLException {
        if (max < 0) {
            throw new SQLException("Invalid max row size set. Cannot be of " +
                "value: " + max);
        } else if (max < this.getFetchSize()) {
            throw new SQLException("Invalid max row size set. Cannot be less " +
                "than the fetchSize.");
        }
        this.maxRows = max;
    }

    /**
     * Sets to the given <code>boolean</code> whether or not the driver will
     * scan for escape syntax and do escape substitution before sending SQL
     * statements to the database. The default is for the driver to do escape
     * processing.
     * <P>
     * Note: Since <code>PreparedStatement</code> objects have usually been
     * parsed prior to making this call, disabling escape processing for
     * prepared statements will likely have no effect.
     *
     * @param enable <code>true</code> to enable escape processing;
     *     <code>false</code> to disable it
     * @throws SQLException if an error occurs setting the underlying JDBC
     * technology-enabled driver to process the escape syntax
     */
    public void setEscapeProcessing(boolean enable) throws SQLException {
        escapeProcessing = enable;
    }

    /**
     * Retrieves the maximum number of seconds the driver will wait for a
     * query to execute. If the limit is exceeded, an <code>SQLException</code>
     * is thrown.
     *
     * @return the current query timeout limit in seconds; zero means that
     *     there is no limit
     * @throws SQLException if an error occurs in determining the query
     *     time-out value
     */
    public int getQueryTimeout() throws SQLException {
        return queryTimeout;
    }

    /**
     * Sets to the given number the maximum number of seconds the driver will
     * wait for a query to execute. If the limit is exceeded, an
     * <code>SQLException</code> is thrown.
     *
     * @param seconds the new query time-out limit in seconds; zero means that
     *     there is no limit; must not be less than zero
     * @throws SQLException if an error occurs setting the query
     *     time-out or if the query time-out value is less than 0
     */
    public void setQueryTimeout(int seconds) throws SQLException {
        if (seconds < 0) {
            throw new SQLException("Invalid query timeout value set. Cannot be " +
            "of value: " + seconds);
        }
        this.queryTimeout = seconds;
    }

    /**
     * Retrieves a <code>boolean</code> indicating whether rows marked
     * for deletion appear in the set of current rows.
     * The default value is <code>false</code>.
     * <P>
     * Note: Allowing deleted rows to remain visible complicates the behavior
     * of some of the methods.  However, most <code>RowSet</code> object users
     * can simply ignore this extra detail because only sophisticated
     * applications will likely want to take advantage of this feature.
     *
     * @return <code>true</code> if deleted rows are visible;
     *         <code>false</code> otherwise
     * @throws SQLException if an error occurs determining if deleted rows
     * are visible or not
     * @see #setShowDeleted
     */
    public boolean getShowDeleted() throws SQLException {
        return showDeleted;
    }

    /**
     * Sets the property <code>showDeleted</code> to the given
     * <code>boolean</code> value, which determines whether
     * rows marked for deletion appear in the set of current rows.
     *
     * @param value <code>true</code> if deleted rows should be shown;
     *     <code>false</code> otherwise
     * @throws SQLException if an error occurs setting whether deleted
     *     rows are visible or not
     * @see #getShowDeleted
     */
    public void setShowDeleted(boolean value) throws SQLException {
        showDeleted = value;
    }

    /**
     * Ascertains whether escape processing is enabled for this
     * <code>RowSet</code> object.
     *
     * @return <code>true</code> if escape processing is turned on;
     *         <code>false</code> otherwise
     * @throws SQLException if an error occurs determining if escape
     *     processing is enabled or not or if the internal escape
     *     processing trigger has not been enabled
     */
    public boolean getEscapeProcessing() throws SQLException {
        return escapeProcessing;
    }

    /**
     * Gives the driver a performance hint as to the direction in
     * which the rows in this <code>RowSet</code> object will be
     * processed.  The driver may ignore this hint.
     * <P>
     * A <code>RowSet</code> object inherits the default properties of the
     * <code>ResultSet</code> object from which it got its data.  That
     * <code>ResultSet</code> object's default fetch direction is set by
     * the <code>Statement</code> object that created it.
     * <P>
     * This method applies to a <code>RowSet</code> object only while it is
     * connected to a database using a JDBC driver.
     * <p>
     * A <code>RowSet</code> object may use this method at any time to change
     * its setting for the fetch direction.
     *
     * @param direction one of <code>ResultSet.FETCH_FORWARD</code>,
     *                  <code>ResultSet.FETCH_REVERSE</code>, or
     *                  <code>ResultSet.FETCH_UNKNOWN</code>
     * @throws SQLException if (1) the <code>RowSet</code> type is
     *     <code>TYPE_FORWARD_ONLY</code> and the given fetch direction is not
     *     <code>FETCH_FORWARD</code> or (2) the given fetch direction is not
     *     one of the following:
     *        ResultSet.FETCH_FORWARD,
     *        ResultSet.FETCH_REVERSE, or
     *        ResultSet.FETCH_UNKNOWN
     * @see #getFetchDirection
     */
    public void setFetchDirection(int direction) throws SQLException {
        // Changed the condition checking to the below as there were two
        // conditions that had to be checked
        // 1. RowSet is TYPE_FORWARD_ONLY and direction is not FETCH_FORWARD
        // 2. Direction is not one of the valid values

        if (((getType() == ResultSet.TYPE_FORWARD_ONLY) && (direction != ResultSet.FETCH_FORWARD)) ||
            ((direction != ResultSet.FETCH_FORWARD) &&
            (direction != ResultSet.FETCH_REVERSE) &&
            (direction != ResultSet.FETCH_UNKNOWN))) {
            throw new SQLException("Invalid Fetch Direction");
        }
        fetchDir = direction;
    }

    /**
     * Retrieves this <code>RowSet</code> object's current setting for the
     * fetch direction. The default type is <code>ResultSet.FETCH_FORWARD</code>
     *
     * @return one of <code>ResultSet.FETCH_FORWARD</code>,
     *                  <code>ResultSet.FETCH_REVERSE</code>, or
     *                  <code>ResultSet.FETCH_UNKNOWN</code>
     * @throws SQLException if an error occurs in determining the
     *     current fetch direction for fetching rows
     * @see #setFetchDirection
     */
    public int getFetchDirection() throws SQLException {

        //Added the following code to throw a
        //SQL Exception if the fetchDir is not
        //set properly.Bug id:4914155

        // This checking is not necessary!

        /*
         if((fetchDir != ResultSet.FETCH_FORWARD) &&
           (fetchDir != ResultSet.FETCH_REVERSE) &&
           (fetchDir != ResultSet.FETCH_UNKNOWN)) {
            throw new SQLException("Fetch Direction Invalid");
         }
         */
        return (fetchDir);
    }

    /**
     * Sets the fetch size for this <code>RowSet</code> object to the given number of
     * rows.  The fetch size gives a JDBC technology-enabled driver ("JDBC driver")
     * a hint as to the
     * number of rows that should be fetched from the database when more rows
     * are needed for this <code>RowSet</code> object. If the fetch size specified
     * is zero, the driver ignores the value and is free to make its own best guess
     * as to what the fetch size should be.
     * <P>
     * A <code>RowSet</code> object inherits the default properties of the
     * <code>ResultSet</code> object from which it got its data.  That
     * <code>ResultSet</code> object's default fetch size is set by
     * the <code>Statement</code> object that created it.
     * <P>
     * This method applies to a <code>RowSet</code> object only while it is
     * connected to a database using a JDBC driver.
     * For connected <code>RowSet</code> implementations such as
     * <code>JdbcRowSet</code>, this method has a direct and immediate effect
     * on the underlying JDBC driver.
     * <P>
     * A <code>RowSet</code> object may use this method at any time to change
     * its setting for the fetch size.
     * <p>
     * For <code>RowSet</code> implementations such as
     * <code>CachedRowSet</code>, which operate in a disconnected environment,
     * the <code>SyncProvider</code> object being used
     * may leverage the fetch size to poll the data source and
     * retrieve a number of rows that do not exceed the fetch size and that may
     * form a subset of the actual rows returned by the original query. This is
     * an implementation variance determined by the specific <code>SyncProvider</code>
     * object employed by the disconnected <code>RowSet</code> object.
     * <P>
     *
     * @param rows the number of rows to fetch; <code>0</code> to let the
     *        driver decide what the best fetch size is; must not be less
     *        than <code>0</code> or more than the maximum number of rows
     *        allowed for this <code>RowSet</code> object (the number returned
     *        by a call to the method {@link #getMaxRows})
     * @throws SQLException if the specified fetch size is less than <code>0</code>
     *        or more than the limit for the maximum number of rows
     * @see #getFetchSize
     */
    public void setFetchSize(int rows) throws SQLException {
        //Added this checking as maxRows can be 0 when this function is called
        //maxRows = 0 means rowset can hold any number of rows, os this checking
        // is needed to take care of this condition.
        if (getMaxRows() == 0 && rows >= 0)  {
            fetchSize = rows;
            return;
        }
        if ((rows < 0) || (rows > getMaxRows())) {
            throw new SQLException("Invalid fetch size set. Cannot be of " +
            "value: " + rows);
        }
        fetchSize = rows;
    }

    /**
     * Returns the fetch size for this <code>RowSet</code> object. The default
     * value is zero.
     *
     * @return the number of rows suggested as the fetch size when this <code>RowSet</code> object
     *     needs more rows from the database
     * @throws SQLException if an error occurs determining the number of rows in the
     *     current fetch size
     * @see #setFetchSize
     */
    public int getFetchSize() throws SQLException {
        return fetchSize;
    }

    /**
     * Returns the concurrency for this <code>RowSet</code> object.
     * The default is <code>CONCUR_UPDATABLE</code> for both connected and
     * disconnected <code>RowSet</code> objects.
     * <P>
     * An application can call the method <code>setConcurrency</code> at any time
     * to change a <code>RowSet</code> object's concurrency.
     * <p>
     * @return the concurrency type for this <code>RowSet</code>
     *     object, which must be one of the following:
     *     <code>ResultSet.CONCUR_READ_ONLY</code> or
     *     <code>ResultSet.CONCUR_UPDATABLE</code>
     * @throws SQLException if an error occurs getting the concurrency
     *     of this <code>RowSet</code> object
     * @see #setConcurrency
     * @see #isReadOnly
     */
    public int getConcurrency() throws SQLException {
        return concurrency;
    }

    //-----------------------------------------------------------------------
    // Parameters
    //-----------------------------------------------------------------------

    /**
     * Checks the given index to see whether it is less than <code>1</code> and
     * throws an <code>SQLException</code> object if it is.
     * <P>
     * This method is called by many methods internally; it is never
     * called by an application directly.
     *
     * @param idx an <code>int</code> indicating which parameter is to be
     *     checked; the first parameter is <code>1</code>
     * @throws SQLException if the parameter is less than <code>1</code>
     */
    private void checkParamIndex(int idx) throws SQLException {
        if ((idx < 1)) {
            throw new SQLException("Invalid Parameter Index");
        }
    }

    //---------------------------------------------------------------------
    // setter methods for setting the parameters in a <code>RowSet</code> object's command
    //---------------------------------------------------------------------

    /**
     * Sets the designated parameter to SQL <code>NULL</code>.
     * Note that the parameter's SQL type must be specified using one of the
         * type codes defined in <code>java.sql.Types</code>.  This SQL type is
     * specified in the second parameter.
     * <p>
     * Note that the second parameter tells the DBMS the data type of the value being
     * set to <code>NULL</code>. Some DBMSs require this information, so it is required
     * in order to make code more portable.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <P>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     * <P>
     * Calls made to the method <code>getParams</code> after this version of
     * <code>setNull</code>
     * has been called will return an <code>Object</code> array containing the parameter values that
     * have been set.  In that array, the element that represents the values
     * set with this method will itself be an array. The first element of that array
     * is <code>null</code>.
     * The second element is the value set for <i>sqlType</i>.
     * The parameter number is indicated by an element's position in the array
     * returned by the method <code>getParams</code>,
     * with the first element being the value for the first placeholder parameter, the
     * second element being the value for the second placeholder parameter, and so on.
     * In other words, if the second placeholder parameter is being set to
     * <code>null</code>, the array containing it will be the second element in
     * the array returned by <code>getParams</code>.
     * <P>
     * Note that because the numbering of elements in an array starts at zero,
     * the array element that corresponds to placeholder parameter number
     * <i>parameterIndex</i> is <i>parameterIndex</i> -1.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param sqlType an <code>int</code> that is one of the SQL type codes
     *        defined in the class {@link java.sql.Types}. If a non-standard
     *        <i>sqlType</i> is supplied, this method will not throw a
     *        <code>SQLException</code>. This allows implicit support for
     *        non-standard SQL types.
     * @throws SQLException if a database access error occurs or the given
     *        parameter index is out of bounds
     * @see #getParams
     */
    public void setNull(int parameterIndex, int sqlType) throws SQLException {
        Object nullVal[];
        checkParamIndex(parameterIndex);

        nullVal = new Object[2];
        nullVal[0] = null;
        nullVal[1] = new Integer(sqlType);

       if (params == null){
            throw new SQLException("Set initParams() before setNull");
       }

        params.put(new Integer(parameterIndex - 1), nullVal);
    }

    /**
     * Sets the designated parameter to SQL <code>NULL</code>.
     *
     * Although this version of the  method <code>setNull</code> is intended
     * for user-defined
     * and <code>REF</code> parameters, this method may be used to set a null
     * parameter for any JDBC type. The following are user-defined types:
     * <code>STRUCT</code>, <code>DISTINCT</code>, and <code>JAVA_OBJECT</code>,
     * and named array types.
     *
     * <P><B>Note:</B> To be portable, applications must give the
     * SQL type code and the fully qualified SQL type name when specifying
     * a <code>NULL</code> user-defined or <code>REF</code> parameter.
     * In the case of a user-defined type, the name is the type name of
     * the parameter itself.  For a <code>REF</code> parameter, the name is
     * the type name of the referenced type.  If a JDBC technology-enabled
     * driver does not need the type code or type name information,
     * it may ignore it.
     * <P>
     * If the parameter does not have a user-defined or <code>REF</code> type,
     * the given <code>typeName</code> parameter is ignored.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <P>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     * <P>
     * Calls made to the method <code>getParams</code> after this version of
     * <code>setNull</code>
     * has been called will return an <code>Object</code> array containing the parameter values that
     * have been set.  In that array, the element that represents the values
     * set with this method will itself be an array. The first element of that array
     * is <code>null</code>.
     * The second element is the value set for <i>sqlType</i>, and the third
     * element is the value set for <i>typeName</i>.
     * The parameter number is indicated by an element's position in the array
     * returned by the method <code>getParams</code>,
     * with the first element being the value for the first placeholder parameter, the
     * second element being the value for the second placeholder parameter, and so on.
     * In other words, if the second placeholder parameter is being set to
     * <code>null</code>, the array containing it will be the second element in
     * the array returned by <code>getParams</code>.
     * <P>
     * Note that because the numbering of elements in an array starts at zero,
     * the array element that corresponds to placeholder parameter number
     * <i>parameterIndex</i> is <i>parameterIndex</i> -1.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param sqlType a value from <code>java.sql.Types</code>
     * @param typeName the fully qualified name of an SQL user-defined type,
     *                 which is ignored if the parameter is not a user-defined
     *                 type or <code>REF</code> value
     * @throws SQLException if an error occurs or the given parameter index
     *            is out of bounds
     * @see #getParams
     */
    public void setNull(int parameterIndex, int sqlType, String typeName)
        throws SQLException {

        Object nullVal[];
        checkParamIndex(parameterIndex);

        nullVal = new Object[3];
        nullVal[0] = null;
        nullVal[1] = new Integer(sqlType);
        nullVal[2] = new String(typeName);

       if(params == null){
            throw new SQLException("Set initParams() before setNull");
       }

        params.put(new Integer(parameterIndex - 1), nullVal);
    }


    /**
     * Sets the designated parameter to the given <code>boolean</code> in the
     * Java programming language.  The driver converts this to an SQL
     * <code>BIT</code> value when it sends it to the database.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code>, <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <p>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x the parameter value
     * @throws SQLException if an error occurs or the
     *                         parameter index is out of bounds
     * @see #getParams
     */
    public void setBoolean(int parameterIndex, boolean x) throws SQLException {
        checkParamIndex(parameterIndex);

       if(params == null){
            throw new SQLException("Set initParams() before setNull");
       }

        params.put(new Integer(parameterIndex - 1), new Boolean(x));
    }

    /**
     * Sets the designated parameter to the given <code>byte</code> in the Java
     * programming language.  The driver converts this to an SQL
     * <code>TINYINT</code> value when it sends it to the database.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <p>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x the parameter value
     * @throws SQLException if an error occurs or the
     *                         parameter index is out of bounds
     * @see #getParams
     */
    public void setByte(int parameterIndex, byte x) throws SQLException {
        checkParamIndex(parameterIndex);

       if(params == null){
            throw new SQLException("Set initParams() before setByte");
       }

        params.put(new Integer(parameterIndex - 1), new Byte(x));
    }

    /**
     * Sets the designated parameter to the given <code>short</code> in the
     * Java programming language.  The driver converts this to an SQL
     * <code>SMALLINT</code> value when it sends it to the database.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <p>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     * <p>
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x the parameter value
     * @throws SQLException if an error occurs or the
     *                         parameter index is out of bounds
     * @see #getParams
     */
    public void setShort(int parameterIndex, short x) throws SQLException {
        checkParamIndex(parameterIndex);

        if(params == null){
             throw new SQLException("Set initParams() before setShort");
        }

        params.put(new Integer(parameterIndex - 1), new Short(x));
    }

    /**
     * Sets the designated parameter to an <code>int</code> in the Java
     * programming language.  The driver converts this to an SQL
     * <code>INTEGER</code> value when it sends it to the database.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <P>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x the parameter value
     * @throws SQLException if an error occurs or the
     *                         parameter index is out of bounds
     * @see #getParams
     */
    public void setInt(int parameterIndex, int x) throws SQLException {
        checkParamIndex(parameterIndex);
        if(params == null){
             throw new SQLException("Set initParams() before setInt");
        }
        params.put(new Integer(parameterIndex - 1), new Integer(x));
    }

    /**
     * Sets the designated parameter to the given <code>long</code> in the Java
     * programming language.  The driver converts this to an SQL
     * <code>BIGINT</code> value when it sends it to the database.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <P>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x the parameter value
     * @throws SQLException if an error occurs or the
     *                         parameter index is out of bounds
     * @see #getParams
     */
    public void setLong(int parameterIndex, long x) throws SQLException {
        checkParamIndex(parameterIndex);
        if(params == null){
             throw new SQLException("Set initParams() before setLong");
        }
        params.put(new Integer(parameterIndex - 1), new Long(x));
    }

    /**
     * Sets the designated parameter to the given <code>float</code> in the
     * Java programming language.  The driver converts this to an SQL
     * <code>FLOAT</code> value when it sends it to the database.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <P>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x the parameter value
     * @throws SQLException if an error occurs or the
     *                         parameter index is out of bounds
     * @see #getParams
     */
    public void setFloat(int parameterIndex, float x) throws SQLException {
        checkParamIndex(parameterIndex);
        if(params == null){
             throw new SQLException("Set initParams() before setFloat");
        }
        params.put(new Integer(parameterIndex - 1), new Float(x));
    }

    /**
     * Sets the designated parameter to the given <code>double</code> in the
     * Java programming language.  The driver converts this to an SQL
     * <code>DOUBLE</code> value when it sends it to the database.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <P>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     * S
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x the parameter value
     * @throws SQLException if an error occurs or the
     *                         parameter index is out of bounds
     * @see #getParams
     */
    public void setDouble(int parameterIndex, double x) throws SQLException {
        checkParamIndex(parameterIndex);
        if(params == null){
             throw new SQLException("Set initParams() before setDouble");
        }
        params.put(new Integer(parameterIndex - 1), new Double(x));
    }

    /**
     * Sets the designated parameter to the given
     * <code>java.lang.BigDecimal</code> value.  The driver converts this to
     * an SQL <code>NUMERIC</code> value when it sends it to the database.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <P>
     * Note: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x the parameter value
     * @throws SQLException if an error occurs or the
     *                         parameter index is out of bounds
     * @see #getParams
     */
    public void setBigDecimal(int parameterIndex, java.math.BigDecimal x) throws SQLException {
        checkParamIndex(parameterIndex);
        if(params == null){
             throw new SQLException("Set initParams() before setBigDecimal");
        }
        params.put(new Integer(parameterIndex - 1), x);
    }

    /**
     * Sets the designated parameter to the given <code>String</code>
     * value.  The driver converts this to an SQL
     * <code>VARCHAR</code> or <code>LONGVARCHAR</code> value
     * (depending on the argument's size relative to the driver's limits
     * on <code>VARCHAR</code> values) when it sends it to the database.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <p>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     * <p>
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x the parameter value
     * @throws SQLException if an error occurs or the
     *                         parameter index is out of bounds
     * @see #getParams
     */
    public void setString(int parameterIndex, String x) throws SQLException {
        checkParamIndex(parameterIndex);
        if(params == null){
             throw new SQLException("Set initParams() before setString");
        }
        params.put(new Integer(parameterIndex - 1), x);
    }

    /**
     * Sets the designated parameter to the given array of bytes.
     * The driver converts this to an SQL
     * <code>VARBINARY</code> or <code>LONGVARBINARY</code> value
     * (depending on the argument's size relative to the driver's limits
     * on <code>VARBINARY</code> values) when it sends it to the database.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <p>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x the parameter value
     * @throws SQLException if an error occurs or the
     *                         parameter index is out of bounds
     * @see #getParams
     */
    public void setBytes(int parameterIndex, byte x[]) throws SQLException {
        checkParamIndex(parameterIndex);
        if(params == null){
             throw new SQLException("Set initParams() before setBytes");
        }
        params.put(new Integer(parameterIndex - 1), x);
    }

    /**
     * Sets the designated parameter to the given <code>java.sql.Date</code>
     * value. The driver converts this to an SQL
     * <code>DATE</code> value when it sends it to the database.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <P>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     * <P>
     * Calls made to the method <code>getParams</code> after this version
     * of <code>setDate</code>
     * has been called will return an array with the value to be set for
     * placeholder parameter number <i>parameterIndex</i> being the <code>Date</code>
     * object supplied as the second parameter.
     * Note that because the numbering of elements in an array starts at zero,
     * the array element that corresponds to placeholder parameter number
     * <i>parameterIndex</i> is <i>parameterIndex</i> -1.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x the parameter value
     * @throws SQLException if an error occurs or the
     *                         parameter index is out of bounds
     * @see #getParams
     */
    public void setDate(int parameterIndex, java.sql.Date x) throws SQLException {
        checkParamIndex(parameterIndex);

        if(params == null){
             throw new SQLException("Set initParams() before setDate");
        }
        params.put(new Integer(parameterIndex - 1), x);
    }

    /**
     * Sets the designated parameter to the given <code>java.sql.Time</code>
     * value.  The driver converts this to an SQL <code>TIME</code> value
     * when it sends it to the database.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <P>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     * <P>
     * Calls made to the method <code>getParams</code> after this version
     * of the method <code>setTime</code>
     * has been called will return an array of the parameters that have been set.
     * The parameter to be set for parameter placeholder number <i>parameterIndex</i>
     * will be the <code>Time</code> object that was set as the second parameter
     * to this method.
     * <P>
     * Note that because the numbering of elements in an array starts at zero,
     * the array element that corresponds to placeholder parameter number
     * <i>parameterIndex</i> is <i>parameterIndex</i> -1.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x a <code>java.sql.Time</code> object, which is to be set as the value
     *              for placeholder parameter <i>parameterIndex</i>
     * @throws SQLException if an error occurs or the
     *                         parameter index is out of bounds
     * @see #getParams
     */
    public void setTime(int parameterIndex, java.sql.Time x) throws SQLException {
        checkParamIndex(parameterIndex);
        if(params == null){
             throw new SQLException("Set initParams() before setTime");
        }

        params.put(new Integer(parameterIndex - 1), x);
    }

    /**
     * Sets the designated parameter to the given
     * <code>java.sql.Timestamp</code> value.
     * The driver converts this to an SQL <code>TIMESTAMP</code> value when it
     * sends it to the database.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <P>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     * <P>
     * Calls made to the method <code>getParams</code> after this version of
     * <code>setTimestamp</code>
     * has been called will return an array with the value for parameter placeholder
     * number <i>parameterIndex</i> being the <code>Timestamp</code> object that was
     * supplied as the second parameter to this method.
     * Note that because the numbering of elements in an array starts at zero,
     * the array element that corresponds to placeholder parameter number
     * <i>parameterIndex</i> is <i>parameterIndex</i> -1.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x a <code>java.sql.Timestamp</code> object
     * @throws SQLException if an error occurs or the
     *                         parameter index is out of bounds
     * @see #getParams
     */
    public void setTimestamp(int parameterIndex, java.sql.Timestamp x) throws SQLException {
        checkParamIndex(parameterIndex);
        if(params == null){
             throw new SQLException("Set initParams() before setTimestamp");
        }

        params.put(new Integer(parameterIndex - 1), x);
    }

    /**
     * Sets the designated parameter to the given
     * <code>java.io.InputStream</code> object,
     * which will have the specified number of bytes.
     * The contents of the stream will be read and sent to the database.
     * This method throws an <code>SQLException</code> object if the number of bytes
     * read and sent to the database is not equal to <i>length</i>.
     * <P>
     * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
     * parameter, it may be more practical to send it via a
     * <code>java.io.InputStream</code> object. A JDBC technology-enabled
     * driver will read the data from the stream as needed until it reaches
     * end-of-file. The driver will do any necessary conversion from ASCII to
     * the database <code>CHAR</code> format.
     *
     * <P><B>Note:</B> This stream object can be either a standard
     * Java stream object or your own subclass that implements the
     * standard interface.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <P>
     * Note: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     * <P>
     * Calls made to the method <code>getParams</code> after <code>setAsciiStream</code>
     * has been called will return an array containing the parameter values that
     * have been set.  The element in the array that represents the values
     * set with this method will itself be an array. The first element of that array
     * is the given <code>java.io.InputStream</code> object.
     * The second element is the value set for <i>length</i>.
     * The third element is an internal <code>BaseRowSet</code> constant
     * specifying that the stream passed to this method is an ASCII stream.
     * The parameter number is indicated by an element's position in the array
     * returned by the method <code>getParams</code>,
     * with the first element being the value for the first placeholder parameter, the
     * second element being the value for the second placeholder parameter, and so on.
     * In other words, if the input stream being set is the value for the second
     * placeholder parameter, the array containing it will be the second element in
     * the array returned by <code>getParams</code>.
     * <P>
     * Note that because the numbering of elements in an array starts at zero,
     * the array element that corresponds to placeholder parameter number
     * <i>parameterIndex</i> is element number <i>parameterIndex</i> -1.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x the Java input stream that contains the ASCII parameter value
     * @param length the number of bytes in the stream. This is the number of bytes
     *       the driver will send to the DBMS; lengths of 0 or less are
     *       are undefined but will cause an invalid length exception to be
     *       thrown in the underlying JDBC driver.
     * @throws SQLException if an error occurs, the parameter index is out of bounds,
     *       or when connected to a data source, the number of bytes the driver reads
     *       and sends to the database is not equal to the number of bytes specified
     *       in <i>length</i>
     * @see #getParams
     */
    public void setAsciiStream(int parameterIndex, java.io.InputStream x, int length) throws SQLException {
        Object asciiStream[];
        checkParamIndex(parameterIndex);

        asciiStream = new Object[3];
        asciiStream[0] = x;
        asciiStream[1] = new Integer(length);
        asciiStream[2] = new Integer(ASCII_STREAM_PARAM);

        if(params == null){
             throw new SQLException("Set initParams() before setAsciiStream");
        }

        params.put(new Integer(parameterIndex - 1), asciiStream);
    }

  /**
   * Sets the designated parameter in this <code>RowSet</code> object's command
   * to the given input stream.
   * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
   * parameter, it may be more practical to send it via a
   * <code>java.io.InputStream</code>. Data will be read from the stream
   * as needed until end-of-file is reached.  The JDBC driver will
   * do any necessary conversion from ASCII to the database char format.
   *
   * <P><B>Note:</B> This stream object can either be a standard
   * Java stream object or your own subclass that implements the
   * standard interface.
   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
   * it might be more efficient to use a version of
   * <code>setAsciiStream</code> which takes a length parameter.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the Java input stream that contains the ASCII parameter value
   * @exception SQLException if a database access error occurs or
   * this method is called on a closed <code>PreparedStatement</code>
   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
   * @since 1.6
   */
  public void setAsciiStream(int parameterIndex, java.io.InputStream x)
                      throws SQLException {
      throw new SQLFeatureNotSupportedException("Feature not supported");
  }

    /**
     * Sets the designated parameter to the given <code>java.io.InputStream</code>
     * object, which will have the specified number of bytes.
     * The contents of the stream will be read and sent to the database.
     * This method throws an <code>SQLException</code> object if the number of bytes
     * read and sent to the database is not equal to <i>length</i>.
     * <P>
     * When a very large binary value is input to a
     * <code>LONGVARBINARY</code> parameter, it may be more practical
     * to send it via a <code>java.io.InputStream</code> object.
     * A JDBC technology-enabled driver will read the data from the
     * stream as needed until it reaches end-of-file.
     *
     * <P><B>Note:</B> This stream object can be either a standard
     * Java stream object or your own subclass that implements the
     * standard interface.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     *<P>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     * <P>
     * Calls made to the method <code>getParams</code> after <code>setBinaryStream</code>
     * has been called will return an array containing the parameter values that
     * have been set.  In that array, the element that represents the values
     * set with this method will itself be an array. The first element of that array
     * is the given <code>java.io.InputStream</code> object.
     * The second element is the value set for <i>length</i>.
     * The third element is an internal <code>BaseRowSet</code> constant
     * specifying that the stream passed to this method is a binary stream.
     * The parameter number is indicated by an element's position in the array
     * returned by the method <code>getParams</code>,
     * with the first element being the value for the first placeholder parameter, the
     * second element being the value for the second placeholder parameter, and so on.
     * In other words, if the input stream being set is the value for the second
     * placeholder parameter, the array containing it will be the second element in
     * the array returned by <code>getParams</code>.
     * <P>
     * Note that because the numbering of elements in an array starts at zero,
     * the array element that corresponds to placeholder parameter number
     * <i>parameterIndex</i> is element number <i>parameterIndex</i> -1.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x the input stream that contains the binary value to be set
     * @param length the number of bytes in the stream; lengths of 0 or less are
     *         are undefined but will cause an invalid length exception to be
     *         thrown in the underlying JDBC driver.
     * @throws SQLException if an error occurs, the parameter index is out of bounds,
     *         or when connected to a data source, the number of bytes the driver
     *         reads and sends to the database is not equal to the number of bytes
     *         specified in <i>length</i>
     * @see #getParams
     */
    public void setBinaryStream(int parameterIndex, java.io.InputStream x, int length) throws SQLException {
        Object binaryStream[];
        checkParamIndex(parameterIndex);

        binaryStream = new Object[3];
        binaryStream[0] = x;
        binaryStream[1] = new Integer(length);
        binaryStream[2] = new Integer(BINARY_STREAM_PARAM);
        if(params == null){
             throw new SQLException("Set initParams() before setBinaryStream");
        }

        params.put(new Integer(parameterIndex - 1), binaryStream);
    }


   /**
   * Sets the designated parameter in this <code>RowSet</code> object's command
   * to the given input stream.
   * When a very large binary value is input to a <code>LONGVARBINARY</code>
   * parameter, it may be more practical to send it via a
   * <code>java.io.InputStream</code> object. The data will be read from the
   * stream as needed until end-of-file is reached.
   *
   * <P><B>Note:</B> This stream object can either be a standard
   * Java stream object or your own subclass that implements the
   * standard interface.
   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
   * it might be more efficient to use a version of
   * <code>setBinaryStream</code> which takes a length parameter.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the java input stream which contains the binary parameter value
   * @exception SQLException if a database access error occurs or
   * this method is called on a closed <code>PreparedStatement</code>
   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
   * @since 1.6
   */
  public void setBinaryStream(int parameterIndex, java.io.InputStream x)
                              throws SQLException {
      throw new SQLFeatureNotSupportedException("Feature not supported");
  }


    /**
     * Sets the designated parameter to the given
     * <code>java.io.InputStream</code> object, which will have the specified
     * number of bytes. The contents of the stream will be read and sent
     * to the database.
     * This method throws an <code>SQLException</code> if the number of bytes
     * read and sent to the database is not equal to <i>length</i>.
     * <P>
     * When a very large Unicode value is input to a
     * <code>LONGVARCHAR</code> parameter, it may be more practical
     * to send it via a <code>java.io.InputStream</code> object.
     * A JDBC technology-enabled driver will read the data from the
     * stream as needed, until it reaches end-of-file.
     * The driver will do any necessary conversion from Unicode to the
     * database <code>CHAR</code> format.
     * The byte format of the Unicode stream must be Java UTF-8, as
     * defined in the Java Virtual Machine Specification.
     *
     * <P><B>Note:</B> This stream object can be either a standard
     * Java stream object or your own subclass that implements the
     * standard interface.
     * <P>
     * This method is deprecated; the method <code>getCharacterStream</code>
     * should be used in its place.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Calls made to the method <code>getParams</code> after <code>setUnicodeStream</code>
     * has been called will return an array containing the parameter values that
     * have been set.  In that array, the element that represents the values
     * set with this method will itself be an array. The first element of that array
     * is the given <code>java.io.InputStream</code> object.
     * The second element is the value set for <i>length</i>.
     * The third element is an internal <code>BaseRowSet</code> constant
     * specifying that the stream passed to this method is a Unicode stream.
     * The parameter number is indicated by an element's position in the array
     * returned by the method <code>getParams</code>,
     * with the first element being the value for the first placeholder parameter, the
     * second element being the value for the second placeholder parameter, and so on.
     * In other words, if the input stream being set is the value for the second
     * placeholder parameter, the array containing it will be the second element in
     * the array returned by <code>getParams</code>.
     * <P>
     * Note that because the numbering of elements in an array starts at zero,
     * the array element that corresponds to placeholder parameter number
     * <i>parameterIndex</i> is element number <i>parameterIndex</i> -1.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x the <code>java.io.InputStream</code> object that contains the
     *          UNICODE parameter value
     * @param length the number of bytes in the input stream
     * @throws SQLException if an error occurs, the parameter index is out of bounds,
     *         or the number of bytes the driver reads and sends to the database is
     *         not equal to the number of bytes specified in <i>length</i>
     * @deprecated getCharacterStream should be used in its place
     * @see #getParams
     */

    public void setUnicodeStream(int parameterIndex, java.io.InputStream x, int length) throws SQLException {
        Object unicodeStream[];
        checkParamIndex(parameterIndex);

        unicodeStream = new Object[3];
        unicodeStream[0] = x;
        unicodeStream[1] = new Integer(length);
        unicodeStream[2] = new Integer(UNICODE_STREAM_PARAM);
        if(params == null){
             throw new SQLException("Set initParams() before setUnicodeStream");
        }
        params.put(new Integer(parameterIndex - 1), unicodeStream);
    }

    /**
     * Sets the designated parameter to the given <code>java.io.Reader</code>
     * object, which will have the specified number of characters. The
     * contents of the reader will be read and sent to the database.
     * This method throws an <code>SQLException</code> if the number of bytes
     * read and sent to the database is not equal to <i>length</i>.
     * <P>
     * When a very large Unicode value is input to a
     * <code>LONGVARCHAR</code> parameter, it may be more practical
     * to send it via a <code>Reader</code> object.
     * A JDBC technology-enabled driver will read the data from the
     * stream as needed until it reaches end-of-file.
     * The driver will do any necessary conversion from Unicode to the
     * database <code>CHAR</code> format.
     * The byte format of the Unicode stream must be Java UTF-8, as
     * defined in the Java Virtual Machine Specification.
     *
     * <P><B>Note:</B> This stream object can be either a standard
     * Java stream object or your own subclass that implements the
     * standard interface.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <P>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     * <P>
     * Calls made to the method <code>getParams</code> after
     * <code>setCharacterStream</code>
     * has been called will return an array containing the parameter values that
     * have been set.  In that array, the element that represents the values
     * set with this method will itself be an array. The first element of that array
     * is the given <code>java.io.Reader</code> object.
     * The second element is the value set for <i>length</i>.
     * The parameter number is indicated by an element's position in the array
     * returned by the method <code>getParams</code>,
     * with the first element being the value for the first placeholder parameter, the
     * second element being the value for the second placeholder parameter, and so on.
     * In other words, if the reader being set is the value for the second
     * placeholder parameter, the array containing it will be the second element in
     * the array returned by <code>getParams</code>.
     * <P>
     * Note that because the numbering of elements in an array starts at zero,
     * the array element that corresponds to placeholder parameter number
     * <i>parameterIndex</i> is element number <i>parameterIndex</i> -1.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param reader the <code>Reader</code> object that contains the
     *        Unicode data
     * @param length the number of characters in the stream; lengths of 0 or
     *        less are undefined but will cause an invalid length exception to
     *        be thrown in the underlying JDBC driver.
     * @throws SQLException if an error occurs, the parameter index is out of bounds,
     *        or when connected to a data source, the number of bytes the driver
     *        reads and sends to the database is not equal to the number of bytes
     *        specified in <i>length</i>
     * @see #getParams
     */
    public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException {
        Object charStream[];
        checkParamIndex(parameterIndex);

        charStream = new Object[2];
        charStream[0] = reader;
        charStream[1] = new Integer(length);
        if(params == null){
             throw new SQLException("Set initParams() before setCharacterStream");
        }
        params.put(new Integer(parameterIndex - 1), charStream);
    }

   /**
   * Sets the designated parameter in this <code>RowSet</code> object's command
   * to the given <code>Reader</code>
   * object.
   * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
   * parameter, it may be more practical to send it via a
   * <code>java.io.Reader</code> object. The data will be read from the stream
   * as needed until end-of-file is reached.  The JDBC driver will
   * do any necessary conversion from UNICODE to the database char format.
   *
   * <P><B>Note:</B> This stream object can either be a standard
   * Java stream object or your own subclass that implements the
   * standard interface.
   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
   * it might be more efficient to use a version of
   * <code>setCharacterStream</code> which takes a length parameter.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param reader the <code>java.io.Reader</code> object that contains the
   *        Unicode data
   * @exception SQLException if a database access error occurs or
   * this method is called on a closed <code>PreparedStatement</code>
   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
   * @since 1.6
   */
  public void setCharacterStream(int parameterIndex,
                          java.io.Reader reader) throws SQLException {
      throw new SQLFeatureNotSupportedException("Feature not supported");
  }

    /**
     * Sets the designated parameter to an <code>Object</code> in the Java
     * programming language. The second parameter must be an
     * <code>Object</code> type.  For integral values, the
     * <code>java.lang</code> equivalent
     * objects should be used. For example, use the class <code>Integer</code>
     * for an <code>int</code>.
     * <P>
     * The driver converts this object to the specified
     * target SQL type before sending it to the database.
     * If the object has a custom mapping (is of a class implementing
     * <code>SQLData</code>), the driver should call the method
     * <code>SQLData.writeSQL</code> to write the object to the SQL
     * data stream. If, on the other hand, the object is of a class
     * implementing <code>Ref</code>, <code>Blob</code>, <code>Clob</code>,
     * <code>Struct</code>, or <code>Array</code>,
     * the driver should pass it to the database as a value of the
     * corresponding SQL type.
     * <P>
     * <p>Note that this method may be used to pass database-
     * specific abstract data types.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <P>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     * <P>
     * Calls made to the method <code>getParams</code> after this version of
     * <code>setObject</code>
     * has been called will return an array containing the parameter values that
     * have been set.  In that array, the element that represents the values
     * set with this method will itself be an array. The first element of that array
     * is the given <code>Object</code> instance, and the
     * second element is the value set for <i>targetSqlType</i>.  The
     * third element is the value set for <i>scale</i>, which the driver will
     * ignore if the type of the object being set is not
     * <code>java.sql.Types.NUMERIC</code> or <code>java.sql.Types.DECIMAL</code>.
     * The parameter number is indicated by an element's position in the array
     * returned by the method <code>getParams</code>,
     * with the first element being the value for the first placeholder parameter, the
     * second element being the value for the second placeholder parameter, and so on.
     * In other words, if the object being set is the value for the second
     * placeholder parameter, the array containing it will be the second element in
     * the array returned by <code>getParams</code>.
     *<P>
     * Note that because the numbering of elements in an array starts at zero,
     * the array element that corresponds to placeholder parameter number
     * <i>parameterIndex</i> is element number <i>parameterIndex</i> -1.
     *
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x the <code>Object</code> containing the input parameter value;
     *        must be an <code>Object</code> type
     * @param targetSqlType the SQL type (as defined in <code>java.sql.Types</code>)
     *        to be sent to the database. The <code>scale</code> argument may
     *        further qualify this type. If a non-standard <i>targetSqlType</i>
     *        is supplied, this method will not throw a <code>SQLException</code>.
     *        This allows implicit support for non-standard SQL types.
     * @param scale for the types <code>java.sql.Types.DECIMAL</code> and
     *        <code>java.sql.Types.NUMERIC</code>, this is the number
     *        of digits after the decimal point.  For all other types, this
     *        value will be ignored.
     * @throws SQLException if an error occurs or the parameter index is out of bounds
     * @see #getParams
     */
    public void setObject(int parameterIndex, Object x, int targetSqlType, int scale) throws SQLException {
        Object obj[];
        checkParamIndex(parameterIndex);

        obj = new Object[3];
        obj[0] = x;
        obj[1] = new Integer(targetSqlType);
        obj[2] = new Integer(scale);
        if(params == null){
             throw new SQLException("Set initParams() before setObject");
        }
        params.put(new Integer(parameterIndex - 1), obj);
    }

    /**
     * Sets the value of the designated parameter with the given
     * <code>Object</code> value.
     * This method is like <code>setObject(int parameterIndex, Object x, int
     * targetSqlType, int scale)</code> except that it assumes a scale of zero.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <P>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     * <P>
     * Calls made to the method <code>getParams</code> after this version of
     * <code>setObject</code>
     * has been called will return an array containing the parameter values that
     * have been set.  In that array, the element that represents the values
     * set with this method will itself be an array. The first element of that array
     * is the given <code>Object</code> instance.
     * The second element is the value set for <i>targetSqlType</i>.
     * The parameter number is indicated by an element's position in the array
     * returned by the method <code>getParams</code>,
     * with the first element being the value for the first placeholder parameter, the
     * second element being the value for the second placeholder parameter, and so on.
     * In other words, if the object being set is the value for the second
     * placeholder parameter, the array containing it will be the second element in
     * the array returned by <code>getParams</code>.
     * <P>
     * Note that because the numbering of elements in an array starts at zero,
     * the array element that corresponds to placeholder parameter number
     * <i>parameterIndex</i> is element number <i>parameterIndex</i> -1.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x the <code>Object</code> containing the input parameter value;
     *        must be an <code>Object</code> type
     * @param targetSqlType the SQL type (as defined in <code>java.sql.Types</code>)
     *        to be sent to the database. If a non-standard <i>targetSqlType</i>
     *        is supplied, this method will not throw a <code>SQLException</code>.
     *        This allows implicit support for non-standard SQL types.
     * @throws SQLException if an error occurs or the parameter index
     *        is out of bounds
     * @see #getParams
     */
    public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {
        Object obj[];
        checkParamIndex(parameterIndex);

        obj = new Object[2];
        obj[0] = x;
        obj[1] = new Integer(targetSqlType);
        if (params == null){
             throw new SQLException("Set initParams() before setObject");
        }
        params.put(new Integer(parameterIndex - 1), obj);
    }

    /**
     * Sets the designated parameter to an <code>Object</code> in the Java
     * programming language. The second parameter must be an
     * <code>Object</code>
     * type.  For integral values, the <code>java.lang</code> equivalent
     * objects should be used. For example, use the class <code>Integer</code>
     * for an <code>int</code>.
     * <P>
     * The JDBC specification defines a standard mapping from
     * Java <code>Object</code> types to SQL types.  The driver will
     * use this standard mapping to  convert the given object
     * to its corresponding SQL type before sending it to the database.
     * If the object has a custom mapping (is of a class implementing
     * <code>SQLData</code>), the driver should call the method
     * <code>SQLData.writeSQL</code> to write the object to the SQL
     * data stream.
     * <P>
     * If, on the other hand, the object is of a class
     * implementing <code>Ref</code>, <code>Blob</code>, <code>Clob</code>,
     * <code>Struct</code>, or <code>Array</code>,
     * the driver should pass it to the database as a value of the
     * corresponding SQL type.
     * <P>
     * This method throws an exception if there
     * is an ambiguity, for example, if the object is of a class
     * implementing more than one interface.
     * <P>
     * Note that this method may be used to pass database-specific
     * abstract data types.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <p>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     * <P>
     * After this method has been called, a call to the
     * method <code>getParams</code>
     * will return an object array of the current command parameters, which will
     * include the <code>Object</code> set for placeholder parameter number
     * <code>parameterIndex</code>.
     * Note that because the numbering of elements in an array starts at zero,
     * the array element that corresponds to placeholder parameter number
     * <i>parameterIndex</i> is element number <i>parameterIndex</i> -1.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x the object containing the input parameter value
     * @throws SQLException if an error occurs the
     *                         parameter index is out of bounds, or there
     *                         is ambiguity in the implementation of the
     *                         object being set
     * @see #getParams
     */
    public void setObject(int parameterIndex, Object x) throws SQLException {
        checkParamIndex(parameterIndex);
        if (params == null) {
             throw new SQLException("Set initParams() before setObject");
        }
        params.put(new Integer(parameterIndex - 1), x);
    }

    /**
     * Sets the designated parameter to the given <code>Ref</code> object in
     * the Java programming language.  The driver converts this to an SQL
     * <code>REF</code> value when it sends it to the database. Internally, the
     * <code>Ref</code> is represented as a <code>SerialRef</code> to ensure
     * serializability.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <p>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     * <p>
     * After this method has been called, a call to the
     * method <code>getParams</code>
     * will return an object array of the current command parameters, which will
     * include the <code>Ref</code> object set for placeholder parameter number
     * <code>parameterIndex</code>.
     * Note that because the numbering of elements in an array starts at zero,
     * the array element that corresponds to placeholder parameter number
     * <i>parameterIndex</i> is element number <i>parameterIndex</i> -1.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param ref a <code>Ref</code> object representing an SQL <code>REF</code>
     *         value; cannot be null
     * @throws SQLException if an error occurs; the parameter index is out of
     *         bounds or the <code>Ref</code> object is <code>null</code>; or
     *         the <code>Ref</code> object returns a <code>null</code> base type
     *         name.
     * @see #getParams
     * @see javax.sql.rowset.serial.SerialRef
     */
    public void setRef (int parameterIndex, Ref ref) throws SQLException {
        checkParamIndex(parameterIndex);
        if (params == null) {
             throw new SQLException("Set initParams() before setRef");
        }
        params.put(new Integer(parameterIndex - 1), new SerialRef(ref));
    }

    /**
     * Sets the designated parameter to the given <code>Blob</code> object in
     * the Java programming language.  The driver converts this to an SQL
     * <code>BLOB</code> value when it sends it to the database. Internally,
     * the <code>Blob</code> is represented as a <code>SerialBlob</code>
     * to ensure serializability.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     * <p>
     * After this method has been called, a call to the
     * method <code>getParams</code>
     * will return an object array of the current command parameters, which will
     * include the <code>Blob</code> object set for placeholder parameter number
     * <code>parameterIndex</code>.
     * Note that because the numbering of elements in an array starts at zero,
     * the array element that corresponds to placeholder parameter number
     * <i>parameterIndex</i> is element number <i>parameterIndex</i> -1.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x a <code>Blob</code> object representing an SQL
     *          <code>BLOB</code> value
     * @throws SQLException if an error occurs or the
     *                         parameter index is out of bounds
     * @see #getParams
     * @see javax.sql.rowset.serial.SerialBlob
     */
    public void setBlob (int parameterIndex, Blob x) throws SQLException {
        checkParamIndex(parameterIndex);
        if(params == null){
             throw new SQLException("Set initParams() before setBlob");
        }
        params.put(new Integer(parameterIndex - 1), new SerialBlob(x));
    }

    /**
     * Sets the designated parameter to the given <code>Clob</code> object in
     * the Java programming language.  The driver converts this to an SQL
     * <code>CLOB</code> value when it sends it to the database. Internally, the
     * <code>Clob</code> is represented as a <code>SerialClob</code> to ensure
     * serializability.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <p>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     * <p>
     * After this method has been called, a call to the
     * method <code>getParams</code>
     * will return an object array of the current command parameters, which will
     * include the <code>Clob</code> object set for placeholder parameter number
     * <code>parameterIndex</code>.
     * Note that because the numbering of elements in an array starts at zero,
     * the array element that corresponds to placeholder parameter number
     * <i>parameterIndex</i> is element number <i>parameterIndex</i> -1.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *     in this <code>RowSet</code> object's command that is to be set.
     *     The first parameter is 1, the second is 2, and so on; must be
     *     <code>1</code> or greater
     * @param x a <code>Clob</code> object representing an SQL
     *     <code>CLOB</code> value; cannot be null
     * @throws SQLException if an error occurs; the parameter index is out of
     *     bounds or the <code>Clob</code> is null
     * @see #getParams
     * @see javax.sql.rowset.serial.SerialBlob
     */
    public void setClob (int parameterIndex, Clob x) throws SQLException {
        checkParamIndex(parameterIndex);
        if(params == null){
             throw new SQLException("Set initParams() before setClob");
        }
        params.put(new Integer(parameterIndex - 1), new SerialClob(x));
    }

    /**
     * Sets the designated parameter to an <code>Array</code> object in the
     * Java programming language.  The driver converts this to an SQL
     * <code>ARRAY</code> value when it sends it to the database. Internally,
     * the <code>Array</code> is represented as a <code>SerialArray</code>
     * to ensure serializability.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <P>
     * Note: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     * <p>
     * After this method has been called, a call to the
     * method <code>getParams</code>
     * will return an object array of the current command parameters, which will
     * include the <code>Array</code> object set for placeholder parameter number
     * <code>parameterIndex</code>.
     * Note that because the numbering of elements in an array starts at zero,
     * the array element that corresponds to placeholder parameter number
     * <i>parameterIndex</i> is element number <i>parameterIndex</i> -1.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param array an <code>Array</code> object representing an SQL
     *        <code>ARRAY</code> value; cannot be null. The <code>Array</code> object
     *        passed to this method must return a non-null Object for all
     *        <code>getArray()</code> method calls. A null value will cause a
     *        <code>SQLException</code> to be thrown.
     * @throws SQLException if an error occurs; the parameter index is out of
     *        bounds or the <code>ARRAY</code> is null
     * @see #getParams
     * @see javax.sql.rowset.serial.SerialArray
     */
    public void setArray (int parameterIndex, Array array) throws SQLException {
        checkParamIndex(parameterIndex);
        if (params == null){
             throw new SQLException("Set initParams() before setArray");
        }
        params.put(new Integer(parameterIndex - 1), new SerialArray(array));
    }

    /**
     * Sets the designated parameter to the given <code>java.sql.Date</code>
     * object.
     * When the DBMS does not store time zone information, the driver will use
     * the given <code>Calendar</code> object to construct the SQL <code>DATE</code>
     * value to send to the database. With a
     * <code>Calendar</code> object, the driver can calculate the date
     * taking into account a custom time zone.  If no <code>Calendar</code>
     * object is specified, the driver uses the time zone of the Virtual Machine
     * that is running the application.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <P>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     * <P>
     * Calls made to the method <code>getParams</code> after this version of
     * <code>setDate</code>
     * has been called will return an array containing the parameter values that
     * have been set.  In that array, the element that represents the values
     * set with this method will itself be an array. The first element of that array
     * is the given <code>java.sql.Date</code> object.
     * The second element is the value set for <i>cal</i>.
     * The parameter number is indicated by an element's position in the array
     * returned by the method <code>getParams</code>,
     * with the first element being the value for the first placeholder parameter, the
     * second element being the value for the second placeholder parameter, and so on.
     * In other words, if the date being set is the value for the second
     * placeholder parameter, the array containing it will be the second element in
     * the array returned by <code>getParams</code>.
     * <P>
     * Note that because the numbering of elements in an array starts at zero,
     * the array element that corresponds to placeholder parameter number
     * <i>parameterIndex</i> is <i>parameterIndex</i> -1.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x a <code>java.sql.Date</code> object representing an SQL
     *        <code>DATE</code> value
     * @param cal a <code>java.util.Calendar</code> object to use when
     *        when constructing the date
     * @throws SQLException if an error occurs or the
     *                         parameter index is out of bounds
     * @see #getParams
     */
    public void setDate(int parameterIndex, java.sql.Date x, Calendar cal) throws SQLException {
        Object date[];
        checkParamIndex(parameterIndex);

        date = new Object[2];
        date[0] = x;
        date[1] = cal;
        if(params == null){
             throw new SQLException("Set initParams() before setDate");
        }
        params.put(new Integer(parameterIndex - 1), date);
    }

    /**
     * Sets the designated parameter to the given <code>java.sql.Time</code>
     * object.  The driver converts this
     * to an SQL <code>TIME</code> value when it sends it to the database.
     * <P>
     * When the DBMS does not store time zone information, the driver will use
     * the given <code>Calendar</code> object to construct the SQL <code>TIME</code>
     * value to send to the database. With a
     * <code>Calendar</code> object, the driver can calculate the date
     * taking into account a custom time zone.  If no <code>Calendar</code>
     * object is specified, the driver uses the time zone of the Virtual Machine
     * that is running the application.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <P>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     * <P>
     * Calls made to the method <code>getParams</code> after this version of
     * <code>setTime</code>
     * has been called will return an array containing the parameter values that
     * have been set.  In that array, the element that represents the values
     * set with this method will itself be an array. The first element of that array
     * is the given <code>java.sql.Time</code> object.
     * The second element is the value set for <i>cal</i>.
     * The parameter number is indicated by an element's position in the array
     * returned by the method <code>getParams</code>,
     * with the first element being the value for the first placeholder parameter, the
     * second element being the value for the second placeholder parameter, and so on.
     * In other words, if the time being set is the value for the second
     * placeholder parameter, the array containing it will be the second element in
     * the array returned by <code>getParams</code>.
     * <P>
     * Note that because the numbering of elements in an array starts at zero,
     * the array element that corresponds to placeholder parameter number
     * <i>parameterIndex</i> is <i>parameterIndex</i> -1.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x a <code>java.sql.Time</code> object
     * @param cal the <code>java.util.Calendar</code> object the driver can use to
     *         construct the time
     * @throws SQLException if an error occurs or the
     *                         parameter index is out of bounds
     * @see #getParams
     */
    public void setTime(int parameterIndex, java.sql.Time x, Calendar cal) throws SQLException {
        Object time[];
        checkParamIndex(parameterIndex);

        time = new Object[2];
        time[0] = x;
        time[1] = cal;
        if(params == null){
             throw new SQLException("Set initParams() before setTime");
        }
        params.put(new Integer(parameterIndex - 1), time);
    }

    /**
     * Sets the designated parameter to the given
     * <code>java.sql.Timestamp</code> object.  The driver converts this
     * to an SQL <code>TIMESTAMP</code> value when it sends it to the database.
     * <P>
     * When the DBMS does not store time zone information, the driver will use
     * the given <code>Calendar</code> object to construct the SQL <code>TIMESTAMP</code>
     * value to send to the database. With a
     * <code>Calendar</code> object, the driver can calculate the timestamp
     * taking into account a custom time zone.  If no <code>Calendar</code>
     * object is specified, the driver uses the time zone of the Virtual Machine
     * that is running the application.
     * <P>
     * The parameter value set by this method is stored internally and
     * will be supplied as the appropriate parameter in this <code>RowSet</code>
     * object's command when the method <code>execute</code> is called.
     * Methods such as <code>execute</code> and <code>populate</code> must be
     * provided in any class that extends this class and implements one or
     * more of the standard JSR-114 <code>RowSet</code> interfaces.
     * <P>
     * NOTE: <code>JdbcRowSet</code> does not require the <code>populate</code> method
     * as it is undefined in this class.
     * <P>
     * Calls made to the method <code>getParams</code> after this version of
     * <code>setTimestamp</code>
     * has been called will return an array containing the parameter values that
     * have been set.  In that array, the element that represents the values
     * set with this method will itself be an array. The first element of that array
     * is the given <code>java.sql.Timestamp</code> object.
     * The second element is the value set for <i>cal</i>.
     * The parameter number is indicated by an element's position in the array
     * returned by the method <code>getParams</code>,
     * with the first element being the value for the first placeholder parameter, the
     * second element being the value for the second placeholder parameter, and so on.
     * In other words, if the timestamp being set is the value for the second
     * placeholder parameter, the array containing it will be the second element in
     * the array returned by <code>getParams</code>.
     * <P>
     * Note that because the numbering of elements in an array starts at zero,
     * the array element that corresponds to placeholder parameter number
     * <i>parameterIndex</i> is <i>parameterIndex</i> -1.
     *
     * @param parameterIndex the ordinal number of the placeholder parameter
     *        in this <code>RowSet</code> object's command that is to be set.
     *        The first parameter is 1, the second is 2, and so on; must be
     *        <code>1</code> or greater
     * @param x a <code>java.sql.Timestamp</code> object
     * @param cal the <code>java.util.Calendar</code> object the driver can use to
     *         construct the timestamp
     * @throws SQLException if an error occurs or the
     *                         parameter index is out of bounds
     * @see #getParams
     */
    public void setTimestamp(int parameterIndex, java.sql.Timestamp x, Calendar cal) throws SQLException {
        Object timestamp[];
        checkParamIndex(parameterIndex);

        timestamp = new Object[2];
        timestamp[0] = x;
        timestamp[1] = cal;
        if(params == null){
             throw new SQLException("Set initParams() before setTimestamp");
        }
        params.put(new Integer(parameterIndex - 1), timestamp);
    }

    /**
     * Clears all of the current parameter values in this <code>RowSet</code>
     * object's internal representation of the parameters to be set in
     * this <code>RowSet</code> object's command when it is executed.
     * <P>
     * In general, parameter values remain in force for repeated use in
     * this <code>RowSet</code> object's command. Setting a parameter value with the
     * setter methods automatically clears the value of the
     * designated parameter and replaces it with the new specified value.
     * <P>
     * This method is called internally by the <code>setCommand</code>
     * method to clear all of the parameters set for the previous command.
     * <P>
     * Furthermore, this method differs from the <code>initParams</code>
     * method in that it maintains the schema of the <code>RowSet</code> object.
     *
     * @throws SQLException if an error occurs clearing the parameters
     */
    public void clearParameters() throws SQLException {
        params.clear();
    }

    /**
     * Retrieves an array containing the parameter values (both Objects and
     * primitives) that have been set for this
     * <code>RowSet</code> object's command and throws an <code>SQLException</code> object
     * if all parameters have not been set.   Before the command is sent to the
     * DBMS to be executed, these parameters will be substituted
     * for placeholder parameters in the  <code>PreparedStatement</code> object
     * that is the command for a <code>RowSet</code> implementation extending
     * the <code>BaseRowSet</code> class.
     * <P>
     * Each element in the array that is returned is an <code>Object</code> instance
     * that contains the values of the parameters supplied to a setter method.
     * The order of the elements is determined by the value supplied for
     * <i>parameterIndex</i>.  If the setter method takes only the parameter index
     * and the value to be set (possibly null), the array element will contain the value to be set
     * (which will be expressed as an <code>Object</code>).  If there are additional
     * parameters, the array element will itself be an array containing the value to be set
     * plus any additional parameter values supplied to the setter method. If the method
     * sets a stream, the array element includes the type of stream being supplied to the
     * method. These additional parameters are for the use of the driver or the DBMS and may or
     * may not be used.
     * <P>
     * NOTE: Stored parameter values of types <code>Array</code>, <code>Blob</code>,
     * <code>Clob</code> and <code>Ref</code> are returned as <code>SerialArray</code>,
     * <code>SerialBlob</code>, <code>SerialClob</code> and <code>SerialRef</code>
     * respectively.
     *
     * @return an array of <code>Object</code> instances that includes the
     *         parameter values that may be set in this <code>RowSet</code> object's
     *         command; an empty array if no parameters have been set
     * @throws SQLException if an error occurs retrieveing the object array of
     *         parameters of this <code>RowSet</code> object or if not all parameters have
     *         been set
     */
    public Object[] getParams() throws SQLException {
        if (params == null) {

            initParams();
            Object [] paramsArray = new Object[params.size()];
            return paramsArray;

        } else {
            // The parameters may be set in random order
            // but all must be set, check to verify all
            // have been set till the last parameter
            // else throw exception.

            Object[] paramsArray = new Object[params.size()];
            for (int i = 0; i < params.size(); i++) {
               paramsArray[i] = params.get(new Integer(i));
               if (paramsArray[i] == null) {
                 throw new SQLException("missing parameter: " + (i + 1));
               } //end if
            } //end for
            return paramsArray;

        } //end if

    } //end getParams


 /**
    * Sets the designated parameter to SQL <code>NULL</code>.
    *
    * <P><B>Note:</B> You must specify the parameter's SQL type.
    *
    * @param parameterName the name of the parameter
    * @param sqlType the SQL type code defined in <code>java.sql.Types</code>
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @since 1.4
    */
   public void setNull(String parameterName, int sqlType) throws SQLException {
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
    * Sets the designated parameter to SQL <code>NULL</code>.
    * This version of the method <code>setNull</code> should
    * be used for user-defined types and REF type parameters.  Examples
    * of user-defined types include: STRUCT, DISTINCT, JAVA_OBJECT, and
    * named array types.
    *
    * <P><B>Note:</B> To be portable, applications must give the
    * SQL type code and the fully-qualified SQL type name when specifying
    * a NULL user-defined or REF parameter.  In the case of a user-defined type
    * the name is the type name of the parameter itself.  For a REF
    * parameter, the name is the type name of the referenced type.  If
    * a JDBC driver does not need the type code or type name information,
    * it may ignore it.
    *
    * Although it is intended for user-defined and Ref parameters,
    * this method may be used to set a null parameter of any JDBC type.
    * If the parameter does not have a user-defined or REF type, the given
    * typeName is ignored.
    *
    *
    * @param parameterName the name of the parameter
    * @param sqlType a value from <code>java.sql.Types</code>
    * @param typeName the fully-qualified name of an SQL user-defined type;
    *        ignored if the parameter is not a user-defined type or
    *        SQL <code>REF</code> value
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @since 1.4
    */
   public void setNull (String parameterName, int sqlType, String typeName)
       throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }



 /**
    * Sets the designated parameter to the given Java <code>boolean</code> value.
    * The driver converts this
    * to an SQL <code>BIT</code> or <code>BOOLEAN</code> value when it sends it to the database.
    *
    * @param parameterName the name of the parameter
    * @param x the parameter value
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @see #getBoolean
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @since 1.4
    */
   public void setBoolean(String parameterName, boolean x) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }



 /**
    * Sets the designated parameter to the given Java <code>byte</code> value.
    * The driver converts this
    * to an SQL <code>TINYINT</code> value when it sends it to the database.
    *
    * @param parameterName the name of the parameter
    * @param x the parameter value
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @see #getByte
    * @since 1.4
    */
   public void setByte(String parameterName, byte x) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }



 /**
    * Sets the designated parameter to the given Java <code>short</code> value.
    * The driver converts this
    * to an SQL <code>SMALLINT</code> value when it sends it to the database.
    *
    * @param parameterName the name of the parameter
    * @param x the parameter value
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @see #getShort
    * @since 1.4
    */
   public void setShort(String parameterName, short x) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
    * Sets the designated parameter to the given Java <code>int</code> value.
    * The driver converts this
    * to an SQL <code>INTEGER</code> value when it sends it to the database.
    *
    * @param parameterName the name of the parameter
    * @param x the parameter value
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @see #getInt
    * @since 1.4
    */
   public void setInt(String parameterName, int x) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
    * Sets the designated parameter to the given Java <code>long</code> value.
    * The driver converts this
    * to an SQL <code>BIGINT</code> value when it sends it to the database.
    *
    * @param parameterName the name of the parameter
    * @param x the parameter value
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @see #getLong
    * @since 1.4
    */
   public void setLong(String parameterName, long x) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
    * Sets the designated parameter to the given Java <code>float</code> value.
    * The driver converts this
    * to an SQL <code>FLOAT</code> value when it sends it to the database.
    *
    * @param parameterName the name of the parameter
    * @param x the parameter value
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @see #getFloat
    * @since 1.4
    */
   public void setFloat(String parameterName, float x) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
    * Sets the designated parameter to the given Java <code>double</code> value.
    * The driver converts this
    * to an SQL <code>DOUBLE</code> value when it sends it to the database.
    *
    * @param parameterName the name of the parameter
    * @param x the parameter value
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @see #getDouble
    * @since 1.4
    */
   public void setDouble(String parameterName, double x) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }



 /**
    * Sets the designated parameter to the given
    * <code>java.math.BigDecimal</code> value.
    * The driver converts this to an SQL <code>NUMERIC</code> value when
    * it sends it to the database.
    *
    * @param parameterName the name of the parameter
    * @param x the parameter value
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @see #getBigDecimal
    * @since 1.4
    */
   public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }



 /**
    * Sets the designated parameter to the given Java <code>String</code> value.
    * The driver converts this
    * to an SQL <code>VARCHAR</code> or <code>LONGVARCHAR</code> value
    * (depending on the argument's
    * size relative to the driver's limits on <code>VARCHAR</code> values)
    * when it sends it to the database.
    *
    * @param parameterName the name of the parameter
    * @param x the parameter value
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @see #getString
    * @since 1.4
    */
   public void setString(String parameterName, String x) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }



 /**
    * Sets the designated parameter to the given Java array of bytes.
    * The driver converts this to an SQL <code>VARBINARY</code> or
    * <code>LONGVARBINARY</code> (depending on the argument's size relative
    * to the driver's limits on <code>VARBINARY</code> values) when it sends
    * it to the database.
    *
    * @param parameterName the name of the parameter
    * @param x the parameter value
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @see #getBytes
    * @since 1.4
    */
   public void setBytes(String parameterName, byte x[]) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }



 /**
    * Sets the designated parameter to the given <code>java.sql.Timestamp</code> value.
    * The driver
    * converts this to an SQL <code>TIMESTAMP</code> value when it sends it to the
    * database.
    *
    * @param parameterName the name of the parameter
    * @param x the parameter value
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @see #getTimestamp
    * @since 1.4
    */
   public void setTimestamp(String parameterName, java.sql.Timestamp x)
       throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }



 /**
    * Sets the designated parameter to the given input stream, which will have
    * the specified number of bytes.
    * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
    * parameter, it may be more practical to send it via a
    * <code>java.io.InputStream</code>. Data will be read from the stream
    * as needed until end-of-file is reached.  The JDBC driver will
    * do any necessary conversion from ASCII to the database char format.
    *
    * <P><B>Note:</B> This stream object can either be a standard
    * Java stream object or your own subclass that implements the
    * standard interface.
    *
    * @param parameterName the name of the parameter
    * @param x the Java input stream that contains the ASCII parameter value
    * @param length the number of bytes in the stream
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @since 1.4
    */
   public void setAsciiStream(String parameterName, java.io.InputStream x, int length)
       throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
    * Sets the designated parameter to the given input stream, which will have
    * the specified number of bytes.
    * When a very large binary value is input to a <code>LONGVARBINARY</code>
    * parameter, it may be more practical to send it via a
    * <code>java.io.InputStream</code> object. The data will be read from the stream
    * as needed until end-of-file is reached.
    *
    * <P><B>Note:</B> This stream object can either be a standard
    * Java stream object or your own subclass that implements the
    * standard interface.
    *
    * @param parameterName the name of the parameter
    * @param x the java input stream which contains the binary parameter value
    * @param length the number of bytes in the stream
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @since 1.4
    */
   public void setBinaryStream(String parameterName, java.io.InputStream x,
                        int length) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


  /**
    * Sets the designated parameter to the given <code>Reader</code>
    * object, which is the given number of characters long.
    * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
    * parameter, it may be more practical to send it via a
    * <code>java.io.Reader</code> object. The data will be read from the stream
    * as needed until end-of-file is reached.  The JDBC driver will
    * do any necessary conversion from UNICODE to the database char format.
    *
    * <P><B>Note:</B> This stream object can either be a standard
    * Java stream object or your own subclass that implements the
    * standard interface.
    *
    * @param parameterName the name of the parameter
    * @param reader the <code>java.io.Reader</code> object that
    *        contains the UNICODE data used as the designated parameter
    * @param length the number of characters in the stream
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @since 1.4
    */
   public void setCharacterStream(String parameterName,
                           java.io.Reader reader,
                           int length) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


  /**
   * Sets the designated parameter to the given input stream.
   * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
   * parameter, it may be more practical to send it via a
   * <code>java.io.InputStream</code>. Data will be read from the stream
   * as needed until end-of-file is reached.  The JDBC driver will
   * do any necessary conversion from ASCII to the database char format.
   *
   * <P><B>Note:</B> This stream object can either be a standard
   * Java stream object or your own subclass that implements the
   * standard interface.
   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
   * it might be more efficient to use a version of
   * <code>setAsciiStream</code> which takes a length parameter.
   *
   * @param parameterName the name of the parameter
   * @param x the Java input stream that contains the ASCII parameter value
   * @exception SQLException if a database access error occurs or
   * this method is called on a closed <code>CallableStatement</code>
   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
     * @since 1.6
  */
  public void setAsciiStream(String parameterName, java.io.InputStream x)
          throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
    * Sets the designated parameter to the given input stream.
    * When a very large binary value is input to a <code>LONGVARBINARY</code>
    * parameter, it may be more practical to send it via a
    * <code>java.io.InputStream</code> object. The data will be read from the
    * stream as needed until end-of-file is reached.
    *
    * <P><B>Note:</B> This stream object can either be a standard
    * Java stream object or your own subclass that implements the
    * standard interface.
    * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
    * it might be more efficient to use a version of
    * <code>setBinaryStream</code> which takes a length parameter.
    *
    * @param parameterName the name of the parameter
    * @param x the java input stream which contains the binary parameter value
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
    * @since 1.6
    */
   public void setBinaryStream(String parameterName, java.io.InputStream x)
   throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }



 /**
    * Sets the designated parameter to the given <code>Reader</code>
    * object.
    * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
    * parameter, it may be more practical to send it via a
    * <code>java.io.Reader</code> object. The data will be read from the stream
    * as needed until end-of-file is reached.  The JDBC driver will
    * do any necessary conversion from UNICODE to the database char format.
    *
    * <P><B>Note:</B> This stream object can either be a standard
    * Java stream object or your own subclass that implements the
    * standard interface.
    * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
    * it might be more efficient to use a version of
    * <code>setCharacterStream</code> which takes a length parameter.
    *
    * @param parameterName the name of the parameter
    * @param reader the <code>java.io.Reader</code> object that contains the
    *        Unicode data
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
    * @since 1.6
    */
   public void setCharacterStream(String parameterName,
                         java.io.Reader reader) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
  * Sets the designated parameter in this <code>RowSet</code> object's command
  * to a <code>Reader</code> object. The
  * <code>Reader</code> reads the data till end-of-file is reached. The
  * driver does the necessary conversion from Java character format to
  * the national character set in the database.

  * <P><B>Note:</B> This stream object can either be a standard
  * Java stream object or your own subclass that implements the
  * standard interface.
  * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
  * it might be more efficient to use a version of
  * <code>setNCharacterStream</code> which takes a length parameter.
  *
  * @param parameterIndex of the first parameter is 1, the second is 2, ...
  * @param value the parameter value
  * @throws SQLException if the driver does not support national
  *         character sets;  if the driver can detect that a data conversion
  *  error could occur ; if a database access error occurs; or
  * this method is called on a closed <code>PreparedStatement</code>
  * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
  * @since 1.6
  */
  public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }



 /**
    * Sets the value of the designated parameter with the given object. The second
    * argument must be an object type; for integral values, the
    * <code>java.lang</code> equivalent objects should be used.
    *
    * <p>The given Java object will be converted to the given targetSqlType
    * before being sent to the database.
    *
    * If the object has a custom mapping (is of a class implementing the
    * interface <code>SQLData</code>),
    * the JDBC driver should call the method <code>SQLData.writeSQL</code> to write it
    * to the SQL data stream.
    * If, on the other hand, the object is of a class implementing
    * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>,  <code>NClob</code>,
    *  <code>Struct</code>, <code>java.net.URL</code>,
    * or <code>Array</code>, the driver should pass it to the database as a
    * value of the corresponding SQL type.
    * <P>
    * Note that this method may be used to pass datatabase-
    * specific abstract data types.
    *
    * @param parameterName the name of the parameter
    * @param x the object containing the input parameter value
    * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
    * sent to the database. The scale argument may further qualify this type.
    * @param scale for java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types,
    *          this is the number of digits after the decimal point.  For all other
    *          types, this value will be ignored.
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if <code>targetSqlType</code> is
    * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,
    * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,
    * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,
    *  <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
    * or  <code>STRUCT</code> data type and the JDBC driver does not support
    * this data type
    * @see Types
    * @see #getObject
    * @since 1.4
    */
   public void setObject(String parameterName, Object x, int targetSqlType, int scale)
       throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }



 /**
    * Sets the value of the designated parameter with the given object.
    * This method is like the method <code>setObject</code>
    * above, except that it assumes a scale of zero.
    *
    * @param parameterName the name of the parameter
    * @param x the object containing the input parameter value
    * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
    *                      sent to the database
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if <code>targetSqlType</code> is
    * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,
    * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,
    * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,
    *  <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
    * or  <code>STRUCT</code> data type and the JDBC driver does not support
    * this data type
    * @see #getObject
    * @since 1.4
    */
   public void setObject(String parameterName, Object x, int targetSqlType)
       throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
   * Sets the value of the designated parameter with the given object.
   * The second parameter must be of type <code>Object</code>; therefore, the
   * <code>java.lang</code> equivalent objects should be used for built-in types.
   *
   * <p>The JDBC specification specifies a standard mapping from
   * Java <code>Object</code> types to SQL types.  The given argument
   * will be converted to the corresponding SQL type before being
   * sent to the database.
   *
   * <p>Note that this method may be used to pass datatabase-
   * specific abstract data types, by using a driver-specific Java
   * type.
   *
   * If the object is of a class implementing the interface <code>SQLData</code>,
   * the JDBC driver should call the method <code>SQLData.writeSQL</code>
   * to write it to the SQL data stream.
   * If, on the other hand, the object is of a class implementing
   * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>,  <code>NClob</code>,
   *  <code>Struct</code>, <code>java.net.URL</code>,
   * or <code>Array</code>, the driver should pass it to the database as a
   * value of the corresponding SQL type.
   * <P>
   * This method throws an exception if there is an ambiguity, for example, if the
   * object is of a class implementing more than one of the interfaces named above.
   *
   * @param parameterName the name of the parameter
   * @param x the object containing the input parameter value
   * @exception SQLException if a database access error occurs,
   * this method is called on a closed <code>CallableStatement</code> or if the given
   *            <code>Object</code> parameter is ambiguous
   * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
   * this method
   * @see #getObject
   * @since 1.4
   */
  public void setObject(String parameterName, Object x) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }



 /**
    * Sets the designated parameter to a <code>InputStream</code> object.  The inputstream must contain  the number
    * of characters specified by length otherwise a <code>SQLException</code> will be
    * generated when the <code>PreparedStatement</code> is executed.
    * This method differs from the <code>setBinaryStream (int, InputStream, int)</code>
    * method because it informs the driver that the parameter value should be
    * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
    * the driver may have to do extra work to determine whether the parameter
    * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
    * @param parameterIndex index of the first parameter is 1,
    * the second is 2, ...
    * @param inputStream An object that contains the data to set the parameter
    * value to.
    * @param length the number of bytes in the parameter data.
    * @throws SQLException if a database access error occurs,
    * this method is called on a closed <code>PreparedStatement</code>,
    * if parameterIndex does not correspond
    * to a parameter marker in the SQL statement,  if the length specified
    * is less than zero or if the number of bytes in the inputstream does not match
    * the specfied length.
    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
    *
    * @since 1.6
    */
    public void setBlob(int parameterIndex, InputStream inputStream, long length)
       throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
    * Sets the designated parameter to a <code>InputStream</code> object.
    * This method differs from the <code>setBinaryStream (int, InputStream)</code>
    * method because it informs the driver that the parameter value should be
    * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
    * the driver may have to do extra work to determine whether the parameter
    * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
    *
    * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
    * it might be more efficient to use a version of
    * <code>setBlob</code> which takes a length parameter.
    *
    * @param parameterIndex index of the first parameter is 1,
    * the second is 2, ...
    * @param inputStream An object that contains the data to set the parameter
    * value to.
    * @throws SQLException if a database access error occurs,
    * this method is called on a closed <code>PreparedStatement</code> or
    * if parameterIndex does not correspond
    * to a parameter marker in the SQL statement,
    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
    *
    * @since 1.6
    */
    public void setBlob(int parameterIndex, InputStream inputStream)
       throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
    * Sets the designated parameter to a <code>InputStream</code> object.  The <code>inputstream</code> must contain  the number
     * of characters specified by length, otherwise a <code>SQLException</code> will be
     * generated when the <code>CallableStatement</code> is executed.
     * This method differs from the <code>setBinaryStream (int, InputStream, int)</code>
     * method because it informs the driver that the parameter value should be
     * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
     * the driver may have to do extra work to determine whether the parameter
     * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
     *
     * @param parameterName the name of the parameter to be set
     * the second is 2, ...
     *
     * @param inputStream An object that contains the data to set the parameter
     * value to.
     * @param length the number of bytes in the parameter data.
     * @throws SQLException  if parameterIndex does not correspond
     * to a parameter marker in the SQL statement,  or if the length specified
     * is less than zero; if the number of bytes in the inputstream does not match
     * the specfied length; if a database access error occurs or
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
     *
     * @since 1.6
     */
     public void setBlob(String parameterName, InputStream inputStream, long length)
        throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
    * Sets the designated parameter to the given <code>java.sql.Blob</code> object.
    * The driver converts this to an SQL <code>BLOB</code> value when it
    * sends it to the database.
    *
    * @param parameterName the name of the parameter
    * @param x a <code>Blob</code> object that maps an SQL <code>BLOB</code> value
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @since 1.6
    */
   public void setBlob (String parameterName, Blob x) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
    * Sets the designated parameter to a <code>InputStream</code> object.
    * This method differs from the <code>setBinaryStream (int, InputStream)</code>
    * method because it informs the driver that the parameter value should be
    * sent to the server as a <code>BLOB</code>.  When the <code>setBinaryStream</code> method is used,
    * the driver may have to do extra work to determine whether the parameter
    * data should be send to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
    *
    * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
    * it might be more efficient to use a version of
    * <code>setBlob</code> which takes a length parameter.
    *
    * @param parameterName the name of the parameter
    * @param inputStream An object that contains the data to set the parameter
    * value to.
    * @throws SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
    *
    * @since 1.6
    */
    public void setBlob(String parameterName, InputStream inputStream)
       throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
   * Sets the designated parameter to a <code>Reader</code> object.  The reader must contain  the number
   * of characters specified by length otherwise a <code>SQLException</code> will be
   * generated when the <code>PreparedStatement</code> is executed.
   *This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
   * because it informs the driver that the parameter value should be sent to
   * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
   * driver may have to do extra work to determine whether the parameter
   * data should be sent to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
   * @param parameterIndex index of the first parameter is 1, the second is 2, ...
   * @param reader An object that contains the data to set the parameter value to.
   * @param length the number of characters in the parameter data.
   * @throws SQLException if a database access error occurs, this method is called on
   * a closed <code>PreparedStatement</code>, if parameterIndex does not correspond to a parameter
   * marker in the SQL statement, or if the length specified is less than zero.
   *
   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
   * @since 1.6
   */
   public void setClob(int parameterIndex, Reader reader, long length)
     throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


/**
   * Sets the designated parameter to a <code>Reader</code> object.
   * This method differs from the <code>setCharacterStream (int, Reader)</code> method
   * because it informs the driver that the parameter value should be sent to
   * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
   * driver may have to do extra work to determine whether the parameter
   * data should be sent to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
   *
   * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
   * it might be more efficient to use a version of
   * <code>setClob</code> which takes a length parameter.
   *
   * @param parameterIndex index of the first parameter is 1, the second is 2, ...
   * @param reader An object that contains the data to set the parameter value to.
   * @throws SQLException if a database access error occurs, this method is called on
   * a closed <code>PreparedStatement</code>or if parameterIndex does not correspond to a parameter
   * marker in the SQL statement
   *
   * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
   * @since 1.6
   */
   public void setClob(int parameterIndex, Reader reader)
     throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
    * Sets the designated parameter to a <code>Reader</code> object.  The <code>reader</code> must contain  the number
               * of characters specified by length otherwise a <code>SQLException</code> will be
               * generated when the <code>CallableStatement</code> is executed.
              * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
              * because it informs the driver that the parameter value should be sent to
              * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
              * driver may have to do extra work to determine whether the parameter
              * data should be send to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
              * @param parameterName the name of the parameter to be set
              * @param reader An object that contains the data to set the parameter value to.
              * @param length the number of characters in the parameter data.
              * @throws SQLException if parameterIndex does not correspond to a parameter
              * marker in the SQL statement; if the length specified is less than zero;
              * a database access error occurs or
              * this method is called on a closed <code>CallableStatement</code>
              * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
              * this method
              *
              * @since 1.6
              */
              public void setClob(String parameterName, Reader reader, long length)
      throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


  /**
    * Sets the designated parameter to the given <code>java.sql.Clob</code> object.
    * The driver converts this to an SQL <code>CLOB</code> value when it
    * sends it to the database.
    *
    * @param parameterName the name of the parameter
    * @param x a <code>Clob</code> object that maps an SQL <code>CLOB</code> value
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @since 1.6
    */
   public void setClob (String parameterName, Clob x) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
    * Sets the designated parameter to a <code>Reader</code> object.
    * This method differs from the <code>setCharacterStream (int, Reader)</code> method
    * because it informs the driver that the parameter value should be sent to
    * the server as a <code>CLOB</code>.  When the <code>setCharacterStream</code> method is used, the
    * driver may have to do extra work to determine whether the parameter
    * data should be send to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
    *
    * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
    * it might be more efficient to use a version of
    * <code>setClob</code> which takes a length parameter.
    *
    * @param parameterName the name of the parameter
    * @param reader An object that contains the data to set the parameter value to.
    * @throws SQLException if a database access error occurs or this method is called on
    * a closed <code>CallableStatement</code>
    *
    * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
    * @since 1.6
    */
    public void setClob(String parameterName, Reader reader)
      throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
    * Sets the designated parameter to the given <code>java.sql.Date</code> value
    * using the default time zone of the virtual machine that is running
    * the application.
    * The driver converts this
    * to an SQL <code>DATE</code> value when it sends it to the database.
    *
    * @param parameterName the name of the parameter
    * @param x the parameter value
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @see #getDate
    * @since 1.4
    */
   public void setDate(String parameterName, java.sql.Date x)
       throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
    * Sets the designated parameter to the given <code>java.sql.Date</code> value,
    * using the given <code>Calendar</code> object.  The driver uses
    * the <code>Calendar</code> object to construct an SQL <code>DATE</code> value,
    * which the driver then sends to the database.  With a
    * a <code>Calendar</code> object, the driver can calculate the date
    * taking into account a custom timezone.  If no
    * <code>Calendar</code> object is specified, the driver uses the default
    * timezone, which is that of the virtual machine running the application.
    *
    * @param parameterName the name of the parameter
    * @param x the parameter value
    * @param cal the <code>Calendar</code> object the driver will use
    *            to construct the date
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @see #getDate
    * @since 1.4
    */
   public void setDate(String parameterName, java.sql.Date x, Calendar cal)
       throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
    * Sets the designated parameter to the given <code>java.sql.Time</code> value.
    * The driver converts this
    * to an SQL <code>TIME</code> value when it sends it to the database.
    *
    * @param parameterName the name of the parameter
    * @param x the parameter value
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @see #getTime
    * @since 1.4
    */
   public void setTime(String parameterName, java.sql.Time x)
       throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
    * Sets the designated parameter to the given <code>java.sql.Time</code> value,
    * using the given <code>Calendar</code> object.  The driver uses
    * the <code>Calendar</code> object to construct an SQL <code>TIME</code> value,
    * which the driver then sends to the database.  With a
    * a <code>Calendar</code> object, the driver can calculate the time
    * taking into account a custom timezone.  If no
    * <code>Calendar</code> object is specified, the driver uses the default
    * timezone, which is that of the virtual machine running the application.
    *
    * @param parameterName the name of the parameter
    * @param x the parameter value
    * @param cal the <code>Calendar</code> object the driver will use
    *            to construct the time
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @see #getTime
    * @since 1.4
    */
   public void setTime(String parameterName, java.sql.Time x, Calendar cal)
       throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
    * Sets the designated parameter to the given <code>java.sql.Timestamp</code> value,
    * using the given <code>Calendar</code> object.  The driver uses
    * the <code>Calendar</code> object to construct an SQL <code>TIMESTAMP</code> value,
    * which the driver then sends to the database.  With a
    * a <code>Calendar</code> object, the driver can calculate the timestamp
    * taking into account a custom timezone.  If no
    * <code>Calendar</code> object is specified, the driver uses the default
    * timezone, which is that of the virtual machine running the application.
    *
    * @param parameterName the name of the parameter
    * @param x the parameter value
    * @param cal the <code>Calendar</code> object the driver will use
    *            to construct the timestamp
    * @exception SQLException if a database access error occurs or
    * this method is called on a closed <code>CallableStatement</code>
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @see #getTimestamp
    * @since 1.4
    */
   public void setTimestamp(String parameterName, java.sql.Timestamp x, Calendar cal)
       throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
   * Sets the designated parameter to the given <code>java.sql.SQLXML</code> object. The driver converts this to an
    * SQL <code>XML</code> value when it sends it to the database.
    * @param parameterIndex index of the first parameter is 1, the second is 2, ...
    * @param xmlObject a <code>SQLXML</code> object that maps an SQL <code>XML</code> value
    * @throws SQLException if a database access error occurs, this method
    *  is called on a closed result set,
    * the <code>java.xml.transform.Result</code>,
    *  <code>Writer</code> or <code>OutputStream</code> has not been closed
    * for the <code>SQLXML</code> object  or
    *  if there is an error processing the XML value.  The <code>getCause</code> method
    *  of the exception may provide a more detailed exception, for example, if the
    *  stream does not contain valid XML.
    * @since 1.6
    */
   public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


  /**
   * Sets the designated parameter to the given <code>java.sql.SQLXML</code> object. The driver converts this to an
    * <code>SQL XML</code> value when it sends it to the database.
    * @param parameterName the name of the parameter
    * @param xmlObject a <code>SQLXML</code> object that maps an <code>SQL XML</code> value
    * @throws SQLException if a database access error occurs, this method
    *  is called on a closed result set,
    * the <code>java.xml.transform.Result</code>,
    *  <code>Writer</code> or <code>OutputStream</code> has not been closed
    * for the <code>SQLXML</code> object  or
    *  if there is an error processing the XML value.  The <code>getCause</code> method
    *  of the exception may provide a more detailed exception, for example, if the
    *  stream does not contain valid XML.
    * @since 1.6
    */
   public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
  * Sets the designated parameter to the given <code>java.sql.RowId</code> object. The
  * driver converts this to a SQL <code>ROWID</code> value when it sends it
  * to the database
  *
  * @param parameterIndex the first parameter is 1, the second is 2, ...
  * @param x the parameter value
  * @throws SQLException if a database access error occurs
  *
  * @since 1.6
  */
 public void setRowId(int parameterIndex, RowId x) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
 * Sets the designated parameter to the given <code>java.sql.RowId</code> object. The
 * driver converts this to a SQL <code>ROWID</code> when it sends it to the
 * database.
 *
 * @param parameterName the name of the parameter
 * @param x the parameter value
 * @throws SQLException if a database access error occurs
 * @since 1.6
 */
 public void setRowId(String parameterName, RowId x) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }

 /**
  * Sets the designated paramter to the given <code>String</code> object.
  * The driver converts this to a SQL <code>NCHAR</code> or
  * <code>NVARCHAR</code> or <code>LONGNVARCHAR</code> value
  * (depending on the argument's
  * size relative to the driver's limits on <code>NVARCHAR</code> values)
  * when it sends it to the database.
  *
  * @param parameterIndex of the first parameter is 1, the second is 2, ...
  * @param value the parameter value
  * @throws SQLException if the driver does not support national
  *         character sets;  if the driver can detect that a data conversion
  *  error could occur ; or if a database access error occurs
  * @since 1.6
  */
  public void setNString(int parameterIndex, String value) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
  * Sets the designated paramter to the given <code>String</code> object.
  * The driver converts this to a SQL <code>NCHAR</code> or
  * <code>NVARCHAR</code> or <code>LONGNVARCHAR</code>
  * @param parameterName the name of the column to be set
  * @param value the parameter value
  * @throws SQLException if the driver does not support national
  *         character sets;  if the driver can detect that a data conversion
  *  error could occur; or if a database access error occurs
  * @since 1.6
  */
 public void setNString(String parameterName, String value)
         throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
  * Sets the designated parameter to a <code>Reader</code> object. The
  * <code>Reader</code> reads the data till end-of-file is reached. The
  * driver does the necessary conversion from Java character format to
  * the national character set in the database.
  * @param parameterIndex of the first parameter is 1, the second is 2, ...
  * @param value the parameter value
  * @param length the number of characters in the parameter data.
  * @throws SQLException if the driver does not support national
  *         character sets;  if the driver can detect that a data conversion
  *  error could occur ; or if a database access error occurs
  * @since 1.6
  */
  public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
  * Sets the designated parameter to a <code>Reader</code> object. The
  * <code>Reader</code> reads the data till end-of-file is reached. The
  * driver does the necessary conversion from Java character format to
  * the national character set in the database.
  * @param parameterName the name of the column to be set
  * @param value the parameter value
  * @param length the number of characters in the parameter data.
  * @throws SQLException if the driver does not support national
  *         character sets;  if the driver can detect that a data conversion
  *  error could occur; or if a database access error occurs
  * @since 1.6
  */
 public void setNCharacterStream(String parameterName, Reader value, long length)
         throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
  * Sets the designated parameter to a <code>Reader</code> object. The
  * <code>Reader</code> reads the data till end-of-file is reached. The
  * driver does the necessary conversion from Java character format to
  * the national character set in the database.

  * <P><B>Note:</B> This stream object can either be a standard
  * Java stream object or your own subclass that implements the
  * standard interface.
  * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
  * it might be more efficient to use a version of
  * <code>setNCharacterStream</code> which takes a length parameter.
  *
  * @param parameterName the name of the parameter
  * @param value the parameter value
  * @throws SQLException if the driver does not support national
  *         character sets;  if the driver can detect that a data conversion
  *  error could occur ; if a database access error occurs; or
  * this method is called on a closed <code>CallableStatement</code>
  * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
  * @since 1.6
  */
  public void setNCharacterStream(String parameterName, Reader value) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
 * Sets the designated parameter to a <code>java.sql.NClob</code> object. The object
 * implements the <code>java.sql.NClob</code> interface. This <code>NClob</code>
 * object maps to a SQL <code>NCLOB</code>.
 * @param parameterName the name of the column to be set
 * @param value the parameter value
 * @throws SQLException if the driver does not support national
 *         character sets;  if the driver can detect that a data conversion
 *  error could occur; or if a database access error occurs
 * @since 1.6
 */
 public void setNClob(String parameterName, NClob value) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
  * Sets the designated parameter to a <code>Reader</code> object.  The <code>reader</code> must contain    * the number
             * of characters specified by length otherwise a <code>SQLException</code> will be
            * generated when the <code>CallableStatement</code> is executed.
            * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
            * because it informs the driver that the parameter value should be sent to
            * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
            * driver may have to do extra work to determine whether the parameter
            * data should be send to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
            *
            * @param parameterName the name of the parameter to be set
            * @param reader An object that contains the data to set the parameter value to.
            * @param length the number of characters in the parameter data.
            * @throws SQLException if parameterIndex does not correspond to a parameter
            * marker in the SQL statement; if the length specified is less than zero;
            * if the driver does not support national
            *         character sets;  if the driver can detect that a data conversion
            *  error could occur; if a database access error occurs or
            * this method is called on a closed <code>CallableStatement</code>
            * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
            * this method
            * @since 1.6
            */
            public void setNClob(String parameterName, Reader reader, long length)
    throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
  * Sets the designated parameter to a <code>Reader</code> object.
  * This method differs from the <code>setCharacterStream (int, Reader)</code> method
  * because it informs the driver that the parameter value should be sent to
  * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
  * driver may have to do extra work to determine whether the parameter
  * data should be send to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
  * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
  * it might be more efficient to use a version of
  * <code>setNClob</code> which takes a length parameter.
  *
  * @param parameterName the name of the parameter
  * @param reader An object that contains the data to set the parameter value to.
  * @throws SQLException if the driver does not support national character sets;
  * if the driver can detect that a data conversion
  *  error could occur;  if a database access error occurs or
  * this method is called on a closed <code>CallableStatement</code>
  * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
  *
  * @since 1.6
  */
  public void setNClob(String parameterName, Reader reader)
    throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


    /**
     * Sets the designated parameter to a <code>Reader</code> object.  The reader must contain  the number
     * of characters specified by length otherwise a <code>SQLException</code> will be
     * generated when the <code>PreparedStatement</code> is executed.
     * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
     * because it informs the driver that the parameter value should be sent to
     * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
     * driver may have to do extra work to determine whether the parameter
     * data should be sent to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
     * @param parameterIndex index of the first parameter is 1, the second is 2, ...
     * @param reader An object that contains the data to set the parameter value to.
     * @param length the number of characters in the parameter data.
     * @throws SQLException if parameterIndex does not correspond to a parameter
     * marker in the SQL statement; if the length specified is less than zero;
     * if the driver does not support national character sets;
     * if the driver can detect that a data conversion
     *  error could occur;  if a database access error occurs or
     * this method is called on a closed <code>PreparedStatement</code>
     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
     *
     * @since 1.6
     */
     public void setNClob(int parameterIndex, Reader reader, long length)
       throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


    /**
     * Sets the designated parameter to a <code>java.sql.NClob</code> object. The driver converts this oa
     * SQL <code>NCLOB</code> value when it sends it to the database.
     * @param parameterIndex of the first parameter is 1, the second is 2, ...
     * @param value the parameter value
     * @throws SQLException if the driver does not support national
     *         character sets;  if the driver can detect that a data conversion
     *  error could occur ; or if a database access error occurs
     * @since 1.6
     */
     public void setNClob(int parameterIndex, NClob value) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
  * Sets the designated parameter to a <code>Reader</code> object.
  * This method differs from the <code>setCharacterStream (int, Reader)</code> method
  * because it informs the driver that the parameter value should be sent to
  * the server as a <code>NCLOB</code>.  When the <code>setCharacterStream</code> method is used, the
  * driver may have to do extra work to determine whether the parameter
  * data should be sent to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
  * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
  * it might be more efficient to use a version of
  * <code>setNClob</code> which takes a length parameter.
  *
  * @param parameterIndex index of the first parameter is 1, the second is 2, ...
  * @param reader An object that contains the data to set the parameter value to.
  * @throws SQLException if parameterIndex does not correspond to a parameter
  * marker in the SQL statement;
  * if the driver does not support national character sets;
  * if the driver can detect that a data conversion
  *  error could occur;  if a database access error occurs or
  * this method is called on a closed <code>PreparedStatement</code>
  * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
  *
  * @since 1.6
  */
  public void setNClob(int parameterIndex, Reader reader)
    throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }


 /**
  * Sets the designated parameter to the given <code>java.net.URL</code> value.
  * The driver converts this to an SQL <code>DATALINK</code> value
  * when it sends it to the database.
  *
  * @param parameterIndex the first parameter is 1, the second is 2, ...
  * @param x the <code>java.net.URL</code> object to be set
  * @exception SQLException if a database access error occurs or
  * this method is called on a closed <code>PreparedStatement</code>
  * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
  * @since 1.4
  */
  public void setURL(int parameterIndex, java.net.URL x) throws SQLException{
        throw new SQLFeatureNotSupportedException("Feature not supported");
   }



    static final long serialVersionUID = 4886719666485113312L;

} //end class
