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

📄 tdsstatement.java

📁 Java写的TDS协议(JDBC/ODBC)实现
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
//
// Copyright 1998 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.
//



/**
 * A Statement object is used for executing a static SQL statement and
 * obtaining the results produced by it.
 *
 * <p>Only one ResultSet per Statement can be open at any point in time.
 * Therefore, if the reading of one ResultSet is interleaved with the
 * reading of another, each must have been generated by different
 * Statements.  All statement execute methods implicitly close a
 * statement's current ResultSet if an open one exists.
 *
 * @see java.sql.Statement
 * @see ResultSet
 * @version $Id: TdsStatement.java,v 1.4 2002/10/22 11:22:51 alin_sinpalean Exp $
 */
package net.sourceforge.jtds.jdbc;

import java.sql.*;


public class TdsStatement implements java.sql.Statement
{
    public static final String cvsVersion = "$Id: TdsStatement.java,v 1.4 2002/10/22 11:22:51 alin_sinpalean Exp $";

    private TdsConnection connection; // The connection that created us

    SQLWarningChain warningChain; // The warning chain
    TdsResultSet results = null;

    private Tds actTds = null;
    private boolean escapeProcessing = true;

    private int updateCount  = -1;
    private int maxFieldSize = (1<<31)-1;
    private int maxRows      = 0;
    private int timeout      = 0; // The timeout for a query
    private int fetchSize    = AbstractResultSet.DEFAULT_FETCH_SIZE;
    private int fetchDir     = ResultSet.FETCH_FORWARD;

    private int type = ResultSet.TYPE_FORWARD_ONLY;
    private int concurrency = ResultSet.CONCUR_READ_ONLY;

    private boolean isClosed = false;

    public TdsStatement(TdsConnection con, int type, int concurrency)
        throws SQLException
    {
        this.connection = con;
        this.warningChain = new SQLWarningChain();
        this.type = type;
        this.concurrency = concurrency;
    }

