1 /*-------------------------------------------------------------------------
4 * code to create and destroy POSTGRES heap relations
6 * Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.4 1996/11/05 11:57:50 scrappy Exp $
13 * heap_creatr() - Create an uncataloged heap relation
14 * heap_create() - Create a cataloged relation
15 * heap_destroy() - Removes named relation from catalogs
18 * this code taken from access/heap/create.c, which contains
19 * the old heap_creater, amcreate, and amdestroy. those routines
20 * will soon call these routines using the function manager,
21 * just like the poorly named "NewXXX" routines do. The
22 * "New" routines are all going to die soon, once and for all!
25 *-------------------------------------------------------------------------
27 #include <stdio.h> /* for sprintf() */
33 #include <catalog/heap.h>
34 #include <catalog/pg_proc.h>
36 #include "parser/catalog_utils.h"
38 #include "access/heapam.h"
39 #include "access/genam.h"
40 #include "access/istrat.h"
41 #include "storage/bufmgr.h"
42 #include "lib/hasht.h"
43 #include "miscadmin.h"
45 #include "utils/builtins.h"
46 #include "utils/mcxt.h"
47 #include "utils/palloc.h"
48 #include "utils/relcache.h"
50 #include "catalog/catname.h"
51 #include "catalog/pg_attribute.h"
52 #include "catalog/pg_index.h"
53 #include "catalog/pg_inherits.h"
54 #include "catalog/pg_ipl.h"
55 #include "catalog/index.h"
56 #include "catalog/indexing.h"
58 #include "catalog/catalog.h"
60 #include "storage/lmgr.h"
62 #include "rewrite/rewriteRemove.h"
64 #include "storage/smgr.h"
66 static void AddNewAttributeTuples(Oid new_rel_oid, TupleDesc tupdesc);
67 static void CheckAttributeNames(TupleDesc tupdesc);
69 /* ----------------------------------------------------------------
70 * XXX UGLY HARD CODED BADNESS FOLLOWS XXX
72 * these should all be moved to someplace in the lib/catalog
73 * module, if not obliterated first.
74 * ----------------------------------------------------------------
80 * Should the executor special case these attributes in the future?
81 * Advantage: consume 1/2 the space in the ATTRIBUTE relation.
82 * Disadvantage: having rules to compute values in these tuples may
83 * be more difficult if not impossible.
86 static FormData_pg_attribute a1 = {
87 0xffffffff, {"ctid"}, 27l, 0l, 0l, 0l, sizeof (ItemPointerData),
88 SelfItemPointerAttributeNumber, 0, '\0', '\001', 0l, 'i'
91 static FormData_pg_attribute a2 = {
92 0xffffffff, {"oid"}, 26l, 0l, 0l, 0l, sizeof(Oid),
93 ObjectIdAttributeNumber, 0, '\001', '\001', 0l, 'i'
96 static FormData_pg_attribute a3 = {
97 0xffffffff, {"xmin"}, 28l, 0l, 0l, 0l, sizeof (TransactionId),
98 MinTransactionIdAttributeNumber, 0, '\0', '\001', 0l, 'i',
101 static FormData_pg_attribute a4 = {
102 0xffffffff, {"cmin"}, 29l, 0l, 0l, 0l, sizeof (CommandId),
103 MinCommandIdAttributeNumber, 0, '\001', '\001', 0l, 's'
106 static FormData_pg_attribute a5 = {
107 0xffffffff, {"xmax"}, 28l, 0l, 0l, 0l, sizeof (TransactionId),
108 MaxTransactionIdAttributeNumber, 0, '\0', '\001', 0l, 'i'
111 static FormData_pg_attribute a6 = {
112 0xffffffff, {"cmax"}, 29l, 0l, 0l, 0l, sizeof (CommandId),
113 MaxCommandIdAttributeNumber, 0, '\001', '\001', 0l, 's'
116 static FormData_pg_attribute a7 = {
117 0xffffffff, {"chain"}, 27l, 0l, 0l, 0l, sizeof (ItemPointerData),
118 ChainItemPointerAttributeNumber, 0, '\0', '\001', 0l, 'i',
121 static FormData_pg_attribute a8 = {
122 0xffffffff, {"anchor"}, 27l, 0l, 0l, 0l, sizeof (ItemPointerData),
123 AnchorItemPointerAttributeNumber, 0, '\0', '\001', 0l, 'i'
126 static FormData_pg_attribute a9 = {
127 0xffffffff, {"tmin"}, 20l, 0l, 0l, 0l, sizeof (AbsoluteTime),
128 MinAbsoluteTimeAttributeNumber, 0, '\001', '\001', 0l, 'i'
131 static FormData_pg_attribute a10 = {
132 0xffffffff, {"tmax"}, 20l, 0l, 0l, 0l, sizeof (AbsoluteTime),
133 MaxAbsoluteTimeAttributeNumber, 0, '\001', '\001', 0l, 'i'
136 static FormData_pg_attribute a11 = {
137 0xffffffff, {"vtype"}, 18l, 0l, 0l, 0l, sizeof (char),
138 VersionTypeAttributeNumber, 0, '\001', '\001', 0l, 'c'
141 static AttributeTupleForm HeapAtt[] =
142 { &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10, &a11 };
144 /* ----------------------------------------------------------------
145 * XXX END OF UGLY HARD CODED BADNESS XXX
146 * ----------------------------------------------------------------
149 /* the tempRelList holds
150 the list of temporary uncatalogued relations that are created.
151 these relations should be destroyed at the end of transactions
153 typedef struct tempRelList {
154 Relation *rels; /* array of relation descriptors */
155 int num; /* number of temporary relations */
156 int size; /* size of space allocated for the rels array */
159 #define TEMP_REL_LIST_SIZE 32
161 static TempRelList *tempRels = NULL;
164 /* ----------------------------------------------------------------
165 * heap_creatr - Create an uncataloged heap relation
167 * Fields relpages, reltuples, reltuples, relkeys, relhistory,
168 * relisindexed, and relkind of rdesc->rd_rel are initialized
169 * to all zeros, as are rd_last and rd_hook. Rd_refcnt is set to 1.
171 * Remove the system relation specific code to elsewhere eventually.
173 * Eventually, must place information about this temporary relation
174 * into the transaction context block.
177 * if heap_creatr is called with "" as the name, then heap_creatr will create a
178 * temporary name "temp_$RELOID" for the relation
179 * ----------------------------------------------------------------
182 heap_creatr(char *name,
191 char* relname = name;
194 int natts = tupDesc->natts;
195 /* AttributeTupleForm *att = tupDesc->attrs; */
197 extern GlobalMemory CacheCxt;
198 MemoryContext oldcxt;
204 AssertArg(natts > 0);
206 if (IsSystemRelationName(relname) && IsNormalProcessingMode())
209 "Illegal class name: %s -- pg_ is reserved for system catalogs",
214 * switch to the cache context so that we don't lose
215 * allocations at the end of this transaction, I guess.
220 CacheCxt = CreateGlobalMemory("Cache");
222 oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt);
225 * real ugly stuff to assign the proper relid in the relation
226 * descriptor follows.
229 if (! strcmp(RelationRelationName,relname))
231 relid = RelOid_pg_class;
234 else if (! strcmp(AttributeRelationName,relname))
236 relid = RelOid_pg_attribute;
239 else if (! strcmp(ProcedureRelationName, relname))
241 relid = RelOid_pg_proc;
244 else if (! strcmp(TypeRelationName,relname))
246 relid = RelOid_pg_type;
255 sprintf(tempname, "temp_%d", relid);
262 * allocate a new relation descriptor.
264 * XXX the length computation may be incorrect, handle elsewhere
267 len = sizeof(RelationData);
269 rdesc = (Relation) palloc(len);
270 memset((char *)rdesc, 0,len);
273 create a new tuple descriptor from the one passed in
275 rdesc->rd_att = CreateTupleDescCopy(tupDesc);
278 * initialize the fields of our new relation descriptor
283 * nail the reldesc if this is a bootstrap create reln and
284 * we may need it in the cache later on in the bootstrap
285 * process so we don't ever want it kicked out. e.g. pg_attribute!!!
289 rdesc->rd_isnailed = true;
291 RelationSetReferenceCount(rdesc, 1);
293 rdesc->rd_rel = (Form_pg_class)palloc(sizeof *rdesc->rd_rel);
295 memset((char *)rdesc->rd_rel, 0,
296 sizeof *rdesc->rd_rel);
297 namestrcpy(&(rdesc->rd_rel->relname), relname);
298 rdesc->rd_rel->relkind = RELKIND_UNCATALOGED;
299 rdesc->rd_rel->relnatts = natts;
300 rdesc->rd_rel->relsmgr = smgr;
302 for (i = 0; i < natts; i++) {
303 rdesc->rd_att->attrs[i]->attrelid = relid;
306 rdesc->rd_id = relid;
309 /* for system relations, set the reltype field here */
310 rdesc->rd_rel->reltype = relid;
314 * remember if this is a temp relation
318 rdesc->rd_istemp = isTemp;
321 * have the storage manager create the relation.
325 rdesc->rd_fd = (File)smgrcreate(smgr, rdesc);
327 RelationRegisterRelation(rdesc);
329 MemoryContextSwitchTo(oldcxt);
331 /* add all temporary relations to the tempRels list
332 so they can be properly disposed of at the end of transaction
335 AddToTempRelList(rdesc);
341 /* ----------------------------------------------------------------
342 * heap_create - Create a cataloged relation
344 * this is done in 6 steps:
346 * 1) CheckAttributeNames() is used to make certain the tuple
347 * descriptor contains a valid set of attribute names
349 * 2) pg_class is opened and RelationAlreadyExists()
350 * preforms a scan to ensure that no relation with the
351 * same name already exists.
353 * 3) heap_creater() is called to create the new relation on
356 * 4) TypeDefine() is called to define a new type corresponding
357 * to the new relation.
359 * 5) AddNewAttributeTuples() is called to register the
360 * new relation's schema in pg_attribute.
362 * 6) AddPgRelationTuple() is called to register the
363 * relation itself in the catalogs.
365 * 7) the relations are closed and the new relation's oid
369 * A new relation is inserted into the RELATION relation
370 * with the specified attribute(s) (newly inserted into
371 * the ATTRIBUTE relation). How does concurrency control
372 * work? Is it automatic now? Expects the caller to have
373 * attname, atttypid, atttyparg, attproc, and attlen domains filled.
374 * Create fills the attnum domains sequentually from zero,
375 * fills the attnvals domains with zeros, and fills the
376 * attrelid fields with the relid.
378 * scan relation catalog for name conflict
379 * scan type catalog for typids (if not arg)
380 * create and insert attribute(s) into attribute catalog
381 * create new relation
382 * insert new relation into attribute catalog
384 * Should coordinate with heap_creater(). Either it should
385 * not be called or there should be a way to prevent
386 * the relation from being removed at the end of the
387 * transaction if it is successful ('u'/'r' may be enough).
388 * Also, if the transaction does not commit, then the
389 * relation should be removed.
391 * XXX amcreate ignores "off" when inserting (for now).
392 * XXX amcreate (like the other utilities) needs to understand indexes.
394 * ----------------------------------------------------------------
397 /* --------------------------------
398 * CheckAttributeNames
400 * this is used to make certain the tuple descriptor contains a
401 * valid set of attribute names. a problem simply generates
402 * elog(WARN) which aborts the current transaction.
403 * --------------------------------
406 CheckAttributeNames(TupleDesc tupdesc)
410 int natts = tupdesc->natts;
413 * first check for collision with system attribute names
416 * also, warn user if attribute to be created has
417 * an unknown typid (usually as a result of a 'retrieve into'
420 for (i = 0; i < natts; i += 1) {
421 for (j = 0; j < sizeof HeapAtt / sizeof HeapAtt[0]; j += 1) {
422 if (nameeq(&(HeapAtt[j]->attname),
423 &(tupdesc->attrs[i]->attname))) {
425 "create: system attribute named \"%s\"",
426 HeapAtt[j]->attname.data);
429 if (tupdesc->attrs[i]->atttypid == UNKNOWNOID)
432 "create: attribute named \"%s\" has an unknown type",
433 tupdesc->attrs[i]->attname.data);
438 * next check for repeated attribute names
441 for (i = 1; i < natts; i += 1) {
442 for (j = 0; j < i; j += 1) {
443 if (nameeq(&(tupdesc->attrs[j]->attname),
444 &(tupdesc->attrs[i]->attname))) {
446 "create: repeated attribute \"%s\"",
447 tupdesc->attrs[j]->attname.data);
453 /* --------------------------------
454 * RelationAlreadyExists
456 * this preforms a scan of pg_class to ensure that
457 * no relation with the same name already exists. The caller
458 * has to open pg_class and pass an open descriptor.
459 * --------------------------------
462 RelationAlreadyExists(Relation pg_class_desc, char relname[])
465 HeapScanDesc pg_class_scan;
469 * If this is not bootstrap (initdb) time, use the catalog index
473 if (!IsBootstrapProcessingMode()) {
474 tup = ClassNameIndexScan(pg_class_desc, relname);
475 if (HeapTupleIsValid(tup)) {
479 return ((int) false);
483 * At bootstrap time, we have to do this the hard way. Form the
487 ScanKeyEntryInitialize(&key,
489 (AttrNumber)Anum_pg_class_relname,
490 (RegProcedure)NameEqualRegProcedure,
497 pg_class_scan = heap_beginscan(pg_class_desc,
504 * get a tuple. if the tuple is NULL then it means we
505 * didn't find an existing relation.
508 tup = heap_getnext(pg_class_scan, 0, (Buffer *)NULL);
511 * end the scan and return existance of relation.
514 heap_endscan(pg_class_scan);
517 (PointerIsValid(tup) == true);
520 /* --------------------------------
521 * AddNewAttributeTuples
523 * this registers the new relation's schema by adding
524 * tuples to pg_attribute.
525 * --------------------------------
528 AddNewAttributeTuples(Oid new_rel_oid,
531 AttributeTupleForm *dpp;
536 Relation idescs[Num_pg_attr_indices];
537 int natts = tupdesc->natts;
543 rdesc = heap_openr(AttributeRelationName);
546 * Check if we have any indices defined on pg_attribute.
550 Assert(rdesc->rd_rel);
551 hasindex = RelationGetRelationTupleForm(rdesc)->relhasindex;
553 CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
556 * initialize tuple descriptor. Note we use setheapoverride()
557 * so that we can see the effects of our TypeDefine() done
561 setheapoverride(true);
563 setheapoverride(false);
566 * first we add the user attributes..
569 dpp = tupdesc->attrs;
570 for (i = 0; i < natts; i++) {
571 (*dpp)->attrelid = new_rel_oid;
572 (*dpp)->attnvals = 0l;
574 tup = heap_addheader(Natts_pg_attribute,
575 ATTRIBUTE_TUPLE_SIZE,
578 heap_insert(rdesc, tup);
581 CatalogIndexInsert(idescs, Num_pg_attr_indices, rdesc, tup);
588 * next we add the system attributes..
592 for (i = 0; i < -1 - FirstLowInvalidHeapAttributeNumber; i++) {
593 (*dpp)->attrelid = new_rel_oid;
594 /* (*dpp)->attnvals = 0l; unneeded */
596 tup = heap_addheader(Natts_pg_attribute,
597 ATTRIBUTE_TUPLE_SIZE,
600 heap_insert(rdesc, tup);
603 CatalogIndexInsert(idescs, Num_pg_attr_indices, rdesc, tup);
612 * close pg_attribute indices
615 CatalogCloseIndices(Num_pg_attr_indices, idescs);
618 /* --------------------------------
621 * this registers the new relation in the catalogs by
622 * adding a tuple to pg_class.
623 * --------------------------------
626 AddPgRelationTuple(Relation pg_class_desc,
627 Relation new_rel_desc,
632 Form_pg_class new_rel_reltup;
634 Relation idescs[Num_pg_class_indices];
638 * first we munge some of the information in our
639 * uncataloged relation's relation descriptor.
642 new_rel_reltup = new_rel_desc->rd_rel;
644 /* CHECK should get new_rel_oid first via an insert then use XXX */
645 /* new_rel_reltup->reltuples = 1; */ /* XXX */
647 new_rel_reltup->relowner = GetUserId();
648 new_rel_reltup->relkind = RELKIND_RELATION;
649 new_rel_reltup->relarch = arch;
650 new_rel_reltup->relnatts = natts;
653 * now form a tuple to add to pg_class
654 * XXX Natts_pg_class_fixed is a hack - see pg_class.h
657 tup = heap_addheader(Natts_pg_class_fixed,
659 (char *) new_rel_reltup);
660 tup->t_oid = new_rel_oid;
663 * finally insert the new tuple and free it.
665 * Note: I have no idea why we do a
666 * SetProcessingMode(BootstrapProcessing);
670 isBootstrap = IsBootstrapProcessingMode() ? true : false;
672 SetProcessingMode(BootstrapProcessing);
674 heap_insert(pg_class_desc, tup);
678 * First, open the catalog indices and insert index tuples for
682 CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
683 CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class_desc, tup);
684 CatalogCloseIndices(Num_pg_class_indices, idescs);
686 /* now restore processing mode */
687 SetProcessingMode(NormalProcessing);
694 /* --------------------------------
695 * addNewRelationType -
697 * define a complex type corresponding to the new relation
698 * --------------------------------
701 addNewRelationType(char *typeName, Oid new_rel_oid)
705 /* The sizes are set to oid size because it makes implementing sets MUCH
706 * easier, and no one (we hope) uses these fields to figure out
707 * how much space to allocate for the type.
708 * An oid is the type used for a set definition. When a user
709 * requests a set, what they actually get is the oid of a tuple in
710 * the pg_proc catalog, so the size of the "set" is the size
712 * Similarly, byval being true makes sets much easier, and
713 * it isn't used by anything else.
714 * Note the assumption that OIDs are the same size as int4s.
716 new_type_oid = TypeCreate(typeName, /* type name */
717 new_rel_oid, /* relation oid */
718 tlen(type("oid")), /* internal size */
719 tlen(type("oid")), /* external size */
720 'c', /* type-type (catalog) */
721 ',', /* default array delimiter */
722 "int4in", /* input procedure */
723 "int4out", /* output procedure */
724 "int4in", /* send procedure */
725 "int4out", /* receive procedure */
726 NULL, /* array element type - irrelevent */
727 "-", /* default type value */
728 (bool) 1, /* passed by value */
729 'i'); /* default alignment */
732 /* --------------------------------
735 * creates a new cataloged relation. see comments above.
736 * --------------------------------
739 heap_create(char relname[],
740 char *typename, /* not used currently */
745 Relation pg_class_desc;
746 Relation new_rel_desc;
748 /* NameData typeNameData; */
749 int natts = tupdesc->natts;
755 AssertState(IsNormalProcessingMode() || IsBootstrapProcessingMode());
756 if (natts == 0 || natts > MaxHeapAttributeNumber)
757 elog(WARN, "amcreate: from 1 to %d attributes must be specified",
758 MaxHeapAttributeNumber);
760 CheckAttributeNames(tupdesc);
763 * open pg_class and see that the relation doesn't
767 pg_class_desc = heap_openr(RelationRelationName);
769 if (RelationAlreadyExists(pg_class_desc, relname)) {
770 heap_close(pg_class_desc);
771 elog(WARN, "amcreate: %s relation already exists", relname);
775 * ok, relation does not already exist so now we
776 * create an uncataloged relation and pull its relation oid
777 * from the newly formed relation descriptor.
779 * Note: The call to heap_creatr() does all the "real" work
780 * of creating the disk file for the relation.
783 new_rel_desc = heap_creatr(relname, smgr, tupdesc);
784 new_rel_oid = new_rel_desc->rd_att->attrs[0]->attrelid;
787 * since defining a relation also defines a complex type,
788 * we add a new system type corresponding to the new relation.
791 /* namestrcpy(&typeNameData, relname);*/
792 /* addNewRelationType(&typeNameData, new_rel_oid);*/
793 addNewRelationType(relname, new_rel_oid);
796 * now add tuples to pg_attribute for the attributes in
800 AddNewAttributeTuples(new_rel_oid, tupdesc);
803 * now update the information in pg_class.
806 AddPgRelationTuple(pg_class_desc,
813 * ok, the relation has been cataloged, so close our relations
814 * and return the oid of the newly created relation.
816 * SOMEDAY: fill the STATISTIC relation properly.
819 heap_close(new_rel_desc);
820 heap_close(pg_class_desc);
826 /* ----------------------------------------------------------------
827 * heap_destroy - removes all record of named relation from catalogs
829 * 1) open relation, check for existence, etc.
830 * 2) remove inheritance information
832 * 4) remove pg_class tuple
833 * 5) remove pg_attribute tuples
834 * 6) remove pg_type tuples
838 * Except for vital relations, removes relation from
839 * relation catalog, and related attributes from
840 * attribute catalog (needed?). (Anything else???)
842 * get proper relation from relation catalog (if not arg)
843 * check if relation is vital (strcmp()/reltype???)
844 * scan attribute catalog deleting attributes of reldesc
846 * delete relation from relation catalog
847 * (How are the tuples of the relation discarded???)
849 * XXX Must fix to work with indexes.
850 * There may be a better order for doing things.
851 * Problems with destroying a deleted database--cannot create
852 * a struct reldesc without having an open file descriptor.
853 * ----------------------------------------------------------------
856 /* --------------------------------
857 * RelationRemoveInheritance
859 * Note: for now, we cause an exception if relation is a
860 * superclass. Someday, we may want to allow this and merge
861 * the type info into subclass procedures.... this seems like
863 * --------------------------------
866 RelationRemoveInheritance(Relation relation)
868 Relation catalogRelation;
877 catalogRelation = heap_openr(InheritsRelationName);
880 * form a scan key for the subclasses of this class
884 ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_inherits_inhparent,
885 ObjectIdEqualRegProcedure,
886 ObjectIdGetDatum(RelationGetRelationId(relation)));
888 scan = heap_beginscan(catalogRelation,
895 * if any subclasses exist, then we disallow the deletion.
898 tuple = heap_getnext(scan, 0, (Buffer *)NULL);
899 if (HeapTupleIsValid(tuple)) {
901 heap_close(catalogRelation);
903 elog(WARN, "relation <%d> inherits \"%s\"",
904 ((InheritsTupleForm) GETSTRUCT(tuple))->inhrel,
905 RelationGetRelationName(relation));
909 * If we get here, it means the relation has no subclasses
910 * so we can trash it. First we remove dead INHERITS tuples.
913 entry.sk_attno = Anum_pg_inherits_inhrel;
915 scan = heap_beginscan(catalogRelation,
922 tuple = heap_getnext(scan, 0, (Buffer *)NULL);
923 if (!HeapTupleIsValid(tuple)) {
926 heap_delete(catalogRelation, &tuple->t_ctid);
930 heap_close(catalogRelation);
933 * now remove dead IPL tuples
937 heap_openr(InheritancePrecidenceListRelationName);
939 entry.sk_attno = Anum_pg_ipl_iplrel;
941 scan = heap_beginscan(catalogRelation,
948 tuple = heap_getnext(scan, 0, (Buffer *)NULL);
949 if (!HeapTupleIsValid(tuple)) {
952 heap_delete(catalogRelation, &tuple->t_ctid);
956 heap_close(catalogRelation);
959 /* --------------------------------
960 * RelationRemoveIndexes
962 * --------------------------------
965 RelationRemoveIndexes(Relation relation)
967 Relation indexRelation;
972 indexRelation = heap_openr(IndexRelationName);
974 ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_index_indrelid,
975 ObjectIdEqualRegProcedure,
976 ObjectIdGetDatum(RelationGetRelationId(relation)));
978 scan = heap_beginscan(indexRelation,
985 tuple = heap_getnext(scan, 0, (Buffer *)NULL);
986 if (!HeapTupleIsValid(tuple)) {
990 index_destroy(((IndexTupleForm)GETSTRUCT(tuple))->indexrelid);
994 heap_close(indexRelation);
997 /* --------------------------------
998 * DeletePgRelationTuple
1000 * --------------------------------
1003 DeletePgRelationTuple(Relation rdesc)
1005 Relation pg_class_desc;
1006 HeapScanDesc pg_class_scan;
1014 pg_class_desc = heap_openr(RelationRelationName);
1017 * create a scan key to locate the relation oid of the
1018 * relation to delete
1021 ScanKeyEntryInitialize(&key, 0, ObjectIdAttributeNumber,
1022 F_INT4EQ, rdesc->rd_att->attrs[0]->attrelid);
1024 pg_class_scan = heap_beginscan(pg_class_desc,
1031 * use heap_getnext() to fetch the pg_class tuple. If this
1032 * tuple is not valid then something's wrong.
1035 tup = heap_getnext(pg_class_scan, 0, (Buffer *) NULL);
1037 if (! PointerIsValid(tup)) {
1038 heap_endscan(pg_class_scan);
1039 heap_close(pg_class_desc);
1040 elog(WARN, "DeletePgRelationTuple: %s relation nonexistent",
1041 &rdesc->rd_rel->relname);
1045 * delete the relation tuple from pg_class, and finish up.
1048 heap_endscan(pg_class_scan);
1049 heap_delete(pg_class_desc, &tup->t_ctid);
1051 heap_close(pg_class_desc);
1054 /* --------------------------------
1055 * DeletePgAttributeTuples
1057 * --------------------------------
1060 DeletePgAttributeTuples(Relation rdesc)
1062 Relation pg_attribute_desc;
1063 HeapScanDesc pg_attribute_scan;
1071 pg_attribute_desc = heap_openr(AttributeRelationName);
1074 * create a scan key to locate the attribute tuples to delete
1075 * and begin the scan.
1078 ScanKeyEntryInitialize(&key, 0, Anum_pg_attribute_attrelid,
1079 F_INT4EQ, rdesc->rd_att->attrs[0]->attrelid);
1081 /* -----------------
1082 * Get a write lock _before_ getting the read lock in the scan
1085 RelationSetLockForWrite(pg_attribute_desc);
1087 pg_attribute_scan = heap_beginscan(pg_attribute_desc,
1094 * use heap_getnext() / amdelete() until all attribute tuples
1095 * have been deleted.
1098 while (tup = heap_getnext(pg_attribute_scan, 0, (Buffer *)NULL),
1099 PointerIsValid(tup)) {
1101 heap_delete(pg_attribute_desc, &tup->t_ctid);
1108 heap_endscan(pg_attribute_scan);
1111 * Release the write lock
1114 RelationUnsetLockForWrite(pg_attribute_desc);
1115 heap_close(pg_attribute_desc);
1119 /* --------------------------------
1122 * If the user attempts to destroy a relation and there
1123 * exists attributes in other relations of type
1124 * "relation we are deleting", then we have to do something
1125 * special. presently we disallow the destroy.
1126 * --------------------------------
1129 DeletePgTypeTuple(Relation rdesc)
1131 Relation pg_type_desc;
1132 HeapScanDesc pg_type_scan;
1133 Relation pg_attribute_desc;
1134 HeapScanDesc pg_attribute_scan;
1145 pg_type_desc = heap_openr(TypeRelationName);
1148 * create a scan key to locate the type tuple corresponding
1152 ScanKeyEntryInitialize(&key, 0, Anum_pg_type_typrelid, F_INT4EQ,
1153 rdesc->rd_att->attrs[0]->attrelid);
1155 pg_type_scan = heap_beginscan(pg_type_desc,
1162 * use heap_getnext() to fetch the pg_type tuple. If this
1163 * tuple is not valid then something's wrong.
1166 tup = heap_getnext(pg_type_scan, 0, (Buffer *)NULL);
1168 if (! PointerIsValid(tup)) {
1169 heap_endscan(pg_type_scan);
1170 heap_close(pg_type_desc);
1171 elog(WARN, "DeletePgTypeTuple: %s type nonexistent",
1172 &rdesc->rd_rel->relname);
1176 * now scan pg_attribute. if any other relations have
1177 * attributes of the type of the relation we are deleteing
1178 * then we have to disallow the deletion. should talk to
1179 * stonebraker about this. -cim 6/19/90
1182 typoid = tup->t_oid;
1184 pg_attribute_desc = heap_openr(AttributeRelationName);
1186 ScanKeyEntryInitialize(&attkey,
1187 0, Anum_pg_attribute_atttypid, F_INT4EQ,
1190 pg_attribute_scan = heap_beginscan(pg_attribute_desc,
1197 * try and get a pg_attribute tuple. if we succeed it means
1198 * we cant delete the relation because something depends on
1202 atttup = heap_getnext(pg_attribute_scan, 0, (Buffer *)NULL);
1204 if (PointerIsValid(atttup)) {
1205 Oid relid = ((AttributeTupleForm) GETSTRUCT(atttup))->attrelid;
1207 heap_endscan(pg_type_scan);
1208 heap_close(pg_type_desc);
1209 heap_endscan(pg_attribute_scan);
1210 heap_close(pg_attribute_desc);
1212 elog(WARN, "DeletePgTypeTuple: att of type %s exists in relation %d",
1213 &rdesc->rd_rel->relname, relid);
1215 heap_endscan(pg_attribute_scan);
1216 heap_close(pg_attribute_desc);
1219 * Ok, it's safe so we delete the relation tuple
1220 * from pg_type and finish up. But first end the scan so that
1221 * we release the read lock on pg_type. -mer 13 Aug 1991
1224 heap_endscan(pg_type_scan);
1225 heap_delete(pg_type_desc, &tup->t_ctid);
1227 heap_close(pg_type_desc);
1230 /* --------------------------------
1233 * --------------------------------
1236 heap_destroy(char *relname)
1241 * first open the relation. if the relation does exist,
1242 * heap_openr() returns NULL.
1245 rdesc = heap_openr(relname);
1247 elog(WARN,"Relation %s Does Not Exist!", relname);
1250 * prevent deletion of system relations
1253 if (IsSystemRelationName(RelationGetRelationName(rdesc)->data))
1254 elog(WARN, "amdestroy: cannot destroy %s relation",
1255 &rdesc->rd_rel->relname);
1258 * remove inheritance information
1261 RelationRemoveInheritance(rdesc);
1264 * remove indexes if necessary
1267 if (rdesc->rd_rel->relhasindex) {
1268 RelationRemoveIndexes(rdesc);
1272 * remove rules if necessary
1275 if (rdesc->rd_rules != NULL) {
1276 RelationRemoveRules(rdesc->rd_id);
1280 * delete attribute tuples
1283 DeletePgAttributeTuples(rdesc);
1286 * delete type tuple. here we want to see the effects
1287 * of the deletions we just did, so we use setheapoverride().
1290 setheapoverride(true);
1291 DeletePgTypeTuple(rdesc);
1292 setheapoverride(false);
1295 * delete relation tuple
1298 DeletePgRelationTuple(rdesc);
1301 * flush the relation from the relcache
1304 RelationIdInvalidateRelationCacheByRelationId(rdesc->rd_id);
1307 * unlink the relation and finish up.
1310 (void) smgrunlink(rdesc->rd_rel->relsmgr, rdesc);
1311 if(rdesc->rd_istemp) {
1312 rdesc->rd_tmpunlinked = TRUE;
1319 * destroy and close temporary relations
1324 heap_destroyr(Relation rdesc)
1326 ReleaseTmpRelBuffers(rdesc);
1327 (void) smgrunlink(rdesc->rd_rel->relsmgr, rdesc);
1328 if(rdesc->rd_istemp) {
1329 rdesc->rd_tmpunlinked = TRUE;
1332 RemoveFromTempRelList(rdesc);
1336 /**************************************************************
1337 functions to deal with the list of temporary relations
1338 **************************************************************/
1343 initialize temporary relations list
1344 the tempRelList is a list of temporary relations that
1345 are created in the course of the transactions
1346 they need to be destroyed properly at the end of the transactions
1348 MODIFIES the global variable tempRels
1352 malloc is used instead of palloc because we KNOW when we are
1353 going to free these things. Keeps us away from the memory context
1361 free(tempRels->rels);
1365 tempRels = (TempRelList*)malloc(sizeof(TempRelList));
1366 tempRels->size = TEMP_REL_LIST_SIZE;
1367 tempRels->rels = (Relation*)malloc(sizeof(Relation) * tempRels->size);
1368 memset(tempRels->rels, 0, sizeof(Relation) * tempRels->size);
1373 removes a relation from the TempRelList
1375 MODIFIES the global variable tempRels
1376 we don't really remove it, just mark it as NULL
1377 and DestroyTempRels will look for NULLs
1380 RemoveFromTempRelList(Relation r)
1387 for (i=0; i<tempRels->num; i++) {
1388 if (tempRels->rels[i] == r) {
1389 tempRels->rels[i] = NULL;
1396 add a temporary relation to the TempRelList
1398 MODIFIES the global variable tempRels
1401 AddToTempRelList(Relation r)
1406 if (tempRels->num == tempRels->size) {
1407 tempRels->size += TEMP_REL_LIST_SIZE;
1408 tempRels->rels = realloc(tempRels->rels, tempRels->size);
1410 tempRels->rels[tempRels->num] = r;
1415 go through the tempRels list and destroy each of the relations
1426 for (i=0;i<tempRels->num;i++) {
1427 rdesc = tempRels->rels[i];
1428 /* rdesc may be NULL if it has been removed from the list already */
1430 heap_destroyr(rdesc);
1432 free(tempRels->rels);