llResultsSupported = false;
                    for (int i = 0; i < rowNumber; i++) {
                        rs.next();
                    }
                }
            }
        }
        // Otherwise, manually scroll to the correct row.
        else {
            for (int i = 0; i < rowNumber; i++) {
                rs.next();
            }
        }
    }

    /**
     * Limits the number of the results in a result set (to startIndex + numResults).
     * Sets the fetch size depending on the features of the JDBC driver and make
     * sure that the size is not bigger than 500. 
     * @param pstmt the PreparedStatement
     * @param startIndex the first row with interesting data
     * @param numResults the number of interesting results
     */
    public static void limitRowsAndFetchSize(PreparedStatement pstmt, int startIndex, int numResults) {
        final int MAX_FETCHRESULTS = 500;
        final int maxRows = startIndex + numResults;
        setMaxRows(pstmt, maxRows);
        if (pstmt_fetchSizeSupported)
        {
            if (scrollResultsSupported) {
                setFetchSize(pstmt, Math.min(MAX_FETCHRESULTS, numResults));
            }
            else {
                setFetchSize(pstmt, Math.min(MAX_FETCHRESULTS, maxRows));            
            }
        }
    }
    
    /**
     * Sets the number of rows that the JDBC driver should buffer at a time.
     * The operation is automatically bypassed if Openfire knows that the
     * the JDBC driver or database doesn't support it.
     *
     * @param pstmt the PreparedStatement to set the fetch size for.
     * @param fetchSize the fetchSize.
     */
    public static void setFetchSize(PreparedStatement pstmt, int fetchSize) {
        if (pstmt_fetchSizeSupported) {
            try {
                pstmt.setFetchSize(fetchSize);
            }
            catch (Throwable t) {
                // Ignore. Exception may happen if the driver doesn't support
                // this operation and we didn't set meta-data correctly.
           