    /**
     * Constructor for a Statement.  It simply sets the connection
     * that created us.
     *
     * @param  con  the Connection instance that creates us
     */
    public TdsStatement(TdsConnection con)
        throws SQLException
    {
        this(con, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
    }

    /**
     * Releases <code>actTds</code> IF there are no outstanding results.
     */
    protected synchronized void releaseTds() throws SQLException
    {
        // MJH remove test of autoCommit
        if( actTds == null )
            return;

        // Don't free the Tds if there are any results left.
        /** @todo Check if this is correct in case an IOException occurs */
        if( actTds.moreResults() )
            return;

        try
        {
            connection.freeTds(actTds);
            actTds = null;
        }
        catch (TdsException e)
        {
            throw new SQLException("Confusion in freeing Tds: " + e);
        }
    }

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

    /**
     * Execute an SQL statement that returns a single <code>ResultSet</code>.
     *
     * @param sql typically a static SQL SELECT statement
     * @return    a <code>ResultSet</code> that contains the data produced by
     *            the query; never <code>null</code>
     * @exception SQLException if a database access error occurs
     */
    public synchronized ResultSet executeQuery(String sql) throws SQLException
    {
        checkClosed();

        if( type == ResultSet.TYPE_FORWARD_ONLY &&
            concurrency == ResultSet.CONCUR_READ_ONLY )
        {
            if( internalExecute(sql) )
                return results;
            else
                throw new SQLException("No ResultSet was produced.");
        }
        else
            return new CursorResultSet(this, sql, fetchDir);
    }

    /**
     * This is the internal function that all subclasses should call.
     * It is not executeQuery() to allow subclasses (in particular
     * CursorResultSet) to override that functionality without
     * breaking the internal methods.
     *
     * @param sql any SQL statement
     * @return true if the next result is a ResulSet, false if it is
     *      an update count or there are no more results
     * @exception SQLException if a database access error occurs
     */
    public final synchronized boolean internalExecute(String sql) throws SQLException
    {
        checkClosed();
        return executeImpl(getTds(false), sql, warningChain);
    }

    public final synchronized boolean internalExecute(String sql, Tds tds, SQLWarningChain wChain) throws SQLException
    {
        checkClosed();
        return executeImpl(tds, sql, wChain);
    }

    private final boolean executeImpl(Tds tds, String sql, SQLWarningChain wChain)
        throws SQLException
    {
        // Clear warnings, otherwise the last exception will be thrown.
        wChain.clearWarnings();
        updateCount = -1;

        // Consume all outstanding results. Otherwise it will either deadlock,
        // crash or return results from the previous query.
        skipToEnd();

        try
        {
            if( escapeProcessing )
                sql = Tds.toNativeSql(sql, tds.getServerType());

            tds.executeQuery(sql, this, wChain, timeout);
        }
        catch(java.io.IOException e)
        {
            throw new SQLException("Network error: " + e.getMessage());
        }
        catch(net.sourceforge.jtds.jdbc.TdsException e)
        {
            throw new SQLException("TDS error: " + e.getMessage());
        }

        // SAfe We must do this to ensure we throw SQLExceptions on timed out
        //      statements
        wChain.checkForExceptions();

        return getMoreResults(tds, wChain, true);
    }

    public final synchronized boolean internalExecuteCall(String name, ParameterListItem[] formalParameterList,
        ParameterListItem[] actualParameterList, Tds tds, SQLWarningChain wChain) throws SQLException
    {
        checkClosed();
        return executeCallImpl(tds, name, formalParameterList, actualParameterList, wChain);
    }

    private boolean executeCallImpl(Tds tds, String name, ParameterListItem[] formalParameterList,
        ParameterListItem[] actualParameterList, SQLWarningChain wChain) throws SQLException
    {
        wChain.clearWarnings();
        // SAfe This is where all outstanding results must be skipped, to make
        //      sure they don't interfere with the the current ones.
        skipToEnd();

        boolean result;

        try {
            // execute the stored procedure.
            tds.executeProcedure(name, formalParameterList, actualParameterList, this, wChain, getQueryTimeout());

            result = getMoreResults(tds, warningChain, true);
        }
        catch ( TdsException e ) {
            throw new SQLException( e.toString() );
        }
        catch ( java.io.IOException e ) {
            throw new SQLException( e.toString() );
        }
        finally {
            tds.comm.packetType = 0;
        }

        return result;
    }

    /**
     * Execute a SQL INSERT, UPDATE or DELETE statement.  In addition
     * SQL statements that return nothing such as SQL DDL statements
     * can be executed
     *
     * Any IDs generated for AUTO_INCREMENT fields can be retrieved
     * by looking through the SQLWarning chain of this statement
     * for warnings of the form "LAST_INSERTED_ID = 'some number',
     * COMMAND = 'your sql'".
     *
     * @param  sql  an SQL statement
     * @return      either a row count, or 0 for SQL commands
     * @exception SQLException if a database access error occurs
     */

    public synchronized int executeUpdate(String sql) throws SQLException
    {
        checkClosed();

        if( internalExecute(sql) )
        {
            skipToEnd();
            throw new SQLException("executeUpdate can't return a result set");
        }
        else
        {
            int res = getUpdateCount();
            // We should return 0 (at least that's what the javadoc above says)
            return res==-1 ? 0 : res;
        }
    }

    protected synchronized void closeResults(boolean allowTdsRelease)
        throws java.sql.SQLException
    {
        if( results != null )
        {
            results.close(allowTdsRelease);
            results = null;
        }
    }

    /**
     * Eats all available input from the server. Not very efficient (since it
     * reads in all data by creating <code>ResultSets</code> and processing
     * them), but at least it works (the old version would crash when reading in
     * a row because it didn't have any information about the row's Context).
     * <p>
     * This could be changed to use the <code>TdsComm</code> to read in all the
     * server response without processing it, but that requires some changes in
     * <code>TdsComm</code>, too.
     */
    protected synchronized void skipToEnd() throws java.sql.SQLException
    {
        if( actTds != null )
        {
            // SAfe This is the only place we should send a CANCEL packet
            //      ourselves. We can't do that in Tds.discardResultSet because
            //      we could cancel other results when what we want is to only
            //      close the ResultSet in order to get the other results.

            // SAfe On a second thought, we'd better not cancel the execution.
            //      Someone could run a big update script and not process all
            //      the results, thinking that as long as there were no
            //      exceptions, all went right, but we would cancel the script.
            //      Anyway, this was a good test for the cancel mechanism. :o)
//            try
//            {
//                if( actTds.moreResults() )
//                    actTds.cancel();
//            }
//            catch( java.io.IOException ex )
//            {
//                throw new SQLException(ex.toString());
//            }
//            catch( TdsException ex )
//            {
//                throw new SQLException(ex.toString());

⌨️ 快捷键说明

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