4 * Description: This module contains functions for creating a manual result set
5 * (the TupleList) and retrieving data from it for a specific row/column.
7 * Classes: TupleListClass (Functions prefix: "TL_")
11 * Comments: See "notice.txt" for copyright and license information.
16 #include "tuplelist.h"
20 TL_Constructor(UInt4 fieldcnt)
24 mylog("in TL_Constructor\n");
26 rv = (TupleListClass *) malloc(sizeof(TupleListClass));
30 rv->num_fields = fieldcnt;
32 rv->list_start = NULL;
35 rv->last_indexed = -1;
38 mylog("exit TL_Constructor\n");
44 TL_Destructor(TupleListClass *self)
50 mylog("TupleList: in DESTRUCTOR\n");
52 node = self->list_start;
55 for (lf = 0; lf < self->num_fields; lf++)
56 if (node->tuple[lf].value != NULL)
57 free(node->tuple[lf].value);
65 mylog("TupleList: exit DESTRUCTOR\n");
70 TL_get_fieldval(TupleListClass *self, Int4 tupleno, Int2 fieldno)
79 if (self->last_indexed == -1)
80 /* we have an empty tuple list */
83 /* some more sanity checks */
84 if ((tupleno >= self->num_tuples) || (tupleno < 0))
85 /* illegal tuple number range */
88 if ((fieldno >= self->num_fields) || (fieldno < 0))
89 /* illegel field number range */
93 * check if we are accessing the same tuple that was used in the last
94 * fetch (e.g: for fetching all the fields one after another. Do this
97 if (tupleno == self->last_indexed)
98 return self->lastref->tuple[fieldno].value;
100 /* now for the tricky part... */
103 * Since random access is quite inefficient for linked lists we use
104 * the lastref pointer that points to the last element referenced by a
105 * get_fieldval() call in conjunction with the its index number that
106 * is stored in last_indexed. (So we use some locality of reference
107 * principle to speed things up)
110 delta = tupleno - self->last_indexed;
111 /* if delta is positive, we have to go forward */
114 * now check if we are closer to the start or the end of the list than
115 * to our last_indexed pointer
117 from_end = (self->num_tuples - 1) - tupleno;
119 start_is_closer = labs(delta) > tupleno;
122 * true if we are closer to the start of the list than to the
123 * last_indexed pointer
126 end_is_closer = labs(delta) > from_end;
127 /* true if we are closer at the end of the list */
131 /* scanning from the end is the shortest way. so we do that... */
133 for (lf = 0; lf < from_end; lf++)
136 else if (start_is_closer)
140 * the shortest way is to start the search from the head of the
143 rv = self->list_start;
144 for (lf = 0; lf < tupleno; lf++)
149 /* the closest way is starting from our lastref - pointer */
153 * at first determine whether we have to search forward or
158 /* we have to search backwards */
159 for (lf = 0; lf < (-1) * delta; lf++)
164 /* ok, we have to search forward... */
165 for (lf = 0; lf < delta; lf++)
171 * now we have got our return pointer, so update the lastref and the
172 * last_indexed values
175 self->last_indexed = tupleno;
177 return rv->tuple[fieldno].value;
183 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;
206 * there is already an element in the list, so add the new one at
207 * the end of the list
209 self->list_end->next = new_field;
210 new_field->prev = self->list_end;
211 self->list_end = new_field;
215 /* this method of building a list cannot fail, so we return 1 */