alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 * MM JDBC Drivers for MySQL
 *
 * $Id: PreparedStatement.java,v 1.2 1998/08/25 00:53:47 mmatthew Exp $
 *
 * Copyright (C) 1998 Mark Matthews <mmatthew@worldserver.com>
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 * 
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA  02111-1307, USA.
 *
 * See the COPYING file located in the top-level-directory of
 * the archive of this library for complete text of license.
 */

/**
 * A SQL Statement is pre-compiled and stored in a PreparedStatement object.
 * This object can then be used to efficiently execute this statement multiple
 * times.
 *
 * <p>Note: The setXXX methods for setting IN parameter values must
 * specify types that are compatible with the defined SQL type of the input
 * parameter.  For instance, if the IN parameter has SQL type Integer, then
 * setInt should be used.
 *
 * <p>If arbitrary parameter type conversions are required, then the setObject 
 * method should be used with a target SQL type.
 *
 * @see java.sql.ResultSet
 * @see java.sql.PreparedStatement
 * @author Mark Matthews <mmatthew@worldserver.com>
 * @version $Id$
 */

package org.gjt.mm.mysql;

import java.io.*;
import java.math.*;
import java.sql.*;
import java.text.*;
import java.util.*;

public class PreparedStatement extends org.gjt.mm.mysql.Statement 
    implements java.sql.PreparedStatement  
{

    private String        _Sql              = null;
    private String[]      _TemplateStrings  = null;
    private String[]      _ParameterStrings = null;
    private InputStream[] _ParameterStreams = null;
    private boolean[]     _IsStream         = null;
    private Connection    _Conn             = null;

    private boolean       _do_concat        = false;
    private boolean       _has_limit_clause = false;
    
    /**
     * Constructor for the PreparedStatement class.
     * Split the SQL statement into segments - separated by the arguments.
     * When we rebuild the thing with the arguments, we can substitute the
     * args and join the whole thing together.
     *
     * @param conn the instanatiating connection
     * @param sql the SQL statement with ? for IN markers
     * @exception java.sql.SQLException if something bad occurs
     */

    public PreparedStatement(Connection Conn, String Sql, String Catalog) throws java.sql.SQLException
    {
	super(Conn, Catalog);

	if (Sql.indexOf("||") != -1) {
	    _do_concat = true;
	}
	
	_has_limit_clause = (Sql.toUpperCase().indexOf("LIMIT") != -1);

	Vector V = new Vector();
	boolean inQuotes = false;
	int lastParmEnd = 0, i;

	_Sql = Sql;
	_Conn = Conn;

	for (i = 0; i < _Sql.length(); ++i) {
	    int c = _Sql.charAt(i);
		    
	    if (c == '\'')
		inQuotes = !inQuotes;
	    if (c == '?' && !inQuotes)
		{
		    V.addElement(_Sql.substring (lastParmEnd, i));
		    lastParmEnd = i + 1;
		}
	}
	V.addElement(_Sql.substring (lastParmEnd, _Sql.length()));

	_TemplateStrings = new String[V.size()];
	_ParameterStrings = new String[V.size() - 1];
	_ParameterStreams = new InputStream[V.size() - 1];
	_IsStream         = new boolean[V.size() - 1];
	clearParameters();

	for (i = 0 ; i < _TemplateStrings.length; ++i) {
	    _TemplateStrings[i] = (String)V.elementAt(i);
	}

	for (int j = 0; j < _ParameterStrings.length; j++) {
	    _IsStream[j] = false;
	}
    }

    /**
     * A Prepared SQL query is executed and its ResultSet is returned
     *
     * @return a ResultSet that contains the data produced by the
     *      query - never null
     * @exception java.sql.SQLException if a database access error occurs
     */

    public java.sql.ResultSet executeQuery() throws java.sql.SQLException
    {
	boolean do_escape_processing = _escapeProcessing;
	_escapeProcessing = false; // Do escape processing part-by-part
   
	Buffer Packet = new Buffer(MysqlIO.getMaxBuf());
	Packet.writeByte((byte)MysqlDefs.QUERY);
	      
	String Encoding = null;

	if (_Conn.useUnicode()) {
	    Encoding = _Conn.getEncoding();
	}

	try {
	    for (int i = 0 ; i < _ParameterStrings.length ; ++i) {

		if (_ParameterStrings[i] == null && 
		    (_IsStream[i] && _ParameterStreams[i] == null)) {
		    throw new java.sql.SQLException("No value specified for parameter " + (i + 1), "07001");
		}

		if (Encoding != null) {
		    Packet.writeStringNoNull(_TemplateStrings[i], Encoding);
		}
		else {
		    Packet.writeStringNoNull(_TemplateStrings[i]);
		}
	    
		if (_IsStream[i]) {
		    Packet.writeBytesNoNull(streamToBytes(_ParameterStreams[i]));
		}
		else {
		    if (do_escape_processing) {
			_ParameterStrings[i] = _Escaper.escapeSQL(_ParameterStrings[i]);
		    }
			
		    if (Encoding != null) {
			Packet.writeStringNoNull(_ParameterStrings[i], Encoding);
		    }
		    else {
			Packet.writeStringNoNull(_ParameterStrings[i]);
		    }
		}
	    }

	    if (Encoding != null) {
		Packet.writeStringNoNull(_TemplateStrings[_ParameterStrings.length], Encoding);
	    }
	    else {
		Packet.writeStringNoNull(_TemplateStrings[_ParameterStrings.length]);
	    }
	}
	catch (java.io.UnsupportedEncodingException UE) {
	    throw new SQLException("Unsupported character encoding '" + Encoding + "'");
	}
		
	if (_Results != null) {
	    _Results.close();
	}

	// We need to execute this all together
	// So synchronize on the Connection's mutex (because 
	// even queries going through there synchronize
	// on the same mutex.

	synchronized (_Conn.getMutex()) {
	    String OldCatalog = null;

	    if (!_Conn.getCatalog().equals(_Catalog)) {
		OldCatalog = _Conn.getCatalog();
		_Conn.setCatalog(_Catalog);
	    }

	    if (_Conn.useMaxRows()) {

		// If there isn't a limit clause in the SQL
		// then limit the number of rows to return in 
		// an efficient manner. Only do this if
		// setMaxRows() hasn't been used on any Statements
		// generated from the current Connection (saves
		// a query, and network traffic).

		if (_has_limit_clause) { 
		    _Results = _Conn.execSQL(null, _max_rows, Packet);
		}
		else {
		    if (_max_rows <= 0) {
			_Conn.execSQL("SET OPTION SQL_SELECT_LIMIT=" 
				      + MysqlDefs.MAX_ROWS, -1);
		    }
		    else {
			_Conn.execSQL("SET OPTION SQL_SELECT_LIMIT=" + _max_rows,-1);
		    }
			        		            
		    _Results = _Conn.execSQL(null, -1, Packet);

		    if (OldCatalog != null) {
			_Conn.setCatalog(OldCatalog);
		    }
		}
	    }
	    else {
		_Results = _Conn.execSQL(null, -1, Packet);	    
	    }

	    if (OldCatalog != null) {
		_Conn.setCatalog(OldCatalog);
	    }
	}

	_last_insert_id = _Results.getUpdateID();
	_NextResults = _Results;
	_Results.setConnection(_Conn);
	
	_escapeProcessing = do_escape_processing;
	
	return _Results;
    }

    /**
     * Execute a SQL INSERT, UPDATE or DELETE statement.  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; or
     *      0 for SQL statements that return nothing.
     * @exception java.sql.SQLException if a database access error occurs
     */

    public int executeUpdate() throws java.sql.SQLException
    {
	boolean do_escape_processing = _escapeProcessing;
	_escapeProcessing = false;
		            
	Buffer Packet = new Buffer(MysqlIO.getMaxBuf());
	Packet.writeByte((byte)MysqlDefs.QUERY);
	
	String Encoding = null;

	if (_Conn.useUnicode()) {
	    Encoding = _Conn.getEncoding();
	}

	try {
	    for (int i = 0 ; i < _ParameterStrings.length ; ++i) {
		if (_ParameterStrings[i] == null && 
		    (_IsStream[i] && _ParameterStreams[i] == null)) {
		    throw new java.sql.SQLException("No value specified for parameter " + (i + 1), "07001");
		}

		if (Encoding != null) {
		    Packet.writeStringNoNull(_TemplateStrings[i], Encoding);
		}
		else {
		    Packet.writeStringNoNull(_TemplateStrings[i]);
		}
		    
		if (_IsStream[i]) {
		    Packet.writeBytesNoNull(streamToBytes(_ParameterStreams[i]));
		}
		else {
		    if (do_escape_processing) {
			_ParameterStrings[i] = _Escaper.escapeSQL(_ParameterStrings[i]);
		    }
			
		    if (Encoding != null) {
			Packet.writeStringNoNull(_ParameterStrings[i], Encoding);
		    }
		    else {
			Packet.writeStringNoNull(_ParameterStrings[i]);
		    }
		}
	    }
		
	    if (Encoding != null) {
		Packet.writeStringNoNull(_TemplateStrings[_ParameterStrings.length], Encoding);
	    }
	    else {
		Packet.writeStringNoNull(_TemplateStrings[_ParameterStrings.length]);
	    }
	}
	catch (java.io.UnsupportedEncodingException UE) {
	    throw new SQLException("Unsupported character encoding '" + Encoding + "'");
	}
		
	// The checking and changing of catalogs
        // must happen in sequence, so synchronize
        // on the same mutex that _Conn is using

	ResultSet RS = null;

	synchronized (_Conn.getMutex()) {
	    String OldCatalog = null;

	    if (!_Conn.getCatalog().equals(_Catalog)) {
		OldCatalog = _Conn.getCatalog();
		_Conn.setCatalog(_Catalog);
	    }

	    RS = _Conn.execSQL(null, -1, Packet);

	    if (OldCatalog != null) {
		_Conn.setCatalog(OldCatalog);
	    }
	}
	
	if (RS.reallyResult()) {
	    throw new java.sql.SQLException("Results returned for UPDATE ONLY.", "01S03");
	}
	else {
	    _update_count = RS.getUpdateCount();
		    
	    int truncated_update_count = 0;

	    if (_update_count > Integer.MAX_VALUE) {
		truncated_update_count = Integer.MAX_VALUE;
	    }
	    else {
		truncated_update_count = (int)_update_count;
	    }

	    _last_insert_id = RS.getUpdateID();
		    
	    _escapeProcessing = do_escape_processing;
			
	    return truncated_update_count;
	}
    }       

    /**
     * Set a parameter to SQL NULL
     *
     * <p>Note: You must specify the parameters SQL type (although
     * PostgreSQL ignores it)
     *
     * @param parameterIndex the first parameter is 1, etc...
     * @param sqlType the SQL type code defined in java.sql.Types
     * @exception java.sql.SQLException if a database access error occurs
     */

    public void setNull(int parameterIndex, int sqlType) throws java.sql.SQLException
    {
	set(parameterIndex, "null");
    }

    /**
     * Set a parameter to a Java boolean value.  The driver converts this
     * to a SQL BIT value when it sends it to the database.
     *
     * @param parameterIndex the first parameter is 1...
     * @param x the parameter value
     * @exception java.sql.SQLException if a database access error occurs
     */
    public void setBoolean(int parameterIndex, boolean x) throws java.sql.SQLException
    {
	set(parameterIndex, x ? "'t'" : "'f'");
    }

    /**
     * Set a parameter to a Java byte value.  The driver converts this to
     * a SQL TINYINT value when it sends it to the database.
     *
     * @param parameterIndex the first parameter is 1...
     * @param x the parameter value
     * @exception java.sql.SQLException if a database access error occurs
     */
    public void setByte(int parameterIndex, byte x) throws java.sql.SQLException
    {
	set(parameterIndex, (new Integer(x)).toString());
    }

    /**
     * Set a parameter to a Java short value.  The driver converts this
     * to a SQL SMALLINT value when it sends it to the database.
     *
     * @param parameterIndex the first parameter is 1...
     * @param x the parameter value
     * @exception java.sql.SQLException if a database access error occurs
     */
    public void setShort(int parameterIndex, short x) throws java.sql.SQLException
    {
	set(parameterIndex, (new Integer(x)).toString());
    }

    /**
     * Set a parameter to a Java int value.  The driver converts this to
     * a SQL INTEGER value when it sends it to the database.
     *
     * @param parameterIndex the first parameter is 1...
     * @param x the parameter value
     * @exception java.sql.SQLException if a database access error occurs
     */
    public void setInt(int parameterIndex, int x) throws java.sql.SQLException
    {
	set(parameterIndex, (new Integer(x)).toString());
    }

    /**
     * Set a parameter to a Java long value.  The driver converts this to
     * a SQL BIGINT value when it sends it to the database.
     *
     * @param parameterIndex the first parameter is 1...
     * @param x the parameter value
     * @exception java.sql.SQLException if a database access error occurs
     */
    public void setLong(int parameterIndex, long x) throws java.sql.SQLException
    {
	set(parameterIndex, (new Long(x)).toString());
    }

    /**
     * Set a parameter to a Java float value.  The driver converts this
     * to a SQL FLOAT value when it sends it to the database.
     *
     * @param parameterIndex the first parameter is 1...
     * @param x the parameter value
     * @exception java.sql.SQLException if a database access error occurs
     */
    public void setFloat(int parameterIndex, float x) throws java.sql.SQLException
    {
	set(parameterIndex, (new Float(x)).toString());
    }

    /**
     * Set a parameter to a Java double value.  The driver converts this
     * to a SQL DOUBLE value when it sends it to the database
     *
     * @param parameterIndex the first parameter is 1...
     * @param x the parameter value
     * @exception java.sql.SQLException if a database access error occurs
     */
    public void setDouble(int parameterIndex, double x) throws java.sql.SQLException
    {
	set(parameterIndex, _DoubleFormatter.format(x));
	// - Fix for large doubles by Steve Ferguson
    }

    /**
     * Set a parameter to a java.lang.BigDecimal value.  The driver
     * converts this to a SQL NUMERIC value when it sends it to the
     * database.
     *
     * @param parameterIndex the first parameter is 1...
     * @param x the parameter value
     * @exception java.sql.SQLException if a database access error occurs
     */
    public void setBigDecimal(int parameterIndex, BigDecimal X) throws java.sql.SQLException
    {
	if (X == null) {
	    setNull(parameterIndex, java.sql.Types.DECIMAL);
	}
	else {
	    set(parameterIndex, X.toString());
	}
    }

    /**
     * Set a parameter to a Java String value.  The driver converts this
     * to a SQL VARCHAR or LONGVARCHAR value (depending on the arguments
     * size relative to the driver's limits on VARCHARs) when it sends it
     * to the database.
     *
     * @param parameterIndex the first parameter is 1...
     * @param x the parameter value
     * @exception java.sql.SQLException if a database access error occurs
     */

    public void setString(int parameterIndex, String X) throws java.sql.SQLException
    {
	// if the passed string is null, then set this column to null
		
	if(X == null) {
	    set(parameterIndex, "null");
	}
	else {
	    StringBuffer B = new StringBuffer();
	    int i;
			        
	    B.append('\'');

	    for (i = 0 ; i < X.length() ; ++i) {
		char c = X.charAt(i);
				
		if (c == '\\' || c == '\'' || c == '"') {
		    B.append((char)'\\');
		}
		B.append(c);
	    }
			
	    B.append('\'');
	    set(parameterIndex, B.toString());
	}
    }

    /**
     * Set a parameter to a Java array of bytes.  The driver converts this
     * to a SQL VARBINARY or LONGVARBINARY (depending on the argument's
     * size relative to the driver's limits on VARBINARYs) when it sends
     * it to the database.
     *
     *
     * @param parameterIndex the first parameter is 1...
     * @param x the parameter value
     * @exception java.sql.SQLException if a database access error occurs
     */

    public void setBytes(int parameterIndex, byte x[]) throws java.sql.SQLException
    {
	if (x == null) {
	    setNull(parameterIndex, java.sql.Types.BINARY);
	}
	else {
	    ByteArrayInputStream BIn = new ByteArrayInputStream(x);
	    setBinaryStream(parameterIndex, BIn, x.length);
	}
    }

    /**
     * Set a parameter to a java.sql.Date value.  The driver converts this
     * to a SQL DATE value when it sends it to the database.
     *
     * @param parameterIndex the first parameter is 1...
     * @param x the parameter value
     * @exception java.sql.SQLException if a database access error occurs
     */

    public void setDate(int parameterIndex, java.sql.Date X) throws java.sql.SQLException
    {
	if (X == null) {
	    setNull(parameterIndex, java.sql.Types.DATE);
	}
	else {
	    SimpleDateFormat DF = new SimpleDateFormat("''yyyy-MM-dd''");
	    
	    set(parameterIndex, DF.format(X));
	}
    }

    /**
     * Set a parameter to a java.sql.Time value.  The driver converts
     * this to a SQL TIME value when it sends it to the database.
     *
     * @param parameterIndex the first parameter is 1...));
     * @param x the parameter value
     * @exception java.sql.SQLException if a database access error occurs
     */

    public void setTime(int parameterIndex, Time X) throws java.sql.SQLException
    {
	if (X == null) {
	    setNull(parameterIndex, java.sql.Types.TIME);
	}
	else {
	    set(parameterIndex, "'" + X.toString() + "'");
	}
    }

    /**
     * Set a parameter to a java.sql.Timestamp value.  The driver converts
     * this to a SQL TIMESTAMP value when it sends it to the database.
     *
     * @param parameterIndex the first parameter is 1...
     * @param x the parameter value
     * @exception java.sql.SQLException if a database access error occurs
     */

    public void setTimestamp(int parameterIndex, Timestamp X) throws java.sql.SQLException
    {
	if (X == null) {
	    setNull(parameterIndex, java.sql.Types.TIMESTAMP);
	}
	else {
	    EscapeProcessor EP = new EscapeProcessor();
	    String TimestampString = EP.escapeSQL("{ts '" + X.toString() + "'}");
	    set(parameterIndex, TimestampString);
	}
    }

    /**
     * When a very large ASCII value is input to a LONGVARCHAR parameter,
     * it may be more practical to send it via a java.io.InputStream.
     * JDBC will read the data from the stream as needed, until it reaches
     * end-of-file.  The JDBC driver will do any necessary conversion from
     * ASCII to the database char format.
     *
     * <P>Note: 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...
     * @param x the parameter value
     * @param length the number of bytes in the stream
     * @exception java.sql.SQLException if a database access error occurs
     */

    public void setAsciiStream(int parameterIndex, InputStream X, int length) throws java.sql.SQLException
    {
	if (X == null) {
	    setNull(parameterIndex, java.sql.Types.VARCHAR);
	}
	else {
	    setBinaryStream(parameterIndex, X, length);
	}
    }

    /**
     * When a very large Unicode value is input to a LONGVARCHAR parameter,
     * it may be more practical to send it via a java.io.InputStream.
     * JDBC will read the data from the stream as needed, until it reaches
     * end-of-file.  The JDBC driver will do any necessary conversion from
     * UNICODE to the database char format.
     *
     * <P>Note: 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...
     * @param x the parameter value
     * @exception java.sql.SQLException if a database access error occurs
     */

    public void setUnicodeStream(int parameterIndex, InputStream X, int length) throws java.sql.SQLException
    {
	if (X == null) {
	    setNull(parameterIndex, java.sql.Types.VARCHAR);
	}
	else {
	    setBinaryStream(parameterIndex, X, length);
	}
    }

    /**
     * When a very large binary value is input to a LONGVARBINARY parameter,
     * it may be more practical to send it via a java.io.InputStream.
     * JDBC will read the data from the stream as needed, until it reaches
     * end-of-file.  
     *
     * <P>Note: 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...
     * @param x the parameter value
     * @exception java.sql.SQLException if a database access error occurs
     */

    public void setBinaryStream(int parameterIndex, InputStream X, int length) throws java.sql.SQLException
    {
	if (X == null) {
	    setNull(parameterIndex, java.sql.Types.BINARY);
	}
	else {
	    if (parameterIndex < 1 || 
		parameterIndex > _TemplateStrings.length) {
		throw new java.sql.SQLException("Parameter index out of range (" + parameterIndex + " > " + _TemplateStrings.length + ")", "S1009");
	    }
	    _ParameterStreams[parameterIndex - 1] = X;
	    _IsStream[parameterIndex - 1] = true;
	}
    }

    /**
     * In general, parameter values remain in force for repeated used of a
     * Statement.  Setting a parameter value automatically clears its
     * previous value.  However, in coms cases, it is useful to immediately
     * release the resources used by the current parameter values; this
     * can be done by calling clearParameters
     *
     * @exception java.sql.SQLException if a database access error occurs
     */

    public void clearParameters() throws java.sql.SQLException
    {
	for (int i = 0 ; i < _ParameterStrings.length ; i++) {
	    _ParameterStrings[i] = null;
	    _ParameterStreams[i] = null;
	    _IsStream[i] = false;
	}

    }

    /**
     * Set the value of a parameter using an object; use the java.lang
     * equivalent objects for integral values.
     *
     * <P>The given Java object will be converted to the targetSqlType before
     * being sent to the database.
     *
     * <P>note that this method may be used to pass database-specific
     * abstract data types.  This is done by using a Driver-specific
     * Java type and using a targetSqlType of java.sql.Types.OTHER
     *
     * @param parameterIndex the first parameter is 1...
     * @param x the object containing the input parameter value
     * @param targetSqlType The SQL type to be send to the database
     * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC
     *      types this is the number of digits after the decimal.  For 
     *      all other types this value will be ignored.
     * @exception java.sql.SQLException if a database access error occurs
     */

    public void setObject(int parameterIndex, Object X, int targetSqlType, int scale) throws java.sql.SQLException
    {
	if (X == null) {
	    setNull(parameterIndex, java.sql.Types.OTHER);
	}
	else try {
	    switch (targetSqlType)
		{
		case Types.TINYINT:
		case Types.SMALLINT:
		case Types.INTEGER:
		case Types.BIGINT:
		case Types.REAL:
		case Types.FLOAT:
		case Types.DOUBLE:
		case Types.DECIMAL:
		case Types.NUMERIC:
                    Number X_as_number;
		    if (X instanceof Boolean)
			X_as_number=((Boolean)X).booleanValue() ? new Integer(1) : new Integer(0);
		    else if (X instanceof String)
                        switch (targetSqlType) {
			case Types.TINYINT:
			case Types.SMALLINT:
			case Types.INTEGER:
			    X_as_number=Integer.valueOf((String)X);
			    break;
			case Types.BIGINT:
			    X_as_number=Long.valueOf((String)X);
			    break;
			case Types.REAL:
			    X_as_number=Float.valueOf((String)X);
			    break;
			case Types.FLOAT:
			case Types.DOUBLE:
			    X_as_number=Double.valueOf((String)X);
			    break;
			case Types.DECIMAL:
			case Types.NUMERIC:
			default:
			    X_as_number=new java.math.BigDecimal((String)X);
			}
		    else
			X_as_number=(Number)X;
                    switch (targetSqlType) {
		    case Types.TINYINT:
		    case Types.SMALLINT:
		    case Types.INTEGER:
			setInt(parameterIndex, X_as_number.intValue());
			break;
		    case Types.BIGINT:
			setLong(parameterIndex, X_as_number.longValue());
			break;
		    case Types.REAL:
			setFloat(parameterIndex, X_as_number.floatValue());
			break;
		    case Types.FLOAT:
		    case Types.DOUBLE:
			setDouble(parameterIndex, X_as_number.doubleValue());
			break;
		    case Types.DECIMAL:
		    case Types.NUMERIC:
		    default:
			if (X_as_number instanceof java.math.BigDecimal)
			    setBigDecimal(parameterIndex, (java.math.BigDecimal)X_as_number);
			else if (X_as_number instanceof java.math.BigInteger)
			    setBigDecimal(parameterIndex, new java.math.BigDecimal((java.math.BigInteger)X_as_number,scale));
			else
			    setBigDecimal(parameterIndex, new java.math.BigDecimal(X_as_number.doubleValue()));
			break;
		    }
		    break;
		case Types.CHAR:
		case Types.VARCHAR:
		case Types.LONGVARCHAR:
		    setString(parameterIndex, X.toString());
		    break;
		case Types.BINARY:
		case Types.VARBINARY:
		case Types.LONGVARBINARY:
		    if (X instanceof String)
			setBytes(parameterIndex, ((String)X).getBytes());
		    else
			setBytes(parameterIndex, (byte[])X);
		    break;
		case Types.DATE:
		case Types.TIMESTAMP:
                    java.util.Date X_as_date;
		    if (X instanceof String) {
                        ParsePosition pp=new ParsePosition(0);
			java.text.DateFormat sdf=new java.text.SimpleDateFormat(getDateTimePattern((String)X,false));
                        X_as_date=sdf.parse((String)X,pp);
		    } else
			X_as_date=(java.util.Date)X;
		    switch(targetSqlType) {
		    case Types.DATE:
			if (X_as_date instanceof java.sql.Date)
			    setDate(parameterIndex,(java.sql.Date)X_as_date);
			else
			    setDate(parameterIndex,new java.sql.Date(X_as_date.getTime()));
			break;
		    case Types.TIMESTAMP:
			if (X_as_date instanceof java.sql.Timestamp)
			    setTimestamp(parameterIndex,(java.sql.Timestamp)X_as_date);
			else
			    setTimestamp(parameterIndex,new java.sql.Timestamp(X_as_date.getTime()));
			break;
		    }
		    break;
		case Types.TIME:
		    if (X instanceof String) {
			java.text.DateFormat sdf=new java.text.SimpleDateFormat(getDateTimePattern((String)X,true));
			setTime(parameterIndex,new java.sql.Time(sdf.parse((String)X).getTime()));
		    } else
			setTime(parameterIndex,(java.sql.Time)X);
		    break;
		case Types.OTHER:
		    try {
			ByteArrayOutputStream BytesOut = new ByteArrayOutputStream();
			ObjectOutputStream ObjectOut = new ObjectOutputStream(BytesOut);
			ObjectOut.writeObject(X);
			ObjectOut.flush();
			ObjectOut.close();
			BytesOut.flush();
			BytesOut.close();
      
			byte[] buf = BytesOut.toByteArray();
			ByteArrayInputStream BytesIn = new ByteArrayInputStream(buf);
			setBinaryStream(parameterIndex, BytesIn, -1);
		    }
		    catch (Exception E) {
			throw new java.sql.SQLException("Invalid argument value: " + E.getClass().getName(), "S1009");
		    }
		    break;
		default:
		    throw new java.sql.SQLException("Unknown Types value", "S1000");
		}
        } catch (Exception ex) {
	    if (ex instanceof java.sql.SQLException) throw (java.sql.SQLException)ex;
	    else throw new java.sql.SQLException("Cannot convert "+X.getClass().toString()+" to SQL type requested", "S1000");
	}
    }

    public void setObject(int parameterIndex, Object X, int targetSqlType) throws java.sql.SQLException
    {
	setObject(parameterIndex, X, targetSqlType, 0);
    }

    public void setObject(int parameterIndex, Object X) throws java.sql.SQLException
    {
	if (X == null) {
	    setNull(parameterIndex, java.sql.Types.OTHER);
	}
	else {
	    if (X instanceof String)
		setString(parameterIndex, (String)X);
	    else if (X instanceof BigDecimal)
		setBigDecimal(parameterIndex, (BigDecimal)X);
	    else if (X instanceof Integer)
		setInt(parameterIndex, ((Integer)X).intValue());
	    else if (X instanceof Long)
		setLong(parameterIndex, ((Long)X).longValue());
	    else if (X instanceof Float)
		setFloat(parameterIndex, ((Float)X).floatValue());
	    else if (X instanceof Double)
		setDouble(parameterIndex, ((Double)X).doubleValue());
	    else if (X instanceof byte[])
		setBytes(parameterIndex, (byte[])X);
	    else if (X instanceof java.sql.Date)
		setDate(parameterIndex, (java.sql.Date)X);
	    else if (X instanceof Time)
		setTime(parameterIndex, (Time)X);
	    else if (X instanceof Timestamp)
		setTimestamp(parameterIndex, (Timestamp)X);
	    else if (X instanceof Boolean)
		setBoolean(parameterIndex, ((Boolean)X).booleanValue());
	    else {
		try {
		    ByteArrayOutputStream BytesOut = new ByteArrayOutputStream();
		    ObjectOutputStream ObjectOut = new ObjectOutputStream(BytesOut);
		    ObjectOut.writeObject(X);
		    ObjectOut.flush();
		    ObjectOut.close();
		    BytesOut.flush();
		    BytesOut.close();
		    
		    byte[] buf = BytesOut.toByteArray();
		    ByteArrayInputStream BytesIn = new ByteArrayInputStream(buf);
		    setBinaryStream(parameterIndex, BytesIn, -1);
		}
		catch (Exception E) {
		    throw new java.sql.SQLException("Invalid argument value: " + E.getClass().getName(), "S1009");
		}
	    }
	}
    }
    
    /**
     * Some prepared statements return multiple results; the execute method
     * handles these complex statements as well as the simpler form of 
     * statements handled by executeQuery and executeUpdate
     *
     * @return true if the next result is a ResultSet; false if it is an
     *      update count or there are no more results
     * @exception java.sql.SQLException if a database access error occurs
     */

    public boolean execute() throws java.sql.SQLException
    {
	boolean do_escape_processing = _escapeProcessing;
	_escapeProcessing = false;

	
	Buffer Packet = new Buffer(MysqlIO.getMaxBuf());
	Packet.writeByte((byte)MysqlDefs.QUERY);
		            
	String Encoding = null;

	if (_Conn.useUnicode()) {
	    Encoding = _Conn.getEncoding();
	}

	try {
	    for (int i = 0 ; i < _ParameterStrings.length ; ++i) {
		if (_ParameterStrings[i] == null && 
		    (_IsStream[i] && _ParameterStreams[i] == null)) {
		    throw new java.sql.SQLException("No value specified for parameter " + (i + 1));
		}

		if (Encoding != null) {
		    Packet.writeStringNoNull(_TemplateStrings[i], Encoding);
		}
		else {
		    Packet.writeStringNoNull(_TemplateStrings[i]);
		}
		    
		if (_IsStream[i]) {
		    Packet.writeBytesNoNull(streamToBytes(_ParameterStreams[i]));
		}
		else {
		    if (do_escape_processing) {
			_ParameterStrings[i] = _Escaper.escapeSQL(_ParameterStrings[i]);
		    }
			
		    if (Encoding != null) {
			Packet.writeStringNoNull(_ParameterStrings[i], Encoding);
		    }
		    else {
			Packet.writeStringNoNull(_ParameterStrings[i]);
		    }
		}
	    }
		
	    if (Encoding != null) {
		Packet.writeStringNoNull(_TemplateStrings[_ParameterStrings.length], Encoding);
	    }
	    else {
		Packet.writeStringNoNull(_TemplateStrings[_ParameterStrings.length]);
	    }
	}
	catch (java.io.UnsupportedEncodingException UE) {
	    throw new SQLException("Unsupported character encoding '" + Encoding + "'");
	}

	ResultSet RS = null;

	
	synchronized (_Conn.getMutex()) {
	    String OldCatalog = null;

	    if (!_Conn.getCatalog().equals(_Catalog)) {
		OldCatalog = _Conn.getCatalog();
		_Conn.setCatalog(_Catalog);
	    }

	    // If there isn't a limit clause in the SQL
	    // then limit the number of rows to return in 
	    // an efficient manner. Only do this if
	    // setMaxRows() hasn't been used on any Statements
	    // generated from the current Connection (saves
	    // a query, and network traffic).
	
	    if (_Conn.useMaxRows()) {
		if (_has_limit_clause) { 
		    RS = _Conn.execSQL(null, _max_rows, Packet);
		}
		else {
		    if (_max_rows <= 0) {
			_Conn.execSQL("SET OPTION SQL_SELECT_LIMIT=" 
				      + MysqlDefs.MAX_ROWS, -1);
		    }
		    else {
			_Conn.execSQL("SET OPTION SQL_SELECT_LIMIT=" + _max_rows,-1);
		    }                
		    RS = _Conn.execSQL(null, -1, Packet);
		}
	    }
	    else {
		RS = _Conn.execSQL(null, -1, Packet);	    
	    }

	    if (OldCatalog != null) {
		_Conn.setCatalog(OldCatalog);
	    }
	}
		    
	_last_insert_id = RS.getUpdateID();

	if (RS != null) {
	    _Results = RS;
	}

	_escapeProcessing = do_escape_processing;
	
	RS.setConnection(_Conn);

	return (RS != null && RS.reallyResult());
    }

    public String toString()
    {
	String Encoding = null;

	if (_Conn.useUnicode()) {
	    Encoding = _Conn.getEncoding();
	}

	StringBuffer SB = new StringBuffer();
	SB.append(super.toString());
	SB.append(": ");
	
	try {
	    for (int i = 0 ; i < _ParameterStrings.length ; ++i) {
	    
		if (Encoding != null) {
		    SB.append(new String(_TemplateStrings[i].getBytes(), Encoding));
		}
		else {
		    SB.append(_TemplateStrings[i]);
		}
	    	if (_ParameterStrings[i] == null && 
		    (_IsStream[i] && _ParameterStreams[i] == null)) {
		    SB.append("** NOT SPECIFIED **");
		}
		else if (_IsStream[i]) {
		    SB.append("** STREAM DATA **");
		}
		else {
		    if (_escapeProcessing) {
			try {
			    _ParameterStrings[i] = _Escaper.escapeSQL(_ParameterStrings[i]);
			}
			catch (SQLException SQE) {}
		    }
		
		    if (Encoding != null) {
			SB.append(new String(_ParameterStrings[i].getBytes(), Encoding));
		    }
		    else {
			SB.append(_ParameterStrings[i]);
		    }
		}
	    }
	
	    if (Encoding != null) {
		SB.append(new String(_TemplateStrings[_ParameterStrings.length].getBytes(), Encoding));
	    }
	    else {
		SB.append(_TemplateStrings[_ParameterStrings.length]);
	    }
	}
	catch (java.io.UnsupportedEncodingException UE) {
	    SB.append("\n\n** WARNING **\n\n Unsupported character encoding '");
	    SB.append(Encoding);
	    SB.append("'");
	}

	return SB.toString();
    }
	
	      
    /**
     * There are a lot of setXXX classes which all basically do
     * the same thing.  We need a method which actually does the
     * set for us.
     *
     * @param paramIndex the index into the inString
     * @param s a string to be stored
     * @exception java.sql.SQLException if something goes wrong
     */

    private final void set(int paramIndex, String S) throws java.sql.SQLException
    {
	if (paramIndex < 1 || paramIndex > _TemplateStrings.length) {
	    throw new java.sql.SQLException("Parameter index out of range (" + paramIndex + " > " + _TemplateStrings.length + ").", "S1009");
	}
	_ParameterStrings[paramIndex - 1] = S;
    }

    private final int readblock(InputStream i,byte[] b) throws java.sql.SQLException
    {
	try  {
	    return i.read(b);
	}
	catch (Throwable E) {
            throw new java.sql.SQLException("Error reading from InputStream " +
					    E.getClass().getName(), "S1000");
	}
    }

    private final void escapeblock(byte[] buf,ByteArrayOutputStream BytesOut,int
				   size)
    {
	int c =0;
    
	for (int i=0;i<size;i++) {
	    byte b = buf[i];
	    if (b == '\0') {
		BytesOut.write('\\');
		BytesOut.write('0');
	    }
	    else {
		if (b == '\\' || b == '\'' || b == '"') {
		    BytesOut.write('\\');
		}
		BytesOut.write(b);
	    }
	}
    }

    /**
     * For the setXXXStream() methods. Basically converts an
     * InputStream into a String. Not very efficient, but it
     * works.
     *
     */
     
    private final byte[] streamToBytes(InputStream In) throws java.sql.SQLException
    {
	byte[] bi=new byte[128*1024];
	ByteArrayOutputStream BytesOut = new ByteArrayOutputStream();
	int bc = readblock(In,bi);
 
	BytesOut.write('\'');
   
	while (bc > 0) {
	    escapeblock(bi,BytesOut,bc);
	    bc = readblock(In,bi);
	}
   
	BytesOut.write('\'');
   
	return BytesOut.toByteArray();
    }

    private final char getSuccessor(char c,int n) 
    {
	return  (c=='y' && n==2) ? 'X' : //ym
	    ((c=='y' && n<4) ? 'y' :
	     ((c=='y') ? 'M' :
	      ((c=='M' && n==2) ? 'Y' : //Md
	       ((c=='M' && n<3) ? 'M' :
		((c=='M') ? 'd' :
		 ((c=='d' && n<2) ? 'd' :
		  ((c=='d') ? 'h' :
		   ((c=='h' && n<2) ? 'h' :
		    ((c=='h') ? 'm' :
		     ((c=='m' && n<2) ? 'm' :
		      ((c=='m') ? 's' :
		       ((c=='s' && n<2) ? 's' : 'W' ))))))))))));
    }

    private final String getDateTimePattern(String dt,boolean toTime) throws Exception 
    {
	int n,z,count,maxvecs;
	char c,separator;
	StringReader reader=new StringReader(dt+" ");
	Vector vec=new Vector();
	Vector vec_removelist=new Vector();
	Object[] nv=new Object[3];
	Object[] v;
	nv[0]=new Character('y');
	nv[1]=new StringBuffer();
	nv[2]=new Integer(0);
	vec.addElement(nv);
	if (toTime) {
	    nv=new Object[3];
	    nv[0]=new Character('h');
	    nv[1]=new StringBuffer();
	    nv[2]=new Integer(0);
	    vec.addElement(nv);
	}
	while ((z=reader.read())!=-1) {
	    separator=(char)z;
	    maxvecs=vec.size();
	    for(count=0;count<maxvecs;count++) {
		v=(Object [])vec.elementAt(count);
		n=((Integer)v[2]).intValue();
		c = getSuccessor(((Character)v[0]).charValue(),n);
		if (!Character.isLetterOrDigit(separator)) {
		    if ((c==((Character)v[0]).charValue())&&(c!='S'))
			vec_removelist.addElement(v);
		    else {
			((StringBuffer)v[1]).append(separator);
			if (c=='X' || c=='Y')
			    v[2]=new Integer(4);
		    }
		} else {
		    if (c=='X') {
			c='y';
			nv=new Object[3];
			nv[1]=(new StringBuffer(((StringBuffer)v[1]).toString())).append('M');
			nv[0]=new Character('M');
			nv[2]=new Integer(1);
			vec.addElement(nv);
		    } else if (c=='Y') {
			c='M';
			nv=new Object[3];
			nv[1]=(new StringBuffer(((StringBuffer)v[1]).toString())).append('d');
			nv[0]=new Character('d');
			nv[2]=new Integer(1);
			vec.addElement(nv);
		    }
		    ((StringBuffer)v[1]).append(c);
			
		    if (c==((Character)v[0]).charValue())
			v[2]=new Integer(n+1);
		    else {
			v[0]=new Character(c);
			v[2]=new Integer(1);
		    }
		}
	    }
	    for(Enumeration en=vec_removelist.elements();
		en.hasMoreElements();) {
		v=(Object [])en.nextElement();
		vec.removeElement(v);
	    }
	    vec_removelist.removeAllElements();
	}
	for(Enumeration en=vec.elements();en.hasMoreElements();) {
	    v=(Object [])en.nextElement();
	    c=((Character)v[0]).charValue();
	    n=((Integer)v[2]).intValue();
	    boolean bk=getSuccessor(c,n)!=c;
	    boolean atEnd=((c=='s'||c=='m'||(c=='h' && toTime))&&bk);
	    boolean finishesAtDate=(bk&&(c=='d')&& !toTime);
	    boolean containsEnd=(((StringBuffer)v[1]).toString().indexOf('W')!=-1);
	    if ((!atEnd && !finishesAtDate) || (containsEnd)) {
		vec_removelist.addElement(v);
	    }
	}
	for(Enumeration en=vec_removelist.elements();en.hasMoreElements();)
	    vec.removeElement(en.nextElement());
	vec_removelist.removeAllElements();
	v=(Object [])vec.firstElement(); //might throw exception
	StringBuffer format=((StringBuffer)v[1]);
	format.setLength(format.length()-1);
	return format.toString();
    }
  
    /**
     * Formatter for double - Steve Ferguson
     */
  
    private static NumberFormat _DoubleFormatter; 
 
    // Class Initializer
	
    static {
	_DoubleFormatter = 
	    NumberFormat.getNumberInstance(java.util.Locale.US);
	_DoubleFormatter.setGroupingUsed(false);
	// attempt to prevent truncation
	_DoubleFormatter.setMaximumFractionDigits(8); 
    }
};
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.