📄 mscursorresultset.java
字号:
// With meta data (we're not expecting any ResultSets), no timeout // (because we're not sending the request yet), don't alter max // rows, don't alter max field size, don't send yet tds.executeSQL(null, "sp_cursor", param, false, 0, -1, -1, false); if (param.length != 4) { param = new ParamInfo[4]; param[0] = PARAM_CURSOR_HANDLE; } // Setup fetchtype param PARAM_FETCHTYPE.value = FETCH_INFO; param[1] = PARAM_FETCHTYPE; // Setup rownum PARAM_ROWNUM_OUT.clearOutValue(); param[2] = PARAM_ROWNUM_OUT; // Setup numRows parameter PARAM_NUMROWS_OUT.clearOutValue(); param[3] = PARAM_NUMROWS_OUT; // No meta data (no ResultSets expected), use statement timeout, // don't alter max rows, don't alter max field size, send now tds.executeSQL(null, "sp_cursorfetch", param, true, statement.getQueryTimeout(), -1, -1, true); } // Consume the sp_cursor response tds.consumeOneResponse(); statement.getMessages().checkErrors(); Integer retVal = tds.getReturnStatus(); if (retVal.intValue() != 0) { throw new SQLException(Messages.get("error.resultset.cursorfail"), "24000"); } // // Allow row values to be garbage collected // if (row != null) { for (int i = 0; i < row.length; i++) { if (row[i] != null) { row[i].clearInValue(); } } } // Consume the sp_cursorfetch response tds.clearResponseQueue(); statement.getMessages().checkErrors(); cursorPos = ((Integer) PARAM_ROWNUM_OUT.getOutValue()).intValue(); rowsInResult = ((Integer) PARAM_NUMROWS_OUT.getOutValue()).intValue(); // Update row status if (opType == CURSOR_OP_DELETE || opType == CURSOR_OP_UPDATE) { Object[] currentRow = getCurrentRow(); if (currentRow == null) { throw new SQLException( Messages.get("error.resultset.updatefail"), "24000"); } // No need to re-fetch the row, just mark it as deleted or dirty currentRow[columns.length - 1] = (opType == CURSOR_OP_DELETE) ? SQL_ROW_DELETED : SQL_ROW_DIRTY; } } /** * Close a server side cursor. * * @throws SQLException */ private void cursorClose() throws SQLException { TdsCore tds = statement.getTds(); statement.clearWarnings(); ParamInfo param[] = new ParamInfo[1]; // Setup cursor handle param param[0] = PARAM_CURSOR_HANDLE; tds.executeSQL(null, "sp_cursorclose", param, false, statement.getQueryTimeout(), -1, -1, true); tds.clearResponseQueue(); statement.getMessages().checkErrors(); } /** * Processes the output of a cursor open or fetch operation. Fetches a * batch of rows from the <code>TdsCore</code>, loading them into the row * cache and optionally sets the column meta data (if called on cursor * open). Consumes all the response and checks for server returned errors. * * @param tds the <code>TdsCore</code> instance * @param setMeta whether column meta data needs to be loaded (cursor open) * @throws SQLException if an error occurs or an error message is returned * by the server */ private void processOutput(TdsCore tds, boolean setMeta) throws SQLException { while (!tds.getMoreResults() && !tds.isEndOfResponse()); int i = 0; if (tds.isResultSet()) { // Set column meta data if necessary if (setMeta) { this.columns = copyInfo(tds.getColumns()); this.columnCount = getColumnCount(columns); } // With TDS 7 the data row (if any) is sent without any // preceding resultset header. // With TDS 8 there is a dummy result set header first // then the data. This case also used if meta data not supressed. if (tds.isRowData() || tds.getNextRow()) { do { rowCache[i++] = copyRow(tds.getRowData()); } while (tds.getNextRow()); } } else if (setMeta) { statement.getMessages().addException(new SQLException( Messages.get("error.statement.noresult"), "24000")); } // Set the rest of the rows to null for (; i < rowCache.length; ++i) { rowCache[i] = null; } tds.clearResponseQueue(); statement.messages.checkErrors(); }//// -------------------- java.sql.ResultSet methods -------------------// public void afterLast() throws SQLException { checkOpen(); checkScrollable(); if (pos != POS_AFTER_LAST) { // SAfe Just fetch a very large absolute value cursorFetch(FETCH_ABSOLUTE, Integer.MAX_VALUE); } } public void beforeFirst() throws SQLException { checkOpen(); checkScrollable(); if (pos != POS_BEFORE_FIRST) { cursorFetch(FETCH_ABSOLUTE, 0); } } public void cancelRowUpdates() throws SQLException { checkOpen(); checkUpdateable(); if (onInsertRow) { throw new SQLException(Messages.get("error.resultset.insrow"), "24000"); } for (int i = 0; updateRow != null && i < updateRow.length; i++) { if (updateRow[i] != null) { updateRow[i].clearInValue(); } } } public void close() throws SQLException { if (!closed) { try { if (!statement.getConnection().isClosed()) { cursorClose(); } } finally { closed = true; statement = null; } } } public void deleteRow() throws SQLException { checkOpen(); checkUpdateable(); if (getCurrentRow() == null) { throw new SQLException(Messages.get("error.resultset.norow"), "24000"); } if (onInsertRow) { throw new SQLException(Messages.get("error.resultset.insrow"), "24000"); } cursor(CURSOR_OP_DELETE, null); } public void insertRow() throws SQLException { checkOpen(); checkUpdateable(); if (!onInsertRow) { throw new SQLException(Messages.get("error.resultset.notinsrow"), "24000"); } cursor(CURSOR_OP_INSERT, insertRow); } public void moveToCurrentRow() throws SQLException { checkOpen(); checkUpdateable(); onInsertRow = false; } public void moveToInsertRow() throws SQLException { checkOpen(); checkUpdateable(); if (insertRow == null) { insertRow = new ParamInfo[columnCount]; } onInsertRow = true; } public void refreshRow() throws SQLException { checkOpen(); if (onInsertRow) { throw new SQLException(Messages.get("error.resultset.insrow"), "24000"); } cursorFetch(FETCH_REPEAT, 0); } public void updateRow() throws SQLException { checkOpen(); checkUpdateable(); if (getCurrentRow() == null) { throw new SQLException(Messages.get("error.resultset.norow"), "24000"); } if (onInsertRow) { throw new SQLException(Messages.get("error.resultset.insrow"), "24000"); } if (updateRow != null) { cursor(CURSOR_OP_UPDATE, updateRow); } } public boolean first() throws SQLException { checkOpen(); checkScrollable(); pos = 1; if (getCurrentRow() == null) { return cursorFetch(FETCH_FIRST, 0); } else { return true; } } // FIXME Make the isXXX() methods work with forward-only cursors (rowsInResult == -1) public boolean isLast() throws SQLException { checkOpen(); return(pos == rowsInResult) && (rowsInResult != 0); } public boolean last() throws SQLException { checkOpen(); checkScrollable(); pos = rowsInResult; if (getCurrentRow() == null) { if (cursorFetch(FETCH_LAST, 0)) { // Set pos to the last row, as the number of rows can change pos = rowsInResult; return true; } else { return false; } } else { return true; } } public boolean next() throws SQLException { checkOpen(); ++pos; if (getCurrentRow() == null) { return cursorFetch(FETCH_NEXT, 0); } else { return true; } } public boolean previous() throws SQLException { checkOpen(); checkScrollable(); // Don't bother if we're already before the first row if (pos == POS_BEFORE_FIRST) { return false; } // Save current ResultSet position int initPos = pos; // Decrement current position --pos; if (initPos == POS_AFTER_LAST || getCurrentRow() == null) { boolean res = cursorFetch(FETCH_PREVIOUS, 0); pos = (initPos == POS_AFTER_LAST) ? rowsInResult : (initPos - 1); return res; } else { return true; } } public boolean rowDeleted() throws SQLException { checkOpen(); Object[] currentRow = getCurrentRow(); // If there is no current row, return false (the row was not deleted) if (currentRow == null) { return false; } // Reload if dirty if (SQL_ROW_DIRTY.equals(currentRow[columns.length - 1])) { cursorFetch(FETCH_REPEAT, 0); currentRow = getCurrentRow(); } return SQL_ROW_DELETED.equals(currentRow[columns.length - 1]); } public boolean rowInserted() throws SQLException { checkOpen(); // No way to find out return false; } public boolean rowUpdated() throws SQLException { checkOpen(); // No way to find out return false; } public boolean absolute(int row) throws SQLException { checkOpen(); checkScrollable(); pos = (row >= 0) ? row : (rowsInResult - row + 1); if (getCurrentRow() == null) { boolean result = cursorFetch(FETCH_ABSOLUTE, row); if (cursorPos == 1 && row + rowsInResult < 0) { pos = 0; result = false; } return result; } else { return true; } } public boolean relative(int row) throws SQLException { checkOpen(); checkScrollable(); pos = (pos == POS_AFTER_LAST) ? (rowsInResult + 1 + row) : (pos + row); if (getCurrentRow() == null) { if (pos < cursorPos) { // If fetching backwards fetch the row and the rows before it, // then restore pos int savePos = pos; boolean result = cursorFetch(FETCH_RELATIVE, pos - cursorPos - fetchSize + 1); if (result) { pos = savePos; } else { pos = POS_BEFORE_FIRST; } return result; } else { return cursorFetch(FETCH_RELATIVE, pos - cursorPos); } } else { return true; } } protected Object[] getCurrentRow() { if (pos < cursorPos || pos >= cursorPos + rowCache.length) { return null; } return rowCache[pos - cursorPos]; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -