~ubuntu-branches/ubuntu/natty/psqlodbc/natty

« back to all changes in this revision

Viewing changes to tuplelist.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2004-05-13 10:47:36 UTC
  • Revision ID: james.westby@ubuntu.com-20040513104736-a530gmn0p3knep89
Tags: upstream-07.03.0200
ImportĀ upstreamĀ versionĀ 07.03.0200

Show diffs side-by-side

added added

removed removed

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