📄 qresult.c
字号:
* more rows so don't call next_tuple again! */ if (conn != NULL) { ConnInfo *ci = &(conn->connInfo); BOOL fetch_cursor = (cursor && cursor[0]); QR_set_conn(self, conn); mylog("%s: cursor = '%s', self->cursor=%p\n", func, (cursor == NULL) ? "" : cursor, QR_get_cursor(self)); if (cursor && !cursor[0]) cursor = NULL; if (fetch_cursor) { if (!cursor) { QR_set_rstatus(self, PORES_INTERNAL_ERROR); QR_set_message(self, "Internal Error -- no cursor for fetch"); return FALSE; } } QR_set_cursor(self, cursor); /* * Read the field attributes. * * $$$$ Should do some error control HERE! $$$$ */ if (CI_read_fields(self->fields, QR_get_conn(self))) { QR_set_rstatus(self, PORES_FIELDS_OK); self->num_fields = CI_get_num_fields(self->fields); if (QR_haskeyset(self)) self->num_fields -= self->num_key_fields; } else { QR_set_rstatus(self, PORES_BAD_RESPONSE); QR_set_message(self, "Error reading field information"); return FALSE; } mylog("%s: past CI_read_fields: num_fields = %d\n", func, self->num_fields); if (fetch_cursor) { if (self->cache_size <= 0) self->cache_size = ci->drivers.fetch_max; tuple_size = self->cache_size; } else tuple_size = TUPLE_MALLOC_INC; /* allocate memory for the tuple cache */ mylog("MALLOC: tuple_size = %d, size = %d\n", tuple_size, self->num_fields * sizeof(TupleField) * tuple_size); self->count_backend_allocated = self->count_keyset_allocated = 0; if (self->num_fields > 0) { QR_MALLOC_return_with_error(self->backend_tuples, TupleField, self->num_fields * sizeof(TupleField) * tuple_size, self, "Could not get memory for tuple cache.", FALSE); self->count_backend_allocated = tuple_size; } if (QR_haskeyset(self)) { if (self->keyset = (KeySet *) calloc(sizeof(KeySet), tuple_size), !self->keyset) { QR_set_rstatus(self, PORES_FATAL_ERROR); QR_set_message(self, "Could not get memory for tuple cache."); return FALSE; } self->count_keyset_allocated = tuple_size; } QR_set_fetching_tuples(self); /* Force a read to occur in next_tuple */ QR_set_num_cached_rows(self, 0); QR_set_next_in_cache(self, 0); QR_set_rowstart_in_cache(self, 0); self->key_base = 0; return QR_next_tuple(self, NULL); } else { /* * Always have to read the field attributes. But we dont have to * reallocate memory for them! */ if (!CI_read_fields(NULL, QR_get_conn(self))) { QR_set_rstatus(self, PORES_BAD_RESPONSE); QR_set_message(self, "Error reading field information"); return FALSE; } return TRUE; }}/* * Close the cursor and end the transaction (if no cursors left) * We only close the cursor if other cursors are used. */intQR_close(QResultClass *self){ ConnectionClass *conn; QResultClass *res; int ret = TRUE; conn = QR_get_conn(self); if (self && QR_get_cursor(self)) { if (CC_is_in_error_trans(conn)) { if (QR_is_withhold(self)) CC_mark_a_object_to_discard(conn, 'p', QR_get_cursor(self)); } else { UDWORD flag = ROLLBACK_ON_ERROR | IGNORE_ABORT_ON_CONN; char buf[64]; snprintf(buf, sizeof(buf), "close \"%s\"", QR_get_cursor(self)); /* End the transaction if there are no cursors left on this conn */ if (CC_is_in_autocommit(conn) && CC_cursor_count(conn) <= 1) { mylog("QResult: END transaction on conn=%p\n", conn); strncat(buf, ";commit", sizeof(buf)); flag |= END_WITH_COMMIT; } res = CC_send_query(conn, buf, NULL, flag, NULL); QR_Destructor(res); } QR_set_no_fetching_tuples(self); self->cursTuple = -1; QR_set_cursor(self, NULL); if (!ret) return ret;#ifdef NOT_USED /* End the transaction if there are no cursors left on this conn */ if (CC_is_in_autocommit(conn) && CC_cursor_count(conn) == 0) { mylog("QResult: END transaction on conn=%p\n", conn); if (!CC_commit(conn)) { QR_set_rstatus(self, PORES_FATAL_ERROR); QR_set_message(self, "Error ending transaction."); ret = FALSE; } }#endif /* NOT_USED */ } return ret;}BOOLQR_get_tupledata(QResultClass *self, BOOL binary){ BOOL haskeyset = QR_haskeyset(self); SQLULEN num_total_rows = QR_get_num_total_tuples(self);inolog("QR_get_tupledata num_fields=%d\n", self->num_fields); if (!QR_get_cursor(self)) { if (self->num_fields > 0 && num_total_rows >= self->count_backend_allocated) { SQLLEN tuple_size = self->count_backend_allocated; mylog("REALLOC: old_count = %d, size = %d\n", tuple_size, self->num_fields * sizeof(TupleField) * tuple_size); if (tuple_size < 1) tuple_size = TUPLE_MALLOC_INC; else tuple_size *= 2; QR_REALLOC_return_with_error(self->backend_tuples, TupleField, tuple_size * self->num_fields * sizeof(TupleField), self, "Out of memory while reading tuples.", FALSE); self->count_backend_allocated = tuple_size; } if (haskeyset && self->num_cached_keys >= self->count_keyset_allocated) { SQLLEN tuple_size = self->count_keyset_allocated; if (tuple_size < 1) tuple_size = TUPLE_MALLOC_INC; else tuple_size *= 2; QR_REALLOC_return_with_error(self->keyset, KeySet, sizeof(KeySet) * tuple_size, self, "Out of mwmory while allocating keyset", FALSE); self->count_keyset_allocated = tuple_size; } } if (!QR_read_a_tuple_from_db(self, (char) binary)) { QR_set_rstatus(self, PORES_BAD_RESPONSE); QR_set_message(self, "Error reading the tuple"); return FALSE; }inolog("!!%p->cursTup=%d total_read=%d\n", self, self->cursTuple, self->num_total_read); if (!QR_once_reached_eof(self) && self->cursTuple >= (Int4) self->num_total_read) self->num_total_read = self->cursTuple + 1;inolog("!!cursTup=%d total_read=%d\n", self->cursTuple, self->num_total_read); if (self->num_fields > 0) { QR_inc_num_cache(self); } else if (haskeyset) self->num_cached_keys++; return TRUE;}static SQLLEN enlargeKeyCache(QResultClass *self, SQLLEN add_size, const char *message){ size_t alloc, alloc_req; Int4 num_fields = self->num_fields; BOOL curs = (NULL != QR_get_cursor(self)); if (add_size <= 0) return self->count_keyset_allocated; alloc = self->count_backend_allocated; if (num_fields > 0 && ((alloc_req = (Int4)self->num_cached_rows + add_size) > alloc || !self->backend_tuples)) { if (1 > alloc) { if (curs) alloc = alloc_req; else alloc = (alloc_req > TUPLE_MALLOC_INC ? alloc_req : TUPLE_MALLOC_INC); } else { do { alloc *= 2; } while (alloc < alloc_req); } self->count_backend_allocated = 0; QR_REALLOC_return_with_error(self->backend_tuples, TupleField, num_fields * sizeof(TupleField) * alloc, self, message, -1); self->count_backend_allocated = alloc; } alloc = self->count_keyset_allocated; if (QR_haskeyset(self) && ((alloc_req = (Int4)self->num_cached_keys + add_size) > alloc || !self->keyset)) { if (1 > alloc) { if (curs) alloc = alloc_req; else alloc = (alloc_req > TUPLE_MALLOC_INC ? alloc_req : TUPLE_MALLOC_INC); } else { do { alloc *= 2; } while (alloc < alloc_req); } self->count_keyset_allocated = 0; QR_REALLOC_return_with_error(self->keyset, KeySet, sizeof(KeySet) * alloc, self, message, -1); self->count_keyset_allocated = alloc; } return alloc;}/* This function is called by fetch_tuples() AND SQLFetch() */intQR_next_tuple(QResultClass *self, StatementClass *stmt){ CSTR func = "QR_next_tuple"; int id, ret = TRUE; SocketClass *sock; /* Speed up access */ SQLLEN fetch_number = self->fetch_number, cur_fetch = 0; SQLLEN num_total_rows; SQLLEN num_backend_rows = self->num_cached_rows, num_rows_in; Int4 num_fields = self->num_fields, fetch_size, req_size; SQLLEN offset = 0, end_tuple; char boundary_adjusted = FALSE; TupleField *the_tuples = self->backend_tuples; /* ERROR_MSG_LENGTH is sufficient */ char msgbuffer[ERROR_MSG_LENGTH + 1]; /* QR_set_command() dups this string so doesn't need static */ char cmdbuffer[ERROR_MSG_LENGTH + 1]; char fetch[128]; QueryInfo qi; ConnectionClass *conn; ConnInfo *ci = NULL; BOOL msg_truncated, rcvend, internally_invoked = FALSE; BOOL reached_eof_now = FALSE, curr_eof; /* detecting EOF is pretty important */ BOOL ExecuteRequest = FALSE; Int4 response_length;inolog("Oh %p->fetch_number=%d\n", self, self->fetch_number);inolog("in total_read=%d cursT=%d currT=%d ad=%d total=%d rowsetSize=%d\n", self->num_total_read, self->cursTuple, stmt ? stmt->currTuple : -1, self->ad_count, QR_get_num_total_tuples(self), self->rowset_size_include_ommitted); num_total_rows = QR_get_num_total_tuples(self); conn = QR_get_conn(self); curr_eof = FALSE; req_size = self->rowset_size_include_ommitted; if (QR_once_reached_eof(self) && self->cursTuple >= (Int4) QR_get_num_total_read(self)) curr_eof = TRUE; if (0 != self->move_offset) { char movecmd[256]; QResultClass *mres; SQLULEN movement, moved; movement = self->move_offset; if (QR_is_moving_backward(self)) { if (self->cache_size > req_size) { SQLLEN incr_move = self->cache_size - (req_size < 0 ? 1 : req_size); movement += incr_move; if (movement > (UInt4)(self->cursTuple + 1)) movement = self->cursTuple + 1; } else self->cache_size = req_size;inolog("cache=%d rowset=%d movement=" FORMAT_ULEN "\n", self->cache_size, req_size, movement); sprintf(movecmd, "move backward " FORMAT_ULEN " in \"%s\"", movement, QR_get_cursor(self)); } else if (QR_is_moving_forward(self)) sprintf(movecmd, "move " FORMAT_ULEN " in \"%s\"", movement, QR_get_cursor(self)); else { sprintf(movecmd, "move all in \"%s\"", QR_get_cursor(self)); movement = INT_MAX; } mres = CC_send_query(conn, movecmd, NULL, 0, stmt); if (!QR_command_maybe_successful(mres)) { QR_Destructor(mres); if (stmt) SC_set_error(stmt, STMT_EXEC_ERROR, "move error occured", func); return -1; } moved = movement; if (sscanf(mres->command, "MOVE %lu", &moved) > 0) {inolog("moved=%d ? " FORMAT_ULEN "\n", moved, movement); if (moved < movement) { if (0 < moved) moved++; else if (QR_is_moving_backward(self) && self->cursTuple < 0) ; else if (QR_is_moving_not_backward(self) && curr_eof) ; else moved++; if (QR_is_moving_not_backward(self)) { curr_eof = TRUE; if (!QR_once_reached_eof(self)) { self->num_total_read = self->cursTuple + moved; QR_set_reached_eof(self); } } if (QR_is_moving_from_the_last(self)) /* in case of FETCH LAST */ { SQLULEN bmovement, mback; SQLLEN rowset_start = self->cursTuple + 1, back_offset = self->move_offset, backpt;inolog("FETCH LAST case\n"); if (getNthValid(self, QR_get_num_total_tuples(self) - 1, SQL_FETCH_PRIOR, self->move_offset, &backpt) < 0) { /* the rowset_start is on BOF */ self->tupleField = NULL; SC_set_rowset_start(stmt, -1, TRUE); stmt->currTuple = -1; return -1; } back_offset = QR_get_num_total_tuples(self) - backpt;inolog("back_offset=%d and move_offset=%d\n", back_offset, self->move_offset); if (back_offset + 1 > (Int4) self->ad_count) { bmovement = back_offset + 1 - self->ad_count; sprintf(movecmd, "move backward " FORMAT_ULEN " in \"%s\"", bmovement, QR_get_cursor(self)); QR_Destructor(mres); mres = CC_send_query(conn, movecmd, NULL, 0, stmt); if (!QR_command_maybe_successful(mres)) { QR_Destructor(mres); if (stmt) SC_set_error(stmt, STMT_EXEC_ERROR, "move error occured", func); return -1; } if (sscanf(mres->command, "MOVE %lu", &mback) > 0) { if (mback < bmovement) mback++; if (moved < mback) { QR_set_move_backward(self); mback -= moved; moved = mback; self->move_offset = moved; rowset_start = self->cursTuple - moved + 1; } else { QR_set_move_forward(self); moved-= mback; self->move_offset = moved; rowset_start = self->cursTuple + moved + 1; } } } else { QR_set_move_forward(self); self->move_offset = moved + self->ad_count - back_offset - 1; rowset_start = self->cursTuple +self->move_offset + 1; /* adjust move_offset */ /*** self->move_offset++; ***/ } if (stmt) { SC_set_rowset_start(stmt, rowset_start, TRUE); /* affects the result's rowset_start but it is reset immediately ... */ stmt->currTuple = RowIdx2GIdx(-1, stmt); } } } } /* ... by the following call */ QR_set_rowstart_in_cache(self, -1); if (QR_is_moving_backward(self)) { self->cursTuple -= moved; offset = moved - self->move_offset; } else { self->cursTuple += moved; offset = self->move_offset - moved; } QR_Destructor(mres); self->move_offset = 0; num_backend_rows = self->num_cached_rows; } else if (fetch_number < num_backend_rows) { /* return a row from cache */ mylog("%s: fetch_number < fcount: returning tuple %d, fcount = %d\n", func, fetch_number, num_backend_rows); self->tupleField = the_tuples + (fetch_number * num_fields);inolog("tupleField=%p\n", self->tupleField); /* move to next row */ QR_inc_next_in_cache(self); return TRUE; } else if (QR_once_reached_eof(self)) { BOOL reached_eod = FALSE; SQLULEN num_total_read = self->num_total_read; if (stmt) { if (stmt->currTuple + 1 >= num_total_rows) reached_eod = TRUE; } else if (self->cursTuple + 1 >= (Int4)num_total_read) { if (self->ad_count == 0) reached_eod = TRUE; } if (reached_eod) { mylog("next_tuple: fetch end\n"); self->tupleField = NULL; /* end of tuples */ return -1; } } end_tuple = req_size + QR_get_rowstart_in_cache(self); /* * See if we need to fetch another group of rows. We may be being * called from send_query(), and if so, don't send another fetch, * just fall through and read the tuples. */ self->tupleField = NULL; fetch_size = 0; if (!QR_is_fetching_tuples(self)) { ci = &(conn->connInfo); if (!QR_get_cursor(self)) { mylog("%s: ALL_ROWS: done, fcount = %d, fetch_number = %d\n", func, QR_get_num_total_tuples(self), fetch_number); self->tupleField = NULL; QR_set_reached_eof(self); return -1; /* end of tuples */ } if (QR_get_rowstart_in_cache(self) >= num_backend_rows || QR_is_moving(self))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -