⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 preparedstatement_base.java

📁 Java写的TDS协议(JDBC/ODBC)实现
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
//
// Copyright 1998,1999 CDS Networks, Inc., Medford Oregon
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
// 3. All advertising materials mentioning features or use of this software
//    must display the following acknowledgement:
//      This product includes software developed by CDS Networks, Inc.
// 4. The name of CDS Networks, Inc.  may not be used to endorse or promote
//    products derived from this software without specific prior
//    written permission.
//
// THIS SOFTWARE IS PROVIDED BY CDS NETWORKS, INC. ``AS IS'' AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.  IN NO EVENT SHALL CDS NETWORKS, INC. BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//


package net.sourceforge.jtds.jdbc;

import java.math.BigDecimal;
import java.sql.*;
import java.util.Map;

/**
 * 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>
 * <B>Note:</B> 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.
 *
 * @author     Craig Spannring
 * @author     The FreeTDS project
 * @author     Alin Sinpalean
 * @version    $Id: PreparedStatement_base.java,v 1.3 2002/10/18 15:21:07 alin_sinpalean Exp $
 * @see        Connection#prepareStatement
 * @see        ResultSet
 */
public class PreparedStatement_base extends TdsStatement implements PreparedStatementHelper, java.sql.PreparedStatement
{
    public final static String cvsVersion = "$Id: PreparedStatement_base.java,v 1.3 2002/10/18 15:21:07 alin_sinpalean Exp $";

    String rawQueryString = null;
    ParameterListItem[] parameterList = null;
    static Map typemap = null;

    public PreparedStatement_base(TdsConnection conn_, String sql) throws SQLException
    {
        this( conn_, sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY );
    }

    public PreparedStatement_base(TdsConnection conn_, String sql, int type, int concurrency ) throws SQLException
    {
        super( conn_, type, concurrency );

        rawQueryString = conn_.nativeSQL(sql);

        int i;
        int numberOfParameters = ParameterUtils.countParameters( rawQueryString );

        parameterList = new ParameterListItem[numberOfParameters];

        for ( i = 0; i < numberOfParameters; i++ )
            parameterList[i] = new ParameterListItem();
    }

    protected void NotImplemented() throws java.sql.SQLException
    {
        throw new SQLException( "Not Implemented" );
    }

    /**
     * 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 clearParameters.
     *
     * @exception  SQLException  if a database-access error occurs.
     */
    public void clearParameters() throws SQLException
    {
        int i;
        for ( i = 0; i < parameterList.length; i++ ) {
            parameterList[i].clear();
        }
    }

    public boolean execute() throws SQLException
    {
        Tds tds = getTds(false);
        return execute( tds );
    }

    /**
     *  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.
     *
     *@exception  SQLException  if a database-access error occurs.
     *@see                      Statement#execute
     */
    public boolean execute( Tds tds ) throws SQLException
    {
        //
        // TDS can handle prepared statements by creating a temporary
        // procedure.  Since procedure must have the datatype specified
        // in the procedure declaration we will have to defer creating
        // the actual procedure until the statement is executed.  By
        // that time we know all the types of all of the parameters.
        //

        Procedure procedure = null;
        boolean result = false;

        // SAfe No need for this either. We'll have to consume all input, nut
        //      just the last ResultSet (if one exists).
//        closeResults(false);
        // SAfe No need for this. getMoreResults sets it to -1 at start, anyway
//        updateCount = -2;

        // First make sure the caller has filled in all the parameters.
        ParameterUtils.verifyThatParametersAreSet( parameterList );

        // Find a stored procedure that is compatible with this set of parameters if one exists.
        procedure = findCompatibleStoredProcedure( tds, rawQueryString );
        // now look in tds

        // if we don't have a suitable match then create a new temporary stored procedure
        if( procedure == null )
        {
            // Create the stored procedure
            procedure = new Procedure( rawQueryString, tds.getUniqueProcedureName(), parameterList, tds );

            // SAfe Submit it to the SQL Server before adding it to the cache or procedures of transaction list.
            //      Otherwise, if submitProcedure fails (e.g. because of a syntax error) it will be in our procedure
            //      cache, but not on the server.
            submitProcedure( tds, procedure );

            // store it in the procedureCache
            tds.procedureCache.put( rawQueryString, procedure );

            // MJH Only record the proc name in proceduresOfTra if in manual commit mode
            if( !getConnection().getAutoCommit() ) // MJH
                tds.proceduresOfTra.add( procedure );
        }

        result = internalExecuteCall(procedure.getProcedureName(), procedure.getParameterList(), parameterList, tds,
            warningChain);

        return result;
    }

    private Procedure findCompatibleStoredProcedure( Tds tds, String rawQueryString )
    {
        return (Procedure)tds.procedureCache.get(rawQueryString);
    }

    private void submitProcedure( Tds tds, Procedure proc )
             throws SQLException
    {
        String sql = proc.getPreparedSqlString();
        tds.submitProcedure( sql, warningChain );
    }

    /**
     * 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  SQLException  if a database-access error occurs.
     */
    public java.sql.ResultSet executeQuery() throws SQLException
    {
//        closeResults(false);

        Tds tds = getTds(false);

        if( !execute(tds) )
        {
            skipToEnd();
            releaseTds();
            throw new SQLException( "Was expecting a result set" );
        }

        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  SQLException  if a database-access error occurs.
     */
    public int executeUpdate() throws SQLException
    {
//        closeResults(false);

        Tds tds = getTds(false);
        if ( execute( tds ) ) {
            skipToEnd();
            releaseTds();
            throw new SQLException( "executeUpdate can't return a result set" );
        }
        else {
            int res = getUpdateCount();
            releaseTds();
            return res;
        }
    }


    /**
     *  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>
     *
     *  <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 ASCII
     *      parameter value
     *@param  length            the number of bytes in the stream
     *@exception  SQLException  if a database-access error occurs.
     */
    public void setAsciiStream( int parameterIndex,
            java.io.InputStream x,
            int length )
             throws SQLException
    {
        NotImplemented();
    }


    /**
     *  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, the second is 2, ...
     *@param  x                 the parameter value
     *@exception  SQLException  if a database-access error occurs.
     */
    public void setBigDecimal( int parameterIndex, BigDecimal x ) throws SQLException
    {
        setParam( parameterIndex, x, java.sql.Types.DECIMAL, -1 );
    }


    /**
     *  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>
     *
     *  <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
     *@exception  SQLException  if a database-access error occurs.
     */
    public void setBinaryStream( int parameterIndex,
            java.io.InputStream x,
            int length )
             throws SQLException
    {
        if ( length == 0 ) {
            setBytes( parameterIndex, null );
        }
        byte[] bs = new byte[length];
        int actlen;
        try {
            actlen = x.read( bs );
        }
        catch ( java.io.IOException e ) {
            SQLException newE = new SQLException( "setBinaryStream: IO-Exception occured reading Stream" + e.toString() );
            throw newE;
        }
        if ( actlen != length ) {
            throw new SQLException( "SetBinaryStream parameterized Length: " + Integer.toString( length ) + " got length: " + Integer.toString( actlen ) );
        }
        else {
            try {
                actlen = x.read( bs );
            }
            catch ( java.io.IOException e ) {
                SQLException newE = new SQLException( "setBinaryStream: IO-Exception occured reading Stream" + e.toString() );
                throw newE;
            }
            if ( actlen != -1 ) {
                throw new SQLException( "SetBinaryStream parameterized Length: " + Integer.toString( length ) + " got more than that " );
            }
        }
        this.setBytes( parameterIndex, bs );
    }


    /**
     *  Set a parameter to a Java boolean value. The driver converts this to a

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -