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