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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * heap.c
  4.  *   code to create and destroy POSTGRES heap relations
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/catalog/heap.c,v 1.89 1999/07/08 02:46:37 momjian Exp $
  11.  *
  12.  *
  13.  * INTERFACE ROUTINES
  14.  * heap_create() - Create an uncataloged heap relation
  15.  * heap_create_with_catalog() - Create a cataloged relation
  16.  * heap_destroy_with_catalog() - Removes named relation from catalogs
  17.  *
  18.  * NOTES
  19.  *   this code taken from access/heap/create.c, which contains
  20.  *   the old heap_create_with_catalog, amcreate, and amdestroy.
  21.  *   those routines will soon call these routines using the function
  22.  *   manager,
  23.  *   just like the poorly named "NewXXX" routines do. The
  24.  *   "New" routines are all going to die soon, once and for all!
  25.  * -cim 1/13/91
  26.  *
  27.  *-------------------------------------------------------------------------
  28.  */
  29. #include "postgres.h"
  30. #include "miscadmin.h"
  31. #include "access/heapam.h"
  32. #include "catalog/catalog.h"
  33. #include "catalog/catname.h"
  34. #include "catalog/heap.h"
  35. #include "catalog/index.h"
  36. #include "catalog/indexing.h"
  37. #include "catalog/pg_attrdef.h"
  38. #include "catalog/pg_index.h"
  39. #include "catalog/pg_inherits.h"
  40. #include "catalog/pg_ipl.h"
  41. #include "catalog/pg_relcheck.h"
  42. #include "catalog/pg_type.h"
  43. #include "commands/trigger.h"
  44. #include "fmgr.h"
  45. #include "nodes/plannodes.h"
  46. #include "optimizer/tlist.h"
  47. #include "parser/parse_expr.h"
  48. #include "parser/parse_node.h"
  49. #include "parser/parse_target.h"
  50. #include "parser/parse_type.h"
  51. #include "parser/parse_coerce.h"
  52. #include "rewrite/rewriteRemove.h"
  53. #include "storage/bufmgr.h"
  54. #include "storage/lmgr.h"
  55. #include "storage/smgr.h"
  56. #include "tcop/tcopprot.h"
  57. #include "utils/catcache.h"
  58. #include "utils/builtins.h"
  59. #include "utils/mcxt.h"
  60. #include "utils/relcache.h"
  61. #include "utils/syscache.h"
  62. #include "utils/tqual.h"
  63. #include "utils/temprel.h"
  64. #ifndef HAVE_MEMMOVE
  65. #include <regex/utils.h>
  66. #else
  67. #include <string.h>
  68. #endif
  69. static void AddNewRelationTuple(Relation pg_class_desc,
  70.   Relation new_rel_desc, Oid new_rel_oid, unsigned natts,
  71. char relkind, char *temp_relname);
  72. static void AddToNoNameRelList(Relation r);
  73. static void DeleteAttributeTuples(Relation rel);
  74. static void DeleteRelationTuple(Relation rel);
  75. static void DeleteTypeTuple(Relation rel);
  76. static void RelationRemoveIndexes(Relation relation);
  77. static void RelationRemoveInheritance(Relation relation);
  78. static void RemoveFromNoNameRelList(Relation r);
  79. static void AddNewRelationType(char *typeName, Oid new_rel_oid);
  80. static void StoreConstraints(Relation rel);
  81. static void RemoveConstraints(Relation rel);
  82. /* ----------------------------------------------------------------
  83.  * XXX UGLY HARD CODED BADNESS FOLLOWS XXX
  84.  *
  85.  * these should all be moved to someplace in the lib/catalog
  86.  * module, if not obliterated first.
  87.  * ----------------------------------------------------------------
  88.  */
  89. /*
  90.  * Note:
  91.  * Should the executor special case these attributes in the future?
  92.  * Advantage: consume 1/2 the space in the ATTRIBUTE relation.
  93.  * Disadvantage:  having rules to compute values in these tuples may
  94.  * be more difficult if not impossible.
  95.  */
  96. static FormData_pg_attribute a1 = {
  97. 0xffffffff, {"ctid"}, TIDOID, 0, sizeof(ItemPointerData),
  98. SelfItemPointerAttributeNumber, 0, -1, -1, '', '', 'i', '', ''
  99. };
  100. static FormData_pg_attribute a2 = {
  101. 0xffffffff, {"oid"}, OIDOID, 0, sizeof(Oid),
  102. ObjectIdAttributeNumber, 0, -1, -1, '01', '', 'i', '', ''
  103. };
  104. static FormData_pg_attribute a3 = {
  105. 0xffffffff, {"xmin"}, XIDOID, 0, sizeof(TransactionId),
  106. MinTransactionIdAttributeNumber, 0, -1, -1, '01', '', 'i', '', ''
  107. };
  108. static FormData_pg_attribute a4 = {
  109. 0xffffffff, {"cmin"}, CIDOID, 0, sizeof(CommandId),
  110. MinCommandIdAttributeNumber, 0, -1, -1, '01', '', 'i', '', ''
  111. };
  112. static FormData_pg_attribute a5 = {
  113. 0xffffffff, {"xmax"}, XIDOID, 0, sizeof(TransactionId),
  114. MaxTransactionIdAttributeNumber, 0, -1, -1, '01', '', 'i', '', ''
  115. };
  116. static FormData_pg_attribute a6 = {
  117. 0xffffffff, {"cmax"}, CIDOID, 0, sizeof(CommandId),
  118. MaxCommandIdAttributeNumber, 0, -1, -1, '01', '', 'i', '', ''
  119. };
  120. static Form_pg_attribute HeapAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6};
  121. /* ----------------------------------------------------------------
  122.  * XXX END OF UGLY HARD CODED BADNESS XXX
  123.  * ----------------------------------------------------------------
  124.  */
  125. /* the tempRelList holds
  126.    the list of temporary uncatalogued relations that are created.
  127.    these relations should be destroyed at the end of transactions
  128. */
  129. typedef struct tempRelList
  130. {
  131. Relation   *rels; /* array of relation descriptors */
  132. int num; /* number of temporary relations */
  133. int size; /* size of space allocated for the rels
  134.  * array */
  135. } TempRelList;
  136. #define NONAME_REL_LIST_SIZE 32
  137. static TempRelList *tempRels = NULL;
  138. /* ----------------------------------------------------------------
  139.  * heap_create - Create an uncataloged heap relation
  140.  *
  141.  * Fields relpages, reltuples, reltuples, relkeys, relhistory,
  142.  * relisindexed, and relkind of rel->rd_rel are initialized
  143.  * to all zeros, as are rd_last and rd_hook.  Rd_refcnt is set to 1.
  144.  *
  145.  * Remove the system relation specific code to elsewhere eventually.
  146.  *
  147.  * Eventually, must place information about this temporary relation
  148.  * into the transaction context block.
  149.  *
  150.  *
  151.  * if heap_create is called with "" as the name, then heap_create will create
  152.  * a temporary name "pg_noname.$PID.$SEQUENCE" for the relation
  153.  * ----------------------------------------------------------------
  154.  */
  155. Relation
  156. heap_create(char *relname,
  157. TupleDesc tupDesc,
  158. bool isnoname,
  159. bool istemp)
  160. {
  161. unsigned i;
  162. Oid relid;
  163. Relation rel;
  164. int len;
  165. bool nailme = false;
  166. int natts = tupDesc->natts;
  167. static unsigned int uniqueId = 0;
  168. extern GlobalMemory CacheCxt;
  169. MemoryContext oldcxt;
  170. /* ----------------
  171.  * sanity checks
  172.  * ----------------
  173.  */
  174. AssertArg(natts > 0);
  175. if (relname && !allowSystemTableMods && IsSystemRelationName(relname) && IsNormalProcessingMode())
  176. {
  177. elog(ERROR, "Illegal class name '%s'"
  178.  "ntThe 'pg_' name prefix is reserved for system catalogs",
  179.  relname);
  180. }
  181. /* ----------------
  182.  * switch to the cache context so that we don't lose
  183.  * allocations at the end of this transaction, I guess.
  184.  * -cim 6/14/90
  185.  * ----------------
  186.  */
  187. if (!CacheCxt)
  188. CacheCxt = CreateGlobalMemory("Cache");
  189. oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
  190. /* ----------------
  191.  * real ugly stuff to assign the proper relid in the relation
  192.  * descriptor follows.
  193.  * ----------------
  194.  */
  195. if (relname && !strcmp(RelationRelationName, relname))
  196. {
  197. relid = RelOid_pg_class;
  198. nailme = true;
  199. }
  200. else if (relname && !strcmp(AttributeRelationName, relname))
  201. {
  202. relid = RelOid_pg_attribute;
  203. nailme = true;
  204. }
  205. else if (relname && !strcmp(ProcedureRelationName, relname))
  206. {
  207. relid = RelOid_pg_proc;
  208. nailme = true;
  209. }
  210. else if (relname && !strcmp(TypeRelationName, relname))
  211. {
  212. relid = RelOid_pg_type;
  213. nailme = true;
  214. }
  215. else
  216. relid = newoid();
  217. if (isnoname)
  218. {
  219. Assert(!relname);
  220. relname = palloc(NAMEDATALEN);
  221. snprintf(relname, NAMEDATALEN, "pg_noname.%d.%u",
  222.  (int) MyProcPid, uniqueId++);
  223. }
  224. if (istemp)
  225. {
  226. /* replace relname of caller */
  227. snprintf(relname, NAMEDATALEN, "pg_temp.%d.%u",
  228.  MyProcPid, uniqueId++);
  229. }
  230. /* ----------------
  231.  * allocate a new relation descriptor.
  232.  *
  233.  * XXX the length computation may be incorrect, handle elsewhere
  234.  * ----------------
  235.  */
  236. len = sizeof(RelationData);
  237. rel = (Relation) palloc(len);
  238. MemSet((char *) rel, 0, len);
  239. /*
  240.  * create a new tuple descriptor from the one passed in
  241.  */
  242. rel->rd_att = CreateTupleDescCopyConstr(tupDesc);
  243. /* ----------------
  244.  * nail the reldesc if this is a bootstrap create reln and
  245.  * we may need it in the cache later on in the bootstrap
  246.  * process so we don't ever want it kicked out.  e.g. pg_attribute!!!
  247.  * ----------------
  248.  */
  249. if (nailme)
  250. rel->rd_isnailed = true;
  251. RelationSetReferenceCount(rel, 1);
  252. rel->rd_rel = (Form_pg_class) palloc(sizeof *rel->rd_rel);
  253. /* ----------------
  254.  * initialize the fields of our new relation descriptor
  255.  * ----------------
  256.  */
  257. MemSet((char *) rel->rd_rel, 0, sizeof *rel->rd_rel);
  258. namestrcpy(&(rel->rd_rel->relname), relname);
  259. rel->rd_rel->relkind = RELKIND_UNCATALOGED;
  260. rel->rd_rel->relnatts = natts;
  261. if (tupDesc->constr)
  262. rel->rd_rel->relchecks = tupDesc->constr->num_check;
  263. for (i = 0; i < natts; i++)
  264. rel->rd_att->attrs[i]->attrelid = relid;
  265. RelationGetRelid(rel) = relid;
  266. if (nailme)
  267. {
  268. /* for system relations, set the reltype field here */
  269. rel->rd_rel->reltype = relid;
  270. }
  271. /* ----------------
  272.  * remember if this is a noname relation
  273.  * ----------------
  274.  */
  275. rel->rd_isnoname = isnoname;
  276. /* ----------------
  277.  * have the storage manager create the relation.
  278.  * ----------------
  279.  */
  280. rel->rd_nonameunlinked = TRUE; /* change once table is created */
  281. rel->rd_fd = (File) smgrcreate(DEFAULT_SMGR, rel);
  282. rel->rd_nonameunlinked = FALSE;
  283. RelationRegisterRelation(rel);
  284. MemoryContextSwitchTo(oldcxt);
  285. /*
  286.  * add all noname relations to the tempRels list so they can be
  287.  * properly disposed of at the end of transaction
  288.  */
  289. if (isnoname)
  290. AddToNoNameRelList(rel);
  291. return rel;
  292. }
  293. /* ----------------------------------------------------------------
  294.  * heap_create_with_catalog - Create a cataloged relation
  295.  *
  296.  * this is done in 6 steps:
  297.  *
  298.  * 1) CheckAttributeNames() is used to make certain the tuple
  299.  *    descriptor contains a valid set of attribute names
  300.  *
  301.  * 2) pg_class is opened and RelationFindRelid()
  302.  *    preforms a scan to ensure that no relation with the
  303.  *    same name already exists.
  304.  *
  305.  * 3) heap_create_with_catalog() is called to create the new relation
  306.  *    on disk.
  307.  *
  308.  * 4) TypeDefine() is called to define a new type corresponding
  309.  *    to the new relation.
  310.  *
  311.  * 5) AddNewAttributeTuples() is called to register the
  312.  *    new relation's schema in pg_attribute.
  313.  *
  314.  * 6) AddNewRelationTuple() is called to register the
  315.  *    relation itself in the catalogs.
  316.  *
  317.  * 7) StoreConstraints is called () - vadim 08/22/97
  318.  *
  319.  * 8) the relations are closed and the new relation's oid
  320.  *    is returned.
  321.  *
  322.  * old comments:
  323.  * A new relation is inserted into the RELATION relation
  324.  * with the specified attribute(s) (newly inserted into
  325.  * the ATTRIBUTE relation).  How does concurrency control
  326.  * work?  Is it automatic now?  Expects the caller to have
  327.  * attname, atttypid, atttyparg, attproc, and attlen domains filled.
  328.  * Create fills the attnum domains sequentually from zero,
  329.  * fills the attdisbursion domains with zeros, and fills the
  330.  * attrelid fields with the relid.
  331.  *
  332.  * scan relation catalog for name conflict
  333.  * scan type catalog for typids (if not arg)
  334.  * create and insert attribute(s) into attribute catalog
  335.  * create new relation
  336.  * insert new relation into attribute catalog
  337.  *
  338.  * Should coordinate with heap_create_with_catalog(). Either
  339.  * it should not be called or there should be a way to prevent
  340.  * the relation from being removed at the end of the
  341.  * transaction if it is successful ('u'/'r' may be enough).
  342.  * Also, if the transaction does not commit, then the
  343.  * relation should be removed.
  344.  *
  345.  * XXX amcreate ignores "off" when inserting (for now).
  346.  * XXX amcreate (like the other utilities) needs to understand indexes.
  347.  *
  348.  * ----------------------------------------------------------------
  349.  */
  350. /* --------------------------------
  351.  * CheckAttributeNames
  352.  *
  353.  * this is used to make certain the tuple descriptor contains a
  354.  * valid set of attribute names.  a problem simply generates
  355.  * elog(ERROR) which aborts the current transaction.
  356.  * --------------------------------
  357.  */
  358. static void
  359. CheckAttributeNames(TupleDesc tupdesc)
  360. {
  361. unsigned i;
  362. unsigned j;
  363. int natts = tupdesc->natts;
  364. /* ----------------
  365.  * first check for collision with system attribute names
  366.  * ----------------
  367.  *
  368.  *  also, warn user if attribute to be created has
  369.  *  an unknown typid  (usually as a result of a 'retrieve into'
  370.  *   - jolly
  371.  */
  372. for (i = 0; i < natts; i += 1)
  373. {
  374. for (j = 0; j < sizeof HeapAtt / sizeof HeapAtt[0]; j += 1)
  375. {
  376. if (nameeq(&(HeapAtt[j]->attname),
  377.    &(tupdesc->attrs[i]->attname)))
  378. {
  379. elog(ERROR, "Attribute '%s' has a name conflict"
  380.  "ntName matches an existing system attribute",
  381.  HeapAtt[j]->attname.data);
  382. }
  383. }
  384. if (tupdesc->attrs[i]->atttypid == UNKNOWNOID)
  385. {
  386. elog(NOTICE, "Attribute '%s' has an unknown type"
  387.  "ntRelation created; continue",
  388.  tupdesc->attrs[i]->attname.data);
  389. }
  390. }
  391. /* ----------------
  392.  * next check for repeated attribute names
  393.  * ----------------
  394.  */
  395. for (i = 1; i < natts; i += 1)
  396. {
  397. for (j = 0; j < i; j += 1)
  398. {
  399. if (nameeq(&(tupdesc->attrs[j]->attname),
  400.    &(tupdesc->attrs[i]->attname)))
  401. {
  402. elog(ERROR, "Attribute '%s' is repeated",
  403.  tupdesc->attrs[j]->attname.data);
  404. }
  405. }
  406. }
  407. }
  408. /* --------------------------------
  409.  * RelnameFindRelid
  410.  *
  411.  * this preforms a scan of pg_class to ensure that
  412.  * no relation with the same name already exists.
  413.  * --------------------------------
  414.  */
  415. Oid
  416. RelnameFindRelid(char *relname)
  417. {
  418. HeapTuple tuple;
  419. Oid relid;
  420. /*
  421.  * If this is not bootstrap (initdb) time, use the catalog index on
  422.  * pg_class.
  423.  */
  424. if (!IsBootstrapProcessingMode())
  425. {
  426. tuple = SearchSysCacheTuple(RELNAME,
  427. PointerGetDatum(relname),
  428. 0, 0, 0);
  429. if (HeapTupleIsValid(tuple))
  430. relid = tuple->t_data->t_oid;
  431. else
  432. relid = InvalidOid;
  433. }
  434. else
  435. {
  436. Relation pg_class_desc;
  437. ScanKeyData key;
  438. HeapScanDesc pg_class_scan;
  439. pg_class_desc = heap_openr(RelationRelationName);
  440. /* ----------------
  441.  * At bootstrap time, we have to do this the hard way.  Form the
  442.  * scan key.
  443.  * ----------------
  444.  */
  445. ScanKeyEntryInitialize(&key,
  446.    0,
  447.    (AttrNumber) Anum_pg_class_relname,
  448.    (RegProcedure) F_NAMEEQ,
  449.    (Datum) relname);
  450. /* ----------------
  451.  * begin the scan
  452.  * ----------------
  453.  */
  454. pg_class_scan = heap_beginscan(pg_class_desc,
  455.    0,
  456.    SnapshotNow,
  457.    1,
  458.    &key);
  459. /* ----------------
  460.  * get a tuple.  if the tuple is NULL then it means we
  461.  * didn't find an existing relation.
  462.  * ----------------
  463.  */
  464. tuple = heap_getnext(pg_class_scan, 0);
  465. if (HeapTupleIsValid(tuple))
  466. relid = tuple->t_data->t_oid;
  467. else
  468. relid = InvalidOid;
  469. heap_endscan(pg_class_scan);
  470. heap_close(pg_class_desc);
  471. }
  472. return relid;
  473. }
  474. /* --------------------------------
  475.  * AddNewAttributeTuples
  476.  *
  477.  * this registers the new relation's schema by adding
  478.  * tuples to pg_attribute.
  479.  * --------------------------------
  480.  */
  481. static void
  482. AddNewAttributeTuples(Oid new_rel_oid,
  483.   TupleDesc tupdesc)
  484. {
  485. Form_pg_attribute *dpp;
  486. unsigned i;
  487. HeapTuple tup;
  488. Relation rel;
  489. bool hasindex;
  490. Relation idescs[Num_pg_attr_indices];
  491. int natts = tupdesc->natts;
  492. /* ----------------
  493.  * open pg_attribute
  494.  * ----------------
  495.  */
  496. rel = heap_openr(AttributeRelationName);
  497. /* -----------------
  498.  * Check if we have any indices defined on pg_attribute.
  499.  * -----------------
  500.  */
  501. Assert(rel);
  502. Assert(rel->rd_rel);
  503. hasindex = RelationGetForm(rel)->relhasindex;
  504. if (hasindex)
  505. CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
  506. /* ----------------
  507.  * initialize tuple descriptor.  Note we use setheapoverride()
  508.  * so that we can see the effects of our TypeDefine() done
  509.  * previously.
  510.  * ----------------
  511.  */
  512. setheapoverride(true);
  513. fillatt(tupdesc);
  514. setheapoverride(false);
  515. /* ----------------
  516.  * first we add the user attributes..
  517.  * ----------------
  518.  */
  519. dpp = tupdesc->attrs;
  520. for (i = 0; i < natts; i++)
  521. {
  522. (*dpp)->attrelid = new_rel_oid;
  523. (*dpp)->attdisbursion = 0;
  524. tup = heap_addheader(Natts_pg_attribute,
  525.  ATTRIBUTE_TUPLE_SIZE,
  526.  (char *) *dpp);
  527. heap_insert(rel, tup);
  528. if (hasindex)
  529. CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
  530. pfree(tup);
  531. dpp++;
  532. }
  533. /* ----------------
  534.  * next we add the system attributes..
  535.  * ----------------
  536.  */
  537. dpp = HeapAtt;
  538. for (i = 0; i < -1 - FirstLowInvalidHeapAttributeNumber; i++)
  539. {
  540. (*dpp)->attrelid = new_rel_oid;
  541. /* (*dpp)->attdisbursion = 0;    unneeded */
  542. tup = heap_addheader(Natts_pg_attribute,
  543.  ATTRIBUTE_TUPLE_SIZE,
  544.  (char *) *dpp);
  545. heap_insert(rel, tup);
  546. if (hasindex)
  547. CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
  548. pfree(tup);
  549. dpp++;
  550. }
  551. heap_close(rel);
  552. /*
  553.  * close pg_attribute indices
  554.  */
  555. if (hasindex)
  556. CatalogCloseIndices(Num_pg_attr_indices, idescs);
  557. }
  558. /* --------------------------------
  559.  * AddNewRelationTuple
  560.  *
  561.  * this registers the new relation in the catalogs by
  562.  * adding a tuple to pg_class.
  563.  * --------------------------------
  564.  */
  565. static void
  566. AddNewRelationTuple(Relation pg_class_desc,
  567. Relation new_rel_desc,
  568. Oid new_rel_oid,
  569. unsigned natts,
  570. char relkind,
  571. char *temp_relname)
  572. {
  573. Form_pg_class new_rel_reltup;
  574. HeapTuple tup;
  575. Relation idescs[Num_pg_class_indices];
  576. bool isBootstrap;
  577. /* ----------------
  578.  * first we munge some of the information in our
  579.  * uncataloged relation's relation descriptor.
  580.  * ----------------
  581.  */
  582. new_rel_reltup = new_rel_desc->rd_rel;
  583. /* CHECK should get new_rel_oid first via an insert then use XXX */
  584. /* ----------------
  585.  * Here we insert bogus estimates of the size of the new relation.
  586.  * In reality, of course, the new relation has 0 tuples and pages,
  587.  * and if we were tracking these statistics accurately then we'd
  588.  * set the fields that way.  But at present the stats will be updated
  589.  * only by VACUUM or CREATE INDEX, and the user might insert a lot of
  590.  * tuples before he gets around to doing either of those.  So, instead
  591.  * of saying the relation is empty, we insert guesstimates.  The point
  592.  * is to keep the optimizer from making really stupid choices on
  593.  * never-yet-vacuumed tables; so the estimates need only be large
  594.  * enough to discourage the optimizer from using nested-loop plans.
  595.  * With this hack, nested-loop plans will be preferred only after
  596.  * the table has been proven to be small by VACUUM or CREATE INDEX.
  597.  * Maintaining the stats on-the-fly would solve the problem more cleanly,
  598.  * but the overhead of that would likely cost more than it'd save.
  599.  * (NOTE: CREATE INDEX inserts the same bogus estimates if it finds the
  600.  * relation has 0 rows and pages. See index.c.)
  601.  * ----------------
  602.  */
  603. new_rel_reltup->relpages = 10; /* bogus estimates */
  604. new_rel_reltup->reltuples = 1000;
  605. new_rel_reltup->relowner = GetUserId();
  606. new_rel_reltup->relkind = relkind;
  607. new_rel_reltup->relnatts = natts;
  608. /* ----------------
  609.  * now form a tuple to add to pg_class
  610.  * XXX Natts_pg_class_fixed is a hack - see pg_class.h
  611.  * ----------------
  612.  */
  613. tup = heap_addheader(Natts_pg_class_fixed,
  614.  CLASS_TUPLE_SIZE,
  615.  (char *) new_rel_reltup);
  616. tup->t_data->t_oid = new_rel_oid;
  617. /* ----------------
  618.  * finally insert the new tuple and free it.
  619.  *
  620.  * Note: I have no idea why we do a
  621.  * SetProcessingMode(BootstrapProcessing);
  622.  *   here -cim 6/14/90
  623.  * ----------------
  624.  */
  625. isBootstrap = IsBootstrapProcessingMode() ? true : false;
  626. SetProcessingMode(BootstrapProcessing);
  627. heap_insert(pg_class_desc, tup);
  628. if (temp_relname)
  629. create_temp_relation(temp_relname, tup);
  630. if (!isBootstrap)
  631. {
  632. /*
  633.  * First, open the catalog indices and insert index tuples for the
  634.  * new relation.
  635.  */
  636. CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
  637. CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class_desc, tup);
  638. CatalogCloseIndices(Num_pg_class_indices, idescs);
  639. /* now restore processing mode */
  640. SetProcessingMode(NormalProcessing);
  641. }
  642. pfree(tup);
  643. }
  644. /* --------------------------------
  645.  * AddNewRelationType -
  646.  *
  647.  * define a complex type corresponding to the new relation
  648.  * --------------------------------
  649.  */
  650. static void
  651. AddNewRelationType(char *typeName, Oid new_rel_oid)
  652. {
  653. Oid new_type_oid;
  654. /*
  655.  * The sizes are set to oid size because it makes implementing sets
  656.  * MUCH easier, and no one (we hope) uses these fields to figure out
  657.  * how much space to allocate for the type. An oid is the type used
  658.  * for a set definition.  When a user requests a set, what they
  659.  * actually get is the oid of a tuple in the pg_proc catalog, so the
  660.  * size of the "set" is the size of an oid. Similarly, byval being
  661.  * true makes sets much easier, and it isn't used by anything else.
  662.  * Note the assumption that OIDs are the same size as int4s.
  663.  */
  664. new_type_oid = TypeCreate(typeName, /* type name */
  665.   new_rel_oid, /* relation oid */
  666.   typeLen(typeidType(OIDOID)), /* internal size */
  667.   typeLen(typeidType(OIDOID)), /* external size */
  668.   'c', /* type-type (catalog) */
  669.   ',', /* default array delimiter */
  670.   "int4in", /* input procedure */
  671.   "int4out", /* output procedure */
  672.   "int4in", /* receive procedure */
  673.   "int4out", /* send procedure */
  674.   NULL, /* array element type - irrelevent */
  675.   "-", /* default type value */
  676.   (bool) 1, /* passed by value */
  677.   'i'); /* default alignment */
  678. }
  679. /* --------------------------------
  680.  * heap_create_with_catalog
  681.  *
  682.  * creates a new cataloged relation.  see comments above.
  683.  * --------------------------------
  684.  */
  685. Oid
  686. heap_create_with_catalog(char *relname,
  687.  TupleDesc tupdesc,
  688.  char relkind,
  689.  bool istemp)
  690. {
  691. Relation pg_class_desc;
  692. Relation new_rel_desc;
  693. Oid new_rel_oid;
  694. int natts = tupdesc->natts;
  695. char    *temp_relname = NULL;
  696. /* ----------------
  697.  * sanity checks
  698.  * ----------------
  699.  */
  700. Assert(IsNormalProcessingMode() || IsBootstrapProcessingMode());
  701. if (natts == 0 || natts > MaxHeapAttributeNumber)
  702. elog(ERROR, "Number of attributes is out of range"
  703.  "ntFrom 1 to %d attributes may be specified",
  704.  MaxHeapAttributeNumber);
  705. CheckAttributeNames(tupdesc);
  706. /* temp tables can mask non-temp tables */
  707. if ((!istemp && RelnameFindRelid(relname)) ||
  708. (istemp && get_temp_rel_by_name(relname) != NULL))
  709. elog(ERROR, "Relation '%s' already exists", relname);
  710. /* invalidate cache so non-temp table is masked by temp */
  711. if (istemp)
  712. {
  713. Oid relid = RelnameFindRelid(relname);
  714. if (relid != InvalidOid)
  715. RelationForgetRelation(relid);
  716. }
  717. /* save user relation name because heap_create changes it */
  718. if (istemp)
  719. {
  720. temp_relname = pstrdup(relname); /* save original value */
  721. relname = palloc(NAMEDATALEN);
  722. strcpy(relname, temp_relname); /* heap_create will change this */
  723. }
  724. /* ----------------
  725.  * ok, relation does not already exist so now we
  726.  * create an uncataloged relation and pull its relation oid
  727.  * from the newly formed relation descriptor.
  728.  *
  729.  * Note: The call to heap_create() does all the "real" work
  730.  * of creating the disk file for the relation.
  731.  * This changes relname for noname and temp tables.
  732.  * ----------------
  733.  */
  734. new_rel_desc = heap_create(relname, tupdesc, false, istemp);
  735. new_rel_oid = new_rel_desc->rd_att->attrs[0]->attrelid;
  736. /* ----------------
  737.  * since defining a relation also defines a complex type,
  738.  * we add a new system type corresponding to the new relation.
  739.  * ----------------
  740.  */
  741. AddNewRelationType(relname, new_rel_oid);
  742. /* ----------------
  743.  * now add tuples to pg_attribute for the attributes in
  744.  * our new relation.
  745.  * ----------------
  746.  */
  747. AddNewAttributeTuples(new_rel_oid, tupdesc);
  748. /* ----------------
  749.  * now update the information in pg_class.
  750.  * ----------------
  751.  */
  752. pg_class_desc = heap_openr(RelationRelationName);
  753. AddNewRelationTuple(pg_class_desc,
  754. new_rel_desc,
  755. new_rel_oid,
  756. natts,
  757. relkind,
  758. temp_relname);
  759. StoreConstraints(new_rel_desc);
  760. if (istemp)
  761. {
  762. pfree(relname);
  763. pfree(temp_relname);
  764. }
  765. /* ----------------
  766.  * ok, the relation has been cataloged, so close our relations
  767.  * and return the oid of the newly created relation.
  768.  *
  769.  * SOMEDAY: fill the STATISTIC relation properly.
  770.  * ----------------
  771.  */
  772. heap_close(new_rel_desc);
  773. heap_close(pg_class_desc);
  774. return new_rel_oid;
  775. }
  776. /* ----------------------------------------------------------------
  777.  * heap_destroy_with_catalog - removes all record of named relation from catalogs
  778.  *
  779.  * 1) open relation, check for existence, etc.
  780.  * 2) remove inheritance information
  781.  * 3) remove indexes
  782.  * 4) remove pg_class tuple
  783.  * 5) remove pg_attribute tuples
  784.  * 6) remove pg_type tuples
  785.  * 7) RemoveConstraints ()
  786.  * 8) unlink relation
  787.  *
  788.  * old comments
  789.  * Except for vital relations, removes relation from
  790.  * relation catalog, and related attributes from
  791.  * attribute catalog (needed?).  (Anything else?)
  792.  *
  793.  * get proper relation from relation catalog (if not arg)
  794.  * check if relation is vital (strcmp()/reltype?)
  795.  * scan attribute catalog deleting attributes of reldesc
  796.  * (necessary?)
  797.  * delete relation from relation catalog
  798.  * (How are the tuples of the relation discarded?)
  799.  *
  800.  * XXX Must fix to work with indexes.
  801.  * There may be a better order for doing things.
  802.  * Problems with destroying a deleted database--cannot create
  803.  * a struct reldesc without having an open file descriptor.
  804.  * ----------------------------------------------------------------
  805.  */
  806. /* --------------------------------
  807.  * RelationRemoveInheritance
  808.  *
  809.  * Note: for now, we cause an exception if relation is a
  810.  * superclass.  Someday, we may want to allow this and merge
  811.  * the type info into subclass procedures.... this seems like
  812.  * lots of work.
  813.  * --------------------------------
  814.  */
  815. static void
  816. RelationRemoveInheritance(Relation relation)
  817. {
  818. Relation catalogRelation;
  819. HeapTuple tuple;
  820. HeapScanDesc scan;
  821. ScanKeyData entry;
  822. bool found = false;
  823. /* ----------------
  824.  * open pg_inherits
  825.  * ----------------
  826.  */
  827. catalogRelation = heap_openr(InheritsRelationName);
  828. /* ----------------
  829.  * form a scan key for the subclasses of this class
  830.  * and begin scanning
  831.  * ----------------
  832.  */
  833. ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_inherits_inhparent,
  834.    F_OIDEQ,
  835.    ObjectIdGetDatum(RelationGetRelid(relation)));
  836. scan = heap_beginscan(catalogRelation,
  837.   false,
  838.   SnapshotNow,
  839.   1,
  840.   &entry);
  841. /* ----------------
  842.  * if any subclasses exist, then we disallow the deletion.
  843.  * ----------------
  844.  */
  845. tuple = heap_getnext(scan, 0);
  846. if (HeapTupleIsValid(tuple))
  847. {
  848. heap_endscan(scan);
  849. heap_close(catalogRelation);
  850. elog(ERROR, "Relation '%u' inherits '%s'",
  851.  ((Form_pg_inherits) GETSTRUCT(tuple))->inhrel,
  852.  RelationGetRelationName(relation));
  853. }
  854. /* ----------------
  855.  * If we get here, it means the relation has no subclasses
  856.  * so we can trash it.  First we remove dead INHERITS tuples.
  857.  * ----------------
  858.  */
  859. entry.sk_attno = Anum_pg_inherits_inhrel;
  860. scan = heap_beginscan(catalogRelation,
  861.   false,
  862.   SnapshotNow,
  863.   1,
  864.   &entry);
  865. while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
  866. {
  867. heap_delete(catalogRelation, &tuple->t_self, NULL);
  868. found = true;
  869. }
  870. heap_endscan(scan);
  871. heap_close(catalogRelation);
  872. /* ----------------
  873.  * now remove dead IPL tuples
  874.  * ----------------
  875.  */
  876. catalogRelation = heap_openr(InheritancePrecidenceListRelationName);
  877. entry.sk_attno = Anum_pg_ipl_iplrel;
  878. scan = heap_beginscan(catalogRelation,
  879.   false,
  880.   SnapshotNow,
  881.   1,
  882.   &entry);
  883. while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
  884. heap_delete(catalogRelation, &tuple->t_self, NULL);
  885. heap_endscan(scan);
  886. heap_close(catalogRelation);
  887. }
  888. /* --------------------------------
  889.  * RelationRemoveIndexes
  890.  *
  891.  * --------------------------------
  892.  */
  893. static void
  894. RelationRemoveIndexes(Relation relation)
  895. {
  896. Relation indexRelation;
  897. HeapTuple tuple;
  898. HeapScanDesc scan;
  899. ScanKeyData entry;
  900. indexRelation = heap_openr(IndexRelationName);
  901. ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_index_indrelid,
  902.    F_OIDEQ,
  903.    ObjectIdGetDatum(RelationGetRelid(relation)));
  904. scan = heap_beginscan(indexRelation,
  905.   false,
  906.   SnapshotNow,
  907.   1,
  908.   &entry);
  909. while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
  910. index_destroy(((Form_pg_index) GETSTRUCT(tuple))->indexrelid);
  911. heap_endscan(scan);
  912. heap_close(indexRelation);
  913. }
  914. /* --------------------------------
  915.  * DeleteRelationTuple
  916.  *
  917.  * --------------------------------
  918.  */
  919. static void
  920. DeleteRelationTuple(Relation rel)
  921. {
  922. Relation pg_class_desc;
  923. HeapTuple tup;
  924. /* ----------------
  925.  * open pg_class
  926.  * ----------------
  927.  */
  928. pg_class_desc = heap_openr(RelationRelationName);
  929. tup = SearchSysCacheTupleCopy(RELOID,
  930.    ObjectIdGetDatum(rel->rd_att->attrs[0]->attrelid),
  931.   0, 0, 0);
  932. if (!HeapTupleIsValid(tup))
  933. {
  934. heap_close(pg_class_desc);
  935. elog(ERROR, "Relation '%s' does not exist",
  936.  &rel->rd_rel->relname);
  937. }
  938. /* ----------------
  939.  * delete the relation tuple from pg_class, and finish up.
  940.  * ----------------
  941.  */
  942. heap_delete(pg_class_desc, &tup->t_self, NULL);
  943. pfree(tup);
  944. heap_close(pg_class_desc);
  945. }
  946. /* --------------------------------
  947.  * DeleteAttributeTuples
  948.  *
  949.  * --------------------------------
  950.  */
  951. static void
  952. DeleteAttributeTuples(Relation rel)
  953. {
  954. Relation pg_attribute_desc;
  955. HeapTuple tup;
  956. int2 attnum;
  957. /* ----------------
  958.  * open pg_attribute
  959.  * ----------------
  960.  */
  961. pg_attribute_desc = heap_openr(AttributeRelationName);
  962. /* -----------------
  963.  * Get a write lock _before_ getting the read lock in the scan
  964.  * ----------------
  965.  */
  966. LockRelation(pg_attribute_desc, AccessExclusiveLock);
  967. for (attnum = FirstLowInvalidHeapAttributeNumber + 1;
  968.  attnum <= rel->rd_att->natts;
  969.  attnum++)
  970. {
  971. if (HeapTupleIsValid(tup = SearchSysCacheTupleCopy(ATTNUM,
  972.  ObjectIdGetDatum(RelationGetRelid(rel)),
  973.    Int16GetDatum(attnum),
  974.    0, 0)))
  975. {
  976. heap_delete(pg_attribute_desc, &tup->t_self, NULL);
  977. pfree(tup);
  978. }
  979. }
  980. /* ----------------
  981.  * Release the write lock
  982.  * ----------------
  983.  */
  984. UnlockRelation(pg_attribute_desc, AccessExclusiveLock);
  985. heap_close(pg_attribute_desc);
  986. }
  987. /* --------------------------------
  988.  * DeleteTypeTuple
  989.  *
  990.  * If the user attempts to destroy a relation and there
  991.  * exists attributes in other relations of type
  992.  * "relation we are deleting", then we have to do something
  993.  * special.  presently we disallow the destroy.
  994.  * --------------------------------
  995.  */
  996. static void
  997. DeleteTypeTuple(Relation rel)
  998. {
  999. Relation pg_type_desc;
  1000. HeapScanDesc pg_type_scan;
  1001. Relation pg_attribute_desc;
  1002. HeapScanDesc pg_attribute_scan;
  1003. ScanKeyData key;
  1004. ScanKeyData attkey;
  1005. HeapTuple tup;
  1006. HeapTuple atttup;
  1007. Oid typoid;
  1008. /* ----------------
  1009.  * open pg_type
  1010.  * ----------------
  1011.  */
  1012. pg_type_desc = heap_openr(TypeRelationName);
  1013. /* ----------------
  1014.  * create a scan key to locate the type tuple corresponding
  1015.  * to this relation.
  1016.  * ----------------
  1017.  */
  1018. ScanKeyEntryInitialize(&key, 0,
  1019.    Anum_pg_type_typrelid,
  1020.    F_OIDEQ,
  1021.    ObjectIdGetDatum(RelationGetRelid(rel)));
  1022. pg_type_scan = heap_beginscan(pg_type_desc,
  1023.   0,
  1024.   SnapshotNow,
  1025.   1,
  1026.   &key);
  1027. /* ----------------
  1028.  * use heap_getnext() to fetch the pg_type tuple. If this
  1029.  * tuple is not valid then something's wrong.
  1030.  * ----------------
  1031.  */
  1032. tup = heap_getnext(pg_type_scan, 0);
  1033. if (!HeapTupleIsValid(tup))
  1034. {
  1035. heap_endscan(pg_type_scan);
  1036. heap_close(pg_type_desc);
  1037. elog(ERROR, "DeleteTypeTuple: %s type nonexistent",
  1038.  &rel->rd_rel->relname);
  1039. }
  1040. /* ----------------
  1041.  * now scan pg_attribute. if any other relations have
  1042.  * attributes of the type of the relation we are deleteing
  1043.  * then we have to disallow the deletion. should talk to
  1044.  * stonebraker about this.  -cim 6/19/90
  1045.  * ----------------
  1046.  */
  1047. typoid = tup->t_data->t_oid;
  1048. pg_attribute_desc = heap_openr(AttributeRelationName);
  1049. ScanKeyEntryInitialize(&attkey,
  1050.    0,
  1051.    Anum_pg_attribute_atttypid,
  1052.    F_OIDEQ,
  1053.    typoid);
  1054. pg_attribute_scan = heap_beginscan(pg_attribute_desc,
  1055.    0,
  1056.    SnapshotNow,
  1057.    1,
  1058.    &attkey);
  1059. /* ----------------
  1060.  * try and get a pg_attribute tuple.  if we succeed it means
  1061.  * we can't delete the relation because something depends on
  1062.  * the schema.
  1063.  * ----------------
  1064.  */
  1065. atttup = heap_getnext(pg_attribute_scan, 0);
  1066. if (HeapTupleIsValid(atttup))
  1067. {
  1068. Oid relid = ((Form_pg_attribute) GETSTRUCT(atttup))->attrelid;
  1069. heap_endscan(pg_type_scan);
  1070. heap_close(pg_type_desc);
  1071. heap_endscan(pg_attribute_scan);
  1072. heap_close(pg_attribute_desc);
  1073. elog(ERROR, "DeleteTypeTuple: att of type %s exists in relation %u",
  1074.  &rel->rd_rel->relname, relid);
  1075. }
  1076. heap_endscan(pg_attribute_scan);
  1077. heap_close(pg_attribute_desc);
  1078. /* ----------------
  1079.  * Ok, it's safe so we delete the relation tuple
  1080.  * from pg_type and finish up.  But first end the scan so that
  1081.  * we release the read lock on pg_type.  -mer 13 Aug 1991
  1082.  * ----------------
  1083.  */
  1084. heap_delete(pg_type_desc, &tup->t_self, NULL);
  1085. heap_endscan(pg_type_scan);
  1086. heap_close(pg_type_desc);
  1087. }
  1088. /* --------------------------------
  1089.  * heap_destroy_with_catalog
  1090.  *
  1091.  * --------------------------------
  1092.  */
  1093. void
  1094. heap_destroy_with_catalog(char *relname)
  1095. {
  1096. Relation rel;
  1097. Oid rid;
  1098. bool istemp = (get_temp_rel_by_name(relname) != NULL);
  1099. /* ----------------
  1100.  * first open the relation.  if the relation does exist,
  1101.  * heap_openr() returns NULL.
  1102.  * ----------------
  1103.  */
  1104. rel = heap_openr(relname);
  1105. if (rel == NULL)
  1106. elog(ERROR, "Relation '%s' does not exist", relname);
  1107. LockRelation(rel, AccessExclusiveLock);
  1108. rid = rel->rd_id;
  1109. /* ----------------
  1110.  * prevent deletion of system relations
  1111.  * ----------------
  1112.  */
  1113. /* allow temp of pg_class? Guess so. */
  1114. if (!istemp &&
  1115. !allowSystemTableMods && IsSystemRelationName(RelationGetRelationName(rel)->data))
  1116. elog(ERROR, "System relation '%s' cannot be destroyed",
  1117.  &rel->rd_rel->relname);
  1118. /* ----------------
  1119.  * remove inheritance information
  1120.  * ----------------
  1121.  */
  1122. RelationRemoveInheritance(rel);
  1123. /* ----------------
  1124.  * remove indexes if necessary
  1125.  * ----------------
  1126.  */
  1127. if (rel->rd_rel->relhasindex)
  1128. RelationRemoveIndexes(rel);
  1129. /* ----------------
  1130.  * remove rules if necessary
  1131.  * ----------------
  1132.  */
  1133. if (rel->rd_rules != NULL)
  1134. RelationRemoveRules(rid);
  1135. /* triggers */
  1136. if (rel->rd_rel->reltriggers > 0)
  1137. RelationRemoveTriggers(rel);
  1138. /* ----------------
  1139.  * delete attribute tuples
  1140.  * ----------------
  1141.  */
  1142. DeleteAttributeTuples(rel);
  1143. if (istemp)
  1144. remove_temp_relation(rid);
  1145. /* ----------------
  1146.  * delete type tuple. here we want to see the effects
  1147.  * of the deletions we just did, so we use setheapoverride().
  1148.  * ----------------
  1149.  */
  1150. setheapoverride(true);
  1151. DeleteTypeTuple(rel);
  1152. setheapoverride(false);
  1153. /* ----------------
  1154.  * delete relation tuple
  1155.  * ----------------
  1156.  */
  1157. /* must delete fake tuple in cache */
  1158. DeleteRelationTuple(rel);
  1159. /*
  1160.  * release dirty buffers of this relation
  1161.  */
  1162. ReleaseRelationBuffers(rel);
  1163. /* ----------------
  1164.  * flush the relation from the relcache
  1165.  * ----------------
  1166.  * Does nothing!!! Flushing moved below. - vadim 06/04/97
  1167. RelationIdInvalidateRelationCacheByRelationId(rel->rd_id);
  1168.  */
  1169. RemoveConstraints(rel);
  1170. /* ----------------
  1171.  * unlink the relation and finish up.
  1172.  * ----------------
  1173.  */
  1174. if (!(rel->rd_isnoname) || !(rel->rd_nonameunlinked))
  1175. smgrunlink(DEFAULT_SMGR, rel);
  1176. rel->rd_nonameunlinked = TRUE;
  1177. UnlockRelation(rel, AccessExclusiveLock);
  1178. heap_close(rel);
  1179. RelationForgetRelation(rid);
  1180. }
  1181. /*
  1182.  * heap_destroy
  1183.  *   destroy and close temporary relations
  1184.  *
  1185.  */
  1186. void
  1187. heap_destroy(Relation rel)
  1188. {
  1189. ReleaseRelationBuffers(rel);
  1190. if (!(rel->rd_isnoname) || !(rel->rd_nonameunlinked))
  1191. smgrunlink(DEFAULT_SMGR, rel);
  1192. rel->rd_nonameunlinked = TRUE;
  1193. heap_close(rel);
  1194. RemoveFromNoNameRelList(rel);
  1195. }
  1196. /**************************************************************
  1197.   functions to deal with the list of temporary relations
  1198. **************************************************************/
  1199. /* --------------
  1200.    InitTempRellist():
  1201.    initialize temporary relations list
  1202.    the tempRelList is a list of temporary relations that
  1203.    are created in the course of the transactions
  1204.    they need to be destroyed properly at the end of the transactions
  1205.    MODIFIES the global variable tempRels
  1206.  >> NOTE <<
  1207.    malloc is used instead of palloc because we KNOW when we are
  1208.    going to free these things. Keeps us away from the memory context
  1209.    hairyness
  1210. */
  1211. void
  1212. InitNoNameRelList(void)
  1213. {
  1214. if (tempRels)
  1215. {
  1216. free(tempRels->rels);
  1217. free(tempRels);
  1218. }
  1219. tempRels = (TempRelList *) malloc(sizeof(TempRelList));
  1220. tempRels->size = NONAME_REL_LIST_SIZE;
  1221. tempRels->rels = (Relation *) malloc(sizeof(Relation) * tempRels->size);
  1222. MemSet(tempRels->rels, 0, sizeof(Relation) * tempRels->size);
  1223. tempRels->num = 0;
  1224. }
  1225. /*
  1226.    removes a relation from the TempRelList
  1227.    MODIFIES the global variable tempRels
  1228.   we don't really remove it, just mark it as NULL
  1229.   and DestroyNoNameRels will look for NULLs
  1230. */
  1231. static void
  1232. RemoveFromNoNameRelList(Relation r)
  1233. {
  1234. int i;
  1235. if (!tempRels)
  1236. return;
  1237. for (i = 0; i < tempRels->num; i++)
  1238. {
  1239. if (tempRels->rels[i] == r)
  1240. {
  1241. tempRels->rels[i] = NULL;
  1242. break;
  1243. }
  1244. }
  1245. }
  1246. /*
  1247.    add a temporary relation to the TempRelList
  1248.    MODIFIES the global variable tempRels
  1249. */
  1250. static void
  1251. AddToNoNameRelList(Relation r)
  1252. {
  1253. if (!tempRels)
  1254. return;
  1255. if (tempRels->num == tempRels->size)
  1256. {
  1257. tempRels->size += NONAME_REL_LIST_SIZE;
  1258. tempRels->rels = realloc(tempRels->rels,
  1259.  sizeof(Relation) * tempRels->size);
  1260. }
  1261. tempRels->rels[tempRels->num] = r;
  1262. tempRels->num++;
  1263. }
  1264. /*
  1265.    go through the tempRels list and destroy each of the relations
  1266. */
  1267. void
  1268. DestroyNoNameRels(void)
  1269. {
  1270. int i;
  1271. Relation rel;
  1272. if (!tempRels)
  1273. return;
  1274. for (i = 0; i < tempRels->num; i++)
  1275. {
  1276. rel = tempRels->rels[i];
  1277. /* rel may be NULL if it has been removed from the list already */
  1278. if (rel)
  1279. heap_destroy(rel);
  1280. }
  1281. free(tempRels->rels);
  1282. free(tempRels);
  1283. tempRels = NULL;
  1284. }
  1285. static void
  1286. StoreAttrDefault(Relation rel, AttrDefault *attrdef)
  1287. {
  1288. char str[MAX_PARSE_BUFFER];
  1289. char cast[2 * NAMEDATALEN] = {0};
  1290. Form_pg_attribute atp = rel->rd_att->attrs[attrdef->adnum - 1];
  1291. List    *queryTree_list;
  1292. List    *planTree_list;
  1293. Query    *query;
  1294. TargetEntry *te;
  1295. Resdom    *resdom;
  1296. Node    *expr;
  1297. Oid type;
  1298. char    *adbin;
  1299. MemoryContext oldcxt;
  1300. Relation adrel;
  1301. Relation idescs[Num_pg_attrdef_indices];
  1302. HeapTuple tuple;
  1303. Datum values[4];
  1304. char nulls[4] = {' ', ' ', ' ', ' '};
  1305. extern GlobalMemory CacheCxt;
  1306. start:
  1307. /*
  1308.  * Surround table name with double quotes to allow mixed-case and
  1309.  * whitespaces in names. - BGA 1998-11-14
  1310.  */
  1311. snprintf(str, MAX_PARSE_BUFFER,
  1312.  "select %s%s from "%.*s"", attrdef->adsrc, cast,
  1313.  NAMEDATALEN, rel->rd_rel->relname.data);
  1314. setheapoverride(true);
  1315. planTree_list = pg_parse_and_plan(str, NULL, 0,
  1316.   &queryTree_list, None, FALSE);
  1317. setheapoverride(false);
  1318. query = (Query *) lfirst(queryTree_list);
  1319. if (length(query->rtable) > 1 ||
  1320. flatten_tlist(query->targetList) != NIL)
  1321. elog(ERROR, "Cannot use attribute(s) in DEFAULT clause");
  1322. te = (TargetEntry *) lfirst(query->targetList);
  1323. resdom = te->resdom;
  1324. expr = te->expr;
  1325. type = exprType(expr);
  1326. if (type != atp->atttypid)
  1327. {
  1328. if (IS_BINARY_COMPATIBLE(type, atp->atttypid))
  1329. ; /* use without change */
  1330. else if (can_coerce_type(1, &(type), &(atp->atttypid)))
  1331. expr = coerce_type(NULL, (Node *) expr, type, atp->atttypid,
  1332.    atp->atttypmod);
  1333. else if (IsA(expr, Const))
  1334. {
  1335. if (*cast != 0)
  1336. elog(ERROR, "DEFAULT clause const type '%s' mismatched with column type '%s'",
  1337.  typeidTypeName(type), typeidTypeName(atp->atttypid));
  1338. snprintf(cast, 2 * NAMEDATALEN, ":: %s", typeidTypeName(atp->atttypid));
  1339. goto start;
  1340. }
  1341. else
  1342. elog(ERROR, "DEFAULT clause type '%s' mismatched with column type '%s'",
  1343.  typeidTypeName(type), typeidTypeName(atp->atttypid));
  1344. }
  1345. adbin = nodeToString(expr);
  1346. oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
  1347. attrdef->adbin = pstrdup(adbin);
  1348. (void) MemoryContextSwitchTo(oldcxt);
  1349. pfree(adbin);
  1350. values[Anum_pg_attrdef_adrelid - 1] = rel->rd_id;
  1351. values[Anum_pg_attrdef_adnum - 1] = attrdef->adnum;
  1352. values[Anum_pg_attrdef_adbin - 1] = PointerGetDatum(textin(attrdef->adbin));
  1353. values[Anum_pg_attrdef_adsrc - 1] = PointerGetDatum(textin(attrdef->adsrc));
  1354. adrel = heap_openr(AttrDefaultRelationName);
  1355. tuple = heap_formtuple(adrel->rd_att, values, nulls);
  1356. CatalogOpenIndices(Num_pg_attrdef_indices, Name_pg_attrdef_indices, idescs);
  1357. heap_insert(adrel, tuple);
  1358. CatalogIndexInsert(idescs, Num_pg_attrdef_indices, adrel, tuple);
  1359. CatalogCloseIndices(Num_pg_attrdef_indices, idescs);
  1360. heap_close(adrel);
  1361. pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
  1362. pfree(DatumGetPointer(values[Anum_pg_attrdef_adsrc - 1]));
  1363. pfree(tuple);
  1364. }
  1365. static void
  1366. StoreRelCheck(Relation rel, ConstrCheck *check)
  1367. {
  1368. char str[MAX_PARSE_BUFFER];
  1369. List    *queryTree_list;
  1370. List    *planTree_list;
  1371. Query    *query;
  1372. Plan    *plan;
  1373. List    *qual;
  1374. char    *ccbin;
  1375. MemoryContext oldcxt;
  1376. Relation rcrel;
  1377. Relation idescs[Num_pg_relcheck_indices];
  1378. HeapTuple tuple;
  1379. Datum values[4];
  1380. char nulls[4] = {' ', ' ', ' ', ' '};
  1381. extern GlobalMemory CacheCxt;
  1382. /*
  1383.  * Check for table's existance. Surround table name with double-quotes
  1384.  * to allow mixed-case and whitespace names. - thomas 1998-11-12
  1385.  */
  1386. snprintf(str, MAX_PARSE_BUFFER,
  1387.  "select 1 from "%.*s" where %s",
  1388.  NAMEDATALEN, rel->rd_rel->relname.data, check->ccsrc);
  1389. setheapoverride(true);
  1390. planTree_list = pg_parse_and_plan(str, NULL, 0,
  1391.   &queryTree_list, None, FALSE);
  1392. setheapoverride(false);
  1393. query = (Query *) lfirst(queryTree_list);
  1394. if (length(query->rtable) > 1)
  1395. elog(ERROR, "Only relation '%.*s' can be referenced",
  1396.  NAMEDATALEN, rel->rd_rel->relname.data);
  1397. plan = (Plan *) lfirst(planTree_list);
  1398. qual = plan->qual;
  1399. ccbin = nodeToString(qual);
  1400. oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
  1401. check->ccbin = (char *) palloc(strlen(ccbin) + 1);
  1402. strcpy(check->ccbin, ccbin);
  1403. (void) MemoryContextSwitchTo(oldcxt);
  1404. pfree(ccbin);
  1405. values[Anum_pg_relcheck_rcrelid - 1] = rel->rd_id;
  1406. values[Anum_pg_relcheck_rcname - 1] = PointerGetDatum(namein(check->ccname));
  1407. values[Anum_pg_relcheck_rcbin - 1] = PointerGetDatum(textin(check->ccbin));
  1408. values[Anum_pg_relcheck_rcsrc - 1] = PointerGetDatum(textin(check->ccsrc));
  1409. rcrel = heap_openr(RelCheckRelationName);
  1410. tuple = heap_formtuple(rcrel->rd_att, values, nulls);
  1411. CatalogOpenIndices(Num_pg_relcheck_indices, Name_pg_relcheck_indices, idescs);
  1412. heap_insert(rcrel, tuple);
  1413. CatalogIndexInsert(idescs, Num_pg_relcheck_indices, rcrel, tuple);
  1414. CatalogCloseIndices(Num_pg_relcheck_indices, idescs);
  1415. heap_close(rcrel);
  1416. pfree(DatumGetPointer(values[Anum_pg_relcheck_rcname - 1]));
  1417. pfree(DatumGetPointer(values[Anum_pg_relcheck_rcbin - 1]));
  1418. pfree(DatumGetPointer(values[Anum_pg_relcheck_rcsrc - 1]));
  1419. pfree(tuple);
  1420. return;
  1421. }
  1422. static void
  1423. StoreConstraints(Relation rel)
  1424. {
  1425. TupleConstr *constr = rel->rd_att->constr;
  1426. int i;
  1427. if (!constr)
  1428. return;
  1429. if (constr->num_defval > 0)
  1430. {
  1431. for (i = 0; i < constr->num_defval; i++)
  1432. StoreAttrDefault(rel, &(constr->defval[i]));
  1433. }
  1434. if (constr->num_check > 0)
  1435. {
  1436. for (i = 0; i < constr->num_check; i++)
  1437. StoreRelCheck(rel, &(constr->check[i]));
  1438. }
  1439. return;
  1440. }
  1441. static void
  1442. RemoveAttrDefault(Relation rel)
  1443. {
  1444. Relation adrel;
  1445. HeapScanDesc adscan;
  1446. ScanKeyData key;
  1447. HeapTuple tup;
  1448. adrel = heap_openr(AttrDefaultRelationName);
  1449. ScanKeyEntryInitialize(&key, 0, Anum_pg_attrdef_adrelid,
  1450.    F_OIDEQ, rel->rd_id);
  1451. LockRelation(adrel, AccessExclusiveLock);
  1452. adscan = heap_beginscan(adrel, 0, SnapshotNow, 1, &key);
  1453. while (HeapTupleIsValid(tup = heap_getnext(adscan, 0)))
  1454. heap_delete(adrel, &tup->t_self, NULL);
  1455. heap_endscan(adscan);
  1456. UnlockRelation(adrel, AccessExclusiveLock);
  1457. heap_close(adrel);
  1458. }
  1459. static void
  1460. RemoveRelCheck(Relation rel)
  1461. {
  1462. Relation rcrel;
  1463. HeapScanDesc rcscan;
  1464. ScanKeyData key;
  1465. HeapTuple tup;
  1466. rcrel = heap_openr(RelCheckRelationName);
  1467. ScanKeyEntryInitialize(&key, 0, Anum_pg_relcheck_rcrelid,
  1468.    F_OIDEQ, rel->rd_id);
  1469. LockRelation(rcrel, AccessExclusiveLock);
  1470. rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key);
  1471. while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0)))
  1472. heap_delete(rcrel, &tup->t_self, NULL);
  1473. heap_endscan(rcscan);
  1474. UnlockRelation(rcrel, AccessExclusiveLock);
  1475. heap_close(rcrel);
  1476. }
  1477. static void
  1478. RemoveConstraints(Relation rel)
  1479. {
  1480. TupleConstr *constr = rel->rd_att->constr;
  1481. if (!constr)
  1482. return;
  1483. if (constr->num_defval > 0)
  1484. RemoveAttrDefault(rel);
  1485. if (constr->num_check > 0)
  1486. RemoveRelCheck(rel);
  1487. return;
  1488. }