]> granicus.if.org Git - postgresql/blob - src/backend/catalog/heap.c
Reimplement parsing and storage of default expressions and constraint
[postgresql] / src / backend / catalog / heap.c
1 /*-------------------------------------------------------------------------
2  *
3  * heap.c
4  *        code to create and destroy POSTGRES heap relations
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.100 1999/10/03 23:55:26 tgl Exp $
11  *
12  *
13  * INTERFACE ROUTINES
14  *              heap_create()                   - Create an uncataloged heap relation
15  *              heap_create_with_catalog() - Create a cataloged relation
16  *              heap_destroy_with_catalog() - Removes named relation from catalogs
17  *
18  * NOTES
19  *        this code taken from access/heap/create.c, which contains
20  *        the old heap_create_with_catalog, amcreate, and amdestroy.
21  *        those routines will soon call these routines using the function
22  *        manager,
23  *        just like the poorly named "NewXXX" routines do.      The
24  *        "New" routines are all going to die soon, once and for all!
25  *              -cim 1/13/91
26  *
27  *-------------------------------------------------------------------------
28  */
29 #include "postgres.h"
30 #include "miscadmin.h"
31
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_index.h"
42 #include "catalog/pg_inherits.h"
43 #include "catalog/pg_ipl.h"
44 #include "catalog/pg_proc.h"
45 #include "catalog/pg_relcheck.h"
46 #include "commands/trigger.h"
47 #include "optimizer/clauses.h"
48 #include "optimizer/planmain.h"
49 #include "optimizer/tlist.h"
50 #include "optimizer/var.h"
51 #include "parser/parse_clause.h"
52 #include "parser/parse_coerce.h"
53 #include "parser/parse_expr.h"
54 #include "parser/parse_relation.h"
55 #include "rewrite/rewriteRemove.h"
56 #include "storage/smgr.h"
57 #include "tcop/tcopprot.h"
58 #include "utils/builtins.h"
59 #include "utils/portal.h"
60 #include "utils/relcache.h"
61 #include "utils/syscache.h"
62 #include "utils/temprel.h"
63
64
65 static void AddNewRelationTuple(Relation pg_class_desc,
66                                   Relation new_rel_desc, Oid new_rel_oid, unsigned natts,
67                                         char relkind, char *temp_relname);
68 static void AddToNoNameRelList(Relation r);
69 static void DeleteAttributeTuples(Relation rel);
70 static void DeleteRelationTuple(Relation rel);
71 static void DeleteTypeTuple(Relation rel);
72 static void RelationRemoveIndexes(Relation relation);
73 static void RelationRemoveInheritance(Relation relation);
74 static void RemoveFromNoNameRelList(Relation r);
75 static void AddNewRelationType(char *typeName, Oid new_rel_oid);
76 static void StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin,
77                                                          bool updatePgAttribute);
78 static void StoreRelCheck(Relation rel, char *ccname, char *ccbin);
79 static void StoreConstraints(Relation rel);
80 static void RemoveConstraints(Relation rel);
81
82
83 /* ----------------------------------------------------------------
84  *                              XXX UGLY HARD CODED BADNESS FOLLOWS XXX
85  *
86  *              these should all be moved to someplace in the lib/catalog
87  *              module, if not obliterated first.
88  * ----------------------------------------------------------------
89  */
90
91
92 /*
93  * Note:
94  *              Should the executor special case these attributes in the future?
95  *              Advantage:      consume 1/2 the space in the ATTRIBUTE relation.
96  *              Disadvantage:  having rules to compute values in these tuples may
97  *                              be more difficult if not impossible.
98  */
99
100 static FormData_pg_attribute a1 = {
101         0xffffffff, {"ctid"}, TIDOID, 0, sizeof(ItemPointerData),
102         SelfItemPointerAttributeNumber, 0, -1, -1, '\0', '\0', 'i', '\0', '\0'
103 };
104
105 static FormData_pg_attribute a2 = {
106         0xffffffff, {"oid"}, OIDOID, 0, sizeof(Oid),
107         ObjectIdAttributeNumber, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'
108 };
109
110 static FormData_pg_attribute a3 = {
111         0xffffffff, {"xmin"}, XIDOID, 0, sizeof(TransactionId),
112         MinTransactionIdAttributeNumber, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'
113 };
114
115 static FormData_pg_attribute a4 = {
116         0xffffffff, {"cmin"}, CIDOID, 0, sizeof(CommandId),
117         MinCommandIdAttributeNumber, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'
118 };
119
120 static FormData_pg_attribute a5 = {
121         0xffffffff, {"xmax"}, XIDOID, 0, sizeof(TransactionId),
122         MaxTransactionIdAttributeNumber, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'
123 };
124
125 static FormData_pg_attribute a6 = {
126         0xffffffff, {"cmax"}, CIDOID, 0, sizeof(CommandId),
127         MaxCommandIdAttributeNumber, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'
128 };
129
130 static Form_pg_attribute HeapAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6};
131
132 /* ----------------------------------------------------------------
133  *                              XXX END OF UGLY HARD CODED BADNESS XXX
134  * ----------------------------------------------------------------
135  */
136
137 /* the tempRelList holds
138    the list of temporary uncatalogued relations that are created.
139    these relations should be destroyed at the end of transactions
140 */
141 typedef struct tempRelList
142 {
143         Relation   *rels;                       /* array of relation descriptors */
144         int                     num;                    /* number of temporary relations */
145         int                     size;                   /* size of space allocated for the rels
146                                                                  * array */
147 } TempRelList;
148
149 #define NONAME_REL_LIST_SIZE    32
150
151 static TempRelList *tempRels = NULL;
152
153
154 /* ----------------------------------------------------------------
155  *              heap_create             - Create an uncataloged heap relation
156  *
157  *              Fields relpages, reltuples, reltuples, relkeys, relhistory,
158  *              relisindexed, and relkind of rel->rd_rel are initialized
159  *              to all zeros, as are rd_last and rd_hook.  Rd_refcnt is set to 1.
160  *
161  *              Remove the system relation specific code to elsewhere eventually.
162  *
163  *              Eventually, must place information about this temporary relation
164  *              into the transaction context block.
165  *
166  *
167  * if heap_create is called with "" as the name, then heap_create will create
168  * a temporary name "pg_noname.$PID.$SEQUENCE" for the relation
169  * ----------------------------------------------------------------
170  */
171 Relation
172 heap_create(char *relname,
173                         TupleDesc tupDesc,
174                         bool isnoname,
175                         bool istemp)
176 {
177         unsigned        i;
178         Oid                     relid;
179         Relation        rel;
180         int                     len;
181         bool            nailme = false;
182         int                     natts = tupDesc->natts;
183         static unsigned int uniqueId = 0;
184
185         extern GlobalMemory CacheCxt;
186         MemoryContext oldcxt;
187
188
189         /* ----------------
190          *      sanity checks
191          * ----------------
192          */
193         AssertArg(natts > 0);
194
195         if (relname && !allowSystemTableMods && IsSystemRelationName(relname) && IsNormalProcessingMode())
196         {
197                 elog(ERROR, "Illegal class name '%s'"
198                          "\n\tThe 'pg_' name prefix is reserved for system catalogs",
199                          relname);
200         }
201
202         /* ----------------
203          *      switch to the cache context so that we don't lose
204          *      allocations at the end of this transaction, I guess.
205          *      -cim 6/14/90
206          * ----------------
207          */
208         if (!CacheCxt)
209                 CacheCxt = CreateGlobalMemory("Cache");
210
211         oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
212
213         /* ----------------
214          *      real ugly stuff to assign the proper relid in the relation
215          *      descriptor follows.
216          * ----------------
217          */
218         if (relname && !strcmp(RelationRelationName, relname))
219         {
220                 relid = RelOid_pg_class;
221                 nailme = true;
222         }
223         else if (relname && !strcmp(AttributeRelationName, relname))
224         {
225                 relid = RelOid_pg_attribute;
226                 nailme = true;
227         }
228         else if (relname && !strcmp(ProcedureRelationName, relname))
229         {
230                 relid = RelOid_pg_proc;
231                 nailme = true;
232         }
233         else if (relname && !strcmp(TypeRelationName, relname))
234         {
235                 relid = RelOid_pg_type;
236                 nailme = true;
237         }
238         else
239                 relid = newoid();
240
241         if (isnoname)
242         {
243                 Assert(!relname);
244                 relname = palloc(NAMEDATALEN);
245                 snprintf(relname, NAMEDATALEN, "pg_noname.%d.%u",
246                                  (int) MyProcPid, uniqueId++);
247         }
248
249         if (istemp)
250         {
251                 /* replace relname of caller */
252                 snprintf(relname, NAMEDATALEN, "pg_temp.%d.%u", MyProcPid, uniqueId++);
253         }
254
255         /* ----------------
256          *      allocate a new relation descriptor.
257          * ----------------
258          */
259         len = sizeof(RelationData);
260
261         rel = (Relation) palloc(len);
262         MemSet((char *) rel, 0, len);
263
264         /*
265          * create a new tuple descriptor from the one passed in
266          */
267         rel->rd_att = CreateTupleDescCopyConstr(tupDesc);
268
269         /* ----------------
270          *      nail the reldesc if this is a bootstrap create reln and
271          *      we may need it in the cache later on in the bootstrap
272          *      process so we don't ever want it kicked out.  e.g. pg_attribute!!!
273          * ----------------
274          */
275         if (nailme)
276                 rel->rd_isnailed = true;
277
278         RelationSetReferenceCount(rel, 1);
279
280         rel->rd_rel = (Form_pg_class) palloc(sizeof *rel->rd_rel);
281
282         /* ----------------
283          *      initialize the fields of our new relation descriptor
284          * ----------------
285          */
286         MemSet((char *) rel->rd_rel, 0, sizeof *rel->rd_rel);
287         namestrcpy(&(rel->rd_rel->relname), relname);
288         rel->rd_rel->relkind = RELKIND_UNCATALOGED;
289         rel->rd_rel->relnatts = natts;
290         if (tupDesc->constr)
291                 rel->rd_rel->relchecks = tupDesc->constr->num_check;
292
293         for (i = 0; i < natts; i++)
294                 rel->rd_att->attrs[i]->attrelid = relid;
295
296         RelationGetRelid(rel) = relid;
297
298         if (nailme)
299         {
300                 /* for system relations, set the reltype field here */
301                 rel->rd_rel->reltype = relid;
302         }
303
304         /* ----------------
305          *      remember if this is a noname relation
306          * ----------------
307          */
308         rel->rd_isnoname = isnoname;
309
310         /* ----------------
311          *      have the storage manager create the relation.
312          * ----------------
313          */
314
315         rel->rd_nonameunlinked = TRUE;          /* change once table is created */
316         rel->rd_fd = (File) smgrcreate(DEFAULT_SMGR, rel);
317         rel->rd_nonameunlinked = FALSE;
318
319         RelationRegisterRelation(rel);
320
321         MemoryContextSwitchTo(oldcxt);
322
323         /*
324          * add all noname relations to the tempRels list so they can be
325          * properly disposed of at the end of transaction
326          */
327         if (isnoname)
328                 AddToNoNameRelList(rel);
329
330         return rel;
331 }
332
333
334 /* ----------------------------------------------------------------
335  *              heap_create_with_catalog                - Create a cataloged relation
336  *
337  *              this is done in 6 steps:
338  *
339  *              1) CheckAttributeNames() is used to make certain the tuple
340  *                 descriptor contains a valid set of attribute names
341  *
342  *              2) pg_class is opened and RelationFindRelid()
343  *                 preforms a scan to ensure that no relation with the
344  *                 same name already exists.
345  *
346  *              3) heap_create_with_catalog() is called to create the new relation
347  *                 on disk.
348  *
349  *              4) TypeDefine() is called to define a new type corresponding
350  *                 to the new relation.
351  *
352  *              5) AddNewAttributeTuples() is called to register the
353  *                 new relation's schema in pg_attribute.
354  *
355  *              6) AddNewRelationTuple() is called to register the
356  *                 relation itself in the catalogs.
357  *
358  *              7) StoreConstraints is called ()                - vadim 08/22/97
359  *
360  *              8) the relations are closed and the new relation's oid
361  *                 is returned.
362  *
363  * old comments:
364  *              A new relation is inserted into the RELATION relation
365  *              with the specified attribute(s) (newly inserted into
366  *              the ATTRIBUTE relation).  How does concurrency control
367  *              work?  Is it automatic now?  Expects the caller to have
368  *              attname, atttypid, atttyparg, attproc, and attlen domains filled.
369  *              Create fills the attnum domains sequentually from zero,
370  *              fills the attdisbursion domains with zeros, and fills the
371  *              attrelid fields with the relid.
372  *
373  *              scan relation catalog for name conflict
374  *              scan type catalog for typids (if not arg)
375  *              create and insert attribute(s) into attribute catalog
376  *              create new relation
377  *              insert new relation into attribute catalog
378  *
379  *              Should coordinate with heap_create_with_catalog(). Either
380  *              it should not be called or there should be a way to prevent
381  *              the relation from being removed at the end of the
382  *              transaction if it is successful ('u'/'r' may be enough).
383  *              Also, if the transaction does not commit, then the
384  *              relation should be removed.
385  *
386  *              XXX amcreate ignores "off" when inserting (for now).
387  *              XXX amcreate (like the other utilities) needs to understand indexes.
388  *
389  * ----------------------------------------------------------------
390  */
391
392 /* --------------------------------
393  *              CheckAttributeNames
394  *
395  *              this is used to make certain the tuple descriptor contains a
396  *              valid set of attribute names.  a problem simply generates
397  *              elog(ERROR) which aborts the current transaction.
398  * --------------------------------
399  */
400 static void
401 CheckAttributeNames(TupleDesc tupdesc)
402 {
403         unsigned        i;
404         unsigned        j;
405         int                     natts = tupdesc->natts;
406
407         /* ----------------
408          *      first check for collision with system attribute names
409          * ----------------
410          *
411          *       also, warn user if attribute to be created has
412          *       an unknown typid  (usually as a result of a 'retrieve into'
413          *        - jolly
414          */
415         for (i = 0; i < natts; i += 1)
416         {
417                 for (j = 0; j < sizeof HeapAtt / sizeof HeapAtt[0]; j += 1)
418                 {
419                         if (nameeq(&(HeapAtt[j]->attname),
420                                            &(tupdesc->attrs[i]->attname)))
421                         {
422                                 elog(ERROR, "Attribute '%s' has a name conflict"
423                                          "\n\tName matches an existing system attribute",
424                                          HeapAtt[j]->attname.data);
425                         }
426                 }
427                 if (tupdesc->attrs[i]->atttypid == UNKNOWNOID)
428                 {
429                         elog(NOTICE, "Attribute '%s' has an unknown type"
430                                  "\n\tRelation created; continue",
431                                  tupdesc->attrs[i]->attname.data);
432                 }
433         }
434
435         /* ----------------
436          *      next check for repeated attribute names
437          * ----------------
438          */
439         for (i = 1; i < natts; i += 1)
440         {
441                 for (j = 0; j < i; j += 1)
442                 {
443                         if (nameeq(&(tupdesc->attrs[j]->attname),
444                                            &(tupdesc->attrs[i]->attname)))
445                         {
446                                 elog(ERROR, "Attribute '%s' is repeated",
447                                          tupdesc->attrs[j]->attname.data);
448                         }
449                 }
450         }
451 }
452
453 /* --------------------------------
454  *              RelnameFindRelid
455  *
456  *              this preforms a scan of pg_class to ensure that
457  *              no relation with the same name already exists.
458  * --------------------------------
459  */
460 Oid
461 RelnameFindRelid(char *relname)
462 {
463         HeapTuple       tuple;
464         Oid                     relid;
465
466         /*
467          * If this is not bootstrap (initdb) time, use the catalog index on
468          * pg_class.
469          */
470         if (!IsBootstrapProcessingMode())
471         {
472                 tuple = SearchSysCacheTuple(RELNAME,
473                                                                         PointerGetDatum(relname),
474                                                                         0, 0, 0);
475                 if (HeapTupleIsValid(tuple))
476                         relid = tuple->t_data->t_oid;
477                 else
478                         relid = InvalidOid;
479         }
480         else
481         {
482                 Relation        pg_class_desc;
483                 ScanKeyData key;
484                 HeapScanDesc pg_class_scan;
485
486                 pg_class_desc = heap_openr(RelationRelationName, AccessShareLock);
487
488                 /* ----------------
489                  *      At bootstrap time, we have to do this the hard way.  Form the
490                  *      scan key.
491                  * ----------------
492                  */
493                 ScanKeyEntryInitialize(&key,
494                                                            0,
495                                                            (AttrNumber) Anum_pg_class_relname,
496                                                            (RegProcedure) F_NAMEEQ,
497                                                            (Datum) relname);
498
499                 /* ----------------
500                  *      begin the scan
501                  * ----------------
502                  */
503                 pg_class_scan = heap_beginscan(pg_class_desc,
504                                                                            0,
505                                                                            SnapshotNow,
506                                                                            1,
507                                                                            &key);
508
509                 /* ----------------
510                  *      get a tuple.  if the tuple is NULL then it means we
511                  *      didn't find an existing relation.
512                  * ----------------
513                  */
514                 tuple = heap_getnext(pg_class_scan, 0);
515
516                 if (HeapTupleIsValid(tuple))
517                         relid = tuple->t_data->t_oid;
518                 else
519                         relid = InvalidOid;
520
521                 heap_endscan(pg_class_scan);
522
523                 heap_close(pg_class_desc, AccessShareLock);
524         }
525         return relid;
526 }
527
528 /* --------------------------------
529  *              AddNewAttributeTuples
530  *
531  *              this registers the new relation's schema by adding
532  *              tuples to pg_attribute.
533  * --------------------------------
534  */
535 static void
536 AddNewAttributeTuples(Oid new_rel_oid,
537                                           TupleDesc tupdesc)
538 {
539         Form_pg_attribute *dpp;
540         unsigned        i;
541         HeapTuple       tup;
542         Relation        rel;
543         bool            hasindex;
544         Relation        idescs[Num_pg_attr_indices];
545         int                     natts = tupdesc->natts;
546
547         /* ----------------
548          *      open pg_attribute
549          * ----------------
550          */
551         rel = heap_openr(AttributeRelationName, RowExclusiveLock);
552
553         /* -----------------
554          * Check if we have any indices defined on pg_attribute.
555          * -----------------
556          */
557         hasindex = RelationGetForm(rel)->relhasindex;
558         if (hasindex)
559                 CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
560
561         /* ----------------
562          *      initialize tuple descriptor.  Note we use setheapoverride()
563          *      so that we can see the effects of our TypeDefine() done
564          *      previously.
565          * ----------------
566          */
567         setheapoverride(true);
568         fillatt(tupdesc);
569         setheapoverride(false);
570
571         /* ----------------
572          *      first we add the user attributes..
573          * ----------------
574          */
575         dpp = tupdesc->attrs;
576         for (i = 0; i < natts; i++)
577         {
578                 (*dpp)->attrelid = new_rel_oid;
579                 (*dpp)->attdisbursion = 0;
580
581                 tup = heap_addheader(Natts_pg_attribute,
582                                                          ATTRIBUTE_TUPLE_SIZE,
583                                                          (char *) *dpp);
584
585                 heap_insert(rel, tup);
586
587                 if (hasindex)
588                         CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
589
590                 pfree(tup);
591                 dpp++;
592         }
593
594         /* ----------------
595          *      next we add the system attributes..
596          * ----------------
597          */
598         dpp = HeapAtt;
599         for (i = 0; i < -1 - FirstLowInvalidHeapAttributeNumber; i++)
600         {
601                 (*dpp)->attrelid = new_rel_oid;
602                 /* (*dpp)->attdisbursion = 0;      unneeded */
603
604                 tup = heap_addheader(Natts_pg_attribute,
605                                                          ATTRIBUTE_TUPLE_SIZE,
606                                                          (char *) *dpp);
607
608                 heap_insert(rel, tup);
609
610                 if (hasindex)
611                         CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
612
613                 pfree(tup);
614                 dpp++;
615         }
616
617         heap_close(rel, RowExclusiveLock);
618
619         /*
620          * close pg_attribute indices
621          */
622         if (hasindex)
623                 CatalogCloseIndices(Num_pg_attr_indices, idescs);
624 }
625
626 /* --------------------------------
627  *              AddNewRelationTuple
628  *
629  *              this registers the new relation in the catalogs by
630  *              adding a tuple to pg_class.
631  * --------------------------------
632  */
633 static void
634 AddNewRelationTuple(Relation pg_class_desc,
635                                         Relation new_rel_desc,
636                                         Oid new_rel_oid,
637                                         unsigned natts,
638                                         char relkind,
639                                         char *temp_relname)
640 {
641         Form_pg_class new_rel_reltup;
642         HeapTuple       tup;
643         Relation        idescs[Num_pg_class_indices];
644         bool            isBootstrap;
645
646         /* ----------------
647          *      first we munge some of the information in our
648          *      uncataloged relation's relation descriptor.
649          * ----------------
650          */
651         new_rel_reltup = new_rel_desc->rd_rel;
652
653         /* CHECK should get new_rel_oid first via an insert then use XXX */
654
655         /* ----------------
656          * Here we insert bogus estimates of the size of the new relation.
657          * In reality, of course, the new relation has 0 tuples and pages,
658          * and if we were tracking these statistics accurately then we'd
659          * set the fields that way.  But at present the stats will be updated
660          * only by VACUUM or CREATE INDEX, and the user might insert a lot of
661          * tuples before he gets around to doing either of those.  So, instead
662          * of saying the relation is empty, we insert guesstimates.  The point
663          * is to keep the optimizer from making really stupid choices on
664          * never-yet-vacuumed tables; so the estimates need only be large
665          * enough to discourage the optimizer from using nested-loop plans.
666          * With this hack, nested-loop plans will be preferred only after
667          * the table has been proven to be small by VACUUM or CREATE INDEX.
668          * Maintaining the stats on-the-fly would solve the problem more cleanly,
669          * but the overhead of that would likely cost more than it'd save.
670          * (NOTE: CREATE INDEX inserts the same bogus estimates if it finds the
671          * relation has 0 rows and pages. See index.c.)
672          * ----------------
673          */
674         new_rel_reltup->relpages = 10;          /* bogus estimates */
675         new_rel_reltup->reltuples = 1000;
676
677         new_rel_reltup->relowner = GetUserId();
678         new_rel_reltup->relkind = relkind;
679         new_rel_reltup->relnatts = natts;
680
681         /* ----------------
682          *      now form a tuple to add to pg_class
683          *      XXX Natts_pg_class_fixed is a hack - see pg_class.h
684          * ----------------
685          */
686         tup = heap_addheader(Natts_pg_class_fixed,
687                                                  CLASS_TUPLE_SIZE,
688                                                  (char *) new_rel_reltup);
689         tup->t_data->t_oid = new_rel_oid;
690
691         /* ----------------
692          *      finally insert the new tuple and free it.
693          *
694          *      Note: I have no idea why we do a
695          *                      SetProcessingMode(BootstrapProcessing);
696          *                here -cim 6/14/90
697          * ----------------
698          */
699         isBootstrap = IsBootstrapProcessingMode() ? true : false;
700
701         SetProcessingMode(BootstrapProcessing);
702
703         heap_insert(pg_class_desc, tup);
704
705         if (temp_relname)
706                 create_temp_relation(temp_relname, tup);
707
708         if (!isBootstrap)
709         {
710
711                 /*
712                  * First, open the catalog indices and insert index tuples for the
713                  * new relation.
714                  */
715
716                 CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
717                 CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class_desc, tup);
718                 CatalogCloseIndices(Num_pg_class_indices, idescs);
719                 /* now restore processing mode */
720                 SetProcessingMode(NormalProcessing);
721         }
722
723         pfree(tup);
724 }
725
726
727 /* --------------------------------
728  *              AddNewRelationType -
729  *
730  *              define a complex type corresponding to the new relation
731  * --------------------------------
732  */
733 static void
734 AddNewRelationType(char *typeName, Oid new_rel_oid)
735 {
736         Oid                     new_type_oid;
737
738         /*
739          * The sizes are set to oid size because it makes implementing sets
740          * MUCH easier, and no one (we hope) uses these fields to figure out
741          * how much space to allocate for the type. An oid is the type used
742          * for a set definition.  When a user requests a set, what they
743          * actually get is the oid of a tuple in the pg_proc catalog, so the
744          * size of the "set" is the size of an oid. Similarly, byval being
745          * true makes sets much easier, and it isn't used by anything else.
746          * Note the assumption that OIDs are the same size as int4s.
747          */
748         new_type_oid = TypeCreate(typeName, /* type name */
749                                                           new_rel_oid,          /* relation oid */
750                                                           typeLen(typeidType(OIDOID)),          /* internal size */
751                                                           typeLen(typeidType(OIDOID)),          /* external size */
752                                                           'c',          /* type-type (catalog) */
753                                                           ',',          /* default array delimiter */
754                                                           "int4in", /* input procedure */
755                                                           "int4out",            /* output procedure */
756                                                           "int4in", /* receive procedure */
757                                                           "int4out",            /* send procedure */
758                                                           NULL,         /* array element type - irrelevent */
759                                                           "-",          /* default type value */
760                                                           (bool) 1, /* passed by value */
761                                                           'i');         /* default alignment */
762 }
763
764 /* --------------------------------
765  *              heap_create_with_catalog
766  *
767  *              creates a new cataloged relation.  see comments above.
768  * --------------------------------
769  */
770 Oid
771 heap_create_with_catalog(char *relname,
772                                                  TupleDesc tupdesc,
773                                                  char relkind,
774                                                  bool istemp)
775 {
776         Relation        pg_class_desc;
777         Relation        new_rel_desc;
778         Oid                     new_rel_oid;
779         int                     natts = tupdesc->natts;
780         char       *temp_relname = NULL;
781
782         /* ----------------
783          *      sanity checks
784          * ----------------
785          */
786         Assert(IsNormalProcessingMode() || IsBootstrapProcessingMode());
787         if (natts == 0 || natts > MaxHeapAttributeNumber)
788                 elog(ERROR, "Number of attributes is out of range"
789                          "\n\tFrom 1 to %d attributes may be specified",
790                          MaxHeapAttributeNumber);
791
792         CheckAttributeNames(tupdesc);
793
794         /* temp tables can mask non-temp tables */
795         if ((!istemp && RelnameFindRelid(relname)) ||
796                 (istemp && get_temp_rel_by_name(relname) != NULL))
797                 elog(ERROR, "Relation '%s' already exists", relname);
798
799         /* save user relation name because heap_create changes it */
800         if (istemp)
801         {
802                 temp_relname = pstrdup(relname);                /* save original value */
803                 relname = palloc(NAMEDATALEN);
804                 strcpy(relname, temp_relname);  /* heap_create will change this */
805         }
806
807         /* ----------------
808          *      ok, relation does not already exist so now we
809          *      create an uncataloged relation and pull its relation oid
810          *      from the newly formed relation descriptor.
811          *
812          *      Note: The call to heap_create() does all the "real" work
813          *      of creating the disk file for the relation.
814          *      This changes relname for noname and temp tables.
815          * ----------------
816          */
817         new_rel_desc = heap_create(relname, tupdesc, false, istemp);
818
819         new_rel_oid = new_rel_desc->rd_att->attrs[0]->attrelid;
820
821         /* ----------------
822          *      since defining a relation also defines a complex type,
823          *      we add a new system type corresponding to the new relation.
824          * ----------------
825          */
826         AddNewRelationType(relname, new_rel_oid);
827
828         /* ----------------
829          *      now add tuples to pg_attribute for the attributes in
830          *      our new relation.
831          * ----------------
832          */
833         AddNewAttributeTuples(new_rel_oid, tupdesc);
834
835         /* ----------------
836          *      now update the information in pg_class.
837          * ----------------
838          */
839         pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock);
840
841         AddNewRelationTuple(pg_class_desc,
842                                                 new_rel_desc,
843                                                 new_rel_oid,
844                                                 natts,
845                                                 relkind,
846                                                 temp_relname);
847
848         StoreConstraints(new_rel_desc);
849
850         if (istemp)
851         {
852                 pfree(relname);
853                 pfree(temp_relname);
854         }
855
856         /* ----------------
857          *      ok, the relation has been cataloged, so close our relations
858          *      and return the oid of the newly created relation.
859          *
860          *      SOMEDAY: fill the STATISTIC relation properly.
861          * ----------------
862          */
863         heap_close(new_rel_desc, NoLock); /* do not unlock till end of xact */
864         heap_close(pg_class_desc, RowExclusiveLock);
865
866         return new_rel_oid;
867 }
868
869
870 /* ----------------------------------------------------------------
871  *              heap_destroy_with_catalog       - removes all record of named relation from catalogs
872  *
873  *              1)      open relation, check for existence, etc.
874  *              2)      remove inheritance information
875  *              3)      remove indexes
876  *              4)      remove pg_class tuple
877  *              5)      remove pg_attribute tuples
878  *              6)      remove pg_type tuples
879  *              7)      RemoveConstraints ()
880  *              8)      unlink relation
881  *
882  * old comments
883  *              Except for vital relations, removes relation from
884  *              relation catalog, and related attributes from
885  *              attribute catalog (needed?).  (Anything else?)
886  *
887  *              get proper relation from relation catalog (if not arg)
888  *              check if relation is vital (strcmp()/reltype?)
889  *              scan attribute catalog deleting attributes of reldesc
890  *                              (necessary?)
891  *              delete relation from relation catalog
892  *              (How are the tuples of the relation discarded?)
893  *
894  *              XXX Must fix to work with indexes.
895  *              There may be a better order for doing things.
896  *              Problems with destroying a deleted database--cannot create
897  *              a struct reldesc without having an open file descriptor.
898  * ----------------------------------------------------------------
899  */
900
901 /* --------------------------------
902  *              RelationRemoveInheritance
903  *
904  *              Note: for now, we cause an exception if relation is a
905  *              superclass.  Someday, we may want to allow this and merge
906  *              the type info into subclass procedures....      this seems like
907  *              lots of work.
908  * --------------------------------
909  */
910 static void
911 RelationRemoveInheritance(Relation relation)
912 {
913         Relation        catalogRelation;
914         HeapTuple       tuple;
915         HeapScanDesc scan;
916         ScanKeyData entry;
917         bool            found = false;
918
919         /* ----------------
920          *      open pg_inherits
921          * ----------------
922          */
923         catalogRelation = heap_openr(InheritsRelationName, RowExclusiveLock);
924
925         /* ----------------
926          *      form a scan key for the subclasses of this class
927          *      and begin scanning
928          * ----------------
929          */
930         ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_inherits_inhparent,
931                                                    F_OIDEQ,
932                                                    ObjectIdGetDatum(RelationGetRelid(relation)));
933
934         scan = heap_beginscan(catalogRelation,
935                                                   false,
936                                                   SnapshotNow,
937                                                   1,
938                                                   &entry);
939
940         /* ----------------
941          *      if any subclasses exist, then we disallow the deletion.
942          * ----------------
943          */
944         tuple = heap_getnext(scan, 0);
945         if (HeapTupleIsValid(tuple))
946         {
947                 Oid             subclass = ((Form_pg_inherits) GETSTRUCT(tuple))->inhrel;
948
949                 heap_endscan(scan);
950                 heap_close(catalogRelation, RowExclusiveLock);
951
952                 elog(ERROR, "Relation '%u' inherits '%s'",
953                          subclass, RelationGetRelationName(relation));
954         }
955         heap_endscan(scan);
956
957         /* ----------------
958          *      If we get here, it means the relation has no subclasses
959          *      so we can trash it.  First we remove dead INHERITS tuples.
960          * ----------------
961          */
962         entry.sk_attno = Anum_pg_inherits_inhrel;
963
964         scan = heap_beginscan(catalogRelation,
965                                                   false,
966                                                   SnapshotNow,
967                                                   1,
968                                                   &entry);
969
970         while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
971         {
972                 heap_delete(catalogRelation, &tuple->t_self, NULL);
973                 found = true;
974         }
975
976         heap_endscan(scan);
977         heap_close(catalogRelation, RowExclusiveLock);
978
979         /* ----------------
980          *      now remove dead IPL tuples
981          * ----------------
982          */
983         catalogRelation = heap_openr(InheritancePrecidenceListRelationName,
984                                                                  RowExclusiveLock);
985
986         entry.sk_attno = Anum_pg_ipl_iplrel;
987
988         scan = heap_beginscan(catalogRelation,
989                                                   false,
990                                                   SnapshotNow,
991                                                   1,
992                                                   &entry);
993
994         while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
995                 heap_delete(catalogRelation, &tuple->t_self, NULL);
996
997         heap_endscan(scan);
998         heap_close(catalogRelation, RowExclusiveLock);
999 }
1000
1001 /* --------------------------------
1002  *              RelationRemoveIndexes
1003  *
1004  * --------------------------------
1005  */
1006 static void
1007 RelationRemoveIndexes(Relation relation)
1008 {
1009         Relation        indexRelation;
1010         HeapTuple       tuple;
1011         HeapScanDesc scan;
1012         ScanKeyData entry;
1013
1014         indexRelation = heap_openr(IndexRelationName, RowExclusiveLock);
1015
1016         ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_index_indrelid,
1017                                                    F_OIDEQ,
1018                                                    ObjectIdGetDatum(RelationGetRelid(relation)));
1019
1020         scan = heap_beginscan(indexRelation,
1021                                                   false,
1022                                                   SnapshotNow,
1023                                                   1,
1024                                                   &entry);
1025
1026         while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
1027                 index_destroy(((Form_pg_index) GETSTRUCT(tuple))->indexrelid);
1028
1029         heap_endscan(scan);
1030         heap_close(indexRelation, RowExclusiveLock);
1031 }
1032
1033 /* --------------------------------
1034  *              DeleteRelationTuple
1035  *
1036  * --------------------------------
1037  */
1038 static void
1039 DeleteRelationTuple(Relation rel)
1040 {
1041         Relation        pg_class_desc;
1042         HeapTuple       tup;
1043
1044         /* ----------------
1045          *      open pg_class
1046          * ----------------
1047          */
1048         pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock);
1049
1050         tup = SearchSysCacheTupleCopy(RELOID,
1051                                            ObjectIdGetDatum(rel->rd_att->attrs[0]->attrelid),
1052                                                                   0, 0, 0);
1053         if (!HeapTupleIsValid(tup))
1054         {
1055                 heap_close(pg_class_desc, RowExclusiveLock);
1056                 elog(ERROR, "Relation '%s' does not exist",
1057                          &rel->rd_rel->relname);
1058         }
1059
1060         /* ----------------
1061          *      delete the relation tuple from pg_class, and finish up.
1062          * ----------------
1063          */
1064         heap_delete(pg_class_desc, &tup->t_self, NULL);
1065         pfree(tup);
1066
1067         heap_close(pg_class_desc, RowExclusiveLock);
1068 }
1069
1070 /* --------------------------------
1071  * RelationTruncateIndexes - This routine is used to truncate all
1072  * indices associated with the heap relation to zero tuples.
1073  * The routine will truncate and then reconstruct the indices on
1074  * the relation specified by the heapRelation parameter.
1075  * --------------------------------
1076  */
1077 static void
1078 RelationTruncateIndexes(Relation heapRelation)
1079 {
1080         Relation indexRelation, currentIndex;
1081         ScanKeyData entry;
1082         HeapScanDesc scan;
1083         HeapTuple indexTuple, procTuple, classTuple;
1084         Form_pg_index index;
1085         Oid heapId, indexId, procId, accessMethodId;
1086         Node *oldPred = NULL;
1087         PredInfo *predInfo;
1088         List *cnfPred = NULL;
1089         AttrNumber *attributeNumberA;
1090         FuncIndexInfo fInfo, *funcInfo = NULL;
1091         int i, numberOfAttributes;
1092         char *predString;
1093
1094         heapId = RelationGetRelid(heapRelation);
1095
1096         /* Scan pg_index to find indexes on heapRelation */
1097
1098         indexRelation = heap_openr(IndexRelationName, AccessShareLock);
1099         ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indrelid, F_OIDEQ,
1100                                                    ObjectIdGetDatum(heapId));
1101         scan = heap_beginscan(indexRelation, false, SnapshotNow, 1, &entry);
1102         while (HeapTupleIsValid(indexTuple = heap_getnext(scan, 0)))
1103         {
1104                 /*
1105                  * For each index, fetch index attributes so we can apply index_build
1106                  */
1107                 index = (Form_pg_index) GETSTRUCT(indexTuple);
1108                 indexId = index->indexrelid;
1109                 procId = index->indproc;
1110
1111                 for (i = 0; i < INDEX_MAX_KEYS; i++)
1112                 {
1113                         if (index->indkey[i] == InvalidAttrNumber)
1114                                 break;
1115                 }
1116                 numberOfAttributes = i;
1117
1118                 /* If a valid where predicate, compute predicate Node */
1119                 if (VARSIZE(&index->indpred) != 0)
1120                 {
1121                         predString = fmgr(F_TEXTOUT, &index->indpred);
1122                         oldPred = stringToNode(predString);
1123                         pfree(predString);
1124                 }
1125                 predInfo = (PredInfo *) palloc(sizeof(PredInfo));
1126                 predInfo->pred = (Node *) cnfPred;
1127                 predInfo->oldPred = oldPred;
1128
1129                 /* Assign Index keys to attributes array */
1130                 attributeNumberA = (AttrNumber *) palloc(numberOfAttributes *
1131                                                                                                  sizeof(AttrNumber));
1132                 for (i = 0; i < numberOfAttributes; i++)
1133                         attributeNumberA[i] = index->indkey[i];
1134
1135                 /* If this is a procedural index, initialize our FuncIndexInfo */
1136                 if (procId != InvalidOid)
1137                 {
1138                         funcInfo = &fInfo;
1139                         FIsetnArgs(funcInfo, numberOfAttributes);
1140                         procTuple = SearchSysCacheTuple(PROOID, ObjectIdGetDatum(procId),
1141                                                                                         0, 0, 0);
1142                         if (!HeapTupleIsValid(procTuple))
1143                                 elog(ERROR, "RelationTruncateIndexes: index procedure not found");
1144                         namecpy(&(funcInfo->funcName),
1145                                         &(((Form_pg_proc) GETSTRUCT(procTuple))->proname));
1146                         FIsetProcOid(funcInfo, procTuple->t_data->t_oid);
1147                 }
1148
1149                 /* Fetch the classTuple associated with this index */
1150                 classTuple = SearchSysCacheTupleCopy(RELOID, ObjectIdGetDatum(indexId),
1151                                                                                          0, 0, 0);
1152                 if (!HeapTupleIsValid(classTuple))
1153                         elog(ERROR, "RelationTruncateIndexes: index access method not found");
1154                 accessMethodId = ((Form_pg_class) GETSTRUCT(classTuple))->relam;
1155
1156                 /* Open our index relation */
1157                 currentIndex = index_open(indexId);
1158                 if (currentIndex == NULL)
1159                         elog(ERROR, "RelationTruncateIndexes: can't open index relation");
1160
1161                 /* Obtain exclusive lock on it, just to be sure */
1162                 LockRelation(currentIndex, AccessExclusiveLock);
1163
1164                 /*
1165                  * Release any buffers associated with this index.  If they're dirty,
1166                  * they're just dropped without bothering to flush to disk.
1167                  */
1168                 ReleaseRelationBuffers(currentIndex);
1169                 if (FlushRelationBuffers(currentIndex, (BlockNumber) 0, false) < 0)
1170                         elog(ERROR, "RelationTruncateIndexes: unable to flush index from buffer pool");
1171
1172                 /* Now truncate the actual data and set blocks to zero */
1173                 smgrtruncate(DEFAULT_SMGR, currentIndex, 0);
1174                 currentIndex->rd_nblocks = 0;
1175
1176                 /* Initialize the index and rebuild */
1177                 InitIndexStrategy(numberOfAttributes, currentIndex, accessMethodId);
1178                 index_build(heapRelation, currentIndex, numberOfAttributes,
1179                                         attributeNumberA, 0, NULL, funcInfo, predInfo);
1180
1181                 /*
1182                  * index_build will close both the heap and index relations
1183                  * (but not give up the locks we hold on them).  That's fine
1184                  * for the index, but we need to open the heap again.  We need
1185                  * no new lock, since this backend still has the exclusive lock
1186                  * grabbed by heap_truncate.
1187                  */
1188                 heapRelation = heap_open(heapId, NoLock);
1189                 Assert(heapRelation != NULL);
1190         }
1191
1192         /* Complete the scan and close pg_index */
1193     heap_endscan(scan);
1194         heap_close(indexRelation, AccessShareLock);
1195 }
1196
1197 /* ----------------------------
1198  *   heap_truncate
1199  *
1200  *   This routine is used to truncate the data from the
1201  *   storage manager of any data within the relation handed
1202  *   to this routine.
1203  * ----------------------------
1204  */
1205
1206 void
1207 heap_truncate(char *relname)
1208 {
1209         Relation rel;
1210         Oid rid;
1211
1212         /* Open relation for processing, and grab exclusive access on it. */
1213
1214         rel = heap_openr(relname, AccessExclusiveLock);
1215         rid = rel->rd_id;
1216
1217         /* ----------------
1218          *      TRUNCATE TABLE within a transaction block is dangerous, because
1219          *      if the transaction is later rolled back we have no way to
1220          *      undo truncation of the relation's physical file.  For now, allow it
1221          *      but emit a warning message.
1222          *      Someday we might want to consider postponing the physical truncate
1223          *      until transaction commit, but that's a lot of work...
1224          *      The only case that actually works right is for relations created
1225          *      in the current transaction, since the post-abort state would be that
1226          *      they don't exist anyway.  So, no warning in that case.
1227          * ----------------
1228          */
1229         if (IsTransactionBlock() && ! rel->rd_myxactonly)
1230                 elog(NOTICE, "Caution: TRUNCATE TABLE cannot be rolled back, so don't abort now");
1231
1232         /*
1233          * Release any buffers associated with this relation.  If they're dirty,
1234          * they're just dropped without bothering to flush to disk.
1235          */
1236
1237         ReleaseRelationBuffers(rel);
1238         if (FlushRelationBuffers(rel, (BlockNumber) 0, false) < 0)
1239                 elog(ERROR, "heap_truncate: unable to flush relation from buffer pool");
1240
1241         /* Now truncate the actual data and set blocks to zero */
1242
1243         smgrtruncate(DEFAULT_SMGR, rel, 0);
1244         rel->rd_nblocks = 0;
1245
1246         /* If this relation has indexes, truncate the indexes too */
1247         if (rel->rd_rel->relhasindex)
1248                 RelationTruncateIndexes(rel);
1249
1250         /*
1251          * Close the relation, but keep exclusive lock on it until commit.
1252          */
1253         heap_close(rel, NoLock);
1254
1255         /*
1256          * Is this really necessary?
1257          */
1258         RelationForgetRelation(rid);
1259 }
1260
1261
1262 /* --------------------------------
1263  *              DeleteAttributeTuples
1264  *
1265  * --------------------------------
1266  */
1267 static void
1268 DeleteAttributeTuples(Relation rel)
1269 {
1270         Relation        pg_attribute_desc;
1271         HeapTuple       tup;
1272         int2            attnum;
1273
1274         /* ----------------
1275          *      open pg_attribute
1276          * ----------------
1277          */
1278         pg_attribute_desc = heap_openr(AttributeRelationName, RowExclusiveLock);
1279
1280         for (attnum = FirstLowInvalidHeapAttributeNumber + 1;
1281                  attnum <= rel->rd_att->natts;
1282                  attnum++)
1283         {
1284                 if (HeapTupleIsValid(tup = SearchSysCacheTupleCopy(ATTNUM,
1285                                                                  ObjectIdGetDatum(RelationGetRelid(rel)),
1286                                                                                                    Int16GetDatum(attnum),
1287                                                                                                                    0, 0)))
1288                 {
1289                         heap_delete(pg_attribute_desc, &tup->t_self, NULL);
1290                         pfree(tup);
1291                 }
1292         }
1293
1294         heap_close(pg_attribute_desc, RowExclusiveLock);
1295 }
1296
1297 /* --------------------------------
1298  *              DeleteTypeTuple
1299  *
1300  *              If the user attempts to destroy a relation and there
1301  *              exists attributes in other relations of type
1302  *              "relation we are deleting", then we have to do something
1303  *              special.  presently we disallow the destroy.
1304  * --------------------------------
1305  */
1306 static void
1307 DeleteTypeTuple(Relation rel)
1308 {
1309         Relation        pg_type_desc;
1310         HeapScanDesc pg_type_scan;
1311         Relation        pg_attribute_desc;
1312         HeapScanDesc pg_attribute_scan;
1313         ScanKeyData key;
1314         ScanKeyData attkey;
1315         HeapTuple       tup;
1316         HeapTuple       atttup;
1317         Oid                     typoid;
1318
1319         /* ----------------
1320          *      open pg_type
1321          * ----------------
1322          */
1323         pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
1324
1325         /* ----------------
1326          *      create a scan key to locate the type tuple corresponding
1327          *      to this relation.
1328          * ----------------
1329          */
1330         ScanKeyEntryInitialize(&key, 0,
1331                                                    Anum_pg_type_typrelid,
1332                                                    F_OIDEQ,
1333                                                    ObjectIdGetDatum(RelationGetRelid(rel)));
1334
1335         pg_type_scan = heap_beginscan(pg_type_desc,
1336                                                                   0,
1337                                                                   SnapshotNow,
1338                                                                   1,
1339                                                                   &key);
1340
1341         /* ----------------
1342          *      use heap_getnext() to fetch the pg_type tuple.  If this
1343          *      tuple is not valid then something's wrong.
1344          * ----------------
1345          */
1346         tup = heap_getnext(pg_type_scan, 0);
1347
1348         if (!HeapTupleIsValid(tup))
1349         {
1350                 heap_endscan(pg_type_scan);
1351                 heap_close(pg_type_desc, RowExclusiveLock);
1352                 elog(ERROR, "DeleteTypeTuple: %s type nonexistent",
1353                          &rel->rd_rel->relname);
1354         }
1355
1356         /* ----------------
1357          *      now scan pg_attribute.  if any other relations have
1358          *      attributes of the type of the relation we are deleteing
1359          *      then we have to disallow the deletion.  should talk to
1360          *      stonebraker about this.  -cim 6/19/90
1361          * ----------------
1362          */
1363         typoid = tup->t_data->t_oid;
1364
1365         pg_attribute_desc = heap_openr(AttributeRelationName, RowExclusiveLock);
1366
1367         ScanKeyEntryInitialize(&attkey,
1368                                                    0,
1369                                                    Anum_pg_attribute_atttypid,
1370                                                    F_OIDEQ,
1371                                                    typoid);
1372
1373         pg_attribute_scan = heap_beginscan(pg_attribute_desc,
1374                                                                            0,
1375                                                                            SnapshotNow,
1376                                                                            1,
1377                                                                            &attkey);
1378
1379         /* ----------------
1380          *      try and get a pg_attribute tuple.  if we succeed it means
1381          *      we can't delete the relation because something depends on
1382          *      the schema.
1383          * ----------------
1384          */
1385         atttup = heap_getnext(pg_attribute_scan, 0);
1386
1387         if (HeapTupleIsValid(atttup))
1388         {
1389                 Oid                     relid = ((Form_pg_attribute) GETSTRUCT(atttup))->attrelid;
1390
1391                 heap_endscan(pg_attribute_scan);
1392                 heap_close(pg_attribute_desc, RowExclusiveLock);
1393                 heap_endscan(pg_type_scan);
1394                 heap_close(pg_type_desc, RowExclusiveLock);
1395
1396                 elog(ERROR, "DeleteTypeTuple: att of type %s exists in relation %u",
1397                          &rel->rd_rel->relname, relid);
1398         }
1399         heap_endscan(pg_attribute_scan);
1400         heap_close(pg_attribute_desc, RowExclusiveLock);
1401
1402         /* ----------------
1403          *      Ok, it's safe so we delete the relation tuple
1404          *      from pg_type and finish up.  But first end the scan so that
1405          *      we release the read lock on pg_type.  -mer 13 Aug 1991
1406          * ----------------
1407          */
1408         heap_delete(pg_type_desc, &tup->t_self, NULL);
1409
1410         heap_endscan(pg_type_scan);
1411         heap_close(pg_type_desc, RowExclusiveLock);
1412 }
1413
1414 /* --------------------------------
1415  *              heap_destroy_with_catalog
1416  *
1417  * --------------------------------
1418  */
1419 void
1420 heap_destroy_with_catalog(char *relname)
1421 {
1422         Relation        rel;
1423         Oid                     rid;
1424         bool            istemp = (get_temp_rel_by_name(relname) != NULL);
1425
1426         /* ----------------
1427          *      Open and lock the relation.
1428          * ----------------
1429          */
1430         rel = heap_openr(relname, AccessExclusiveLock);
1431         rid = rel->rd_id;
1432
1433         /* ----------------
1434          *      prevent deletion of system relations
1435          * ----------------
1436          */
1437         /* allow temp of pg_class? Guess so. */
1438         if (!istemp && !allowSystemTableMods &&
1439                 IsSystemRelationName(RelationGetRelationName(rel)->data))
1440                 elog(ERROR, "System relation '%s' cannot be destroyed",
1441                          &rel->rd_rel->relname);
1442
1443         /* ----------------
1444          *      DROP TABLE within a transaction block is dangerous, because
1445          *      if the transaction is later rolled back there will be no way to
1446          *      undo the unlink of the relation's physical file.  For now, allow it
1447          *      but emit a warning message.
1448          *      Someday we might want to consider postponing the physical unlink
1449          *      until transaction commit, but that's a lot of work...
1450          *      The only case that actually works right is for relations created
1451          *      in the current transaction, since the post-abort state would be that
1452          *      they don't exist anyway.  So, no warning in that case.
1453          * ----------------
1454          */
1455         if (IsTransactionBlock() && ! rel->rd_myxactonly)
1456                 elog(NOTICE, "Caution: DROP TABLE cannot be rolled back, so don't abort now");
1457
1458         /* ----------------
1459          *      remove inheritance information
1460          * ----------------
1461          */
1462         RelationRemoveInheritance(rel);
1463
1464         /* ----------------
1465          *      remove indexes if necessary
1466          * ----------------
1467          */
1468         if (rel->rd_rel->relhasindex)
1469                 RelationRemoveIndexes(rel);
1470
1471         /* ----------------
1472          *      remove rules if necessary
1473          * ----------------
1474          */
1475         if (rel->rd_rules != NULL)
1476                 RelationRemoveRules(rid);
1477
1478         /* triggers */
1479         RelationRemoveTriggers(rel);
1480
1481         /* ----------------
1482          *      delete attribute tuples
1483          * ----------------
1484          */
1485         DeleteAttributeTuples(rel);
1486
1487         if (istemp)
1488                 remove_temp_relation(rid);
1489
1490         /* ----------------
1491          *      delete type tuple.      here we want to see the effects
1492          *      of the deletions we just did, so we use setheapoverride().
1493          * ----------------
1494          */
1495         setheapoverride(true);
1496         DeleteTypeTuple(rel);
1497         setheapoverride(false);
1498
1499         /* ----------------
1500          *      delete relation tuple
1501          * ----------------
1502          */
1503         /* must delete fake tuple in cache */
1504         DeleteRelationTuple(rel);
1505
1506         /*
1507          * release dirty buffers of this relation
1508          */
1509         ReleaseRelationBuffers(rel);
1510
1511         RemoveConstraints(rel);
1512
1513         /* ----------------
1514          *      unlink the relation's physical file and finish up.
1515          * ----------------
1516          */
1517         if (!(rel->rd_isnoname) || !(rel->rd_nonameunlinked))
1518                 smgrunlink(DEFAULT_SMGR, rel);
1519
1520         rel->rd_nonameunlinked = TRUE;
1521
1522         /*
1523          * Close relcache entry, but *keep* AccessExclusiveLock on the
1524          * relation until transaction commit.  This ensures no one else
1525          * will try to do something with the doomed relation.
1526          */
1527         heap_close(rel, NoLock);
1528
1529         /* ----------------
1530          *      flush the relation from the relcache
1531          * ----------------
1532          */
1533         RelationForgetRelation(rid);
1534 }
1535
1536 /*
1537  * heap_destroy
1538  *        destroy and close temporary relations
1539  *
1540  */
1541
1542 void
1543 heap_destroy(Relation rel)
1544 {
1545         ReleaseRelationBuffers(rel);
1546         if (!(rel->rd_isnoname) || !(rel->rd_nonameunlinked))
1547                 smgrunlink(DEFAULT_SMGR, rel);
1548         rel->rd_nonameunlinked = TRUE;
1549         heap_close(rel, NoLock);
1550         RemoveFromNoNameRelList(rel);
1551 }
1552
1553
1554 /**************************************************************
1555   functions to deal with the list of temporary relations
1556 **************************************************************/
1557
1558 /* --------------
1559    InitTempRellist():
1560
1561    initialize temporary relations list
1562    the tempRelList is a list of temporary relations that
1563    are created in the course of the transactions
1564    they need to be destroyed properly at the end of the transactions
1565
1566    MODIFIES the global variable tempRels
1567
1568  >> NOTE <<
1569
1570    malloc is used instead of palloc because we KNOW when we are
1571    going to free these things.  Keeps us away from the memory context
1572    hairyness
1573
1574 */
1575 void
1576 InitNoNameRelList(void)
1577 {
1578         if (tempRels)
1579         {
1580                 free(tempRels->rels);
1581                 free(tempRels);
1582         }
1583
1584         tempRels = (TempRelList *) malloc(sizeof(TempRelList));
1585         tempRels->size = NONAME_REL_LIST_SIZE;
1586         tempRels->rels = (Relation *) malloc(sizeof(Relation) * tempRels->size);
1587         MemSet(tempRels->rels, 0, sizeof(Relation) * tempRels->size);
1588         tempRels->num = 0;
1589 }
1590
1591 /*
1592    removes a relation from the TempRelList
1593
1594    MODIFIES the global variable tempRels
1595           we don't really remove it, just mark it as NULL
1596           and DestroyNoNameRels will look for NULLs
1597 */
1598 static void
1599 RemoveFromNoNameRelList(Relation r)
1600 {
1601         int                     i;
1602
1603         if (!tempRels)
1604                 return;
1605
1606         for (i = 0; i < tempRels->num; i++)
1607         {
1608                 if (tempRels->rels[i] == r)
1609                 {
1610                         tempRels->rels[i] = NULL;
1611                         break;
1612                 }
1613         }
1614 }
1615
1616 /*
1617    add a temporary relation to the TempRelList
1618
1619    MODIFIES the global variable tempRels
1620 */
1621 static void
1622 AddToNoNameRelList(Relation r)
1623 {
1624         if (!tempRels)
1625                 return;
1626
1627         if (tempRels->num == tempRels->size)
1628         {
1629                 tempRels->size += NONAME_REL_LIST_SIZE;
1630                 tempRels->rels = realloc(tempRels->rels,
1631                                                                  sizeof(Relation) * tempRels->size);
1632         }
1633         tempRels->rels[tempRels->num] = r;
1634         tempRels->num++;
1635 }
1636
1637 /*
1638    go through the tempRels list and destroy each of the relations
1639 */
1640 void
1641 DestroyNoNameRels(void)
1642 {
1643         int                     i;
1644         Relation        rel;
1645
1646         if (!tempRels)
1647                 return;
1648
1649         for (i = 0; i < tempRels->num; i++)
1650         {
1651                 rel = tempRels->rels[i];
1652                 /* rel may be NULL if it has been removed from the list already */
1653                 if (rel)
1654                         heap_destroy(rel);
1655         }
1656         free(tempRels->rels);
1657         free(tempRels);
1658         tempRels = NULL;
1659 }
1660
1661 /*
1662  * Store a default expression for column attnum of relation rel.
1663  * The expression must be presented as a nodeToString() string.
1664  * If updatePgAttribute is true, update the pg_attribute entry
1665  * for the column to show that a default exists.
1666  */
1667 static void
1668 StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin,
1669                                  bool updatePgAttribute)
1670 {
1671         Form_pg_attribute atp = rel->rd_att->attrs[attnum - 1];
1672         Node       *expr;
1673         Oid                     type;
1674         RangeTblEntry *rte;
1675         char       *adsrc;
1676         Relation        adrel;
1677         Relation        idescs[Num_pg_attrdef_indices];
1678         HeapTuple       tuple;
1679         Datum           values[4];
1680         static char     nulls[4] = {' ', ' ', ' ', ' '};
1681         Relation        attrrel;
1682         Relation        attridescs[Num_pg_attr_indices];
1683         HeapTuple       atttup;
1684         Form_pg_attribute attStruct;
1685
1686         expr = stringToNode(adbin);
1687         type = exprType(expr);
1688
1689         if (type != atp->atttypid)
1690         {
1691                 /*
1692                  * Check that it will be possible to coerce the expression
1693                  * to the column's type.  We store the expression without
1694                  * coercion, however, to avoid premature coercion in cases like
1695                  * CREATE TABLE tbl (fld datetime DEFAULT 'now');
1696                  */
1697                 coerce_type(NULL, expr, type, atp->atttypid, atp->atttypmod);
1698         }
1699
1700         /*
1701          * deparse_expression needs a RangeTblEntry list, so make one
1702          */
1703         rte = makeNode(RangeTblEntry);
1704         rte->relname = RelationGetRelationName(rel)->data;
1705         rte->refname = RelationGetRelationName(rel)->data;
1706         rte->relid = RelationGetRelid(rel);
1707         rte->inh = false;
1708         rte->inFromCl = true;
1709         rte->skipAcl = false;
1710         adsrc = deparse_expression(expr, lcons(lcons(rte, NIL), NIL), false);
1711
1712         values[Anum_pg_attrdef_adrelid - 1] = rel->rd_id;
1713         values[Anum_pg_attrdef_adnum - 1] = attnum;
1714         values[Anum_pg_attrdef_adbin - 1] = PointerGetDatum(textin(adbin));
1715         values[Anum_pg_attrdef_adsrc - 1] = PointerGetDatum(textin(adsrc));
1716         adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
1717         tuple = heap_formtuple(adrel->rd_att, values, nulls);
1718         heap_insert(adrel, tuple);
1719         CatalogOpenIndices(Num_pg_attrdef_indices, Name_pg_attrdef_indices,
1720                                            idescs);
1721         CatalogIndexInsert(idescs, Num_pg_attrdef_indices, adrel, tuple);
1722         CatalogCloseIndices(Num_pg_attrdef_indices, idescs);
1723         heap_close(adrel, RowExclusiveLock);
1724
1725         pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
1726         pfree(DatumGetPointer(values[Anum_pg_attrdef_adsrc - 1]));
1727         pfree(tuple);
1728         pfree(adsrc);
1729
1730         if (! updatePgAttribute)
1731                 return;                                 /* done if pg_attribute is OK */
1732
1733         attrrel = heap_openr(AttributeRelationName, RowExclusiveLock);
1734         atttup = SearchSysCacheTupleCopy(ATTNUM,
1735                                                                          ObjectIdGetDatum(rel->rd_id),
1736                                                                          (Datum) attnum, 0, 0);
1737         if (!HeapTupleIsValid(atttup))
1738                 elog(ERROR, "cache lookup of attribute %d in relation %u failed",
1739                          attnum, rel->rd_id);
1740         attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
1741         if (! attStruct->atthasdef)
1742         {
1743                 attStruct->atthasdef = true;
1744                 heap_replace(attrrel, &atttup->t_self, atttup, NULL);
1745                 /* keep catalog indices current */
1746                 CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices,
1747                                                    attridescs);
1748                 CatalogIndexInsert(attridescs, Num_pg_attr_indices, attrrel, atttup);
1749                 CatalogCloseIndices(Num_pg_attr_indices, attridescs);
1750         }
1751         heap_close(attrrel, RowExclusiveLock);
1752         pfree(atttup);
1753 }
1754
1755 /*
1756  * Store a constraint expression for the given relation.
1757  * The expression must be presented as a nodeToString() string.
1758  *
1759  * Caller is responsible for updating the count of constraints
1760  * in the pg_class entry for the relation.
1761  */
1762 static void
1763 StoreRelCheck(Relation rel, char *ccname, char *ccbin)
1764 {
1765         Node       *expr;
1766         RangeTblEntry *rte;
1767         char       *ccsrc;
1768         Relation        rcrel;
1769         Relation        idescs[Num_pg_relcheck_indices];
1770         HeapTuple       tuple;
1771         Datum           values[4];
1772         static char     nulls[4] = {' ', ' ', ' ', ' '};
1773
1774         /*
1775          * Convert condition to a normal boolean expression tree.
1776          */
1777         expr = stringToNode(ccbin);
1778         expr = (Node *) make_ands_explicit((List *) expr);
1779         /*
1780          * deparse_expression needs a RangeTblEntry list, so make one
1781          */
1782         rte = makeNode(RangeTblEntry);
1783         rte->relname = RelationGetRelationName(rel)->data;
1784         rte->refname = RelationGetRelationName(rel)->data;
1785         rte->relid = RelationGetRelid(rel);
1786         rte->inh = false;
1787         rte->inFromCl = true;
1788         rte->skipAcl = false;
1789         ccsrc = deparse_expression(expr, lcons(lcons(rte, NIL), NIL), false);
1790
1791         values[Anum_pg_relcheck_rcrelid - 1] = rel->rd_id;
1792         values[Anum_pg_relcheck_rcname - 1] = PointerGetDatum(namein(ccname));
1793         values[Anum_pg_relcheck_rcbin - 1] = PointerGetDatum(textin(ccbin));
1794         values[Anum_pg_relcheck_rcsrc - 1] = PointerGetDatum(textin(ccsrc));
1795         rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock);
1796         tuple = heap_formtuple(rcrel->rd_att, values, nulls);
1797         heap_insert(rcrel, tuple);
1798         CatalogOpenIndices(Num_pg_relcheck_indices, Name_pg_relcheck_indices,
1799                                            idescs);
1800         CatalogIndexInsert(idescs, Num_pg_relcheck_indices, rcrel, tuple);
1801         CatalogCloseIndices(Num_pg_relcheck_indices, idescs);
1802         heap_close(rcrel, RowExclusiveLock);
1803
1804         pfree(DatumGetPointer(values[Anum_pg_relcheck_rcname - 1]));
1805         pfree(DatumGetPointer(values[Anum_pg_relcheck_rcbin - 1]));
1806         pfree(DatumGetPointer(values[Anum_pg_relcheck_rcsrc - 1]));
1807         pfree(tuple);
1808         pfree(ccsrc);
1809 }
1810
1811 /*
1812  * Store defaults and constraints passed in via the tuple constraint struct.
1813  *
1814  * NOTE: only pre-cooked expressions will be passed this way, which is to
1815  * say expressions inherited from an existing relation.  Newly parsed
1816  * expressions can be added later, by direct calls to StoreAttrDefault
1817  * and StoreRelCheck (see AddRelationRawConstraints()).  We assume that
1818  * pg_attribute and pg_class entries for the relation were already set
1819  * to reflect the existence of these defaults/constraints.
1820  */
1821 static void
1822 StoreConstraints(Relation rel)
1823 {
1824         TupleConstr *constr = rel->rd_att->constr;
1825         int                     i;
1826
1827         if (!constr)
1828                 return;
1829
1830         for (i = 0; i < constr->num_defval; i++)
1831                 StoreAttrDefault(rel, constr->defval[i].adnum,
1832                                                  constr->defval[i].adbin, false);
1833
1834         for (i = 0; i < constr->num_check; i++)
1835                 StoreRelCheck(rel, constr->check[i].ccname,
1836                                           constr->check[i].ccbin);
1837 }
1838
1839 /*
1840  * AddRelationRawConstraints
1841  *
1842  * Add raw (not-yet-transformed) column default expressions and/or constraint
1843  * check expressions to an existing relation.  This is defined to do both
1844  * for efficiency in DefineRelation, but of course you can do just one or
1845  * the other by passing empty lists.
1846  *
1847  * rel: relation to be modified
1848  * rawColDefaults: list of RawColumnDefault structures
1849  * rawConstraints: list of Constraint nodes
1850  *
1851  * All entries in rawColDefaults will be processed.  Entries in rawConstraints
1852  * will be processed only if they are CONSTR_CHECK type and contain a "raw"
1853  * expression.
1854  *
1855  * NB: caller should have opened rel with AccessExclusiveLock, and should
1856  * hold that lock till end of transaction.
1857  */
1858 void
1859 AddRelationRawConstraints(Relation rel,
1860                                                   List *rawColDefaults,
1861                                                   List *rawConstraints)
1862 {
1863         char       *relname = RelationGetRelationName(rel)->data;
1864         TupleDesc       tupleDesc;
1865         TupleConstr *oldconstr;
1866         int                     numoldchecks;
1867         ConstrCheck *oldchecks;
1868         ParseState *pstate;
1869         int                     numchecks;
1870         List       *listptr;
1871         Relation        relrel;
1872         Relation        relidescs[Num_pg_class_indices];
1873         HeapTuple       reltup;
1874         Form_pg_class relStruct;
1875
1876         /*
1877          * Get info about existing constraints.
1878          */
1879         tupleDesc = RelationGetDescr(rel);
1880         oldconstr = tupleDesc->constr;
1881         if (oldconstr)
1882         {
1883                 numoldchecks = oldconstr->num_check;
1884                 oldchecks = oldconstr->check;
1885         }
1886         else
1887         {
1888                 numoldchecks = 0;
1889                 oldchecks = NULL;
1890         }
1891
1892         /*
1893          * Create a dummy ParseState and insert the target relation as
1894          * its sole rangetable entry.  We need a ParseState for transformExpr.
1895          */
1896         pstate = make_parsestate(NULL);
1897         makeRangeTable(pstate, NULL, NULL);
1898         addRangeTableEntry(pstate, relname, relname, false, true);
1899
1900         /*
1901          * Process column default expressions.
1902          */
1903         foreach(listptr, rawColDefaults)
1904         {
1905                 RawColumnDefault *colDef = (RawColumnDefault *) lfirst(listptr);
1906                 Node       *expr;
1907
1908                 Assert(colDef->raw_default != NULL);
1909                 /*
1910                  * Transform raw parsetree to executable expression.
1911                  */
1912                 expr = transformExpr(pstate, colDef->raw_default, EXPR_COLUMN_FIRST);
1913                 /*
1914                  * Make sure default expr does not refer to any vars.
1915                  */
1916                 if (contain_var_clause(expr))
1917                         elog(ERROR, "Cannot use attribute(s) in DEFAULT clause");
1918                 /*
1919                  * Might as well try to reduce any constant expressions.
1920                  */
1921                 expr = eval_const_expressions(expr);
1922                 /*
1923                  * Must fix opids, in case any operators remain...
1924                  */
1925                 fix_opids(expr);
1926                 /*
1927                  * OK, store it.
1928                  */
1929                 StoreAttrDefault(rel, colDef->attnum, nodeToString(expr), true);
1930         }
1931
1932         /*
1933          * Process constraint expressions.
1934          */
1935         numchecks = numoldchecks;
1936         foreach(listptr, rawConstraints)
1937         {
1938                 Constraint *cdef = (Constraint *) lfirst(listptr);
1939                 char       *ccname;
1940                 Node       *expr;
1941
1942                 if (cdef->contype != CONSTR_CHECK || cdef->raw_expr == NULL)
1943                         continue;
1944                 Assert(cdef->cooked_expr == NULL);
1945
1946                 /* Check name uniqueness, or generate a new name */
1947                 if (cdef->name != NULL)
1948                 {
1949                         int                     i;
1950                         List       *listptr2;
1951
1952                         ccname = cdef->name;
1953                         /* Check against old constraints */
1954                         for (i = 0; i < numoldchecks; i++)
1955                         {
1956                                 if (strcmp(oldchecks[i].ccname, ccname) == 0)
1957                                         elog(ERROR, "Duplicate CHECK constraint name: '%s'",
1958                                                  ccname);
1959                         }
1960                         /* Check against other new constraints */
1961                         foreach(listptr2, rawConstraints)
1962                         {
1963                                 Constraint *cdef2 = (Constraint *) lfirst(listptr2);
1964
1965                                 if (cdef2 == cdef ||
1966                                         cdef2->contype != CONSTR_CHECK ||
1967                                         cdef2->raw_expr == NULL ||
1968                                         cdef2->name == NULL)
1969                                         continue;
1970                                 if (strcmp(cdef2->name, ccname) == 0)
1971                                         elog(ERROR, "Duplicate CHECK constraint name: '%s'",
1972                                                  ccname);
1973                         }
1974                 }
1975                 else
1976                 {
1977                         ccname = (char *) palloc(NAMEDATALEN);
1978                         snprintf(ccname, NAMEDATALEN, "$%d", numchecks + 1);
1979                 }
1980                 /*
1981                  * Transform raw parsetree to executable expression.
1982                  */
1983                 expr = transformExpr(pstate, cdef->raw_expr, EXPR_COLUMN_FIRST);
1984                 /*
1985                  * Make sure no outside relations are referred to.
1986                  */
1987                 if (length(pstate->p_rtable) != 1)
1988                         elog(ERROR, "Only relation '%s' can be referenced in CHECK",
1989                                  relname);
1990                 /*
1991                  * Might as well try to reduce any constant expressions.
1992                  */
1993                 expr = eval_const_expressions(expr);
1994                 /*
1995                  * Constraints are evaluated with execQual, which expects an
1996                  * implicit-AND list, so convert expression to implicit-AND form.
1997                  * (We could go so far as to convert to CNF, but that's probably
1998                  * overkill...)
1999                  */
2000                 expr = (Node *) make_ands_implicit((Expr *) expr);
2001                 /*
2002                  * Must fix opids in operator clauses.
2003                  */
2004                 fix_opids(expr);
2005                 /*
2006                  * OK, store it.
2007                  */
2008                 StoreRelCheck(rel, ccname, nodeToString(expr));
2009
2010                 numchecks++;
2011         }
2012
2013         /*
2014          * Update the count of constraints in the relation's pg_class tuple.
2015          * We do this even if there was no change, in order to ensure that an
2016          * SI update message is sent out for the pg_class tuple, which will
2017          * force other backends to rebuild their relcache entries for the rel.
2018          * (Of course, for a newly created rel there is no need for an SI message,
2019          * but for ALTER TABLE ADD ATTRIBUTE this'd be important.)
2020          */
2021         relrel = heap_openr(RelationRelationName, RowExclusiveLock);
2022         reltup = SearchSysCacheTupleCopy(RELOID,
2023                                                                          ObjectIdGetDatum(rel->rd_id),
2024                                                                          0, 0, 0);
2025         if (!HeapTupleIsValid(reltup))
2026                 elog(ERROR, "cache lookup of relation %u failed", rel->rd_id);
2027         relStruct = (Form_pg_class) GETSTRUCT(reltup);
2028
2029         relStruct->relchecks = numchecks;
2030
2031         heap_replace(relrel, &reltup->t_self, reltup, NULL);
2032
2033         /* keep catalog indices current */
2034         CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices,
2035                                            relidescs);
2036         CatalogIndexInsert(relidescs, Num_pg_class_indices, relrel, reltup);
2037         CatalogCloseIndices(Num_pg_class_indices, relidescs);
2038
2039         heap_close(relrel, RowExclusiveLock);
2040         pfree(reltup);
2041
2042         /*
2043          * Force rebuild of our own relcache entry, otherwise subsequent commands
2044          * in this transaction won't see the new defaults/constraints.
2045          * Must bump command counter or relcache rebuild won't see 'em either.
2046          *
2047          * (This might seem unnecessary, since we are sending out an SI message;
2048          * but if the relation has just been created then relcache.c will ignore
2049          * the SI message on the grounds that the rel is transaction-local...)
2050          */
2051         CommandCounterIncrement();
2052         RelationRebuildRelation(rel);
2053 }
2054
2055 static void
2056 RemoveAttrDefault(Relation rel)
2057 {
2058         Relation        adrel;
2059         HeapScanDesc adscan;
2060         ScanKeyData key;
2061         HeapTuple       tup;
2062
2063         adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
2064
2065         ScanKeyEntryInitialize(&key, 0, Anum_pg_attrdef_adrelid,
2066                                                    F_OIDEQ, rel->rd_id);
2067
2068         adscan = heap_beginscan(adrel, 0, SnapshotNow, 1, &key);
2069
2070         while (HeapTupleIsValid(tup = heap_getnext(adscan, 0)))
2071                 heap_delete(adrel, &tup->t_self, NULL);
2072
2073         heap_endscan(adscan);
2074         heap_close(adrel, RowExclusiveLock);
2075 }
2076
2077 static void
2078 RemoveRelCheck(Relation rel)
2079 {
2080         Relation        rcrel;
2081         HeapScanDesc rcscan;
2082         ScanKeyData key;
2083         HeapTuple       tup;
2084
2085         rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock);
2086
2087         ScanKeyEntryInitialize(&key, 0, Anum_pg_relcheck_rcrelid,
2088                                                    F_OIDEQ, rel->rd_id);
2089
2090         rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key);
2091
2092         while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0)))
2093                 heap_delete(rcrel, &tup->t_self, NULL);
2094
2095         heap_endscan(rcscan);
2096         heap_close(rcrel, RowExclusiveLock);
2097 }
2098
2099 static void
2100 RemoveConstraints(Relation rel)
2101 {
2102         TupleConstr *constr = rel->rd_att->constr;
2103
2104         if (!constr)
2105                 return;
2106
2107         if (constr->num_defval > 0)
2108                 RemoveAttrDefault(rel);
2109
2110         if (constr->num_check > 0)
2111                 RemoveRelCheck(rel);
2112 }