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