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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * syscache.c
  4.  *   System cache management routines
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.28.2.1 1999/08/02 05:25:01 scrappy Exp $
  11.  *
  12.  * NOTES
  13.  *   These routines allow the parser/planner/executor to perform
  14.  *   rapid lookups on the contents of the system catalogs.
  15.  *
  16.  *   see catalog/syscache.h for a list of the cache id's
  17.  *
  18.  *-------------------------------------------------------------------------
  19.  */
  20. #include "postgres.h"
  21. #include "access/heapam.h"
  22. #include "catalog/catname.h"
  23. #include "catalog/pg_aggregate.h"
  24. #include "catalog/pg_amop.h"
  25. #include "catalog/pg_group.h"
  26. #include "catalog/pg_index.h"
  27. #include "catalog/pg_inherits.h"
  28. #include "catalog/pg_language.h"
  29. #include "catalog/pg_listener.h"
  30. #include "catalog/pg_opclass.h"
  31. #include "catalog/pg_operator.h"
  32. #include "catalog/pg_proc.h"
  33. #include "catalog/pg_rewrite.h"
  34. #include "catalog/pg_shadow.h"
  35. #include "catalog/pg_type.h"
  36. #include "utils/catcache.h"
  37. extern bool AMI_OVERRIDE; /* XXX style */
  38. #include "utils/syscache.h"
  39. #include "catalog/indexing.h"
  40. typedef HeapTuple (*ScanFunc) ();
  41. /* ----------------
  42.  * Warning:  cacheinfo[] below is changed, then be sure and
  43.  * update the magic constants in syscache.h!
  44.  * ----------------
  45.  */
  46. static struct cachedesc cacheinfo[] = {
  47. {AccessMethodOperatorRelationName, /* AMOPOPID */
  48. 3,
  49. {
  50. Anum_pg_amop_amopclaid,
  51. Anum_pg_amop_amopopr,
  52. Anum_pg_amop_amopid,
  53. 0
  54. },
  55. sizeof(FormData_pg_amop),
  56. NULL,
  57. (ScanFunc) NULL},
  58. {AccessMethodOperatorRelationName, /* AMOPSTRATEGY */
  59. 3,
  60. {
  61. Anum_pg_amop_amopid,
  62. Anum_pg_amop_amopclaid,
  63. Anum_pg_amop_amopstrategy,
  64. 0
  65. },
  66. sizeof(FormData_pg_amop),
  67. NULL,
  68. (ScanFunc) NULL},
  69. {AttributeRelationName, /* ATTNAME */
  70. 2,
  71. {
  72. Anum_pg_attribute_attrelid,
  73. Anum_pg_attribute_attname,
  74. 0,
  75. 0
  76. },
  77. ATTRIBUTE_TUPLE_SIZE,
  78. AttributeNameIndex,
  79. (ScanFunc) AttributeNameIndexScan},
  80. {AttributeRelationName, /* ATTNUM */
  81. 2,
  82. {
  83. Anum_pg_attribute_attrelid,
  84. Anum_pg_attribute_attnum,
  85. 0,
  86. 0
  87. },
  88. ATTRIBUTE_TUPLE_SIZE,
  89. AttributeNumIndex,
  90. (ScanFunc) AttributeNumIndexScan},
  91. {IndexRelationName, /* INDEXRELID */
  92. 1,
  93. {
  94. Anum_pg_index_indexrelid,
  95. 0,
  96. 0,
  97. 0
  98. },
  99. offsetof(FormData_pg_index, indpred),
  100. NULL,
  101. NULL},
  102. {LanguageRelationName, /* LANNAME */
  103. 1,
  104. {
  105. Anum_pg_language_lanname,
  106. 0,
  107. 0,
  108. 0
  109. },
  110. offsetof(FormData_pg_language, lancompiler),
  111. NULL,
  112. NULL},
  113. {OperatorRelationName, /* OPRNAME */
  114. 4,
  115. {
  116. Anum_pg_operator_oprname,
  117. Anum_pg_operator_oprleft,
  118. Anum_pg_operator_oprright,
  119. Anum_pg_operator_oprkind
  120. },
  121. sizeof(FormData_pg_operator),
  122. NULL,
  123. NULL},
  124. {OperatorRelationName, /* OPROID */
  125. 1,
  126. {
  127. ObjectIdAttributeNumber,
  128. 0,
  129. 0,
  130. 0
  131. },
  132. sizeof(FormData_pg_operator),
  133. NULL,
  134. (ScanFunc) NULL},
  135. {ProcedureRelationName, /* PRONAME */
  136. 3,
  137. {
  138. Anum_pg_proc_proname,
  139. Anum_pg_proc_pronargs,
  140. Anum_pg_proc_proargtypes,
  141. 0
  142. },
  143. offsetof(FormData_pg_proc, prosrc),
  144. ProcedureNameIndex,
  145. (ScanFunc) ProcedureNameIndexScan},
  146. {ProcedureRelationName, /* PROOID */
  147. 1,
  148. {
  149. ObjectIdAttributeNumber,
  150. 0,
  151. 0,
  152. 0
  153. },
  154. offsetof(FormData_pg_proc, prosrc),
  155. ProcedureOidIndex,
  156. (ScanFunc) ProcedureOidIndexScan},
  157. {RelationRelationName, /* RELNAME */
  158. 1,
  159. {
  160. Anum_pg_class_relname,
  161. 0,
  162. 0,
  163. 0
  164. },
  165. CLASS_TUPLE_SIZE,
  166. ClassNameIndex,
  167. (ScanFunc) ClassNameIndexScan},
  168. {RelationRelationName, /* RELOID */
  169. 1,
  170. {
  171. ObjectIdAttributeNumber,
  172. 0,
  173. 0,
  174. 0
  175. },
  176. CLASS_TUPLE_SIZE,
  177. ClassOidIndex,
  178. (ScanFunc) ClassOidIndexScan},
  179. {TypeRelationName, /* TYPNAME */
  180. 1,
  181. {
  182. Anum_pg_type_typname,
  183. 0,
  184. 0,
  185. 0
  186. },
  187. offsetof(FormData_pg_type, typalign) +sizeof(char),
  188. TypeNameIndex,
  189. TypeNameIndexScan},
  190. {TypeRelationName, /* TYPOID */
  191. 1,
  192. {
  193. ObjectIdAttributeNumber,
  194. 0,
  195. 0,
  196. 0
  197. },
  198. offsetof(FormData_pg_type, typalign) +sizeof(char),
  199. TypeOidIndex,
  200. TypeOidIndexScan},
  201. {AccessMethodRelationName, /* AMNAME */
  202. 1,
  203. {
  204. Anum_pg_am_amname,
  205. 0,
  206. 0,
  207. 0
  208. },
  209. sizeof(FormData_pg_am),
  210. NULL,
  211. NULL},
  212. {OperatorClassRelationName, /* CLANAME */
  213. 1,
  214. {
  215. Anum_pg_opclass_opcname,
  216. 0,
  217. 0,
  218. 0
  219. },
  220. sizeof(FormData_pg_opclass),
  221. NULL,
  222. NULL},
  223. {IndexRelationName, /* INDRELIDKEY *//* never used */
  224. 2,
  225. {
  226. Anum_pg_index_indrelid,
  227. Anum_pg_index_indkey,
  228. 0,
  229. 0
  230. },
  231. offsetof(FormData_pg_index, indpred),
  232. NULL,
  233. (ScanFunc) NULL},
  234. {InheritsRelationName, /* INHRELID */
  235. 2,
  236. {
  237. Anum_pg_inherits_inhrel,
  238. Anum_pg_inherits_inhseqno,
  239. 0,
  240. 0
  241. },
  242. sizeof(FormData_pg_inherits),
  243. NULL,
  244. (ScanFunc) NULL},
  245. {RewriteRelationName, /* RULOID */
  246. 1,
  247. {
  248. ObjectIdAttributeNumber,
  249. 0,
  250. 0,
  251. 0
  252. },
  253. offsetof(FormData_pg_rewrite, ev_qual),
  254. NULL,
  255. (ScanFunc) NULL},
  256. {AggregateRelationName, /* AGGNAME */
  257. 2,
  258. {
  259. Anum_pg_aggregate_aggname,
  260. Anum_pg_aggregate_aggbasetype,
  261. 0,
  262. 0
  263. },
  264. offsetof(FormData_pg_aggregate, agginitval1),
  265. NULL,
  266. (ScanFunc) NULL},
  267. {ListenerRelationName, /* LISTENREL */
  268. 2,
  269. {
  270. Anum_pg_listener_relname,
  271. Anum_pg_listener_pid,
  272. 0,
  273. 0
  274. },
  275. sizeof(FormData_pg_listener),
  276. NULL,
  277. (ScanFunc) NULL},
  278. {ShadowRelationName, /* USENAME */
  279. 1,
  280. {
  281. Anum_pg_shadow_usename,
  282. 0,
  283. 0,
  284. 0
  285. },
  286. sizeof(FormData_pg_shadow),
  287. NULL,
  288. (ScanFunc) NULL},
  289. {ShadowRelationName, /* USESYSID */
  290. 1,
  291. {
  292. Anum_pg_shadow_usesysid,
  293. 0,
  294. 0,
  295. 0
  296. },
  297. sizeof(FormData_pg_shadow),
  298. NULL,
  299. (ScanFunc) NULL},
  300. {GroupRelationName, /* GRONAME */
  301. 1,
  302. {
  303. Anum_pg_group_groname,
  304. 0,
  305. 0,
  306. 0
  307. },
  308. offsetof(FormData_pg_group, grolist[0]),
  309. NULL,
  310. (ScanFunc) NULL},
  311. {GroupRelationName, /* GROSYSID */
  312. 1,
  313. {
  314. Anum_pg_group_grosysid,
  315. 0,
  316. 0,
  317. 0
  318. },
  319. offsetof(FormData_pg_group, grolist[0]),
  320. NULL,
  321. (ScanFunc) NULL},
  322. {RewriteRelationName, /* REWRITENAME */
  323. 1,
  324. {
  325. Anum_pg_rewrite_rulename,
  326. 0,
  327. 0,
  328. 0
  329. },
  330. offsetof(FormData_pg_rewrite, ev_qual),
  331. NULL,
  332. (ScanFunc) NULL},
  333. {ProcedureRelationName, /* PROSRC */
  334. 1,
  335. {
  336. Anum_pg_proc_prosrc,
  337. 0,
  338. 0,
  339. 0
  340. },
  341. offsetof(FormData_pg_proc, prosrc),
  342. ProcedureSrcIndex,
  343. (ScanFunc) ProcedureSrcIndexScan},
  344. {OperatorClassRelationName, /* CLADEFTYPE */
  345. 1,
  346. {
  347. Anum_pg_opclass_opcdeftype,
  348. 0,
  349. 0,
  350. 0
  351. },
  352. sizeof(FormData_pg_opclass),
  353. NULL,
  354. (ScanFunc) NULL},
  355. {LanguageRelationName, /* LANOID */
  356. 1,
  357. {
  358. ObjectIdAttributeNumber,
  359. 0,
  360. 0,
  361. 0
  362. },
  363. offsetof(FormData_pg_language, lancompiler),
  364. NULL,
  365. NULL}
  366. };
  367. static struct catcache *SysCache[lengthof(cacheinfo)];
  368. static int32 SysCacheSize = lengthof(cacheinfo);
  369. /*
  370.  * zerocaches
  371.  *
  372.  *   Make sure the SysCache structure is zero'd.
  373.  */
  374. void
  375. zerocaches()
  376. {
  377. MemSet((char *) SysCache, 0, SysCacheSize * sizeof(struct catcache *));
  378. }
  379. /*
  380.  * Note:
  381.  * This function was written because the initialized catalog caches
  382.  * are used to determine which caches may contain tuples which need
  383.  * to be invalidated in other backends.
  384.  */
  385. void
  386. InitCatalogCache()
  387. {
  388. int cacheId; /* XXX type */
  389. if (!AMI_OVERRIDE)
  390. {
  391. for (cacheId = 0; cacheId < SysCacheSize; cacheId += 1)
  392. {
  393. Assert(!PointerIsValid((Pointer) SysCache[cacheId]));
  394. SysCache[cacheId] = InitSysCache(cacheinfo[cacheId].name,
  395.  cacheinfo[cacheId].indname,
  396.  cacheId,
  397.  cacheinfo[cacheId].nkeys,
  398.  cacheinfo[cacheId].key,
  399.    cacheinfo[cacheId].iScanFunc);
  400. if (!PointerIsValid((char *) SysCache[cacheId]))
  401. {
  402. elog(ERROR,
  403.  "InitCatalogCache: Can't init cache %s(%d)",
  404.  cacheinfo[cacheId].name,
  405.  cacheId);
  406. }
  407. }
  408. }
  409. }
  410. /*
  411.  * SearchSysCacheTupleCopy
  412.  *
  413.  * This is like SearchSysCacheTuple, except it returns a copy of the tuple
  414.  * that the user is required to pfree().
  415.  */
  416. HeapTuple
  417. SearchSysCacheTupleCopy(int cacheId, /* cache selection code */
  418. Datum key1,
  419. Datum key2,
  420. Datum key3,
  421. Datum key4)
  422. {
  423. HeapTuple cachetup;
  424. cachetup = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
  425. if (PointerIsValid(cachetup))
  426. return heap_copytuple(cachetup);
  427. else
  428. return cachetup; /* NULL */
  429. }
  430. /*
  431.  * SearchSysCacheTuple
  432.  *
  433.  * A layer on top of SearchSysCache that does the initialization and
  434.  * key-setting for you.
  435.  *
  436.  * Returns the cache copy of the tuple if one is found, NULL if not.
  437.  * The tuple is the 'cache' copy.
  438.  *
  439.  * XXX The tuple that is returned is NOT supposed to be pfree'd!
  440.  */
  441. HeapTuple
  442. SearchSysCacheTuple(int cacheId,/* cache selection code */
  443. Datum key1,
  444. Datum key2,
  445. Datum key3,
  446. Datum key4)
  447. {
  448. HeapTuple tp;
  449. if (cacheId < 0 || cacheId >= SysCacheSize)
  450. {
  451. elog(ERROR, "SearchSysCacheTuple: Bad cache id %d", cacheId);
  452. return (HeapTuple) NULL;
  453. }
  454. Assert(AMI_OVERRIDE || PointerIsValid(SysCache[cacheId]));
  455. if (!PointerIsValid(SysCache[cacheId]))
  456. {
  457. SysCache[cacheId] = InitSysCache(cacheinfo[cacheId].name,
  458.  cacheinfo[cacheId].indname,
  459.  cacheId,
  460.  cacheinfo[cacheId].nkeys,
  461.  cacheinfo[cacheId].key,
  462.  cacheinfo[cacheId].iScanFunc);
  463. if (!PointerIsValid(SysCache[cacheId]))
  464. elog(ERROR,
  465.  "InitCatalogCache: Can't init cache %s(%d)",
  466.  cacheinfo[cacheId].name,
  467.  cacheId);
  468. }
  469. tp = SearchSysCache(SysCache[cacheId], key1, key2, key3, key4);
  470. if (!HeapTupleIsValid(tp))
  471. {
  472. #ifdef CACHEDEBUG
  473. elog(DEBUG,
  474.  "SearchSysCacheTuple: Search %s(%d) %d %d %d %d failed",
  475.  cacheinfo[cacheId].name,
  476.  cacheId, key1, key2, key3, key4);
  477. #endif
  478. return (HeapTuple) NULL;
  479. }
  480. return tp;
  481. }
  482. /*
  483.  * SearchSysCacheStruct
  484.  *   Fills 's' with the information retrieved by calling SearchSysCache()
  485.  *   with arguments key1...key4.  Retrieves only the portion of the tuple
  486.  *   which is not variable-length.
  487.  *
  488.  * NOTE: we are assuming that non-variable-length fields in the system
  489.  *  catalogs will always be defined!
  490.  *
  491.  * Returns 1L if a tuple was found, 0L if not.
  492.  */
  493. int32
  494. SearchSysCacheStruct(int cacheId, /* cache selection code */
  495.  char *returnStruct, /* (preallocated!) */
  496.  Datum key1,
  497.  Datum key2,
  498.  Datum key3,
  499.  Datum key4)
  500. {
  501. HeapTuple tp;
  502. if (!PointerIsValid(returnStruct))
  503. {
  504. elog(ERROR, "SearchSysCacheStruct: No receiving struct");
  505. return 0;
  506. }
  507. tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
  508. if (!HeapTupleIsValid(tp))
  509. return 0;
  510. memcpy(returnStruct, (char *) GETSTRUCT(tp), cacheinfo[cacheId].size);
  511. return 1;
  512. }
  513. /*
  514.  * SearchSysCacheGetAttribute
  515.  *   Returns the attribute corresponding to 'attributeNumber' for
  516.  *   a given cached tuple.  This routine usually needs to be used for
  517.  *   attributes that might be NULL or might be at a variable offset
  518.  *   in the tuple.
  519.  *
  520.  * XXX This re-opens the relation, so this is slower than just pulling
  521.  * fixed-location fields out of the struct returned by SearchSysCacheTuple.
  522.  *
  523.  * [callers all assume this returns a (struct varlena *). -ay 10/94]
  524.  */
  525. void *
  526. SearchSysCacheGetAttribute(int cacheId,
  527.    AttrNumber attributeNumber,
  528.    Datum key1,
  529.    Datum key2,
  530.    Datum key3,
  531.    Datum key4)
  532. {
  533. HeapTuple tp;
  534. char    *cacheName;
  535. Relation relation;
  536. int32 attributeLength,
  537. attributeByValue;
  538. bool isNull;
  539. Datum attributeValue;
  540. void    *returnValue;
  541. tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
  542. cacheName = cacheinfo[cacheId].name;
  543. if (!HeapTupleIsValid(tp))
  544. {
  545. #ifdef CACHEDEBUG
  546. elog(DEBUG,
  547.  "SearchSysCacheGetAttribute: Lookup in %s(%d) failed",
  548.  cacheName, cacheId);
  549. #endif  /* defined(CACHEDEBUG) */
  550. return NULL;
  551. }
  552. relation = heap_openr(cacheName);
  553. if (attributeNumber < 0 &&
  554. attributeNumber > FirstLowInvalidHeapAttributeNumber)
  555. {
  556. attributeLength = heap_sysattrlen(attributeNumber);
  557. attributeByValue = heap_sysattrbyval(attributeNumber);
  558. }
  559. else if (attributeNumber > 0 &&
  560.  attributeNumber <= relation->rd_rel->relnatts)
  561. {
  562. attributeLength = relation->rd_att->attrs[attributeNumber - 1]->attlen;
  563. attributeByValue = relation->rd_att->attrs[attributeNumber - 1]->attbyval;
  564. }
  565. else
  566. {
  567. elog(ERROR,
  568.  "SearchSysCacheGetAttribute: Bad attr # %d in %s(%d)",
  569.  attributeNumber, cacheName, cacheId);
  570. return NULL;
  571. }
  572. attributeValue = heap_getattr(tp,
  573.   attributeNumber,
  574.   RelationGetDescr(relation),
  575.   &isNull);
  576. if (isNull)
  577. {
  578. /*
  579.  * Used to be an elog(DEBUG, ...) here and a claim that it should
  580.  * be a FATAL error, I don't think either is warranted -mer 6/9/92
  581.  */
  582. return NULL;
  583. }
  584. if (attributeByValue)
  585. returnValue = (void *) attributeValue;
  586. else
  587. {
  588. char    *tmp;
  589. int size = (attributeLength < 0)
  590. ? VARSIZE((struct varlena *) attributeValue) /* variable length */
  591. : attributeLength; /* fixed length */
  592. tmp = (char *) palloc(size);
  593. memcpy(tmp, (void *) attributeValue, size);
  594. returnValue = (void *) tmp;
  595. }
  596. heap_close(relation);
  597. return returnValue;
  598. }
  599. /*
  600.  * TypeDefaultRetrieve
  601.  *
  602.  *   Given a type OID, return the typdefault field associated with that
  603.  *   type.  The result is a Datum, and points to palloc'd storage for
  604.  *   non-pass-by-value types.
  605.  *
  606.  * [identical to get_typdefault, expecting a (struct varlena *) as ret val.
  607.  * some day, either of the functions should be removed  -ay 10/94]
  608.  */
  609. void *
  610. TypeDefaultRetrieve(Oid typId)
  611. {
  612. struct varlena *typDefault;
  613. int32 dataSize;
  614. HeapTuple typeTuple;
  615. Form_pg_type type;
  616. int32 typByVal,
  617. typLen;
  618. void    *returnValue;
  619. /*
  620.  * First, see if there is a non-null typdefault field (usually there isn't)
  621.  */
  622. typDefault = (struct varlena *)
  623. SearchSysCacheGetAttribute(TYPOID,
  624.    Anum_pg_type_typdefault,
  625.    ObjectIdGetDatum(typId),
  626.    0, 0, 0);
  627. if (typDefault == NULL)
  628. {
  629. #ifdef CACHEDEBUG
  630. elog(DEBUG, "TypeDefaultRetrieve: No extractable typdefault in %s(%d)",
  631.  cacheinfo[TYPOID].name, TYPOID);
  632. #endif  /* defined(CACHEDEBUG) */
  633. return NULL;
  634. }
  635. dataSize = VARSIZE(typDefault) - VARHDRSZ;
  636. /*
  637.  * Need the type's length and byVal fields.
  638.  *
  639.  * XXX silly to repeat the syscache search that SearchSysCacheGetAttribute
  640.  * just did --- but at present this path isn't taken often enough to
  641.  * make it worth fixing.
  642.  */
  643. typeTuple = SearchSysCacheTuple(TYPOID,
  644. ObjectIdGetDatum(typId),
  645. 0, 0, 0);
  646. if (!HeapTupleIsValid(typeTuple))
  647. {
  648. /* should never get here, really... */
  649. #ifdef CACHEDEBUG
  650. elog(DEBUG, "TypeDefaultRetrieve: Lookup in %s(%d) failed",
  651.  cacheinfo[TYPOID].name, TYPOID);
  652. #endif  /* defined(CACHEDEBUG) */
  653. return NULL;
  654. }
  655. type = (Form_pg_type) GETSTRUCT(typeTuple);
  656. typLen = type->typlen;
  657. typByVal = type->typbyval;
  658. if (typByVal)
  659. {
  660. int8 i8;
  661. int16 i16;
  662. int32 i32 = 0;
  663. if (dataSize == typLen)
  664. {
  665. switch (typLen)
  666. {
  667. case sizeof(int8):
  668. memcpy((char *) &i8, VARDATA(typDefault), sizeof(int8));
  669. i32 = i8;
  670. break;
  671. case sizeof(int16):
  672. memcpy((char *) &i16, VARDATA(typDefault), sizeof(int16));
  673. i32 = i16;
  674. break;
  675. case sizeof(int32):
  676. memcpy((char *) &i32, VARDATA(typDefault), sizeof(int32));
  677. break;
  678. }
  679. returnValue = (void *) i32;
  680. }
  681. else
  682. returnValue = NULL;
  683. }
  684. else
  685. {
  686. if ((typLen < 0 && dataSize < 0) || dataSize != typLen)
  687. returnValue = NULL;
  688. else
  689. {
  690. returnValue = (void *) palloc(VARSIZE(typDefault));
  691. memcpy((char *) returnValue,
  692.    (char *) typDefault,
  693.    (int) VARSIZE(typDefault));
  694. }
  695. }
  696. return returnValue;
  697. }