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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * genam.c
  4.  *   general index access method routines
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/access/index/genam.c,v 1.17.2.2 1999/08/02 05:56:38 scrappy Exp $
  11.  *
  12.  * NOTES
  13.  *   many of the old access method routines have been turned into
  14.  *   macros and moved to genam.h -cim 4/30/91
  15.  *
  16.  *-------------------------------------------------------------------------
  17.  */
  18. /*
  19.  * OLD COMMENTS
  20.  * Scans are implemented as follows:
  21.  *
  22.  * `0' represents an invalid item pointer.
  23.  * `-' represents an unknown item pointer.
  24.  * `X' represents a known item pointers.
  25.  * `+' represents known or invalid item pointers.
  26.  * `*' represents any item pointers.
  27.  *
  28.  * State is represented by a triple of these symbols in the order of
  29.  * previous, current, next.  Note that the case of reverse scans works
  30.  * identically.
  31.  *
  32.  * State Result
  33.  * (1) + + - + 0 0 (if the next item pointer is invalid)
  34.  * (2) + X - (otherwise)
  35.  * (3) * 0 0 * 0 0 (no change)
  36.  * (4) + X 0 X 0 0 (shift)
  37.  * (5) * + X + X - (shift, add unknown)
  38.  *
  39.  * All other states cannot occur.
  40.  *
  41.  * Note:
  42.  *It would be possible to cache the status of the previous and
  43.  * next item pointer using the flags.
  44.  * ----------------------------------------------------------------
  45.  */
  46. #include "postgres.h"
  47. #include "access/genam.h"
  48. /* ----------------------------------------------------------------
  49.  * general access method routines
  50.  *
  51.  * All indexed access methods use an identical scan structure.
  52.  * We don't know how the various AMs do locking, however, so we don't
  53.  * do anything about that here.
  54.  *
  55.  * The intent is that an AM implementor will define a front-end routine
  56.  * that calls this one, to fill in the scan, and then does whatever kind
  57.  * of locking he wants.
  58.  * ----------------------------------------------------------------
  59.  */
  60. /* ----------------
  61.  * RelationGetIndexScan -- Create and fill an IndexScanDesc.
  62.  *
  63.  * This routine creates an index scan structure and sets its contents
  64.  * up correctly. This routine calls AMrescan to set up the scan with
  65.  * the passed key.
  66.  *
  67.  * Parameters:
  68.  * relation -- index relation for scan.
  69.  * scanFromEnd -- if true, begin scan at one of the index's
  70.  *    endpoints.
  71.  * numberOfKeys -- count of scan keys (more than one won't
  72.  * necessarily do anything useful, yet).
  73.  * key -- the ScanKey for the starting position of the scan.
  74.  *
  75.  * Returns:
  76.  * An initialized IndexScanDesc.
  77.  *
  78.  * Side Effects:
  79.  * Bumps the ref count on the relation to keep it in the cache.
  80.  *
  81.  * ----------------
  82.  */
  83. IndexScanDesc
  84. RelationGetIndexScan(Relation relation,
  85.  bool scanFromEnd,
  86.  uint16 numberOfKeys,
  87.  ScanKey key)
  88. {
  89. IndexScanDesc scan;
  90. if (!RelationIsValid(relation))
  91. elog(ERROR, "RelationGetIndexScan: relation invalid");
  92. scan = (IndexScanDesc) palloc(sizeof(IndexScanDescData));
  93. scan->relation = relation;
  94. scan->opaque = NULL;
  95. scan->numberOfKeys = numberOfKeys;
  96. ItemPointerSetInvalid(&scan->previousItemData);
  97. ItemPointerSetInvalid(&scan->currentItemData);
  98. ItemPointerSetInvalid(&scan->nextItemData);
  99. ItemPointerSetInvalid(&scan->previousMarkData);
  100. ItemPointerSetInvalid(&scan->currentMarkData);
  101. ItemPointerSetInvalid(&scan->nextMarkData);
  102. if (numberOfKeys > 0)
  103. scan->keyData = (ScanKey) palloc(sizeof(ScanKeyData) * numberOfKeys);
  104. else
  105. scan->keyData = NULL;
  106. index_rescan(scan, scanFromEnd, key);
  107. return scan;
  108. }
  109. #ifdef NOT_USED
  110. /* ----------------
  111.  * IndexScanRestart -- Restart an index scan.
  112.  *
  113.  * This routine isn't used by any existing access method.  It's
  114.  * appropriate if relation level locks are what you want.
  115.  *
  116.  * Returns:
  117.  * None.
  118.  *
  119.  * Side Effects:
  120.  * None.
  121.  * ----------------
  122.  */
  123. void
  124. IndexScanRestart(IndexScanDesc scan,
  125.  bool scanFromEnd,
  126.  ScanKey key)
  127. {
  128. if (!IndexScanIsValid(scan))
  129. elog(ERROR, "IndexScanRestart: invalid scan");
  130. ItemPointerSetInvalid(&scan->previousItemData);
  131. ItemPointerSetInvalid(&scan->currentItemData);
  132. ItemPointerSetInvalid(&scan->nextItemData);
  133. if (RelationGetNumberOfBlocks(scan->relation) == 0)
  134. scan->flags = ScanUnmarked;
  135. else if (scanFromEnd)
  136. scan->flags = ScanUnmarked | ScanUncheckedPrevious;
  137. else
  138. scan->flags = ScanUnmarked | ScanUncheckedNext;
  139. scan->scanFromEnd = (bool) scanFromEnd;
  140. if (scan->numberOfKeys > 0)
  141. memmove(scan->keyData,
  142. key,
  143. scan->numberOfKeys * sizeof(ScanKeyData));
  144. }
  145. /* ----------------
  146.  * IndexScanEnd -- End and index scan.
  147.  *
  148.  * This routine is not used by any existing access method, but is
  149.  * suitable for use if you don't want to do sophisticated locking.
  150.  *
  151.  * Returns:
  152.  * None.
  153.  *
  154.  * Side Effects:
  155.  * None.
  156.  * ----------------
  157.  */
  158. void
  159. IndexScanEnd(IndexScanDesc scan)
  160. {
  161. if (!IndexScanIsValid(scan))
  162. elog(ERROR, "IndexScanEnd: invalid scan");
  163. pfree(scan);
  164. }
  165. /* ----------------
  166.  * IndexScanMarkPosition -- Mark current position in a scan.
  167.  *
  168.  * This routine isn't used by any existing access method, but is the
  169.  * one that AM implementors should use, if they don't want to do any
  170.  * special locking.  If relation-level locking is sufficient, this is
  171.  * the routine for you.
  172.  *
  173.  * Returns:
  174.  * None.
  175.  *
  176.  * Side Effects:
  177.  * None.
  178.  * ----------------
  179.  */
  180. void
  181. IndexScanMarkPosition(IndexScanDesc scan)
  182. {
  183. RetrieveIndexResult result;
  184. if (scan->flags & ScanUncheckedPrevious)
  185. {
  186. result = index_getnext(scan, BackwardScanDirection);
  187. if (result != NULL)
  188. {
  189. scan->previousItemData = result->index_iptr;
  190. pfree(result);
  191. }
  192. else
  193. ItemPointerSetInvalid(&scan->previousItemData);
  194. }
  195. else if (scan->flags & ScanUncheckedNext)
  196. {
  197. result = (RetrieveIndexResult)
  198. index_getnext(scan, ForwardScanDirection);
  199. if (result != NULL)
  200. {
  201. scan->nextItemData = result->index_iptr;
  202. pfree(result);
  203. }
  204. else
  205. ItemPointerSetInvalid(&scan->nextItemData);
  206. }
  207. scan->previousMarkData = scan->previousItemData;
  208. scan->currentMarkData = scan->currentItemData;
  209. scan->nextMarkData = scan->nextItemData;
  210. scan->flags = 0x0; /* XXX should have a symbolic name */
  211. }
  212. /* ----------------
  213.  * IndexScanRestorePosition -- Restore position on a marked scan.
  214.  *
  215.  * This routine isn't used by any existing access method, but is the
  216.  * one that AM implementors should use if they don't want to do any
  217.  * special locking.  If relation-level locking is sufficient, then
  218.  * this is the one you want.
  219.  *
  220.  * Returns:
  221.  * None.
  222.  *
  223.  * Side Effects:
  224.  * None.
  225.  * ----------------
  226.  */
  227. void
  228. IndexScanRestorePosition(IndexScanDesc scan)
  229. {
  230. if (scan->flags & ScanUnmarked)
  231. elog(ERROR, "IndexScanRestorePosition: no mark to restore");
  232. scan->previousItemData = scan->previousMarkData;
  233. scan->currentItemData = scan->currentMarkData;
  234. scan->nextItemData = scan->nextMarkData;
  235. scan->flags = 0x0; /* XXX should have a symbolic name */
  236. }
  237. #endif