diff options
author | Hiroshi Inoue <inoue@tpf.co.jp> | 2002-01-11 02:50:01 +0000 |
---|---|---|
committer | Hiroshi Inoue <inoue@tpf.co.jp> | 2002-01-11 02:50:01 +0000 |
commit | f43b5de649cdf8a36f7d90a96932800cb0e34162 (patch) | |
tree | 6fb1ec57cff266680ab2adaf8c0976a643627b7c /src/interfaces/odbc/windev/tuplelist.c | |
parent | 5370cd6b03610bdb6c6dee0fbf87ad9cdf524395 (diff) |
Add a directory to save the changes until 7.3-tree is branched.
Diffstat (limited to 'src/interfaces/odbc/windev/tuplelist.c')
-rw-r--r-- | src/interfaces/odbc/windev/tuplelist.c | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/src/interfaces/odbc/windev/tuplelist.c b/src/interfaces/odbc/windev/tuplelist.c new file mode 100644 index 00000000000..0ae2130bff4 --- /dev/null +++ b/src/interfaces/odbc/windev/tuplelist.c @@ -0,0 +1,216 @@ +/*-------- + * Module: tuplelist.c + * + * Description: This module contains functions for creating a manual + * result set (the TupleList) and retrieving data from + * it for a specific row/column. + * + * Classes: TupleListClass (Functions prefix: "TL_") + * + * API functions: none + * + * Comments: See "notice.txt" for copyright and license information. + *-------- + */ + +#include "tuplelist.h" + +#include <stdlib.h> +#include "tuple.h" + + +TupleListClass * +TL_Constructor(UInt4 fieldcnt) +{ + TupleListClass *rv; + + mylog("in TL_Constructor\n"); + + rv = (TupleListClass *) malloc(sizeof(TupleListClass)); + if (rv) + { + rv->num_fields = fieldcnt; + rv->num_tuples = 0; + rv->list_start = NULL; + rv->list_end = NULL; + rv->lastref = NULL; + rv->last_indexed = -1; + } + + mylog("exit TL_Constructor\n"); + + return rv; +} + + +void +TL_Destructor(TupleListClass *self) +{ + int lf; + TupleNode *node, + *tp; + + mylog("TupleList: in DESTRUCTOR\n"); + + node = self->list_start; + while (node != NULL) + { + for (lf = 0; lf < self->num_fields; lf++) + if (node->tuple[lf].value != NULL) + free(node->tuple[lf].value); + tp = node->next; + free(node); + node = tp; + } + + free(self); + + mylog("TupleList: exit DESTRUCTOR\n"); +} + + +void * +TL_get_fieldval(TupleListClass *self, Int4 tupleno, Int2 fieldno) +{ + Int4 lf; + Int4 delta, + from_end; + char end_is_closer, + start_is_closer; + TupleNode *rv; + + if (self->last_indexed == -1) + /* we have an empty tuple list */ + return NULL; + + /* some more sanity checks */ + if ((tupleno >= self->num_tuples) || (tupleno < 0)) + /* illegal tuple number range */ + return NULL; + + if ((fieldno >= self->num_fields) || (fieldno < 0)) + /* illegel field number range */ + return NULL; + + /* + * check if we are accessing the same tuple that was used in the last + * fetch (e.g: for fetching all the fields one after another. Do this + * to speed things up + */ + if (tupleno == self->last_indexed) + return self->lastref->tuple[fieldno].value; + + /* now for the tricky part... */ + + /* + * Since random access is quite inefficient for linked lists we use + * the lastref pointer that points to the last element referenced by a + * get_fieldval() call in conjunction with the its index number that + * is stored in last_indexed. (So we use some locality of reference + * principle to speed things up) + */ + + delta = tupleno - self->last_indexed; + /* if delta is positive, we have to go forward */ + + /* + * now check if we are closer to the start or the end of the list than + * to our last_indexed pointer + */ + from_end = (self->num_tuples - 1) - tupleno; + + start_is_closer = labs(delta) > tupleno; + + /* + * true if we are closer to the start of the list than to the + * last_indexed pointer + */ + + end_is_closer = labs(delta) > from_end; + /* true if we are closer at the end of the list */ + + if (end_is_closer) + { + /* scanning from the end is the shortest way. so we do that... */ + rv = self->list_end; + for (lf = 0; lf < from_end; lf++) + rv = rv->prev; + } + else if (start_is_closer) + { + /* + * the shortest way is to start the search from the head of the + * list + */ + rv = self->list_start; + for (lf = 0; lf < tupleno; lf++) + rv = rv->next; + } + else + { + /* the closest way is starting from our lastref - pointer */ + rv = self->lastref; + + /* + * at first determine whether we have to search forward or + * backwards + */ + if (delta < 0) + { + /* we have to search backwards */ + for (lf = 0; lf < (-1) * delta; lf++) + rv = rv->prev; + } + else + { + /* ok, we have to search forward... */ + for (lf = 0; lf < delta; lf++) + rv = rv->next; + } + } + + /* + * now we have got our return pointer, so update the lastref and the + * last_indexed values + */ + self->lastref = rv; + self->last_indexed = tupleno; + + return rv->tuple[fieldno].value; +} + + +char +TL_add_tuple(TupleListClass *self, TupleNode *new_field) +{ + /* + * we append the tuple at the end of the doubly linked list of the + * tuples we have already read in + */ + + new_field->prev = NULL; + new_field->next = NULL; + + if (self->list_start == NULL) + { + /* the list is empty, we have to add the first tuple */ + self->list_start = new_field; + self->list_end = new_field; + self->lastref = new_field; + self->last_indexed = 0; + } + else + { + /* + * there is already an element in the list, so add the new one at + * the end of the list + */ + self->list_end->next = new_field; + new_field->prev = self->list_end; + self->list_end = new_field; + } + self->num_tuples++; + + /* this method of building a list cannot fail, so we return 1 */ + return 1; +} |