summaryrefslogtreecommitdiff
path: root/src/interfaces/odbc/tuplelist.c
diff options
context:
space:
mode:
authorMarc G. Fournier <scrappy@hub.org>1998-04-13 15:02:05 +0000
committerMarc G. Fournier <scrappy@hub.org>1998-04-13 15:02:05 +0000
commit9e3382dfc5affce3b653534714343d5e546e1a3e (patch)
treee5627cb0e135d52c2e4af55a239795d18ba5e7f9 /src/interfaces/odbc/tuplelist.c
parentd4d26f9c33791f7aefd667e3688d9a18400006e1 (diff)
Replace old PostODBC driver with new one...
This one is based on an older PostODBC driver, rewritten and maintained by InsightDist(?)
Diffstat (limited to 'src/interfaces/odbc/tuplelist.c')
-rw-r--r--src/interfaces/odbc/tuplelist.c188
1 files changed, 188 insertions, 0 deletions
diff --git a/src/interfaces/odbc/tuplelist.c b/src/interfaces/odbc/tuplelist.c
new file mode 100644
index 00000000000..80b962482f2
--- /dev/null
+++ b/src/interfaces/odbc/tuplelist.c
@@ -0,0 +1,188 @@
+
+/* 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 <stdlib.h>
+#include <malloc.h>
+#include "tuplelist.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;
+}
+
+