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.61 1998/08/26 17:12:08 momjian Exp $
13 * heap_create() - Create an uncataloged heap relation
14 * heap_create_with_catalog() - Create a cataloged relation
15 * heap_destroy_with_catalog() - Removes named relation from catalogs
18 * this code taken from access/heap/create.c, which contains
19 * the old heap_create_with_catalog, amcreate, and amdestroy.
20 * those routines will soon call these routines using the function
22 * just like the poorly named "NewXXX" routines do. The
23 * "New" routines are all going to die soon, once and for all!
26 *-------------------------------------------------------------------------
30 #include "access/heapam.h"
31 #include "catalog/catalog.h"
32 #include "catalog/catname.h"
33 #include "catalog/heap.h"
34 #include "catalog/index.h"
35 #include "catalog/indexing.h"
36 #include "catalog/pg_attrdef.h"
37 #include "catalog/pg_index.h"
38 #include "catalog/pg_inherits.h"
39 #include "catalog/pg_ipl.h"
40 #include "catalog/pg_relcheck.h"
41 #include "catalog/pg_type.h"
42 #include "commands/trigger.h"
44 #include "miscadmin.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_type.h"
50 #include "parser/parse_coerce.h"
51 #include "rewrite/rewriteRemove.h"
52 #include "storage/bufmgr.h"
53 #include "storage/lmgr.h"
54 #include "storage/smgr.h"
55 #include "tcop/tcopprot.h"
56 #include "utils/builtins.h"
57 #include "utils/mcxt.h"
58 #include "utils/relcache.h"
59 #include "utils/syscache.h"
60 #include "utils/tqual.h"
63 #include <regex/utils.h>
69 AddPgRelationTuple(Relation pg_class_desc,
70 Relation new_rel_desc, Oid new_rel_oid, unsigned natts,
72 static void AddToTempRelList(Relation r);
73 static void DeletePgAttributeTuples(Relation rel);
74 static void DeletePgRelationTuple(Relation rel);
75 static void DeletePgTypeTuple(Relation rel);
76 static int RelationAlreadyExists(Relation pg_class_desc, char relname[]);
77 static void RelationRemoveIndexes(Relation relation);
78 static void RelationRemoveInheritance(Relation relation);
79 static void RemoveFromTempRelList(Relation r);
80 static void addNewRelationType(char *typeName, Oid new_rel_oid);
81 static void StoreConstraints(Relation rel);
82 static void RemoveConstraints(Relation rel);
85 /* ----------------------------------------------------------------
86 * XXX UGLY HARD CODED BADNESS FOLLOWS XXX
88 * these should all be moved to someplace in the lib/catalog
89 * module, if not obliterated first.
90 * ----------------------------------------------------------------
96 * Should the executor special case these attributes in the future?
97 * Advantage: consume 1/2 the space in the ATTRIBUTE relation.
98 * Disadvantage: having rules to compute values in these tuples may
99 * be more difficult if not impossible.
102 static FormData_pg_attribute a1 = {
103 0xffffffff, {"ctid"}, TIDOID, 0, sizeof(ItemPointerData),
104 SelfItemPointerAttributeNumber, 0, -1, -1, '\0', '\0', 'i', '\0', '\0'
107 static FormData_pg_attribute a2 = {
108 0xffffffff, {"oid"}, OIDOID, 0, sizeof(Oid),
109 ObjectIdAttributeNumber, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'
112 static FormData_pg_attribute a3 = {
113 0xffffffff, {"xmin"}, XIDOID, 0, sizeof(TransactionId),
114 MinTransactionIdAttributeNumber, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'
117 static FormData_pg_attribute a4 = {
118 0xffffffff, {"cmin"}, CIDOID, 0, sizeof(CommandId),
119 MinCommandIdAttributeNumber, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'
122 static FormData_pg_attribute a5 = {
123 0xffffffff, {"xmax"}, XIDOID, 0, sizeof(TransactionId),
124 MaxTransactionIdAttributeNumber, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'
127 static FormData_pg_attribute a6 = {
128 0xffffffff, {"cmax"}, CIDOID, 0, sizeof(CommandId),
129 MaxCommandIdAttributeNumber, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'
132 static AttributeTupleForm HeapAtt[] =
133 {&a1, &a2, &a3, &a4, &a5, &a6};
135 /* ----------------------------------------------------------------
136 * XXX END OF UGLY HARD CODED BADNESS XXX
137 * ----------------------------------------------------------------
140 /* the tempRelList holds
141 the list of temporary uncatalogued relations that are created.
142 these relations should be destroyed at the end of transactions
144 typedef struct tempRelList
146 Relation *rels; /* array of relation descriptors */
147 int num; /* number of temporary relations */
148 int size; /* size of space allocated for the rels
152 #define TEMP_REL_LIST_SIZE 32
154 static TempRelList *tempRels = NULL;
157 /* ----------------------------------------------------------------
158 * heap_create - Create an uncataloged heap relation
160 * Fields relpages, reltuples, reltuples, relkeys, relhistory,
161 * relisindexed, and relkind of rel->rd_rel are initialized
162 * to all zeros, as are rd_last and rd_hook. Rd_refcnt is set to 1.
164 * Remove the system relation specific code to elsewhere eventually.
166 * Eventually, must place information about this temporary relation
167 * into the transaction context block.
170 * if heap_create is called with "" as the name, then heap_create will create
171 * a temporary name "temp_$RELOID" for the relation
172 * ----------------------------------------------------------------
175 heap_create(char *name,
183 char *relname = name;
184 char tempname[NAMEDATALEN];
186 int natts = tupDesc->natts;
188 /* AttributeTupleForm *att = tupDesc->attrs; */
190 extern GlobalMemory CacheCxt;
191 MemoryContext oldcxt;
197 AssertArg(natts > 0);
199 if (IsSystemRelationName(relname) && IsNormalProcessingMode())
202 "Illegal class name: %s -- pg_ is reserved for system catalogs",
207 * switch to the cache context so that we don't lose
208 * allocations at the end of this transaction, I guess.
213 CacheCxt = CreateGlobalMemory("Cache");
215 oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
218 * real ugly stuff to assign the proper relid in the relation
219 * descriptor follows.
222 if (!strcmp(RelationRelationName, relname))
224 relid = RelOid_pg_class;
227 else if (!strcmp(AttributeRelationName, relname))
229 relid = RelOid_pg_attribute;
232 else if (!strcmp(ProcedureRelationName, relname))
234 relid = RelOid_pg_proc;
237 else if (!strcmp(TypeRelationName, relname))
239 relid = RelOid_pg_type;
248 sprintf(tempname, "temp_%d", relid);
249 Assert(strlen(tempname) < NAMEDATALEN);
256 * allocate a new relation descriptor.
258 * XXX the length computation may be incorrect, handle elsewhere
261 len = sizeof(RelationData);
263 rel = (Relation) palloc(len);
264 MemSet((char *) rel, 0, len);
267 create a new tuple descriptor from the one passed in
269 rel->rd_att = CreateTupleDescCopyConstr(tupDesc);
272 * initialize the fields of our new relation descriptor
277 * nail the reldesc if this is a bootstrap create reln and
278 * we may need it in the cache later on in the bootstrap
279 * process so we don't ever want it kicked out. e.g. pg_attribute!!!
283 rel->rd_isnailed = true;
285 RelationSetReferenceCount(rel, 1);
287 rel->rd_rel = (Form_pg_class) palloc(sizeof *rel->rd_rel);
289 MemSet((char *) rel->rd_rel, 0,
290 sizeof *rel->rd_rel);
291 namestrcpy(&(rel->rd_rel->relname), relname);
292 rel->rd_rel->relkind = RELKIND_UNCATALOGED;
293 rel->rd_rel->relnatts = natts;
295 rel->rd_rel->relchecks = tupDesc->constr->num_check;
297 for (i = 0; i < natts; i++)
298 rel->rd_att->attrs[i]->attrelid = relid;
300 RelationGetRelid(rel) = relid;
304 /* for system relations, set the reltype field here */
305 rel->rd_rel->reltype = relid;
309 * remember if this is a temp relation
313 rel->rd_istemp = isTemp;
316 * have the storage manager create the relation.
320 rel->rd_tmpunlinked = TRUE; /* change once table is created */
321 rel->rd_fd = (File) smgrcreate(DEFAULT_SMGR, rel);
322 rel->rd_tmpunlinked = FALSE;
324 RelationRegisterRelation(rel);
326 MemoryContextSwitchTo(oldcxt);
329 * add all temporary relations to the tempRels list so they can be
330 * properly disposed of at the end of transaction
333 AddToTempRelList(rel);
339 /* ----------------------------------------------------------------
340 * heap_create_with_catalog - Create a cataloged relation
342 * this is done in 6 steps:
344 * 1) CheckAttributeNames() is used to make certain the tuple
345 * descriptor contains a valid set of attribute names
347 * 2) pg_class is opened and RelationAlreadyExists()
348 * preforms a scan to ensure that no relation with the
349 * same name already exists.
351 * 3) heap_create_with_catalog() is called to create the new relation
354 * 4) TypeDefine() is called to define a new type corresponding
355 * to the new relation.
357 * 5) AddNewAttributeTuples() is called to register the
358 * new relation's schema in pg_attribute.
360 * 6) AddPgRelationTuple() is called to register the
361 * relation itself in the catalogs.
363 * 7) StoreConstraints is called () - vadim 08/22/97
365 * 8) 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 attdisbursion 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_create_with_catalog(). Either
385 * it should 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(ERROR) 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)
422 for (j = 0; j < sizeof HeapAtt / sizeof HeapAtt[0]; j += 1)
424 if (nameeq(&(HeapAtt[j]->attname),
425 &(tupdesc->attrs[i]->attname)))
428 "create: system attribute named \"%s\"",
429 HeapAtt[j]->attname.data);
432 if (tupdesc->attrs[i]->atttypid == UNKNOWNOID)
435 "create: attribute named \"%s\" has an unknown type",
436 tupdesc->attrs[i]->attname.data);
441 * next check for repeated attribute names
444 for (i = 1; i < natts; i += 1)
446 for (j = 0; j < i; j += 1)
448 if (nameeq(&(tupdesc->attrs[j]->attname),
449 &(tupdesc->attrs[i]->attname)))
452 "create: repeated attribute \"%s\"",
453 tupdesc->attrs[j]->attname.data);
459 /* --------------------------------
460 * RelationAlreadyExists
462 * this preforms a scan of pg_class to ensure that
463 * no relation with the same name already exists. The caller
464 * has to open pg_class and pass an open descriptor.
465 * --------------------------------
468 RelationAlreadyExists(Relation pg_class_desc, char relname[])
471 HeapScanDesc pg_class_scan;
475 * If this is not bootstrap (initdb) time, use the catalog index on
479 if (!IsBootstrapProcessingMode())
481 tup = SearchSysCacheTuple(RELNAME,
482 PointerGetDatum(relname),
484 if (HeapTupleIsValid(tup))
491 * At bootstrap time, we have to do this the hard way. Form the
495 ScanKeyEntryInitialize(&key,
497 (AttrNumber) Anum_pg_class_relname,
498 (RegProcedure) F_NAMEEQ,
505 pg_class_scan = heap_beginscan(pg_class_desc,
512 * get a tuple. if the tuple is NULL then it means we
513 * didn't find an existing relation.
516 tup = heap_getnext(pg_class_scan, 0);
519 * end the scan and return existance of relation.
522 heap_endscan(pg_class_scan);
524 return HeapTupleIsValid(tup);
527 /* --------------------------------
528 * AddNewAttributeTuples
530 * this registers the new relation's schema by adding
531 * tuples to pg_attribute.
532 * --------------------------------
535 AddNewAttributeTuples(Oid new_rel_oid,
538 AttributeTupleForm *dpp;
543 Relation idescs[Num_pg_attr_indices];
544 int natts = tupdesc->natts;
550 rel = heap_openr(AttributeRelationName);
553 * Check if we have any indices defined on pg_attribute.
558 hasindex = RelationGetRelationTupleForm(rel)->relhasindex;
560 CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
563 * initialize tuple descriptor. Note we use setheapoverride()
564 * so that we can see the effects of our TypeDefine() done
568 setheapoverride(true);
570 setheapoverride(false);
573 * first we add the user attributes..
576 dpp = tupdesc->attrs;
577 for (i = 0; i < natts; i++)
579 (*dpp)->attrelid = new_rel_oid;
580 (*dpp)->attdisbursion = 0;
582 tup = heap_addheader(Natts_pg_attribute,
583 ATTRIBUTE_TUPLE_SIZE,
586 heap_insert(rel, tup);
588 CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
595 * next we add the system attributes..
599 for (i = 0; i < -1 - FirstLowInvalidHeapAttributeNumber; i++)
601 (*dpp)->attrelid = new_rel_oid;
602 /* (*dpp)->attdisbursion = 0; unneeded */
604 tup = heap_addheader(Natts_pg_attribute,
605 ATTRIBUTE_TUPLE_SIZE,
608 heap_insert(rel, tup);
611 CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
620 * close pg_attribute indices
623 CatalogCloseIndices(Num_pg_attr_indices, idescs);
626 /* --------------------------------
629 * this registers the new relation in the catalogs by
630 * adding a tuple to pg_class.
631 * --------------------------------
634 AddPgRelationTuple(Relation pg_class_desc,
635 Relation new_rel_desc,
640 Form_pg_class new_rel_reltup;
642 Relation idescs[Num_pg_class_indices];
646 * first we munge some of the information in our
647 * uncataloged relation's relation descriptor.
650 new_rel_reltup = new_rel_desc->rd_rel;
652 /* CHECK should get new_rel_oid first via an insert then use XXX */
653 /* new_rel_reltup->reltuples = 1; *//* XXX */
655 new_rel_reltup->relowner = GetUserId();
656 new_rel_reltup->relkind = relkind;
657 new_rel_reltup->relnatts = natts;
660 * now form a tuple to add to pg_class
661 * XXX Natts_pg_class_fixed is a hack - see pg_class.h
664 tup = heap_addheader(Natts_pg_class_fixed,
666 (char *) new_rel_reltup);
667 tup->t_oid = new_rel_oid;
670 * finally insert the new tuple and free it.
672 * Note: I have no idea why we do a
673 * SetProcessingMode(BootstrapProcessing);
677 isBootstrap = IsBootstrapProcessingMode() ? true : false;
679 SetProcessingMode(BootstrapProcessing);
681 heap_insert(pg_class_desc, tup);
687 * First, open the catalog indices and insert index tuples for the
691 CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
692 CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class_desc, tup);
693 CatalogCloseIndices(Num_pg_class_indices, idescs);
695 /* now restore processing mode */
696 SetProcessingMode(NormalProcessing);
703 /* --------------------------------
704 * addNewRelationType -
706 * define a complex type corresponding to the new relation
707 * --------------------------------
710 addNewRelationType(char *typeName, Oid new_rel_oid)
715 * The sizes are set to oid size because it makes implementing sets
716 * MUCH easier, and no one (we hope) uses these fields to figure out
717 * how much space to allocate for the type. An oid is the type used
718 * for a set definition. When a user requests a set, what they
719 * actually get is the oid of a tuple in the pg_proc catalog, so the
720 * size of the "set" is the size of an oid. Similarly, byval being
721 * true makes sets much easier, and it isn't used by anything else.
722 * Note the assumption that OIDs are the same size as int4s.
724 new_type_oid = TypeCreate(typeName, /* type name */
725 new_rel_oid, /* relation oid */
726 typeLen(typeidType(OIDOID)), /* internal size */
727 typeLen(typeidType(OIDOID)), /* external size */
728 'c', /* type-type (catalog) */
729 ',', /* default array delimiter */
730 "int4in", /* input procedure */
731 "int4out", /* output procedure */
732 "int4in", /* receive procedure */
733 "int4out", /* send procedure */
734 NULL, /* array element type - irrelevent */
735 "-", /* default type value */
736 (bool) 1, /* passed by value */
737 'i'); /* default alignment */
740 /* --------------------------------
741 * heap_create_with_catalog
743 * creates a new cataloged relation. see comments above.
744 * --------------------------------
747 heap_create_with_catalog(char *relname,
751 Relation pg_class_desc;
752 Relation new_rel_desc;
755 int natts = tupdesc->natts;
761 AssertState(IsNormalProcessingMode() || IsBootstrapProcessingMode());
762 if (natts == 0 || natts > MaxHeapAttributeNumber)
763 elog(ERROR, "amcreate: from 1 to %d attributes must be specified",
764 MaxHeapAttributeNumber);
766 CheckAttributeNames(tupdesc);
769 * open pg_class and see that the relation doesn't
773 pg_class_desc = heap_openr(RelationRelationName);
775 if (RelationAlreadyExists(pg_class_desc, relname))
777 heap_close(pg_class_desc);
778 elog(ERROR, "amcreate: %s relation already exists", relname);
782 * ok, relation does not already exist so now we
783 * create an uncataloged relation and pull its relation oid
784 * from the newly formed relation descriptor.
786 * Note: The call to heap_create() does all the "real" work
787 * of creating the disk file for the relation.
790 new_rel_desc = heap_create(relname, tupdesc);
791 new_rel_oid = new_rel_desc->rd_att->attrs[0]->attrelid;
794 * since defining a relation also defines a complex type,
795 * we add a new system type corresponding to the new relation.
798 addNewRelationType(relname, new_rel_oid);
801 * now add tuples to pg_attribute for the attributes in
805 AddNewAttributeTuples(new_rel_oid, tupdesc);
808 * now update the information in pg_class.
811 AddPgRelationTuple(pg_class_desc,
817 StoreConstraints(new_rel_desc);
820 * ok, the relation has been cataloged, so close our relations
821 * and return the oid of the newly created relation.
823 * SOMEDAY: fill the STATISTIC relation properly.
826 heap_close(new_rel_desc);
827 heap_close(pg_class_desc);
833 /* ----------------------------------------------------------------
834 * heap_destroy_with_catalog - removes all record of named relation from catalogs
836 * 1) open relation, check for existence, etc.
837 * 2) remove inheritance information
839 * 4) remove pg_class tuple
840 * 5) remove pg_attribute tuples
841 * 6) remove pg_type tuples
842 * 7) RemoveConstraints ()
846 * Except for vital relations, removes relation from
847 * relation catalog, and related attributes from
848 * attribute catalog (needed?). (Anything else?)
850 * get proper relation from relation catalog (if not arg)
851 * check if relation is vital (strcmp()/reltype?)
852 * scan attribute catalog deleting attributes of reldesc
854 * delete relation from relation catalog
855 * (How are the tuples of the relation discarded?)
857 * XXX Must fix to work with indexes.
858 * There may be a better order for doing things.
859 * Problems with destroying a deleted database--cannot create
860 * a struct reldesc without having an open file descriptor.
861 * ----------------------------------------------------------------
864 /* --------------------------------
865 * RelationRemoveInheritance
867 * Note: for now, we cause an exception if relation is a
868 * superclass. Someday, we may want to allow this and merge
869 * the type info into subclass procedures.... this seems like
871 * --------------------------------
874 RelationRemoveInheritance(Relation relation)
876 Relation catalogRelation;
886 catalogRelation = heap_openr(InheritsRelationName);
889 * form a scan key for the subclasses of this class
893 ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_inherits_inhparent,
895 ObjectIdGetDatum(RelationGetRelid(relation)));
897 scan = heap_beginscan(catalogRelation,
904 * if any subclasses exist, then we disallow the deletion.
907 tuple = heap_getnext(scan, 0);
908 if (HeapTupleIsValid(tuple))
911 heap_close(catalogRelation);
913 elog(ERROR, "relation <%d> inherits \"%s\"",
914 ((InheritsTupleForm) GETSTRUCT(tuple))->inhrel,
915 RelationGetRelationName(relation));
919 * If we get here, it means the relation has no subclasses
920 * so we can trash it. First we remove dead INHERITS tuples.
923 entry.sk_attno = Anum_pg_inherits_inhrel;
925 scan = heap_beginscan(catalogRelation,
931 while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
933 heap_delete(catalogRelation, &tuple->t_ctid);
938 heap_close(catalogRelation);
941 * now remove dead IPL tuples
944 catalogRelation = heap_openr(InheritancePrecidenceListRelationName);
946 entry.sk_attno = Anum_pg_ipl_iplrel;
948 scan = heap_beginscan(catalogRelation,
954 while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
955 heap_delete(catalogRelation, &tuple->t_ctid);
958 heap_close(catalogRelation);
961 /* --------------------------------
962 * RelationRemoveIndexes
964 * --------------------------------
967 RelationRemoveIndexes(Relation relation)
969 Relation indexRelation;
974 indexRelation = heap_openr(IndexRelationName);
976 ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_index_indrelid,
978 ObjectIdGetDatum(RelationGetRelid(relation)));
980 scan = heap_beginscan(indexRelation,
986 while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
987 index_destroy(((IndexTupleForm) GETSTRUCT(tuple))->indexrelid);
990 heap_close(indexRelation);
993 /* --------------------------------
994 * DeletePgRelationTuple
996 * --------------------------------
999 DeletePgRelationTuple(Relation rel)
1001 Relation pg_class_desc;
1008 pg_class_desc = heap_openr(RelationRelationName);
1010 tup = SearchSysCacheTupleCopy(RELOID,
1011 ObjectIdGetDatum(rel->rd_att->attrs[0]->attrelid),
1013 if (!HeapTupleIsValid(tup))
1015 heap_close(pg_class_desc);
1016 elog(ERROR, "DeletePgRelationTuple: %s relation nonexistent",
1017 &rel->rd_rel->relname);
1021 * delete the relation tuple from pg_class, and finish up.
1024 heap_delete(pg_class_desc, &tup->t_ctid);
1027 heap_close(pg_class_desc);
1030 /* --------------------------------
1031 * DeletePgAttributeTuples
1033 * --------------------------------
1036 DeletePgAttributeTuples(Relation rel)
1038 Relation pg_attribute_desc;
1046 pg_attribute_desc = heap_openr(AttributeRelationName);
1048 /* -----------------
1049 * Get a write lock _before_ getting the read lock in the scan
1052 RelationSetLockForWrite(pg_attribute_desc);
1054 for (attnum = FirstLowInvalidHeapAttributeNumber + 1;
1055 attnum <= rel->rd_att->natts;
1058 if (HeapTupleIsValid(tup = SearchSysCacheTupleCopy(ATTNUM,
1059 ObjectIdGetDatum(RelationGetRelid(rel)),
1060 Int16GetDatum(attnum),
1063 heap_delete(pg_attribute_desc, &tup->t_ctid);
1069 * Release the write lock
1072 RelationUnsetLockForWrite(pg_attribute_desc);
1073 heap_close(pg_attribute_desc);
1076 /* --------------------------------
1079 * If the user attempts to destroy a relation and there
1080 * exists attributes in other relations of type
1081 * "relation we are deleting", then we have to do something
1082 * special. presently we disallow the destroy.
1083 * --------------------------------
1086 DeletePgTypeTuple(Relation rel)
1088 Relation pg_type_desc;
1089 HeapScanDesc pg_type_scan;
1090 Relation pg_attribute_desc;
1091 HeapScanDesc pg_attribute_scan;
1102 pg_type_desc = heap_openr(TypeRelationName);
1105 * create a scan key to locate the type tuple corresponding
1109 ScanKeyEntryInitialize(&key, 0,
1110 Anum_pg_type_typrelid,
1112 ObjectIdGetDatum(RelationGetRelid(rel)));
1114 pg_type_scan = heap_beginscan(pg_type_desc,
1121 * use heap_getnext() to fetch the pg_type tuple. If this
1122 * tuple is not valid then something's wrong.
1125 tup = heap_getnext(pg_type_scan, 0);
1127 if (!HeapTupleIsValid(tup))
1129 heap_endscan(pg_type_scan);
1130 heap_close(pg_type_desc);
1131 elog(ERROR, "DeletePgTypeTuple: %s type nonexistent",
1132 &rel->rd_rel->relname);
1136 * now scan pg_attribute. if any other relations have
1137 * attributes of the type of the relation we are deleteing
1138 * then we have to disallow the deletion. should talk to
1139 * stonebraker about this. -cim 6/19/90
1142 typoid = tup->t_oid;
1144 pg_attribute_desc = heap_openr(AttributeRelationName);
1146 ScanKeyEntryInitialize(&attkey,
1148 Anum_pg_attribute_atttypid,
1152 pg_attribute_scan = heap_beginscan(pg_attribute_desc,
1159 * try and get a pg_attribute tuple. if we succeed it means
1160 * we can't delete the relation because something depends on
1164 atttup = heap_getnext(pg_attribute_scan, 0);
1166 if (HeapTupleIsValid(atttup))
1168 Oid relid = ((AttributeTupleForm) GETSTRUCT(atttup))->attrelid;
1170 heap_endscan(pg_type_scan);
1171 heap_close(pg_type_desc);
1172 heap_endscan(pg_attribute_scan);
1173 heap_close(pg_attribute_desc);
1175 elog(ERROR, "DeletePgTypeTuple: att of type %s exists in relation %d",
1176 &rel->rd_rel->relname, relid);
1178 heap_endscan(pg_attribute_scan);
1179 heap_close(pg_attribute_desc);
1182 * Ok, it's safe so we delete the relation tuple
1183 * from pg_type and finish up. But first end the scan so that
1184 * we release the read lock on pg_type. -mer 13 Aug 1991
1187 heap_delete(pg_type_desc, &tup->t_ctid);
1189 heap_endscan(pg_type_scan);
1190 heap_close(pg_type_desc);
1193 /* --------------------------------
1194 * heap_destroy_with_catalog
1196 * --------------------------------
1199 heap_destroy_with_catalog(char *relname)
1205 * first open the relation. if the relation does exist,
1206 * heap_openr() returns NULL.
1209 rel = heap_openr(relname);
1211 elog(ERROR, "Relation %s Does Not Exist!", relname);
1213 RelationSetLockForWrite(rel);
1217 * prevent deletion of system relations
1220 if (IsSystemRelationName(RelationGetRelationName(rel)->data))
1221 elog(ERROR, "amdestroy: cannot destroy %s relation",
1222 &rel->rd_rel->relname);
1225 * remove inheritance information
1228 RelationRemoveInheritance(rel);
1231 * remove indexes if necessary
1234 if (rel->rd_rel->relhasindex)
1235 RelationRemoveIndexes(rel);
1238 * remove rules if necessary
1241 if (rel->rd_rules != NULL)
1242 RelationRemoveRules(rid);
1245 if (rel->rd_rel->reltriggers > 0)
1246 RelationRemoveTriggers(rel);
1249 * delete attribute tuples
1252 DeletePgAttributeTuples(rel);
1255 * delete type tuple. here we want to see the effects
1256 * of the deletions we just did, so we use setheapoverride().
1259 setheapoverride(true);
1260 DeletePgTypeTuple(rel);
1261 setheapoverride(false);
1264 * delete relation tuple
1267 DeletePgRelationTuple(rel);
1270 * release dirty buffers of this relation
1272 ReleaseRelationBuffers(rel);
1275 * flush the relation from the relcache
1277 * Does nothing!!! Flushing moved below. - vadim 06/04/97
1278 RelationIdInvalidateRelationCacheByRelationId(rel->rd_id);
1281 RemoveConstraints(rel);
1284 * unlink the relation and finish up.
1287 if (!(rel->rd_istemp) || !(rel->rd_tmpunlinked))
1288 smgrunlink(DEFAULT_SMGR, rel);
1290 rel->rd_tmpunlinked = TRUE;
1292 RelationUnsetLockForWrite(rel);
1296 /* ok - flush the relation from the relcache */
1297 RelationForgetRelation(rid);
1302 * destroy and close temporary relations
1307 heap_destroy(Relation rel)
1309 ReleaseRelationBuffers(rel);
1310 if (!(rel->rd_istemp) || !(rel->rd_tmpunlinked))
1311 smgrunlink(DEFAULT_SMGR, rel);
1312 rel->rd_tmpunlinked = TRUE;
1314 RemoveFromTempRelList(rel);
1318 /**************************************************************
1319 functions to deal with the list of temporary relations
1320 **************************************************************/
1325 initialize temporary relations list
1326 the tempRelList is a list of temporary relations that
1327 are created in the course of the transactions
1328 they need to be destroyed properly at the end of the transactions
1330 MODIFIES the global variable tempRels
1334 malloc is used instead of palloc because we KNOW when we are
1335 going to free these things. Keeps us away from the memory context
1340 InitTempRelList(void)
1344 free(tempRels->rels);
1348 tempRels = (TempRelList *) malloc(sizeof(TempRelList));
1349 tempRels->size = TEMP_REL_LIST_SIZE;
1350 tempRels->rels = (Relation *) malloc(sizeof(Relation) * tempRels->size);
1351 MemSet(tempRels->rels, 0, sizeof(Relation) * tempRels->size);
1356 removes a relation from the TempRelList
1358 MODIFIES the global variable tempRels
1359 we don't really remove it, just mark it as NULL
1360 and DestroyTempRels will look for NULLs
1363 RemoveFromTempRelList(Relation r)
1370 for (i = 0; i < tempRels->num; i++)
1372 if (tempRels->rels[i] == r)
1374 tempRels->rels[i] = NULL;
1381 add a temporary relation to the TempRelList
1383 MODIFIES the global variable tempRels
1386 AddToTempRelList(Relation r)
1391 if (tempRels->num == tempRels->size)
1393 tempRels->size += TEMP_REL_LIST_SIZE;
1394 tempRels->rels = realloc(tempRels->rels,
1395 sizeof(Relation) * tempRels->size);
1397 tempRels->rels[tempRels->num] = r;
1402 go through the tempRels list and destroy each of the relations
1405 DestroyTempRels(void)
1413 for (i = 0; i < tempRels->num; i++)
1415 rel = tempRels->rels[i];
1416 /* rel may be NULL if it has been removed from the list already */
1420 free(tempRels->rels);
1427 StoreAttrDefault(Relation rel, AttrDefault *attrdef)
1429 char str[MAX_PARSE_BUFFER];
1430 char cast[2 * NAMEDATALEN] = {0};
1431 AttributeTupleForm atp = rel->rd_att->attrs[attrdef->adnum - 1];
1432 QueryTreeList *queryTree_list;
1434 List *planTree_list;
1439 MemoryContext oldcxt;
1441 Relation idescs[Num_pg_attrdef_indices];
1444 char nulls[4] = {' ', ' ', ' ', ' '};
1445 extern GlobalMemory CacheCxt;
1448 sprintf(str, "select %s%s from %.*s", attrdef->adsrc, cast,
1449 NAMEDATALEN, rel->rd_rel->relname.data);
1450 setheapoverride(true);
1451 planTree_list = (List *) pg_parse_and_plan(str, NULL, 0, &queryTree_list, None, FALSE);
1452 setheapoverride(false);
1453 query = (Query *) (queryTree_list->qtrees[0]);
1455 if (length(query->rtable) > 1 ||
1456 flatten_tlist(query->targetList) != NIL)
1457 elog(ERROR, "DEFAULT: cannot use attribute(s)");
1458 te = (TargetEntry *) lfirst(query->targetList);
1459 resdom = te->resdom;
1462 if (IsA(expr, Const))
1464 if (((Const *) expr)->consttype != atp->atttypid)
1467 elog(ERROR, "DEFAULT: const type mismatched");
1468 sprintf(cast, ":: %s", typeidTypeName(atp->atttypid));
1472 else if ((exprType(expr) != atp->atttypid)
1473 && !IS_BINARY_COMPATIBLE(exprType(expr), atp->atttypid))
1474 elog(ERROR, "DEFAULT: type mismatched");
1476 adbin = nodeToString(expr);
1477 oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
1478 attrdef->adbin = (char *) palloc(strlen(adbin) + 1);
1479 strcpy(attrdef->adbin, adbin);
1480 (void) MemoryContextSwitchTo(oldcxt);
1483 values[Anum_pg_attrdef_adrelid - 1] = rel->rd_id;
1484 values[Anum_pg_attrdef_adnum - 1] = attrdef->adnum;
1485 values[Anum_pg_attrdef_adbin - 1] = PointerGetDatum(textin(attrdef->adbin));
1486 values[Anum_pg_attrdef_adsrc - 1] = PointerGetDatum(textin(attrdef->adsrc));
1487 adrel = heap_openr(AttrDefaultRelationName);
1488 tuple = heap_formtuple(adrel->rd_att, values, nulls);
1489 CatalogOpenIndices(Num_pg_attrdef_indices, Name_pg_attrdef_indices, idescs);
1490 heap_insert(adrel, tuple);
1491 CatalogIndexInsert(idescs, Num_pg_attrdef_indices, adrel, tuple);
1492 CatalogCloseIndices(Num_pg_attrdef_indices, idescs);
1495 pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
1496 pfree(DatumGetPointer(values[Anum_pg_attrdef_adsrc - 1]));
1502 StoreRelCheck(Relation rel, ConstrCheck *check)
1504 char str[MAX_PARSE_BUFFER];
1505 QueryTreeList *queryTree_list;
1507 List *planTree_list;
1511 MemoryContext oldcxt;
1513 Relation idescs[Num_pg_relcheck_indices];
1516 char nulls[4] = {' ', ' ', ' ', ' '};
1517 extern GlobalMemory CacheCxt;
1519 sprintf(str, "select 1 from %.*s where %s",
1520 NAMEDATALEN, rel->rd_rel->relname.data, check->ccsrc);
1521 setheapoverride(true);
1522 planTree_list = (List *) pg_parse_and_plan(str, NULL, 0, &queryTree_list, None, FALSE);
1523 setheapoverride(false);
1524 query = (Query *) (queryTree_list->qtrees[0]);
1526 if (length(query->rtable) > 1)
1527 elog(ERROR, "CHECK: only relation %.*s can be referenced",
1528 NAMEDATALEN, rel->rd_rel->relname.data);
1530 plan = (Plan *) lfirst(planTree_list);
1533 ccbin = nodeToString(qual);
1534 oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
1535 check->ccbin = (char *) palloc(strlen(ccbin) + 1);
1536 strcpy(check->ccbin, ccbin);
1537 (void) MemoryContextSwitchTo(oldcxt);
1540 values[Anum_pg_relcheck_rcrelid - 1] = rel->rd_id;
1541 values[Anum_pg_relcheck_rcname - 1] = PointerGetDatum(namein(check->ccname));
1542 values[Anum_pg_relcheck_rcbin - 1] = PointerGetDatum(textin(check->ccbin));
1543 values[Anum_pg_relcheck_rcsrc - 1] = PointerGetDatum(textin(check->ccsrc));
1544 rcrel = heap_openr(RelCheckRelationName);
1545 tuple = heap_formtuple(rcrel->rd_att, values, nulls);
1546 CatalogOpenIndices(Num_pg_relcheck_indices, Name_pg_relcheck_indices, idescs);
1547 heap_insert(rcrel, tuple);
1548 CatalogIndexInsert(idescs, Num_pg_relcheck_indices, rcrel, tuple);
1549 CatalogCloseIndices(Num_pg_relcheck_indices, idescs);
1552 pfree(DatumGetPointer(values[Anum_pg_relcheck_rcname - 1]));
1553 pfree(DatumGetPointer(values[Anum_pg_relcheck_rcbin - 1]));
1554 pfree(DatumGetPointer(values[Anum_pg_relcheck_rcsrc - 1]));
1561 StoreConstraints(Relation rel)
1563 TupleConstr *constr = rel->rd_att->constr;
1569 if (constr->num_defval > 0)
1571 for (i = 0; i < constr->num_defval; i++)
1572 StoreAttrDefault(rel, &(constr->defval[i]));
1575 if (constr->num_check > 0)
1577 for (i = 0; i < constr->num_check; i++)
1578 StoreRelCheck(rel, &(constr->check[i]));
1585 RemoveAttrDefault(Relation rel)
1588 HeapScanDesc adscan;
1592 adrel = heap_openr(AttrDefaultRelationName);
1594 ScanKeyEntryInitialize(&key, 0, Anum_pg_attrdef_adrelid,
1595 F_OIDEQ, rel->rd_id);
1597 RelationSetLockForWrite(adrel);
1599 adscan = heap_beginscan(adrel, 0, SnapshotNow, 1, &key);
1601 while (HeapTupleIsValid(tup = heap_getnext(adscan, 0)))
1602 heap_delete(adrel, &tup->t_ctid);
1604 heap_endscan(adscan);
1606 RelationUnsetLockForWrite(adrel);
1612 RemoveRelCheck(Relation rel)
1615 HeapScanDesc rcscan;
1619 rcrel = heap_openr(RelCheckRelationName);
1621 ScanKeyEntryInitialize(&key, 0, Anum_pg_relcheck_rcrelid,
1622 F_OIDEQ, rel->rd_id);
1624 RelationSetLockForWrite(rcrel);
1626 rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key);
1628 while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0)))
1629 heap_delete(rcrel, &tup->t_ctid);
1631 heap_endscan(rcscan);
1633 RelationUnsetLockForWrite(rcrel);
1639 RemoveConstraints(Relation rel)
1641 TupleConstr *constr = rel->rd_att->constr;
1646 if (constr->num_defval > 0)
1647 RemoveAttrDefault(rel);
1649 if (constr->num_check > 0)
1650 RemoveRelCheck(rel);