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