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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * relcache.c
  4.  *   POSTGRES relation descriptor cache code
  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/relcache.c,v 1.62.2.2 1999/09/02 04:07:18 tgl Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. /*
  15.  * INTERFACE ROUTINES
  16.  * RelationInitialize - initialize relcache
  17.  * RelationIdCacheGetRelation - get a reldesc from the cache (id)
  18.  * RelationNameCacheGetRelation - get a reldesc from the cache (name)
  19.  * RelationIdGetRelation - get a reldesc by relation id
  20.  * RelationNameGetRelation - get a reldesc by relation name
  21.  * RelationClose - close an open relation
  22.  * RelationFlushRelation - flush relation information
  23.  *
  24.  * NOTES
  25.  * This file is in the process of being cleaned up
  26.  * before I add system attribute indexing.  -cim 1/13/91
  27.  *
  28.  * The following code contains many undocumented hacks.  Please be
  29.  * careful....
  30.  *
  31.  */
  32. #include <sys/types.h>
  33. #include <errno.h>
  34. #include <sys/file.h>
  35. #include <fcntl.h>
  36. #include "postgres.h"
  37. #include "access/genam.h"
  38. #include "access/heapam.h"
  39. #include "access/istrat.h"
  40. #include "catalog/catalog.h"
  41. #include "catalog/catname.h"
  42. #include "catalog/index.h"
  43. #include "catalog/indexing.h"
  44. #include "catalog/pg_attrdef.h"
  45. #include "catalog/pg_log.h"
  46. #include "catalog/pg_proc.h"
  47. #include "catalog/pg_relcheck.h"
  48. #include "catalog/pg_rewrite.h"
  49. #include "catalog/pg_type.h"
  50. #include "catalog/pg_variable.h"
  51. #include "lib/hasht.h"
  52. #include "miscadmin.h"
  53. #include "storage/smgr.h"
  54. #include "utils/builtins.h"
  55. #include "utils/catcache.h"
  56. #include "utils/relcache.h"
  57. static void RelationFlushRelation(Relation *relationPtr,
  58.   bool onlyFlushReferenceCountZero);
  59. static Relation RelationNameCacheGetRelation(char *relationName);
  60. static void init_irels(void);
  61. static void write_irels(void);
  62. /* ----------------
  63.  * externs
  64.  * ----------------
  65.  */
  66. extern bool AMI_OVERRIDE; /* XXX style */
  67. extern GlobalMemory CacheCxt; /* from utils/cache/catcache.c */
  68. /* ----------------
  69.  * hardcoded tuple descriptors.  see lib/backend/catalog/pg_attribute.h
  70.  * ----------------
  71.  */
  72. FormData_pg_attribute Desc_pg_class[Natts_pg_class] = {Schema_pg_class};
  73. FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute] = {Schema_pg_attribute};
  74. FormData_pg_attribute Desc_pg_proc[Natts_pg_proc] = {Schema_pg_proc};
  75. FormData_pg_attribute Desc_pg_type[Natts_pg_type] = {Schema_pg_type};
  76. FormData_pg_attribute Desc_pg_variable[Natts_pg_variable] = {Schema_pg_variable};
  77. FormData_pg_attribute Desc_pg_log[Natts_pg_log] = {Schema_pg_log};
  78. /* ----------------
  79.  * global variables
  80.  *
  81.  * Relations are cached two ways, by name and by id,
  82.  * thus there are two hash tables for referencing them.
  83.  * ----------------
  84.  */
  85. HTAB    *RelationNameCache;
  86. HTAB    *RelationIdCache;
  87. /* ----------------
  88.  * RelationBuildDescInfo exists so code can be shared
  89.  * between RelationIdGetRelation() and RelationNameGetRelation()
  90.  * ----------------
  91.  */
  92. typedef struct RelationBuildDescInfo
  93. {
  94. int infotype; /* lookup by id or by name */
  95. #define INFO_RELID 1
  96. #define INFO_RELNAME 2
  97. union
  98. {
  99. Oid info_id; /* relation object id */
  100. char    *info_name; /* relation name */
  101. } i;
  102. } RelationBuildDescInfo;
  103. typedef struct relidcacheent
  104. {
  105. Oid reloid;
  106. Relation reldesc;
  107. } RelIdCacheEnt;
  108. typedef struct relnamecacheent
  109. {
  110. NameData relname;
  111. Relation reldesc;
  112. } RelNameCacheEnt;
  113. /* -----------------
  114.  * macros to manipulate name cache and id cache
  115.  * -----------------
  116.  */
  117. #define RelationCacheInsert(RELATION)
  118. do { 
  119. RelIdCacheEnt *idhentry; RelNameCacheEnt *namehentry; 
  120. char *relname; Oid reloid; bool found; 
  121. relname = (RELATION->rd_rel->relname).data; 
  122. namehentry = (RelNameCacheEnt*)hash_search(RelationNameCache, 
  123.    relname, 
  124.    HASH_ENTER, 
  125.    &found); 
  126. if (namehentry == NULL) 
  127. elog(FATAL, "can't insert into relation descriptor cache"); 
  128. if (found && !IsBootstrapProcessingMode()) 
  129. /* used to give notice -- now just keep quiet */ ; 
  130. namehentry->reldesc = RELATION; 
  131. reloid = RELATION->rd_id; 
  132. idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, 
  133.    (char *)&reloid, 
  134.    HASH_ENTER, 
  135.    &found); 
  136. if (idhentry == NULL) 
  137. elog(FATAL, "can't insert into relation descriptor cache"); 
  138. if (found && !IsBootstrapProcessingMode()) 
  139. /* used to give notice -- now just keep quiet */ ; 
  140. idhentry->reldesc = RELATION; 
  141. } while(0)
  142. #define RelationNameCacheLookup(NAME, RELATION) 
  143. do { 
  144. RelNameCacheEnt *hentry; bool found; 
  145. hentry = (RelNameCacheEnt*)hash_search(RelationNameCache, 
  146.    (char *)NAME,HASH_FIND,&found); 
  147. if (hentry == NULL) 
  148. elog(FATAL, "error in CACHE"); 
  149. if (found) 
  150. RELATION = hentry->reldesc; 
  151. else 
  152. RELATION = NULL; 
  153. } while(0)
  154. #define RelationIdCacheLookup(ID, RELATION) 
  155. do { 
  156. RelIdCacheEnt *hentry; 
  157. bool found; 
  158. hentry = (RelIdCacheEnt*)hash_search(RelationIdCache, 
  159.  (char *)&(ID),HASH_FIND, &found); 
  160. if (hentry == NULL) 
  161. elog(FATAL, "error in CACHE"); 
  162. if (found) 
  163. RELATION = hentry->reldesc; 
  164. else 
  165. RELATION = NULL; 
  166. } while(0)
  167. #define RelationCacheDelete(RELATION) 
  168. do { 
  169. RelNameCacheEnt *namehentry; RelIdCacheEnt *idhentry; 
  170. char *relname; Oid reloid; bool found; 
  171. relname = (RELATION->rd_rel->relname).data; 
  172. namehentry = (RelNameCacheEnt*)hash_search(RelationNameCache, 
  173.    relname, 
  174.    HASH_REMOVE, 
  175.    &found); 
  176. if (namehentry == NULL) 
  177. elog(FATAL, "can't delete from relation descriptor cache"); 
  178. if (!found) 
  179. elog(NOTICE, "trying to delete a reldesc that does not exist."); 
  180. reloid = RELATION->rd_id; 
  181. idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, 
  182.    (char *)&reloid, 
  183.    HASH_REMOVE, &found); 
  184. if (idhentry == NULL) 
  185. elog(FATAL, "can't delete from relation descriptor cache"); 
  186. if (!found) 
  187. elog(NOTICE, "trying to delete a reldesc that does not exist."); 
  188. } while(0)
  189. /* non-export function prototypes */
  190. static void formrdesc(char *relationName, u_int natts,
  191.   FormData_pg_attribute *att);
  192. #ifdef NOT_USED /* See comments at line 1304 */
  193. static void RelationFlushIndexes(Relation *r, Oid accessMethodId);
  194. #endif
  195. static HeapTuple ScanPgRelation(RelationBuildDescInfo buildinfo);
  196. static HeapTuple scan_pg_rel_seq(RelationBuildDescInfo buildinfo);
  197. static HeapTuple scan_pg_rel_ind(RelationBuildDescInfo buildinfo);
  198. static Relation AllocateRelationDesc(u_int natts, Form_pg_class relp);
  199. static void RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,
  200.    Relation relation, u_int natts);
  201. static void build_tupdesc_seq(RelationBuildDescInfo buildinfo,
  202.   Relation relation, u_int natts);
  203. static void build_tupdesc_ind(RelationBuildDescInfo buildinfo,
  204.   Relation relation, u_int natts);
  205. static Relation RelationBuildDesc(RelationBuildDescInfo buildinfo);
  206. static void IndexedAccessMethodInitialize(Relation relation);
  207. static void AttrDefaultFetch(Relation relation);
  208. static void RelCheckFetch(Relation relation);
  209. extern void RelationBuildTriggers(Relation relation);
  210. extern void FreeTriggerDesc(Relation relation);
  211. /*
  212.  * newlyCreatedRelns -
  213.  *   relations created during this transaction. We need to keep track of
  214.  *   these.
  215.  */
  216. static List *newlyCreatedRelns = NULL;
  217. /* ----------------------------------------------------------------
  218.  * RelationIdGetRelation() and RelationNameGetRelation()
  219.  * support functions
  220.  * ----------------------------------------------------------------
  221.  */
  222. #if NOT_USED /* XXX This doesn't seem to be used
  223.  * anywhere */
  224. /* --------------------------------
  225.  * BuildDescInfoError returns a string appropriate to
  226.  * the buildinfo passed to it
  227.  * --------------------------------
  228.  */
  229. static char *
  230. BuildDescInfoError(RelationBuildDescInfo buildinfo)
  231. {
  232. static char errBuf[64];
  233. MemSet(errBuf, 0, (int) sizeof(errBuf));
  234. switch (buildinfo.infotype)
  235. {
  236. case INFO_RELID:
  237. sprintf(errBuf, "(relation id %u)", buildinfo.i.info_id);
  238. break;
  239. case INFO_RELNAME:
  240. sprintf(errBuf, "(relation name %s)", buildinfo.i.info_name);
  241. break;
  242. }
  243. return errBuf;
  244. }
  245. #endif
  246. /* --------------------------------
  247.  * ScanPgRelation
  248.  *
  249.  * this is used by RelationBuildDesc to find a pg_class
  250.  * tuple matching either a relation name or a relation id
  251.  * as specified in buildinfo.
  252.  * --------------------------------
  253.  */
  254. static HeapTuple
  255. ScanPgRelation(RelationBuildDescInfo buildinfo)
  256. {
  257. /*
  258.  * If this is bootstrap time (initdb), then we can't use the system
  259.  * catalog indices, because they may not exist yet.  Otherwise, we
  260.  * can, and do.
  261.  */
  262. if (IsBootstrapProcessingMode())
  263. return scan_pg_rel_seq(buildinfo);
  264. else
  265. return scan_pg_rel_ind(buildinfo);
  266. }
  267. static HeapTuple
  268. scan_pg_rel_seq(RelationBuildDescInfo buildinfo)
  269. {
  270. HeapTuple pg_class_tuple;
  271. HeapTuple return_tuple;
  272. Relation pg_class_desc;
  273. HeapScanDesc pg_class_scan;
  274. ScanKeyData key;
  275. /* ----------------
  276.  * form a scan key
  277.  * ----------------
  278.  */
  279. switch (buildinfo.infotype)
  280. {
  281. case INFO_RELID:
  282. ScanKeyEntryInitialize(&key, 0,
  283.    ObjectIdAttributeNumber,
  284.    F_OIDEQ,
  285.    ObjectIdGetDatum(buildinfo.i.info_id));
  286. break;
  287. case INFO_RELNAME:
  288. ScanKeyEntryInitialize(&key, 0,
  289.    Anum_pg_class_relname,
  290.    F_NAMEEQ,
  291.    NameGetDatum(buildinfo.i.info_name));
  292. break;
  293. default:
  294. elog(ERROR, "ScanPgRelation: bad buildinfo");
  295. return NULL;
  296. }
  297. /* ----------------
  298.  * open pg_class and fetch a tuple
  299.  * ----------------
  300.  */
  301. pg_class_desc = heap_openr(RelationRelationName);
  302. pg_class_scan = heap_beginscan(pg_class_desc, 0, SnapshotNow, 1, &key);
  303. pg_class_tuple = heap_getnext(pg_class_scan, 0);
  304. /* ----------------
  305.  * get set to return tuple
  306.  * ----------------
  307.  */
  308. if (!HeapTupleIsValid(pg_class_tuple))
  309. return_tuple = pg_class_tuple;
  310. else
  311. {
  312. /* ------------------
  313.  * a satanic bug used to live here: pg_class_tuple used to be
  314.  * returned here without having the corresponding buffer pinned.
  315.  * so when the buffer gets replaced, all hell breaks loose.
  316.  * this bug is discovered and killed by wei on 9/27/91.
  317.  * -------------------
  318.  */
  319. return_tuple = heap_copytuple(pg_class_tuple);
  320. }
  321. /* all done */
  322. heap_endscan(pg_class_scan);
  323. heap_close(pg_class_desc);
  324. return return_tuple;
  325. }
  326. static HeapTuple
  327. scan_pg_rel_ind(RelationBuildDescInfo buildinfo)
  328. {
  329. Relation pg_class_desc;
  330. HeapTuple return_tuple;
  331. pg_class_desc = heap_openr(RelationRelationName);
  332. if (!IsInitProcessingMode())
  333. LockRelation(pg_class_desc, AccessShareLock);
  334. switch (buildinfo.infotype)
  335. {
  336. case INFO_RELID:
  337. return_tuple = ClassOidIndexScan(pg_class_desc, buildinfo.i.info_id);
  338. break;
  339. case INFO_RELNAME:
  340. return_tuple = ClassNameIndexScan(pg_class_desc,
  341.   buildinfo.i.info_name);
  342. break;
  343. default:
  344. elog(ERROR, "ScanPgRelation: bad buildinfo");
  345. /*
  346.  * XXX I hope this is right.  It seems better than returning
  347.  * an uninitialized value
  348.  */
  349. return_tuple = NULL;
  350. }
  351. /* all done */
  352. if (!IsInitProcessingMode())
  353. UnlockRelation(pg_class_desc, AccessShareLock);
  354. heap_close(pg_class_desc);
  355. return return_tuple;
  356. }
  357. /* ----------------
  358.  * AllocateRelationDesc
  359.  *
  360.  * This is used to allocate memory for a new relation descriptor
  361.  * and initialize the rd_rel field.
  362.  * ----------------
  363.  */
  364. static Relation
  365. AllocateRelationDesc(u_int natts, Form_pg_class relp)
  366. {
  367. Relation relation;
  368. Size len;
  369. Form_pg_class relationForm;
  370. /* ----------------
  371.  * allocate space for the relation tuple form
  372.  * ----------------
  373.  */
  374. relationForm = (Form_pg_class)
  375. palloc((Size) (sizeof(FormData_pg_class)));
  376. memmove((char *) relationForm, (char *) relp, CLASS_TUPLE_SIZE);
  377. /* ----------------
  378.  * allocate space for new relation descriptor
  379.  */
  380. len = sizeof(RelationData) + 10; /* + 10 is voodoo XXX mao */
  381. relation = (Relation) palloc(len);
  382. /* ----------------
  383.  * clear new reldesc
  384.  * ----------------
  385.  */
  386. MemSet((char *) relation, 0, len);
  387. /* initialize attribute tuple form */
  388. relation->rd_att = CreateTemplateTupleDesc(natts);
  389. /* and initialize relation tuple form */
  390. relation->rd_rel = relationForm;
  391. return relation;
  392. }
  393. /* --------------------------------
  394.  * RelationBuildTupleDesc
  395.  *
  396.  * Form the relation's tuple descriptor from information in
  397.  * the pg_attribute, pg_attrdef & pg_relcheck system cataloges.
  398.  * --------------------------------
  399.  */
  400. static void
  401. RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,
  402.    Relation relation,
  403.    u_int natts)
  404. {
  405. /*
  406.  * If this is bootstrap time (initdb), then we can't use the system
  407.  * catalog indices, because they may not exist yet.  Otherwise, we
  408.  * can, and do.
  409.  */
  410. if (IsBootstrapProcessingMode())
  411. build_tupdesc_seq(buildinfo, relation, natts);
  412. else
  413. build_tupdesc_ind(buildinfo, relation, natts);
  414. }
  415. static void
  416. build_tupdesc_seq(RelationBuildDescInfo buildinfo,
  417.   Relation relation,
  418.   u_int natts)
  419. {
  420. HeapTuple pg_attribute_tuple;
  421. Relation pg_attribute_desc;
  422. HeapScanDesc pg_attribute_scan;
  423. Form_pg_attribute attp;
  424. ScanKeyData key;
  425. int need;
  426. /* ----------------
  427.  * form a scan key
  428.  * ----------------
  429.  */
  430. ScanKeyEntryInitialize(&key, 0,
  431.    Anum_pg_attribute_attrelid,
  432.    F_OIDEQ,
  433.    ObjectIdGetDatum(RelationGetRelid(relation)));
  434. /* ----------------
  435.  * open pg_attribute and begin a scan
  436.  * ----------------
  437.  */
  438. pg_attribute_desc = heap_openr(AttributeRelationName);
  439. pg_attribute_scan = heap_beginscan(pg_attribute_desc, 0, SnapshotNow, 1, &key);
  440. /* ----------------
  441.  * add attribute data to relation->rd_att
  442.  * ----------------
  443.  */
  444. need = natts;
  445. pg_attribute_tuple = heap_getnext(pg_attribute_scan, 0);
  446. while (HeapTupleIsValid(pg_attribute_tuple) && need > 0)
  447. {
  448. attp = (Form_pg_attribute) GETSTRUCT(pg_attribute_tuple);
  449. if (attp->attnum > 0)
  450. {
  451. relation->rd_att->attrs[attp->attnum - 1] =
  452. (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
  453. memmove((char *) (relation->rd_att->attrs[attp->attnum - 1]),
  454. (char *) attp,
  455. ATTRIBUTE_TUPLE_SIZE);
  456. need--;
  457. }
  458. pg_attribute_tuple = heap_getnext(pg_attribute_scan, 0);
  459. }
  460. if (need > 0)
  461. elog(ERROR, "catalog is missing %d attribute%s for relid %u",
  462.  need, (need == 1 ? "" : "s"), RelationGetRelid(relation));
  463. /* ----------------
  464.  * end the scan and close the attribute relation
  465.  * ----------------
  466.  */
  467. heap_endscan(pg_attribute_scan);
  468. heap_close(pg_attribute_desc);
  469. }
  470. static void
  471. build_tupdesc_ind(RelationBuildDescInfo buildinfo,
  472.   Relation relation,
  473.   u_int natts)
  474. {
  475. Relation attrel;
  476. HeapTuple atttup;
  477. Form_pg_attribute attp;
  478. TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr));
  479. AttrDefault *attrdef = NULL;
  480. int ndef = 0;
  481. int i;
  482. constr->has_not_null = false;
  483. attrel = heap_openr(AttributeRelationName);
  484. for (i = 1; i <= relation->rd_rel->relnatts; i++)
  485. {
  486. atttup = (HeapTuple) AttributeNumIndexScan(attrel,
  487.   RelationGetRelid(relation), i);
  488. if (!HeapTupleIsValid(atttup))
  489. elog(ERROR, "cannot find attribute %d of relation %s", i,
  490.  relation->rd_rel->relname.data);
  491. attp = (Form_pg_attribute) GETSTRUCT(atttup);
  492. relation->rd_att->attrs[i - 1] =
  493. (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
  494. memmove((char *) (relation->rd_att->attrs[i - 1]),
  495. (char *) attp,
  496. ATTRIBUTE_TUPLE_SIZE);
  497. /* Update if this attribute have a constraint */
  498. if (attp->attnotnull)
  499. constr->has_not_null = true;
  500. if (attp->atthasdef)
  501. {
  502. if (attrdef == NULL)
  503. attrdef = (AttrDefault *) palloc(relation->rd_rel->relnatts *
  504.  sizeof(AttrDefault));
  505. attrdef[ndef].adnum = i;
  506. attrdef[ndef].adbin = NULL;
  507. attrdef[ndef].adsrc = NULL;
  508. ndef++;
  509. }
  510. }
  511. heap_close(attrel);
  512. if (constr->has_not_null || ndef > 0 || relation->rd_rel->relchecks)
  513. {
  514. relation->rd_att->constr = constr;
  515. if (ndef > 0) /* DEFAULTs */
  516. {
  517. if (ndef < relation->rd_rel->relnatts)
  518. constr->defval = (AttrDefault *)
  519. repalloc(attrdef, ndef * sizeof(AttrDefault));
  520. else
  521. constr->defval = attrdef;
  522. constr->num_defval = ndef;
  523. AttrDefaultFetch(relation);
  524. }
  525. else
  526. constr->num_defval = 0;
  527. if (relation->rd_rel->relchecks > 0) /* CHECKs */
  528. {
  529. constr->num_check = relation->rd_rel->relchecks;
  530. constr->check = (ConstrCheck *) palloc(constr->num_check *
  531.    sizeof(ConstrCheck));
  532. MemSet(constr->check, 0, constr->num_check * sizeof(ConstrCheck));
  533. RelCheckFetch(relation);
  534. }
  535. else
  536. constr->num_check = 0;
  537. }
  538. else
  539. {
  540. pfree(constr);
  541. relation->rd_att->constr = NULL;
  542. }
  543. }
  544. /* --------------------------------
  545.  * RelationBuildRuleLock
  546.  *
  547.  * Form the relation's rewrite rules from information in
  548.  * the pg_rewrite system catalog.
  549.  * --------------------------------
  550.  */
  551. static void
  552. RelationBuildRuleLock(Relation relation)
  553. {
  554. HeapTuple pg_rewrite_tuple;
  555. Relation pg_rewrite_desc;
  556. TupleDesc pg_rewrite_tupdesc;
  557. HeapScanDesc pg_rewrite_scan;
  558. ScanKeyData key;
  559. RuleLock   *rulelock;
  560. int numlocks;
  561. RewriteRule **rules;
  562. int maxlocks;
  563. /* ----------------
  564.  * form an array to hold the rewrite rules (the array is extended if
  565.  * necessary)
  566.  * ----------------
  567.  */
  568. maxlocks = 4;
  569. rules = (RewriteRule **) palloc(sizeof(RewriteRule *) * maxlocks);
  570. numlocks = 0;
  571. /* ----------------
  572.  * form a scan key
  573.  * ----------------
  574.  */
  575. ScanKeyEntryInitialize(&key, 0,
  576.    Anum_pg_rewrite_ev_class,
  577.    F_OIDEQ,
  578.    ObjectIdGetDatum(RelationGetRelid(relation)));
  579. /* ----------------
  580.  * open pg_attribute and begin a scan
  581.  * ----------------
  582.  */
  583. pg_rewrite_desc = heap_openr(RewriteRelationName);
  584. pg_rewrite_scan = heap_beginscan(pg_rewrite_desc, 0, SnapshotNow, 1, &key);
  585. pg_rewrite_tupdesc = RelationGetDescr(pg_rewrite_desc);
  586. /* ----------------
  587.  * add attribute data to relation->rd_att
  588.  * ----------------
  589.  */
  590. while (HeapTupleIsValid(pg_rewrite_tuple = heap_getnext(pg_rewrite_scan, 0)))
  591. {
  592. bool isnull;
  593. Datum ruleaction;
  594. Datum rule_evqual_string;
  595. RewriteRule *rule;
  596. rule = (RewriteRule *) palloc(sizeof(RewriteRule));
  597. rule->ruleId = pg_rewrite_tuple->t_data->t_oid;
  598. rule->event = (int) heap_getattr(pg_rewrite_tuple,
  599.  Anum_pg_rewrite_ev_type, pg_rewrite_tupdesc,
  600.  &isnull) - 48;
  601. rule->attrno = (int) heap_getattr(pg_rewrite_tuple,
  602.  Anum_pg_rewrite_ev_attr, pg_rewrite_tupdesc,
  603.   &isnull);
  604. rule->isInstead = !!heap_getattr(pg_rewrite_tuple,
  605.   Anum_pg_rewrite_is_instead, pg_rewrite_tupdesc,
  606.  &isnull);
  607. ruleaction = heap_getattr(pg_rewrite_tuple,
  608.    Anum_pg_rewrite_ev_action, pg_rewrite_tupdesc,
  609.   &isnull);
  610. rule_evqual_string = heap_getattr(pg_rewrite_tuple,
  611.  Anum_pg_rewrite_ev_qual, pg_rewrite_tupdesc,
  612.   &isnull);
  613. ruleaction = PointerGetDatum(textout((struct varlena *) DatumGetPointer(ruleaction)));
  614. rule_evqual_string = PointerGetDatum(textout((struct varlena *) DatumGetPointer(rule_evqual_string)));
  615. rule->actions = (List *) stringToNode(DatumGetPointer(ruleaction));
  616. rule->qual = (Node *) stringToNode(DatumGetPointer(rule_evqual_string));
  617. rules[numlocks++] = rule;
  618. if (numlocks == maxlocks)
  619. {
  620. maxlocks *= 2;
  621. rules = (RewriteRule **) repalloc(rules, sizeof(RewriteRule *) * maxlocks);
  622. }
  623. }
  624. /* ----------------
  625.  * end the scan and close the attribute relation
  626.  * ----------------
  627.  */
  628. heap_endscan(pg_rewrite_scan);
  629. heap_close(pg_rewrite_desc);
  630. /* ----------------
  631.  * form a RuleLock and insert into relation
  632.  * ----------------
  633.  */
  634. rulelock = (RuleLock *) palloc(sizeof(RuleLock));
  635. rulelock->numLocks = numlocks;
  636. rulelock->rules = rules;
  637. relation->rd_rules = rulelock;
  638. return;
  639. }
  640. /* --------------------------------
  641.  * RelationBuildDesc
  642.  *
  643.  * To build a relation descriptor, we have to allocate space,
  644.  * open the underlying unix file and initialize the following
  645.  * fields:
  646.  *
  647.  * File    rd_fd;  open file descriptor
  648.  * int    rd_nblocks;  number of blocks in rel
  649.  *  it will be set in ambeginscan()
  650.  * uint16    rd_refcnt;  reference count
  651.  * Form_pg_am    rd_am;  AM tuple
  652.  * Form_pg_class    rd_rel;  RELATION tuple
  653.  * Oid    rd_id;  relations's object id
  654.  * Pointer    lockInfo;  ptr. to misc. info.
  655.  * TupleDesc    rd_att;  tuple desciptor
  656.  *
  657.  * Note: rd_ismem (rel is in-memory only) is currently unused
  658.  * by any part of the system. someday this will indicate that
  659.  * the relation lives only in the main-memory buffer pool
  660.  * -cim 2/4/91
  661.  * --------------------------------
  662.  */
  663. static Relation
  664. RelationBuildDesc(RelationBuildDescInfo buildinfo)
  665. {
  666. File fd;
  667. Relation relation;
  668. u_int natts;
  669. Oid relid;
  670. Oid relam;
  671. Form_pg_class relp;
  672. MemoryContext oldcxt;
  673. HeapTuple pg_class_tuple;
  674. oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
  675. /* ----------------
  676.  * find the tuple in pg_class corresponding to the given relation id
  677.  * ----------------
  678.  */
  679. pg_class_tuple = ScanPgRelation(buildinfo);
  680. /* ----------------
  681.  * if no such tuple exists, return NULL
  682.  * ----------------
  683.  */
  684. if (!HeapTupleIsValid(pg_class_tuple))
  685. {
  686. MemoryContextSwitchTo(oldcxt);
  687. return NULL;
  688. }
  689. /* ----------------
  690.  * get information from the pg_class_tuple
  691.  * ----------------
  692.  */
  693. relid = pg_class_tuple->t_data->t_oid;
  694. relp = (Form_pg_class) GETSTRUCT(pg_class_tuple);
  695. natts = relp->relnatts;
  696. /* ----------------
  697.  * allocate storage for the relation descriptor,
  698.  * initialize relation->rd_rel and get the access method id.
  699.  * ----------------
  700.  */
  701. relation = AllocateRelationDesc(natts, relp);
  702. relam = relation->rd_rel->relam;
  703. /* ----------------
  704.  * initialize the relation's relation id (relation->rd_id)
  705.  * ----------------
  706.  */
  707. RelationGetRelid(relation) = relid;
  708. /* ----------------
  709.  * initialize relation->rd_refcnt
  710.  * ----------------
  711.  */
  712. RelationSetReferenceCount(relation, 1);
  713. /* ----------------
  714.  *  normal relations are not nailed into the cache
  715.  * ----------------
  716.  */
  717. relation->rd_isnailed = false;
  718. /* ----------------
  719.  * initialize the access method information (relation->rd_am)
  720.  * ----------------
  721.  */
  722. if (OidIsValid(relam))
  723. relation->rd_am = (Form_pg_am) AccessMethodObjectIdGetForm(relam);
  724. /* ----------------
  725.  * initialize the tuple descriptor (relation->rd_att).
  726.  * remember, rd_att is an array of attribute pointers that lives
  727.  * off the end of the relation descriptor structure so space was
  728.  * already allocated for it by AllocateRelationDesc.
  729.  * ----------------
  730.  */
  731. RelationBuildTupleDesc(buildinfo, relation, natts);
  732. /* ----------------
  733.  * initialize rules that affect this relation
  734.  * ----------------
  735.  */
  736. if (relp->relhasrules)
  737. RelationBuildRuleLock(relation);
  738. else
  739. relation->rd_rules = NULL;
  740. /* Triggers */
  741. if (relp->reltriggers > 0)
  742. RelationBuildTriggers(relation);
  743. else
  744. relation->trigdesc = NULL;
  745. /* ----------------
  746.  * initialize index strategy and support information for this relation
  747.  * ----------------
  748.  */
  749. if (OidIsValid(relam))
  750. IndexedAccessMethodInitialize(relation);
  751. /* ----------------
  752.  * initialize the relation lock manager information
  753.  * ----------------
  754.  */
  755. RelationInitLockInfo(relation); /* see lmgr.c */
  756. /* ----------------
  757.  * open the relation and assign the file descriptor returned
  758.  * by the storage manager code to rd_fd.
  759.  * ----------------
  760.  */
  761. fd = smgropen(DEFAULT_SMGR, relation);
  762. Assert(fd >= -1);
  763. if (fd == -1)
  764. elog(NOTICE, "RelationIdBuildRelation: smgropen(%s): %m",
  765.  &relp->relname);
  766. relation->rd_fd = fd;
  767. /* ----------------
  768.  * insert newly created relation into proper relcaches,
  769.  * restore memory context and return the new reldesc.
  770.  * ----------------
  771.  */
  772. RelationCacheInsert(relation);
  773. /* -------------------
  774.  * free the memory allocated for pg_class_tuple
  775.  * and for lock data pointed to by pg_class_tuple
  776.  * -------------------
  777.  */
  778. pfree(pg_class_tuple);
  779. MemoryContextSwitchTo(oldcxt);
  780. return relation;
  781. }
  782. static void
  783. IndexedAccessMethodInitialize(Relation relation)
  784. {
  785. IndexStrategy strategy;
  786. RegProcedure *support;
  787. int natts;
  788. Size stratSize;
  789. Size supportSize;
  790. uint16 relamstrategies;
  791. uint16 relamsupport;
  792. natts = relation->rd_rel->relnatts;
  793. relamstrategies = relation->rd_am->amstrategies;
  794. stratSize = AttributeNumberGetIndexStrategySize(natts, relamstrategies);
  795. strategy = (IndexStrategy) palloc(stratSize);
  796. relamsupport = relation->rd_am->amsupport;
  797. if (relamsupport > 0)
  798. {
  799. supportSize = natts * (relamsupport * sizeof(RegProcedure));
  800. support = (RegProcedure *) palloc(supportSize);
  801. }
  802. else
  803. support = (RegProcedure *) NULL;
  804. IndexSupportInitialize(strategy, support,
  805.    relation->rd_att->attrs[0]->attrelid,
  806.    relation->rd_rel->relam,
  807.    relamstrategies, relamsupport, natts);
  808. RelationSetIndexSupport(relation, strategy, support);
  809. }
  810. /* --------------------------------
  811.  * formrdesc
  812.  *
  813.  * This is a special version of RelationBuildDesc()
  814.  * used by RelationInitialize() in initializing the
  815.  * relcache.  The system relation descriptors built
  816.  * here are all nailed in the descriptor caches, for
  817.  * bootstrapping.
  818.  * --------------------------------
  819.  */
  820. static void
  821. formrdesc(char *relationName,
  822.   u_int natts,
  823.   FormData_pg_attribute *att)
  824. {
  825. Relation relation;
  826. Size len;
  827. int i;
  828. /* ----------------
  829.  * allocate new relation desc
  830.  * ----------------
  831.  */
  832. len = sizeof(RelationData);
  833. relation = (Relation) palloc(len);
  834. MemSet((char *) relation, 0, len);
  835. /* ----------------
  836.  * don't open the unix file yet..
  837.  * ----------------
  838.  */
  839. relation->rd_fd = -1;
  840. /* ----------------
  841.  * initialize reference count
  842.  * ----------------
  843.  */
  844. RelationSetReferenceCount(relation, 1);
  845. /* ----------------
  846.  * initialize relation tuple form
  847.  * ----------------
  848.  */
  849. relation->rd_rel = (Form_pg_class)
  850. palloc((Size) (sizeof(*relation->rd_rel)));
  851. MemSet(relation->rd_rel, 0, sizeof(FormData_pg_class));
  852. namestrcpy(&relation->rd_rel->relname, relationName);
  853. /* ----------------
  854.    initialize attribute tuple form
  855. */
  856. relation->rd_att = CreateTemplateTupleDesc(natts);
  857. /*
  858.  * For debugging purposes, it's important to distinguish between
  859.  * shared and non-shared relations, even at bootstrap time.  There's
  860.  * code in the buffer manager that traces allocations that has to know
  861.  * about this.
  862.  */
  863. if (IsSystemRelationName(relationName))
  864. {
  865. relation->rd_rel->relowner = 6; /* XXX use sym const */
  866. relation->rd_rel->relisshared = IsSharedSystemRelationName(relationName);
  867. }
  868. else
  869. {
  870. relation->rd_rel->relowner = 0;
  871. relation->rd_rel->relisshared = false;
  872. }
  873. relation->rd_rel->relpages = 1; /* XXX */
  874. relation->rd_rel->reltuples = 1; /* XXX */
  875. relation->rd_rel->relkind = RELKIND_RELATION;
  876. relation->rd_rel->relnatts = (uint16) natts;
  877. relation->rd_isnailed = true;
  878. /* ----------------
  879.  * initialize tuple desc info
  880.  * ----------------
  881.  */
  882. for (i = 0; i < natts; i++)
  883. {
  884. relation->rd_att->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
  885. MemSet((char *) relation->rd_att->attrs[i], 0,
  886.    ATTRIBUTE_TUPLE_SIZE);
  887. memmove((char *) relation->rd_att->attrs[i],
  888. (char *) &att[i],
  889. ATTRIBUTE_TUPLE_SIZE);
  890. }
  891. /* ----------------
  892.  * initialize relation id
  893.  * ----------------
  894.  */
  895. RelationGetRelid(relation) = relation->rd_att->attrs[0]->attrelid;
  896. /* ----------------
  897.  * add new reldesc to relcache
  898.  * ----------------
  899.  */
  900. RelationCacheInsert(relation);
  901. RelationInitLockInfo(relation);
  902. /*
  903.  * Determining this requires a scan on pg_class, but to do the scan
  904.  * the rdesc for pg_class must already exist.  Therefore we must do
  905.  * the check (and possible set) after cache insertion.
  906.  */
  907. relation->rd_rel->relhasindex =
  908. CatalogHasIndex(relationName, RelationGetRelid(relation));
  909. }
  910. /* ----------------------------------------------------------------
  911.  *  Relation Descriptor Lookup Interface
  912.  * ----------------------------------------------------------------
  913.  */
  914. /* --------------------------------
  915.  * RelationIdCacheGetRelation
  916.  *
  917.  * only try to get the reldesc by looking up the cache
  918.  * do not go to the disk. this is used by BlockPrepareFile()
  919.  * and RelationIdGetRelation below.
  920.  * --------------------------------
  921.  */
  922. Relation
  923. RelationIdCacheGetRelation(Oid relationId)
  924. {
  925. Relation rd;
  926. RelationIdCacheLookup(relationId, rd);
  927. if (RelationIsValid(rd))
  928. {
  929. if (rd->rd_fd == -1)
  930. {
  931. rd->rd_fd = smgropen(DEFAULT_SMGR, rd);
  932. Assert(rd->rd_fd != -1);
  933. }
  934. RelationIncrementReferenceCount(rd);
  935. }
  936. return rd;
  937. }
  938. /* --------------------------------
  939.  * RelationNameCacheGetRelation
  940.  * --------------------------------
  941.  */
  942. static Relation
  943. RelationNameCacheGetRelation(char *relationName)
  944. {
  945. Relation rd;
  946. NameData name;
  947. /*
  948.  * make sure that the name key used for hash lookup is properly
  949.  * null-padded
  950.  */
  951. namestrcpy(&name, relationName);
  952. RelationNameCacheLookup(name.data, rd);
  953. if (RelationIsValid(rd))
  954. {
  955. if (rd->rd_fd == -1)
  956. {
  957. rd->rd_fd = smgropen(DEFAULT_SMGR, rd);
  958. Assert(rd->rd_fd != -1);
  959. }
  960. RelationIncrementReferenceCount(rd);
  961. }
  962. return rd;
  963. }
  964. /* --------------------------------
  965.  * RelationIdGetRelation
  966.  *
  967.  * return a relation descriptor based on its id.
  968.  * return a cached value if possible
  969.  * --------------------------------
  970.  */
  971. Relation
  972. RelationIdGetRelation(Oid relationId)
  973. {
  974. Relation rd;
  975. RelationBuildDescInfo buildinfo;
  976. /* ----------------
  977.  * increment access statistics
  978.  * ----------------
  979.  */
  980. IncrHeapAccessStat(local_RelationIdGetRelation);
  981. IncrHeapAccessStat(global_RelationIdGetRelation);
  982. /* ----------------
  983.  * first try and get a reldesc from the cache
  984.  * ----------------
  985.  */
  986. rd = RelationIdCacheGetRelation(relationId);
  987. if (RelationIsValid(rd))
  988. return rd;
  989. /* ----------------
  990.  * no reldesc in the cache, so have RelationBuildDesc()
  991.  * build one and add it.
  992.  * ----------------
  993.  */
  994. buildinfo.infotype = INFO_RELID;
  995. buildinfo.i.info_id = relationId;
  996. rd = RelationBuildDesc(buildinfo);
  997. return rd;
  998. }
  999. /* --------------------------------
  1000.  * RelationNameGetRelation
  1001.  *
  1002.  * return a relation descriptor based on its name.
  1003.  * return a cached value if possible
  1004.  * --------------------------------
  1005.  */
  1006. Relation
  1007. RelationNameGetRelation(char *relationName)
  1008. {
  1009. Relation rd;
  1010. RelationBuildDescInfo buildinfo;
  1011. /* ----------------
  1012.  * increment access statistics
  1013.  * ----------------
  1014.  */
  1015. IncrHeapAccessStat(local_RelationNameGetRelation);
  1016. IncrHeapAccessStat(global_RelationNameGetRelation);
  1017. /* ----------------
  1018.  * first try and get a reldesc from the cache
  1019.  * ----------------
  1020.  */
  1021. rd = RelationNameCacheGetRelation(relationName);
  1022. if (RelationIsValid(rd))
  1023. return rd;
  1024. /* ----------------
  1025.  * no reldesc in the cache, so have RelationBuildDesc()
  1026.  * build one and add it.
  1027.  * ----------------
  1028.  */
  1029. buildinfo.infotype = INFO_RELNAME;
  1030. buildinfo.i.info_name = relationName;
  1031. rd = RelationBuildDesc(buildinfo);
  1032. return rd;
  1033. }
  1034. /* ----------------
  1035.  * old "getreldesc" interface.
  1036.  * ----------------
  1037.  */
  1038. #ifdef NOT_USED
  1039. Relation
  1040. getreldesc(char *relationName)
  1041. {
  1042. /* ----------------
  1043.  * increment access statistics
  1044.  * ----------------
  1045.  */
  1046. IncrHeapAccessStat(local_getreldesc);
  1047. IncrHeapAccessStat(global_getreldesc);
  1048. return RelationNameGetRelation(relationName);
  1049. }
  1050. #endif
  1051. /* ----------------------------------------------------------------
  1052.  * cache invalidation support routines
  1053.  * ----------------------------------------------------------------
  1054.  */
  1055. /* --------------------------------
  1056.  * RelationClose - close an open relation
  1057.  * --------------------------------
  1058.  */
  1059. void
  1060. RelationClose(Relation relation)
  1061. {
  1062. /* Note: no locking manipulations needed */
  1063. RelationDecrementReferenceCount(relation);
  1064. }
  1065. /* --------------------------------
  1066.  * RelationFlushRelation
  1067.  *
  1068.  *  Actually blows away a relation... RelationFree doesn't do
  1069.  *  anything anymore.
  1070.  * --------------------------------
  1071.  */
  1072. static void
  1073. RelationFlushRelation(Relation *relationPtr,
  1074.   bool onlyFlushReferenceCountZero)
  1075. {
  1076. MemoryContext oldcxt;
  1077. Relation relation = *relationPtr;
  1078. if (relation->rd_isnailed)
  1079. {
  1080. /* this is a nailed special relation for bootstraping */
  1081. return;
  1082. }
  1083. if (!onlyFlushReferenceCountZero ||
  1084. RelationHasReferenceCountZero(relation))
  1085. {
  1086. oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
  1087. /* make sure smgr and lower levels close the relation's files,
  1088.  * if they weren't closed already
  1089.  */
  1090. smgrclose(DEFAULT_SMGR, relation);
  1091. RelationCacheDelete(relation);
  1092. FreeTupleDesc(relation->rd_att);
  1093. SystemCacheRelationFlushed(RelationGetRelid(relation));
  1094. FreeTriggerDesc(relation);
  1095. #ifdef NOT_USED
  1096. if (relation->rd_rules)
  1097. {
  1098. int j;
  1099. for (j = 0; j < relation->rd_rules->numLocks; j++)
  1100. pfree(relation->rd_rules->rules[j]);
  1101. pfree(relation->rd_rules->rules);
  1102. pfree(relation->rd_rules);
  1103. }
  1104. #endif
  1105. pfree(RelationGetLockInfo(relation));
  1106. pfree(RelationGetForm(relation));
  1107. pfree(relation);
  1108. MemoryContextSwitchTo(oldcxt);
  1109. }
  1110. }
  1111. /* --------------------------------
  1112.  * RelationForgetRelation -
  1113.  *    RelationFlushRelation + if the relation is myxactonly then
  1114.  *    get rid of the relation descriptor from the newly created
  1115.  *    relation list.
  1116.  * --------------------------------
  1117.  */
  1118. void
  1119. RelationForgetRelation(Oid rid)
  1120. {
  1121. Relation relation;
  1122. RelationIdCacheLookup(rid, relation);
  1123. if (PointerIsValid(relation))
  1124. {
  1125. if (relation->rd_myxactonly)
  1126. {
  1127. MemoryContext oldcxt;
  1128. List    *curr;
  1129. List    *prev = NIL;
  1130. oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
  1131. foreach(curr, newlyCreatedRelns)
  1132. {
  1133. Relation reln = lfirst(curr);
  1134. Assert(reln != NULL && reln->rd_myxactonly);
  1135. if (RelationGetRelid(reln) == rid)
  1136. break;
  1137. prev = curr;
  1138. }
  1139. if (curr == NIL)
  1140. elog(FATAL, "Local relation %s not found in list",
  1141.  (RelationGetRelationName(relation))->data);
  1142. if (prev == NIL)
  1143. newlyCreatedRelns = lnext(newlyCreatedRelns);
  1144. else
  1145. lnext(prev) = lnext(curr);
  1146. pfree(curr);
  1147. MemoryContextSwitchTo(oldcxt);
  1148. }
  1149. RelationFlushRelation(&relation, false);
  1150. }
  1151. }
  1152. /* --------------------------------
  1153.  * RelationIdInvalidateRelationCacheByRelationId
  1154.  * --------------------------------
  1155.  */
  1156. void
  1157. RelationIdInvalidateRelationCacheByRelationId(Oid relationId)
  1158. {
  1159. Relation relation;
  1160. RelationIdCacheLookup(relationId, relation);
  1161. /*
  1162.  * "local" relations are invalidated by RelationPurgeLocalRelation.
  1163.  * (This is to make LocalBufferSync's life easier: want the descriptor
  1164.  * to hang around for a while. In fact, won't we want this for
  1165.  * BufferSync also? But I'll leave it for now since I don't want to
  1166.  * break anything.) - ay 3/95
  1167.  */
  1168. if (PointerIsValid(relation) && !relation->rd_myxactonly)
  1169. {
  1170. /*
  1171.  * The boolean onlyFlushReferenceCountZero in RelationFlushReln()
  1172.  * should be set to true when we are incrementing the command
  1173.  * counter and to false when we are starting a new xaction.  This
  1174.  * can be determined by checking the current xaction status.
  1175.  */
  1176. RelationFlushRelation(&relation, CurrentXactInProgress());
  1177. }
  1178. }
  1179. #if NOT_USED /* See comments at line 1304 */
  1180. /* --------------------------------
  1181.  * RelationIdInvalidateRelationCacheByAccessMethodId
  1182.  *
  1183.  * RelationFlushIndexes is needed for use with HashTableWalk..
  1184.  * --------------------------------
  1185.  */
  1186. static void
  1187. RelationFlushIndexes(Relation *r,
  1188.  Oid accessMethodId)
  1189. {
  1190. Relation relation = *r;
  1191. if (!RelationIsValid(relation))
  1192. {
  1193. elog(NOTICE, "inval call to RFI");
  1194. return;
  1195. }
  1196. if (relation->rd_rel->relkind == RELKIND_INDEX && /* XXX style */
  1197. (!OidIsValid(accessMethodId) ||
  1198.  relation->rd_rel->relam == accessMethodId))
  1199. RelationFlushRelation(&relation, false);
  1200. }
  1201. #endif
  1202. void
  1203. RelationIdInvalidateRelationCacheByAccessMethodId(Oid accessMethodId)
  1204. {
  1205. #ifdef NOT_USED
  1206. /*
  1207.  * 25 aug 1992:  mao commented out the ht walk below.  it should be
  1208.  * doing the right thing, in theory, but flushing reldescs for index
  1209.  * relations apparently doesn't work.  we want to cut 4.0.1, and i
  1210.  * don't want to introduce new bugs.  this code never executed before,
  1211.  * so i'm turning it off for now.  after the release is cut, i'll fix
  1212.  * this up.
  1213.  */
  1214. HashTableWalk(RelationNameCache, (HashtFunc) RelationFlushIndexes,
  1215.   accessMethodId);
  1216. #else
  1217. return;
  1218. #endif
  1219. }
  1220. /*
  1221.  * RelationCacheInvalidate
  1222.  *
  1223.  *  Will blow away either all the cached relation descriptors or
  1224.  *  those that have a zero reference count.
  1225.  *
  1226.  */
  1227. void
  1228. RelationCacheInvalidate(bool onlyFlushReferenceCountZero)
  1229. {
  1230. HashTableWalk(RelationNameCache, (HashtFunc) RelationFlushRelation,
  1231.   onlyFlushReferenceCountZero);
  1232. /*
  1233.  * nailed-in reldescs will still be in the cache... 7 hardwired heaps
  1234.  * + 3 hardwired indices == 10 total.
  1235.  */
  1236. if (!onlyFlushReferenceCountZero)
  1237. {
  1238. Assert(RelationNameCache->hctl->nkeys == 10);
  1239. Assert(RelationIdCache->hctl->nkeys == 10);
  1240. }
  1241. }
  1242. /* --------------------------------
  1243.  * RelationRegisterRelation -
  1244.  *    register the Relation descriptor of a newly created relation
  1245.  *    with the relation descriptor Cache.
  1246.  * --------------------------------
  1247.  */
  1248. void
  1249. RelationRegisterRelation(Relation relation)
  1250. {
  1251. MemoryContext oldcxt;
  1252. oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
  1253. if (oldcxt != (MemoryContext) CacheCxt)
  1254. elog(NOIND, "RelationRegisterRelation: WARNING: Context != CacheCxt");
  1255. RelationCacheInsert(relation);
  1256. RelationInitLockInfo(relation);
  1257. /*
  1258.  * we've just created the relation. It is invisible to anyone else
  1259.  * before the transaction is committed. Setting rd_myxactonly allows
  1260.  * us to use the local buffer manager for select/insert/etc before the
  1261.  * end of transaction. (We also need to keep track of relations
  1262.  * created during a transaction and does the necessary clean up at the
  1263.  * end of the transaction.) - ay 3/95
  1264.  */
  1265. relation->rd_myxactonly = TRUE;
  1266. newlyCreatedRelns = lcons(relation, newlyCreatedRelns);
  1267. MemoryContextSwitchTo(oldcxt);
  1268. }
  1269. /*
  1270.  * RelationPurgeLocalRelation -
  1271.  *   find all the Relation descriptors marked rd_myxactonly and reset them.
  1272.  *   This should be called at the end of a transaction (commit/abort) when
  1273.  *   the "local" relations will become visible to others and the multi-user
  1274.  *   buffer pool should be used.
  1275.  */
  1276. void
  1277. RelationPurgeLocalRelation(bool xactCommitted)
  1278. {
  1279. MemoryContext oldcxt;
  1280. if (newlyCreatedRelns == NULL)
  1281. return;
  1282. oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
  1283. while (newlyCreatedRelns)
  1284. {
  1285. List    *l = newlyCreatedRelns;
  1286. Relation reln = lfirst(l);
  1287. Assert(reln != NULL && reln->rd_myxactonly);
  1288. if (!xactCommitted)
  1289. {
  1290. /*
  1291.  * remove the file if we abort. This is so that files for
  1292.  * tables created inside a transaction block get removed.
  1293.  */
  1294. if (reln->rd_isnoname)
  1295. {
  1296. if (!(reln->rd_nonameunlinked))
  1297. {
  1298. smgrunlink(DEFAULT_SMGR, reln);
  1299. reln->rd_nonameunlinked = TRUE;
  1300. }
  1301. }
  1302. else
  1303. smgrunlink(DEFAULT_SMGR, reln);
  1304. }
  1305. reln->rd_myxactonly = FALSE;
  1306. if (!IsBootstrapProcessingMode())
  1307. RelationFlushRelation(&reln, FALSE);
  1308. newlyCreatedRelns = lnext(newlyCreatedRelns);
  1309. pfree(l);
  1310. }
  1311. MemoryContextSwitchTo(oldcxt);
  1312. }
  1313. /* --------------------------------
  1314.  * RelationInitialize
  1315.  *
  1316.  * This initializes the relation descriptor cache.
  1317.  * --------------------------------
  1318.  */
  1319. #define INITRELCACHESIZE 400
  1320. void
  1321. RelationInitialize(void)
  1322. {
  1323. MemoryContext oldcxt;
  1324. HASHCTL ctl;
  1325. /* ----------------
  1326.  * switch to cache memory context
  1327.  * ----------------
  1328.  */
  1329. if (!CacheCxt)
  1330. CacheCxt = CreateGlobalMemory("Cache");
  1331. oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
  1332. /* ----------------
  1333.  * create global caches
  1334.  * ----------------
  1335.  */
  1336. MemSet(&ctl, 0, (int) sizeof(ctl));
  1337. ctl.keysize = sizeof(NameData);
  1338. ctl.datasize = sizeof(Relation);
  1339. RelationNameCache = hash_create(INITRELCACHESIZE, &ctl, HASH_ELEM);
  1340. ctl.keysize = sizeof(Oid);
  1341. ctl.hash = tag_hash;
  1342. RelationIdCache = hash_create(INITRELCACHESIZE, &ctl,
  1343.   HASH_ELEM | HASH_FUNCTION);
  1344. /* ----------------
  1345.  * initialize the cache with pre-made relation descriptors
  1346.  * for some of the more important system relations.  These
  1347.  * relations should always be in the cache.
  1348.  * ----------------
  1349.  */
  1350. formrdesc(RelationRelationName, Natts_pg_class, Desc_pg_class);
  1351. formrdesc(AttributeRelationName, Natts_pg_attribute, Desc_pg_attribute);
  1352. formrdesc(ProcedureRelationName, Natts_pg_proc, Desc_pg_proc);
  1353. formrdesc(TypeRelationName, Natts_pg_type, Desc_pg_type);
  1354. formrdesc(VariableRelationName, Natts_pg_variable, Desc_pg_variable);
  1355. formrdesc(LogRelationName, Natts_pg_log, Desc_pg_log);
  1356. /*
  1357.  * If this isn't initdb time, then we want to initialize some index
  1358.  * relation descriptors, as well.  The descriptors are for
  1359.  * pg_attnumind (to make building relation descriptors fast) and
  1360.  * possibly others, as they're added.
  1361.  */
  1362. if (!IsBootstrapProcessingMode())
  1363. init_irels();
  1364. MemoryContextSwitchTo(oldcxt);
  1365. }
  1366. static void
  1367. AttrDefaultFetch(Relation relation)
  1368. {
  1369. AttrDefault *attrdef = relation->rd_att->constr->defval;
  1370. int ndef = relation->rd_att->constr->num_defval;
  1371. Relation adrel;
  1372. Relation irel;
  1373. ScanKeyData skey;
  1374. HeapTupleData tuple;
  1375. Form_pg_attrdef adform;
  1376. IndexScanDesc sd;
  1377. RetrieveIndexResult indexRes;
  1378. struct varlena *val;
  1379. bool isnull;
  1380. int found;
  1381. int i;
  1382. ScanKeyEntryInitialize(&skey,
  1383.    (bits16) 0x0,
  1384.    (AttrNumber) 1,
  1385.    (RegProcedure) F_OIDEQ,
  1386.    ObjectIdGetDatum(RelationGetRelid(relation)));
  1387. adrel = heap_openr(AttrDefaultRelationName);
  1388. irel = index_openr(AttrDefaultIndex);
  1389. sd = index_beginscan(irel, false, 1, &skey);
  1390. tuple.t_data = NULL;
  1391. for (found = 0;;)
  1392. {
  1393. Buffer buffer;
  1394. indexRes = index_getnext(sd, ForwardScanDirection);
  1395. if (!indexRes)
  1396. break;
  1397. tuple.t_self = indexRes->heap_iptr;
  1398. heap_fetch(adrel, SnapshotNow, &tuple, &buffer);
  1399. pfree(indexRes);
  1400. if (tuple.t_data == NULL)
  1401. continue;
  1402. found++;
  1403. adform = (Form_pg_attrdef) GETSTRUCT(&tuple);
  1404. for (i = 0; i < ndef; i++)
  1405. {
  1406. if (adform->adnum != attrdef[i].adnum)
  1407. continue;
  1408. if (attrdef[i].adsrc != NULL)
  1409. elog(ERROR, "AttrDefaultFetch: second record found for attr %s in rel %s",
  1410. relation->rd_att->attrs[adform->adnum - 1]->attname.data,
  1411.  relation->rd_rel->relname.data);
  1412. val = (struct varlena *) fastgetattr(&tuple,
  1413.  Anum_pg_attrdef_adbin,
  1414.  adrel->rd_att, &isnull);
  1415. if (isnull)
  1416. elog(ERROR, "AttrDefaultFetch: adbin IS NULL for attr %s in rel %s",
  1417. relation->rd_att->attrs[adform->adnum - 1]->attname.data,
  1418.  relation->rd_rel->relname.data);
  1419. attrdef[i].adbin = textout(val);
  1420. val = (struct varlena *) fastgetattr(&tuple,
  1421.  Anum_pg_attrdef_adsrc,
  1422.  adrel->rd_att, &isnull);
  1423. if (isnull)
  1424. elog(ERROR, "AttrDefaultFetch: adsrc IS NULL for attr %s in rel %s",
  1425. relation->rd_att->attrs[adform->adnum - 1]->attname.data,
  1426.  relation->rd_rel->relname.data);
  1427. attrdef[i].adsrc = textout(val);
  1428. break;
  1429. }
  1430. ReleaseBuffer(buffer);
  1431. if (i >= ndef)
  1432. elog(ERROR, "AttrDefaultFetch: unexpected record found for attr %d in rel %s",
  1433.  adform->adnum,
  1434.  relation->rd_rel->relname.data);
  1435. }
  1436. if (found < ndef)
  1437. elog(ERROR, "AttrDefaultFetch: %d record not found for rel %s",
  1438.  ndef - found, relation->rd_rel->relname.data);
  1439. index_endscan(sd);
  1440. pfree(sd);
  1441. index_close(irel);
  1442. heap_close(adrel);
  1443. }
  1444. static void
  1445. RelCheckFetch(Relation relation)
  1446. {
  1447. ConstrCheck *check = relation->rd_att->constr->check;
  1448. int ncheck = relation->rd_att->constr->num_check;
  1449. Relation rcrel;
  1450. Relation irel;
  1451. ScanKeyData skey;
  1452. HeapTupleData tuple;
  1453. IndexScanDesc sd;
  1454. RetrieveIndexResult indexRes;
  1455. Name rcname;
  1456. struct varlena *val;
  1457. bool isnull;
  1458. int found;
  1459. ScanKeyEntryInitialize(&skey,
  1460.    (bits16) 0x0,
  1461.    (AttrNumber) 1,
  1462.    (RegProcedure) F_OIDEQ,
  1463.    ObjectIdGetDatum(RelationGetRelid(relation)));
  1464. rcrel = heap_openr(RelCheckRelationName);
  1465. irel = index_openr(RelCheckIndex);
  1466. sd = index_beginscan(irel, false, 1, &skey);
  1467. tuple.t_data = NULL;
  1468. for (found = 0;;)
  1469. {
  1470. Buffer buffer;
  1471. indexRes = index_getnext(sd, ForwardScanDirection);
  1472. if (!indexRes)
  1473. break;
  1474. tuple.t_self = indexRes->heap_iptr;
  1475. heap_fetch(rcrel, SnapshotNow, &tuple, &buffer);
  1476. pfree(indexRes);
  1477. if (tuple.t_data == NULL)
  1478. continue;
  1479. if (found == ncheck)
  1480. elog(ERROR, "RelCheckFetch: unexpected record found for rel %s",
  1481.  relation->rd_rel->relname.data);
  1482. rcname = (Name) fastgetattr(&tuple,
  1483. Anum_pg_relcheck_rcname,
  1484. rcrel->rd_att, &isnull);
  1485. if (isnull)
  1486. elog(ERROR, "RelCheckFetch: rcname IS NULL for rel %s",
  1487.  relation->rd_rel->relname.data);
  1488. check[found].ccname = nameout(rcname);
  1489. val = (struct varlena *) fastgetattr(&tuple,
  1490.  Anum_pg_relcheck_rcbin,
  1491.  rcrel->rd_att, &isnull);
  1492. if (isnull)
  1493. elog(ERROR, "RelCheckFetch: rcbin IS NULL for rel %s",
  1494.  relation->rd_rel->relname.data);
  1495. check[found].ccbin = textout(val);
  1496. val = (struct varlena *) fastgetattr(&tuple,
  1497.  Anum_pg_relcheck_rcsrc,
  1498.  rcrel->rd_att, &isnull);
  1499. if (isnull)
  1500. elog(ERROR, "RelCheckFetch: rcsrc IS NULL for rel %s",
  1501.  relation->rd_rel->relname.data);
  1502. check[found].ccsrc = textout(val);
  1503. found++;
  1504. ReleaseBuffer(buffer);
  1505. }
  1506. if (found < ncheck)
  1507. elog(ERROR, "RelCheckFetch: %d record not found for rel %s",
  1508.  ncheck - found,
  1509.  relation->rd_rel->relname.data);
  1510. index_endscan(sd);
  1511. pfree(sd);
  1512. index_close(irel);
  1513. heap_close(rcrel);
  1514. }
  1515. /*
  1516.  * init_irels(), write_irels() -- handle special-case initialization of
  1517.  *    index relation descriptors.
  1518.  *
  1519.  * In late 1992, we started regularly having databases with more than
  1520.  * a thousand classes in them.  With this number of classes, it became
  1521.  * critical to do indexed lookups on the system catalogs.
  1522.  *
  1523.  * Bootstrapping these lookups is very hard.  We want to be able to
  1524.  * use an index on pg_attribute, for example, but in order to do so,
  1525.  * we must have read pg_attribute for the attributes in the index,
  1526.  * which implies that we need to use the index.
  1527.  *
  1528.  * In order to get around the problem, we do the following:
  1529.  *
  1530.  *    +  When the database system is initialized (at initdb time), we
  1531.  *   don't use indices on pg_attribute.  We do sequential scans.
  1532.  *
  1533.  *    +  When the backend is started up in normal mode, we load an image
  1534.  *   of the appropriate relation descriptors, in internal format,
  1535.  *   from an initialization file in the data/base/... directory.
  1536.  *
  1537.  *    +  If the initialization file isn't there, then we create the
  1538.  *   relation descriptors using sequential scans and write 'em to
  1539.  *   the initialization file for use by subsequent backends.
  1540.  *
  1541.  * We could dispense with the initialization file and just build the
  1542.  * critical reldescs the hard way on every backend startup, but that
  1543.  * slows down backend startup noticeably if pg_class is large.
  1544.  *
  1545.  * As of v6.5, vacuum.c deletes the initialization file at completion
  1546.  * of a VACUUM, so that it will be rebuilt at the next backend startup.
  1547.  * This ensures that vacuum-collected stats for the system indexes
  1548.  * will eventually get used by the optimizer --- otherwise the relcache
  1549.  * entries for these indexes will show zero sizes forever, since the
  1550.  * relcache entries are pinned in memory and will never be reloaded
  1551.  * from pg_class.
  1552.  */
  1553. /* pg_attnumind, pg_classnameind, pg_classoidind */
  1554. #define Num_indices_bootstrap 3
  1555. static void
  1556. init_irels(void)
  1557. {
  1558. Size len;
  1559. int nread;
  1560. File fd;
  1561. Relation irel[Num_indices_bootstrap];
  1562. Relation ird;
  1563. Form_pg_am am;
  1564. Form_pg_class relform;
  1565. IndexStrategy strat;
  1566. RegProcedure *support;
  1567. int i;
  1568. int relno;
  1569. #ifndef __CYGWIN32__
  1570. if ((fd = FileNameOpenFile(RELCACHE_INIT_FILENAME, O_RDONLY, 0600)) < 0)
  1571. #else
  1572. if ((fd = FileNameOpenFile(RELCACHE_INIT_FILENAME, O_RDONLY | O_BINARY, 0600)) < 0)
  1573. #endif
  1574. {
  1575. write_irels();
  1576. return;
  1577. }
  1578. FileSeek(fd, 0L, SEEK_SET);
  1579. for (relno = 0; relno < Num_indices_bootstrap; relno++)
  1580. {
  1581. /* first read the relation descriptor length */
  1582. if ((nread = FileRead(fd, (char *) &len, sizeof(len))) != sizeof(len))
  1583. {
  1584. write_irels();
  1585. return;
  1586. }
  1587. ird = irel[relno] = (Relation) palloc(len);
  1588. MemSet(ird, 0, len);
  1589. /* then, read the Relation structure */
  1590. if ((nread = FileRead(fd, (char *) ird, len)) != len)
  1591. {
  1592. write_irels();
  1593. return;
  1594. }
  1595. /* the file descriptor is not yet opened */
  1596. ird->rd_fd = -1;
  1597. /* lock info is not initialized */
  1598. ird->lockInfo = (char *) NULL;
  1599. /* next, read the access method tuple form */
  1600. if ((nread = FileRead(fd, (char *) &len, sizeof(len))) != sizeof(len))
  1601. {
  1602. write_irels();
  1603. return;
  1604. }
  1605. am = (Form_pg_am) palloc(len);
  1606. if ((nread = FileRead(fd, (char *) am, len)) != len)
  1607. {
  1608. write_irels();
  1609. return;
  1610. }
  1611. ird->rd_am = am;
  1612. /* next read the relation tuple form */
  1613. if ((nread = FileRead(fd, (char *) &len, sizeof(len))) != sizeof(len))
  1614. {
  1615. write_irels();
  1616. return;
  1617. }
  1618. relform = (Form_pg_class) palloc(len);
  1619. if ((nread = FileRead(fd, (char *) relform, len)) != len)
  1620. {
  1621. write_irels();
  1622. return;
  1623. }
  1624. ird->rd_rel = relform;
  1625. /* initialize attribute tuple forms */
  1626. ird->rd_att = CreateTemplateTupleDesc(relform->relnatts);
  1627. /* next read all the attribute tuple form data entries */
  1628. len = ATTRIBUTE_TUPLE_SIZE;
  1629. for (i = 0; i < relform->relnatts; i++)
  1630. {
  1631. if ((nread = FileRead(fd, (char *) &len, sizeof(len))) != sizeof(len))
  1632. {
  1633. write_irels();
  1634. return;
  1635. }
  1636. ird->rd_att->attrs[i] = (Form_pg_attribute) palloc(len);
  1637. if ((nread = FileRead(fd, (char *) ird->rd_att->attrs[i], len)) != len)
  1638. {
  1639. write_irels();
  1640. return;
  1641. }
  1642. }
  1643. /* next, read the index strategy map */
  1644. if ((nread = FileRead(fd, (char *) &len, sizeof(len))) != sizeof(len))
  1645. {
  1646. write_irels();
  1647. return;
  1648. }
  1649. strat = (IndexStrategy) palloc(len);
  1650. if ((nread = FileRead(fd, (char *) strat, len)) != len)
  1651. {
  1652. write_irels();
  1653. return;
  1654. }
  1655. /* oh, for god's sake... */
  1656. #define SMD(i) strat[0].strategyMapData[i].entry[0]
  1657. /* have to reinit the function pointers in the strategy maps */
  1658. for (i = 0; i < am->amstrategies * relform->relnatts; i++)
  1659. {
  1660. fmgr_info(SMD(i).sk_procedure,
  1661.   &(SMD(i).sk_func));
  1662. SMD(i).sk_nargs = SMD(i).sk_func.fn_nargs;
  1663. }
  1664. /*
  1665.  * use a real field called rd_istrat instead of the bogosity of
  1666.  * hanging invisible fields off the end of a structure - jolly
  1667.  */
  1668. ird->rd_istrat = strat;
  1669. /* finally, read the vector of support procedures */
  1670. if ((nread = FileRead(fd, (char *) &len, sizeof(len))) != sizeof(len))
  1671. {
  1672. write_irels();
  1673. return;
  1674. }
  1675. support = (RegProcedure *) palloc(len);
  1676. if ((nread = FileRead(fd, (char *) support, len)) != len)
  1677. {
  1678. write_irels();
  1679. return;
  1680. }
  1681. /*
  1682.  * p += sizeof(IndexStrategy); ((RegProcedure **) p) = support;
  1683.  */
  1684. ird->rd_support = support;
  1685. RelationCacheInsert(ird);
  1686. RelationInitLockInfo(ird);
  1687. }
  1688. }
  1689. static void
  1690. write_irels(void)
  1691. {
  1692. Size len;
  1693. int nwritten;
  1694. File fd;
  1695. Relation irel[Num_indices_bootstrap];
  1696. Relation ird;
  1697. Form_pg_am am;
  1698. Form_pg_class relform;
  1699. IndexStrategy strat;
  1700. RegProcedure *support;
  1701. ProcessingMode oldmode;
  1702. int i;
  1703. int relno;
  1704. RelationBuildDescInfo bi;
  1705. #ifndef __CYGWIN32__
  1706. fd = FileNameOpenFile(RELCACHE_INIT_FILENAME, O_WRONLY | O_CREAT | O_TRUNC, 0600);
  1707. #else
  1708. fd = FileNameOpenFile(RELCACHE_INIT_FILENAME, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600);
  1709. #endif
  1710. if (fd < 0)
  1711. elog(FATAL, "cannot create init file %s", RELCACHE_INIT_FILENAME);
  1712. FileSeek(fd, 0L, SEEK_SET);
  1713. /*
  1714.  * Build a relation descriptor for pg_attnumind without resort to the
  1715.  * descriptor cache.  In order to do this, we set ProcessingMode to
  1716.  * Bootstrap.  The effect of this is to disable indexed relation
  1717.  * searches -- a necessary step, since we're trying to instantiate the
  1718.  * index relation descriptors here.
  1719.  */
  1720. oldmode = GetProcessingMode();
  1721. SetProcessingMode(BootstrapProcessing);
  1722. bi.infotype = INFO_RELNAME;
  1723. bi.i.info_name = AttributeNumIndex;
  1724. irel[0] = RelationBuildDesc(bi);
  1725. irel[0]->rd_isnailed = true;
  1726. bi.i.info_name = ClassNameIndex;
  1727. irel[1] = RelationBuildDesc(bi);
  1728. irel[1]->rd_isnailed = true;
  1729. bi.i.info_name = ClassOidIndex;
  1730. irel[2] = RelationBuildDesc(bi);
  1731. irel[2]->rd_isnailed = true;
  1732. SetProcessingMode(oldmode);
  1733. /* nail the descriptor in the cache */
  1734. for (relno = 0; relno < Num_indices_bootstrap; relno++)
  1735. {
  1736. ird = irel[relno];
  1737. /* save the volatile fields in the relation descriptor */
  1738. am = ird->rd_am;
  1739. ird->rd_am = (Form_pg_am) NULL;
  1740. relform = ird->rd_rel;
  1741. ird->rd_rel = (Form_pg_class) NULL;
  1742. strat = ird->rd_istrat;
  1743. support = ird->rd_support;
  1744. /*
  1745.  * first write the relation descriptor , excluding strategy and
  1746.  * support
  1747.  */
  1748. len = sizeof(RelationData);
  1749. /* first, write the relation descriptor length */
  1750. if ((nwritten = FileWrite(fd, (char *) &len, sizeof(len)))
  1751. != sizeof(len))
  1752. elog(FATAL, "cannot write init file -- descriptor length");
  1753. /* next, write out the Relation structure */
  1754. if ((nwritten = FileWrite(fd, (char *) ird, len)) != len)
  1755. elog(FATAL, "cannot write init file -- reldesc");
  1756. /* next, write the access method tuple form */
  1757. len = sizeof(FormData_pg_am);
  1758. if ((nwritten = FileWrite(fd, (char *) &len, sizeof(len)))
  1759. != sizeof(len))
  1760. elog(FATAL, "cannot write init file -- am tuple form length");
  1761. if ((nwritten = FileWrite(fd, (char *) am, len)) != len)
  1762. elog(FATAL, "cannot write init file -- am tuple form");
  1763. /* next write the relation tuple form */
  1764. len = sizeof(FormData_pg_class);
  1765. if ((nwritten = FileWrite(fd, (char *) &len, sizeof(len)))
  1766. != sizeof(len))
  1767. elog(FATAL, "cannot write init file -- relation tuple form length");
  1768. if ((nwritten = FileWrite(fd, (char *) relform, len)) != len)
  1769. elog(FATAL, "cannot write init file -- relation tuple form");
  1770. /* next, do all the attribute tuple form data entries */
  1771. len = ATTRIBUTE_TUPLE_SIZE;
  1772. for (i = 0; i < relform->relnatts; i++)
  1773. {
  1774. if ((nwritten = FileWrite(fd, (char *) &len, sizeof(len)))
  1775. != sizeof(len))
  1776. elog(FATAL, "cannot write init file -- length of attdesc %d", i);
  1777. if ((nwritten = FileWrite(fd, (char *) ird->rd_att->attrs[i], len))
  1778. != len)
  1779. elog(FATAL, "cannot write init file -- attdesc %d", i);
  1780. }
  1781. /* next, write the index strategy map */
  1782. len = AttributeNumberGetIndexStrategySize(relform->relnatts,
  1783.   am->amstrategies);
  1784. if ((nwritten = FileWrite(fd, (char *) &len, sizeof(len)))
  1785. != sizeof(len))
  1786. elog(FATAL, "cannot write init file -- strategy map length");
  1787. if ((nwritten = FileWrite(fd, (char *) strat, len)) != len)
  1788. elog(FATAL, "cannot write init file -- strategy map");
  1789. /* finally, write the vector of support procedures */
  1790. len = relform->relnatts * (am->amsupport * sizeof(RegProcedure));
  1791. if ((nwritten = FileWrite(fd, (char *) &len, sizeof(len)))
  1792. != sizeof(len))
  1793. elog(FATAL, "cannot write init file -- support vector length");
  1794. if ((nwritten = FileWrite(fd, (char *) support, len)) != len)
  1795. elog(FATAL, "cannot write init file -- support vector");
  1796. /* restore volatile fields */
  1797. ird->rd_am = am;
  1798. ird->rd_rel = relform;
  1799. }
  1800. FileClose(fd);
  1801. }