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

📄 jtdsstatement.java

📁 jtds的源码 是你学习java的好东西
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
     * Implements the common functionality for plain statement {@link #execute}
     * and {#link #executeUpdate}: basic checks, cleaning up of previous
     * results, setting up and executing the query and loading the first
     * results.
     *
     * @param sql    an SQL <code>INSERT</code>, <code>UPDATE</code> or
     *               <code>DELETE</code> statement or an SQL statement that
     *               returns nothing, such as an SQL DDL statement
     * @param autoGeneratedKeys a flag indicating whether auto-generated keys
     *               should be made available for retrieval
     * @param update boolean flag indicating whether the caller is
     *               {@link #executeUpdate} -- in this case an exception is
     *               thrown if the first result is not an update count and no
     *               cursor is created (direct execution)
     * @return <code>true</code> if the first result is a
     *         <code>ResultSet</code>, <code>false</code> if it's an update
     *         count
     * @see #execute
     * @see #executeUpdate
     */
    private boolean executeImpl(String sql, int autoGeneratedKeys, boolean update)
            throws SQLException {
        initialize();

        if (sql == null || sql.length() == 0) {
            throw new SQLException(Messages.get("error.generic.nosql"), "HY000");
        }

        boolean returnKeys;
        String sqlWord = "";
        if (escapeProcessing) {
            String tmp[] = SQLParser.parse(sql, null, connection, false);

            if (tmp[1].length() != 0) {
                throw new SQLException(
                        Messages.get("error.statement.badsql"), "07000");
            }

            sql = tmp[0];
            sqlWord = tmp[2];
        } else {
            // Escape processing turned off so
            // see if we can extract "insert" from start of statement
            sql = sql.trim();
            if (sql.length() > 5) {
                sqlWord = sql.substring(0,6).toLowerCase();
            }
        }

        if (autoGeneratedKeys == RETURN_GENERATED_KEYS) {
            returnKeys = "insert".equals(sqlWord);
        } else if (autoGeneratedKeys == NO_GENERATED_KEYS) {
            returnKeys = false;
        } else {
            throw new SQLException(
                    Messages.get("error.generic.badoption",
                            Integer.toString(autoGeneratedKeys),
                            "autoGeneratedKeys"),
                    "HY092");
        }

        if (returnKeys) {
            if (connection.getServerType() == Driver.SQLSERVER
                    && connection.getDatabaseMajorVersion() >= 8) {
                sql += " SELECT SCOPE_IDENTITY() AS ID";
            } else {
                sql += " SELECT @@IDENTITY AS ID";
            }
        }

        return executeSQL(sql, null, null, returnKeys, update,
                !update && useCursor(returnKeys, sqlWord));
    }

    /**
     * Determines whether a cursor should be used based on the requested result
     * set type and concurrency, whether a cursor name has been set, the
     * <code>useCursors</code> connection property has been set, the first
     * word in the SQL query is either SELECT or EXEC/EXECUTE and no generated
     * keys are returned.
     *
     * @param returnKeys indicates whether keys will be returned by the query
     * @param sqlWord    the first word in the SQL query; can be
     *                   <code>null</code> if the caller is
     *                   {@link #executeQuery}
     * @return <code>true</code> if a cursor should be used, <code>false</code>
     *         if not
     */
    protected boolean useCursor(boolean returnKeys, String sqlWord) {
        return (resultSetType != ResultSet.TYPE_FORWARD_ONLY
                    || resultSetConcurrency != ResultSet.CONCUR_READ_ONLY
                    || connection.getUseCursors()
                    || cursorName != null)
                && !returnKeys
                && (sqlWord == null || "select".equals(sqlWord) || sqlWord.startsWith("exec"));
    }

    /**
     * Retrieve the default fetch size for this statement.
     *
     * @return the default fetch size for a new <code>ResultSet</code>
     */
    int getDefaultFetchSize() {
        return (0 < this.maxRows && this.maxRows < DEFAULT_FETCH_SIZE)
                ? this.maxRows : DEFAULT_FETCH_SIZE;
    }

// ------------------ java.sql.Statement methods ----------------------

    public int getFetchDirection() throws SQLException {
        checkOpen();

        return this.fetchDirection;
    }

    public int getFetchSize() throws SQLException {
        checkOpen();

        return this.fetchSize;
    }

    public int getMaxFieldSize() throws SQLException {
        checkOpen();

        return this.maxFieldSize;
    }

    public int getMaxRows() throws SQLException {
        checkOpen();

        return this.maxRows;
    }

    public int getQueryTimeout() throws SQLException {
        checkOpen();

        return this.queryTimeout;
    }

    public int getResultSetConcurrency() throws SQLException {
        checkOpen();

        return this.resultSetConcurrency;
    }

    public int getResultSetHoldability() throws SQLException {
        checkOpen();

        return JtdsResultSet.HOLD_CURSORS_OVER_COMMIT;
    }

    public int getResultSetType() throws SQLException {
        checkOpen();

        return resultSetType;
    }

    public int getUpdateCount() throws SQLException {
        checkOpen();

        return updateCount;
    }

    public void cancel() throws SQLException {
        checkOpen();

        if (tds != null) {
            tds.cancel(false);
        }
    }

    public void clearBatch() throws SQLException {
        checkOpen();

        if (batchValues != null) {
            batchValues.clear();
        }
    }

    public void clearWarnings() throws SQLException {
        checkOpen();

        messages.clearWarnings();
    }

    public void close() throws SQLException {
        if (!closed) {
            SQLException closeEx = null;
            try {
                closeAllResultSets();
            } catch (SQLException ex) {
                if (!"HYT00".equals(ex.getSQLState())
                        && !"HY008".equals(ex.getSQLState())) {
                    // Only throw exceptions not caused by cancels or timeouts
                    closeEx = ex;
                }
            } finally {
                SQLException releaseEx = null;
                try {
                    if (!connection.isClosed()) {
                        connection.releaseTds(tds);
                    }
                    // Check for server side errors
                    tds.getMessages().checkErrors();
                } catch (SQLException ex) {
                    // Remember any exception thrown
                    releaseEx = ex;
                    // Queue up any result set close exceptions
                    if (closeEx != null) {
                        releaseEx.setNextException(closeEx);
                    }
                } finally {
                    // Clean up everything
                    closed = true;
                    tds = null;
                    connection.removeStatement(this);
                    connection = null;

                    // Re-throw any caught exception
                    if (releaseEx != null) {
                        throw releaseEx;
                    }
                }
            }
            // Throw any exception caught during result set close
            if (closeEx != null) {
                throw closeEx;
            }
        }
    }

    public boolean getMoreResults() throws SQLException {
        checkOpen();

        return getMoreResults(CLOSE_ALL_RESULTS);
    }

    /**
     * Execute batch of SQL Statements.
     * <p/>
     * The JDBC3 standard says that the behaviour of this method must be
     * consistent for any DBMS. As Sybase (and to a lesser extent SQL Server)
     * will sometimes continue after a batch execution error, the only way to
     * comply with the standard is to always return an array of update counts
     * the same size as the batch list. Slots in the array beyond the last
     * executed statement are set to <code>EXECUTE_FAILED</code>.
     *
     * @return update counts as an <code>int[]</code>
     */
    public int[] executeBatch()
            throws SQLException, BatchUpdateException {
        checkOpen();
        initialize();

        if (batchValues == null || batchValues.size() == 0) {
            return new int[0];
        }

        int size = batchValues.size();
        int executeSize = connection.getBatchSize();
        executeSize = (executeSize == 0) ? Integer.MAX_VALUE : executeSize;
        SQLException sqlEx;
        ArrayList counts = new ArrayList(size);

        try {
            // Lock the connection, making sure the batch executes atomically. This is especially important in the
            // case of prepared statement batches (where we don't want the prepares rolled back before being executed)
            // but should also provide some level of sanity in the general case.
            synchronized (connection) {
                if (connection.getServerType() == Driver.SYBASE
                    && connection.getTdsVersion() == Driver.TDS50) {
                    sqlEx = executeSybaseBatch(size, executeSize, counts);
                } else {
                    sqlEx = executeMSBatch(size, executeSize, counts);
                }
            }

            // Ensure array is the same size as the original statement list
            int updateCounts[] = new int[size];
            // Copy the update counts into the int array
            int results = counts.size();
            for (int i = 0; i < results; i++) {
                updateCounts[i] = ((Integer) counts.get(i)).intValue();
            }
            // Pad any remaining slots with EXECUTE_FAILED
            for (int i = results; i < updateCounts.length; i++) {
                updateCounts[i] = EXECUTE_FAILED.intValue();
            }

            // See if we should return an exception
            if (sqlEx != null) {
                BatchUpdateException batchEx =
                        new BatchUpdateException(sqlEx.getMessage(),
                                                 sqlEx.getSQLState(),
                                                 sqlEx.getErrorCode(),
                                                 updateCounts);
                // Chain any other exceptions
                batchEx.setNextException(sqlEx.getNextException());
                throw batchEx;
            }
            return updateCounts;
        } catch (BatchUpdateException ex) {
            // If it's a BatchUpdateException let it go
            throw ex;
        } catch (SQLException ex) {
            // An SQLException can only occur while sending the batch
            // (getBatchCounts() doesn't throw SQLExceptions), so we have to
            // end the batch and return the partial results
            // FIXME What should we send here to flush out the batch?
            // Come to think of it, is there any circumstance under which this
            // could actually happen without the connection getting closed?
            // No counts will have been returned either as last packet will not
            // have been sent.
            throw new BatchUpdateException(ex.getMessage(), ex.getSQLState(),
                    ex.getErrorCode(), new int[0]);
        } finally {
            clearBatch();
        }
    }

    public void setFetchDirection(int direction) throws SQLException {
        checkOpen();
        switch (direction) {
        case ResultSet.FETCH_UNKNOWN:
        case ResultSet.FETCH_REVERSE:
        case ResultSet.FETCH_FORWARD:

⌨️ 快捷键说明

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