📄 qresult.c
字号:
/* Module: qresult.c * * Description: This module contains functions related to * managing result information (i.e, fetching rows from the backend, * managing the tuple cache, etc.) and retrieving it. * Depending on the situation, a QResultClass will hold either data * from the backend or a manually built result (see "qresult.h" to * see which functions/macros are for manual or backend results. * For manually built results, the QResultClass simply points to * TupleList and ColumnInfo structures, which actually hold the data. * * Classes: QResultClass (Functions prefix: "QR_") * * API functions: none * * Comments: See "notice.txt" for copyright and license information. * */#include "qresult.h"#include "misc.h"#include <stdio.h>#include <string.h>#ifndef TRUE#define TRUE (BOOL)1#endif#ifndef FALSE#define FALSE (BOOL)0#endifextern GLOBAL_VALUES globals;/* Used for building a Manual Result only *//* All info functions call this function to create the manual result set. */void QR_set_num_fields(QResultClass *self, int new_num_fields){ mylog("in QR_set_num_fields\n"); CI_set_num_fields(self->fields, new_num_fields); if(self->manual_tuples) TL_Destructor(self->manual_tuples); self->manual_tuples = TL_Constructor(new_num_fields); mylog("exit QR_set_num_fields\n");}void QR_set_position(QResultClass *self, int pos){ self->tupleField = self->backend_tuples + ((self->base + pos) * self->num_fields);}voidQR_set_cache_size(QResultClass *self, int cache_size){ self->cache_size = cache_size;}void QR_set_rowset_size(QResultClass *self, int rowset_size){ self->rowset_size = rowset_size;}voidQR_inc_base(QResultClass *self, int base_inc){ self->base += base_inc;}/************************************//* CLASS QResult *//************************************/QResultClass *QR_Constructor(void){QResultClass *rv; mylog("in QR_Constructor\n"); rv = (QResultClass *) malloc(sizeof(QResultClass)); if (rv != NULL) { rv->status = PGRES_EMPTY_QUERY; /* construct the column info */ if ( ! (rv->fields = CI_Constructor())) { free(rv); return NULL; } rv->manual_tuples = NULL; rv->backend_tuples = NULL; rv->message = NULL; rv->command = NULL; rv->notice = NULL; rv->conn = NULL; rv->inTuples = FALSE; rv->fcount = 0; rv->fetch_count = 0; rv->base = 0; rv->currTuple = -1; rv->num_fields = 0; rv->tupleField = NULL; rv->cursor = NULL; rv->cache_size = globals.fetch_max; rv->rowset_size = 1; } mylog("exit QR_Constructor\n"); return rv;}voidQR_Destructor(QResultClass *self){ mylog("QResult: in DESTRUCTOR\n"); /* manual result set tuples */ if (self->manual_tuples) TL_Destructor(self->manual_tuples); // If conn is defined, then we may have used "backend_tuples", // so in case we need to, free it up. Also, close the cursor. if (self->conn && self->conn->sock && CC_is_in_trans(self->conn)) QR_close(self); // close the cursor if there is one QR_free_memory(self); // safe to call anyway // Should have been freed in the close() but just in case... if (self->cursor) free(self->cursor); /* Free up column info */ if (self->fields) CI_Destructor(self->fields); /* Free command info (this is from strdup()) */ if (self->command) free(self->command); /* Free notice info (this is from strdup()) */ if (self->notice) free(self->notice); free(self); mylog("QResult: exit DESTRUCTOR\n");}voidQR_set_command(QResultClass *self, char *msg){ if (self->command) free(self->command); self->command = msg ? strdup(msg) : NULL;}void QR_set_notice(QResultClass *self, char *msg){ if (self->notice) free(self->notice); self->notice = msg ? strdup(msg) : NULL;}void QR_free_memory(QResultClass *self){register int lf, row;register TupleField *tuple = self->backend_tuples;int fcount = self->fcount;int num_fields = self->num_fields; mylog("QResult: free memory in, fcount=%d\n", fcount); if ( self->backend_tuples) { for (row = 0; row < fcount; row++) { mylog("row = %d, num_fields = %d\n", row, num_fields); for (lf=0; lf < num_fields; lf++) { if (tuple[lf].value != NULL) { mylog("free [lf=%d] %u\n", lf, tuple[lf].value); free(tuple[lf].value); } } tuple += num_fields; // next row } free(self->backend_tuples); self->backend_tuples = NULL; } self->fcount = 0; mylog("QResult: free memory out\n");}// This function is called by send_query()charQR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor){int tuple_size; // If called from send_query the first time (conn != NULL), // then set the inTuples state, // and read the tuples. If conn is NULL, // it implies that we are being called from next_tuple(), // like to get more rows so don't call next_tuple again! if (conn != NULL) { self->conn = conn; mylog("QR_fetch_tuples: cursor = '%s', self->cursor=%u\n", (cursor==NULL)?"":cursor, self->cursor); if (self->cursor) free(self->cursor); if ( globals.use_declarefetch) { if (! cursor || cursor[0] == '\0') { self->status = PGRES_INTERNAL_ERROR; QR_set_message(self, "Internal Error -- no cursor for fetch"); return FALSE; } self->cursor = strdup(cursor); } // Read the field attributes. // $$$$ Should do some error control HERE! $$$$ if ( CI_read_fields(self->fields, self->conn)) { self->status = PGRES_FIELDS_OK; self->num_fields = CI_get_num_fields(self->fields); } else { self->status = PGRES_BAD_RESPONSE; QR_set_message(self, "Error reading field information"); return FALSE; } mylog("QR_fetch_tuples: past CI_read_fields: num_fields = %d\n", self->num_fields); if (globals.use_declarefetch) 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->backend_tuples = (TupleField *) malloc(self->num_fields * sizeof(TupleField) * tuple_size); if ( ! self->backend_tuples) { self->status = PGRES_FATAL_ERROR; QR_set_message(self, "Could not get memory for tuple cache."); return FALSE; } self->inTuples = TRUE; /* Force a read to occur in next_tuple */ self->fcount = tuple_size+1; self->fetch_count = tuple_size+1; self->base = 0; return QR_next_tuple(self); } else { // Always have to read the field attributes. // But we dont have to reallocate memory for them! if ( ! CI_read_fields(NULL, self->conn)) { self->status = PGRES_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 cursor/end the transaction if a cursor was used.intQR_close(QResultClass *self){QResultClass *res; if (globals.use_declarefetch && self->conn && self->cursor) { char buf[64]; sprintf(buf, "close %s", self->cursor); mylog("QResult: closing cursor: '%s'\n", buf); res = CC_send_query(self->conn, buf, NULL); self->inTuples = FALSE; self->currTuple = -1; free(self->cursor); self->cursor = NULL; if (res == NULL) { self->status = PGRES_FATAL_ERROR; QR_set_message(self, "Error closing cursor."); return FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -