package ModSQL;
import java.math.BigDecimal;
import java.util.Calendar;
import java.sql.*;
import java.io.*;

/* $Id: PreparedStatement.java,v 1.12 2003/05/29 07:55:43 cvs Exp $
 *
 * Copyright (c) 2003 Chris Studholme <chris.studholme@utoronto.ca>
 *
 * May be copied or modified under the terms of the GNU General Public
 * License.  See COPYING for more information.
 */

/**
 * An object that represents a precompiled SQL statement.  Objects of this
 * class can also be used as {@link Statement} objects.
 *
 * @see Connection#prepareStatement
 * @see ResultSet
 * @author chris.studholme@utoronto.ca
 */
public class PreparedStatement implements java.sql.PreparedStatement {

  /** DatabaseManager to use when looking up table names. */
  private DatabaseManager tablemanager;

  /** Connection that created this statement. */
  private Connection connection;

  /** Current prepared query. */
  protected Query query=null;

  /** Update count that resulted from executing the query. */
  protected int updatecount=-1;

  /**
   * Setup an empty statement.
   *
   * @param tablemanager manager to use when looking up tables
   * @param connection connection that created this statement
   */
  public PreparedStatement(DatabaseManager tablemanager, 
			   Connection connection) {
    this.tablemanager = tablemanager;
    this.connection = connection;
  }
  /**
   * Create a prepared statement and parse the query provided.
   *
   * @param tablemanager manager to use when looking up tables
   * @param connection connection that created this statement
   * @param sql query to prepare
   * @throws SQLException if an error occurs
   */
  public PreparedStatement(DatabaseManager tablemanager, 
			   Connection connection, String sql) 
    throws SQLException {
    this.tablemanager = tablemanager;
    this.connection = connection;
    parseQuery(sql);
  }

  /**
   * Close and delete any SQL statement currently prepared.
   *
   * @throws SQLException if an error occurs
   */
  private void ResetStatement() throws SQLException {
    if (query!=null) {
      query.close();
      query=null;
    }
    updatecount=-1;
  }

  /**
   * In many cases, it is desirable to immediately release a
   * Statements's database and JDBC resources instead of waiting for
   * this to happen when it is automatically closed; the close
   * method provides this immediate release.
   *
   * <P><B>Note:</B> A Statement is automatically closed when it is
   * garbage collected. When a Statement is closed, its current
   * ResultSet, if one exists, is also closed.  
   *
   * @throws SQLException if a database-access error occurs.
   */
  public void close() throws SQLException {
    ResetStatement();
    tablemanager=null;
    connection=null;
  }

  /**
   * Parse a SQL query.
   *
   * @param sql queyr to parse
   * @throws SQLException if an error occurs
   */
  private void parseQuery(String sql) throws SQLException {
    StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(sql));
    tokenizer.resetSyntax();
    tokenizer.whitespaceChars(0,' ');
    tokenizer.ordinaryChar('!');
    tokenizer.quoteChar('"');
    tokenizer.ordinaryChar('#');
    tokenizer.ordinaryChar('$');
    tokenizer.ordinaryChar('%');
    tokenizer.ordinaryChar('&');
    tokenizer.quoteChar('\'');
    tokenizer.ordinaryChar('(');
    tokenizer.ordinaryChar(')');
    tokenizer.ordinaryChar('*');
    tokenizer.ordinaryChar('+');
    tokenizer.ordinaryChar(',');
    tokenizer.ordinaryChar('-');
    tokenizer.wordChars('.','.');
    tokenizer.ordinaryChar('/');
    tokenizer.wordChars('0','9');
    tokenizer.ordinaryChar(':');
    tokenizer.ordinaryChar(';');
    tokenizer.ordinaryChar('<');
    tokenizer.ordinaryChar('=');
    tokenizer.ordinaryChar('>');
    tokenizer.wordChars('?','?');
    tokenizer.ordinaryChar('@');
    tokenizer.wordChars('A','Z');
    tokenizer.ordinaryChar('[');
    tokenizer.ordinaryChar('\\');
    tokenizer.ordinaryChar(']');
    tokenizer.ordinaryChar('^');
    tokenizer.wordChars('_','_');
    tokenizer.ordinaryChar('`');
    tokenizer.wordChars('a','z');
    tokenizer.ordinaryChar('{');
    tokenizer.ordinaryChar('|');
    tokenizer.ordinaryChar('}');
    tokenizer.ordinaryChar('~');
    tokenizer.ordinaryChar(127);
    tokenizer.wordChars(128,255);
    tokenizer.eolIsSignificant(false);
    tokenizer.lowerCaseMode(true);
      
    ResetStatement();

    try {
      if (tokenizer.nextToken()!=StreamTokenizer.TT_WORD)
	throw new SQLException("query expected at or before "+tokenizer);

      if (tokenizer.sval.equals("select"))
	query = new Select(tokenizer,tablemanager);
      else if (tokenizer.sval.equals("update")) 
	query = new Update(tokenizer,tablemanager);
      else if (tokenizer.sval.equals("insert")) 
	query = new Insert(tokenizer,tablemanager);
      else if (tokenizer.sval.equals("delete")) 
	query = new Delete(tokenizer,tablemanager);
      else if (tokenizer.sval.equals("create")) 
	query = new Create(tokenizer,tablemanager);
      else if (tokenizer.sval.equals("drop")) 
	query = new Drop(tokenizer,tablemanager);
      else 
	throw new SQLException("unrecognized SQL command '"+
			       tokenizer.sval+"'");

      if (tokenizer.ttype!=StreamTokenizer.TT_EOF && tokenizer.ttype!=';')
	throw new SQLException("';' expected at or before "+tokenizer);
      
      if (DriverConfig.debugLevel>0)
	System.err.println("ModSQL.PreparedStatement: "+query.toString(false));

      query.optimize();
    }
    catch (Exception e) {
      if (e instanceof SQLException)
	throw (SQLException)e;
      e.printStackTrace();
      throw new SQLExceptionWithCause("unknown error",e);
    }
  }

  /**
   * Execute a SQL statement that returns a single ResultSet.
   *
   * @param sql typically this is a static SQL SELECT statement
   * @return a ResultSet that contains the data produced by the
   * query; never null 
   * @throws SQLException if a database-access error occurs.
   */
  public java.sql.ResultSet executeQuery(String sql) throws SQLException {
    if (execute(sql))
      return getResultSet();
    throw new SQLException("no ResultSet from executeQuery");
  }

  /**
   * Execute a SQL INSERT, UPDATE or DELETE statement. In addition,
   * SQL statements that return nothing such as SQL DDL statements
   * can be executed.
   *
   * @param sql a SQL INSERT, UPDATE or DELETE statement or a SQL
   * statement that returns nothing
   * @return either the row count for INSERT, UPDATE or DELETE or 0
   * for SQL statements that return nothing
   * @throws SQLException if a database-access error occurs.
   */
  public int executeUpdate(String sql) throws SQLException {
    if (execute(sql)==false) {
      int result=getUpdateCount();
      return result!=-1 ? result : 0;
    }
    throw new SQLException("ResultSet returned in executeUpdate");
  }

  /**
   * Execute a SQL statement that may return multiple results.
   * Under some (uncommon) situations a single SQL statement may return
   * multiple result sets and/or update counts.  Normally you can ignore
   * this, unless you're executing a stored procedure that you know may
   * return multiple results, or unless you're dynamically executing an
   * unknown SQL string.  The "execute", "getMoreResults", "getResultSet"
   * and "getUpdateCount" methods let you navigate through multiple results.
   *
   * The "execute" method executes a SQL statement and indicates the
   * form of the first result.  You can then use getResultSet or
   * getUpdateCount to retrieve the result, and getMoreResults to
   * move to any subsequent result(s).
   *
   * @param sql any SQL statement
   * @return true if the next result is a ResultSet; false if it is
   * an update count or there are no more results
   * @throws SQLException if a database-access error occurs.
   * @see #getResultSet
   * @see #getUpdateCount
   * @see #getMoreResults 
   */
  public boolean execute(String sql) throws SQLException {
    parseQuery(sql);
    updatecount = query.execute();
    return updatecount==-1;
  }


  /**
   * Executes the SQL query in this <code>PreparedStatement</code> object
   * and returns the result set generated by the query.
   *
   * @return a <code>ResultSet</code> object that contains the data produced by the
   * query; never <code>null</code>
   * @throws SQLException if a database access error occurs
   */
  public java.sql.ResultSet executeQuery() throws SQLException {
    if (execute())
      return getResultSet();
    throw new SQLException("no ResultSet from executeQuery");
  }

  /**
   * Executes the SQL INSERT, UPDATE or DELETE statement
   * in this <code>PreparedStatement</code> object.
   * In addition,
   * SQL statements that return nothing, such as SQL DDL statements,
   * can be executed.
   *
   * @return either the row count for INSERT, UPDATE or DELETE statements;
   * or 0 for SQL statements that return nothing
   * @throws SQLException if a database access error occurs
   */
  public int executeUpdate() throws SQLException {
    if (execute()==false) {
      int result=getUpdateCount();
      return result!=-1 ? result : 0;
    }
    throw new SQLException("ResultSet returned in executeUpdate");
  }


  /**
   * Executes any kind of SQL statement.
   * Some prepared statements return multiple results; the <code>execute</code>
   * method handles these complex statements as well as the simpler
   * form of statements handled by the methods <code>executeQuery</code>
   * and <code>executeUpdate</code>.
   *
   * @throws SQLException if a database access error occurs
   */
  public boolean execute() throws SQLException {
    if (query==null)
      throw new SQLException("no query prepared");
    updatecount = query.execute();
    return updatecount==-1;
  }

	
  /**
   *  getResultSet returns the current result as a ResultSet.  It
   *  should only be called once per result.
   *
   * @return the current result as a ResultSet; null if the result
   * is an update count or there are no more results
   * @throws SQLException if a database-access error occurs.
   * @see #execute 
   */
  public java.sql.ResultSet getResultSet() throws SQLException {
    return query instanceof Select ? 
      new ResultSet((Select)query,this) : null;
  }


  /**
   * Gets the number, types and properties of a <code>ResultSet</code>
   * object's columns.
   *
   * @return the description of a <code>ResultSet</code> object's columns
   * @throws SQLException if a database access error occurs
   */
  public java.sql.ResultSetMetaData getMetaData() throws SQLException {
    return query instanceof Select ? 
      new ResultSetMetaData((Select)query) : null;
  }


  /**
   *  getUpdateCount returns the current result as an update count;
   *  if the result is a ResultSet or there are no more results, -1
   *  is returned.  It should only be called once per result.
   * 
   * @return the current result as an update count; -1 if it is a
   * ResultSet or there are no more results
   * @throws SQLException if a database-access error occurs.
   * @see #execute 
   */
  public int getUpdateCount() throws SQLException {
    return updatecount;
  }

  /**
   * getMoreResults moves to a Statement's next result.  It returns true if 
   * this result is a ResultSet.  getMoreResults also implicitly
   * closes any current ResultSet obtained with getResultSet.
   *
   * There are no more results when (!getMoreResults() &&
   * (getUpdateCount() == -1)
   *
   * @return true if the next result is a ResultSet; false if it is
   * an update count or there are no more results
   * @throws SQLException if a database-access error occurs.
   * @see #execute 
   */
  public boolean getMoreResults() throws SQLException {
    return false;
  }

  /**
   * The maxFieldSize limit (in bytes) is the maximum amount of data
   * returned for any column value; it only applies to BINARY,
   * VARBINARY, LONGVARBINARY, CHAR, VARCHAR, and LONGVARCHAR
   * columns.  If the limit is exceeded, the excess data is silently
   * discarded.
   *
   * @return the current max column size limit; zero means unlimited 
   * @throws SQLException if a database-access error occurs.
   */
  public int getMaxFieldSize() throws SQLException {
    return 0;
  }
    
  /**
   * The maxFieldSize limit (in bytes) is set to limit the size of
   * data that can be returned for any column value; it only applies
   * to BINARY, VARBINARY, LONGVARBINARY, CHAR, VARCHAR, and
   * LONGVARCHAR fields.  If the limit is exceeded, the excess data
   * is silently discarded. For maximum portability use values
   * greater than 256.
   *
   * @param max the new max column size limit; zero means unlimited 
   * @throws SQLException if a database-access error occurs.
   */
  public void setMaxFieldSize(int max) throws SQLException {
    throw new SQLException("not implemented");
  }

  /**
   * The maxRows limit is the maximum number of rows that a
   * ResultSet can contain.  If the limit is exceeded, the excess
   * rows are silently dropped.
   *
   * @return the current max row limit; zero means unlimited
   * @throws SQLException if a database-access error occurs.
   */
  public int getMaxRows() throws SQLException {
    return 0;
  }

  /**
   * The maxRows limit is set to limit the number of rows that any
   * ResultSet can contain.  If the limit is exceeded, the excess
   * rows are silently dropped.
   *
   * @param max the new max rows limit; zero means unlimited 
   * @throws SQLException if a database-access error occurs.
   */
  public void setMaxRows(int max) throws SQLException {
    throw new SQLException("not implemented");
  }

  /**
   * If escape scanning is on (the default), the driver will do
   * escape substitution before sending the SQL to the database.
   *
   * Note: Since prepared statements have usually been parsed prior
   * to making this call, disabling escape processing for prepared
   * statements will like have no affect.
   *
   * @param enable true to enable; false to disable
   * @throws SQLException if a database-access error occurs.
   */
  public void setEscapeProcessing(boolean enable) throws SQLException {
  }

  /**
   * The queryTimeout limit is the number of seconds the driver will
   * wait for a Statement to execute. If the limit is exceeded, a
   * SQLException is thrown.
   *
   * @return the current query timeout limit in seconds; zero means unlimited 
   * @throws SQLException if a database-access error occurs.
   */
  public int getQueryTimeout() throws SQLException {
    return 0;
  }

  /**
   * The queryTimeout limit is the number of seconds the driver will
   * wait for a Statement to execute. If the limit is exceeded, a
   * SQLException is thrown.
   *
   * @param seconds the new query timeout limit in seconds; zero means 
   * unlimited 
   * @throws SQLException if a database-access error occurs.
   */
  public void setQueryTimeout(int seconds) throws SQLException {
    throw new SQLException("not implemented");
  }

  /**
   * Cancel can be used by one thread to cancel a statement that
   * is being executed by another thread.
   *
   * @throws SQLException if a database-access error occurs.
   */
  public void cancel() throws SQLException {
    throw new SQLException("not implemented");
  }

  /**
   * The first warning reported by calls on this Statement is
   * returned.  A Statment's execute methods clear its SQLWarning
   * chain. Subsequent Statement warnings will be chained to this
   * SQLWarning.
   *
   * <p>The warning chain is automatically cleared each time
   * a statement is (re)executed.
   *
   * <P><B>Note:</B> If you are processing a ResultSet then any
   * warnings associated with ResultSet reads will be chained on the
   * ResultSet object.
   *
   * @return the first SQLWarning or null 
   * @throws SQLException if a database-access error occurs.
   */
  public SQLWarning getWarnings() throws SQLException {
    return null;
  }

  /**
   * After this call, getWarnings returns null until a new warning is
   * reported for this Statement.  
   *
   * @throws SQLException if a database-access error occurs.
   */
  public void clearWarnings() throws SQLException {
  }

  /**
   * setCursorname defines the SQL cursor name that will be used by
   * subsequent Statement execute methods. This name can then be
   * used in SQL positioned update/delete statements to identify the
   * current row in the ResultSet generated by this statement.  If
   * the database doesn't support positioned update/delete, this
   * method is a noop.  To insure that a cursor has the proper isolation
   * level to support update, the cursor's select statement should be
   * of the form 'select for update ...'. If the 'for update' clause is 
   * omitted the positioned updates may fail.
   *
   * <P><B>Note:</B> By definition, positioned update/delete
   * execution must be done by a different Statement than the one
   * which generated the ResultSet being used for positioning. Also,
   * cursor names must be unique within a Connection.
   *
   * @param name the new cursor name.  
   * @throws SQLException if a database-access error occurs.
   */
  public void setCursorName(String name) throws SQLException {
  }
	

  /**
   * Give a hint as to the direction in which the rows in a result set
   * will be processed. The hint applies only to result sets created 
   * using this Statement object.  The default value is 
   * ResultSet.FETCH_FORWARD.
   *
   * @param direction the initial direction for processing rows
   * @throws SQLException if a database-access error occurs or direction
   * is not one of ResultSet.FETCH_FORWARD, ResultSet.FETCH_REVERSE, or
   * ResultSet.FETCH_UNKNOWN
   */
  public void setFetchDirection(int direction) throws SQLException {
    throw new SQLException("not implemented");
  }
  
  /**
   * Determine the fetch direction.
   *
   * @return the default fetch direction
   * @throws SQLException if a database-access error occurs
   */
  public int getFetchDirection() throws SQLException {
    return ResultSet.FETCH_FORWARD;
  }
  
  /**
   * Give the JDBC driver a hint as to the number of rows that should 
   * be fetched from the database when more rows are needed.  The number 
   * of rows specified only affects result sets created using this 
   * statement. If the value specified is zero, then the hint is ignored.
   * The default value is zero.
   *
   * @param rows the number of rows to fetch
   * @throws SQLException if a database-access error occurs, or the
   * condition 0 <= rows <= this.getMaxRows() is not satisfied.
   */
  public void setFetchSize(int rows) throws SQLException {
    throw new SQLException("not implemented");
  }
  
  /**
   * Determine the default fetch size.
   */
  public int getFetchSize() throws SQLException {
    return 0;
  }
  
  /**
   * Determine the result set concurrency.
   */
  public int getResultSetConcurrency() throws SQLException {
    return ResultSet.CONCUR_READ_ONLY;
  }
  
  /**
   * Determine the result set type.
   */
  public int getResultSetType()  throws SQLException {
    return ResultSet.TYPE_FORWARD_ONLY;
  }
  
  /**
   * Adds a SQL command to the current batch of commmands for the statement.
   * This method is optional.
   *
   * @param sql typically this is a static SQL INSERT or UPDATE statement
   * @throws SQLException if a database-access error occurs, or the
   * driver does not support batch statements
   */
  public void addBatch(String sql) throws SQLException {
    throw new SQLException("not implemented");
  }

  /**
   * Adds a set of parameters to this <code>PreparedStatement</code>
   * object's batch of commands.
   * 
   * @throws SQLException if a database access error occurs
   * @see Statement#addBatch
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC
   *      2.0 API</a>
   */
  public void addBatch() throws SQLException {
    throw new SQLException("not implemented");
  }
  
  /**
   * Make the set of commands in the current batch empty.
   * This method is optional.
   *
   * @throws SQLException if a database-access error occurs, or the
   * driver does not support batch statements
   */
  public void clearBatch() throws SQLException {
    throw new SQLException("not implemented");
  }
  
  /**
   * Submit a batch of commands to the database for execution.
   * This method is optional.
   *
   * @return an array of update counts containing one element for each
   * command in the batch.  The array is ordered according 
   * to the order in which commands were inserted into the batch
   * @throws SQLException if a database-access error occurs, or the
   * driver does not support batch statements
   */
  public int[] executeBatch() throws SQLException {
    throw new SQLException("not implemented");
  }
  
  /**
   * Return the Connection that produced the Statement.
   */
  public java.sql.Connection getConnection() throws SQLException {
    return connection;
  }


  /**
   * Query as parsed.
   */
  public String toString() {
    return query!=null ? query.toString(false) : "[Empty Statement]";
  }


  /**
   * Clears the current parameter values immediately.
   * <P>In general, parameter values remain in force for repeated use of a
   * statement. Setting a parameter value automatically clears its
   * previous value.  However, in some cases it is useful to immediately
   * release the resources used by the current parameter values; this can
   * be done by calling the method <code>clearParameters</code>.
   *
   * @throws SQLException if a database access error occurs
   */
  public void clearParameters() throws SQLException {
    throw new SQLException("not implemented");
  }



  /**
   * <p>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
   * Ref, Blob, Clob, Struct, 
   * or Array, 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 parameterIndex the first parameter is 1, the second is 2, ...
   * @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.
   * @throws SQLException if a database access error occurs
   * @see Types 
   */
  public void setObject(int parameterIndex, Object x, int targetSqlType, int scale)
    throws SQLException {
    setObject(parameterIndex,x);
  }

  /**
   * 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 parameterIndex the first parameter is 1, the second is 2, ...
   * @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
   * @throws SQLException if a database access error occurs
   */
  public void setObject(int parameterIndex, Object x, int targetSqlType) 
    throws SQLException {
    setObject(parameterIndex,x,targetSqlType,0);
  }

  /**
   * <p>Sets the value of the designated parameter using 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
   * Ref, Blob, Clob, Struct, 
   * or Array, then the driver should pass it to the database as a value of the 
   * corresponding SQL type.
   *
   * 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 parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the object containing the input parameter value 
   * @throws SQLException if a database access error occurs
   */
  public void setObject(int parameterIndex, Object x) throws SQLException {
    throw new SQLException("not implemented");
  }


  /**
   * Sets the designated parameter to SQL <code>NULL</code>.
   *
   * <P><B>Note:</B> You must specify the parameter's SQL type.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param sqlType the SQL type code defined in <code>java.sql.Types</code>
   * @throws SQLException if a database access error occurs
   */
  public void setNull(int parameterIndex, int sqlType) throws SQLException {
    setObject(parameterIndex,null,sqlType);
  }

  /**
   * Sets the designated parameter to a Java <code>boolean</code> value.
   * The driver converts this
   * to an SQL <code>BIT</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
   */
  public void setBoolean(int parameterIndex, boolean x) throws SQLException {
    setObject(parameterIndex,new Boolean(x),Types.BIT);
  }

  /**
   * Sets the designated parameter to a Java <code>byte</code> value.  
   * The driver converts this
   * to an SQL <code>TINYINT</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
   */
  public void setByte(int parameterIndex, byte x) throws SQLException {
    setObject(parameterIndex,new Byte(x),Types.TINYINT);
  }

  /**
   * Sets the designated parameter to a Java <code>short</code> value. 
   * The driver converts this
   * to an SQL <code>SMALLINT</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
   */
  public void setShort(int parameterIndex, short x) throws SQLException {
    setObject(parameterIndex,new Short(x),Types.SMALLINT);
  }

  /**
   * Sets the designated parameter to a Java <code>int</code> value.  
   * The driver converts this
   * to an SQL <code>INTEGER</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
   */
  public void setInt(int parameterIndex, int x) throws SQLException {
    setObject(parameterIndex,new Integer(x),Types.INTEGER);
  }

  /**
   * Sets the designated parameter to a Java <code>long</code> value. 
   * The driver converts this
   * to an SQL <code>BIGINT</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
   */
  public void setLong(int parameterIndex, long x) throws SQLException {
    setObject(parameterIndex,new Long(x),Types.BIGINT);
  }

  /**
   * Sets the designated parameter to a Java <code>float</code> value. 
   * The driver converts this
   * to an SQL <code>FLOAT</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
   */
  public void setFloat(int parameterIndex, float x) throws SQLException {
    setObject(parameterIndex,new Double(x),Types.FLOAT);
  }

  /**
   * Sets the designated parameter to a Java <code>double</code> value.  
   * The driver converts this
   * to an SQL <code>DOUBLE</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
   */
  public void setDouble(int parameterIndex, double x) throws SQLException {
    setObject(parameterIndex,new Double(x),Types.DOUBLE);
  }

  /**
   * Sets the designated parameter to a <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 parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @throws SQLException if a database access error occurs
   */
  public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {
    throw new SQLException("not implemented");
  }

  /**
   * Sets the designated parameter to a 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 parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @throws SQLException if a database access error occurs
   */
  public void setString(int parameterIndex, String x) throws SQLException {
    setObject(parameterIndex,x,Types.VARCHAR);
  }

  /**
   * Sets the designated parameter to a 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 parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value 
   * @throws SQLException if a database access error occurs
   */
  public void setBytes(int parameterIndex, byte x[]) throws SQLException {
    throw new SQLException("not implemented");
  }

  /**
   * Sets the designated parameter to a <code<java.sql.Date</code> value.  
   * The driver converts this
   * to an SQL <code>DATE</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
   */
  public void setDate(int parameterIndex, java.sql.Date x) throws SQLException {
    throw new SQLException("not implemented");
  }

  /**
   * Sets the designated parameter to a <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 parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @throws SQLException if a database access error occurs
   */
  public void setTime(int parameterIndex, java.sql.Time x) throws SQLException {
    throw new SQLException("not implemented");
  }

  /**
   * Sets the designated parameter to a <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 parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value 
   * @throws SQLException if a database access error occurs
   */
  public void setTimestamp(int parameterIndex, java.sql.Timestamp x)
    throws SQLException {
    throw new SQLException("not implemented");
  }

  /**
   * 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 parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the Java input stream that contains the ASCII parameter value
   * @param length the number of bytes in the stream 
   * @throws SQLException if a database access error occurs
   */
  public void setAsciiStream(int parameterIndex, java.io.InputStream x, int length)
    throws SQLException {
    throw new SQLException("not implemented");
  }

  /**
   * Sets the designated parameter to the given input stream, which will have 
   * the specified number of bytes.
   * 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. 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.
   * 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 either be a standard
   * Java stream object or your own subclass that implements the
   * standard interface.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...  
   * @param x the java input stream which contains the
   * UNICODE parameter value 
   * @param length the number of bytes in the stream 
   * @throws SQLException if a database access error occurs
   * @deprecated
   */
  public void setUnicodeStream(int parameterIndex, java.io.InputStream x, 
			int length) throws SQLException {
    throw new SQLException("not implemented");
  }

  /**
   * 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 parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the java input stream which contains the binary parameter value
   * @param length the number of bytes in the stream 
   * @throws SQLException if a database access error occurs
   */
  public void setBinaryStream(int parameterIndex, java.io.InputStream x, 
		       int length) throws SQLException {
    throw new SQLException("not implemented");
  }


  /**
   * 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 parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the java reader which contains the UNICODE data
   * @param length the number of characters in the stream 
   * @throws SQLException if a database access error occurs
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC
   *      2.0 API</a>
   */
  public void setCharacterStream(int parameterIndex, java.io.Reader reader,
			  int length) throws SQLException {
    throw new SQLException("not implemented");
  }

  /**
   * Sets the designated parameter to the given
   *  <code>REF(&lt;structured-type&gt;)</code> value.
   *
   * @param i the first parameter is 1, the second is 2, ...
   * @param x an SQL <code>REF</code> value
   * @throws SQLException if a database access error occurs
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC
   *      2.0 API</a>
   */
  public void setRef (int i, Ref x) throws SQLException {
    throw new SQLException("not implemented");
  }

  /**
   * Sets the designated parameter to the given
   *  <code>Blob</code> object.
   *
   * @param i the first parameter is 1, the second is 2, ...
   * @param x a <code>Blob</code> object that maps an SQL <code>BLOB</code> value
   * @throws SQLException if a database access error occurs
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC
   *      2.0 API</a>
   */
  public void setBlob (int i, Blob x) throws SQLException {
    throw new SQLException("not implemented");
  }

  /**
   * Sets the designated parameter to the given
   *  <code>Clob</code> object.
   *
   * @param i the first parameter is 1, the second is 2, ...
   * @param x a <code>Clob</code> object that maps an SQL <code>CLOB</code> value
   * @throws SQLException if a database access error occurs
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC
   *      2.0 API</a>
   */
  public void setClob (int i, Clob x) throws SQLException {
    throw new SQLException("not implemented");
  }

  /**
   * Sets the designated parameter to the given
   *  <code>Array</code> object.
   * Sets an Array parameter.
   *
   * @param i the first parameter is 1, the second is 2, ...
   * @param x an <code>Array</code> object that maps an SQL <code>ARRAY</code> value
   * @throws SQLException if a database access error occurs
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC
   *      2.0 API</a>
   */
  public void setArray (int i, Array x) throws SQLException {
    throw new SQLException("not implemented");
  }

  /**
   * 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 parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @param cal the <code>Calendar</code> object the driver will use
   *            to construct the date
   * @throws SQLException if a database access error occurs
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC
   *      2.0 API</a>
   */
  public void setDate(int parameterIndex, java.sql.Date x, Calendar cal)
    throws SQLException {
    throw new SQLException("not implemented");
  }

  /**
   * 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 parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @param cal the <code>Calendar</code> object the driver will use
   *            to construct the time
   * @throws SQLException if a database access error occurs
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC
   *      2.0 API</a>
   */
  public void setTime(int parameterIndex, java.sql.Time x, Calendar cal) 
    throws SQLException {
    throw new SQLException("not implemented");
  }

  /**
   * 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 parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value 
   * @param cal the <code>Calendar</code> object the driver will use
   *            to construct the timestamp
   * @throws SQLException if a database access error occurs
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC
   *      2.0 API</a>
   */
  public void setTimestamp(int parameterIndex, java.sql.Timestamp x, Calendar cal)
    throws SQLException {
    throw new SQLException("not implemented");
  }

  /**
   * 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 parameterIndex the first parameter is 1, the second is 2, ...
   * @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 REF 
   * @throws SQLException if a database access error occurs
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC
   *      2.0 API</a>
   */
  public void setNull (int paramIndex, int sqlType, String typeName) 
    throws SQLException {
    setObject(paramIndex,null,sqlType);
  }
}	
