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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * indexam.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/indexam.c,v 1.30.2.1 1999/08/02 05:56:39 scrappy Exp $
  11.  *
  12.  * INTERFACE ROUTINES
  13.  * index_open - open an index relation by relationId
  14.  * index_openr - open a index relation by name
  15.  * index_close - close a index relation
  16.  * index_beginscan - start a scan of an index
  17.  * index_rescan - restart a scan of an index
  18.  * index_endscan - end a scan
  19.  * index_insert - insert an index tuple into a relation
  20.  * index_delete - delete an item from an index relation
  21.  * index_markpos - mark a scan position
  22.  * index_restrpos - restore a scan position
  23.  * index_getnext - get the next tuple from a scan
  24.  * ** index_fetch - retrieve tuple with tid
  25.  * ** index_replace - replace a tuple
  26.  * ** index_getattr - get an attribute from an index tuple
  27.  * index_getprocid - get a support procedure id from the rel tuple
  28.  *
  29.  * IndexScanIsValid - check index scan
  30.  *
  31.  * NOTES
  32.  * This file contains the index_ routines which used
  33.  * to be a scattered collection of stuff in access/genam.
  34.  *
  35.  * The ** routines: index_fetch, index_replace, and index_getattr
  36.  * have not yet been implemented. They may not be needed.
  37.  *
  38.  * old comments
  39.  * Scans are implemented as follows:
  40.  *
  41.  * `0' represents an invalid item pointer.
  42.  * `-' represents an unknown item pointer.
  43.  * `X' represents a known item pointers.
  44.  * `+' represents known or invalid item pointers.
  45.  * `*' represents any item pointers.
  46.  *
  47.  * State is represented by a triple of these symbols in the order of
  48.  * previous, current, next.  Note that the case of reverse scans works
  49.  * identically.
  50.  *
  51.  * State Result
  52.  * (1) + + - + 0 0 (if the next item pointer is invalid)
  53.  * (2) + X - (otherwise)
  54.  * (3) * 0 0 * 0 0 (no change)
  55.  * (4) + X 0 X 0 0 (shift)
  56.  * (5) * + X + X - (shift, add unknown)
  57.  *
  58.  * All other states cannot occur.
  59.  *
  60.  * Note: It would be possible to cache the status of the previous and
  61.  *   next item pointer using the flags.
  62.  *
  63.  *-------------------------------------------------------------------------
  64.  */
  65. #include "postgres.h"
  66. #include "access/genam.h"
  67. #include "access/heapam.h"
  68. #include "utils/relcache.h"
  69. /* ----------------
  70.  *  undefine macros we aren't going to use that would otherwise
  71.  *  get in our way..  delete is defined in c.h and the am's are
  72.  *  defined in heapam.h
  73.  * ----------------
  74.  */
  75. #undef delete
  76. #undef aminsert
  77. #undef amdelete
  78. #undef ambeginscan
  79. #undef amrescan
  80. #undef amendscan
  81. #undef ammarkpos
  82. #undef amrestrpos
  83. #undef amgettuple
  84. /* ----------------------------------------------------------------
  85.  * macros used in index_ routines
  86.  * ----------------------------------------------------------------
  87.  */
  88. #define RELATION_CHECKS 
  89. AssertMacro(RelationIsValid(relation)), 
  90. AssertMacro(PointerIsValid(relation->rd_am)) 
  91. )
  92. #define SCAN_CHECKS 
  93. AssertMacro(IndexScanIsValid(scan)), 
  94. AssertMacro(RelationIsValid(scan->relation)), 
  95. AssertMacro(PointerIsValid(scan->relation->rd_am)) 
  96. )
  97. #define GET_REL_PROCEDURE(x,y) 
  98. procedure = relation->rd_am->y, 
  99. (!RegProcedureIsValid(procedure)) ? 
  100. elog(ERROR, "index_%s: invalid %s regproc", 
  101. CppAsString(x), CppAsString(y)) 
  102. : (void)NULL 
  103. )
  104. #define GET_SCAN_PROCEDURE(x,y) 
  105. procedure = scan->relation->rd_am->y, 
  106. (!RegProcedureIsValid(procedure)) ? 
  107. elog(ERROR, "index_%s: invalid %s regproc", 
  108. CppAsString(x), CppAsString(y)) 
  109. : (void)NULL 
  110. )
  111. /* ----------------------------------------------------------------
  112.  *    index_ interface functions
  113.  * ----------------------------------------------------------------
  114.  */
  115. /* ----------------
  116.  * index_open - open an index relation by relationId
  117.  *
  118.  * presently the relcache routines do all the work we need
  119.  * to open/close index relations.
  120.  * ----------------
  121.  */
  122. Relation
  123. index_open(Oid relationId)
  124. {
  125. return RelationIdGetRelation(relationId);
  126. }
  127. /* ----------------
  128.  * index_openr - open a index relation by name
  129.  *
  130.  * presently the relcache routines do all the work we need
  131.  * to open/close index relations.
  132.  * ----------------
  133.  */
  134. Relation
  135. index_openr(char *relationName)
  136. {
  137. return RelationNameGetRelation(relationName);
  138. }
  139. /* ----------------
  140.  * index_close - close a index relation
  141.  *
  142.  * presently the relcache routines do all the work we need
  143.  * to open/close index relations.
  144.  * ----------------
  145.  */
  146. void
  147. index_close(Relation relation)
  148. {
  149. RelationClose(relation);
  150. }
  151. /* ----------------
  152.  * index_insert - insert an index tuple into a relation
  153.  * ----------------
  154.  */
  155. InsertIndexResult
  156. index_insert(Relation relation,
  157.  Datum *datum,
  158.  char *nulls,
  159.  ItemPointer heap_t_ctid,
  160.  Relation heapRel)
  161. {
  162. RegProcedure procedure;
  163. InsertIndexResult specificResult;
  164. RELATION_CHECKS;
  165. GET_REL_PROCEDURE(insert, aminsert);
  166. /* ----------------
  167.  * have the am's insert proc do all the work.
  168.  * ----------------
  169.  */
  170. specificResult = (InsertIndexResult)
  171. fmgr(procedure, relation, datum, nulls, heap_t_ctid, heapRel, NULL);
  172. /* must be pfree'ed */
  173. return specificResult;
  174. }
  175. /* ----------------
  176.  * index_delete - delete an item from an index relation
  177.  * ----------------
  178.  */
  179. void
  180. index_delete(Relation relation, ItemPointer indexItem)
  181. {
  182. RegProcedure procedure;
  183. RELATION_CHECKS;
  184. GET_REL_PROCEDURE(delete, amdelete);
  185. fmgr(procedure, relation, indexItem);
  186. }
  187. /* ----------------
  188.  * index_beginscan - start a scan of an index
  189.  * ----------------
  190.  */
  191. IndexScanDesc
  192. index_beginscan(Relation relation,
  193. bool scanFromEnd,
  194. uint16 numberOfKeys,
  195. ScanKey key)
  196. {
  197. IndexScanDesc scandesc;
  198. RegProcedure procedure;
  199. RELATION_CHECKS;
  200. GET_REL_PROCEDURE(beginscan, ambeginscan);
  201. LockRelation(relation, AccessShareLock);
  202. scandesc = (IndexScanDesc)
  203. fmgr(procedure, relation, scanFromEnd, numberOfKeys, key);
  204. return scandesc;
  205. }
  206. /* ----------------
  207.  * index_rescan  - restart a scan of an index
  208.  * ----------------
  209.  */
  210. void
  211. index_rescan(IndexScanDesc scan, bool scanFromEnd, ScanKey key)
  212. {
  213. RegProcedure procedure;
  214. SCAN_CHECKS;
  215. GET_SCAN_PROCEDURE(rescan, amrescan);
  216. fmgr(procedure, scan, scanFromEnd, key);
  217. }
  218. /* ----------------
  219.  * index_endscan - end a scan
  220.  * ----------------
  221.  */
  222. void
  223. index_endscan(IndexScanDesc scan)
  224. {
  225. RegProcedure procedure;
  226. SCAN_CHECKS;
  227. GET_SCAN_PROCEDURE(endscan, amendscan);
  228. fmgr(procedure, scan);
  229. UnlockRelation(scan->relation, AccessShareLock);
  230. }
  231. /* ----------------
  232.  * index_markpos  - mark a scan position
  233.  * ----------------
  234.  */
  235. void
  236. index_markpos(IndexScanDesc scan)
  237. {
  238. RegProcedure procedure;
  239. SCAN_CHECKS;
  240. GET_SCAN_PROCEDURE(markpos, ammarkpos);
  241. fmgr(procedure, scan);
  242. }
  243. /* ----------------
  244.  * index_restrpos - restore a scan position
  245.  * ----------------
  246.  */
  247. void
  248. index_restrpos(IndexScanDesc scan)
  249. {
  250. RegProcedure procedure;
  251. SCAN_CHECKS;
  252. GET_SCAN_PROCEDURE(restrpos, amrestrpos);
  253. fmgr(procedure, scan);
  254. }
  255. /* ----------------
  256.  * index_getnext - get the next tuple from a scan
  257.  *
  258.  * A RetrieveIndexResult is a index tuple/heap tuple pair
  259.  * ----------------
  260.  */
  261. RetrieveIndexResult
  262. index_getnext(IndexScanDesc scan,
  263.   ScanDirection direction)
  264. {
  265. RegProcedure procedure;
  266. RetrieveIndexResult result;
  267. SCAN_CHECKS;
  268. GET_SCAN_PROCEDURE(getnext, amgettuple);
  269. /* ----------------
  270.  * have the am's gettuple proc do all the work.
  271.  * ----------------
  272.  */
  273. result = (RetrieveIndexResult) fmgr(procedure, scan, direction);
  274. return result;
  275. }
  276. /* ----------------
  277.  * index_getprocid
  278.  *
  279.  * Some indexed access methods may require support routines that are
  280.  * not in the operator class/operator model imposed by pg_am. These
  281.  * access methods may store the OIDs of registered procedures they
  282.  * need in pg_amproc. These registered procedure OIDs are ordered in
  283.  * a way that makes sense to the access method, and used only by the
  284.  * access method. The general index code doesn't know anything about
  285.  * the routines involved; it just builds an ordered list of them for
  286.  * each attribute on which an index is defined.
  287.  *
  288.  * This routine returns the requested procedure OID for a particular
  289.  * indexed attribute.
  290.  * ----------------
  291.  */
  292. RegProcedure
  293. index_getprocid(Relation irel,
  294. AttrNumber attnum,
  295. uint16 procnum)
  296. {
  297. RegProcedure *loc;
  298. int natts;
  299. natts = irel->rd_rel->relnatts;
  300. loc = irel->rd_support;
  301. Assert(loc != NULL);
  302. return loc[(natts * (procnum - 1)) + (attnum - 1)];
  303. }
  304. Datum
  305. GetIndexValue(HeapTuple tuple,
  306.   TupleDesc hTupDesc,
  307.   int attOff,
  308.   AttrNumber *attrNums,
  309.   FuncIndexInfo *fInfo,
  310.   bool *attNull)
  311. {
  312. Datum returnVal;
  313. bool isNull = FALSE;
  314. if (PointerIsValid(fInfo) && FIgetProcOid(fInfo) != InvalidOid)
  315. {
  316. int i;
  317. Datum    *attData = (Datum *) palloc(FIgetnArgs(fInfo) * sizeof(Datum));
  318. for (i = 0; i < FIgetnArgs(fInfo); i++)
  319. {
  320. attData[i] = heap_getattr(tuple,
  321.   attrNums[i],
  322.   hTupDesc,
  323.   attNull);
  324. if (*attNull)
  325. isNull = TRUE;
  326. }
  327. returnVal = (Datum) fmgr_array_args(FIgetProcOid(fInfo),
  328. FIgetnArgs(fInfo),
  329. (char **) attData,
  330. &isNull);
  331. pfree(attData);
  332. *attNull = isNull;
  333. }
  334. else
  335. returnVal = heap_getattr(tuple, attrNums[attOff], hTupDesc, attNull);
  336. return returnVal;
  337. }