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