OSDN Git Service

pgindent run. Make it all clean.
[pg-rex/syncrep.git] / src / interfaces / odbc / tuplelist.c
1
2 /* Module:                      tuplelist.c
3  *
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.
6  *
7  * Classes:                     TupleListClass (Functions prefix: "TL_")
8  *
9  * API functions:       none
10  *
11  * Comments:            See "notice.txt" for copyright and license information.
12  *
13  */
14
15 #include <stdlib.h>
16 #include "tuplelist.h"
17 #include "tuple.h"
18
19 TupleListClass *
20 TL_Constructor(UInt4 fieldcnt)
21 {
22         TupleListClass *rv;
23
24         mylog("in TL_Constructor\n");
25
26         rv = (TupleListClass *) malloc(sizeof(TupleListClass));
27         if (rv)
28         {
29
30                 rv->num_fields = fieldcnt;
31                 rv->num_tuples = 0;
32                 rv->list_start = NULL;
33                 rv->list_end = NULL;
34                 rv->lastref = NULL;
35                 rv->last_indexed = -1;
36         }
37
38         mylog("exit TL_Constructor\n");
39
40         return rv;
41 }
42
43 void
44 TL_Destructor(TupleListClass *self)
45 {
46         int                     lf;
47         TupleNode  *node,
48                            *tp;
49
50         mylog("TupleList: in DESTRUCTOR\n");
51
52         node = self->list_start;
53         while (node != NULL)
54         {
55                 for (lf = 0; lf < self->num_fields; lf++)
56                         if (node->tuple[lf].value != NULL)
57                                 free(node->tuple[lf].value);
58                 tp = node->next;
59                 free(node);
60                 node = tp;
61         }
62
63         free(self);
64
65         mylog("TupleList: exit DESTRUCTOR\n");
66 }
67
68
69 void *
70 TL_get_fieldval(TupleListClass *self, Int4 tupleno, Int2 fieldno)
71 {
72         Int4            lf;
73         Int4            delta,
74                                 from_end;
75         char            end_is_closer,
76                                 start_is_closer;
77         TupleNode  *rv;
78
79         if (self->last_indexed == -1)
80                 /* we have an empty tuple list */
81                 return NULL;
82
83         /* some more sanity checks */
84         if ((tupleno >= self->num_tuples) || (tupleno < 0))
85                 /* illegal tuple number range */
86                 return NULL;
87
88         if ((fieldno >= self->num_fields) || (fieldno < 0))
89                 /* illegel field number range */
90                 return NULL;
91
92         /*
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
95          * to speed things up
96          */
97         if (tupleno == self->last_indexed)
98                 return self->lastref->tuple[fieldno].value;
99
100         /* now for the tricky part... */
101
102         /*
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)
108          */
109
110         delta = tupleno - self->last_indexed;
111         /* if delta is positive, we have to go forward */
112
113         /*
114          * now check if we are closer to the start or the end of the list than
115          * to our last_indexed pointer
116          */
117         from_end = (self->num_tuples - 1) - tupleno;
118
119         start_is_closer = labs(delta) > tupleno;
120
121         /*
122          * true if we are closer to the start of the list than to the
123          * last_indexed pointer
124          */
125
126         end_is_closer = labs(delta) > from_end;
127         /* true if we are closer at the end of the list */
128
129         if (end_is_closer)
130         {
131                 /* scanning from the end is the shortest way. so we do that... */
132                 rv = self->list_end;
133                 for (lf = 0; lf < from_end; lf++)
134                         rv = rv->prev;
135         }
136         else if (start_is_closer)
137         {
138
139                 /*
140                  * the shortest way is to start the search from the head of the
141                  * list
142                  */
143                 rv = self->list_start;
144                 for (lf = 0; lf < tupleno; lf++)
145                         rv = rv->next;
146         }
147         else
148         {
149                 /* the closest way is starting from our lastref - pointer */
150                 rv = self->lastref;
151
152                 /*
153                  * at first determine whether we have to search forward or
154                  * backwards
155                  */
156                 if (delta < 0)
157                 {
158                         /* we have to search backwards */
159                         for (lf = 0; lf < (-1) * delta; lf++)
160                                 rv = rv->prev;
161                 }
162                 else
163                 {
164                         /* ok, we have to search forward... */
165                         for (lf = 0; lf < delta; lf++)
166                                 rv = rv->next;
167                 }
168         }
169
170         /*
171          * now we have got our return pointer, so update the lastref and the
172          * last_indexed values
173          */
174         self->lastref = rv;
175         self->last_indexed = tupleno;
176
177         return rv->tuple[fieldno].value;
178 }
179
180
181
182 char
183 TL_add_tuple(TupleListClass *self, TupleNode *new_field)
184 {
185
186         /*
187          * we append the tuple at the end of the doubly linked list of the
188          * tuples we have already read in
189          */
190
191         new_field->prev = NULL;
192         new_field->next = NULL;
193
194         if (self->list_start == NULL)
195         {
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;
201         }
202         else
203         {
204
205                 /*
206                  * there is already an element in the list, so add the new one at
207                  * the end of the list
208                  */
209                 self->list_end->next = new_field;
210                 new_field->prev = self->list_end;
211                 self->list_end = new_field;
212         }
213         self->num_tuples++;
214
215         /* this method of building a list cannot fail, so we return 1 */
216         return 1;
217 }