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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * rtget.c
  4.  *   fetch tuples from an rtree scan.
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/access/rtree/rtget.c,v 1.13.2.1 1999/08/02 05:24:43 scrappy Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. #include "postgres.h"
  15. #include "access/iqual.h"
  16. #include "access/rtree.h"
  17. static OffsetNumber findnext(IndexScanDesc s, Page p, OffsetNumber n,
  18.  ScanDirection dir);
  19. static RetrieveIndexResult rtscancache(IndexScanDesc s, ScanDirection dir);
  20. static RetrieveIndexResult rtfirst(IndexScanDesc s, ScanDirection dir);
  21. static RetrieveIndexResult rtnext(IndexScanDesc s, ScanDirection dir);
  22. static ItemPointer rtheapptr(Relation r, ItemPointer itemp);
  23. RetrieveIndexResult
  24. rtgettuple(IndexScanDesc s, ScanDirection dir)
  25. {
  26. RetrieveIndexResult res;
  27. /* if we have it cached in the scan desc, just return the value */
  28. if ((res = rtscancache(s, dir)) != (RetrieveIndexResult) NULL)
  29. return res;
  30. /* not cached, so we'll have to do some work */
  31. if (ItemPointerIsValid(&(s->currentItemData)))
  32. res = rtnext(s, dir);
  33. else
  34. res = rtfirst(s, dir);
  35. return res;
  36. }
  37. static RetrieveIndexResult
  38. rtfirst(IndexScanDesc s, ScanDirection dir)
  39. {
  40. Buffer b;
  41. Page p;
  42. OffsetNumber n;
  43. OffsetNumber maxoff;
  44. RetrieveIndexResult res;
  45. RTreePageOpaque po;
  46. RTreeScanOpaque so;
  47. RTSTACK    *stk;
  48. BlockNumber blk;
  49. IndexTuple it;
  50. b = ReadBuffer(s->relation, P_ROOT);
  51. p = BufferGetPage(b);
  52. po = (RTreePageOpaque) PageGetSpecialPointer(p);
  53. so = (RTreeScanOpaque) s->opaque;
  54. for (;;)
  55. {
  56. maxoff = PageGetMaxOffsetNumber(p);
  57. if (ScanDirectionIsBackward(dir))
  58. n = findnext(s, p, maxoff, dir);
  59. else
  60. n = findnext(s, p, FirstOffsetNumber, dir);
  61. while (n < FirstOffsetNumber || n > maxoff)
  62. {
  63. ReleaseBuffer(b);
  64. if (so->s_stack == (RTSTACK *) NULL)
  65. return (RetrieveIndexResult) NULL;
  66. stk = so->s_stack;
  67. b = ReadBuffer(s->relation, stk->rts_blk);
  68. p = BufferGetPage(b);
  69. po = (RTreePageOpaque) PageGetSpecialPointer(p);
  70. maxoff = PageGetMaxOffsetNumber(p);
  71. if (ScanDirectionIsBackward(dir))
  72. n = OffsetNumberPrev(stk->rts_child);
  73. else
  74. n = OffsetNumberNext(stk->rts_child);
  75. so->s_stack = stk->rts_parent;
  76. pfree(stk);
  77. n = findnext(s, p, n, dir);
  78. }
  79. if (po->flags & F_LEAF)
  80. {
  81. ItemPointerSet(&(s->currentItemData), BufferGetBlockNumber(b), n);
  82. it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
  83. res = FormRetrieveIndexResult(&(s->currentItemData), &(it->t_tid));
  84. ReleaseBuffer(b);
  85. return res;
  86. }
  87. else
  88. {
  89. stk = (RTSTACK *) palloc(sizeof(RTSTACK));
  90. stk->rts_child = n;
  91. stk->rts_blk = BufferGetBlockNumber(b);
  92. stk->rts_parent = so->s_stack;
  93. so->s_stack = stk;
  94. it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
  95. blk = ItemPointerGetBlockNumber(&(it->t_tid));
  96. ReleaseBuffer(b);
  97. b = ReadBuffer(s->relation, blk);
  98. p = BufferGetPage(b);
  99. po = (RTreePageOpaque) PageGetSpecialPointer(p);
  100. }
  101. }
  102. }
  103. static RetrieveIndexResult
  104. rtnext(IndexScanDesc s, ScanDirection dir)
  105. {
  106. Buffer b;
  107. Page p;
  108. OffsetNumber n;
  109. OffsetNumber maxoff;
  110. RetrieveIndexResult res;
  111. RTreePageOpaque po;
  112. RTreeScanOpaque so;
  113. RTSTACK    *stk;
  114. BlockNumber blk;
  115. IndexTuple it;
  116. blk = ItemPointerGetBlockNumber(&(s->currentItemData));
  117. n = ItemPointerGetOffsetNumber(&(s->currentItemData));
  118. if (ScanDirectionIsForward(dir))
  119. n = OffsetNumberNext(n);
  120. else
  121. n = OffsetNumberPrev(n);
  122. b = ReadBuffer(s->relation, blk);
  123. p = BufferGetPage(b);
  124. po = (RTreePageOpaque) PageGetSpecialPointer(p);
  125. so = (RTreeScanOpaque) s->opaque;
  126. for (;;)
  127. {
  128. maxoff = PageGetMaxOffsetNumber(p);
  129. n = findnext(s, p, n, dir);
  130. while (n < FirstOffsetNumber || n > maxoff)
  131. {
  132. ReleaseBuffer(b);
  133. if (so->s_stack == (RTSTACK *) NULL)
  134. return (RetrieveIndexResult) NULL;
  135. stk = so->s_stack;
  136. b = ReadBuffer(s->relation, stk->rts_blk);
  137. p = BufferGetPage(b);
  138. maxoff = PageGetMaxOffsetNumber(p);
  139. po = (RTreePageOpaque) PageGetSpecialPointer(p);
  140. if (ScanDirectionIsBackward(dir))
  141. n = OffsetNumberPrev(stk->rts_child);
  142. else
  143. n = OffsetNumberNext(stk->rts_child);
  144. so->s_stack = stk->rts_parent;
  145. pfree(stk);
  146. n = findnext(s, p, n, dir);
  147. }
  148. if (po->flags & F_LEAF)
  149. {
  150. ItemPointerSet(&(s->currentItemData), BufferGetBlockNumber(b), n);
  151. it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
  152. res = FormRetrieveIndexResult(&(s->currentItemData), &(it->t_tid));
  153. ReleaseBuffer(b);
  154. return res;
  155. }
  156. else
  157. {
  158. stk = (RTSTACK *) palloc(sizeof(RTSTACK));
  159. stk->rts_child = n;
  160. stk->rts_blk = BufferGetBlockNumber(b);
  161. stk->rts_parent = so->s_stack;
  162. so->s_stack = stk;
  163. it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
  164. blk = ItemPointerGetBlockNumber(&(it->t_tid));
  165. ReleaseBuffer(b);
  166. b = ReadBuffer(s->relation, blk);
  167. p = BufferGetPage(b);
  168. po = (RTreePageOpaque) PageGetSpecialPointer(p);
  169. if (ScanDirectionIsBackward(dir))
  170. n = PageGetMaxOffsetNumber(p);
  171. else
  172. n = FirstOffsetNumber;
  173. }
  174. }
  175. }
  176. static OffsetNumber
  177. findnext(IndexScanDesc s, Page p, OffsetNumber n, ScanDirection dir)
  178. {
  179. OffsetNumber maxoff;
  180. IndexTuple it;
  181. RTreePageOpaque po;
  182. RTreeScanOpaque so;
  183. maxoff = PageGetMaxOffsetNumber(p);
  184. po = (RTreePageOpaque) PageGetSpecialPointer(p);
  185. so = (RTreeScanOpaque) s->opaque;
  186. /*
  187.  * If we modified the index during the scan, we may have a pointer to
  188.  * a ghost tuple, before the scan. If this is the case, back up one.
  189.  */
  190. if (so->s_flags & RTS_CURBEFORE)
  191. {
  192. so->s_flags &= ~RTS_CURBEFORE;
  193. n = OffsetNumberPrev(n);
  194. }
  195. while (n >= FirstOffsetNumber && n <= maxoff)
  196. {
  197. it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
  198. if (po->flags & F_LEAF)
  199. {
  200. if (index_keytest(it,
  201.   RelationGetDescr(s->relation),
  202.   s->numberOfKeys, s->keyData))
  203. break;
  204. }
  205. else
  206. {
  207. if (index_keytest(it,
  208.   RelationGetDescr(s->relation),
  209.   so->s_internalNKey, so->s_internalKey))
  210. break;
  211. }
  212. if (ScanDirectionIsBackward(dir))
  213. n = OffsetNumberPrev(n);
  214. else
  215. n = OffsetNumberNext(n);
  216. }
  217. return n;
  218. }
  219. static RetrieveIndexResult
  220. rtscancache(IndexScanDesc s, ScanDirection dir)
  221. {
  222. RetrieveIndexResult res;
  223. ItemPointer ip;
  224. if (!(ScanDirectionIsNoMovement(dir)
  225.   && ItemPointerIsValid(&(s->currentItemData))))
  226. {
  227. return (RetrieveIndexResult) NULL;
  228. }
  229. ip = rtheapptr(s->relation, &(s->currentItemData));
  230. if (ItemPointerIsValid(ip))
  231. res = FormRetrieveIndexResult(&(s->currentItemData), ip);
  232. else
  233. res = (RetrieveIndexResult) NULL;
  234. pfree(ip);
  235. return res;
  236. }
  237. /*
  238.  * rtheapptr returns the item pointer to the tuple in the heap relation
  239.  * for which itemp is the index relation item pointer.
  240.  */
  241. static ItemPointer
  242. rtheapptr(Relation r, ItemPointer itemp)
  243. {
  244. Buffer b;
  245. Page p;
  246. IndexTuple it;
  247. ItemPointer ip;
  248. OffsetNumber n;
  249. ip = (ItemPointer) palloc(sizeof(ItemPointerData));
  250. if (ItemPointerIsValid(itemp))
  251. {
  252. b = ReadBuffer(r, ItemPointerGetBlockNumber(itemp));
  253. p = BufferGetPage(b);
  254. n = ItemPointerGetOffsetNumber(itemp);
  255. it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
  256. memmove((char *) ip, (char *) &(it->t_tid),
  257. sizeof(ItemPointerData));
  258. ReleaseBuffer(b);
  259. }
  260. else
  261. ItemPointerSetInvalid(ip);
  262. return ip;
  263. }