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

📄 jtdsstatement.java

📁 jtds的源码 是你学习java的好东西
💻 JAVA
📖 第 1 页 / 共 4 页
字号:

    /**
     * Execute the SQL batch on a MS server.
     *
     * @param size the total size of the batch
     * @param executeSize the maximum number of statements to send in one request
     * @param counts the returned update counts
     * @return chained exceptions linked to a <code>SQLException</code>
     * @throws SQLException if a serious error occurs during execution
     */
    protected SQLException executeMSBatch(int size, int executeSize, ArrayList counts) throws SQLException {
        SQLException sqlEx = null;
        for (int i = 0; i < size;) {
            Object value = batchValues.get(i);
            ++i;
            // Execute batch now if max size reached or end of batch
            boolean executeNow = (i % executeSize == 0) || i == size;

            tds.startBatch();
            tds.executeSQL((String) value, null, null, false, 0, -1, -1, executeNow);

            // If the batch has been sent, process the results
            if (executeNow) {
                sqlEx = tds.getBatchCounts(counts, sqlEx);

                // If a serious error then we stop execution now as count
                // is too small.
                if (sqlEx != null && counts.size() != i) {
                    break;
                }
            }
        }
        return sqlEx;
    }

    /**
     * Execute the SQL batch on a Sybase server.
     * <p/>
     * Sybase needs to have the SQL concatenated into one TDS language packet. This method will be overriden for
     * <code>PreparedStatements</code>.
     *
     * @param size the total size of the batch
     * @param executeSize the maximum number of statements to send in one request
     * @param counts the returned update counts
     * @return chained exceptions linked to a <code>SQLException</code>
     * @throws SQLException if a serious error occurs during execution
     */
    protected SQLException executeSybaseBatch(int size, int executeSize, ArrayList counts) throws SQLException {
        StringBuffer sql = new StringBuffer(size * 32); // Make buffer reasonable size
        SQLException sqlEx = null;

        for (int i = 0; i < size;) {
            Object value = batchValues.get(i);
            ++i;
            // Execute batch now if max size reached or end of batch
            boolean executeNow = (i % executeSize == 0) || i == size;

            sql.append((String) value).append(' ');

            if (executeNow) {
                tds.executeSQL(sql.toString(), null, null, false, 0, -1, -1, true);
                sql.setLength(0);
                // If the batch has been sent, process the results
                sqlEx = tds.getBatchCounts(counts, sqlEx);

                // If a serious error or a server error then we stop
                // execution now as count is too small.
                if (sqlEx != null && counts.size() != i) {
                    break;
                }
            }
        }
        return sqlEx;
    }

    /**
     * Executes SQL to obtain a result set.
     *
     * @param sql       the SQL statement to execute
     * @param spName    optional stored procedure name
     * @param params    optional parameters
     * @param useCursor whether a cursor should be created for the SQL
     * @return the result set generated by the query
     */
    protected ResultSet executeSQLQuery(String sql,
                                        String spName,
                                        ParamInfo[] params,
                                        boolean useCursor)
            throws SQLException {
        String warningMessage = null;

        //
        // Try to open a cursor result set if required
        //
        if (useCursor) {
            try {
                if (connection.getServerType() == Driver.SQLSERVER) {
                    currentResult =
                            new MSCursorResultSet(this,
                                    sql,
                                    spName,
                                    params,
                                    resultSetType,
                                    resultSetConcurrency);

                    return currentResult;
                } else {
                    // Use client side cursor for Sybase
                    currentResult =
                        new CachedResultSet(this,
                                sql,
                                spName,
                                params,
                                resultSetType,
                                resultSetConcurrency);

                    return currentResult;
                }
            } catch (SQLException e) {
                checkCursorException(e);
                warningMessage = '[' + e.getSQLState() + "] " + e.getMessage();
            }
        }

        //
        // Could not open a cursor (or was not requested) so try a direct select
        //
        if (spName != null
                && connection.getUseMetadataCache()
                && connection.getPrepareSql() == TdsCore.PREPARE
                && colMetaData != null
                && connection.getServerType() == Driver.SQLSERVER) {
            // There is cached meta data available for this
            // prepared statement
            tds.setColumns(colMetaData);
            tds.executeSQL(sql, spName, params, true, queryTimeout, maxRows,
                    maxFieldSize, true);
        } else {
            tds.executeSQL(sql, spName, params, false, queryTimeout, maxRows,
                    maxFieldSize, true);
        }

        // Update warning chain if cursor was downgraded before processing results
        if (warningMessage != null) {
            addWarning(new SQLWarning(
                    Messages.get("warning.cursordowngraded", warningMessage), "01000"));
        }

        // Ignore update counts preceding the result set. All drivers seem to
        // do this.
        while (!tds.getMoreResults() && !tds.isEndOfResponse());

        // check for server side errors
        messages.checkErrors();

        if (tds.isResultSet()) {
            currentResult = new JtdsResultSet(this,
                                              ResultSet.TYPE_FORWARD_ONLY,
                                              ResultSet.CONCUR_READ_ONLY,
                                              tds.getColumns());
        } else {
            throw new SQLException(
                    Messages.get("error.statement.noresult"), "24000");
        }

        return currentResult;
    }

    /**
     * Executes any type of SQL.
     *
     * @param sql        the SQL statement to execute
     * @param spName     optional stored procedure name
     * @param params     optional parameters
     * @param returnKeys whether the statement returns generated keys
     * @param update     whether the caller is {@link #executeUpdate}
     * @param useCursor  whether the requested result set type or concurrency
     *                   or connection properties request usage of a cursor
     * @return <code>true</code> if the first result is a result set
     * @throws SQLException if an error condition occurs
     */
    protected boolean executeSQL(String sql,
                                 String spName,
                                 ParamInfo[] params,
                                 boolean returnKeys,
                                 boolean update,
                                 boolean useCursor)
            throws SQLException {
        String warningMessage = null;

        //
        // For SQL Server, try to open a cursor result set if required
        // (and possible).
        //
        if (connection.getServerType() == Driver.SQLSERVER && !update && useCursor) {
            try {
                currentResult = new MSCursorResultSet(this, sql, spName,
                        params, resultSetType, resultSetConcurrency);

                return true;
            } catch (SQLException e) {
                checkCursorException(e);
                warningMessage = '[' + e.getSQLState() + "] " + e.getMessage();
            }
        }

        //
        // We are talking to a Sybase server or we could not open a cursor
        // or we did not have a SELECT so just execute the SQL normally.
        //
        tds.executeSQL(sql, spName, params, false, queryTimeout, maxRows,
                maxFieldSize, true);

        if (warningMessage != null) {
            // Update warning chain if cursor was downgraded
            addWarning(new SQLWarning(Messages.get(
                    "warning.cursordowngraded", warningMessage), "01000"));
        }

        if (processResults(returnKeys, update)) {
            Object nextResult = resultQueue.removeFirst();

            // Next result is an update count
            if (nextResult instanceof Integer) {
                updateCount = ((Integer) nextResult).intValue();
                return false;
            }

            // Next result is a ResultSet. Set currentResult and remove it.
            currentResult = (JtdsResultSet) nextResult;
            return true;
        } else {
            return false;
        }
    }

    /**
     * Queue up update counts into {@link #resultQueue} until the end of the
     * response is reached or a <code>ResultSet</code> is encountered. Calling
     * <code>processResults</code> while a <code>ResultSet</code> is open will
     * not close it, but will consume all remaining rows.
     *
     * @param returnKeys <code>true</code> if a generated keys
     *                   <code>ResultSet</code> is expected
     * @param update     <code>true</code> if the method is called from within
     *                   <code>executeUpdate</code>
     * @return           <code>true</code> if there are any results,
     *                   <code>false</code> otherwise
     * @throws SQLException if an error condition occurs
     */
    private boolean processResults(boolean returnKeys, boolean update) throws SQLException {
        if (!resultQueue.isEmpty()) {
            throw new IllegalStateException(
                    "There should be no queued results.");
        }

        while (!tds.isEndOfResponse()) {
            if (!tds.getMoreResults()) {
                if (tds.isUpdateCount()) {
                    if (update && connection.getLastUpdateCount()) {
                        resultQueue.clear();
                    }
                    resultQueue.addLast(new Integer(tds.getUpdateCount()));
                }
            } else {
                if (returnKeys) {
                    // This had better be the generated key
                    // FIXME We could use SELECT @@IDENTITY AS jTDS_SOMETHING and check the column name to make sure
                    if (tds.getNextRow()) {
                        genKeyResultSet = new CachedResultSet(this,
                                tds.getColumns(),
                                tds.getRowData());
                    }
                } else {
                    if (update && resultQueue.isEmpty()) {
                        // Throw exception but queue up any previous ones
                        SQLException ex = new SQLException(
                                Messages.get("error.statement.nocount"), "07000");
                        ex.setNextException(messages.exceptions);
                        throw ex;
                    }

                    resultQueue.add(new JtdsResultSet(
                            this,
                            ResultSet.TYPE_FORWARD_ONLY,
                            ResultSet.CONCUR_READ_ONLY,
                            tds.getColumns()));
                    break;
                }
            }
        }

        // Check for server side errors
        getMessages().checkErrors();

        return !resultQueue.isEmpty();
    }

    /**
     * Cache as many results as possible (up to the first
     * <code>ResultSet</code>). Called by <code>ResultSet</code>s when the
     * end is reached.
     */
    protected void cacheResults() throws SQLException {
        // Cache results
        processResults(false, false);
    }

    /**
     * Initialize the <code>Statement</code>, by cleaning up all queued and
     * unprocessed results. Called by all execute methods.
     *
     * @throws SQLException if an error occurs
     */
    protected void initialize() throws SQLException {
        updateCount = -1;
        resultQueue.clear();
        genKeyResultSet = null;
        tds.clearResponseQueue();
        // FIXME Should old exceptions found now be thrown instead of lost?
        messages.exceptions = null;
        messages.clearWarnings();
        closeAllResultSets();
    }

    /**

⌨️ 快捷键说明

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