OSDN Git Service

Change error messages to oids come out as %u and not %d. Change has no
[pg-rex/syncrep.git] / src / backend / catalog / heap.c
1 /*-------------------------------------------------------------------------
2  *
3  * heap.c
4  *        code to create and destroy POSTGRES heap relations
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.78 1999/05/10 00:44:54 momjian Exp $
11  *
12  *
13  * INTERFACE ROUTINES
14  *              heap_create()                   - Create an uncataloged heap relation
15  *              heap_create_with_catalog() - Create a cataloged relation
16  *              heap_destroy_with_catalog() - Removes named relation from catalogs
17  *
18  * NOTES
19  *        this code taken from access/heap/create.c, which contains
20  *        the old heap_create_with_catalog, amcreate, and amdestroy.
21  *        those routines will soon call these routines using the function
22  *        manager,
23  *        just like the poorly named "NewXXX" routines do.      The
24  *        "New" routines are all going to die soon, once and for all!
25  *              -cim 1/13/91
26  *
27  *-------------------------------------------------------------------------
28  */
29 #include "postgres.h"
30 #include "miscadmin.h"
31
32 #include "access/heapam.h"
33 #include "catalog/catalog.h"
34 #include "catalog/catname.h"
35 #include "catalog/heap.h"
36 #include "catalog/index.h"
37 #include "catalog/indexing.h"
38 #include "catalog/pg_attrdef.h"
39 #include "catalog/pg_index.h"
40 #include "catalog/pg_inherits.h"
41 #include "catalog/pg_ipl.h"
42 #include "catalog/pg_relcheck.h"
43 #include "catalog/pg_type.h"
44 #include "commands/trigger.h"
45 #include "fmgr.h"
46 #include "nodes/plannodes.h"
47 #include "optimizer/tlist.h"
48 #include "parser/parse_expr.h"
49 #include "parser/parse_node.h"
50 #include "parser/parse_type.h"
51 #include "parser/parse_coerce.h"
52 #include "rewrite/rewriteRemove.h"
53 #include "storage/bufmgr.h"
54 #include "storage/lmgr.h"
55 #include "storage/smgr.h"
56 #include "tcop/tcopprot.h"
57 #include "utils/catcache.h"
58 #include "utils/builtins.h"
59 #include "utils/mcxt.h"
60 #include "utils/relcache.h"
61 #include "utils/syscache.h"
62 #include "utils/tqual.h"
63 #include "utils/temprel.h"
64
65 #ifndef HAVE_MEMMOVE
66 #include <regex/utils.h>
67 #else
68 #include <string.h>
69 #endif
70
71 static void AddNewRelationTuple(Relation pg_class_desc,
72                                    Relation new_rel_desc, Oid new_rel_oid, unsigned natts,
73                                    char relkind, char *temp_relname);
74 static void AddToNoNameRelList(Relation r);
75 static void DeleteAttributeTuples(Relation rel);
76 static void DeleteRelationTuple(Relation rel);
77 static void DeleteTypeTuple(Relation rel);
78 static void RelationRemoveIndexes(Relation relation);
79 static void RelationRemoveInheritance(Relation relation);
80 static void RemoveFromNoNameRelList(Relation r);
81 static void AddNewRelationType(char *typeName, Oid new_rel_oid);
82 static void StoreConstraints(Relation rel);
83 static void RemoveConstraints(Relation rel);
84
85
86 /* ----------------------------------------------------------------
87  *                              XXX UGLY HARD CODED BADNESS FOLLOWS XXX
88  *
89  *              these should all be moved to someplace in the lib/catalog
90  *              module, if not obliterated first.
91  * ----------------------------------------------------------------
92  */
93
94
95 /*
96  * Note:
97  *              Should the executor special case these attributes in the future?
98  *              Advantage:      consume 1/2 the space in the ATTRIBUTE relation.
99  *              Disadvantage:  having rules to compute values in these tuples may
100  *                              be more difficult if not impossible.
101  */
102
103 static FormData_pg_attribute a1 = {
104         0xffffffff, {"ctid"}, TIDOID, 0, sizeof(ItemPointerData),
105         SelfItemPointerAttributeNumber, 0, -1, -1, '\0', '\0', 'i', '\0', '\0'
106 };
107
108 static FormData_pg_attribute a2 = {
109         0xffffffff, {"oid"}, OIDOID, 0, sizeof(Oid),
110         ObjectIdAttributeNumber, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'
111 };
112
113 static FormData_pg_attribute a3 = {
114         0xffffffff, {"xmin"}, XIDOID, 0, sizeof(TransactionId),
115         MinTransactionIdAttributeNumber, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'
116 };
117
118 static FormData_pg_attribute a4 = {
119         0xffffffff, {"cmin"}, CIDOID, 0, sizeof(CommandId),
120         MinCommandIdAttributeNumber, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'
121 };
122
123 static FormData_pg_attribute a5 = {
124         0xffffffff, {"xmax"}, XIDOID, 0, sizeof(TransactionId),
125         MaxTransactionIdAttributeNumber, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'
126 };
127
128 static FormData_pg_attribute a6 = {
129         0xffffffff, {"cmax"}, CIDOID, 0, sizeof(CommandId),
130         MaxCommandIdAttributeNumber, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'
131 };
132
133 static Form_pg_attribute HeapAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6};
134
135 /* ----------------------------------------------------------------
136  *                              XXX END OF UGLY HARD CODED BADNESS XXX
137  * ----------------------------------------------------------------
138  */
139
140 /* the tempRelList holds
141    the list of temporary uncatalogued relations that are created.
142    these relations should be destroyed at the end of transactions
143 */
144 typedef struct tempRelList
145 {
146         Relation   *rels;                       /* array of relation descriptors */
147         int                     num;                    /* number of temporary relations */
148         int                     size;                   /* size of space allocated for the rels
149                                                                  * array */
150 } TempRelList;
151
152 #define NONAME_REL_LIST_SIZE    32
153
154 static TempRelList *tempRels = NULL;
155
156
157 /* ----------------------------------------------------------------
158  *              heap_create             - Create an uncataloged heap relation
159  *
160  *              Fields relpages, reltuples, reltuples, relkeys, relhistory,
161  *              relisindexed, and relkind of rel->rd_rel are initialized
162  *              to all zeros, as are rd_last and rd_hook.  Rd_refcnt is set to 1.
163  *
164  *              Remove the system relation specific code to elsewhere eventually.
165  *
166  *              Eventually, must place information about this temporary relation
167  *              into the transaction context block.
168  *
169  *
170  * if heap_create is called with "" as the name, then heap_create will create
171  * a temporary name "pg_noname.$PID.$SEQUENCE" for the relation
172  * ----------------------------------------------------------------
173  */
174 Relation
175 heap_create(char *relname,
176                         TupleDesc tupDesc,
177                         bool isnoname,
178                         bool istemp)
179 {
180         unsigned        i;
181         Oid                     relid;
182         Relation        rel;
183         int                     len;
184         bool            nailme = false;
185         int                     natts = tupDesc->natts;
186         static unsigned int uniqueId = 0;
187         
188         extern GlobalMemory CacheCxt;
189         MemoryContext oldcxt;
190
191
192         /* ----------------
193          *      sanity checks
194          * ----------------
195          */
196         AssertArg(natts > 0);
197
198         if (relname && !allowSystemTableMods && IsSystemRelationName(relname) && IsNormalProcessingMode())
199         {
200                 elog(ERROR, "Illegal class name '%s'"
201                          "\n\tThe 'pg_' name prefix is reserved for system catalogs",
202                          relname);
203         }
204
205         /* ----------------
206          *      switch to the cache context so that we don't lose
207          *      allocations at the end of this transaction, I guess.
208          *      -cim 6/14/90
209          * ----------------
210          */
211         if (!CacheCxt)
212                 CacheCxt = CreateGlobalMemory("Cache");
213
214         oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
215
216         /* ----------------
217          *      real ugly stuff to assign the proper relid in the relation
218          *      descriptor follows.
219          * ----------------
220          */
221         if (relname && !strcmp(RelationRelationName, relname))
222         {
223                 relid = RelOid_pg_class;
224                 nailme = true;
225         }
226         else if (relname && !strcmp(AttributeRelationName, relname))
227         {
228                 relid = RelOid_pg_attribute;
229                 nailme = true;
230         }
231         else if (relname && !strcmp(ProcedureRelationName, relname))
232         {
233                 relid = RelOid_pg_proc;
234                 nailme = true;
235         }
236         else if (relname && !strcmp(TypeRelationName, relname))
237         {
238                 relid = RelOid_pg_type;
239                 nailme = true;
240         }
241         else
242         {
243                 relid = newoid();
244         }
245
246         if (isnoname)
247         {
248                 Assert(!relname);
249                 relname = palloc(NAMEDATALEN);
250                 snprintf(relname, NAMEDATALEN, "pg_noname.%d.%u",
251                         (int) MyProcPid, uniqueId++);
252         }
253
254         if (istemp)
255         {
256                 /* replace relname of caller */
257                 snprintf(relname, NAMEDATALEN, "pg_temp.%d.%u",
258                         (int) MyProcPid, uniqueId++);
259         }
260
261         /* ----------------
262          *      allocate a new relation descriptor.
263          *
264          *      XXX the length computation may be incorrect, handle elsewhere
265          * ----------------
266          */
267         len = sizeof(RelationData);
268
269         rel = (Relation) palloc(len);
270         MemSet((char *) rel, 0, len);
271
272         /*
273          * create a new tuple descriptor from the one passed in
274         */
275         rel->rd_att = CreateTupleDescCopyConstr(tupDesc);
276
277         /* ----------------
278          *      nail the reldesc if this is a bootstrap create reln and
279          *      we may need it in the cache later on in the bootstrap
280          *      process so we don't ever want it kicked out.  e.g. pg_attribute!!!
281          * ----------------
282          */
283         if (nailme)
284                 rel->rd_isnailed = true;
285
286         RelationSetReferenceCount(rel, 1);
287
288         rel->rd_rel = (Form_pg_class) palloc(sizeof *rel->rd_rel);
289
290         /* ----------------
291          *      initialize the fields of our new relation descriptor
292          * ----------------
293          */
294         MemSet((char *) rel->rd_rel, 0, sizeof *rel->rd_rel);
295         namestrcpy(&(rel->rd_rel->relname), relname);
296         rel->rd_rel->relkind = RELKIND_UNCATALOGED;
297         rel->rd_rel->relnatts = natts;
298         if (tupDesc->constr)
299                 rel->rd_rel->relchecks = tupDesc->constr->num_check;
300
301         for (i = 0; i < natts; i++)
302                 rel->rd_att->attrs[i]->attrelid = relid;
303
304         RelationGetRelid(rel) = relid;
305
306         if (nailme)
307         {
308                 /* for system relations, set the reltype field here */
309                 rel->rd_rel->reltype = relid;
310         }
311
312         /* ----------------
313          *      remember if this is a noname relation
314          * ----------------
315          */
316         rel->rd_isnoname = isnoname;
317
318         /* ----------------
319          *      have the storage manager create the relation.
320          * ----------------
321          */
322
323         rel->rd_nonameunlinked = TRUE; /* change once table is created */
324         rel->rd_fd = (File) smgrcreate(DEFAULT_SMGR, rel);
325         rel->rd_nonameunlinked = FALSE;
326
327         RelationRegisterRelation(rel);
328
329         MemoryContextSwitchTo(oldcxt);
330
331         /*
332          * add all noname relations to the tempRels list so they can be
333          * properly disposed of at the end of transaction
334          */
335         if (isnoname)
336                 AddToNoNameRelList(rel);
337
338         return rel;
339 }
340
341
342 /* ----------------------------------------------------------------
343  *              heap_create_with_catalog                - Create a cataloged relation
344  *
345  *              this is done in 6 steps:
346  *
347  *              1) CheckAttributeNames() is used to make certain the tuple
348  *                 descriptor contains a valid set of attribute names
349  *
350  *              2) pg_class is opened and RelationFindRelid()
351  *                 preforms a scan to ensure that no relation with the
352  *                 same name already exists.
353  *
354  *              3) heap_create_with_catalog() is called to create the new relation
355  *                 on disk.
356  *
357  *              4) TypeDefine() is called to define a new type corresponding
358  *                 to the new relation.
359  *
360  *              5) AddNewAttributeTuples() is called to register the
361  *                 new relation's schema in pg_attribute.
362  *
363  *              6) AddNewRelationTuple() is called to register the
364  *                 relation itself in the catalogs.
365  *
366  *              7) StoreConstraints is called ()                - vadim 08/22/97
367  *
368  *              8) the relations are closed and the new relation's oid
369  *                 is returned.
370  *
371  * old comments:
372  *              A new relation is inserted into the RELATION relation
373  *              with the specified attribute(s) (newly inserted into
374  *              the ATTRIBUTE relation).  How does concurrency control
375  *              work?  Is it automatic now?  Expects the caller to have
376  *              attname, atttypid, atttyparg, attproc, and attlen domains filled.
377  *              Create fills the attnum domains sequentually from zero,
378  *              fills the attdisbursion domains with zeros, and fills the
379  *              attrelid fields with the relid.
380  *
381  *              scan relation catalog for name conflict
382  *              scan type catalog for typids (if not arg)
383  *              create and insert attribute(s) into attribute catalog
384  *              create new relation
385  *              insert new relation into attribute catalog
386  *
387  *              Should coordinate with heap_create_with_catalog(). Either
388  *              it should not be called or there should be a way to prevent
389  *              the relation from being removed at the end of the
390  *              transaction if it is successful ('u'/'r' may be enough).
391  *              Also, if the transaction does not commit, then the
392  *              relation should be removed.
393  *
394  *              XXX amcreate ignores "off" when inserting (for now).
395  *              XXX amcreate (like the other utilities) needs to understand indexes.
396  *
397  * ----------------------------------------------------------------
398  */
399
400 /* --------------------------------
401  *              CheckAttributeNames
402  *
403  *              this is used to make certain the tuple descriptor contains a
404  *              valid set of attribute names.  a problem simply generates
405  *              elog(ERROR) which aborts the current transaction.
406  * --------------------------------
407  */
408 static void
409 CheckAttributeNames(TupleDesc tupdesc)
410 {
411         unsigned        i;
412         unsigned        j;
413         int                     natts = tupdesc->natts;
414
415         /* ----------------
416          *      first check for collision with system attribute names
417          * ----------------
418          *
419          *       also, warn user if attribute to be created has
420          *       an unknown typid  (usually as a result of a 'retrieve into'
421          *        - jolly
422          */
423         for (i = 0; i < natts; i += 1)
424         {
425                 for (j = 0; j < sizeof HeapAtt / sizeof HeapAtt[0]; j += 1)
426                 {
427                         if (nameeq(&(HeapAtt[j]->attname),
428                                            &(tupdesc->attrs[i]->attname)))
429                         {
430                                 elog(ERROR, "Attribute '%s' has a name conflict"
431                                          "\n\tName matches an existing system attribute",
432                                          HeapAtt[j]->attname.data);
433                         }
434                 }
435                 if (tupdesc->attrs[i]->atttypid == UNKNOWNOID)
436                 {
437                         elog(NOTICE, "Attribute '%s' has an unknown type"
438                                  "\n\tRelation created; continue",
439                                  tupdesc->attrs[i]->attname.data);
440                 }
441         }
442
443         /* ----------------
444          *      next check for repeated attribute names
445          * ----------------
446          */
447         for (i = 1; i < natts; i += 1)
448         {
449                 for (j = 0; j < i; j += 1)
450                 {
451                         if (nameeq(&(tupdesc->attrs[j]->attname),
452                                            &(tupdesc->attrs[i]->attname)))
453                         {
454                                 elog(ERROR, "Attribute '%s' is repeated",
455                                          tupdesc->attrs[j]->attname.data);
456                         }
457                 }
458         }
459 }
460
461 /* --------------------------------
462  *              RelnameFindRelid
463  *
464  *              this preforms a scan of pg_class to ensure that
465  *              no relation with the same name already exists.
466  * --------------------------------
467  */
468 Oid
469 RelnameFindRelid(char *relname)
470 {
471         HeapTuple       tuple;
472         Oid                     relid;
473
474         /*
475          * If this is not bootstrap (initdb) time, use the catalog index on
476          * pg_class.
477          */
478         if (!IsBootstrapProcessingMode())
479         {
480                 tuple = SearchSysCacheTuple(RELNAME,
481                                                                   PointerGetDatum(relname),
482                                                                   0, 0, 0);
483                 if (HeapTupleIsValid(tuple))
484                         relid = tuple->t_data->t_oid;
485                 else
486                         relid = InvalidOid;
487         }
488         else
489         {
490                 Relation pg_class_desc;
491                 ScanKeyData key;
492                 HeapScanDesc pg_class_scan;
493                 
494                 pg_class_desc = heap_openr(RelationRelationName);
495
496                 /* ----------------
497                  *      At bootstrap time, we have to do this the hard way.  Form the
498                  *      scan key.
499                  * ----------------
500                  */
501                 ScanKeyEntryInitialize(&key,
502                                                            0,
503                                                            (AttrNumber) Anum_pg_class_relname,
504                                                            (RegProcedure) F_NAMEEQ,
505                                                            (Datum) relname);
506         
507                 /* ----------------
508                  *      begin the scan
509                  * ----------------
510                  */
511                 pg_class_scan = heap_beginscan(pg_class_desc,
512                                                                            0,
513                                                                            SnapshotNow,
514                                                                            1,
515                                                                            &key);
516         
517                 /* ----------------
518                  *      get a tuple.  if the tuple is NULL then it means we
519                  *      didn't find an existing relation.
520                  * ----------------
521                  */
522                 tuple = heap_getnext(pg_class_scan, 0);
523         
524                 if (HeapTupleIsValid(tuple))
525                         relid = tuple->t_data->t_oid;
526                 else
527                         relid = InvalidOid;
528
529                 heap_endscan(pg_class_scan);
530
531                 heap_close(pg_class_desc);
532         }
533         return relid;
534 }
535
536 /* --------------------------------
537  *              AddNewAttributeTuples
538  *
539  *              this registers the new relation's schema by adding
540  *              tuples to pg_attribute.
541  * --------------------------------
542  */
543 static void
544 AddNewAttributeTuples(Oid new_rel_oid,
545                                           TupleDesc tupdesc)
546 {
547         Form_pg_attribute *dpp;
548         unsigned        i;
549         HeapTuple       tup;
550         Relation        rel;
551         bool            hasindex;
552         Relation        idescs[Num_pg_attr_indices];
553         int                     natts = tupdesc->natts;
554
555         /* ----------------
556          *      open pg_attribute
557          * ----------------
558          */
559         rel = heap_openr(AttributeRelationName);
560
561         /* -----------------
562          * Check if we have any indices defined on pg_attribute.
563          * -----------------
564          */
565         Assert(rel);
566         Assert(rel->rd_rel);
567         hasindex = RelationGetForm(rel)->relhasindex;
568         if (hasindex)
569                 CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
570
571         /* ----------------
572          *      initialize tuple descriptor.  Note we use setheapoverride()
573          *      so that we can see the effects of our TypeDefine() done
574          *      previously.
575          * ----------------
576          */
577         setheapoverride(true);
578         fillatt(tupdesc);
579         setheapoverride(false);
580
581         /* ----------------
582          *      first we add the user attributes..
583          * ----------------
584          */
585         dpp = tupdesc->attrs;
586         for (i = 0; i < natts; i++)
587         {
588                 (*dpp)->attrelid = new_rel_oid;
589                 (*dpp)->attdisbursion = 0;
590
591                 tup = heap_addheader(Natts_pg_attribute,
592                                                          ATTRIBUTE_TUPLE_SIZE,
593                                                          (char *) *dpp);
594
595                 heap_insert(rel, tup);
596                         
597                 if (hasindex)
598                         CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
599
600                 pfree(tup);
601                 dpp++;
602         }
603
604         /* ----------------
605          *      next we add the system attributes..
606          * ----------------
607          */
608         dpp = HeapAtt;
609         for (i = 0; i < -1 - FirstLowInvalidHeapAttributeNumber; i++)
610         {
611                 (*dpp)->attrelid = new_rel_oid;
612                 /* (*dpp)->attdisbursion = 0;      unneeded */
613
614                 tup = heap_addheader(Natts_pg_attribute,
615                                                          ATTRIBUTE_TUPLE_SIZE,
616                                                          (char *) *dpp);
617
618                 heap_insert(rel, tup);
619
620                 if (hasindex)
621                         CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
622
623                 pfree(tup);
624                 dpp++;
625         }
626
627         heap_close(rel);
628
629         /*
630          * close pg_attribute indices
631          */
632         if (hasindex)
633                 CatalogCloseIndices(Num_pg_attr_indices, idescs);
634 }
635
636 /* --------------------------------
637  *              AddNewRelationTuple
638  *
639  *              this registers the new relation in the catalogs by
640  *              adding a tuple to pg_class.
641  * --------------------------------
642  */
643 static void
644 AddNewRelationTuple(Relation pg_class_desc,
645                                    Relation new_rel_desc,
646                                    Oid new_rel_oid,
647                                    unsigned natts,
648                                    char relkind,
649                                    char *temp_relname)
650 {
651         Form_pg_class new_rel_reltup;
652         HeapTuple       tup;
653         Relation        idescs[Num_pg_class_indices];
654         bool            isBootstrap;
655
656         /* ----------------
657          *      first we munge some of the information in our
658          *      uncataloged relation's relation descriptor.
659          * ----------------
660          */
661         new_rel_reltup = new_rel_desc->rd_rel;
662
663         /* CHECK should get new_rel_oid first via an insert then use XXX */
664
665         /* ----------------
666          * Here we insert bogus estimates of the size of the new relation.
667          * In reality, of course, the new relation has 0 tuples and pages,
668          * and if we were tracking these statistics accurately then we'd
669          * set the fields that way.  But at present the stats will be updated
670          * only by VACUUM or CREATE INDEX, and the user might insert a lot of
671          * tuples before he gets around to doing either of those.  So, instead
672          * of saying the relation is empty, we insert guesstimates.  The point
673          * is to keep the optimizer from making really stupid choices on
674          * never-yet-vacuumed tables; so the estimates need only be large
675          * enough to discourage the optimizer from using nested-loop plans.
676          * With this hack, nested-loop plans will be preferred only after
677          * the table has been proven to be small by VACUUM or CREATE INDEX.
678          * (NOTE: if user does CREATE TABLE, then CREATE INDEX, then loads
679          * the table, he still loses until he vacuums, because CREATE INDEX
680          * will set reltuples to zero.  Can't win 'em all.  Maintaining the
681          * stats on-the-fly would solve the problem, but the overhead of that
682          * would likely cost more than it'd save.)
683          * ----------------
684          */
685         new_rel_reltup->relpages = 10; /* bogus estimates */
686         new_rel_reltup->reltuples = 1000;
687
688         new_rel_reltup->relowner = GetUserId();
689         new_rel_reltup->relkind = relkind;
690         new_rel_reltup->relnatts = natts;
691
692         /* ----------------
693          *      now form a tuple to add to pg_class
694          *      XXX Natts_pg_class_fixed is a hack - see pg_class.h
695          * ----------------
696          */
697         tup = heap_addheader(Natts_pg_class_fixed,
698                                                  CLASS_TUPLE_SIZE,
699                                                  (char *) new_rel_reltup);
700         tup->t_data->t_oid = new_rel_oid;
701
702         /* ----------------
703          *      finally insert the new tuple and free it.
704          *
705          *      Note: I have no idea why we do a
706          *                      SetProcessingMode(BootstrapProcessing);
707          *                here -cim 6/14/90
708          * ----------------
709          */
710         isBootstrap = IsBootstrapProcessingMode() ? true : false;
711
712         SetProcessingMode(BootstrapProcessing);
713
714         heap_insert(pg_class_desc, tup);
715
716         if (temp_relname)
717                 create_temp_relation(temp_relname, tup);
718         
719         if (!isBootstrap)
720         {
721                 /*
722                  * First, open the catalog indices and insert index tuples for the
723                  * new relation.
724                  */
725
726                 CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
727                 CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class_desc, tup);
728                 CatalogCloseIndices(Num_pg_class_indices, idescs);
729                 /* now restore processing mode */
730                 SetProcessingMode(NormalProcessing);
731         }
732         
733         pfree(tup);
734 }
735
736
737 /* --------------------------------
738  *              AddNewRelationType -
739  *
740  *              define a complex type corresponding to the new relation
741  * --------------------------------
742  */
743 static void
744 AddNewRelationType(char *typeName, Oid new_rel_oid)
745 {
746         Oid                     new_type_oid;
747
748         /*
749          * The sizes are set to oid size because it makes implementing sets
750          * MUCH easier, and no one (we hope) uses these fields to figure out
751          * how much space to allocate for the type. An oid is the type used
752          * for a set definition.  When a user requests a set, what they
753          * actually get is the oid of a tuple in the pg_proc catalog, so the
754          * size of the "set" is the size of an oid. Similarly, byval being
755          * true makes sets much easier, and it isn't used by anything else.
756          * Note the assumption that OIDs are the same size as int4s.
757          */
758         new_type_oid = TypeCreate(typeName, /* type name */
759                                                           new_rel_oid,          /* relation oid */
760                                                           typeLen(typeidType(OIDOID)),          /* internal size */
761                                                           typeLen(typeidType(OIDOID)),          /* external size */
762                                                           'c',          /* type-type (catalog) */
763                                                           ',',          /* default array delimiter */
764                                                           "oidin", /* input procedure */
765                                                           "oidout",             /* output procedure */
766                                                           "oidin", /* receive procedure */
767                                                           "oidout",             /* send procedure */
768                                                           NULL,         /* array element type - irrelevent */
769                                                           "-",          /* default type value */
770                                                           (bool) 1, /* passed by value */
771                                                           'i');         /* default alignment */
772 }
773
774 /* --------------------------------
775  *              heap_create_with_catalog
776  *
777  *              creates a new cataloged relation.  see comments above.
778  * --------------------------------
779  */
780 Oid
781 heap_create_with_catalog(char *relname,
782                                                  TupleDesc tupdesc,
783                                                  char relkind,
784                                                  bool istemp)
785 {
786         Relation        pg_class_desc;
787         Relation        new_rel_desc;
788         Oid                     new_rel_oid;
789         int                     natts = tupdesc->natts;
790         char            *temp_relname = NULL;
791         
792         /* ----------------
793          *      sanity checks
794          * ----------------
795          */
796         Assert(IsNormalProcessingMode() || IsBootstrapProcessingMode());
797         if (natts == 0 || natts > MaxHeapAttributeNumber)
798                 elog(ERROR, "Number of attributes is out of range"
799                          "\n\tFrom 1 to %d attributes may be specified",
800                          MaxHeapAttributeNumber);
801
802         CheckAttributeNames(tupdesc);
803
804         /* temp tables can mask non-temp tables */
805         if ((!istemp && RelnameFindRelid(relname)) ||
806            (istemp && get_temp_rel_by_name(relname) != NULL))
807                 elog(ERROR, "Relation '%s' already exists", relname);
808
809         /* invalidate cache so non-temp table is masked by temp */
810         if (istemp)
811         {
812                 Oid relid = RelnameFindRelid(relname);
813
814                 if (relid != InvalidOid)
815                 {
816                         /*
817                          *      This is heavy-handed, but appears necessary bjm 1999/02/01
818                          *      SystemCacheRelationFlushed(relid) is not enough either.
819                          */
820                         RelationForgetRelation(relid);
821                         ResetSystemCache();
822                 }       
823         }
824         
825         /* save user relation name because heap_create changes it */
826         if (istemp)
827         {
828                 temp_relname = pstrdup(relname); /* save original value */
829                 relname = palloc(NAMEDATALEN);
830                 strcpy(relname, temp_relname); /* heap_create will change this */
831         }
832         
833         /* ----------------
834          *      ok, relation does not already exist so now we
835          *      create an uncataloged relation and pull its relation oid
836          *      from the newly formed relation descriptor.
837          *
838          *      Note: The call to heap_create() does all the "real" work
839          *      of creating the disk file for the relation.
840          *  This changes relname for noname and temp tables.
841          * ----------------
842          */
843         new_rel_desc = heap_create(relname, tupdesc, false, istemp);
844
845         new_rel_oid = new_rel_desc->rd_att->attrs[0]->attrelid;
846
847         /* ----------------
848          *      since defining a relation also defines a complex type,
849          *      we add a new system type corresponding to the new relation.
850          * ----------------
851          */
852         AddNewRelationType(relname, new_rel_oid);
853
854         /* ----------------
855          *      now add tuples to pg_attribute for the attributes in
856          *      our new relation.
857          * ----------------
858          */
859         AddNewAttributeTuples(new_rel_oid, tupdesc);
860
861         /* ----------------
862          *      now update the information in pg_class.
863          * ----------------
864          */
865         pg_class_desc = heap_openr(RelationRelationName);
866
867         AddNewRelationTuple(pg_class_desc,
868                                            new_rel_desc,
869                                            new_rel_oid,
870                                            natts,
871                                            relkind,
872                                            temp_relname);
873
874         StoreConstraints(new_rel_desc);
875
876         if (istemp)
877         {
878                 pfree(relname);
879                 pfree(temp_relname);
880         }
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);
890         heap_close(pg_class_desc);
891
892         return new_rel_oid;
893 }
894
895
896 /* ----------------------------------------------------------------
897  *              heap_destroy_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
904  *              6)      remove pg_type tuples
905  *              7)      RemoveConstraints ()
906  *              8)      unlink relation
907  *
908  * old comments
909  *              Except for vital relations, removes relation from
910  *              relation catalog, and related attributes from
911  *              attribute catalog (needed?).  (Anything else?)
912  *
913  *              get proper relation from relation catalog (if not arg)
914  *              check if relation is vital (strcmp()/reltype?)
915  *              scan attribute catalog deleting attributes of reldesc
916  *                              (necessary?)
917  *              delete relation from relation catalog
918  *              (How are the tuples of the relation discarded?)
919  *
920  *              XXX Must fix to work with indexes.
921  *              There may be a better order for doing things.
922  *              Problems with destroying a deleted database--cannot create
923  *              a struct reldesc without having an open file descriptor.
924  * ----------------------------------------------------------------
925  */
926
927 /* --------------------------------
928  *              RelationRemoveInheritance
929  *
930  *              Note: for now, we cause an exception if relation is a
931  *              superclass.  Someday, we may want to allow this and merge
932  *              the type info into subclass procedures....      this seems like
933  *              lots of work.
934  * --------------------------------
935  */
936 static void
937 RelationRemoveInheritance(Relation relation)
938 {
939         Relation        catalogRelation;
940         HeapTuple       tuple;
941         HeapScanDesc scan;
942         ScanKeyData entry;
943         bool            found = false;
944
945         /* ----------------
946          *      open pg_inherits
947          * ----------------
948          */
949         catalogRelation = heap_openr(InheritsRelationName);
950
951         /* ----------------
952          *      form a scan key for the subclasses of this class
953          *      and begin scanning
954          * ----------------
955          */
956         ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_inherits_inhparent,
957                                                    F_OIDEQ,
958                                                    ObjectIdGetDatum(RelationGetRelid(relation)));
959
960         scan = heap_beginscan(catalogRelation,
961                                                   false,
962                                                   SnapshotNow,
963                                                   1,
964                                                   &entry);
965
966         /* ----------------
967          *      if any subclasses exist, then we disallow the deletion.
968          * ----------------
969          */
970         tuple = heap_getnext(scan, 0);
971         if (HeapTupleIsValid(tuple))
972         {
973                 heap_endscan(scan);
974                 heap_close(catalogRelation);
975
976                 elog(ERROR, "Relation '%u' inherits '%s'",
977                          ((Form_pg_inherits) GETSTRUCT(tuple))->inhrel,
978                          RelationGetRelationName(relation));
979         }
980
981         /* ----------------
982          *      If we get here, it means the relation has no subclasses
983          *      so we can trash it.  First we remove dead INHERITS tuples.
984          * ----------------
985          */
986         entry.sk_attno = Anum_pg_inherits_inhrel;
987
988         scan = heap_beginscan(catalogRelation,
989                                                   false,
990                                                   SnapshotNow,
991                                                   1,
992                                                   &entry);
993
994         while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
995         {
996                 heap_delete(catalogRelation, &tuple->t_self, NULL);
997                 found = true;
998         }
999
1000         heap_endscan(scan);
1001         heap_close(catalogRelation);
1002
1003         /* ----------------
1004          *      now remove dead IPL tuples
1005          * ----------------
1006          */
1007         catalogRelation = heap_openr(InheritancePrecidenceListRelationName);
1008
1009         entry.sk_attno = Anum_pg_ipl_iplrel;
1010
1011         scan = heap_beginscan(catalogRelation,
1012                                                   false,
1013                                                   SnapshotNow,
1014                                                   1,
1015                                                   &entry);
1016
1017         while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
1018                 heap_delete(catalogRelation, &tuple->t_self, NULL);
1019
1020         heap_endscan(scan);
1021         heap_close(catalogRelation);
1022 }
1023
1024 /* --------------------------------
1025  *              RelationRemoveIndexes
1026  *
1027  * --------------------------------
1028  */
1029 static void
1030 RelationRemoveIndexes(Relation relation)
1031 {
1032         Relation        indexRelation;
1033         HeapTuple       tuple;
1034         HeapScanDesc scan;
1035         ScanKeyData entry;
1036
1037         indexRelation = heap_openr(IndexRelationName);
1038
1039         ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_index_indrelid,
1040                                                    F_OIDEQ,
1041                                                    ObjectIdGetDatum(RelationGetRelid(relation)));
1042
1043         scan = heap_beginscan(indexRelation,
1044                                                   false,
1045                                                   SnapshotNow,
1046                                                   1,
1047                                                   &entry);
1048
1049         while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
1050                 index_destroy(((Form_pg_index) GETSTRUCT(tuple))->indexrelid);
1051
1052         heap_endscan(scan);
1053         heap_close(indexRelation);
1054 }
1055
1056 /* --------------------------------
1057  *              DeleteRelationTuple
1058  *
1059  * --------------------------------
1060  */
1061 static void
1062 DeleteRelationTuple(Relation rel)
1063 {
1064         Relation        pg_class_desc;
1065         HeapTuple       tup;
1066
1067         /* ----------------
1068          *      open pg_class
1069          * ----------------
1070          */
1071         pg_class_desc = heap_openr(RelationRelationName);
1072
1073         tup = SearchSysCacheTupleCopy(RELOID,
1074                                            ObjectIdGetDatum(rel->rd_att->attrs[0]->attrelid),
1075                                                                   0, 0, 0);
1076         if (!HeapTupleIsValid(tup))
1077         {
1078                 heap_close(pg_class_desc);
1079                 elog(ERROR, "Relation '%s' does not exist",
1080                          &rel->rd_rel->relname);
1081         }
1082
1083         /* ----------------
1084          *      delete the relation tuple from pg_class, and finish up.
1085          * ----------------
1086          */
1087         heap_delete(pg_class_desc, &tup->t_self, NULL);
1088         pfree(tup);
1089
1090         heap_close(pg_class_desc);
1091 }
1092
1093 /* --------------------------------
1094  *              DeleteAttributeTuples
1095  *
1096  * --------------------------------
1097  */
1098 static void
1099 DeleteAttributeTuples(Relation rel)
1100 {
1101         Relation        pg_attribute_desc;
1102         HeapTuple       tup;
1103         int2            attnum;
1104
1105         /* ----------------
1106          *      open pg_attribute
1107          * ----------------
1108          */
1109         pg_attribute_desc = heap_openr(AttributeRelationName);
1110
1111         /* -----------------
1112          * Get a write lock _before_ getting the read lock in the scan
1113          * ----------------
1114          */
1115         LockRelation(pg_attribute_desc, AccessExclusiveLock);
1116
1117         for (attnum = FirstLowInvalidHeapAttributeNumber + 1;
1118                  attnum <= rel->rd_att->natts;
1119                  attnum++)
1120         {
1121                 if (HeapTupleIsValid(tup = SearchSysCacheTupleCopy(ATTNUM,
1122                                                                  ObjectIdGetDatum(RelationGetRelid(rel)),
1123                                                                                                    Int16GetDatum(attnum),
1124                                                                                                                    0, 0)))
1125                 {
1126                         heap_delete(pg_attribute_desc, &tup->t_self, NULL);
1127                         pfree(tup);
1128                 }
1129         }
1130
1131         /* ----------------
1132          * Release the write lock
1133          * ----------------
1134          */
1135         UnlockRelation(pg_attribute_desc, AccessExclusiveLock);
1136         heap_close(pg_attribute_desc);
1137 }
1138
1139 /* --------------------------------
1140  *              DeleteTypeTuple
1141  *
1142  *              If the user attempts to destroy a relation and there
1143  *              exists attributes in other relations of type
1144  *              "relation we are deleting", then we have to do something
1145  *              special.  presently we disallow the destroy.
1146  * --------------------------------
1147  */
1148 static void
1149 DeleteTypeTuple(Relation rel)
1150 {
1151         Relation        pg_type_desc;
1152         HeapScanDesc pg_type_scan;
1153         Relation        pg_attribute_desc;
1154         HeapScanDesc pg_attribute_scan;
1155         ScanKeyData key;
1156         ScanKeyData attkey;
1157         HeapTuple       tup;
1158         HeapTuple       atttup;
1159         Oid                     typoid;
1160
1161         /* ----------------
1162          *      open pg_type
1163          * ----------------
1164          */
1165         pg_type_desc = heap_openr(TypeRelationName);
1166
1167         /* ----------------
1168          *      create a scan key to locate the type tuple corresponding
1169          *      to this relation.
1170          * ----------------
1171          */
1172         ScanKeyEntryInitialize(&key, 0,
1173                                                    Anum_pg_type_typrelid,
1174                                                    F_OIDEQ,
1175                                                    ObjectIdGetDatum(RelationGetRelid(rel)));
1176
1177         pg_type_scan = heap_beginscan(pg_type_desc,
1178                                                                   0,
1179                                                                   SnapshotNow,
1180                                                                   1,
1181                                                                   &key);
1182
1183         /* ----------------
1184          *      use heap_getnext() to fetch the pg_type tuple.  If this
1185          *      tuple is not valid then something's wrong.
1186          * ----------------
1187          */
1188         tup = heap_getnext(pg_type_scan, 0);
1189
1190         if (!HeapTupleIsValid(tup))
1191         {
1192                 heap_endscan(pg_type_scan);
1193                 heap_close(pg_type_desc);
1194                 elog(ERROR, "DeleteTypeTuple: %s type nonexistent",
1195                          &rel->rd_rel->relname);
1196         }
1197
1198         /* ----------------
1199          *      now scan pg_attribute.  if any other relations have
1200          *      attributes of the type of the relation we are deleteing
1201          *      then we have to disallow the deletion.  should talk to
1202          *      stonebraker about this.  -cim 6/19/90
1203          * ----------------
1204          */
1205         typoid = tup->t_data->t_oid;
1206
1207         pg_attribute_desc = heap_openr(AttributeRelationName);
1208
1209         ScanKeyEntryInitialize(&attkey,
1210                                                    0,
1211                                                    Anum_pg_attribute_atttypid,
1212                                                    F_OIDEQ,
1213                                                    typoid);
1214
1215         pg_attribute_scan = heap_beginscan(pg_attribute_desc,
1216                                                                            0,
1217                                                                            SnapshotNow,
1218                                                                            1,
1219                                                                            &attkey);
1220
1221         /* ----------------
1222          *      try and get a pg_attribute tuple.  if we succeed it means
1223          *      we can't delete the relation because something depends on
1224          *      the schema.
1225          * ----------------
1226          */
1227         atttup = heap_getnext(pg_attribute_scan, 0);
1228
1229         if (HeapTupleIsValid(atttup))
1230         {
1231                 Oid                     relid = ((Form_pg_attribute) GETSTRUCT(atttup))->attrelid;
1232
1233                 heap_endscan(pg_type_scan);
1234                 heap_close(pg_type_desc);
1235                 heap_endscan(pg_attribute_scan);
1236                 heap_close(pg_attribute_desc);
1237
1238                 elog(ERROR, "DeleteTypeTuple: att of type %s exists in relation %u",
1239                          &rel->rd_rel->relname, relid);
1240         }
1241         heap_endscan(pg_attribute_scan);
1242         heap_close(pg_attribute_desc);
1243
1244         /* ----------------
1245          *      Ok, it's safe so we delete the relation tuple
1246          *      from pg_type and finish up.  But first end the scan so that
1247          *      we release the read lock on pg_type.  -mer 13 Aug 1991
1248          * ----------------
1249          */
1250         heap_delete(pg_type_desc, &tup->t_self, NULL);
1251
1252         heap_endscan(pg_type_scan);
1253         heap_close(pg_type_desc);
1254 }
1255
1256 /* --------------------------------
1257  *              heap_destroy_with_catalog
1258  *
1259  * --------------------------------
1260  */
1261 void
1262 heap_destroy_with_catalog(char *relname)
1263 {
1264         Relation        rel;
1265         Oid                     rid;
1266         bool            istemp = (get_temp_rel_by_name(relname) != NULL);
1267
1268         /* ----------------
1269          *      first open the relation.  if the relation does exist,
1270          *      heap_openr() returns NULL.
1271          * ----------------
1272          */
1273         rel = heap_openr(relname);
1274         if (rel == NULL)
1275                 elog(ERROR, "Relation '%s' does not exist", relname);
1276
1277         LockRelation(rel, AccessExclusiveLock);
1278         rid = rel->rd_id;
1279
1280         /* ----------------
1281          *      prevent deletion of system relations
1282          * ----------------
1283          */
1284         /* allow temp of pg_class? Guess so. */
1285         if (!istemp &&
1286                 !allowSystemTableMods && IsSystemRelationName(RelationGetRelationName(rel)->data))
1287                 elog(ERROR, "System relation '%s' cannot be destroyed",
1288                          &rel->rd_rel->relname);
1289
1290         /* ----------------
1291          *      remove inheritance information
1292          * ----------------
1293          */
1294         RelationRemoveInheritance(rel);
1295
1296         /* ----------------
1297          *      remove indexes if necessary
1298          * ----------------
1299          */
1300         if (rel->rd_rel->relhasindex)
1301                 RelationRemoveIndexes(rel);
1302
1303         /* ----------------
1304          *      remove rules if necessary
1305          * ----------------
1306          */
1307         if (rel->rd_rules != NULL)
1308                 RelationRemoveRules(rid);
1309
1310         /* triggers */
1311         if (rel->rd_rel->reltriggers > 0)
1312                 RelationRemoveTriggers(rel);
1313
1314         /* ----------------
1315          *      delete attribute tuples
1316          * ----------------
1317          */
1318         DeleteAttributeTuples(rel);
1319
1320         if (istemp)
1321                 remove_temp_relation(rid);
1322                 
1323         /* ----------------
1324          *      delete type tuple.      here we want to see the effects
1325          *      of the deletions we just did, so we use setheapoverride().
1326          * ----------------
1327          */
1328         setheapoverride(true);
1329         DeleteTypeTuple(rel);
1330         setheapoverride(false);
1331
1332         /* ----------------
1333          *      delete relation tuple
1334          * ----------------
1335          */
1336          /* must delete fake tuple in cache */
1337         DeleteRelationTuple(rel);
1338
1339         /*
1340          * release dirty buffers of this relation
1341          */
1342         ReleaseRelationBuffers(rel);
1343
1344         /* ----------------
1345          *      flush the relation from the relcache
1346          * ----------------
1347          * Does nothing!!! Flushing moved below.        - vadim 06/04/97
1348         RelationIdInvalidateRelationCacheByRelationId(rel->rd_id);
1349          */
1350
1351         RemoveConstraints(rel);
1352
1353         /* ----------------
1354          *      unlink the relation and finish up.
1355          * ----------------
1356          */
1357         if (!(rel->rd_isnoname) || !(rel->rd_nonameunlinked))
1358                 smgrunlink(DEFAULT_SMGR, rel);
1359
1360         rel->rd_nonameunlinked = TRUE;
1361
1362         UnlockRelation(rel, AccessExclusiveLock);
1363
1364         heap_close(rel);
1365
1366         RelationForgetRelation(rid);
1367 }
1368
1369 /*
1370  * heap_destroy
1371  *        destroy and close temporary relations
1372  *
1373  */
1374
1375 void
1376 heap_destroy(Relation rel)
1377 {
1378         ReleaseRelationBuffers(rel);
1379         if (!(rel->rd_isnoname) || !(rel->rd_nonameunlinked))
1380                 smgrunlink(DEFAULT_SMGR, rel);
1381         rel->rd_nonameunlinked = TRUE;
1382         heap_close(rel);
1383         RemoveFromNoNameRelList(rel);
1384 }
1385
1386
1387 /**************************************************************
1388   functions to deal with the list of temporary relations
1389 **************************************************************/
1390
1391 /* --------------
1392    InitTempRellist():
1393
1394    initialize temporary relations list
1395    the tempRelList is a list of temporary relations that
1396    are created in the course of the transactions
1397    they need to be destroyed properly at the end of the transactions
1398
1399    MODIFIES the global variable tempRels
1400
1401  >> NOTE <<
1402
1403    malloc is used instead of palloc because we KNOW when we are
1404    going to free these things.  Keeps us away from the memory context
1405    hairyness
1406
1407 */
1408 void
1409 InitNoNameRelList(void)
1410 {
1411         if (tempRels)
1412         {
1413                 free(tempRels->rels);
1414                 free(tempRels);
1415         }
1416
1417         tempRels = (TempRelList *) malloc(sizeof(TempRelList));
1418         tempRels->size = NONAME_REL_LIST_SIZE;
1419         tempRels->rels = (Relation *) malloc(sizeof(Relation) * tempRels->size);
1420         MemSet(tempRels->rels, 0, sizeof(Relation) * tempRels->size);
1421         tempRels->num = 0;
1422 }
1423
1424 /*
1425    removes a relation from the TempRelList
1426
1427    MODIFIES the global variable tempRels
1428           we don't really remove it, just mark it as NULL
1429           and DestroyNoNameRels will look for NULLs
1430 */
1431 static void
1432 RemoveFromNoNameRelList(Relation r)
1433 {
1434         int                     i;
1435
1436         if (!tempRels)
1437                 return;
1438
1439         for (i = 0; i < tempRels->num; i++)
1440         {
1441                 if (tempRels->rels[i] == r)
1442                 {
1443                         tempRels->rels[i] = NULL;
1444                         break;
1445                 }
1446         }
1447 }
1448
1449 /*
1450    add a temporary relation to the TempRelList
1451
1452    MODIFIES the global variable tempRels
1453 */
1454 static void
1455 AddToNoNameRelList(Relation r)
1456 {
1457         if (!tempRels)
1458                 return;
1459
1460         if (tempRels->num == tempRels->size)
1461         {
1462                 tempRels->size += NONAME_REL_LIST_SIZE;
1463                 tempRels->rels = realloc(tempRels->rels,
1464                                                                  sizeof(Relation) * tempRels->size);
1465         }
1466         tempRels->rels[tempRels->num] = r;
1467         tempRels->num++;
1468 }
1469
1470 /*
1471    go through the tempRels list and destroy each of the relations
1472 */
1473 void
1474 DestroyNoNameRels(void)
1475 {
1476         int                     i;
1477         Relation        rel;
1478
1479         if (!tempRels)
1480                 return;
1481
1482         for (i = 0; i < tempRels->num; i++)
1483         {
1484                 rel = tempRels->rels[i];
1485                 /* rel may be NULL if it has been removed from the list already */
1486                 if (rel)
1487                         heap_destroy(rel);
1488         }
1489         free(tempRels->rels);
1490         free(tempRels);
1491         tempRels = NULL;
1492 }
1493
1494
1495 static void
1496 StoreAttrDefault(Relation rel, AttrDefault *attrdef)
1497 {
1498         char            str[MAX_PARSE_BUFFER];
1499         char            cast[2 * NAMEDATALEN] = {0};
1500         Form_pg_attribute atp = rel->rd_att->attrs[attrdef->adnum - 1];
1501         QueryTreeList *queryTree_list;
1502         Query      *query;
1503         List       *planTree_list;
1504         TargetEntry *te;
1505         Resdom     *resdom;
1506         Node       *expr;
1507         Oid                     type;
1508         char       *adbin;
1509         MemoryContext oldcxt;
1510         Relation        adrel;
1511         Relation        idescs[Num_pg_attrdef_indices];
1512         HeapTuple       tuple;
1513         Datum           values[4];
1514         char            nulls[4] = {' ', ' ', ' ', ' '};
1515         extern GlobalMemory CacheCxt;
1516
1517 start:;
1518         /* Surround table name with double quotes to allow mixed-case and
1519          * whitespaces in names. - BGA 1998-11-14
1520          */
1521         snprintf(str, MAX_PARSE_BUFFER, 
1522                          "select %s%s from \"%.*s\"", attrdef->adsrc, cast,
1523                          NAMEDATALEN, rel->rd_rel->relname.data);
1524         setheapoverride(true);
1525         planTree_list = (List *) pg_parse_and_plan(str, NULL, 0, &queryTree_list, None, FALSE);
1526         setheapoverride(false);
1527         query = (Query *) (queryTree_list->qtrees[0]);
1528
1529         if (length(query->rtable) > 1 ||
1530                 flatten_tlist(query->targetList) != NIL)
1531                 elog(ERROR, "Cannot use attribute(s) in DEFAULT clause");
1532         te = (TargetEntry *) lfirst(query->targetList);
1533         resdom = te->resdom;
1534         expr = te->expr;
1535         type = exprType(expr);
1536
1537         if (type != atp->atttypid)
1538         {
1539                 if (IS_BINARY_COMPATIBLE(type, atp->atttypid))
1540                         ; /* use without change */
1541                 else if (can_coerce_type(1, &(type), &(atp->atttypid)))
1542                         expr = coerce_type(NULL, (Node *)expr, type, atp->atttypid);
1543                 else if (IsA(expr, Const))
1544                 {
1545                         if (*cast != 0)
1546                                 elog(ERROR, "DEFAULT clause const type '%s' mismatched with column type '%s'",
1547                                          typeidTypeName(type), typeidTypeName(atp->atttypid));
1548                         snprintf(cast, 2*NAMEDATALEN, ":: %s", typeidTypeName(atp->atttypid));
1549                         goto start;
1550                 }
1551                 else
1552                         elog(ERROR, "DEFAULT clause type '%s' mismatched with column type '%s'",
1553                                  typeidTypeName(type), typeidTypeName(atp->atttypid));
1554         }
1555
1556         adbin = nodeToString(expr);
1557         oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
1558         attrdef->adbin = (char *) palloc(strlen(adbin) + 1);
1559         strcpy(attrdef->adbin, adbin);
1560         (void) MemoryContextSwitchTo(oldcxt);
1561         pfree(adbin);
1562
1563         values[Anum_pg_attrdef_adrelid - 1] = rel->rd_id;
1564         values[Anum_pg_attrdef_adnum - 1] = attrdef->adnum;
1565         values[Anum_pg_attrdef_adbin - 1] = PointerGetDatum(textin(attrdef->adbin));
1566         values[Anum_pg_attrdef_adsrc - 1] = PointerGetDatum(textin(attrdef->adsrc));
1567         adrel = heap_openr(AttrDefaultRelationName);
1568         tuple = heap_formtuple(adrel->rd_att, values, nulls);
1569         CatalogOpenIndices(Num_pg_attrdef_indices, Name_pg_attrdef_indices, idescs);
1570         heap_insert(adrel, tuple);
1571         CatalogIndexInsert(idescs, Num_pg_attrdef_indices, adrel, tuple);
1572         CatalogCloseIndices(Num_pg_attrdef_indices, idescs);
1573         heap_close(adrel);
1574
1575         pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
1576         pfree(DatumGetPointer(values[Anum_pg_attrdef_adsrc - 1]));
1577         pfree(tuple);
1578
1579 }
1580
1581 static void
1582 StoreRelCheck(Relation rel, ConstrCheck *check)
1583 {
1584         char            str[MAX_PARSE_BUFFER];
1585         QueryTreeList *queryTree_list;
1586         Query      *query;
1587         List       *planTree_list;
1588         Plan       *plan;
1589         List       *qual;
1590         char       *ccbin;
1591         MemoryContext oldcxt;
1592         Relation        rcrel;
1593         Relation        idescs[Num_pg_relcheck_indices];
1594         HeapTuple       tuple;
1595         Datum           values[4];
1596         char            nulls[4] = {' ', ' ', ' ', ' '};
1597         extern GlobalMemory CacheCxt;
1598
1599         /* Check for table's existance. Surround table name with double-quotes
1600          * to allow mixed-case and whitespace names. - thomas 1998-11-12
1601          */
1602         snprintf(str, MAX_PARSE_BUFFER, 
1603                         "select 1 from \"%.*s\" where %s",
1604                         NAMEDATALEN, rel->rd_rel->relname.data, check->ccsrc);
1605         setheapoverride(true);
1606         planTree_list = (List *) pg_parse_and_plan(str, NULL, 0, &queryTree_list, None, FALSE);
1607         setheapoverride(false);
1608         query = (Query *) (queryTree_list->qtrees[0]);
1609
1610         if (length(query->rtable) > 1)
1611                 elog(ERROR, "Only relation '%.*s' can be referenced",
1612                          NAMEDATALEN, rel->rd_rel->relname.data);
1613
1614         plan = (Plan *) lfirst(planTree_list);
1615         qual = plan->qual;
1616
1617         ccbin = nodeToString(qual);
1618         oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
1619         check->ccbin = (char *) palloc(strlen(ccbin) + 1);
1620         strcpy(check->ccbin, ccbin);
1621         (void) MemoryContextSwitchTo(oldcxt);
1622         pfree(ccbin);
1623
1624         values[Anum_pg_relcheck_rcrelid - 1] = rel->rd_id;
1625         values[Anum_pg_relcheck_rcname - 1] = PointerGetDatum(namein(check->ccname));
1626         values[Anum_pg_relcheck_rcbin - 1] = PointerGetDatum(textin(check->ccbin));
1627         values[Anum_pg_relcheck_rcsrc - 1] = PointerGetDatum(textin(check->ccsrc));
1628         rcrel = heap_openr(RelCheckRelationName);
1629         tuple = heap_formtuple(rcrel->rd_att, values, nulls);
1630         CatalogOpenIndices(Num_pg_relcheck_indices, Name_pg_relcheck_indices, idescs);
1631         heap_insert(rcrel, tuple);
1632         CatalogIndexInsert(idescs, Num_pg_relcheck_indices, rcrel, tuple);
1633         CatalogCloseIndices(Num_pg_relcheck_indices, idescs);
1634         heap_close(rcrel);
1635
1636         pfree(DatumGetPointer(values[Anum_pg_relcheck_rcname - 1]));
1637         pfree(DatumGetPointer(values[Anum_pg_relcheck_rcbin - 1]));
1638         pfree(DatumGetPointer(values[Anum_pg_relcheck_rcsrc - 1]));
1639         pfree(tuple);
1640
1641         return;
1642 }
1643
1644 static void
1645 StoreConstraints(Relation rel)
1646 {
1647         TupleConstr *constr = rel->rd_att->constr;
1648         int                     i;
1649
1650         if (!constr)
1651                 return;
1652
1653         if (constr->num_defval > 0)
1654         {
1655                 for (i = 0; i < constr->num_defval; i++)
1656                         StoreAttrDefault(rel, &(constr->defval[i]));
1657         }
1658
1659         if (constr->num_check > 0)
1660         {
1661                 for (i = 0; i < constr->num_check; i++)
1662                         StoreRelCheck(rel, &(constr->check[i]));
1663         }
1664
1665         return;
1666 }
1667
1668 static void
1669 RemoveAttrDefault(Relation rel)
1670 {
1671         Relation        adrel;
1672         HeapScanDesc adscan;
1673         ScanKeyData key;
1674         HeapTuple       tup;
1675
1676         adrel = heap_openr(AttrDefaultRelationName);
1677
1678         ScanKeyEntryInitialize(&key, 0, Anum_pg_attrdef_adrelid,
1679                                                    F_OIDEQ, rel->rd_id);
1680
1681         LockRelation(adrel, AccessExclusiveLock);
1682
1683         adscan = heap_beginscan(adrel, 0, SnapshotNow, 1, &key);
1684
1685         while (HeapTupleIsValid(tup = heap_getnext(adscan, 0)))
1686                 heap_delete(adrel, &tup->t_self, NULL);
1687
1688         heap_endscan(adscan);
1689
1690         UnlockRelation(adrel, AccessExclusiveLock);
1691         heap_close(adrel);
1692
1693 }
1694
1695 static void
1696 RemoveRelCheck(Relation rel)
1697 {
1698         Relation        rcrel;
1699         HeapScanDesc rcscan;
1700         ScanKeyData key;
1701         HeapTuple       tup;
1702
1703         rcrel = heap_openr(RelCheckRelationName);
1704
1705         ScanKeyEntryInitialize(&key, 0, Anum_pg_relcheck_rcrelid,
1706                                                    F_OIDEQ, rel->rd_id);
1707
1708         LockRelation(rcrel, AccessExclusiveLock);
1709
1710         rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key);
1711
1712         while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0)))
1713                 heap_delete(rcrel, &tup->t_self, NULL);
1714
1715         heap_endscan(rcscan);
1716
1717         UnlockRelation(rcrel, AccessExclusiveLock);
1718         heap_close(rcrel);
1719
1720 }
1721
1722 static void
1723 RemoveConstraints(Relation rel)
1724 {
1725         TupleConstr *constr = rel->rd_att->constr;
1726
1727         if (!constr)
1728                 return;
1729
1730         if (constr->num_defval > 0)
1731                 RemoveAttrDefault(rel);
1732
1733         if (constr->num_check > 0)
1734                 RemoveRelCheck(rel);
1735
1736         return;
1737 }