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