FIXME: toplevel Makefile: 'make ntest' doesn't run versaplexd for now.
[versaplex.git] / vxodbc / qresult.cc
blobae95a044a74a08054b5e474ec2d0950b438d3eac
1 /*
2 * Description: This module contains functions related to
3 * managing result information (i.e, fetching rows
4 * from the backend, managing the tuple cache, etc.)
5 * and retrieving it. Depending on the situation, a
6 * QResultClass will hold either data from the backend
7 * or a manually built result.
8 */
9 #include "qresult.h"
10 #include "statement.h"
12 #include "misc.h"
13 #include <stdio.h>
14 #include <string.h>
15 #include <limits.h>
18 * Used for building a Manual Result only
19 * All info functions call this function to create the manual result set.
21 void QR_set_num_fields(QResultClass * self, int new_num_fields)
23 BOOL allocrelatt = FALSE;
25 if (!self)
26 return;
27 mylog("in QR_set_num_fields\n");
29 CI_set_num_fields(self->fields, new_num_fields, allocrelatt);
31 mylog("exit QR_set_num_fields\n");
35 void QR_set_position(QResultClass * self, SQLLEN pos)
37 self->tupleField =
38 self->backend_tuples +
39 ((QR_get_rowstart_in_cache(self) + pos) * self->num_fields);
43 void QR_set_cache_size(QResultClass * self, SQLLEN cache_size)
45 self->cache_size = cache_size;
49 void QR_set_rowset_size(QResultClass * self, Int4 rowset_size)
51 self->rowset_size_include_ommitted = rowset_size;
54 void QR_set_cursor(QResultClass * self, const char *name)
56 ConnectionClass *conn = QR_get_conn(self);
58 if (self->cursor_name)
60 free(self->cursor_name);
61 if (conn)
63 CONNLOCK_ACQUIRE(conn);
64 conn->ncursors--;
65 CONNLOCK_RELEASE(conn);
67 self->cursTuple = -1;
68 self->pstatus = 0;
70 if (name)
72 self->cursor_name = strdup(name);
73 if (conn)
75 CONNLOCK_ACQUIRE(conn);
76 conn->ncursors++;
77 CONNLOCK_RELEASE(conn);
79 } else
81 self->cursor_name = NULL;
82 QR_set_no_cursor(self);
87 void QR_set_num_cached_rows(QResultClass * self, SQLLEN num_rows)
89 self->num_cached_rows = num_rows;
90 if (QR_synchronize_keys(self))
91 self->num_cached_keys = self->num_cached_rows;
94 void QR_set_rowstart_in_cache(QResultClass * self, SQLLEN start)
96 mylog("qrflags:%x\n", (int)self->flags);
97 if (QR_synchronize_keys(self))
98 self->key_base = start;
99 self->base = start;
102 void QR_inc_rowstart_in_cache(QResultClass * self, SQLLEN base_inc)
104 if (!QR_has_valid_base(self))
105 mylog
106 ("QR_inc_rowstart_in_cache called while the cache is not ready\n");
107 self->base += base_inc;
108 if (QR_synchronize_keys(self))
109 self->key_base = self->base;
114 * CLASS QResult
116 QResultClass *QR_Constructor()
118 QResultClass *rv;
120 mylog("in QR_Constructor\n");
121 rv = (QResultClass *) malloc(sizeof(QResultClass));
123 if (rv != NULL)
125 rv->rstatus = PORES_EMPTY_QUERY;
126 rv->pstatus = 0;
128 /* construct the column info */
129 if (!(rv->fields = CI_Constructor()))
131 free(rv);
132 return NULL;
134 rv->backend_tuples = NULL;
135 rv->sqlstate[0] = '\0';
136 rv->message = NULL;
137 rv->command = NULL;
138 rv->notice = NULL;
139 rv->conn = NULL;
140 rv->next = NULL;
141 rv->pstatus = 0;
142 rv->count_backend_allocated = 0;
143 rv->count_keyset_allocated = 0;
144 rv->num_total_read = 0;
145 rv->num_cached_rows = 0;
146 rv->num_cached_keys = 0;
147 rv->fetch_number = 0;
148 rv->flags = 0;
149 QR_set_rowstart_in_cache(rv, -1);
150 rv->key_base = -1;
151 rv->recent_processed_row_count = -1;
152 rv->cursTuple = -1;
153 rv->move_offset = 0;
154 rv->num_fields = 0;
155 rv->num_key_fields = PG_NUM_NORMAL_KEYS; /* CTID + OID */
156 rv->tupleField = NULL;
157 rv->cursor_name = NULL;
158 rv->aborted = FALSE;
160 rv->cache_size = 0;
161 rv->rowset_size_include_ommitted = 1;
162 rv->move_direction = 0;
163 rv->keyset = NULL;
164 rv->reload_count = 0;
165 rv->rb_alloc = 0;
166 rv->rb_count = 0;
167 rv->rollback = NULL;
168 rv->ad_alloc = 0;
169 rv->ad_count = 0;
170 rv->added_keyset = NULL;
171 rv->added_tuples = NULL;
172 rv->up_alloc = 0;
173 rv->up_count = 0;
174 rv->updated = NULL;
175 rv->updated_keyset = NULL;
176 rv->updated_tuples = NULL;
177 rv->dl_alloc = 0;
178 rv->dl_count = 0;
179 rv->deleted = NULL;
180 rv->deleted_keyset = NULL;
183 mylog("exit QR_Constructor\n");
184 return rv;
188 // VX_CLEANUP: There's a decent chance this is useless
189 void QR_close_result(QResultClass * self, BOOL destroy)
191 ConnectionClass *conn;
193 if (!self)
194 return;
195 mylog("QResult: in QR_close_result\n");
198 * If conn is defined, then we may have used "backend_tuples", so in
199 * case we need to, free it up. Also, close the cursor.
201 QR_free_memory(self); /* safe to call anyway */
203 /* Should have been freed in the close() but just in case... */
204 QR_set_cursor(self, NULL);
206 /* Free up column info */
207 if (destroy && self->fields)
209 CI_Destructor(self->fields);
210 self->fields = NULL;
213 /* Free command info (this is from strdup()) */
214 if (self->command)
216 free(self->command);
217 self->command = NULL;
220 /* Free message info (this is from strdup()) */
221 if (self->message)
223 free(self->message);
224 self->message = NULL;
227 /* Free notice info (this is from strdup()) */
228 if (self->notice)
230 free(self->notice);
231 self->notice = NULL;
233 /* Destruct the result object in the chain */
234 QR_Destructor(self->next);
235 self->next = NULL;
237 mylog("QResult: exit close_result\n");
238 if (destroy)
240 free(self);
244 void QR_Destructor(QResultClass * self)
246 mylog("QResult: enter DESTRUCTOR (%p)\n", self);
247 if (!self)
248 return;
249 QR_close_result(self, TRUE);
251 mylog("QResult: exit DESTRUCTOR\n");
255 void QR_set_command(QResultClass * self, const char *msg)
257 if (self->command)
258 free(self->command);
260 self->command = msg ? strdup(msg) : NULL;
264 void QR_set_message(QResultClass * self, const char *msg)
266 if (self->message)
267 free(self->message);
269 self->message = msg ? strdup(msg) : NULL;
272 void QR_add_message(QResultClass * self, const char *msg)
274 char *message = self->message;
275 size_t alsize, pos;
277 if (!msg || !msg[0])
278 return;
279 if (message)
281 pos = strlen(message) + 1;
282 alsize = pos + strlen(msg) + 1;
283 } else
285 pos = 0;
286 alsize = strlen(msg) + 1;
288 message = (char *)realloc(message, alsize);
289 if (pos > 0)
290 message[pos - 1] = ';';
291 strcpy(message + pos, msg);
292 self->message = message;
296 void QR_set_notice(QResultClass * self, const char *msg)
298 if (self->notice)
299 free(self->notice);
301 self->notice = msg ? strdup(msg) : NULL;
304 void QR_add_notice(QResultClass * self, const char *msg)
306 char *message = self->notice;
307 size_t alsize, pos;
309 if (!msg || !msg[0])
310 return;
311 if (message)
313 pos = strlen(message) + 1;
314 alsize = pos + strlen(msg) + 1;
315 } else
317 pos = 0;
318 alsize = strlen(msg) + 1;
320 message = (char *)realloc(message, alsize);
321 if (pos > 0)
322 message[pos - 1] = ';';
323 strcpy(message + pos, msg);
324 self->notice = message;
328 TupleField *QR_AddNew(QResultClass * self)
330 size_t alloc;
331 UInt4 num_fields;
333 if (!self)
334 return NULL;
335 inolog("QR_AddNew %dth row(%d fields) alloc=%d\n",
336 self->num_cached_rows, QR_NumResultCols(self),
337 self->count_backend_allocated);
338 if (num_fields = QR_NumResultCols(self), !num_fields)
339 return NULL;
340 if (self->num_fields <= 0)
342 self->num_fields = num_fields;
343 QR_set_reached_eof(self);
345 alloc = self->count_backend_allocated;
346 if (!self->backend_tuples)
348 self->num_cached_rows = 0;
349 alloc = TUPLE_MALLOC_INC;
350 self->backend_tuples = (TupleField *)
351 malloc(alloc * sizeof(TupleField) * num_fields);
352 } else if (self->num_cached_rows >= self->count_backend_allocated)
354 alloc = self->count_backend_allocated * 2;
355 self->backend_tuples = (TupleField *)
356 realloc(self->backend_tuples,
357 alloc * sizeof(TupleField) * num_fields);
359 self->count_backend_allocated = alloc;
361 if (self->backend_tuples)
363 memset(self->backend_tuples +
364 num_fields * self->num_cached_rows, 0,
365 num_fields * sizeof(TupleField));
366 self->num_cached_rows++;
367 self->ad_count++;
369 return self->backend_tuples + num_fields * (self->num_cached_rows -
373 void QR_free_memory(QResultClass * self)
375 SQLLEN num_backend_rows = self->num_cached_rows;
376 int num_fields = self->num_fields;
378 mylog("QResult: free memory in, fcount=%d\n", num_backend_rows);
380 if (self->backend_tuples)
382 ClearCachedRows(self->backend_tuples, num_fields,
383 num_backend_rows);
384 free(self->backend_tuples);
385 self->count_backend_allocated = 0;
386 self->backend_tuples = NULL;
388 if (self->keyset)
390 ConnectionClass *conn = QR_get_conn(self);
392 free(self->keyset);
393 self->keyset = NULL;
394 self->count_keyset_allocated = 0;
395 // VX_CLEANUP: It might be smart to find whatever allocates this, and
396 // kill it too.
397 // VX_CLEANUP: Some of the remainder here might also be useless.
398 self->reload_count = 0;
400 if (self->rollback)
402 free(self->rollback);
403 self->rb_alloc = 0;
404 self->rb_count = 0;
405 self->rollback = NULL;
407 if (self->deleted)
409 free(self->deleted);
410 self->deleted = NULL;
412 if (self->deleted_keyset)
414 free(self->deleted_keyset);
415 self->deleted_keyset = NULL;
417 self->dl_alloc = 0;
418 self->dl_count = 0;
419 /* clear added info */
420 if (self->added_keyset)
422 free(self->added_keyset);
423 self->added_keyset = NULL;
425 if (self->added_tuples)
427 ClearCachedRows(self->added_tuples, num_fields, self->ad_count);
428 free(self->added_tuples);
429 self->added_tuples = NULL;
431 self->ad_alloc = 0;
432 self->ad_count = 0;
433 /* clear updated info */
434 if (self->updated)
436 free(self->updated);
437 self->updated = NULL;
439 if (self->updated_keyset)
441 free(self->updated_keyset);
442 self->updated_keyset = NULL;
444 if (self->updated_tuples)
446 ClearCachedRows(self->updated_tuples, num_fields,
447 self->up_count);
448 free(self->updated_tuples);
449 self->updated_tuples = NULL;
451 self->up_alloc = 0;
452 self->up_count = 0;
454 self->num_total_read = 0;
455 self->num_cached_rows = 0;
456 self->num_cached_keys = 0;
457 self->cursTuple = -1;
458 self->pstatus = 0;
460 mylog("QResult: free memory out\n");
464 static SQLLEN enlargeKeyCache(QResultClass * self, SQLLEN add_size,
465 const char *message)
467 size_t alloc, alloc_req;
468 Int4 num_fields = self->num_fields;
469 BOOL curs = (NULL != QR_get_cursor(self));
471 if (add_size <= 0)
472 return self->count_keyset_allocated;
473 alloc = self->count_backend_allocated;
474 if (num_fields > 0
475 && ((alloc_req = (Int4) self->num_cached_rows + add_size) >
476 alloc || !self->backend_tuples))
478 if (1 > alloc)
480 if (curs)
481 alloc = alloc_req;
482 else
483 alloc =
484 (alloc_req >
485 TUPLE_MALLOC_INC ? alloc_req : TUPLE_MALLOC_INC);
486 } else
490 alloc *= 2;
492 while (alloc < alloc_req);
494 self->count_backend_allocated = 0;
495 QR_REALLOC_return_with_error(self->backend_tuples, TupleField,
496 num_fields * sizeof(TupleField) *
497 alloc, self, message, -1);
498 self->count_backend_allocated = alloc;
500 alloc = self->count_keyset_allocated;
501 if (QR_haskeyset(self)
502 && ((alloc_req = (Int4) self->num_cached_keys + add_size) >
503 alloc || !self->keyset))
505 if (1 > alloc)
507 if (curs)
508 alloc = alloc_req;
509 else
510 alloc =
511 (alloc_req >
512 TUPLE_MALLOC_INC ? alloc_req : TUPLE_MALLOC_INC);
513 } else
517 alloc *= 2;
519 while (alloc < alloc_req);
521 self->count_keyset_allocated = 0;
522 QR_REALLOC_return_with_error(self->keyset, KeySet,
523 sizeof(KeySet) * alloc, self,
524 message, -1);
525 self->count_keyset_allocated = alloc;
527 return alloc;