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