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.126 2000/05/19 03:22:31 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/portal.h"
66 #include "utils/relcache.h"
67 #include "utils/syscache.h"
68 #include "utils/temprel.h"
71 static void AddNewRelationTuple(Relation pg_class_desc,
72 Relation new_rel_desc, Oid new_rel_oid,
74 char relkind, char *temp_relname);
75 static void AddToNoNameRelList(Relation r);
77 static void DeleteAttributeTuples(Relation rel);
78 static void DeleteRelationTuple(Relation rel);
79 static void DeleteTypeTuple(Relation rel);
80 static void RelationRemoveIndexes(Relation relation);
81 static void RelationRemoveInheritance(Relation relation);
82 static void RemoveFromNoNameRelList(Relation r);
83 static void AddNewRelationType(char *typeName, Oid new_rel_oid);
84 static void StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin,
85 bool updatePgAttribute);
86 static void StoreRelCheck(Relation rel, char *ccname, char *ccbin);
87 static void StoreConstraints(Relation rel);
88 static void RemoveConstraints(Relation rel);
89 static void RemoveStatistics(Relation rel);
92 /* ----------------------------------------------------------------
93 * XXX UGLY HARD CODED BADNESS FOLLOWS XXX
95 * these should all be moved to someplace in the lib/catalog
96 * module, if not obliterated first.
97 * ----------------------------------------------------------------
103 * Should the executor special case these attributes in the future?
104 * Advantage: consume 1/2 the space in the ATTRIBUTE relation.
105 * Disadvantage: having rules to compute values in these tuples may
106 * be more difficult if not impossible.
109 static FormData_pg_attribute a1 = {
110 0xffffffff, {"ctid"}, TIDOID, 0, sizeof(ItemPointerData),
111 SelfItemPointerAttributeNumber, 0, -1, -1, '\0', 'p', '\0', 'i', '\0', '\0'
114 static FormData_pg_attribute a2 = {
115 0xffffffff, {"oid"}, OIDOID, 0, sizeof(Oid),
116 ObjectIdAttributeNumber, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0'
119 static FormData_pg_attribute a3 = {
120 0xffffffff, {"xmin"}, XIDOID, 0, sizeof(TransactionId),
121 MinTransactionIdAttributeNumber, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0'
124 static FormData_pg_attribute a4 = {
125 0xffffffff, {"cmin"}, CIDOID, 0, sizeof(CommandId),
126 MinCommandIdAttributeNumber, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0'
129 static FormData_pg_attribute a5 = {
130 0xffffffff, {"xmax"}, XIDOID, 0, sizeof(TransactionId),
131 MaxTransactionIdAttributeNumber, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0'
134 static FormData_pg_attribute a6 = {
135 0xffffffff, {"cmax"}, CIDOID, 0, sizeof(CommandId),
136 MaxCommandIdAttributeNumber, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0'
139 static Form_pg_attribute HeapAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6};
141 /* ----------------------------------------------------------------
142 * XXX END OF UGLY HARD CODED BADNESS XXX
143 * ----------------------------------------------------------------
146 /* the tempRelList holds
147 the list of temporary uncatalogued relations that are created.
148 these relations should be destroyed at the end of transactions
150 typedef struct tempRelList
152 Relation *rels; /* array of relation descriptors */
153 int num; /* number of temporary relations */
154 int size; /* size of space allocated for the rels
158 #define NONAME_REL_LIST_SIZE 32
160 static TempRelList *tempRels = NULL;
163 /* ----------------------------------------------------------------
164 * heap_create - Create an uncataloged heap relation
166 * Fields relpages, reltuples, reltuples, relkeys, relhistory,
167 * relisindexed, and relkind of rel->rd_rel are initialized
168 * to all zeros, as are rd_last and rd_hook. Rd_refcnt is set to 1.
170 * Remove the system relation specific code to elsewhere eventually.
172 * Eventually, must place information about this temporary relation
173 * into the transaction context block.
176 * if heap_create is called with "" as the name, then heap_create will create
177 * a temporary name "pg_noname.$PID.$SEQUENCE" for the relation
178 * ----------------------------------------------------------------
181 heap_create(char *relname,
192 int natts = tupDesc->natts;
193 static unsigned int uniqueId = 0;
195 extern GlobalMemory CacheCxt;
196 MemoryContext oldcxt;
203 AssertArg(natts > 0);
205 if (relname && !allowSystemTableMods &&
206 IsSystemRelationName(relname) && IsNormalProcessingMode())
208 elog(ERROR, "Illegal class name '%s'"
209 "\n\tThe 'pg_' name prefix 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 (relname && !strcmp(RelationRelationName, relname))
231 relid = RelOid_pg_class;
234 else if (relname && !strcmp(AttributeRelationName, relname))
236 relid = RelOid_pg_attribute;
239 else if (relname && !strcmp(ProcedureRelationName, relname))
241 relid = RelOid_pg_proc;
244 else if (relname && !strcmp(TypeRelationName, relname))
246 relid = RelOid_pg_type;
255 relname = palloc(NAMEDATALEN);
256 snprintf(relname, NAMEDATALEN, "pg_noname.%d.%u",
257 (int) MyProcPid, uniqueId++);
262 /* replace relname of caller */
263 snprintf(relname, NAMEDATALEN, "pg_temp.%d.%u", MyProcPid, uniqueId++);
267 * allocate a new relation descriptor.
270 len = sizeof(RelationData);
272 rel = (Relation) palloc(len);
273 MemSet((char *) rel, 0, len);
274 rel->rd_fd = -1; /* table is not open */
275 rel->rd_unlinked = TRUE; /* table is not created yet */
278 * create a new tuple descriptor from the one passed in
280 rel->rd_att = CreateTupleDescCopyConstr(tupDesc);
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 rel->rd_isnailed = true;
291 RelationSetReferenceCount(rel, 1);
293 rel->rd_rel = (Form_pg_class) palloc(sizeof *rel->rd_rel);
296 * initialize the fields of our new relation descriptor
299 MemSet((char *) rel->rd_rel, 0, sizeof *rel->rd_rel);
300 strcpy(RelationGetPhysicalRelationName(rel), relname);
301 rel->rd_rel->relkind = RELKIND_UNCATALOGED;
302 rel->rd_rel->relnatts = natts;
304 rel->rd_rel->relchecks = tupDesc->constr->num_check;
306 for (i = 0; i < natts; i++)
307 rel->rd_att->attrs[i]->attrelid = relid;
309 RelationGetRelid(rel) = relid;
313 /* for system relations, set the reltype field here */
314 rel->rd_rel->reltype = relid;
318 * remember if this is a noname relation
321 rel->rd_isnoname = isnoname;
324 * have the storage manager create the relation.
328 /* smgrcreate() is moved to heap_storage_create() */
330 heap_storage_create(rel);
332 RelationRegisterRelation(rel);
334 MemoryContextSwitchTo(oldcxt);
337 * add all noname relations to the tempRels list so they can be
338 * properly disposed of at the end of transaction
341 AddToNoNameRelList(rel);
347 heap_storage_create(Relation rel)
349 bool smgrcall = false;
351 if (rel->rd_unlinked)
353 rel->rd_fd = (File) smgrcreate(DEFAULT_SMGR, rel);
354 rel->rd_unlinked = FALSE;
360 /* ----------------------------------------------------------------
361 * heap_create_with_catalog - Create a cataloged relation
363 * this is done in 6 steps:
365 * 1) CheckAttributeNames() is used to make certain the tuple
366 * descriptor contains a valid set of attribute names
368 * 2) pg_class is opened and RelationFindRelid()
369 * performs a scan to ensure that no relation with the
370 * same name already exists.
372 * 3) heap_create_with_catalog() is called to create the new relation
375 * 4) TypeDefine() is called to define a new type corresponding
376 * to the new relation.
378 * 5) AddNewAttributeTuples() is called to register the
379 * new relation's schema in pg_attribute.
381 * 6) AddNewRelationTuple() is called to register the
382 * relation itself in the catalogs.
384 * 7) StoreConstraints is called () - vadim 08/22/97
386 * 8) the relations are closed and the new relation's oid
390 * A new relation is inserted into the RELATION relation
391 * with the specified attribute(s) (newly inserted into
392 * the ATTRIBUTE relation). How does concurrency control
393 * work? Is it automatic now? Expects the caller to have
394 * attname, atttypid, atttyparg, attproc, and attlen domains filled.
395 * Create fills the attnum domains sequentually from zero,
396 * fills the attdisbursion domains with zeros, and fills the
397 * attrelid fields with the relid.
399 * scan relation catalog for name conflict
400 * scan type catalog for typids (if not arg)
401 * create and insert attribute(s) into attribute catalog
402 * create new relation
403 * insert new relation into attribute catalog
405 * Should coordinate with heap_create_with_catalog(). Either
406 * it should not be called or there should be a way to prevent
407 * the relation from being removed at the end of the
408 * transaction if it is successful ('u'/'r' may be enough).
409 * Also, if the transaction does not commit, then the
410 * relation should be removed.
412 * XXX amcreate ignores "off" when inserting (for now).
413 * XXX amcreate (like the other utilities) needs to understand indexes.
415 * ----------------------------------------------------------------
418 /* --------------------------------
419 * CheckAttributeNames
421 * this is used to make certain the tuple descriptor contains a
422 * valid set of attribute names. a problem simply generates
423 * elog(ERROR) which aborts the current transaction.
424 * --------------------------------
427 CheckAttributeNames(TupleDesc tupdesc)
431 int natts = tupdesc->natts;
434 * first check for collision with system attribute names
437 * also, warn user if attribute to be created has
438 * an unknown typid (usually as a result of a 'retrieve into'
441 for (i = 0; i < natts; i++)
443 for (j = 0; j < (int) (sizeof(HeapAtt) / sizeof(HeapAtt[0])); j++)
445 if (nameeq(&(HeapAtt[j]->attname),
446 &(tupdesc->attrs[i]->attname)))
448 elog(ERROR, "Attribute '%s' has a name conflict"
449 "\n\tName matches an existing system attribute",
450 NameStr(HeapAtt[j]->attname));
453 if (tupdesc->attrs[i]->atttypid == UNKNOWNOID)
455 elog(NOTICE, "Attribute '%s' has an unknown type"
456 "\n\tRelation created; continue",
457 NameStr(tupdesc->attrs[i]->attname));
462 * next check for repeated attribute names
465 for (i = 1; i < natts; i++)
467 for (j = 0; j < i; j++)
469 if (nameeq(&(tupdesc->attrs[j]->attname),
470 &(tupdesc->attrs[i]->attname)))
472 elog(ERROR, "Attribute '%s' is repeated",
473 NameStr(tupdesc->attrs[j]->attname));
479 /* --------------------------------
482 * Find any existing relation of the given name.
483 * --------------------------------
486 RelnameFindRelid(const char *relname)
492 * If this is not bootstrap (initdb) time, use the catalog index on
495 if (!IsBootstrapProcessingMode())
497 tuple = SearchSysCacheTuple(RELNAME,
498 PointerGetDatum(relname),
500 if (HeapTupleIsValid(tuple))
501 relid = tuple->t_data->t_oid;
507 Relation pg_class_desc;
509 HeapScanDesc pg_class_scan;
511 pg_class_desc = heap_openr(RelationRelationName, AccessShareLock);
514 * At bootstrap time, we have to do this the hard way. Form the
518 ScanKeyEntryInitialize(&key,
520 (AttrNumber) Anum_pg_class_relname,
521 (RegProcedure) F_NAMEEQ,
528 pg_class_scan = heap_beginscan(pg_class_desc,
535 * get a tuple. if the tuple is NULL then it means we
536 * didn't find an existing relation.
539 tuple = heap_getnext(pg_class_scan, 0);
541 if (HeapTupleIsValid(tuple))
542 relid = tuple->t_data->t_oid;
546 heap_endscan(pg_class_scan);
548 heap_close(pg_class_desc, AccessShareLock);
553 /* --------------------------------
554 * AddNewAttributeTuples
556 * this registers the new relation's schema by adding
557 * tuples to pg_attribute.
558 * --------------------------------
561 AddNewAttributeTuples(Oid new_rel_oid,
564 Form_pg_attribute *dpp;
569 Relation idescs[Num_pg_attr_indices];
570 int natts = tupdesc->natts;
576 rel = heap_openr(AttributeRelationName, RowExclusiveLock);
579 * Check if we have any indices defined on pg_attribute.
582 hasindex = RelationGetForm(rel)->relhasindex;
584 CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
587 * initialize tuple descriptor.
593 * first we add the user attributes..
596 dpp = tupdesc->attrs;
597 for (i = 0; i < natts; i++)
599 (*dpp)->attrelid = new_rel_oid;
600 (*dpp)->attdisbursion = 0;
602 tup = heap_addheader(Natts_pg_attribute,
603 ATTRIBUTE_TUPLE_SIZE,
606 heap_insert(rel, tup);
609 CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
616 * next we add the system attributes..
620 for (i = 0; i < -1 - FirstLowInvalidHeapAttributeNumber; i++)
622 (*dpp)->attrelid = new_rel_oid;
623 /* (*dpp)->attdisbursion = 0; unneeded */
625 tup = heap_addheader(Natts_pg_attribute,
626 ATTRIBUTE_TUPLE_SIZE,
629 heap_insert(rel, tup);
632 CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
638 heap_close(rel, RowExclusiveLock);
641 * close pg_attribute indices
644 CatalogCloseIndices(Num_pg_attr_indices, idescs);
647 /* --------------------------------
648 * AddNewRelationTuple
650 * this registers the new relation in the catalogs by
651 * adding a tuple to pg_class.
652 * --------------------------------
655 AddNewRelationTuple(Relation pg_class_desc,
656 Relation new_rel_desc,
662 Form_pg_class new_rel_reltup;
664 Relation idescs[Num_pg_class_indices];
667 * first we munge some of the information in our
668 * uncataloged relation's relation descriptor.
671 new_rel_reltup = new_rel_desc->rd_rel;
674 * Here we insert bogus estimates of the size of the new relation.
675 * In reality, of course, the new relation has 0 tuples and pages,
676 * and if we were tracking these statistics accurately then we'd
677 * set the fields that way. But at present the stats will be updated
678 * only by VACUUM or CREATE INDEX, and the user might insert a lot of
679 * tuples before he gets around to doing either of those. So, instead
680 * of saying the relation is empty, we insert guesstimates. The point
681 * is to keep the optimizer from making really stupid choices on
682 * never-yet-vacuumed tables; so the estimates need only be large
683 * enough to discourage the optimizer from using nested-loop plans.
684 * With this hack, nested-loop plans will be preferred only after
685 * the table has been proven to be small by VACUUM or CREATE INDEX.
686 * Maintaining the stats on-the-fly would solve the problem more cleanly,
687 * but the overhead of that would likely cost more than it'd save.
688 * (NOTE: CREATE INDEX inserts the same bogus estimates if it finds the
689 * relation has 0 rows and pages. See index.c.)
692 new_rel_reltup->relpages = 10; /* bogus estimates */
693 new_rel_reltup->reltuples = 1000;
695 new_rel_reltup->relowner = GetUserId();
696 new_rel_reltup->relkind = relkind;
697 new_rel_reltup->relnatts = natts;
700 * now form a tuple to add to pg_class
701 * XXX Natts_pg_class_fixed is a hack - see pg_class.h
704 tup = heap_addheader(Natts_pg_class_fixed,
706 (char *) new_rel_reltup);
707 tup->t_data->t_oid = new_rel_oid;
710 * finally insert the new tuple and free it.
712 heap_insert(pg_class_desc, tup);
715 create_temp_relation(temp_relname, tup);
717 if (!IsIgnoringSystemIndexes())
721 * First, open the catalog indices and insert index tuples for the
724 CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
725 CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class_desc, tup);
726 CatalogCloseIndices(Num_pg_class_indices, idescs);
733 /* --------------------------------
734 * AddNewRelationType -
736 * define a complex type corresponding to the new relation
737 * --------------------------------
740 AddNewRelationType(char *typeName, Oid new_rel_oid)
745 * The sizes are set to oid size because it makes implementing sets
746 * MUCH easier, and no one (we hope) uses these fields to figure out
747 * how much space to allocate for the type. An oid is the type used
748 * for a set definition. When a user requests a set, what they
749 * actually get is the oid of a tuple in the pg_proc catalog, so the
750 * size of the "set" is the size of an oid. Similarly, byval being
751 * true makes sets much easier, and it isn't used by anything else.
752 * Note the assumption that OIDs are the same size as int4s.
754 new_type_oid = TypeCreate(typeName, /* type name */
755 new_rel_oid, /* relation oid */
756 typeLen(typeidType(OIDOID)), /* internal size */
757 typeLen(typeidType(OIDOID)), /* external size */
758 'c', /* type-type (catalog) */
759 ',', /* default array delimiter */
760 "int4in", /* input procedure */
761 "int4out", /* output procedure */
762 "int4in", /* receive procedure */
763 "int4out", /* send procedure */
764 NULL, /* array element type - irrelevent */
765 "-", /* default type value */
766 (bool) 1, /* passed by value */
767 'i'); /* default alignment */
770 /* --------------------------------
771 * heap_create_with_catalog
773 * creates a new cataloged relation. see comments above.
774 * --------------------------------
777 heap_create_with_catalog(char *relname,
782 Relation pg_class_desc;
783 Relation new_rel_desc;
785 int natts = tupdesc->natts;
786 char *temp_relname = NULL;
792 Assert(IsNormalProcessingMode() || IsBootstrapProcessingMode());
793 if (natts <= 0 || natts > MaxHeapAttributeNumber)
794 elog(ERROR, "Number of attributes is out of range"
795 "\n\tFrom 1 to %d attributes may be specified",
796 MaxHeapAttributeNumber);
798 CheckAttributeNames(tupdesc);
800 /* temp tables can mask non-temp tables */
801 if ((!istemp && RelnameFindRelid(relname)) ||
802 (istemp && get_temp_rel_by_username(relname) != NULL))
803 elog(ERROR, "Relation '%s' already exists", relname);
805 /* save user relation name because heap_create changes it */
808 temp_relname = pstrdup(relname); /* save original value */
809 relname = palloc(NAMEDATALEN);
810 strcpy(relname, temp_relname); /* heap_create will change this */
814 * get_temp_rel_by_username() couldn't check the simultaneous
815 * creation. Uniqueness will be really checked by unique
816 * indexes of system tables but we couldn't check it here.
817 * We have to pospone to create the disk file for this
819 * Another boolean parameter "storage_create" was added
820 * to heap_create() function. If the parameter is false
821 * heap_create() only registers an uncataloged relation
822 * to relation cache and heap_storage_create() should be
824 * We could pull its relation oid from the newly formed
825 * relation descriptor.
827 * Note: The call to heap_create() changes relname for
828 * noname and temp tables.
829 * The call to heap_storage_create() does all the "real"
830 * work of creating the disk file for the relation.
833 new_rel_desc = heap_create(relname, tupdesc, false, istemp, false);
835 new_rel_oid = new_rel_desc->rd_att->attrs[0]->attrelid;
838 * since defining a relation also defines a complex type,
839 * we add a new system type corresponding to the new relation.
842 AddNewRelationType(relname, new_rel_oid);
845 * now add tuples to pg_attribute for the attributes in
849 AddNewAttributeTuples(new_rel_oid, tupdesc);
852 * now update the information in pg_class.
855 pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock);
857 AddNewRelationTuple(pg_class_desc,
864 StoreConstraints(new_rel_desc);
873 * We create the disk file for this relation here
875 heap_storage_create(new_rel_desc);
877 * ok, the relation has been cataloged, so close our relations
878 * and return the oid of the newly created relation.
880 * SOMEDAY: fill the STATISTIC relation properly.
883 heap_close(new_rel_desc, NoLock); /* do not unlock till end of xact */
884 heap_close(pg_class_desc, RowExclusiveLock);
890 /* ----------------------------------------------------------------
891 * heap_drop_with_catalog - removes all record of named relation from catalogs
893 * 1) open relation, check for existence, etc.
894 * 2) remove inheritance information
896 * 4) remove pg_class tuple
897 * 5) remove pg_attribute tuples and related descriptions
898 * 6) remove pg_description tuples
899 * 7) remove pg_type tuples
900 * 8) RemoveConstraints ()
904 * Except for vital relations, removes relation from
905 * relation catalog, and related attributes from
906 * attribute catalog (needed?). (Anything else?)
908 * get proper relation from relation catalog (if not arg)
909 * check if relation is vital (strcmp()/reltype?)
910 * scan attribute catalog deleting attributes of reldesc
912 * delete relation from relation catalog
913 * (How are the tuples of the relation discarded?)
915 * XXX Must fix to work with indexes.
916 * There may be a better order for doing things.
917 * Problems with destroying a deleted database--cannot create
918 * a struct reldesc without having an open file descriptor.
919 * ----------------------------------------------------------------
922 /* --------------------------------
923 * RelationRemoveInheritance
925 * Note: for now, we cause an exception if relation is a
926 * superclass. Someday, we may want to allow this and merge
927 * the type info into subclass procedures.... this seems like
929 * --------------------------------
932 RelationRemoveInheritance(Relation relation)
934 Relation catalogRelation;
944 catalogRelation = heap_openr(InheritsRelationName, RowExclusiveLock);
947 * form a scan key for the subclasses of this class
951 ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_inherits_inhparent,
953 ObjectIdGetDatum(RelationGetRelid(relation)));
955 scan = heap_beginscan(catalogRelation,
962 * if any subclasses exist, then we disallow the deletion.
965 tuple = heap_getnext(scan, 0);
966 if (HeapTupleIsValid(tuple))
968 Oid subclass = ((Form_pg_inherits) GETSTRUCT(tuple))->inhrelid;
971 heap_close(catalogRelation, RowExclusiveLock);
973 elog(ERROR, "Relation '%u' inherits '%s'",
974 subclass, RelationGetRelationName(relation));
979 * If we get here, it means the relation has no subclasses
980 * so we can trash it. First we remove dead INHERITS tuples.
983 entry.sk_attno = Anum_pg_inherits_inhrelid;
985 scan = heap_beginscan(catalogRelation,
991 while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
993 heap_delete(catalogRelation, &tuple->t_self, NULL);
998 heap_close(catalogRelation, RowExclusiveLock);
1001 * now remove dead IPL tuples
1004 catalogRelation = heap_openr(InheritancePrecidenceListRelationName,
1007 entry.sk_attno = Anum_pg_ipl_iplrelid;
1009 scan = heap_beginscan(catalogRelation,
1015 while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
1016 heap_delete(catalogRelation, &tuple->t_self, NULL);
1019 heap_close(catalogRelation, RowExclusiveLock);
1022 /* --------------------------------
1023 * RelationRemoveIndexes
1025 * --------------------------------
1028 RelationRemoveIndexes(Relation relation)
1030 Relation indexRelation;
1035 indexRelation = heap_openr(IndexRelationName, RowExclusiveLock);
1037 ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_index_indrelid,
1039 ObjectIdGetDatum(RelationGetRelid(relation)));
1041 scan = heap_beginscan(indexRelation,
1047 while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
1048 index_drop(((Form_pg_index) GETSTRUCT(tuple))->indexrelid);
1051 heap_close(indexRelation, RowExclusiveLock);
1054 /* --------------------------------
1055 * DeleteRelationTuple
1057 * --------------------------------
1060 DeleteRelationTuple(Relation rel)
1062 Relation pg_class_desc;
1069 pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock);
1071 tup = SearchSysCacheTupleCopy(RELOID,
1072 ObjectIdGetDatum(rel->rd_id),
1074 if (!HeapTupleIsValid(tup))
1076 heap_close(pg_class_desc, RowExclusiveLock);
1077 elog(ERROR, "Relation '%s' does not exist",
1078 RelationGetRelationName(rel));
1082 * delete the relation tuple from pg_class, and finish up.
1085 heap_delete(pg_class_desc, &tup->t_self, NULL);
1086 heap_freetuple(tup);
1088 heap_close(pg_class_desc, RowExclusiveLock);
1091 /* --------------------------------
1092 * RelationTruncateIndexes - This routine is used to truncate all
1093 * indices associated with the heap relation to zero tuples.
1094 * The routine will truncate and then reconstruct the indices on
1095 * the relation specified by the heapRelation parameter.
1096 * --------------------------------
1099 RelationTruncateIndexes(Relation heapRelation)
1101 Relation indexRelation,
1105 HeapTuple indexTuple,
1108 Form_pg_index index;
1113 Node *oldPred = NULL;
1115 List *cnfPred = NULL;
1116 AttrNumber *attributeNumberA;
1117 FuncIndexInfo fInfo,
1123 heapId = RelationGetRelid(heapRelation);
1125 /* Scan pg_index to find indexes on heapRelation */
1127 indexRelation = heap_openr(IndexRelationName, AccessShareLock);
1128 ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indrelid, F_OIDEQ,
1129 ObjectIdGetDatum(heapId));
1130 scan = heap_beginscan(indexRelation, false, SnapshotNow, 1, &entry);
1131 while (HeapTupleIsValid(indexTuple = heap_getnext(scan, 0)))
1135 * For each index, fetch index attributes so we can apply
1138 index = (Form_pg_index) GETSTRUCT(indexTuple);
1139 indexId = index->indexrelid;
1140 procId = index->indproc;
1142 for (i = 0; i < INDEX_MAX_KEYS; i++)
1144 if (index->indkey[i] == InvalidAttrNumber)
1147 numberOfAttributes = i;
1149 /* If a valid where predicate, compute predicate Node */
1150 if (VARSIZE(&index->indpred) != 0)
1152 predString = fmgr(F_TEXTOUT, &index->indpred);
1153 oldPred = stringToNode(predString);
1156 predInfo = (PredInfo *) palloc(sizeof(PredInfo));
1157 predInfo->pred = (Node *) cnfPred;
1158 predInfo->oldPred = oldPred;
1160 /* Assign Index keys to attributes array */
1161 attributeNumberA = (AttrNumber *) palloc(numberOfAttributes *
1162 sizeof(AttrNumber));
1163 for (i = 0; i < numberOfAttributes; i++)
1164 attributeNumberA[i] = index->indkey[i];
1166 /* If this is a procedural index, initialize our FuncIndexInfo */
1167 if (procId != InvalidOid)
1170 FIsetnArgs(funcInfo, numberOfAttributes);
1171 procTuple = SearchSysCacheTuple(PROCOID, ObjectIdGetDatum(procId),
1173 if (!HeapTupleIsValid(procTuple))
1174 elog(ERROR, "RelationTruncateIndexes: index procedure not found");
1175 namecpy(&(funcInfo->funcName),
1176 &(((Form_pg_proc) GETSTRUCT(procTuple))->proname));
1177 FIsetProcOid(funcInfo, procTuple->t_data->t_oid);
1180 /* Fetch the classTuple associated with this index */
1181 classTuple = SearchSysCacheTupleCopy(RELOID, ObjectIdGetDatum(indexId),
1183 if (!HeapTupleIsValid(classTuple))
1184 elog(ERROR, "RelationTruncateIndexes: index access method not found");
1185 accessMethodId = ((Form_pg_class) GETSTRUCT(classTuple))->relam;
1187 /* Open our index relation */
1188 currentIndex = index_open(indexId);
1189 if (currentIndex == NULL)
1190 elog(ERROR, "RelationTruncateIndexes: can't open index relation");
1192 /* Obtain exclusive lock on it, just to be sure */
1193 LockRelation(currentIndex, AccessExclusiveLock);
1196 * Release any buffers associated with this index. If they're
1197 * dirty, they're just dropped without bothering to flush to disk.
1199 ReleaseRelationBuffers(currentIndex);
1201 /* Now truncate the actual data and set blocks to zero */
1202 smgrtruncate(DEFAULT_SMGR, currentIndex, 0);
1203 currentIndex->rd_nblocks = 0;
1205 /* Initialize the index and rebuild */
1206 InitIndexStrategy(numberOfAttributes, currentIndex, accessMethodId);
1207 index_build(heapRelation, currentIndex, numberOfAttributes,
1208 attributeNumberA, 0, NULL, funcInfo, predInfo);
1211 * index_build will close both the heap and index relations (but
1212 * not give up the locks we hold on them). That's fine for the
1213 * index, but we need to open the heap again. We need no new
1214 * lock, since this backend still has the exclusive lock grabbed
1217 heapRelation = heap_open(heapId, NoLock);
1218 Assert(heapRelation != NULL);
1221 /* Complete the scan and close pg_index */
1223 heap_close(indexRelation, AccessShareLock);
1226 /* ----------------------------
1229 * This routine is used to truncate the data from the
1230 * storage manager of any data within the relation handed
1232 * ----------------------------
1236 heap_truncate(char *relname)
1241 /* Open relation for processing, and grab exclusive access on it. */
1243 rel = heap_openr(relname, AccessExclusiveLock);
1244 rid = RelationGetRelid(rel);
1247 * TRUNCATE TABLE within a transaction block is dangerous, because
1248 * if the transaction is later rolled back we have no way to
1249 * undo truncation of the relation's physical file. For now, allow it
1250 * but emit a warning message.
1251 * Someday we might want to consider postponing the physical truncate
1252 * until transaction commit, but that's a lot of work...
1253 * The only case that actually works right is for relations created
1254 * in the current transaction, since the post-abort state would be that
1255 * they don't exist anyway. So, no warning in that case.
1258 if (IsTransactionBlock() && !rel->rd_myxactonly)
1259 elog(NOTICE, "Caution: TRUNCATE TABLE cannot be rolled back, so don't abort now");
1262 * Release any buffers associated with this relation. If they're
1263 * dirty, they're just dropped without bothering to flush to disk.
1266 ReleaseRelationBuffers(rel);
1268 /* Now truncate the actual data and set blocks to zero */
1270 smgrtruncate(DEFAULT_SMGR, rel, 0);
1271 rel->rd_nblocks = 0;
1273 /* If this relation has indexes, truncate the indexes too */
1274 RelationTruncateIndexes(rel);
1277 * Close the relation, but keep exclusive lock on it until commit.
1279 heap_close(rel, NoLock);
1282 * Is this really necessary?
1284 RelationForgetRelation(rid);
1288 /* --------------------------------
1289 * DeleteAttributeTuples
1291 * --------------------------------
1294 DeleteAttributeTuples(Relation rel)
1296 Relation pg_attribute_desc;
1304 pg_attribute_desc = heap_openr(AttributeRelationName, RowExclusiveLock);
1306 for (attnum = FirstLowInvalidHeapAttributeNumber + 1;
1307 attnum <= rel->rd_att->natts;
1310 if (HeapTupleIsValid(tup = SearchSysCacheTupleCopy(ATTNUM,
1311 ObjectIdGetDatum(RelationGetRelid(rel)),
1312 Int16GetDatum(attnum),
1316 /*** Delete any comments associated with this attribute ***/
1318 DeleteComments(tup->t_data->t_oid);
1320 heap_delete(pg_attribute_desc, &tup->t_self, NULL);
1321 heap_freetuple(tup);
1326 heap_close(pg_attribute_desc, RowExclusiveLock);
1329 /* --------------------------------
1332 * If the user attempts to destroy a relation and there
1333 * exists attributes in other relations of type
1334 * "relation we are deleting", then we have to do something
1335 * special. presently we disallow the destroy.
1336 * --------------------------------
1339 DeleteTypeTuple(Relation rel)
1341 Relation pg_type_desc;
1342 HeapScanDesc pg_type_scan;
1343 Relation pg_attribute_desc;
1344 HeapScanDesc pg_attribute_scan;
1355 pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
1358 * create a scan key to locate the type tuple corresponding
1362 ScanKeyEntryInitialize(&key, 0,
1363 Anum_pg_type_typrelid,
1365 ObjectIdGetDatum(RelationGetRelid(rel)));
1367 pg_type_scan = heap_beginscan(pg_type_desc,
1374 * use heap_getnext() to fetch the pg_type tuple. If this
1375 * tuple is not valid then something's wrong.
1378 tup = heap_getnext(pg_type_scan, 0);
1380 if (!HeapTupleIsValid(tup))
1382 heap_endscan(pg_type_scan);
1383 heap_close(pg_type_desc, RowExclusiveLock);
1384 elog(ERROR, "DeleteTypeTuple: %s type nonexistent",
1385 RelationGetRelationName(rel));
1389 * now scan pg_attribute. if any other relations have
1390 * attributes of the type of the relation we are deleteing
1391 * then we have to disallow the deletion. should talk to
1392 * stonebraker about this. -cim 6/19/90
1395 typoid = tup->t_data->t_oid;
1397 pg_attribute_desc = heap_openr(AttributeRelationName, RowExclusiveLock);
1399 ScanKeyEntryInitialize(&attkey,
1401 Anum_pg_attribute_atttypid,
1405 pg_attribute_scan = heap_beginscan(pg_attribute_desc,
1412 * try and get a pg_attribute tuple. if we succeed it means
1413 * we can't delete the relation because something depends on
1417 atttup = heap_getnext(pg_attribute_scan, 0);
1419 if (HeapTupleIsValid(atttup))
1421 Oid relid = ((Form_pg_attribute) GETSTRUCT(atttup))->attrelid;
1423 heap_endscan(pg_attribute_scan);
1424 heap_close(pg_attribute_desc, RowExclusiveLock);
1425 heap_endscan(pg_type_scan);
1426 heap_close(pg_type_desc, RowExclusiveLock);
1428 elog(ERROR, "DeleteTypeTuple: att of type %s exists in relation %u",
1429 RelationGetRelationName(rel), relid);
1431 heap_endscan(pg_attribute_scan);
1432 heap_close(pg_attribute_desc, RowExclusiveLock);
1435 * Ok, it's safe so we delete the relation tuple
1436 * from pg_type and finish up. But first end the scan so that
1437 * we release the read lock on pg_type. -mer 13 Aug 1991
1441 heap_delete(pg_type_desc, &tup->t_self, NULL);
1443 heap_endscan(pg_type_scan);
1444 heap_close(pg_type_desc, RowExclusiveLock);
1447 /* --------------------------------
1448 * heap_drop_with_catalog
1450 * --------------------------------
1453 heap_drop_with_catalog(const char *relname)
1457 bool istemp = (get_temp_rel_by_username(relname) != NULL);
1460 * Open and lock the relation.
1463 rel = heap_openr(relname, AccessExclusiveLock);
1464 rid = RelationGetRelid(rel);
1467 * prevent deletion of system relations
1470 /* allow temp of pg_class? Guess so. */
1471 if (!istemp && !allowSystemTableMods &&
1472 IsSystemRelationName(RelationGetRelationName(rel)))
1473 elog(ERROR, "System relation '%s' cannot be destroyed",
1474 RelationGetRelationName(rel));
1477 * DROP TABLE within a transaction block is dangerous, because
1478 * if the transaction is later rolled back there will be no way to
1479 * undo the unlink of the relation's physical file. For now, allow it
1480 * but emit a warning message.
1481 * Someday we might want to consider postponing the physical unlink
1482 * until transaction commit, but that's a lot of work...
1483 * The only case that actually works right is for relations created
1484 * in the current transaction, since the post-abort state would be that
1485 * they don't exist anyway. So, no warning in that case.
1488 if (IsTransactionBlock() && !rel->rd_myxactonly)
1489 elog(NOTICE, "Caution: DROP TABLE cannot be rolled back, so don't abort now");
1492 * remove inheritance information
1495 RelationRemoveInheritance(rel);
1498 * remove indexes if necessary
1501 /* should ignore relhasindex */
1502 RelationRemoveIndexes(rel);
1505 * remove rules if necessary
1508 if (rel->rd_rules != NULL)
1509 RelationRemoveRules(rid);
1512 RelationRemoveTriggers(rel);
1515 * delete attribute tuples
1518 DeleteAttributeTuples(rel);
1521 * delete comments, statistics, and constraints
1524 DeleteComments(RelationGetRelid(rel));
1526 RemoveStatistics(rel);
1528 RemoveConstraints(rel);
1534 DeleteTypeTuple(rel);
1537 * delete relation tuple
1540 DeleteRelationTuple(rel);
1543 * release dirty buffers of this relation; don't bother to write them
1545 ReleaseRelationBuffers(rel);
1548 * unlink the relation's physical file and finish up.
1551 if (!(rel->rd_isnoname) || !(rel->rd_unlinked))
1552 smgrunlink(DEFAULT_SMGR, rel);
1554 rel->rd_unlinked = TRUE;
1557 * Close relcache entry, but *keep* AccessExclusiveLock on the
1558 * relation until transaction commit. This ensures no one else will
1559 * try to do something with the doomed relation.
1561 heap_close(rel, NoLock);
1564 * flush the relation from the relcache
1567 RelationForgetRelation(rid);
1570 remove_temp_relation(rid);
1575 * destroy and close temporary relations
1580 heap_drop(Relation rel)
1582 ReleaseRelationBuffers(rel);
1583 if (!(rel->rd_isnoname) || !(rel->rd_unlinked))
1584 smgrunlink(DEFAULT_SMGR, rel);
1585 rel->rd_unlinked = TRUE;
1586 heap_close(rel, NoLock);
1587 RemoveFromNoNameRelList(rel);
1591 /**************************************************************
1592 functions to deal with the list of temporary relations
1593 **************************************************************/
1598 initialize temporary relations list
1599 the tempRelList is a list of temporary relations that
1600 are created in the course of the transactions
1601 they need to be destroyed properly at the end of the transactions
1603 MODIFIES the global variable tempRels
1607 malloc is used instead of palloc because we KNOW when we are
1608 going to free these things. Keeps us away from the memory context
1613 InitNoNameRelList(void)
1617 free(tempRels->rels);
1621 tempRels = (TempRelList *) malloc(sizeof(TempRelList));
1622 tempRels->size = NONAME_REL_LIST_SIZE;
1623 tempRels->rels = (Relation *) malloc(sizeof(Relation) * tempRels->size);
1624 MemSet(tempRels->rels, 0, sizeof(Relation) * tempRels->size);
1629 removes a relation from the TempRelList
1631 MODIFIES the global variable tempRels
1632 we don't really remove it, just mark it as NULL
1633 and DropNoNameRels will look for NULLs
1636 RemoveFromNoNameRelList(Relation r)
1643 for (i = 0; i < tempRels->num; i++)
1645 if (tempRels->rels[i] == r)
1647 tempRels->rels[i] = NULL;
1654 add a temporary relation to the TempRelList
1656 MODIFIES the global variable tempRels
1659 AddToNoNameRelList(Relation r)
1664 if (tempRels->num == tempRels->size)
1666 tempRels->size += NONAME_REL_LIST_SIZE;
1667 tempRels->rels = realloc(tempRels->rels,
1668 sizeof(Relation) * tempRels->size);
1670 tempRels->rels[tempRels->num] = r;
1675 go through the tempRels list and destroy each of the relations
1678 DropNoNameRels(void)
1686 for (i = 0; i < tempRels->num; i++)
1688 rel = tempRels->rels[i];
1689 /* rel may be NULL if it has been removed from the list already */
1693 free(tempRels->rels);
1699 * Store a default expression for column attnum of relation rel.
1700 * The expression must be presented as a nodeToString() string.
1701 * If updatePgAttribute is true, update the pg_attribute entry
1702 * for the column to show that a default exists.
1705 StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin,
1706 bool updatePgAttribute)
1712 Relation idescs[Num_pg_attrdef_indices];
1715 static char nulls[4] = {' ', ' ', ' ', ' '};
1717 Relation attridescs[Num_pg_attr_indices];
1719 Form_pg_attribute attStruct;
1722 * Need to construct source equivalent of given node-string.
1724 expr = stringToNode(adbin);
1727 * deparse_expression needs a RangeTblEntry list, so make one
1729 rte = makeNode(RangeTblEntry);
1730 rte->relname = RelationGetRelationName(rel);
1731 #ifndef DISABLE_EREF
1732 rte->ref = makeNode(Attr);
1733 rte->ref->relname = RelationGetRelationName(rel);
1735 rte->relid = RelationGetRelid(rel);
1737 rte->inFromCl = true;
1738 rte->skipAcl = false;
1739 adsrc = deparse_expression(expr, lcons(lcons(rte, NIL), NIL), false);
1741 values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
1742 values[Anum_pg_attrdef_adnum - 1] = attnum;
1743 values[Anum_pg_attrdef_adbin - 1] = PointerGetDatum(textin(adbin));
1744 values[Anum_pg_attrdef_adsrc - 1] = PointerGetDatum(textin(adsrc));
1745 adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
1746 tuple = heap_formtuple(adrel->rd_att, values, nulls);
1747 heap_insert(adrel, tuple);
1748 CatalogOpenIndices(Num_pg_attrdef_indices, Name_pg_attrdef_indices,
1750 CatalogIndexInsert(idescs, Num_pg_attrdef_indices, adrel, tuple);
1751 CatalogCloseIndices(Num_pg_attrdef_indices, idescs);
1752 heap_close(adrel, RowExclusiveLock);
1754 pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
1755 pfree(DatumGetPointer(values[Anum_pg_attrdef_adsrc - 1]));
1756 heap_freetuple(tuple);
1759 if (!updatePgAttribute)
1760 return; /* done if pg_attribute is OK */
1762 attrrel = heap_openr(AttributeRelationName, RowExclusiveLock);
1763 atttup = SearchSysCacheTupleCopy(ATTNUM,
1764 ObjectIdGetDatum(RelationGetRelid(rel)),
1765 (Datum) attnum, 0, 0);
1766 if (!HeapTupleIsValid(atttup))
1767 elog(ERROR, "cache lookup of attribute %d in relation %u failed",
1768 attnum, RelationGetRelid(rel));
1769 attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
1770 if (!attStruct->atthasdef)
1772 attStruct->atthasdef = true;
1773 heap_update(attrrel, &atttup->t_self, atttup, NULL);
1774 /* keep catalog indices current */
1775 CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices,
1777 CatalogIndexInsert(attridescs, Num_pg_attr_indices, attrrel, atttup);
1778 CatalogCloseIndices(Num_pg_attr_indices, attridescs);
1780 heap_close(attrrel, RowExclusiveLock);
1781 heap_freetuple(atttup);
1785 * Store a constraint expression for the given relation.
1786 * The expression must be presented as a nodeToString() string.
1788 * Caller is responsible for updating the count of constraints
1789 * in the pg_class entry for the relation.
1792 StoreRelCheck(Relation rel, char *ccname, char *ccbin)
1798 Relation idescs[Num_pg_relcheck_indices];
1801 static char nulls[4] = {' ', ' ', ' ', ' '};
1804 * Convert condition to a normal boolean expression tree.
1806 expr = stringToNode(ccbin);
1807 expr = (Node *) make_ands_explicit((List *) expr);
1810 * deparse_expression needs a RangeTblEntry list, so make one
1812 rte = makeNode(RangeTblEntry);
1813 rte->relname = RelationGetRelationName(rel);
1814 #ifndef DISABLE_EREF
1815 rte->ref = makeNode(Attr);
1816 rte->ref->relname = RelationGetRelationName(rel);
1818 rte->relid = RelationGetRelid(rel);
1820 rte->inFromCl = true;
1821 rte->skipAcl = false;
1822 ccsrc = deparse_expression(expr, lcons(lcons(rte, NIL), NIL), false);
1824 values[Anum_pg_relcheck_rcrelid - 1] = RelationGetRelid(rel);
1825 values[Anum_pg_relcheck_rcname - 1] = PointerGetDatum(namein(ccname));
1826 values[Anum_pg_relcheck_rcbin - 1] = PointerGetDatum(textin(ccbin));
1827 values[Anum_pg_relcheck_rcsrc - 1] = PointerGetDatum(textin(ccsrc));
1828 rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock);
1829 tuple = heap_formtuple(rcrel->rd_att, values, nulls);
1830 heap_insert(rcrel, tuple);
1831 CatalogOpenIndices(Num_pg_relcheck_indices, Name_pg_relcheck_indices,
1833 CatalogIndexInsert(idescs, Num_pg_relcheck_indices, rcrel, tuple);
1834 CatalogCloseIndices(Num_pg_relcheck_indices, idescs);
1835 heap_close(rcrel, RowExclusiveLock);
1837 pfree(DatumGetPointer(values[Anum_pg_relcheck_rcname - 1]));
1838 pfree(DatumGetPointer(values[Anum_pg_relcheck_rcbin - 1]));
1839 pfree(DatumGetPointer(values[Anum_pg_relcheck_rcsrc - 1]));
1840 heap_freetuple(tuple);
1845 * Store defaults and constraints passed in via the tuple constraint struct.
1847 * NOTE: only pre-cooked expressions will be passed this way, which is to
1848 * say expressions inherited from an existing relation. Newly parsed
1849 * expressions can be added later, by direct calls to StoreAttrDefault
1850 * and StoreRelCheck (see AddRelationRawConstraints()). We assume that
1851 * pg_attribute and pg_class entries for the relation were already set
1852 * to reflect the existence of these defaults/constraints.
1855 StoreConstraints(Relation rel)
1857 TupleConstr *constr = rel->rd_att->constr;
1864 * deparsing of constraint expressions will fail unless the
1865 * just-created pg_attribute tuples for this relation are made
1866 * visible. So, bump the command counter.
1868 CommandCounterIncrement();
1870 for (i = 0; i < constr->num_defval; i++)
1871 StoreAttrDefault(rel, constr->defval[i].adnum,
1872 constr->defval[i].adbin, false);
1874 for (i = 0; i < constr->num_check; i++)
1875 StoreRelCheck(rel, constr->check[i].ccname,
1876 constr->check[i].ccbin);
1880 * AddRelationRawConstraints
1882 * Add raw (not-yet-transformed) column default expressions and/or constraint
1883 * check expressions to an existing relation. This is defined to do both
1884 * for efficiency in DefineRelation, but of course you can do just one or
1885 * the other by passing empty lists.
1887 * rel: relation to be modified
1888 * rawColDefaults: list of RawColumnDefault structures
1889 * rawConstraints: list of Constraint nodes
1891 * All entries in rawColDefaults will be processed. Entries in rawConstraints
1892 * will be processed only if they are CONSTR_CHECK type and contain a "raw"
1895 * NB: caller should have opened rel with AccessExclusiveLock, and should
1896 * hold that lock till end of transaction. Also, we assume the caller has
1897 * done a CommandCounterIncrement if necessary to make the relation's catalog
1901 AddRelationRawConstraints(Relation rel,
1902 List *rawColDefaults,
1903 List *rawConstraints)
1905 char *relname = RelationGetRelationName(rel);
1906 TupleDesc tupleDesc;
1907 TupleConstr *oldconstr;
1909 ConstrCheck *oldchecks;
1914 Relation relidescs[Num_pg_class_indices];
1916 Form_pg_class relStruct;
1919 * Get info about existing constraints.
1921 tupleDesc = RelationGetDescr(rel);
1922 oldconstr = tupleDesc->constr;
1925 numoldchecks = oldconstr->num_check;
1926 oldchecks = oldconstr->check;
1935 * Create a dummy ParseState and insert the target relation as its
1936 * sole rangetable entry. We need a ParseState for transformExpr.
1938 pstate = make_parsestate(NULL);
1939 makeRangeTable(pstate, NULL);
1940 addRangeTableEntry(pstate, relname, makeAttr(relname, NULL), false, true, true);
1943 * Process column default expressions.
1945 foreach(listptr, rawColDefaults)
1947 RawColumnDefault *colDef = (RawColumnDefault *) lfirst(listptr);
1951 Assert(colDef->raw_default != NULL);
1954 * Transform raw parsetree to executable expression.
1956 expr = transformExpr(pstate, colDef->raw_default, EXPR_COLUMN_FIRST);
1959 * Make sure default expr does not refer to any vars.
1961 if (contain_var_clause(expr))
1962 elog(ERROR, "Cannot use attribute(s) in DEFAULT clause");
1965 * Check that it will be possible to coerce the expression to the
1966 * column's type. We store the expression without coercion,
1967 * however, to avoid premature coercion in cases like
1969 * CREATE TABLE tbl (fld datetime DEFAULT 'now');
1971 * NB: this should match the code in updateTargetListEntry() that
1972 * will actually do the coercion, to ensure we don't accept an
1973 * unusable default expression.
1975 type_id = exprType(expr);
1976 if (type_id != InvalidOid)
1978 Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];
1980 if (type_id != atp->atttypid)
1982 if (CoerceTargetExpr(NULL, expr, type_id,
1983 atp->atttypid, atp->atttypmod) == NULL)
1984 elog(ERROR, "Attribute '%s' is of type '%s'"
1985 " but default expression is of type '%s'"
1986 "\n\tYou will need to rewrite or cast the expression",
1987 NameStr(atp->attname),
1988 typeidTypeName(atp->atttypid),
1989 typeidTypeName(type_id));
1994 * Might as well try to reduce any constant expressions.
1996 expr = eval_const_expressions(expr);
1999 * Must fix opids, in case any operators remain...
2006 StoreAttrDefault(rel, colDef->attnum, nodeToString(expr), true);
2010 * Process constraint expressions.
2012 numchecks = numoldchecks;
2013 foreach(listptr, rawConstraints)
2015 Constraint *cdef = (Constraint *) lfirst(listptr);
2019 if (cdef->contype != CONSTR_CHECK || cdef->raw_expr == NULL)
2021 Assert(cdef->cooked_expr == NULL);
2023 /* Check name uniqueness, or generate a new name */
2024 if (cdef->name != NULL)
2029 ccname = cdef->name;
2030 /* Check against old constraints */
2031 for (i = 0; i < numoldchecks; i++)
2033 if (strcmp(oldchecks[i].ccname, ccname) == 0)
2034 elog(ERROR, "Duplicate CHECK constraint name: '%s'",
2037 /* Check against other new constraints */
2038 foreach(listptr2, rawConstraints)
2040 Constraint *cdef2 = (Constraint *) lfirst(listptr2);
2042 if (cdef2 == cdef ||
2043 cdef2->contype != CONSTR_CHECK ||
2044 cdef2->raw_expr == NULL ||
2045 cdef2->name == NULL)
2047 if (strcmp(cdef2->name, ccname) == 0)
2048 elog(ERROR, "Duplicate CHECK constraint name: '%s'",
2054 ccname = (char *) palloc(NAMEDATALEN);
2055 snprintf(ccname, NAMEDATALEN, "$%d", numchecks + 1);
2059 * Transform raw parsetree to executable expression.
2061 expr = transformExpr(pstate, cdef->raw_expr, EXPR_COLUMN_FIRST);
2064 * Make sure it yields a boolean result.
2066 if (exprType(expr) != BOOLOID)
2067 elog(ERROR, "CHECK '%s' does not yield boolean result",
2071 * Make sure no outside relations are referred to.
2073 if (length(pstate->p_rtable) != 1)
2074 elog(ERROR, "Only relation '%s' can be referenced in CHECK",
2078 * Might as well try to reduce any constant expressions.
2080 expr = eval_const_expressions(expr);
2083 * Constraints are evaluated with execQual, which expects an
2084 * implicit-AND list, so convert expression to implicit-AND form.
2085 * (We could go so far as to convert to CNF, but that's probably
2088 expr = (Node *) make_ands_implicit((Expr *) expr);
2091 * Must fix opids in operator clauses.
2098 StoreRelCheck(rel, ccname, nodeToString(expr));
2104 * Update the count of constraints in the relation's pg_class tuple.
2105 * We do this even if there was no change, in order to ensure that an
2106 * SI update message is sent out for the pg_class tuple, which will
2107 * force other backends to rebuild their relcache entries for the rel.
2108 * (Of course, for a newly created rel there is no need for an SI
2109 * message, but for ALTER TABLE ADD ATTRIBUTE this'd be important.)
2111 relrel = heap_openr(RelationRelationName, RowExclusiveLock);
2112 reltup = SearchSysCacheTupleCopy(RELOID,
2113 ObjectIdGetDatum(RelationGetRelid(rel)),
2115 if (!HeapTupleIsValid(reltup))
2116 elog(ERROR, "cache lookup of relation %u failed", RelationGetRelid(rel));
2117 relStruct = (Form_pg_class) GETSTRUCT(reltup);
2119 relStruct->relchecks = numchecks;
2121 heap_update(relrel, &reltup->t_self, reltup, NULL);
2123 /* keep catalog indices current */
2124 CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices,
2126 CatalogIndexInsert(relidescs, Num_pg_class_indices, relrel, reltup);
2127 CatalogCloseIndices(Num_pg_class_indices, relidescs);
2129 heap_close(relrel, RowExclusiveLock);
2130 heap_freetuple(reltup);
2134 RemoveAttrDefault(Relation rel)
2137 HeapScanDesc adscan;
2141 adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
2143 ScanKeyEntryInitialize(&key, 0, Anum_pg_attrdef_adrelid,
2144 F_OIDEQ, RelationGetRelid(rel));
2146 adscan = heap_beginscan(adrel, 0, SnapshotNow, 1, &key);
2148 while (HeapTupleIsValid(tup = heap_getnext(adscan, 0)))
2149 heap_delete(adrel, &tup->t_self, NULL);
2151 heap_endscan(adscan);
2152 heap_close(adrel, RowExclusiveLock);
2156 RemoveRelCheck(Relation rel)
2159 HeapScanDesc rcscan;
2163 rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock);
2165 ScanKeyEntryInitialize(&key, 0, Anum_pg_relcheck_rcrelid,
2166 F_OIDEQ, RelationGetRelid(rel));
2168 rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key);
2170 while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0)))
2171 heap_delete(rcrel, &tup->t_self, NULL);
2173 heap_endscan(rcscan);
2174 heap_close(rcrel, RowExclusiveLock);
2178 RemoveConstraints(Relation rel)
2180 TupleConstr *constr = rel->rd_att->constr;
2185 if (constr->num_defval > 0)
2186 RemoveAttrDefault(rel);
2188 if (constr->num_check > 0)
2189 RemoveRelCheck(rel);
2193 RemoveStatistics(Relation rel)
2195 Relation pgstatistic;
2200 pgstatistic = heap_openr(StatisticRelationName, RowExclusiveLock);
2202 ScanKeyEntryInitialize(&key, 0x0, Anum_pg_statistic_starelid,
2204 ObjectIdGetDatum(RelationGetRelid(rel)));
2205 scan = heap_beginscan(pgstatistic, false, SnapshotNow, 1, &key);
2207 while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
2208 heap_delete(pgstatistic, &tuple->t_self, NULL);
2211 heap_close(pgstatistic, RowExclusiveLock);