📄 results.c
字号:
mylog("SQLExtendedFetch: stmt=%u\n", stmt); if ( ! stmt) { SC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } if ( globals.use_declarefetch && ! stmt->manual_result) { if ( fFetchType != SQL_FETCH_NEXT) { stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR; stmt->errormsg = "Unsupported fetch type for SQLExtendedFetch with UseDeclareFetch option."; return SQL_ERROR; } } SC_clear_error(stmt); if ( ! (res = stmt->result)) { stmt->errormsg = "Null statement result in SQLExtendedFetch."; stmt->errornumber = STMT_SEQUENCE_ERROR; SC_log_error(func, "", stmt); return SQL_ERROR; } /* If a bookmark colunmn is bound but bookmark usage is off, then error */ if (stmt->bookmark.buffer && stmt->options.use_bookmarks == SQL_UB_OFF) { stmt->errornumber = STMT_COLNUM_ERROR; stmt->errormsg = "Attempt to retrieve bookmark with bookmark usage disabled"; SC_log_error(func, "", stmt); return SQL_ERROR; } if (stmt->status == STMT_EXECUTING) { stmt->errormsg = "Can't fetch while statement is still executing."; stmt->errornumber = STMT_SEQUENCE_ERROR; SC_log_error(func, "", stmt); return SQL_ERROR; } if (stmt->status != STMT_FINISHED) { stmt->errornumber = STMT_STATUS_ERROR; stmt->errormsg = "ExtendedFetch can only be called after the successful execution on a SQL statement"; SC_log_error(func, "", stmt); return SQL_ERROR; } if (stmt->bindings == NULL) { // just to avoid a crash if the user insists on calling this // function even if SQL_ExecDirect has reported an Error stmt->errormsg = "Bindings were not allocated properly."; stmt->errornumber = STMT_SEQUENCE_ERROR; SC_log_error(func, "", stmt); return SQL_ERROR; } /* Initialize to no rows fetched */ if (rgfRowStatus) for (i = 0; i < stmt->options.rowset_size; i++) *(rgfRowStatus + i) = SQL_ROW_NOROW; if (pcrow) *pcrow = 0; num_tuples = QR_get_num_tuples(res); /* Save and discard the saved rowset size */ save_rowset_size = stmt->save_rowset_size; stmt->save_rowset_size = -1; switch (fFetchType) { case SQL_FETCH_NEXT: /* From the odbc spec... If positioned before the start of the RESULT SET, then this should be equivalent to SQL_FETCH_FIRST. */ if (stmt->rowset_start < 0) stmt->rowset_start = 0; else { stmt->rowset_start += (save_rowset_size > 0 ? save_rowset_size : stmt->options.rowset_size); } mylog("SQL_FETCH_NEXT: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple); break; case SQL_FETCH_PRIOR: mylog("SQL_FETCH_PRIOR: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple); /* From the odbc spec... If positioned after the end of the RESULT SET, then this should be equivalent to SQL_FETCH_LAST. */ if (stmt->rowset_start >= num_tuples) { stmt->rowset_start = num_tuples <= 0 ? 0 : (num_tuples - stmt->options.rowset_size); } else { stmt->rowset_start -= stmt->options.rowset_size; } break; case SQL_FETCH_FIRST: mylog("SQL_FETCH_FIRST: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple); stmt->rowset_start = 0; break; case SQL_FETCH_LAST: mylog("SQL_FETCH_LAST: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple); stmt->rowset_start = num_tuples <= 0 ? 0 : (num_tuples - stmt->options.rowset_size) ; break; case SQL_FETCH_ABSOLUTE: mylog("SQL_FETCH_ABSOLUTE: num_tuples=%d, currtuple=%d, irow=%d\n", num_tuples, stmt->currTuple, irow); /* Position before result set, but dont fetch anything */ if (irow == 0) { stmt->rowset_start = -1; stmt->currTuple = -1; return SQL_NO_DATA_FOUND; } /* Position before the desired row */ else if (irow > 0) { stmt->rowset_start = irow - 1; } /* Position with respect to the end of the result set */ else { stmt->rowset_start = num_tuples + irow; } break; case SQL_FETCH_RELATIVE: /* Refresh the current rowset -- not currently implemented, but lie anyway */ if (irow == 0) { break; } stmt->rowset_start += irow; break; case SQL_FETCH_BOOKMARK: stmt->rowset_start = irow - 1; break; default: SC_log_error(func, "Unsupported SQLExtendedFetch Direction", stmt); return SQL_ERROR; } /***********************************/ /* CHECK FOR PROPER CURSOR STATE */ /***********************************/ /* Handle Declare Fetch style specially because the end is not really the end... */ if ( globals.use_declarefetch && ! stmt->manual_result) { if (QR_end_tuples(res)) { return SQL_NO_DATA_FOUND; } } else { /* If *new* rowset is after the result_set, return no data found */ if (stmt->rowset_start >= num_tuples) { stmt->rowset_start = num_tuples; return SQL_NO_DATA_FOUND; } } /* If *new* rowset is prior to result_set, return no data found */ if (stmt->rowset_start < 0) { if (stmt->rowset_start + stmt->options.rowset_size <= 0) { stmt->rowset_start = -1; return SQL_NO_DATA_FOUND; } else { /* overlap with beginning of result set, so get first rowset */ stmt->rowset_start = 0; } } /* currTuple is always 1 row prior to the rowset */ stmt->currTuple = stmt->rowset_start - 1; /* increment the base row in the tuple cache */ QR_set_rowset_size(res, stmt->options.rowset_size); QR_inc_base(res, stmt->last_fetch_count); /* Physical Row advancement occurs for each row fetched below */ mylog("SQLExtendedFetch: new currTuple = %d\n", stmt->currTuple); truncated = error = FALSE; for (i = 0; i < stmt->options.rowset_size; i++) { stmt->bind_row = i; // set the binding location result = SC_fetch(stmt); /* Determine Function status */ if (result == SQL_NO_DATA_FOUND) break; else if (result == SQL_SUCCESS_WITH_INFO) truncated = TRUE; else if (result == SQL_ERROR) error = TRUE; /* Determine Row Status */ if (rgfRowStatus) { if (result == SQL_ERROR) *(rgfRowStatus + i) = SQL_ROW_ERROR; else *(rgfRowStatus + i)= SQL_ROW_SUCCESS; } } /* Save the fetch count for SQLSetPos */ stmt->last_fetch_count= i; /* Reset next binding row */ stmt->bind_row = 0; /* Move the cursor position to the first row in the result set. */ stmt->currTuple = stmt->rowset_start; /* For declare/fetch, need to reset cursor to beginning of rowset */ if (globals.use_declarefetch && ! stmt->manual_result) { QR_set_position(res, 0); } /* Set the number of rows retrieved */ if (pcrow) *pcrow = i; if (i == 0) return SQL_NO_DATA_FOUND; /* Only DeclareFetch should wind up here */ else if (error) return SQL_ERROR; else if (truncated) return SQL_SUCCESS_WITH_INFO; else return SQL_SUCCESS;}// This determines whether there are more results sets available for// the "hstmt"./* CC: return SQL_NO_DATA_FOUND since we do not support multiple result sets */RETCODE SQL_API SQLMoreResults( HSTMT hstmt){ return SQL_NO_DATA_FOUND;}// This positions the cursor within a rowset, that was positioned using SQLExtendedFetch.// This will be useful (so far) only when using SQLGetData after SQLExtendedFetch. RETCODE SQL_API SQLSetPos( HSTMT hstmt, UWORD irow, UWORD fOption, UWORD fLock){static char *func = "SQLSetPos";StatementClass *stmt = (StatementClass *) hstmt;QResultClass *res;int num_cols, i;BindInfoClass *bindings = stmt->bindings; if ( ! stmt) { SC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } if (fOption != SQL_POSITION && fOption != SQL_REFRESH) { stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR; stmt->errormsg = "Only SQL_POSITION/REFRESH is supported for SQLSetPos"; SC_log_error(func, "", stmt); return SQL_ERROR; } if ( ! (res = stmt->result)) { stmt->errormsg = "Null statement result in SQLSetPos."; stmt->errornumber = STMT_SEQUENCE_ERROR; SC_log_error(func, "", stmt); return SQL_ERROR; } num_cols = QR_NumResultCols(res); if (irow == 0) { stmt->errornumber = STMT_ROW_OUT_OF_RANGE; stmt->errormsg = "Driver does not support Bulk operations."; SC_log_error(func, "", stmt); return SQL_ERROR; } if (irow > stmt->last_fetch_count) { stmt->errornumber = STMT_ROW_OUT_OF_RANGE; stmt->errormsg = "Row value out of range"; SC_log_error(func, "", stmt); return SQL_ERROR; } irow--; /* Reset for SQLGetData */ for (i = 0; i < num_cols; i++) bindings[i].data_left = -1; QR_set_position(res, irow); stmt->currTuple = stmt->rowset_start + irow; return SQL_SUCCESS;}// Sets options that control the behavior of cursors.RETCODE SQL_API SQLSetScrollOptions( HSTMT hstmt, UWORD fConcurrency, SDWORD crowKeyset, UWORD crowRowset){static char *func = "SQLSetScrollOptions"; SC_log_error(func, "Function not implemented", (StatementClass *) hstmt); return SQL_ERROR;}// Set the cursor name on a statement handleRETCODE SQL_API SQLSetCursorName( HSTMT hstmt, UCHAR FAR *szCursor, SWORD cbCursor){static char *func="SQLSetCursorName";StatementClass *stmt = (StatementClass *) hstmt;int len;mylog("SQLSetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d\n", hstmt, szCursor, cbCursor); if ( ! stmt) { SC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } len = (cbCursor == SQL_NTS) ? strlen(szCursor) : cbCursor; if (len <= 0 || len > sizeof(stmt->cursor_name) - 1) { stmt->errornumber = STMT_INVALID_CURSOR_NAME; stmt->errormsg = "Invalid Cursor Name"; SC_log_error(func, "", stmt); return SQL_ERROR; } strncpy_null(stmt->cursor_name, szCursor, len+1); return SQL_SUCCESS;}// Return the cursor name for a statement handleRETCODE SQL_API SQLGetCursorName( HSTMT hstmt, UCHAR FAR *szCursor, SWORD cbCursorMax, SWORD FAR *pcbCursor){static char *func="SQLGetCursorName";StatementClass *stmt = (StatementClass *) hstmt;int len = 0;RETCODE result;mylog("SQLGetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d, pcbCursor=%u\n", hstmt, szCursor, cbCursorMax, pcbCursor); if ( ! stmt) { SC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } if ( stmt->cursor_name[0] == '\0') { stmt->errornumber = STMT_NO_CURSOR_NAME; stmt->errormsg = "No Cursor name available"; SC_log_error(func, "", stmt); return SQL_ERROR; } result = SQL_SUCCESS; len = strlen(stmt->cursor_name); if (szCursor) { strncpy_null(szCursor, stmt->cursor_name, cbCursorMax); if (len >= cbCursorMax) { result = SQL_SUCCESS_WITH_INFO; stmt->errornumber = STMT_TRUNCATED; stmt->errormsg = "The buffer was too small for the result."; } } if (pcbCursor) *pcbCursor = len; return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -