📄 mscursorresultset.java
字号:
synchronized (tds) {
// 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();
// Consume rest of output and remember any exceptions
tds.clearResponseQueue();
SQLException ex = statement.getMessages().exceptions;
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();
if (ex != null) {
ex.setNextException(statement.getMessages().exceptions);
throw ex;
} else {
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 (asyncCursor || 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 + -