1 /*-------------------------------------------------------------------------
4 * code to create and destroy POSTGRES heap relations
6 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.127 2000/05/20 23:11:29 tgl Exp $
15 * heap_create() - Create an uncataloged heap relation
16 * heap_create_with_catalog() - Create a cataloged relation
17 * heap_drop_with_catalog() - Removes named relation from catalogs
20 * this code taken from access/heap/create.c, which contains
21 * the old heap_create_with_catalog, amcreate, and amdestroy.
22 * those routines will soon call these routines using the function
24 * just like the poorly named "NewXXX" routines do. The
25 * "New" routines are all going to die soon, once and for all!
28 *-------------------------------------------------------------------------
32 #include "access/heapam.h"
33 #include "access/genam.h"
34 #include "access/xact.h"
35 #include "catalog/catalog.h"
36 #include "catalog/catname.h"
37 #include "catalog/heap.h"
38 #include "catalog/index.h"
39 #include "catalog/indexing.h"
40 #include "catalog/pg_attrdef.h"
41 #include "catalog/pg_description.h"
42 #include "catalog/pg_index.h"
43 #include "catalog/pg_inherits.h"
44 #include "catalog/pg_ipl.h"
45 #include "catalog/pg_proc.h"
46 #include "catalog/pg_relcheck.h"
47 #include "catalog/pg_statistic.h"
48 #include "catalog/pg_type.h"
49 #include "commands/comment.h"
50 #include "commands/trigger.h"
51 #include "miscadmin.h"
52 #include "optimizer/clauses.h"
53 #include "optimizer/planmain.h"
54 #include "optimizer/tlist.h"
55 #include "optimizer/var.h"
56 #include "nodes/makefuncs.h"
57 #include "parser/parse_clause.h"
58 #include "parser/parse_expr.h"
59 #include "parser/parse_relation.h"
60 #include "parser/parse_target.h"
61 #include "rewrite/rewriteRemove.h"
62 #include "storage/smgr.h"
63 #include "tcop/tcopprot.h"
64 #include "utils/builtins.h"
65 #include "utils/catcache.h"
66 #include "utils/portal.h"
67 #include "utils/relcache.h"
68 #include "utils/syscache.h"
69 #include "utils/temprel.h"
72 static void AddNewRelationTuple(Relation pg_class_desc,
73 Relation new_rel_desc, Oid new_rel_oid,
75 char relkind, char *temp_relname);
76 static void AddToNoNameRelList(Relation r);
78 static void DeleteAttributeTuples(Relation rel);
79 static void DeleteRelationTuple(Relation rel);
80 static void DeleteTypeTuple(Relation rel);
81 static void RelationRemoveIndexes(Relation relation);
82 static void RelationRemoveInheritance(Relation relation);
83 static void RemoveFromNoNameRelList(Relation r);
84 static void AddNewRelationType(char *typeName, Oid new_rel_oid);
85 static void StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin,
86 bool updatePgAttribute);
87 static void StoreRelCheck(Relation rel, char *ccname, char *ccbin);
88 static void StoreConstraints(Relation rel);
89 static void RemoveConstraints(Relation rel);
90 static void RemoveStatistics(Relation rel);
93 /* ----------------------------------------------------------------
94 * XXX UGLY HARD CODED BADNESS FOLLOWS XXX
96 * these should all be moved to someplace in the lib/catalog
97 * module, if not obliterated first.
98 * ----------------------------------------------------------------
104 * Should the executor special case these attributes in the future?
105 * Advantage: consume 1/2 the space in the ATTRIBUTE relation.
106 * Disadvantage: having rules to compute values in these tuples may
107 * be more difficult if not impossible.
110 static FormData_pg_attribute a1 = {
111 0xffffffff, {"ctid"}, TIDOID, 0, sizeof(ItemPointerData),
112 SelfItemPointerAttributeNumber, 0, -1, -1, '\0', 'p', '\0', 'i', '\0', '\0'
115 static FormData_pg_attribute a2 = {
116 0xffffffff, {"oid"}, OIDOID, 0, sizeof(Oid),
117 ObjectIdAttributeNumber, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0'
120 static FormData_pg_attribute a3 = {
121 0xffffffff, {"xmin"}, XIDOID, 0, sizeof(TransactionId),
122 MinTransactionIdAttributeNumber, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0'
125 static FormData_pg_attribute a4 = {
126 0xffffffff, {"cmin"}, CIDOID, 0, sizeof(CommandId),
127 MinCommandIdAttributeNumber, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0'
130 static FormData_pg_attribute a5 = {
131 0xffffffff, {"xmax"}, XIDOID, 0, sizeof(TransactionId),
132 MaxTransactionIdAttributeNumber, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0'
135 static FormData_pg_attribute a6 = {
136 0xffffffff, {"cmax"}, CIDOID, 0, sizeof(CommandId),
137 MaxCommandIdAttributeNumber, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0'
140 static Form_pg_attribute HeapAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6};
142 /* ----------------------------------------------------------------
143 * XXX END OF UGLY HARD CODED BADNESS XXX
144 * ----------------------------------------------------------------
147 /* the tempRelList holds
148 the list of temporary uncatalogued relations that are created.
149 these relations should be destroyed at the end of transactions
151 typedef struct tempRelList
153 Relation *rels; /* array of relation descriptors */
154 int num; /* number of temporary relations */
155 int size; /* size of space allocated for the rels
159 #define NONAME_REL_LIST_SIZE 32
161 static TempRelList *tempRels = NULL;
164 /* ----------------------------------------------------------------
165 * heap_create - Create an uncataloged heap relation
167 * Fields relpages, reltuples, reltuples, relkeys, relhistory,
168 * relisindexed, and relkind of rel->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_create is called with "" as the name, then heap_create will create
178 * a temporary name "pg_noname.$PID.$SEQUENCE" for the relation
179 * ----------------------------------------------------------------
182 heap_create(char *relname,
188 static unsigned int uniqueId = 0;
195 int natts = tupDesc->natts;
196 MemoryContext oldcxt;
202 AssertArg(natts > 0);
204 if (relname && !allowSystemTableMods &&
205 IsSystemRelationName(relname) && IsNormalProcessingMode())
207 elog(ERROR, "Illegal class name '%s'"
208 "\n\tThe 'pg_' name prefix is reserved for system catalogs",
213 * switch to the cache context so that we don't lose
214 * allocations at the end of this transaction, I guess.
219 CacheCxt = CreateGlobalMemory("Cache");
221 oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
224 * real ugly stuff to assign the proper relid in the relation
225 * descriptor follows.
228 if (relname && !strcmp(RelationRelationName, relname))
230 relid = RelOid_pg_class;
233 else if (relname && !strcmp(AttributeRelationName, relname))
235 relid = RelOid_pg_attribute;
238 else if (relname && !strcmp(ProcedureRelationName, relname))
240 relid = RelOid_pg_proc;
243 else if (relname && !strcmp(TypeRelationName, relname))
245 relid = RelOid_pg_type;
254 relname = palloc(NAMEDATALEN);
255 snprintf(relname, NAMEDATALEN, "pg_noname.%d.%u",
256 (int) MyProcPid, uniqueId++);
261 /* replace relname of caller */
262 snprintf(relname, NAMEDATALEN, "pg_temp.%d.%u", MyProcPid, uniqueId++);
266 * allocate a new relation descriptor.
269 len = sizeof(RelationData);
271 rel = (Relation) palloc(len);
272 MemSet((char *) rel, 0, len);
273 rel->rd_fd = -1; /* table is not open */
274 rel->rd_unlinked = TRUE; /* table is not created yet */
277 * create a new tuple descriptor from the one passed in
279 rel->rd_att = CreateTupleDescCopyConstr(tupDesc);
282 * nail the reldesc if this is a bootstrap create reln and
283 * we may need it in the cache later on in the bootstrap
284 * process so we don't ever want it kicked out. e.g. pg_attribute!!!
288 rel->rd_isnailed = true;
290 RelationSetReferenceCount(rel, 1);
292 rel->rd_rel = (Form_pg_class) palloc(sizeof *rel->rd_rel);
295 * initialize the fields of our new relation descriptor
298 MemSet((char *) rel->rd_rel, 0, sizeof *rel->rd_rel);
299 strcpy(RelationGetPhysicalRelationName(rel), relname);
300 rel->rd_rel->relkind = RELKIND_UNCATALOGED;
301 rel->rd_rel->relnatts = natts;
303 rel->rd_rel->relchecks = tupDesc->constr->num_check;
305 for (i = 0; i < natts; i++)
306 rel->rd_att->attrs[i]->attrelid = relid;
308 RelationGetRelid(rel) = relid;
312 /* for system relations, set the reltype field here */
313 rel->rd_rel->reltype = relid;
317 * remember if this is a noname relation
320 rel->rd_isnoname = isnoname;
323 * have the storage manager create the relation.
327 /* smgrcreate() is moved to heap_storage_create() */
329 heap_storage_create(rel);
331 RelationRegisterRelation(rel);
333 MemoryContextSwitchTo(oldcxt);
336 * add all noname relations to the tempRels list so they can be
337 * properly disposed of at the end of transaction
340 AddToNoNameRelList(rel);
346 heap_storage_create(Relation rel)
348 bool smgrcall = false;
350 if (rel->rd_unlinked)
352 rel->rd_fd = (File) smgrcreate(DEFAULT_SMGR, rel);
353 rel->rd_unlinked = FALSE;
359 /* ----------------------------------------------------------------
360 * heap_create_with_catalog - Create a cataloged relation
362 * this is done in 6 steps:
364 * 1) CheckAttributeNames() is used to make certain the tuple
365 * descriptor contains a valid set of attribute names
367 * 2) pg_class is opened and RelationFindRelid()
368 * performs a scan to ensure that no relation with the
369 * same name already exists.
371 * 3) heap_create_with_catalog() is called to create the new relation
374 * 4) TypeDefine() is called to define a new type corresponding
375 * to the new relation.
377 * 5) AddNewAttributeTuples() is called to register the
378 * new relation's schema in pg_attribute.
380 * 6) AddNewRelationTuple() is called to register the
381 * relation itself in the catalogs.
383 * 7) StoreConstraints is called () - vadim 08/22/97
385 * 8) the relations are closed and the new relation's oid
389 * A new relation is inserted into the RELATION relation
390 * with the specified attribute(s) (newly inserted into
391 * the ATTRIBUTE relation). How does concurrency control
392 * work? Is it automatic now? Expects the caller to have
393 * attname, atttypid, atttyparg, attproc, and attlen domains filled.
394 * Create fills the attnum domains sequentually from zero,
395 * fills the attdisbursion domains with zeros, and fills the
396 * attrelid fields with the relid.
398 * scan relation catalog for name conflict
399 * scan type catalog for typids (if not arg)
400 * create and insert attribute(s) into attribute catalog
401 * create new relation
402 * insert new relation into attribute catalog
404 * Should coordinate with heap_create_with_catalog(). Either
405 * it should not be called or there should be a way to prevent
406 * the relation from being removed at the end of the
407 * transaction if it is successful ('u'/'r' may be enough).
408 * Also, if the transaction does not commit, then the
409 * relation should be removed.
411 * XXX amcreate ignores "off" when inserting (for now).
412 * XXX amcreate (like the other utilities) needs to understand indexes.
414 * ----------------------------------------------------------------
417 /* --------------------------------
418 * CheckAttributeNames
420 * this is used to make certain the tuple descriptor contains a
421 * valid set of attribute names. a problem simply generates
422 * elog(ERROR) which aborts the current transaction.
423 * --------------------------------
426 CheckAttributeNames(TupleDesc tupdesc)
430 int natts = tupdesc->natts;
433 * first check for collision with system attribute names
436 * also, warn user if attribute to be created has
437 * an unknown typid (usually as a result of a 'retrieve into'
440 for (i = 0; i < natts; i++)
442 for (j = 0; j < (int) (sizeof(HeapAtt) / sizeof(HeapAtt[0])); j++)
444 if (nameeq(&(HeapAtt[j]->attname),
445 &(tupdesc->attrs[i]->attname)))
447 elog(ERROR, "Attribute '%s' has a name conflict"
448 "\n\tName matches an existing system attribute",
449 NameStr(HeapAtt[j]->attname));
452 if (tupdesc->attrs[i]->atttypid == UNKNOWNOID)
454 elog(NOTICE, "Attribute '%s' has an unknown type"
455 "\n\tRelation created; continue",
456 NameStr(tupdesc->attrs[i]->attname));
461 * next check for repeated attribute names
464 for (i = 1; i < natts; i++)
466 for (j = 0; j < i; j++)
468 if (nameeq(&(tupdesc->attrs[j]->attname),
469 &(tupdesc->attrs[i]->attname)))
471 elog(ERROR, "Attribute '%s' is repeated",
472 NameStr(tupdesc->attrs[j]->attname));
478 /* --------------------------------
481 * Find any existing relation of the given name.
482 * --------------------------------
485 RelnameFindRelid(const char *relname)
491 * If this is not bootstrap (initdb) time, use the catalog index on
494 if (!IsBootstrapProcessingMode())
496 tuple = SearchSysCacheTuple(RELNAME,
497 PointerGetDatum(relname),
499 if (HeapTupleIsValid(tuple))
500 relid = tuple->t_data->t_oid;
506 Relation pg_class_desc;
508 HeapScanDesc pg_class_scan;
510 pg_class_desc = heap_openr(RelationRelationName, AccessShareLock);
513 * At bootstrap time, we have to do this the hard way. Form the
517 ScanKeyEntryInitialize(&key,
519 (AttrNumber) Anum_pg_class_relname,
520 (RegProcedure) F_NAMEEQ,
527 pg_class_scan = heap_beginscan(pg_class_desc,
534 * get a tuple. if the tuple is NULL then it means we
535 * didn't find an existing relation.
538 tuple = heap_getnext(pg_class_scan, 0);
540 if (HeapTupleIsValid(tuple))
541 relid = tuple->t_data->t_oid;
545 heap_endscan(pg_class_scan);
547 heap_close(pg_class_desc, AccessShareLock);
552 /* --------------------------------
553 * AddNewAttributeTuples
555 * this registers the new relation's schema by adding
556 * tuples to pg_attribute.
557 * --------------------------------
560 AddNewAttributeTuples(Oid new_rel_oid,
563 Form_pg_attribute *dpp;
568 Relation idescs[Num_pg_attr_indices];
569 int natts = tupdesc->natts;
575 rel = heap_openr(AttributeRelationName, RowExclusiveLock);
578 * Check if we have any indices defined on pg_attribute.
581 hasindex = RelationGetForm(rel)->relhasindex;
583 CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
586 * initialize tuple descriptor.
592 * first we add the user attributes..
595 dpp = tupdesc->attrs;
596 for (i = 0; i < natts; i++)
598 (*dpp)->attrelid = new_rel_oid;
599 (*dpp)->attdisbursion = 0;
601 tup = heap_addheader(Natts_pg_attribute,
602 ATTRIBUTE_TUPLE_SIZE,
605 heap_insert(rel, tup);
608 CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
615 * next we add the system attributes..
619 for (i = 0; i < -1 - FirstLowInvalidHeapAttributeNumber; i++)
621 (*dpp)->attrelid = new_rel_oid;
622 /* (*dpp)->attdisbursion = 0; unneeded */
624 tup = heap_addheader(Natts_pg_attribute,
625 ATTRIBUTE_TUPLE_SIZE,
628 heap_insert(rel, tup);
631 CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
637 heap_close(rel, RowExclusiveLock);
640 * close pg_attribute indices
643 CatalogCloseIndices(Num_pg_attr_indices, idescs);
646 /* --------------------------------
647 * AddNewRelationTuple
649 * this registers the new relation in the catalogs by
650 * adding a tuple to pg_class.
651 * --------------------------------
654 AddNewRelationTuple(Relation pg_class_desc,
655 Relation new_rel_desc,
661 Form_pg_class new_rel_reltup;
663 Relation idescs[Num_pg_class_indices];
666 * first we munge some of the information in our
667 * uncataloged relation's relation descriptor.
670 new_rel_reltup = new_rel_desc->rd_rel;
673 * Here we insert bogus estimates of the size of the new relation.
674 * In reality, of course, the new relation has 0 tuples and pages,
675 * and if we were tracking these statistics accurately then we'd
676 * set the fields that way. But at present the stats will be updated
677 * only by VACUUM or CREATE INDEX, and the user might insert a lot of
678 * tuples before he gets around to doing either of those. So, instead
679 * of saying the relation is empty, we insert guesstimates. The point
680 * is to keep the optimizer from making really stupid choices on
681 * never-yet-vacuumed tables; so the estimates need only be large
682 * enough to discourage the optimizer from using nested-loop plans.
683 * With this hack, nested-loop plans will be preferred only after
684 * the table has been proven to be small by VACUUM or CREATE INDEX.
685 * Maintaining the stats on-the-fly would solve the problem more cleanly,
686 * but the overhead of that would likely cost more than it'd save.
687 * (NOTE: CREATE INDEX inserts the same bogus estimates if it finds the
688 * relation has 0 rows and pages. See index.c.)
691 new_rel_reltup->relpages = 10; /* bogus estimates */
692 new_rel_reltup->reltuples = 1000;
694 new_rel_reltup->relowner = GetUserId();
695 new_rel_reltup->relkind = relkind;
696 new_rel_reltup->relnatts = natts;
699 * now form a tuple to add to pg_class
700 * XXX Natts_pg_class_fixed is a hack - see pg_class.h
703 tup = heap_addheader(Natts_pg_class_fixed,
705 (char *) new_rel_reltup);
706 tup->t_data->t_oid = new_rel_oid;
709 * finally insert the new tuple and free it.
711 heap_insert(pg_class_desc, tup);
714 create_temp_relation(temp_relname, tup);
716 if (!IsIgnoringSystemIndexes())
720 * First, open the catalog indices and insert index tuples for the
723 CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
724 CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class_desc, tup);
725 CatalogCloseIndices(Num_pg_class_indices, idescs);
732 /* --------------------------------
733 * AddNewRelationType -
735 * define a complex type corresponding to the new relation
736 * --------------------------------
739 AddNewRelationType(char *typeName, Oid new_rel_oid)
744 * The sizes are set to oid size because it makes implementing sets
745 * MUCH easier, and no one (we hope) uses these fields to figure out
746 * how much space to allocate for the type. An oid is the type used
747 * for a set definition. When a user requests a set, what they
748 * actually get is the oid of a tuple in the pg_proc catalog, so the
749 * size of the "set" is the size of an oid. Similarly, byval being
750 * true makes sets much easier, and it isn't used by anything else.
751 * Note the assumption that OIDs are the same size as int4s.
753 new_type_oid = TypeCreate(typeName, /* type name */
754 new_rel_oid, /* relation oid */
755 typeLen(typeidType(OIDOID)), /* internal size */
756 typeLen(typeidType(OIDOID)), /* external size */
757 'c', /* type-type (catalog) */
758 ',', /* default array delimiter */
759 "int4in", /* input procedure */
760 "int4out", /* output procedure */
761 "int4in", /* receive procedure */
762 "int4out", /* send procedure */
763 NULL, /* array element type - irrelevent */
764 "-", /* default type value */
765 (bool) 1, /* passed by value */
766 'i'); /* default alignment */
769 /* --------------------------------
770 * heap_create_with_catalog
772 * creates a new cataloged relation. see comments above.
773 * --------------------------------
776 heap_create_with_catalog(char *relname,
781 Relation pg_class_desc;
782 Relation new_rel_desc;
784 int natts = tupdesc->natts;
785 char *temp_relname = NULL;
791 Assert(IsNormalProcessingMode() || IsBootstrapProcessingMode());
792 if (natts <= 0 || natts > MaxHeapAttributeNumber)
793 elog(ERROR, "Number of attributes is out of range"
794 "\n\tFrom 1 to %d attributes may be specified",
795 MaxHeapAttributeNumber);
797 CheckAttributeNames(tupdesc);
799 /* temp tables can mask non-temp tables */
800 if ((!istemp && RelnameFindRelid(relname)) ||
801 (istemp && get_temp_rel_by_username(relname) != NULL))
802 elog(ERROR, "Relation '%s' already exists", relname);
804 /* save user relation name because heap_create changes it */
807 temp_relname = pstrdup(relname); /* save original value */
808 relname = palloc(NAMEDATALEN);
809 strcpy(relname, temp_relname); /* heap_create will change this */
813 * get_temp_rel_by_username() couldn't check the simultaneous
814 * creation. Uniqueness will be really checked by unique
815 * indexes of system tables but we couldn't check it here.
816 * We have to pospone to create the disk file for this
818 * Another boolean parameter "storage_create" was added
819 * to heap_create() function. If the parameter is false
820 * heap_create() only registers an uncataloged relation
821 * to relation cache and heap_storage_create() should be
823 * We could pull its relation oid from the newly formed
824 * relation descriptor.
826 * Note: The call to heap_create() changes relname for
827 * noname and temp tables.
828 * The call to heap_storage_create() does all the "real"
829 * work of creating the disk file for the relation.
832 new_rel_desc = heap_create(relname, tupdesc, false, istemp, false);
834 new_rel_oid = new_rel_desc->rd_att->attrs[0]->attrelid;
837 * since defining a relation also defines a complex type,
838 * we add a new system type corresponding to the new relation.
841 AddNewRelationType(relname, new_rel_oid);
844 * now add tuples to pg_attribute for the attributes in
848 AddNewAttributeTuples(new_rel_oid, tupdesc);
851 * now update the information in pg_class.
854 pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock);
856 AddNewRelationTuple(pg_class_desc,
863 StoreConstraints(new_rel_desc);
872 * We create the disk file for this relation here
874 heap_storage_create(new_rel_desc);
876 * ok, the relation has been cataloged, so close our relations
877 * and return the oid of the newly created relation.
879 * SOMEDAY: fill the STATISTIC relation properly.
882 heap_close(new_rel_desc, NoLock); /* do not unlock till end of xact */
883 heap_close(pg_class_desc, RowExclusiveLock);
889 /* ----------------------------------------------------------------
890 * heap_drop_with_catalog - removes all record of named relation from catalogs
892 * 1) open relation, check for existence, etc.
893 * 2) remove inheritance information
895 * 4) remove pg_class tuple
896 * 5) remove pg_attribute tuples and related descriptions
897 * 6) remove pg_description tuples
898 * 7) remove pg_type tuples
899 * 8) RemoveConstraints ()
903 * Except for vital relations, removes relation from
904 * relation catalog, and related attributes from
905 * attribute catalog (needed?). (Anything else?)
907 * get proper relation from relation catalog (if not arg)
908 * check if relation is vital (strcmp()/reltype?)
909 * scan attribute catalog deleting attributes of reldesc
911 * delete relation from relation catalog
912 * (How are the tuples of the relation discarded?)
914 * XXX Must fix to work with indexes.
915 * There may be a better order for doing things.
916 * Problems with destroying a deleted database--cannot create
917 * a struct reldesc without having an open file descriptor.
918 * ----------------------------------------------------------------
921 /* --------------------------------
922 * RelationRemoveInheritance
924 * Note: for now, we cause an exception if relation is a
925 * superclass. Someday, we may want to allow this and merge
926 * the type info into subclass procedures.... this seems like
928 * --------------------------------
931 RelationRemoveInheritance(Relation relation)
933 Relation catalogRelation;
943 catalogRelation = heap_openr(InheritsRelationName, RowExclusiveLock);
946 * form a scan key for the subclasses of this class
950 ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_inherits_inhparent,
952 ObjectIdGetDatum(RelationGetRelid(relation)));
954 scan = heap_beginscan(catalogRelation,
961 * if any subclasses exist, then we disallow the deletion.
964 tuple = heap_getnext(scan, 0);
965 if (HeapTupleIsValid(tuple))
967 Oid subclass = ((Form_pg_inherits) GETSTRUCT(tuple))->inhrelid;
970 heap_close(catalogRelation, RowExclusiveLock);
972 elog(ERROR, "Relation '%u' inherits '%s'",
973 subclass, RelationGetRelationName(relation));
978 * If we get here, it means the relation has no subclasses
979 * so we can trash it. First we remove dead INHERITS tuples.
982 entry.sk_attno = Anum_pg_inherits_inhrelid;
984 scan = heap_beginscan(catalogRelation,
990 while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
992 heap_delete(catalogRelation, &tuple->t_self, NULL);
997 heap_close(catalogRelation, RowExclusiveLock);
1000 * now remove dead IPL tuples
1003 catalogRelation = heap_openr(InheritancePrecidenceListRelationName,
1006 entry.sk_attno = Anum_pg_ipl_iplrelid;
1008 scan = heap_beginscan(catalogRelation,
1014 while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
1015 heap_delete(catalogRelation, &tuple->t_self, NULL);
1018 heap_close(catalogRelation, RowExclusiveLock);
1021 /* --------------------------------
1022 * RelationRemoveIndexes
1024 * --------------------------------
1027 RelationRemoveIndexes(Relation relation)
1029 Relation indexRelation;
1034 indexRelation = heap_openr(IndexRelationName, RowExclusiveLock);
1036 ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_index_indrelid,
1038 ObjectIdGetDatum(RelationGetRelid(relation)));
1040 scan = heap_beginscan(indexRelation,
1046 while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
1047 index_drop(((Form_pg_index) GETSTRUCT(tuple))->indexrelid);
1050 heap_close(indexRelation, RowExclusiveLock);
1053 /* --------------------------------
1054 * DeleteRelationTuple
1056 * --------------------------------
1059 DeleteRelationTuple(Relation rel)
1061 Relation pg_class_desc;
1068 pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock);
1070 tup = SearchSysCacheTupleCopy(RELOID,
1071 ObjectIdGetDatum(rel->rd_id),
1073 if (!HeapTupleIsValid(tup))
1075 heap_close(pg_class_desc, RowExclusiveLock);
1076 elog(ERROR, "Relation '%s' does not exist",
1077 RelationGetRelationName(rel));
1081 * delete the relation tuple from pg_class, and finish up.
1084 heap_delete(pg_class_desc, &tup->t_self, NULL);
1085 heap_freetuple(tup);
1087 heap_close(pg_class_desc, RowExclusiveLock);
1090 /* --------------------------------
1091 * RelationTruncateIndexes - This routine is used to truncate all
1092 * indices associated with the heap relation to zero tuples.
1093 * The routine will truncate and then reconstruct the indices on
1094 * the relation specified by the heapRelation parameter.
1095 * --------------------------------
1098 RelationTruncateIndexes(Relation heapRelation)
1100 Relation indexRelation,
1104 HeapTuple indexTuple,
1107 Form_pg_index index;
1112 Node *oldPred = NULL;
1114 List *cnfPred = NULL;
1115 AttrNumber *attributeNumberA;
1116 FuncIndexInfo fInfo,
1122 heapId = RelationGetRelid(heapRelation);
1124 /* Scan pg_index to find indexes on heapRelation */
1126 indexRelation = heap_openr(IndexRelationName, AccessShareLock);
1127 ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indrelid, F_OIDEQ,
1128 ObjectIdGetDatum(heapId));
1129 scan = heap_beginscan(indexRelation, false, SnapshotNow, 1, &entry);
1130 while (HeapTupleIsValid(indexTuple = heap_getnext(scan, 0)))
1134 * For each index, fetch index attributes so we can apply
1137 index = (Form_pg_index) GETSTRUCT(indexTuple);
1138 indexId = index->indexrelid;
1139 procId = index->indproc;
1141 for (i = 0; i < INDEX_MAX_KEYS; i++)
1143 if (index->indkey[i] == InvalidAttrNumber)
1146 numberOfAttributes = i;
1148 /* If a valid where predicate, compute predicate Node */
1149 if (VARSIZE(&index->indpred) != 0)
1151 predString = fmgr(F_TEXTOUT, &index->indpred);
1152 oldPred = stringToNode(predString);
1155 predInfo = (PredInfo *) palloc(sizeof(PredInfo));
1156 predInfo->pred = (Node *) cnfPred;
1157 predInfo->oldPred = oldPred;
1159 /* Assign Index keys to attributes array */
1160 attributeNumberA = (AttrNumber *) palloc(numberOfAttributes *
1161 sizeof(AttrNumber));
1162 for (i = 0; i < numberOfAttributes; i++)
1163 attributeNumberA[i] = index->indkey[i];
1165 /* If this is a procedural index, initialize our FuncIndexInfo */
1166 if (procId != InvalidOid)
1169 FIsetnArgs(funcInfo, numberOfAttributes);
1170 procTuple = SearchSysCacheTuple(PROCOID, ObjectIdGetDatum(procId),
1172 if (!HeapTupleIsValid(procTuple))
1173 elog(ERROR, "RelationTruncateIndexes: index procedure not found");
1174 namecpy(&(funcInfo->funcName),
1175 &(((Form_pg_proc) GETSTRUCT(procTuple))->proname));
1176 FIsetProcOid(funcInfo, procTuple->t_data->t_oid);
1179 /* Fetch the classTuple associated with this index */
1180 classTuple = SearchSysCacheTupleCopy(RELOID, ObjectIdGetDatum(indexId),
1182 if (!HeapTupleIsValid(classTuple))
1183 elog(ERROR, "RelationTruncateIndexes: index access method not found");
1184 accessMethodId = ((Form_pg_class) GETSTRUCT(classTuple))->relam;
1186 /* Open our index relation */
1187 currentIndex = index_open(indexId);
1188 if (currentIndex == NULL)
1189 elog(ERROR, "RelationTruncateIndexes: can't open index relation");
1191 /* Obtain exclusive lock on it, just to be sure */
1192 LockRelation(currentIndex, AccessExclusiveLock);
1195 * Release any buffers associated with this index. If they're
1196 * dirty, they're just dropped without bothering to flush to disk.
1198 ReleaseRelationBuffers(currentIndex);
1200 /* Now truncate the actual data and set blocks to zero */
1201 smgrtruncate(DEFAULT_SMGR, currentIndex, 0);
1202 currentIndex->rd_nblocks = 0;
1204 /* Initialize the index and rebuild */
1205 InitIndexStrategy(numberOfAttributes, currentIndex, accessMethodId);
1206 index_build(heapRelation, currentIndex, numberOfAttributes,
1207 attributeNumberA, 0, NULL, funcInfo, predInfo);
1210 * index_build will close both the heap and index relations (but
1211 * not give up the locks we hold on them). That's fine for the
1212 * index, but we need to open the heap again. We need no new
1213 * lock, since this backend still has the exclusive lock grabbed
1216 heapRelation = heap_open(heapId, NoLock);
1217 Assert(heapRelation != NULL);
1220 /* Complete the scan and close pg_index */
1222 heap_close(indexRelation, AccessShareLock);
1225 /* ----------------------------
1228 * This routine is used to truncate the data from the
1229 * storage manager of any data within the relation handed
1231 * ----------------------------
1235 heap_truncate(char *relname)
1240 /* Open relation for processing, and grab exclusive access on it. */
1242 rel = heap_openr(relname, AccessExclusiveLock);
1243 rid = RelationGetRelid(rel);
1246 * TRUNCATE TABLE within a transaction block is dangerous, because
1247 * if the transaction is later rolled back we have no way to
1248 * undo truncation of the relation's physical file. For now, allow it
1249 * but emit a warning message.
1250 * Someday we might want to consider postponing the physical truncate
1251 * until transaction commit, but that's a lot of work...
1252 * The only case that actually works right is for relations created
1253 * in the current transaction, since the post-abort state would be that
1254 * they don't exist anyway. So, no warning in that case.
1257 if (IsTransactionBlock() && !rel->rd_myxactonly)
1258 elog(NOTICE, "Caution: TRUNCATE TABLE cannot be rolled back, so don't abort now");
1261 * Release any buffers associated with this relation. If they're
1262 * dirty, they're just dropped without bothering to flush to disk.
1265 ReleaseRelationBuffers(rel);
1267 /* Now truncate the actual data and set blocks to zero */
1269 smgrtruncate(DEFAULT_SMGR, rel, 0);
1270 rel->rd_nblocks = 0;
1272 /* If this relation has indexes, truncate the indexes too */
1273 RelationTruncateIndexes(rel);
1276 * Close the relation, but keep exclusive lock on it until commit.
1278 heap_close(rel, NoLock);
1281 * Is this really necessary?
1283 RelationForgetRelation(rid);
1287 /* --------------------------------
1288 * DeleteAttributeTuples
1290 * --------------------------------
1293 DeleteAttributeTuples(Relation rel)
1295 Relation pg_attribute_desc;
1303 pg_attribute_desc = heap_openr(AttributeRelationName, RowExclusiveLock);
1305 for (attnum = FirstLowInvalidHeapAttributeNumber + 1;
1306 attnum <= rel->rd_att->natts;
1309 if (HeapTupleIsValid(tup = SearchSysCacheTupleCopy(ATTNUM,
1310 ObjectIdGetDatum(RelationGetRelid(rel)),
1311 Int16GetDatum(attnum),
1315 /*** Delete any comments associated with this attribute ***/
1317 DeleteComments(tup->t_data->t_oid);
1319 heap_delete(pg_attribute_desc, &tup->t_self, NULL);
1320 heap_freetuple(tup);
1325 heap_close(pg_attribute_desc, RowExclusiveLock);
1328 /* --------------------------------
1331 * If the user attempts to destroy a relation and there
1332 * exists attributes in other relations of type
1333 * "relation we are deleting", then we have to do something
1334 * special. presently we disallow the destroy.
1335 * --------------------------------
1338 DeleteTypeTuple(Relation rel)
1340 Relation pg_type_desc;
1341 HeapScanDesc pg_type_scan;
1342 Relation pg_attribute_desc;
1343 HeapScanDesc pg_attribute_scan;
1354 pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
1357 * create a scan key to locate the type tuple corresponding
1361 ScanKeyEntryInitialize(&key, 0,
1362 Anum_pg_type_typrelid,
1364 ObjectIdGetDatum(RelationGetRelid(rel)));
1366 pg_type_scan = heap_beginscan(pg_type_desc,
1373 * use heap_getnext() to fetch the pg_type tuple. If this
1374 * tuple is not valid then something's wrong.
1377 tup = heap_getnext(pg_type_scan, 0);
1379 if (!HeapTupleIsValid(tup))
1381 heap_endscan(pg_type_scan);
1382 heap_close(pg_type_desc, RowExclusiveLock);
1383 elog(ERROR, "DeleteTypeTuple: %s type nonexistent",
1384 RelationGetRelationName(rel));
1388 * now scan pg_attribute. if any other relations have
1389 * attributes of the type of the relation we are deleteing
1390 * then we have to disallow the deletion. should talk to
1391 * stonebraker about this. -cim 6/19/90
1394 typoid = tup->t_data->t_oid;
1396 pg_attribute_desc = heap_openr(AttributeRelationName, RowExclusiveLock);
1398 ScanKeyEntryInitialize(&attkey,
1400 Anum_pg_attribute_atttypid,
1404 pg_attribute_scan = heap_beginscan(pg_attribute_desc,
1411 * try and get a pg_attribute tuple. if we succeed it means
1412 * we can't delete the relation because something depends on
1416 atttup = heap_getnext(pg_attribute_scan, 0);
1418 if (HeapTupleIsValid(atttup))
1420 Oid relid = ((Form_pg_attribute) GETSTRUCT(atttup))->attrelid;
1422 heap_endscan(pg_attribute_scan);
1423 heap_close(pg_attribute_desc, RowExclusiveLock);
1424 heap_endscan(pg_type_scan);
1425 heap_close(pg_type_desc, RowExclusiveLock);
1427 elog(ERROR, "DeleteTypeTuple: att of type %s exists in relation %u",
1428 RelationGetRelationName(rel), relid);
1430 heap_endscan(pg_attribute_scan);
1431 heap_close(pg_attribute_desc, RowExclusiveLock);
1434 * Ok, it's safe so we delete the relation tuple
1435 * from pg_type and finish up. But first end the scan so that
1436 * we release the read lock on pg_type. -mer 13 Aug 1991
1440 heap_delete(pg_type_desc, &tup->t_self, NULL);
1442 heap_endscan(pg_type_scan);
1443 heap_close(pg_type_desc, RowExclusiveLock);
1446 /* --------------------------------
1447 * heap_drop_with_catalog
1449 * --------------------------------
1452 heap_drop_with_catalog(const char *relname)
1456 bool istemp = (get_temp_rel_by_username(relname) != NULL);
1459 * Open and lock the relation.
1462 rel = heap_openr(relname, AccessExclusiveLock);
1463 rid = RelationGetRelid(rel);
1466 * prevent deletion of system relations
1469 /* allow temp of pg_class? Guess so. */
1470 if (!istemp && !allowSystemTableMods &&
1471 IsSystemRelationName(RelationGetRelationName(rel)))
1472 elog(ERROR, "System relation '%s' cannot be destroyed",
1473 RelationGetRelationName(rel));
1476 * DROP TABLE within a transaction block is dangerous, because
1477 * if the transaction is later rolled back there will be no way to
1478 * undo the unlink of the relation's physical file. For now, allow it
1479 * but emit a warning message.
1480 * Someday we might want to consider postponing the physical unlink
1481 * until transaction commit, but that's a lot of work...
1482 * The only case that actually works right is for relations created
1483 * in the current transaction, since the post-abort state would be that
1484 * they don't exist anyway. So, no warning in that case.
1487 if (IsTransactionBlock() && !rel->rd_myxactonly)
1488 elog(NOTICE, "Caution: DROP TABLE cannot be rolled back, so don't abort now");
1491 * remove inheritance information
1494 RelationRemoveInheritance(rel);
1497 * remove indexes if necessary
1500 /* should ignore relhasindex */
1501 RelationRemoveIndexes(rel);
1504 * remove rules if necessary
1507 if (rel->rd_rules != NULL)
1508 RelationRemoveRules(rid);
1511 RelationRemoveTriggers(rel);
1514 * delete attribute tuples
1517 DeleteAttributeTuples(rel);
1520 * delete comments, statistics, and constraints
1523 DeleteComments(RelationGetRelid(rel));
1525 RemoveStatistics(rel);
1527 RemoveConstraints(rel);
1533 DeleteTypeTuple(rel);
1536 * delete relation tuple
1539 DeleteRelationTuple(rel);
1542 * release dirty buffers of this relation; don't bother to write them
1544 ReleaseRelationBuffers(rel);
1547 * unlink the relation's physical file and finish up.
1550 if (!(rel->rd_isnoname) || !(rel->rd_unlinked))
1551 smgrunlink(DEFAULT_SMGR, rel);
1553 rel->rd_unlinked = TRUE;
1556 * Close relcache entry, but *keep* AccessExclusiveLock on the
1557 * relation until transaction commit. This ensures no one else will
1558 * try to do something with the doomed relation.
1560 heap_close(rel, NoLock);
1563 * flush the relation from the relcache
1566 RelationForgetRelation(rid);
1569 remove_temp_relation(rid);
1574 * destroy and close temporary relations
1579 heap_drop(Relation rel)
1581 ReleaseRelationBuffers(rel);
1582 if (!(rel->rd_isnoname) || !(rel->rd_unlinked))
1583 smgrunlink(DEFAULT_SMGR, rel);
1584 rel->rd_unlinked = TRUE;
1585 heap_close(rel, NoLock);
1586 RemoveFromNoNameRelList(rel);
1590 /**************************************************************
1591 functions to deal with the list of temporary relations
1592 **************************************************************/
1597 initialize temporary relations list
1598 the tempRelList is a list of temporary relations that
1599 are created in the course of the transactions
1600 they need to be destroyed properly at the end of the transactions
1602 MODIFIES the global variable tempRels
1606 malloc is used instead of palloc because we KNOW when we are
1607 going to free these things. Keeps us away from the memory context
1612 InitNoNameRelList(void)
1616 free(tempRels->rels);
1620 tempRels = (TempRelList *) malloc(sizeof(TempRelList));
1621 tempRels->size = NONAME_REL_LIST_SIZE;
1622 tempRels->rels = (Relation *) malloc(sizeof(Relation) * tempRels->size);
1623 MemSet(tempRels->rels, 0, sizeof(Relation) * tempRels->size);
1628 removes a relation from the TempRelList
1630 MODIFIES the global variable tempRels
1631 we don't really remove it, just mark it as NULL
1632 and DropNoNameRels will look for NULLs
1635 RemoveFromNoNameRelList(Relation r)
1642 for (i = 0; i < tempRels->num; i++)
1644 if (tempRels->rels[i] == r)
1646 tempRels->rels[i] = NULL;
1653 add a temporary relation to the TempRelList
1655 MODIFIES the global variable tempRels
1658 AddToNoNameRelList(Relation r)
1663 if (tempRels->num == tempRels->size)
1665 tempRels->size += NONAME_REL_LIST_SIZE;
1666 tempRels->rels = realloc(tempRels->rels,
1667 sizeof(Relation) * tempRels->size);
1669 tempRels->rels[tempRels->num] = r;
1674 go through the tempRels list and destroy each of the relations
1677 DropNoNameRels(void)
1685 for (i = 0; i < tempRels->num; i++)
1687 rel = tempRels->rels[i];
1688 /* rel may be NULL if it has been removed from the list already */
1692 free(tempRels->rels);
1698 * Store a default expression for column attnum of relation rel.
1699 * The expression must be presented as a nodeToString() string.
1700 * If updatePgAttribute is true, update the pg_attribute entry
1701 * for the column to show that a default exists.
1704 StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin,
1705 bool updatePgAttribute)
1711 Relation idescs[Num_pg_attrdef_indices];
1714 static char nulls[4] = {' ', ' ', ' ', ' '};
1716 Relation attridescs[Num_pg_attr_indices];
1718 Form_pg_attribute attStruct;
1721 * Need to construct source equivalent of given node-string.
1723 expr = stringToNode(adbin);
1726 * deparse_expression needs a RangeTblEntry list, so make one
1728 rte = makeNode(RangeTblEntry);
1729 rte->relname = RelationGetRelationName(rel);
1730 #ifndef DISABLE_EREF
1731 rte->ref = makeNode(Attr);
1732 rte->ref->relname = RelationGetRelationName(rel);
1734 rte->relid = RelationGetRelid(rel);
1736 rte->inFromCl = true;
1737 rte->skipAcl = false;
1738 adsrc = deparse_expression(expr, lcons(lcons(rte, NIL), NIL), false);
1740 values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
1741 values[Anum_pg_attrdef_adnum - 1] = attnum;
1742 values[Anum_pg_attrdef_adbin - 1] = PointerGetDatum(textin(adbin));
1743 values[Anum_pg_attrdef_adsrc - 1] = PointerGetDatum(textin(adsrc));
1744 adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
1745 tuple = heap_formtuple(adrel->rd_att, values, nulls);
1746 heap_insert(adrel, tuple);
1747 CatalogOpenIndices(Num_pg_attrdef_indices, Name_pg_attrdef_indices,
1749 CatalogIndexInsert(idescs, Num_pg_attrdef_indices, adrel, tuple);
1750 CatalogCloseIndices(Num_pg_attrdef_indices, idescs);
1751 heap_close(adrel, RowExclusiveLock);
1753 pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
1754 pfree(DatumGetPointer(values[Anum_pg_attrdef_adsrc - 1]));
1755 heap_freetuple(tuple);
1758 if (!updatePgAttribute)
1759 return; /* done if pg_attribute is OK */
1761 attrrel = heap_openr(AttributeRelationName, RowExclusiveLock);
1762 atttup = SearchSysCacheTupleCopy(ATTNUM,
1763 ObjectIdGetDatum(RelationGetRelid(rel)),
1764 (Datum) attnum, 0, 0);
1765 if (!HeapTupleIsValid(atttup))
1766 elog(ERROR, "cache lookup of attribute %d in relation %u failed",
1767 attnum, RelationGetRelid(rel));
1768 attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
1769 if (!attStruct->atthasdef)
1771 attStruct->atthasdef = true;
1772 heap_update(attrrel, &atttup->t_self, atttup, NULL);
1773 /* keep catalog indices current */
1774 CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices,
1776 CatalogIndexInsert(attridescs, Num_pg_attr_indices, attrrel, atttup);
1777 CatalogCloseIndices(Num_pg_attr_indices, attridescs);
1779 heap_close(attrrel, RowExclusiveLock);
1780 heap_freetuple(atttup);
1784 * Store a constraint expression for the given relation.
1785 * The expression must be presented as a nodeToString() string.
1787 * Caller is responsible for updating the count of constraints
1788 * in the pg_class entry for the relation.
1791 StoreRelCheck(Relation rel, char *ccname, char *ccbin)
1797 Relation idescs[Num_pg_relcheck_indices];
1800 static char nulls[4] = {' ', ' ', ' ', ' '};
1803 * Convert condition to a normal boolean expression tree.
1805 expr = stringToNode(ccbin);
1806 expr = (Node *) make_ands_explicit((List *) expr);
1809 * deparse_expression needs a RangeTblEntry list, so make one
1811 rte = makeNode(RangeTblEntry);
1812 rte->relname = RelationGetRelationName(rel);
1813 #ifndef DISABLE_EREF
1814 rte->ref = makeNode(Attr);
1815 rte->ref->relname = RelationGetRelationName(rel);
1817 rte->relid = RelationGetRelid(rel);
1819 rte->inFromCl = true;
1820 rte->skipAcl = false;
1821 ccsrc = deparse_expression(expr, lcons(lcons(rte, NIL), NIL), false);
1823 values[Anum_pg_relcheck_rcrelid - 1] = RelationGetRelid(rel);
1824 values[Anum_pg_relcheck_rcname - 1] = PointerGetDatum(namein(ccname));
1825 values[Anum_pg_relcheck_rcbin - 1] = PointerGetDatum(textin(ccbin));
1826 values[Anum_pg_relcheck_rcsrc - 1] = PointerGetDatum(textin(ccsrc));
1827 rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock);
1828 tuple = heap_formtuple(rcrel->rd_att, values, nulls);
1829 heap_insert(rcrel, tuple);
1830 CatalogOpenIndices(Num_pg_relcheck_indices, Name_pg_relcheck_indices,
1832 CatalogIndexInsert(idescs, Num_pg_relcheck_indices, rcrel, tuple);
1833 CatalogCloseIndices(Num_pg_relcheck_indices, idescs);
1834 heap_close(rcrel, RowExclusiveLock);
1836 pfree(DatumGetPointer(values[Anum_pg_relcheck_rcname - 1]));
1837 pfree(DatumGetPointer(values[Anum_pg_relcheck_rcbin - 1]));
1838 pfree(DatumGetPointer(values[Anum_pg_relcheck_rcsrc - 1]));
1839 heap_freetuple(tuple);
1844 * Store defaults and constraints passed in via the tuple constraint struct.
1846 * NOTE: only pre-cooked expressions will be passed this way, which is to
1847 * say expressions inherited from an existing relation. Newly parsed
1848 * expressions can be added later, by direct calls to StoreAttrDefault
1849 * and StoreRelCheck (see AddRelationRawConstraints()). We assume that
1850 * pg_attribute and pg_class entries for the relation were already set
1851 * to reflect the existence of these defaults/constraints.
1854 StoreConstraints(Relation rel)
1856 TupleConstr *constr = rel->rd_att->constr;
1863 * deparsing of constraint expressions will fail unless the
1864 * just-created pg_attribute tuples for this relation are made
1865 * visible. So, bump the command counter.
1867 CommandCounterIncrement();
1869 for (i = 0; i < constr->num_defval; i++)
1870 StoreAttrDefault(rel, constr->defval[i].adnum,
1871 constr->defval[i].adbin, false);
1873 for (i = 0; i < constr->num_check; i++)
1874 StoreRelCheck(rel, constr->check[i].ccname,
1875 constr->check[i].ccbin);
1879 * AddRelationRawConstraints
1881 * Add raw (not-yet-transformed) column default expressions and/or constraint
1882 * check expressions to an existing relation. This is defined to do both
1883 * for efficiency in DefineRelation, but of course you can do just one or
1884 * the other by passing empty lists.
1886 * rel: relation to be modified
1887 * rawColDefaults: list of RawColumnDefault structures
1888 * rawConstraints: list of Constraint nodes
1890 * All entries in rawColDefaults will be processed. Entries in rawConstraints
1891 * will be processed only if they are CONSTR_CHECK type and contain a "raw"
1894 * NB: caller should have opened rel with AccessExclusiveLock, and should
1895 * hold that lock till end of transaction. Also, we assume the caller has
1896 * done a CommandCounterIncrement if necessary to make the relation's catalog
1900 AddRelationRawConstraints(Relation rel,
1901 List *rawColDefaults,
1902 List *rawConstraints)
1904 char *relname = RelationGetRelationName(rel);
1905 TupleDesc tupleDesc;
1906 TupleConstr *oldconstr;
1908 ConstrCheck *oldchecks;
1913 Relation relidescs[Num_pg_class_indices];
1915 Form_pg_class relStruct;
1918 * Get info about existing constraints.
1920 tupleDesc = RelationGetDescr(rel);
1921 oldconstr = tupleDesc->constr;
1924 numoldchecks = oldconstr->num_check;
1925 oldchecks = oldconstr->check;
1934 * Create a dummy ParseState and insert the target relation as its
1935 * sole rangetable entry. We need a ParseState for transformExpr.
1937 pstate = make_parsestate(NULL);
1938 makeRangeTable(pstate, NULL);
1939 addRangeTableEntry(pstate, relname, makeAttr(relname, NULL), false, true, true);
1942 * Process column default expressions.
1944 foreach(listptr, rawColDefaults)
1946 RawColumnDefault *colDef = (RawColumnDefault *) lfirst(listptr);
1950 Assert(colDef->raw_default != NULL);
1953 * Transform raw parsetree to executable expression.
1955 expr = transformExpr(pstate, colDef->raw_default, EXPR_COLUMN_FIRST);
1958 * Make sure default expr does not refer to any vars.
1960 if (contain_var_clause(expr))
1961 elog(ERROR, "Cannot use attribute(s) in DEFAULT clause");
1964 * Check that it will be possible to coerce the expression to the
1965 * column's type. We store the expression without coercion,
1966 * however, to avoid premature coercion in cases like
1968 * CREATE TABLE tbl (fld datetime DEFAULT 'now');
1970 * NB: this should match the code in updateTargetListEntry() that
1971 * will actually do the coercion, to ensure we don't accept an
1972 * unusable default expression.
1974 type_id = exprType(expr);
1975 if (type_id != InvalidOid)
1977 Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];
1979 if (type_id != atp->atttypid)
1981 if (CoerceTargetExpr(NULL, expr, type_id,
1982 atp->atttypid, atp->atttypmod) == NULL)
1983 elog(ERROR, "Attribute '%s' is of type '%s'"
1984 " but default expression is of type '%s'"
1985 "\n\tYou will need to rewrite or cast the expression",
1986 NameStr(atp->attname),
1987 typeidTypeName(atp->atttypid),
1988 typeidTypeName(type_id));
1993 * Might as well try to reduce any constant expressions.
1995 expr = eval_const_expressions(expr);
1998 * Must fix opids, in case any operators remain...
2005 StoreAttrDefault(rel, colDef->attnum, nodeToString(expr), true);
2009 * Process constraint expressions.
2011 numchecks = numoldchecks;
2012 foreach(listptr, rawConstraints)
2014 Constraint *cdef = (Constraint *) lfirst(listptr);
2018 if (cdef->contype != CONSTR_CHECK || cdef->raw_expr == NULL)
2020 Assert(cdef->cooked_expr == NULL);
2022 /* Check name uniqueness, or generate a new name */
2023 if (cdef->name != NULL)
2028 ccname = cdef->name;
2029 /* Check against old constraints */
2030 for (i = 0; i < numoldchecks; i++)
2032 if (strcmp(oldchecks[i].ccname, ccname) == 0)
2033 elog(ERROR, "Duplicate CHECK constraint name: '%s'",
2036 /* Check against other new constraints */
2037 foreach(listptr2, rawConstraints)
2039 Constraint *cdef2 = (Constraint *) lfirst(listptr2);
2041 if (cdef2 == cdef ||
2042 cdef2->contype != CONSTR_CHECK ||
2043 cdef2->raw_expr == NULL ||
2044 cdef2->name == NULL)
2046 if (strcmp(cdef2->name, ccname) == 0)
2047 elog(ERROR, "Duplicate CHECK constraint name: '%s'",
2053 ccname = (char *) palloc(NAMEDATALEN);
2054 snprintf(ccname, NAMEDATALEN, "$%d", numchecks + 1);
2058 * Transform raw parsetree to executable expression.
2060 expr = transformExpr(pstate, cdef->raw_expr, EXPR_COLUMN_FIRST);
2063 * Make sure it yields a boolean result.
2065 if (exprType(expr) != BOOLOID)
2066 elog(ERROR, "CHECK '%s' does not yield boolean result",
2070 * Make sure no outside relations are referred to.
2072 if (length(pstate->p_rtable) != 1)
2073 elog(ERROR, "Only relation '%s' can be referenced in CHECK",
2077 * Might as well try to reduce any constant expressions.
2079 expr = eval_const_expressions(expr);
2082 * Constraints are evaluated with execQual, which expects an
2083 * implicit-AND list, so convert expression to implicit-AND form.
2084 * (We could go so far as to convert to CNF, but that's probably
2087 expr = (Node *) make_ands_implicit((Expr *) expr);
2090 * Must fix opids in operator clauses.
2097 StoreRelCheck(rel, ccname, nodeToString(expr));
2103 * Update the count of constraints in the relation's pg_class tuple.
2104 * We do this even if there was no change, in order to ensure that an
2105 * SI update message is sent out for the pg_class tuple, which will
2106 * force other backends to rebuild their relcache entries for the rel.
2107 * (Of course, for a newly created rel there is no need for an SI
2108 * message, but for ALTER TABLE ADD ATTRIBUTE this'd be important.)
2110 relrel = heap_openr(RelationRelationName, RowExclusiveLock);
2111 reltup = SearchSysCacheTupleCopy(RELOID,
2112 ObjectIdGetDatum(RelationGetRelid(rel)),
2114 if (!HeapTupleIsValid(reltup))
2115 elog(ERROR, "cache lookup of relation %u failed", RelationGetRelid(rel));
2116 relStruct = (Form_pg_class) GETSTRUCT(reltup);
2118 relStruct->relchecks = numchecks;
2120 heap_update(relrel, &reltup->t_self, reltup, NULL);
2122 /* keep catalog indices current */
2123 CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices,
2125 CatalogIndexInsert(relidescs, Num_pg_class_indices, relrel, reltup);
2126 CatalogCloseIndices(Num_pg_class_indices, relidescs);
2128 heap_close(relrel, RowExclusiveLock);
2129 heap_freetuple(reltup);
2133 RemoveAttrDefault(Relation rel)
2136 HeapScanDesc adscan;
2140 adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
2142 ScanKeyEntryInitialize(&key, 0, Anum_pg_attrdef_adrelid,
2143 F_OIDEQ, RelationGetRelid(rel));
2145 adscan = heap_beginscan(adrel, 0, SnapshotNow, 1, &key);
2147 while (HeapTupleIsValid(tup = heap_getnext(adscan, 0)))
2148 heap_delete(adrel, &tup->t_self, NULL);
2150 heap_endscan(adscan);
2151 heap_close(adrel, RowExclusiveLock);
2155 RemoveRelCheck(Relation rel)
2158 HeapScanDesc rcscan;
2162 rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock);
2164 ScanKeyEntryInitialize(&key, 0, Anum_pg_relcheck_rcrelid,
2165 F_OIDEQ, RelationGetRelid(rel));
2167 rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key);
2169 while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0)))
2170 heap_delete(rcrel, &tup->t_self, NULL);
2172 heap_endscan(rcscan);
2173 heap_close(rcrel, RowExclusiveLock);
2177 RemoveConstraints(Relation rel)
2179 TupleConstr *constr = rel->rd_att->constr;
2184 if (constr->num_defval > 0)
2185 RemoveAttrDefault(rel);
2187 if (constr->num_check > 0)
2188 RemoveRelCheck(rel);
2192 RemoveStatistics(Relation rel)
2194 Relation pgstatistic;
2199 pgstatistic = heap_openr(StatisticRelationName, RowExclusiveLock);
2201 ScanKeyEntryInitialize(&key, 0x0, Anum_pg_statistic_starelid,
2203 ObjectIdGetDatum(RelationGetRelid(rel)));
2204 scan = heap_beginscan(pgstatistic, false, SnapshotNow, 1, &key);
2206 while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
2207 heap_delete(pgstatistic, &tuple->t_self, NULL);
2210 heap_close(pgstatistic, RowExclusiveLock);