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

📄 jtdsstatement.java

📁 jtds的源码 是你学习java的好东西
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
// jTDS JDBC Driver for Microsoft SQL Server and Sybase
// Copyright (C) 2004 The jTDS Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser 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
//
package net.sourceforge.jtds.jdbc;

import java.sql.BatchUpdateException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Types;
import java.util.ArrayList;
import java.util.LinkedList;

/**
 * jTDS implementation of the java.sql.Statement interface.<p>
 * NB. As allowed by the JDBC standard and like most other drivers,
 * this implementation only allows one open result set at a time.
 * <p>
 * Implementation notes:
 * <p>
 * I experimented with allowing multiple open result sets as supported
 * by the origianal jTDS but rejected this approach for the following
 * reasons:
 * <ol>
 * <li>It is more difficult to ensure that there are no memory leaks and that
 *     cursors are closed if multiple open sets are allowed.
 * <li>The use of one result set allows cursor and non cursor result sets to
 *     be derived from exeuteQuery() or execute() and getResultSet() in the
 *     same way that other drivers do.
 * </ol>
 * In the event of an IO failure the setClosed() method forces this statement
 * and associated result set to close preventing the propogation of errors.
 * This class includes a finalize method which increases the chances of the
 * statement being closed tidly in a pooled environment where the user has
 * forgotten to explicitly close the statement before it goes out of scope.
 *
 * @see java.sql.Statement
 * @see java.sql.Connection#createStatement()
 * @see java.sql.ResultSet
 *
 * @author Mike Hutchinson
 * @version $Id: JtdsStatement.java,v 1.64 2007/07/12 21:03:23 bheineman Exp $
 */
public class JtdsStatement implements java.sql.Statement {
    /*
     * Constants used for backwards compatibility with JDK 1.3
     */
    static final int RETURN_GENERATED_KEYS = 1;
    static final int NO_GENERATED_KEYS = 2;
    static final int CLOSE_CURRENT_RESULT = 1;
    static final int KEEP_CURRENT_RESULT = 2;
    static final int CLOSE_ALL_RESULTS = 3;
    static final int BOOLEAN = 16;
    static final int DATALINK = 70;
    static final Integer SUCCESS_NO_INFO = new Integer(-2);
    static final Integer EXECUTE_FAILED = new Integer(-3);
    static final int DEFAULT_FETCH_SIZE = 100;

    /** The connection owning this statement object. */
    protected ConnectionJDBC2 connection;
    /** The TDS object used for server access. */
    protected TdsCore tds;
    /** The read query timeout in seconds */
    protected int queryTimeout;
    /** The current <code>ResultSet</code>. */
    protected JtdsResultSet currentResult;
    /** The current update count. */
    private int updateCount = -1;
    /** The fetch direction for result sets. */
    protected int fetchDirection = ResultSet.FETCH_FORWARD;
    /** The type of result sets created by this statement. */
    protected int resultSetType = ResultSet.TYPE_FORWARD_ONLY;
    /** The concurrency of result sets created by this statement. */
    protected int resultSetConcurrency = ResultSet.CONCUR_READ_ONLY;
    /** The fetch size (default 100, only used by cursor
     * <code>ResultSet</code>s).
     */
    protected int fetchSize = DEFAULT_FETCH_SIZE;
    /** The cursor name to be used for positioned updates. */
    protected String cursorName;
    /** True if this statement is closed. */
    protected boolean closed;
    /** The maximum field size (not used at present). */
    protected int maxFieldSize;
    /** The maximum number of rows to return (not used at present). */
    protected int maxRows;
    /** True if SQL statements should be preprocessed. */
    protected boolean escapeProcessing = true;
    /** SQL Diagnostic exceptions and warnings. */
    protected final SQLDiagnostic messages;
    /** Batched SQL Statement array. */
    protected ArrayList batchValues;
    /** Dummy result set for getGeneratedKeys. */
    protected JtdsResultSet genKeyResultSet;
    /**
     * List of queued results (update counts, possibly followed by a
     * <code>ResultSet</code>).
     */
    protected final LinkedList resultQueue = new LinkedList();
    /** List of open result sets. */
    protected ArrayList openResultSets;
    /** The cached column meta data. */
    protected ColInfo[] colMetaData;

    /**
     * Construct a new Statement object.
     *
     * @param connection The parent connection.
     * @param resultSetType The result set type for example TYPE_FORWARD_ONLY.
     * @param resultSetConcurrency The concurrency for example CONCUR_READ_ONLY.
     */
    JtdsStatement(ConnectionJDBC2 connection,
                  int resultSetType,
                  int resultSetConcurrency) throws SQLException {
        //
        // This is a good point to do common validation of the result set type
        //
        if (resultSetType < ResultSet.TYPE_FORWARD_ONLY
                || resultSetType > ResultSet.TYPE_SCROLL_SENSITIVE + 1) {
            String method;
            if (this instanceof JtdsCallableStatement) {
                method = "prepareCall";
            } else if (this instanceof JtdsPreparedStatement) {
                method = "prepareStatement";
            } else {
                method = "createStatement";
            }
            throw new SQLException(
                       Messages.get("error.generic.badparam",
                               "resultSetType",
                               method),
                    "HY092");
        }
        //
        // Ditto for the result set concurrency
        //
        if (resultSetConcurrency < ResultSet.CONCUR_READ_ONLY
                || resultSetConcurrency > ResultSet.CONCUR_UPDATABLE + 2) {
                String method;
                if (this instanceof JtdsCallableStatement) {
                    method = "prepareCall";
                } else if (this instanceof JtdsPreparedStatement) {
                    method = "prepareStatement";
                } else {
                    method = "createStatement";
                }
                throw new SQLException(
                        Messages.get("error.generic.badparam",
                                "resultSetConcurrency",
                                method),
                        "HY092");
        }

        this.connection = connection;
        this.resultSetType = resultSetType;
        this.resultSetConcurrency = resultSetConcurrency;

        this.tds = connection.getCachedTds();
        if (this.tds == null) {
            this.messages = new SQLDiagnostic(connection.getServerType());
            this.tds = new TdsCore(this.connection, messages);
        } else {
            this.messages = tds.getMessages();
        }
    }

    /**
     * Called when this object goes out of scope to close any
     * <code>ResultSet</code> object and this statement.
     */
    protected void finalize() throws Throwable {
        super.finalize();
        try {
            close();
        } catch (SQLException e) {
            // Ignore errors
        }
    }

    /**
     * Get the Statement's TDS object.
     *
     * @return The TDS support as a <code>TdsCore</core> Object.
     */
    TdsCore getTds() {
        return tds;
    }

    /**
     * Get the statement's warnings list.
     *
     * @return The warnings list as a <code>SQLDiagnostic</code>.
     */
    SQLDiagnostic getMessages() {
        return messages;
    }

    /**
     * Check that this statement is still open.
     *
     * @throws SQLException if statement closed.
     */
    protected void checkOpen() throws SQLException {
        if (closed || connection == null || connection.isClosed()) {
            throw new SQLException(
                    Messages.get("error.generic.closed", "Statement"), "HY010");
        }
    }

    /**
     * Check that the exception is caused by the failure to open a
     * cursor and not by a more serious SQL error.
     *
     * @param e the exception returned by the cursor class
     * @throws SQLException if exception is not due to a cursor error
     */
    protected void checkCursorException(SQLException e) throws SQLException{
        if (connection == null
                || connection.isClosed()
                || "HYT00".equals(e.getSQLState())
                || "HY008".equals(e.getSQLState())) {
                // Serious error or timeout so return exception to caller
                throw e;
            }
        if (connection.getServerType() == Driver.SYBASE) {
            // Allow retry for Sybase
            return;
        }
        //
        // Check cursor specific errors and ranges for SQL Server
        //
        int error = e.getErrorCode();
        if (error >= 16900 && error <= 16999) {
            // Errors in this range are all related to the cursor API.
            // This is true for all versions of SQL Server.
            return;
        }
        if (error == 6819) {
            // A FOR XML clause was found
            return;
        }
        if (error == 8654) {
            // A inrow textptr exists
            return;
        }
        if (error == 8162) {
            // Formal parameter '%.*ls' was defined as OUTPUT but the actual
            // parameter not declared OUTPUT. This happens when trying to
            // execute a stored procedure with output parameters via a cursor.
            return;
        }
        //
        // More serious error we should rethrow the error and
        // not allow the driver to re-execute sql.
        //
        throw e;
    }

    /**
     * Report that user tried to call a method which has not been implemented.
     *
     * @param method The method name to report in the error message.
     * @throws SQLException
     */
    static void notImplemented(String method) throws SQLException {
        throw new SQLException(
                Messages.get("error.generic.notimp", method), "HYC00");
    }

    /**
     * Close current result set (if any).
     */
    void closeCurrentResultSet() throws SQLException {
        try {
            if (currentResult != null) {
                currentResult.close();
            }
//        } catch (SQLException e) {
            // Ignore
        } finally {
            currentResult = null;
        }
    }

    /**
     * Close all result sets.
     */
    void closeAllResultSets() throws SQLException {
        try {
            if (openResultSets != null) {
                for (int i = 0; i < openResultSets.size(); i++) {
                    JtdsResultSet rs = (JtdsResultSet) openResultSets.get(i);
                    if (rs != null) {
                        rs.close();
                    }
                }
            }
            closeCurrentResultSet();
        } finally {
            openResultSets = null;
        }
    }

    /**
     * Add an SQLWarning object to the statment warnings list.
     *
     * @param w The SQLWarning to add.
     */
    void addWarning(SQLWarning w) {
        messages.addWarning(w);
    }

⌨️ 快捷键说明

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