4
* Description: This module contains functions for creating a manual
5
* result set (the TupleList) and retrieving data from
6
* it for a specific row/column.
8
* Classes: TupleListClass (Functions prefix: "TL_")
12
* Comments: See "notice.txt" for copyright and license information.
16
#include "tuplelist.h"
23
TL_Constructor(UInt4 fieldcnt)
27
mylog("in TL_Constructor\n");
29
rv = (TupleListClass *) malloc(sizeof(TupleListClass));
32
rv->num_fields = fieldcnt;
34
rv->list_start = NULL;
37
rv->last_indexed = -1;
40
mylog("exit TL_Constructor\n");
47
TL_Destructor(TupleListClass *self)
53
mylog("TupleList: in DESTRUCTOR\n");
55
node = self->list_start;
58
for (lf = 0; lf < self->num_fields; lf++)
59
if (node->tuple[lf].value != NULL)
60
free(node->tuple[lf].value);
68
mylog("TupleList: exit DESTRUCTOR\n");
73
TL_get_fieldval(TupleListClass *self, Int4 tupleno, Int2 fieldno)
82
if (self->last_indexed == -1)
83
/* we have an empty tuple list */
86
/* some more sanity checks */
87
if ((tupleno >= self->num_tuples) || (tupleno < 0))
88
/* illegal tuple number range */
91
if ((fieldno >= self->num_fields) || (fieldno < 0))
92
/* illegel field number range */
96
* check if we are accessing the same tuple that was used in the last
97
* fetch (e.g: for fetching all the fields one after another. Do this
100
if (tupleno == self->last_indexed)
101
return self->lastref->tuple[fieldno].value;
103
/* now for the tricky part... */
106
* Since random access is quite inefficient for linked lists we use
107
* the lastref pointer that points to the last element referenced by a
108
* get_fieldval() call in conjunction with the its index number that
109
* is stored in last_indexed. (So we use some locality of reference
110
* principle to speed things up)
113
delta = tupleno - self->last_indexed;
114
/* if delta is positive, we have to go forward */
117
* now check if we are closer to the start or the end of the list than
118
* to our last_indexed pointer
120
from_end = (self->num_tuples - 1) - tupleno;
122
start_is_closer = labs(delta) > tupleno;
125
* true if we are closer to the start of the list than to the
126
* last_indexed pointer
129
end_is_closer = labs(delta) > from_end;
130
/* true if we are closer at the end of the list */
134
/* scanning from the end is the shortest way. so we do that... */
136
for (lf = 0; lf < from_end; lf++)
139
else if (start_is_closer)
142
* the shortest way is to start the search from the head of the
145
rv = self->list_start;
146
for (lf = 0; lf < tupleno; lf++)
151
/* the closest way is starting from our lastref - pointer */
155
* at first determine whether we have to search forward or
160
/* we have to search backwards */
161
for (lf = 0; lf < (-1) * delta; lf++)
166
/* ok, we have to search forward... */
167
for (lf = 0; lf < delta; lf++)
173
* now we have got our return pointer, so update the lastref and the
174
* last_indexed values
177
self->last_indexed = tupleno;
179
return rv->tuple[fieldno].value;
184
TL_add_tuple(TupleListClass *self, TupleNode *new_field)
187
* we append the tuple at the end of the doubly linked list of the
188
* tuples we have already read in
191
new_field->prev = NULL;
192
new_field->next = NULL;
194
if (self->list_start == NULL)
196
/* the list is empty, we have to add the first tuple */
197
self->list_start = new_field;
198
self->list_end = new_field;
199
self->lastref = new_field;
200
self->last_indexed = 0;
205
* there is already an element in the list, so add the new one at
206
* the end of the list
208
self->list_end->next = new_field;
209
new_field->prev = self->list_end;
210
self->list_end = new_field;
214
/* this method of building a list cannot fail, so we return 1 */