tuplelist.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:4k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /* Module:          tuplelist.c
  2.  *
  3.  * Description:     This module contains functions for creating a manual result set
  4.  *                  (the TupleList) and retrieving data from it for a specific row/column.
  5.  *
  6.  * Classes:         TupleListClass (Functions prefix: "TL_")
  7.  *
  8.  * API functions:   none
  9.  *
  10.  * Comments:        See "notice.txt" for copyright and license information.
  11.  *
  12.  */
  13. #include <stdlib.h>
  14. #include <malloc.h>
  15. #include "tuplelist.h"
  16. #include "tuple.h"
  17. TupleListClass *
  18. TL_Constructor(UInt4 fieldcnt)
  19. {
  20. TupleListClass *rv;
  21. mylog("in TL_Constructorn");
  22. rv = (TupleListClass *) malloc(sizeof(TupleListClass));
  23. if (rv) {
  24.         rv->num_fields = fieldcnt;
  25.         rv->num_tuples = 0;
  26.         rv->list_start = NULL;
  27.         rv->list_end = NULL;
  28.         rv->lastref = NULL;
  29.         rv->last_indexed = -1;
  30. }
  31. mylog("exit TL_Constructorn");
  32. return rv;
  33. }
  34. void
  35. TL_Destructor(TupleListClass *self)
  36. {
  37. int lf;
  38. TupleNode *node, *tp;
  39. mylog("TupleList: in DESTRUCTORn");
  40.     node = self->list_start;
  41.     while(node != NULL) {
  42.         for (lf=0; lf < self->num_fields; lf++)
  43.             if (node->tuple[lf].value != NULL) {
  44.                 free(node->tuple[lf].value);
  45.             }
  46.         tp = node->next;
  47.         free(node);
  48.         node = tp;
  49.     }
  50. free(self);
  51. mylog("TupleList: exit DESTRUCTORn");
  52. }
  53. void *
  54. TL_get_fieldval(TupleListClass *self, Int4 tupleno, Int2 fieldno)
  55. {
  56. Int4 lf;
  57. Int4 delta, from_end;
  58. char end_is_closer, start_is_closer;
  59. TupleNode *rv;
  60. if (self->last_indexed == -1)
  61. /* we have an empty tuple list */
  62. return NULL;
  63. /* some more sanity checks */
  64. if ((tupleno >= self->num_tuples) || (tupleno < 0))
  65. /* illegal tuple number range */
  66. return NULL;
  67. if ((fieldno >= self->num_fields) || (fieldno < 0))
  68. /* illegel field number range */
  69. return NULL;
  70.  /* check if we are accessing the same tuple that was used in
  71.     the last fetch (e.g: for fetching all the fields one after
  72.     another. Do this to speed things up
  73.  */
  74. if (tupleno == self->last_indexed)
  75. return self->lastref->tuple[fieldno].value;
  76.  /* now for the tricky part... */
  77.  /*
  78.  Since random access is quite inefficient for linked lists we use
  79.  the lastref pointer that points to the last element referenced
  80.  by a get_fieldval() call in conjunction with the its index number
  81.  that is stored in last_indexed. (So we use some locality of
  82.  reference principle to speed things up)
  83.  */
  84. delta = tupleno - self->last_indexed;
  85. /* if delta is positive, we have to go forward */
  86. /* now check if we are closer to the start or the end of the list
  87. than to our last_indexed pointer
  88. */
  89. from_end = (self->num_tuples - 1) - tupleno;
  90. start_is_closer = labs(delta) > tupleno;
  91. /* true if we are closer to the start of the list than to the
  92. last_indexed pointer
  93. */
  94. end_is_closer = labs(delta) > from_end;
  95. /* true if we are closer at the end of the list */
  96. if (end_is_closer) {
  97. /* scanning from the end is the shortest way. so we do that... */
  98. rv = self->list_end;
  99. for (lf=0; lf < from_end; lf++)
  100. rv = rv->prev;
  101. } else if (start_is_closer) {
  102. /* the shortest way is to start the search from the head of the list */
  103. rv = self->list_start;
  104. for (lf=0; lf < tupleno; lf++)
  105. rv = rv->next;
  106. } else {
  107. /* the closest way is starting from our lastref - pointer */
  108. rv = self->lastref;
  109. /* at first determine whether we have to search forward or backwards */
  110. if (delta < 0) {
  111. /* we have to search backwards */
  112. for(lf=0; lf < (-1)*delta; lf++)
  113. rv = rv->prev;
  114. } else {
  115. /* ok, we have to search forward... */
  116. for (lf=0; lf < delta; lf++)
  117. rv = rv->next;
  118. }
  119. }
  120. /* now we have got our return pointer, so update the lastref
  121. and the last_indexed values
  122. */
  123. self->lastref = rv;
  124. self->last_indexed = tupleno;
  125. return rv->tuple[fieldno].value;
  126. }
  127. char
  128. TL_add_tuple(TupleListClass *self, TupleNode *new_field)
  129. {
  130.  /* we append the tuple at the end of the doubly linked list
  131.     of the tuples we have already read in
  132.  */
  133. new_field->prev = NULL;
  134. new_field->next = NULL;
  135. if (self->list_start == NULL) {
  136. /* the list is empty, we have to add the first tuple */
  137. self->list_start = new_field;
  138. self->list_end = new_field;
  139. self->lastref = new_field;
  140. self->last_indexed = 0;
  141. } else {
  142. /* there is already an element in the list, so add the new
  143. one at the end of the list
  144. */
  145. self->list_end->next = new_field;
  146. new_field->prev = self->list_end;
  147. self->list_end = new_field;
  148. }
  149. self->num_tuples++;
  150. /* this method of building a list cannot fail, so we return 1 */
  151. return 1;
  152. }