📄 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. * * Classes: QResultClass (Functions prefix: "QR_") * * API functions: none * * Comments: See "notice.txt" for copyright and license information. *--------- */#include "qresult.h"#include "statement.h"#include "misc.h"#include <stdio.h>#include <string.h>#include <limits.h>static char QR_read_a_tuple_from_db(QResultClass *, char);/* * Used for building a Manual Result only * All info functions call this function to create the manual result set. */voidQR_set_num_fields(QResultClass *self, int new_num_fields){ BOOL allocrelatt = FALSE; if (!self) return; mylog("in QR_set_num_fields\n"); CI_set_num_fields(self->fields, new_num_fields, allocrelatt); mylog("exit QR_set_num_fields\n");}voidQR_set_position(QResultClass *self, SQLLEN pos){ self->tupleField = self->backend_tuples + ((QR_get_rowstart_in_cache(self) + pos) * self->num_fields);}voidQR_set_cache_size(QResultClass *self, SQLLEN cache_size){ self->cache_size = cache_size;}voidQR_set_rowset_size(QResultClass *self, Int4 rowset_size){ self->rowset_size_include_ommitted = rowset_size;}voidQR_set_cursor(QResultClass *self, const char *name){ ConnectionClass *conn = QR_get_conn(self); if (self->cursor_name) { free(self->cursor_name); if (conn) { CONNLOCK_ACQUIRE(conn); conn->ncursors--; CONNLOCK_RELEASE(conn); } self->cursTuple = -1; self->pstatus = 0; } if (name) { self->cursor_name = strdup(name); if (conn) { CONNLOCK_ACQUIRE(conn); conn->ncursors++; CONNLOCK_RELEASE(conn); } } else { self->cursor_name = NULL; QR_set_no_cursor(self); }}voidQR_set_num_cached_rows(QResultClass *self, SQLLEN num_rows){ self->num_cached_rows = num_rows; if (QR_synchronize_keys(self)) self->num_cached_keys = self->num_cached_rows;}voidQR_set_rowstart_in_cache(QResultClass *self, SQLLEN start){ if (QR_synchronize_keys(self)) self->key_base = start; self->base = start;}voidQR_inc_rowstart_in_cache(QResultClass *self, SQLLEN base_inc){ if (!QR_has_valid_base(self)) mylog("QR_inc_rowstart_in_cache called while the cache is not ready\n"); self->base += base_inc; if (QR_synchronize_keys(self)) self->key_base = self->base;}/* * CLASS QResult */QResultClass *QR_Constructor(){ QResultClass *rv; mylog("in QR_Constructor\n"); rv = (QResultClass *) malloc(sizeof(QResultClass)); if (rv != NULL) { rv->rstatus = PORES_EMPTY_QUERY; rv->pstatus = 0; /* construct the column info */ if (!(rv->fields = CI_Constructor())) { free(rv); return NULL; } rv->backend_tuples = NULL; rv->sqlstate[0] = '\0'; rv->message = NULL; rv->command = NULL; rv->notice = NULL; rv->conn = NULL; rv->next = NULL; rv->pstatus = 0; rv->count_backend_allocated = 0; rv->count_keyset_allocated = 0; rv->num_total_read = 0; rv->num_cached_rows = 0; rv->num_cached_keys = 0; rv->fetch_number = 0; QR_set_rowstart_in_cache(rv, -1); rv->key_base = -1; rv->recent_processed_row_count = -1; rv->cursTuple = -1; rv->move_offset = 0; rv->num_fields = 0; rv->num_key_fields = PG_NUM_NORMAL_KEYS; /* CTID + OID */ rv->tupleField = NULL; rv->cursor_name = NULL; rv->aborted = FALSE; rv->cache_size = 0; rv->rowset_size_include_ommitted = 1; rv->flags = 0; rv->move_direction = 0; rv->keyset = NULL; rv->reload_count = 0; rv->rb_alloc = 0; rv->rb_count = 0; rv->rollback = NULL; rv->ad_alloc = 0; rv->ad_count = 0; rv->added_keyset = NULL; rv->added_tuples = NULL; rv->up_alloc = 0; rv->up_count = 0; rv->updated = NULL; rv->updated_keyset = NULL; rv->updated_tuples = NULL; rv->dl_alloc = 0; rv->dl_count = 0; rv->deleted = NULL; rv->deleted_keyset = NULL; } mylog("exit QR_Constructor\n"); return rv;}voidQR_close_result(QResultClass *self, BOOL destroy){ ConnectionClass *conn; if (!self) return; mylog("QResult: in QR_close_result\n"); /* * 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 ((conn = QR_get_conn(self)) && conn->sock) { if (CC_is_in_trans(conn) || QR_is_withhold(self)) { if (!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... */ QR_set_cursor(self, NULL); /* Free up column info */ if (destroy && self->fields) { CI_Destructor(self->fields); self->fields = NULL; } /* Free command info (this is from strdup()) */ if (self->command) { free(self->command); self->command = NULL; } /* Free message info (this is from strdup()) */ if (self->message) { free(self->message); self->message = NULL; } /* Free notice info (this is from strdup()) */ if (self->notice) { free(self->notice); self->notice = NULL; } /* Destruct the result object in the chain */ QR_Destructor(self->next); self->next = NULL; mylog("QResult: exit close_result\n"); if (destroy) { free(self); }}voidQR_Destructor(QResultClass *self){ mylog("QResult: enter DESTRUCTOR\n"); if (!self) return; QR_close_result(self, TRUE); mylog("QResult: exit DESTRUCTOR\n");}voidQR_set_command(QResultClass *self, const char *msg){ if (self->command) free(self->command); self->command = msg ? strdup(msg) : NULL;}voidQR_set_message(QResultClass *self, const char *msg){ if (self->message) free(self->message); self->message = msg ? strdup(msg) : NULL;}voidQR_add_message(QResultClass *self, const char *msg){ char *message = self->message; size_t alsize, pos; if (!msg || !msg[0]) return; if (message) { pos = strlen(message) + 1; alsize = pos + strlen(msg) + 1; } else { pos = 0; alsize = strlen(msg) + 1; } message = realloc(message, alsize); if (pos > 0) message[pos - 1] = ';'; strcpy(message + pos, msg); self->message = message;}voidQR_set_notice(QResultClass *self, const char *msg){ if (self->notice) free(self->notice); self->notice = msg ? strdup(msg) : NULL;}voidQR_add_notice(QResultClass *self, const char *msg){ char *message = self->notice; size_t alsize, pos; if (!msg || !msg[0]) return; if (message) { pos = strlen(message) + 1; alsize = pos + strlen(msg) + 1; } else { pos = 0; alsize = strlen(msg) + 1; } message = realloc(message, alsize); if (pos > 0) message[pos - 1] = ';'; strcpy(message + pos, msg); self->notice = message;}TupleField *QR_AddNew(QResultClass *self){ size_t alloc; UInt4 num_fields; if (!self) return NULL;inolog("QR_AddNew %dth row(%d fields) alloc=%d\n", self->num_cached_rows, QR_NumResultCols(self), self->count_backend_allocated); if (num_fields = QR_NumResultCols(self), !num_fields) return NULL; if (self->num_fields <= 0) { self->num_fields = num_fields; QR_set_reached_eof(self); } alloc = self->count_backend_allocated; if (!self->backend_tuples) { self->num_cached_rows = 0; alloc = TUPLE_MALLOC_INC; self->backend_tuples = malloc(alloc * sizeof(TupleField) * num_fields); } else if (self->num_cached_rows >= self->count_backend_allocated) { alloc = self->count_backend_allocated * 2; QR_REALLOC_return_with_error(self->backend_tuples, TupleField, alloc * sizeof(TupleField) * num_fields, self, "Out of memory in QR_AddNew.", NULL); } self->count_backend_allocated = alloc; if (self->backend_tuples) { memset(self->backend_tuples + num_fields * self->num_cached_rows, 0, num_fields * sizeof(TupleField)); self->num_cached_rows++; self->ad_count++; } return self->backend_tuples + num_fields * (self->num_cached_rows - 1);}voidQR_free_memory(QResultClass *self){ SQLLEN num_backend_rows = self->num_cached_rows; int num_fields = self->num_fields; mylog("QResult: free memory in, fcount=%d\n", num_backend_rows); if (self->backend_tuples) { ClearCachedRows(self->backend_tuples, num_fields, num_backend_rows); free(self->backend_tuples); self->count_backend_allocated = 0; self->backend_tuples = NULL; } if (self->keyset) { ConnectionClass *conn = QR_get_conn(self); free(self->keyset); self->keyset = NULL; self->count_keyset_allocated = 0; if (self->reload_count > 0 && conn && conn->sock) { char plannm[32]; sprintf(plannm, "_KEYSET_%p", self); if (CC_is_in_error_trans(conn)) { CC_mark_a_object_to_discard(conn, 's',plannm); } else { QResultClass *res; char cmd[64]; sprintf(cmd, "DEALLOCATE \"%s\"", plannm); res = CC_send_query(conn, cmd, NULL, IGNORE_ABORT_ON_CONN | ROLLBACK_ON_ERROR, NULL); QR_Destructor(res); } } self->reload_count = 0; } if (self->rollback) { free(self->rollback); self->rb_alloc = 0; self->rb_count = 0; self->rollback = NULL; } if (self->deleted) { free(self->deleted); self->deleted = NULL; } if (self->deleted_keyset) { free(self->deleted_keyset); self->deleted_keyset = NULL; } self->dl_alloc = 0; self->dl_count = 0; /* clear added info */ if (self->added_keyset) { free(self->added_keyset); self->added_keyset = NULL; } if (self->added_tuples) { ClearCachedRows(self->added_tuples, num_fields, self->ad_count); free(self->added_tuples); self->added_tuples = NULL; } self->ad_alloc = 0; self->ad_count = 0; /* clear updated info */ if (self->updated) { free(self->updated); self->updated = NULL; } if (self->updated_keyset) { free(self->updated_keyset); self->updated_keyset = NULL; } if (self->updated_tuples) { ClearCachedRows(self->updated_tuples, num_fields, self->up_count); free(self->updated_tuples); self->updated_tuples = NULL; } self->up_alloc = 0; self->up_count = 0; self->num_total_read = 0; self->num_cached_rows = 0; self->num_cached_keys = 0; self->cursTuple = -1; self->pstatus = 0; mylog("QResult: free memory out\n");}/* This function is called by send_query() */charQR_fetch_tuples(QResultClass *self, ConnectionClass *conn, const char *cursor){ CSTR func = "QR_fetch_tuples"; SQLLEN 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -