1 /* File: qresult.h 2 * 3 * Description: See "qresult.c" 4 * 5 * Comments: See "readme.txt" for copyright and license information. 6 * 7 */ 8 9 #ifndef __QRESULT_H__ 10 #define __QRESULT_H__ 11 12 #include "psqlodbc.h" 13 14 #include "libpq-fe.h" 15 16 #include "connection.h" 17 #include "columninfo.h" 18 #include "tuple.h" 19 20 #ifdef __cplusplus 21 extern "C" { 22 #endif 23 24 typedef 25 enum QueryResultCode_ 26 { 27 PORES_EMPTY_QUERY = 0, 28 PORES_COMMAND_OK, /* a query command that doesn't return 29 * anything was executed properly by the backend */ 30 PORES_TUPLES_OK, /* a query command that returns tuples 31 * was executed properly by the backend, PGresult 32 * contains the resulttuples */ 33 PORES_COPY_OUT, 34 PORES_COPY_IN, 35 PORES_BAD_RESPONSE, /* an unexpected response was recv'd from 36 * the backend */ 37 PORES_NONFATAL_ERROR, 38 PORES_FATAL_ERROR, 39 PORES_NO_MEMORY_ERROR, 40 PORES_FIELDS_OK = 100, /* field information from a query was 41 * successful */ 42 /* PORES_END_TUPLES, */ 43 PORES_INTERNAL_ERROR 44 } QueryResultCode; 45 46 enum 47 { 48 FQR_REACHED_EOF = (1L << 1) /* reached eof */ 49 ,FQR_HAS_VALID_BASE = (1L << 2) 50 ,FQR_NEEDS_SURVIVAL_CHECK = (1L << 3) /* check if the cursor is open */ 51 }; 52 53 struct QResultClass_ 54 { 55 ColumnInfoClass *fields; /* the Column information */ 56 ConnectionClass *conn; /* the connection this result is using 57 * (backend) */ 58 QResultClass *lnext; /* the following result class */ 59 60 /* Stuff for declare/fetch tuples */ 61 SQLULEN num_total_read; /* the highest absolute position ever read in + 1 */ 62 SQLULEN count_backend_allocated;/* m(re)alloced count */ 63 SQLULEN num_cached_rows; /* count of tuples kept in backend_tuples member */ 64 SQLLEN fetch_number; /* 0-based index to the tuple to read next */ 65 SQLLEN cursTuple; /* absolute current position in the servr's cursor used to retrieve tuples from the DB */ 66 SQLULEN move_offset; 67 SQLLEN base; /* relative position of rowset start in the current data cache(backend_tuples) */ 68 69 UInt2 num_fields; /* number of fields in the result */ 70 UInt2 num_key_fields; /* number of key fields in the result */ 71 UInt4 rowset_size_include_ommitted; /* PG restriction */ 72 SQLLEN recent_processed_row_count; 73 SQLULEN cache_size; 74 SQLULEN cmd_fetch_size; 75 76 QueryResultCode rstatus; /* result status */ 77 78 char sqlstate[8]; 79 char *message; 80 const char *messageref; 81 char *cursor_name; /* The name of the cursor for select statements */ 82 char *command; 83 char *notice; 84 85 TupleField *backend_tuples; /* data from the backend (the tuple cache) */ 86 TupleField *tupleField; /* current backend tuple being retrieved */ 87 88 char pstatus; /* processing status */ 89 char aborted; /* was aborted ? */ 90 char flags; /* this result contains keyset etc ? */ 91 po_ind_t move_direction; /* must move before fetching this 92 result set */ 93 SQLULEN count_keyset_allocated; /* m(re)alloced count */ 94 SQLULEN num_cached_keys; /* count of keys kept in backend_keys member */ 95 KeySet *keyset; 96 SQLLEN key_base; /* relative position of rowset start in the current keyset cache */ 97 UInt2 reload_count; 98 UInt2 rb_alloc; /* count of allocated rollback info */ 99 UInt2 rb_count; /* count of rollback info */ 100 char dataFilled; /* Cache is filled with data ? */ 101 Rollback *rollback; 102 UInt4 ad_alloc; /* count of allocated added info */ 103 UInt4 ad_count; /* count of newly added rows */ 104 KeySet *added_keyset; /* added keyset info */ 105 TupleField *added_tuples; /* added data by myself */ 106 UInt2 dl_alloc; /* count of allocated deleted info */ 107 UInt2 dl_count; /* count of deleted info */ 108 SQLLEN *deleted; /* deleted index info */ 109 KeySet *deleted_keyset; /* deleted keyset info */ 110 UInt2 up_alloc; /* count of allocated updated info */ 111 UInt2 up_count; /* count of updated info */ 112 SQLLEN *updated; /* updated index info */ 113 KeySet *updated_keyset; /* uddated keyset info */ 114 TupleField *updated_tuples; /* uddated data by myself */ 115 }; 116 117 enum { 118 FQR_HASKEYSET = 1L 119 ,FQR_WITHHOLD = (1L << 1) 120 ,FQR_HOLDPERMANENT = (1L << 2) /* the cursor is alive across transactions */ 121 ,FQR_SYNCHRONIZEKEYS = (1L<<3) /* synchronize the keyset range with that of cthe tuples cache */ 122 }; 123 124 #define QR_haskeyset(self) (0 != (self->flags & FQR_HASKEYSET)) 125 #define QR_is_withhold(self) (0 != (self->flags & FQR_WITHHOLD)) 126 #define QR_is_permanent(self) (0 != (self->flags & FQR_HOLDPERMANENT)) 127 #define QR_synchronize_keys(self) (0 != (self->flags & FQR_SYNCHRONIZEKEYS)) 128 #define QR_get_fields(self) (self->fields) 129 130 131 /* These functions are for retrieving data from the qresult */ 132 #define QR_get_value_backend(self, fieldno) (self->tupleField[fieldno].value) 133 #define QR_get_value_backend_row(self, tupleno, fieldno) ((self->backend_tuples + (tupleno * self->num_fields))[fieldno].value) 134 #define QR_get_value_backend_text(self, tupleno, fieldno) QR_get_value_backend_row(self, tupleno, fieldno) 135 #define QR_get_value_backend_int(self, tupleno, fieldno, isNull) atoi(QR_get_value_backend_row(self, tupleno, fieldno)) 136 137 /* These functions are used by both manual and backend results */ 138 #define QR_NumResultCols(self) (CI_get_num_fields(self->fields)) 139 #define QR_NumPublicResultCols(self) (QR_haskeyset(self) ? (CI_get_num_fields(self->fields) - self->num_key_fields) : CI_get_num_fields(self->fields)) 140 #define QR_get_fieldname(self, fieldno_) (CI_get_fieldname(self->fields, fieldno_)) 141 #define QR_get_fieldsize(self, fieldno_) (CI_get_fieldsize(self->fields, fieldno_)) 142 #define QR_get_display_size(self, fieldno_) (CI_get_display_size(self->fields, fieldno_)) 143 #define QR_get_atttypmod(self, fieldno_) (CI_get_atttypmod(self->fields, fieldno_)) 144 #define QR_get_field_type(self, fieldno_) (CI_get_oid(self->fields, fieldno_)) 145 #define QR_get_relid(self, fieldno_) (CI_get_relid(self->fields, fieldno_)) 146 #define QR_get_attid(self, fieldno_) (CI_get_attid(self->fields, fieldno_)) 147 148 /* These functions are used only for manual result sets */ 149 #define QR_get_num_total_tuples(self) (QR_once_reached_eof(self) ? (self->num_total_read + self->ad_count) : self->num_total_read) 150 #define QR_get_num_total_read(self) (self->num_total_read) 151 #define QR_get_num_cached_tuples(self) (self->num_cached_rows) 152 #define QR_set_field_info(self, field_num, name, adtid, adtsize, relid, attid) (CI_set_field_info(self->fields, field_num, name, adtid, adtsize, -1, relid, attid)) 153 #define QR_set_field_info_v(self, field_num, name, adtid, adtsize) (CI_set_field_info(self->fields, field_num, name, adtid, adtsize, -1, 0, 0)) 154 155 /* status macros */ 156 #define QR_command_successful(self) (self && !(self->rstatus == PORES_BAD_RESPONSE || self->rstatus == PORES_NONFATAL_ERROR || self->rstatus == PORES_FATAL_ERROR || self->rstatus == PORES_NO_MEMORY_ERROR)) 157 #define QR_command_maybe_successful(self) (self && !(self->rstatus == PORES_BAD_RESPONSE || self->rstatus == PORES_FATAL_ERROR || self->rstatus == PORES_NO_MEMORY_ERROR)) 158 #define QR_command_nonfatal(self) ( self->rstatus == PORES_NONFATAL_ERROR) 159 #define QR_set_conn(self, conn_) ( self->conn = conn_ ) 160 #define QR_set_rstatus(self, condition) ( self->rstatus = condition ) 161 #define QR_set_sqlstatus(self, status) strcpy(self->sqlstatus, status) 162 #define QR_set_messageref(self, m) ((self)->messageref = m) 163 #define QR_set_aborted(self, aborted_) ( self->aborted = aborted_) 164 #define QR_set_haskeyset(self) (self->flags |= FQR_HASKEYSET) 165 #define QR_set_synchronize_keys(self) (self->flags |= FQR_SYNCHRONIZEKEYS) 166 #define QR_set_no_cursor(self) ((self)->flags &= ~(FQR_WITHHOLD | FQR_HOLDPERMANENT), (self)->pstatus &= ~FQR_NEEDS_SURVIVAL_CHECK) 167 #define QR_set_withhold(self) (self->flags |= FQR_WITHHOLD) 168 #define QR_set_permanent(self) (self->flags |= FQR_HOLDPERMANENT) 169 #define QR_set_reached_eof(self) (self->pstatus |= FQR_REACHED_EOF) 170 #define QR_set_has_valid_base(self) (self->pstatus |= FQR_HAS_VALID_BASE) 171 #define QR_set_no_valid_base(self) (self->pstatus &= ~FQR_HAS_VALID_BASE) 172 #define QR_set_survival_check(self) (self->pstatus |= FQR_NEEDS_SURVIVAL_CHECK) 173 #define QR_set_no_survival_check(self) (self->pstatus &= ~FQR_NEEDS_SURVIVAL_CHECK) 174 #define QR_inc_num_cache(self) \ 175 do { \ 176 self->num_cached_rows++; \ 177 if (QR_haskeyset(self)) \ 178 self->num_cached_keys++; \ 179 } while (0) 180 #define QR_set_next_in_cache(self, number) \ 181 do { \ 182 MYLOG(1, "set the number to " FORMAT_LEN " to read next\n", number); \ 183 self->fetch_number = number; \ 184 } while (0) 185 #define QR_inc_next_in_cache(self) \ 186 do { \ 187 MYLOG(1, "increased the number " FORMAT_LEN, self->fetch_number); \ 188 self->fetch_number++; \ 189 MYLOG(1, "to " FORMAT_LEN " to next read\n", self->fetch_number); \ 190 } while (0) 191 192 #define QR_concat(self, a) ((self)->lnext=(a)) 193 #define QR_detach(self) ((self)->lnext=NULL) 194 #define QR_nextr(self) ((self)->lnext) 195 196 #define QR_get_message(self) ((self)->message ? (self)->message : (self)->messageref) 197 #define QR_get_command(self) (self->command) 198 #define QR_get_notice(self) (self->notice) 199 #define QR_get_rstatus(self) (self->rstatus) 200 #define QR_get_aborted(self) (self->aborted) 201 #define QR_get_conn(self) (self->conn) 202 #define QR_get_cursor(self) (self->cursor_name) 203 #define QR_get_rowstart_in_cache(self) (self->base) 204 #define QR_once_reached_eof(self) ((self->pstatus & FQR_REACHED_EOF) != 0) 205 #define QR_has_valid_base(self) (0 != (self->pstatus & FQR_HAS_VALID_BASE)) 206 #define QR_needs_survival_check(self) (0 != (self->pstatus & FQR_NEEDS_SURVIVAL_CHECK)) 207 208 #define QR_aborted(self) (!self || self->aborted) 209 #define QR_get_reqsize(self) (self->rowset_size_include_ommitted) 210 211 #define QR_stop_movement(self) (self->move_direction = 0) 212 #define QR_is_moving(self) (0 != self->move_direction) 213 #define QR_is_not_moving(self) (0 == self->move_direction) 214 #define QR_set_move_forward(self) (self->move_direction = 1) 215 #define QR_is_moving_forward(self) (1 == self->move_direction) 216 #define QR_set_move_backward(self) (self->move_direction = -1) 217 #define QR_is_moving_backward(self) (-1 == self->move_direction) 218 #define QR_set_move_from_the_last(self) (self->move_direction = 2) 219 #define QR_is_moving_from_the_last(self) (2 == self->move_direction) 220 #define QR_is_moving_not_backward(self) (0 < self->move_direction) 221 222 /* Core Functions */ 223 QResultClass *QR_Constructor(void); 224 void QR_Destructor(QResultClass *self); 225 TupleField *QR_AddNew(QResultClass *self); 226 int QR_next_tuple(QResultClass *self, StatementClass *); 227 int QR_close(QResultClass *self); 228 void QR_on_close_cursor(QResultClass *self); 229 void QR_close_result(QResultClass *self, BOOL destroy); 230 void QR_reset_for_re_execute(QResultClass *self); 231 BOOL QR_from_PGresult(QResultClass *self, StatementClass *stmt, ConnectionClass *conn, const char *cursor, PGresult **pgres); 232 void QR_free_memory(QResultClass *self); 233 void QR_set_command(QResultClass *self, const char *msg); 234 void QR_set_message(QResultClass *self, const char *msg); 235 void QR_add_message(QResultClass *self, const char *msg); 236 void QR_set_notice(QResultClass *self, const char *msg); 237 void QR_add_notice(QResultClass *self, const char *msg); 238 239 void QR_set_num_fields(QResultClass *self, int new_num_fields); /* catalog functions' result only */ 240 void QR_set_fields(QResultClass *self, ColumnInfoClass *); 241 242 void QR_set_num_cached_rows(QResultClass *, SQLLEN); 243 void QR_set_rowstart_in_cache(QResultClass *, SQLLEN); 244 void QR_inc_rowstart_in_cache(QResultClass *self, SQLLEN base_inc); 245 void QR_set_cache_size(QResultClass *self, SQLLEN cache_size); 246 void QR_set_reqsize(QResultClass *self, Int4 reqsize); 247 void QR_set_position(QResultClass *self, SQLLEN pos); 248 void QR_set_cursor(QResultClass *self, const char *name); 249 SQLLEN getNthValid(const QResultClass *self, SQLLEN sta, UWORD orientation, SQLULEN nth, SQLLEN *nearest); 250 SQLLEN QR_move_cursor_to_last(QResultClass *self, StatementClass *stmt); 251 BOOL QR_get_last_bookmark(const QResultClass *self, Int4 index, KeySet *keyset); 252 int QR_search_by_fieldname(const QResultClass *self, const char *name); 253 254 #define QR_MALLOC_return_with_error(t, tp, s, a, m, r) \ 255 do { \ 256 if (t = (tp *) malloc(s), NULL == t) \ 257 { \ 258 QR_set_rstatus(a, PORES_NO_MEMORY_ERROR); \ 259 qlog("QR_MALLOC_error\n"); \ 260 QR_free_memory(a); \ 261 QR_set_messageref(a, m); \ 262 return r; \ 263 } \ 264 } while (0) 265 #define QR_REALLOC_return_with_error(t, tp, s, a, m, r) \ 266 do { \ 267 tp *tmp; \ 268 if (tmp = (tp *) realloc(t, s), NULL == tmp) \ 269 { \ 270 QR_set_rstatus(a, PORES_NO_MEMORY_ERROR); \ 271 qlog("QR_REALLOC_error\n"); \ 272 QR_free_memory(a); \ 273 QR_set_messageref(a, m); \ 274 return r; \ 275 } \ 276 t = tmp; \ 277 } while (0) 278 #define QR_REALLOC_gexit_with_error(t, tp, s, a, m, r) \ 279 do { \ 280 tp *tmp; \ 281 if (tmp = (tp *) realloc(t, s), NULL == tmp) \ 282 { \ 283 QR_set_rstatus(a, PORES_NO_MEMORY_ERROR); \ 284 QR_free_memory(a); \ 285 QR_set_messageref(a, m); \ 286 r; \ 287 goto cleanup; \ 288 } \ 289 t = tmp; \ 290 } while (0) 291 292 #ifdef __cplusplus 293 } 294 #endif 295 #endif /* __QRESULT_H__ */ 296