]> granicus.if.org Git - postgresql/blob - src/backend/catalog/heap.c
Makes it compile...still needs work
[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.4 1996/11/05 11:57:50 scrappy Exp $
11  *
12  * INTERFACE ROUTINES
13  *      heap_creatr()           - Create an uncataloged heap relation
14  *      heap_create()           - Create a cataloged relation
15  *      heap_destroy()          - Removes named relation from catalogs
16  *
17  * NOTES
18  *    this code taken from access/heap/create.c, which contains
19  *    the old heap_creater, amcreate, and amdestroy.  those routines
20  *    will soon call these routines using the function manager,
21  *    just like the poorly named "NewXXX" routines do.  The
22  *    "New" routines are all going to die soon, once and for all!
23  *      -cim 1/13/91
24  *
25  *-------------------------------------------------------------------------
26  */
27 #include <stdio.h>      /* for sprintf() */
28 #include <sys/file.h>
29 #include <string.h>
30
31 #include "postgres.h"
32
33 #include <catalog/heap.h>
34 #include <catalog/pg_proc.h>
35
36 #include "parser/catalog_utils.h"
37
38 #include "access/heapam.h"
39 #include "access/genam.h"
40 #include "access/istrat.h"
41 #include "storage/bufmgr.h"
42 #include "lib/hasht.h"
43 #include "miscadmin.h"
44 #include "fmgr.h"
45 #include "utils/builtins.h"
46 #include "utils/mcxt.h"
47 #include "utils/palloc.h"
48 #include "utils/relcache.h"
49
50 #include "catalog/catname.h"
51 #include "catalog/pg_attribute.h"
52 #include "catalog/pg_index.h"
53 #include "catalog/pg_inherits.h"
54 #include "catalog/pg_ipl.h"
55 #include "catalog/index.h"
56 #include "catalog/indexing.h"
57
58 #include "catalog/catalog.h"
59
60 #include "storage/lmgr.h"
61
62 #include "rewrite/rewriteRemove.h"
63
64 #include "storage/smgr.h"
65
66 static void AddNewAttributeTuples(Oid new_rel_oid, TupleDesc tupdesc);
67 static void CheckAttributeNames(TupleDesc tupdesc);
68
69 /* ----------------------------------------------------------------
70  *              XXX UGLY HARD CODED BADNESS FOLLOWS XXX
71  *
72  *      these should all be moved to someplace in the lib/catalog
73  *      module, if not obliterated first.
74  * ----------------------------------------------------------------
75  */
76
77
78 /*
79  * Note:
80  *      Should the executor special case these attributes in the future?
81  *      Advantage:  consume 1/2 the space in the ATTRIBUTE relation.
82  *      Disadvantage:  having rules to compute values in these tuples may
83  *              be more difficult if not impossible.
84  */
85
86 static  FormData_pg_attribute a1 = {
87     0xffffffff, {"ctid"}, 27l, 0l, 0l, 0l, sizeof (ItemPointerData),
88     SelfItemPointerAttributeNumber, 0, '\0', '\001', 0l, 'i'
89 };
90
91 static  FormData_pg_attribute a2 = {
92     0xffffffff, {"oid"}, 26l, 0l, 0l, 0l, sizeof(Oid),
93     ObjectIdAttributeNumber, 0, '\001', '\001', 0l, 'i'
94 };
95
96 static  FormData_pg_attribute a3 = {
97     0xffffffff, {"xmin"}, 28l, 0l, 0l, 0l, sizeof (TransactionId),
98     MinTransactionIdAttributeNumber, 0, '\0', '\001', 0l, 'i',
99 };
100
101 static  FormData_pg_attribute a4 = {
102     0xffffffff, {"cmin"}, 29l, 0l, 0l, 0l, sizeof (CommandId),
103     MinCommandIdAttributeNumber, 0, '\001', '\001', 0l, 's'
104 };
105
106 static  FormData_pg_attribute a5 = {
107     0xffffffff, {"xmax"}, 28l, 0l, 0l, 0l, sizeof (TransactionId),
108     MaxTransactionIdAttributeNumber, 0, '\0', '\001', 0l, 'i'
109 };
110
111 static  FormData_pg_attribute a6 = {
112     0xffffffff, {"cmax"}, 29l, 0l, 0l, 0l, sizeof (CommandId),
113     MaxCommandIdAttributeNumber, 0, '\001', '\001', 0l, 's'
114 };
115
116 static  FormData_pg_attribute a7 = {
117     0xffffffff, {"chain"}, 27l, 0l, 0l, 0l, sizeof (ItemPointerData),
118     ChainItemPointerAttributeNumber, 0, '\0', '\001', 0l, 'i',
119 };
120
121 static  FormData_pg_attribute a8 = {
122     0xffffffff, {"anchor"}, 27l, 0l, 0l, 0l, sizeof (ItemPointerData),
123     AnchorItemPointerAttributeNumber, 0, '\0', '\001', 0l, 'i'
124 };
125
126 static  FormData_pg_attribute a9 = {
127     0xffffffff, {"tmin"}, 20l, 0l, 0l, 0l, sizeof (AbsoluteTime),
128     MinAbsoluteTimeAttributeNumber, 0, '\001', '\001', 0l, 'i'
129 };
130
131 static  FormData_pg_attribute a10 = {
132     0xffffffff, {"tmax"}, 20l, 0l, 0l, 0l, sizeof (AbsoluteTime),
133     MaxAbsoluteTimeAttributeNumber, 0, '\001', '\001', 0l, 'i'
134 };
135
136 static  FormData_pg_attribute a11 = {
137     0xffffffff, {"vtype"}, 18l, 0l, 0l, 0l, sizeof (char),
138     VersionTypeAttributeNumber, 0, '\001', '\001', 0l, 'c'
139 };
140
141 static  AttributeTupleForm HeapAtt[] =
142 { &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10, &a11 };
143
144 /* ----------------------------------------------------------------
145  *              XXX END OF UGLY HARD CODED BADNESS XXX
146  * ----------------------------------------------------------------
147  */
148
149 /* the tempRelList holds
150    the list of temporary uncatalogued relations that are created.
151    these relations should be destroyed at the end of transactions
152 */
153 typedef struct tempRelList {
154     Relation *rels; /* array of relation descriptors */
155     int  num; /* number of temporary relations */
156     int size; /* size of space allocated for the rels array */
157 } TempRelList;
158
159 #define TEMP_REL_LIST_SIZE  32
160
161 static TempRelList *tempRels = NULL;   
162
163
164 /* ----------------------------------------------------------------
165  *      heap_creatr     - Create an uncataloged heap relation
166  *
167  *      Fields relpages, reltuples, reltuples, relkeys, relhistory,
168  *      relisindexed, and relkind of rdesc->rd_rel are initialized
169  *      to all zeros, as are rd_last and rd_hook.  Rd_refcnt is set to 1.
170  *
171  *      Remove the system relation specific code to elsewhere eventually.
172  *
173  *      Eventually, must place information about this temporary relation
174  *      into the transaction context block.
175  *
176  *  
177  * if heap_creatr is called with "" as the name, then heap_creatr will create a
178  * temporary name   "temp_$RELOID" for the relation
179  * ----------------------------------------------------------------
180  */
181 Relation
182 heap_creatr(char *name, 
183             unsigned smgr,
184             TupleDesc tupDesc) 
185 {
186     register unsigned   i;
187     Oid         relid;
188     Relation            rdesc;
189     int                 len;
190     bool                nailme = false;
191     char*               relname = name;
192     char                tempname[40];
193     int isTemp = 0;
194     int natts = tupDesc->natts;
195 /*    AttributeTupleForm *att = tupDesc->attrs; */
196     
197     extern GlobalMemory CacheCxt;
198     MemoryContext       oldcxt;
199
200     /* ----------------
201      *  sanity checks
202      * ----------------
203      */
204     AssertArg(natts > 0);
205
206     if (IsSystemRelationName(relname) && IsNormalProcessingMode())
207         {
208             elog(WARN, 
209                  "Illegal class name: %s -- pg_ is reserved for system catalogs",
210                  relname);
211         }
212     
213     /* ----------------
214      *  switch to the cache context so that we don't lose
215      *  allocations at the end of this transaction, I guess.
216      *  -cim 6/14/90
217      * ----------------
218      */
219     if (!CacheCxt)
220         CacheCxt = CreateGlobalMemory("Cache");
221     
222     oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt);
223     
224     /* ----------------
225      *  real ugly stuff to assign the proper relid in the relation
226      *  descriptor follows.
227      * ----------------
228      */
229     if (! strcmp(RelationRelationName,relname))
230         {
231             relid = RelOid_pg_class;
232             nailme = true;
233         }
234     else if (! strcmp(AttributeRelationName,relname))
235         {
236             relid = RelOid_pg_attribute;
237             nailme = true;
238         }
239     else if (! strcmp(ProcedureRelationName, relname))
240         {
241             relid = RelOid_pg_proc;
242             nailme = true;
243         }
244     else if (! strcmp(TypeRelationName,relname))
245         {
246             relid = RelOid_pg_type;
247             nailme = true;
248         }
249     else
250       {
251         relid = newoid();
252     
253         if (name[0] == '\0')
254           {
255             sprintf(tempname, "temp_%d", relid);
256             relname = tempname;
257             isTemp = 1;
258           };
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     rdesc = (Relation) palloc(len);
270     memset((char *)rdesc, 0,len);
271     
272     /* ----------
273        create a new tuple descriptor from the one passed in
274     */
275     rdesc->rd_att = CreateTupleDescCopy(tupDesc);
276     
277     /* ----------------
278      *  initialize the fields of our new relation descriptor
279      * ----------------
280      */
281     
282     /* ----------------
283      *  nail the reldesc if this is a bootstrap create reln and
284      *  we may need it in the cache later on in the bootstrap
285      *  process so we don't ever want it kicked out.  e.g. pg_attribute!!!
286      * ----------------
287      */
288     if (nailme)
289         rdesc->rd_isnailed = true;
290     
291     RelationSetReferenceCount(rdesc, 1);
292     
293     rdesc->rd_rel = (Form_pg_class)palloc(sizeof *rdesc->rd_rel);
294     
295     memset((char *)rdesc->rd_rel, 0,
296            sizeof *rdesc->rd_rel);
297     namestrcpy(&(rdesc->rd_rel->relname), relname); 
298     rdesc->rd_rel->relkind = RELKIND_UNCATALOGED;
299     rdesc->rd_rel->relnatts = natts;
300     rdesc->rd_rel->relsmgr = smgr;
301     
302     for (i = 0; i < natts; i++) {
303         rdesc->rd_att->attrs[i]->attrelid = relid;
304     }
305     
306     rdesc->rd_id = relid;
307     
308      if (nailme) {
309         /* for system relations, set the reltype field here */
310         rdesc->rd_rel->reltype = relid;
311      }
312
313     /* ----------------
314      *  remember if this is a temp relation
315      * ----------------
316      */
317
318     rdesc->rd_istemp = isTemp;
319
320     /* ----------------
321      *  have the storage manager create the relation.
322      * ----------------
323      */
324     
325     rdesc->rd_fd = (File)smgrcreate(smgr, rdesc);
326     
327     RelationRegisterRelation(rdesc);
328     
329     MemoryContextSwitchTo(oldcxt);
330     
331     /* add all temporary relations to the tempRels list
332        so they can be properly disposed of at the end of transaction
333     */
334     if (isTemp)
335         AddToTempRelList(rdesc);
336
337     return (rdesc);
338 }
339
340
341 /* ----------------------------------------------------------------
342  *      heap_create     - Create a cataloged relation
343  *
344  *      this is done in 6 steps:
345  *
346  *      1) CheckAttributeNames() is used to make certain the tuple
347  *         descriptor contains a valid set of attribute names
348  *
349  *      2) pg_class is opened and RelationAlreadyExists()
350  *         preforms a scan to ensure that no relation with the
351  *         same name already exists.
352  *
353  *      3) heap_creater() is called to create the new relation on
354  *         disk.
355  *
356  *      4) TypeDefine() is called to define a new type corresponding
357  *         to the new relation.
358  *
359  *      5) AddNewAttributeTuples() is called to register the
360  *         new relation's schema in pg_attribute.
361  *
362  *      6) AddPgRelationTuple() is called to register the
363  *         relation itself in the catalogs.
364  *
365  *      7) 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 attnvals 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_creater().  Either it should
385  *      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(WARN) 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         for (j = 0; j < sizeof HeapAtt / sizeof HeapAtt[0]; j += 1) {
422             if (nameeq(&(HeapAtt[j]->attname),
423                             &(tupdesc->attrs[i]->attname))) {
424                 elog(WARN,
425                      "create: system attribute named \"%s\"",
426                      HeapAtt[j]->attname.data);
427             }
428         }
429         if (tupdesc->attrs[i]->atttypid == UNKNOWNOID)
430             {
431                 elog(NOTICE,
432                      "create: attribute named \"%s\" has an unknown type",
433                       tupdesc->attrs[i]->attname.data);
434             }
435     }
436     
437     /* ----------------
438      *  next check for repeated attribute names
439      * ----------------
440      */
441     for (i = 1; i < natts; i += 1) {
442         for (j = 0; j < i; j += 1) {
443             if (nameeq(&(tupdesc->attrs[j]->attname),
444                             &(tupdesc->attrs[i]->attname))) {
445                 elog(WARN,
446                      "create: repeated attribute \"%s\"",
447                      tupdesc->attrs[j]->attname.data);
448             }
449         }
450     }
451 }
452
453 /* --------------------------------
454  *      RelationAlreadyExists
455  *
456  *      this preforms a scan of pg_class to ensure that
457  *      no relation with the same name already exists.  The caller
458  *      has to open pg_class and pass an open descriptor.
459  * --------------------------------
460  */
461 int
462 RelationAlreadyExists(Relation pg_class_desc, char relname[])
463 {
464     ScanKeyData         key;
465     HeapScanDesc        pg_class_scan;
466     HeapTuple           tup;
467     
468     /*
469      *  If this is not bootstrap (initdb) time, use the catalog index
470      *  on pg_class.
471      */
472     
473     if (!IsBootstrapProcessingMode()) {
474         tup = ClassNameIndexScan(pg_class_desc, relname);
475         if (HeapTupleIsValid(tup)) {
476             pfree(tup);
477             return ((int) true);
478         } else
479             return ((int) false);
480     }
481     
482     /* ----------------
483      *  At bootstrap time, we have to do this the hard way.  Form the
484      *  scan key.
485      * ----------------
486      */
487     ScanKeyEntryInitialize(&key,
488                            0,
489                            (AttrNumber)Anum_pg_class_relname,
490                            (RegProcedure)NameEqualRegProcedure,
491                            (Datum) relname);
492     
493     /* ----------------
494      *  begin the scan
495      * ----------------
496      */
497     pg_class_scan = heap_beginscan(pg_class_desc,
498                                       0,
499                                       NowTimeQual,
500                                       1,
501                                       &key);
502     
503     /* ----------------
504      *  get a tuple.  if the tuple is NULL then it means we
505      *  didn't find an existing relation.
506      * ----------------
507      */
508     tup = heap_getnext(pg_class_scan, 0, (Buffer *)NULL);
509     
510     /* ----------------
511      *  end the scan and return existance of relation.
512      * ----------------
513      */
514     heap_endscan(pg_class_scan);
515     
516     return
517         (PointerIsValid(tup) == true);
518 }
519
520 /* --------------------------------
521  *      AddNewAttributeTuples
522  *
523  *      this registers the new relation's schema by adding
524  *      tuples to pg_attribute.
525  * --------------------------------
526  */
527 static void
528 AddNewAttributeTuples(Oid new_rel_oid,
529                       TupleDesc tupdesc)
530 {
531     AttributeTupleForm *dpp;            
532     unsigned    i;
533     HeapTuple   tup;
534     Relation    rdesc;
535     bool        hasindex;
536     Relation    idescs[Num_pg_attr_indices];
537     int natts = tupdesc->natts;
538     
539     /* ----------------
540      *  open pg_attribute
541      * ----------------
542      */
543     rdesc = heap_openr(AttributeRelationName);
544     
545     /* -----------------
546      * Check if we have any indices defined on pg_attribute.
547      * -----------------
548      */
549     Assert(rdesc);
550     Assert(rdesc->rd_rel);
551     hasindex = RelationGetRelationTupleForm(rdesc)->relhasindex;
552     if (hasindex)
553         CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
554     
555     /* ----------------
556      *  initialize tuple descriptor.  Note we use setheapoverride()
557      *  so that we can see the effects of our TypeDefine() done
558      *  previously.
559      * ----------------
560      */
561     setheapoverride(true);
562     fillatt(tupdesc);
563     setheapoverride(false);
564     
565     /* ----------------
566      *  first we add the user attributes..
567      * ----------------
568      */
569     dpp = tupdesc->attrs;
570     for (i = 0; i < natts; i++) {
571         (*dpp)->attrelid = new_rel_oid;
572         (*dpp)->attnvals = 0l;
573         
574         tup = heap_addheader(Natts_pg_attribute,
575                              ATTRIBUTE_TUPLE_SIZE,
576                              (char *) *dpp);
577         
578         heap_insert(rdesc, tup);
579         
580         if (hasindex)
581             CatalogIndexInsert(idescs, Num_pg_attr_indices, rdesc, tup);
582         
583         pfree(tup);
584         dpp++;
585     }
586     
587     /* ----------------
588      *  next we add the system attributes..
589      * ----------------
590      */
591     dpp = HeapAtt;
592     for (i = 0; i < -1 - FirstLowInvalidHeapAttributeNumber; i++) {
593         (*dpp)->attrelid = new_rel_oid;
594         /*      (*dpp)->attnvals = 0l;  unneeded */
595         
596         tup = heap_addheader(Natts_pg_attribute,
597                              ATTRIBUTE_TUPLE_SIZE,
598                              (char *)*dpp);
599         
600         heap_insert(rdesc, tup);
601         
602         if (hasindex)
603             CatalogIndexInsert(idescs, Num_pg_attr_indices, rdesc, tup);
604         
605         pfree(tup);
606         dpp++;
607     }
608     
609     heap_close(rdesc);
610
611     /*
612      * close pg_attribute indices
613      */
614     if (hasindex)
615         CatalogCloseIndices(Num_pg_attr_indices, idescs);
616 }
617
618 /* --------------------------------
619  *      AddPgRelationTuple
620  *
621  *      this registers the new relation in the catalogs by
622  *      adding a tuple to pg_class.
623  * --------------------------------
624  */
625 void
626 AddPgRelationTuple(Relation pg_class_desc,
627                    Relation new_rel_desc,
628                    Oid new_rel_oid,
629                    int arch,
630                    unsigned natts)
631 {
632     Form_pg_class       new_rel_reltup;
633     HeapTuple           tup;
634     Relation            idescs[Num_pg_class_indices];
635     bool                isBootstrap;
636     
637     /* ----------------
638      *  first we munge some of the information in our
639      *  uncataloged relation's relation descriptor.
640      * ----------------
641      */
642     new_rel_reltup = new_rel_desc->rd_rel;
643     
644     /* CHECK should get new_rel_oid first via an insert then use XXX */
645     /*   new_rel_reltup->reltuples = 1; */ /* XXX */
646     
647     new_rel_reltup->relowner = GetUserId();
648     new_rel_reltup->relkind = RELKIND_RELATION;
649     new_rel_reltup->relarch = arch;
650     new_rel_reltup->relnatts = natts;
651     
652     /* ----------------
653      *  now form a tuple to add to pg_class
654      *  XXX Natts_pg_class_fixed is a hack - see pg_class.h
655      * ----------------
656      */
657     tup = heap_addheader(Natts_pg_class_fixed,
658                          CLASS_TUPLE_SIZE,
659                          (char *) new_rel_reltup);
660     tup->t_oid = new_rel_oid;
661     
662     /* ----------------
663      *  finally insert the new tuple and free it.
664      *
665      *  Note: I have no idea why we do a
666      *          SetProcessingMode(BootstrapProcessing);
667      *        here -cim 6/14/90
668      * ----------------
669      */
670     isBootstrap = IsBootstrapProcessingMode() ? true : false;
671     
672     SetProcessingMode(BootstrapProcessing);
673     
674     heap_insert(pg_class_desc, tup);
675     
676     if (! isBootstrap) {
677         /*
678          *  First, open the catalog indices and insert index tuples for
679          *  the new relation.
680          */
681         
682         CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
683         CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class_desc, tup);
684         CatalogCloseIndices(Num_pg_class_indices, idescs);
685         
686         /* now restore processing mode */
687         SetProcessingMode(NormalProcessing);
688     }
689     
690     pfree(tup);
691 }
692
693
694 /* --------------------------------
695  *      addNewRelationType -
696  *
697  *      define a complex type corresponding to the new relation
698  * --------------------------------
699  */
700 void
701 addNewRelationType(char *typeName, Oid new_rel_oid)
702 {
703     Oid                 new_type_oid;
704
705     /* The sizes are set to oid size because it makes implementing sets MUCH
706      * easier, and no one (we hope) uses these fields to figure out
707      * how much space to allocate for the type. 
708      * An oid is the type used for a set definition.  When a user
709      * requests a set, what they actually get is the oid of a tuple in
710      * the pg_proc catalog, so the size of the "set" is the size
711      * of an oid.
712      * Similarly, byval being true makes sets much easier, and 
713      * it isn't used by anything else.
714      * Note the assumption that OIDs are the same size as int4s.
715      */
716     new_type_oid = TypeCreate(typeName,                 /* type name */
717                               new_rel_oid,              /* relation oid */
718                               tlen(type("oid")),        /* internal size */
719                               tlen(type("oid")),        /* external size */
720                               'c',              /* type-type (catalog) */
721                               ',',              /* default array delimiter */
722                               "int4in", /* input procedure */
723                               "int4out",        /* output procedure */
724                               "int4in",  /* send procedure */
725                               "int4out",        /* receive procedure */
726                               NULL,     /* array element type - irrelevent */
727                               "-",              /* default type value */
728                               (bool) 1, /* passed by value */
729                               'i');     /* default alignment */
730 }
731
732 /* --------------------------------
733  *      heap_create     
734  *
735  *      creates a new cataloged relation.  see comments above.
736  * --------------------------------
737  */
738 Oid
739 heap_create(char relname[],
740             char *typename, /* not used currently */
741             int arch,
742             unsigned smgr,
743             TupleDesc tupdesc)
744 {
745     Relation            pg_class_desc;
746     Relation            new_rel_desc;
747     Oid                 new_rel_oid;
748 /*    NameData            typeNameData; */
749     int natts = tupdesc->natts;
750
751     /* ----------------
752      *  sanity checks
753      * ----------------
754      */
755     AssertState(IsNormalProcessingMode() || IsBootstrapProcessingMode());
756     if (natts == 0 || natts > MaxHeapAttributeNumber)
757         elog(WARN, "amcreate: from 1 to %d attributes must be specified",
758              MaxHeapAttributeNumber);
759     
760     CheckAttributeNames(tupdesc);
761     
762     /* ----------------
763      *  open pg_class and see that the relation doesn't
764      *  already exist.
765      * ----------------
766      */
767     pg_class_desc = heap_openr(RelationRelationName);
768     
769     if (RelationAlreadyExists(pg_class_desc, relname)) {
770         heap_close(pg_class_desc);
771         elog(WARN, "amcreate: %s relation already exists", relname);
772     }
773     
774     /* ----------------
775      *  ok, relation does not already exist so now we
776      *  create an uncataloged relation and pull its relation oid
777      *  from the newly formed relation descriptor.
778      *
779      *  Note: The call to heap_creatr() does all the "real" work
780      *  of creating the disk file for the relation.
781      * ----------------
782      */
783     new_rel_desc = heap_creatr(relname, smgr, tupdesc);
784     new_rel_oid  = new_rel_desc->rd_att->attrs[0]->attrelid;
785     
786     /* ----------------
787      *  since defining a relation also defines a complex type,
788      *  we add a new system type corresponding to the new relation.
789      * ----------------
790      */
791 /*    namestrcpy(&typeNameData, relname);*/
792 /*    addNewRelationType(&typeNameData, new_rel_oid);*/
793     addNewRelationType(relname, new_rel_oid);
794
795     /* ----------------
796      *  now add tuples to pg_attribute for the attributes in
797      *  our new relation.
798      * ----------------
799      */
800     AddNewAttributeTuples(new_rel_oid, tupdesc);
801     
802     /* ----------------
803      *  now update the information in pg_class.
804      * ----------------
805      */
806     AddPgRelationTuple(pg_class_desc,
807                        new_rel_desc,
808                        new_rel_oid,
809                        arch,
810                        natts);
811     
812     /* ----------------
813      *  ok, the relation has been cataloged, so close our relations
814      *  and return the oid of the newly created relation.
815      *
816      *  SOMEDAY: fill the STATISTIC relation properly.
817      * ----------------
818      */
819     heap_close(new_rel_desc);
820     heap_close(pg_class_desc);
821     
822     return new_rel_oid;
823 }
824
825
826 /* ----------------------------------------------------------------
827  *      heap_destroy    - removes all record of named relation from catalogs
828  *
829  *      1)  open relation, check for existence, etc.
830  *      2)  remove inheritance information
831  *      3)  remove indexes
832  *      4)  remove pg_class tuple
833  *      5)  remove pg_attribute tuples
834  *      6)  remove pg_type tuples
835  *      7)  unlink relation
836  *
837  * old comments
838  *      Except for vital relations, removes relation from
839  *      relation catalog, and related attributes from
840  *      attribute catalog (needed?).  (Anything else???)
841  *
842  *      get proper relation from relation catalog (if not arg)
843  *      check if relation is vital (strcmp()/reltype???)
844  *      scan attribute catalog deleting attributes of reldesc
845  *              (necessary?)
846  *      delete relation from relation catalog
847  *      (How are the tuples of the relation discarded???)
848  *
849  *      XXX Must fix to work with indexes.
850  *      There may be a better order for doing things.
851  *      Problems with destroying a deleted database--cannot create
852  *      a struct reldesc without having an open file descriptor.
853  * ----------------------------------------------------------------
854  */
855
856 /* --------------------------------
857  *      RelationRemoveInheritance
858  *
859  *      Note: for now, we cause an exception if relation is a
860  *      superclass.  Someday, we may want to allow this and merge
861  *      the type info into subclass procedures....  this seems like
862  *      lots of work.
863  * --------------------------------
864  */
865 void
866 RelationRemoveInheritance(Relation relation)
867 {
868     Relation            catalogRelation;
869     HeapTuple           tuple;
870     HeapScanDesc        scan;
871     ScanKeyData         entry;
872     
873     /* ----------------
874      *  open pg_inherits
875      * ----------------
876      */
877     catalogRelation = heap_openr(InheritsRelationName);
878     
879     /* ----------------
880      *  form a scan key for the subclasses of this class
881      *  and begin scanning
882      * ----------------
883      */
884     ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_inherits_inhparent,
885                            ObjectIdEqualRegProcedure,
886                            ObjectIdGetDatum(RelationGetRelationId(relation)));
887     
888     scan = heap_beginscan(catalogRelation,
889                           false,
890                           NowTimeQual,
891                           1,
892                           &entry);
893     
894     /* ----------------
895      *  if any subclasses exist, then we disallow the deletion.
896      * ----------------
897      */
898     tuple = heap_getnext(scan, 0, (Buffer *)NULL);
899     if (HeapTupleIsValid(tuple)) {
900         heap_endscan(scan);
901         heap_close(catalogRelation);
902         
903         elog(WARN, "relation <%d> inherits \"%s\"",
904              ((InheritsTupleForm) GETSTRUCT(tuple))->inhrel,
905              RelationGetRelationName(relation));
906     }
907     
908     /* ----------------
909      *  If we get here, it means the relation has no subclasses
910      *  so we can trash it.  First we remove dead INHERITS tuples.
911      * ----------------
912      */
913     entry.sk_attno = Anum_pg_inherits_inhrel;
914     
915     scan = heap_beginscan(catalogRelation,
916                           false,
917                           NowTimeQual,
918                           1,
919                           &entry);
920     
921     for (;;) {
922         tuple = heap_getnext(scan, 0, (Buffer *)NULL);
923         if (!HeapTupleIsValid(tuple)) {
924             break;
925         }
926         heap_delete(catalogRelation, &tuple->t_ctid);
927     }
928     
929     heap_endscan(scan);
930     heap_close(catalogRelation);
931     
932     /* ----------------
933      *  now remove dead IPL tuples
934      * ----------------
935      */
936     catalogRelation =
937         heap_openr(InheritancePrecidenceListRelationName);
938     
939     entry.sk_attno = Anum_pg_ipl_iplrel;
940     
941     scan = heap_beginscan(catalogRelation,
942                           false,
943                           NowTimeQual,
944                           1,
945                           &entry);
946     
947     for (;;) {
948         tuple = heap_getnext(scan, 0, (Buffer *)NULL);
949         if (!HeapTupleIsValid(tuple)) {
950             break;
951         }
952         heap_delete(catalogRelation, &tuple->t_ctid);
953     }
954     
955     heap_endscan(scan);
956     heap_close(catalogRelation);
957 }
958
959 /* --------------------------------
960  *      RelationRemoveIndexes
961  *      
962  * --------------------------------
963  */
964 void
965 RelationRemoveIndexes(Relation relation)
966 {
967     Relation            indexRelation;
968     HeapTuple           tuple;
969     HeapScanDesc        scan;
970     ScanKeyData         entry;
971     
972     indexRelation = heap_openr(IndexRelationName);
973     
974     ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_index_indrelid,
975                            ObjectIdEqualRegProcedure,
976                            ObjectIdGetDatum(RelationGetRelationId(relation)));
977     
978     scan = heap_beginscan(indexRelation,
979                           false,
980                           NowTimeQual,
981                           1,
982                           &entry);
983     
984     for (;;) {
985         tuple = heap_getnext(scan, 0, (Buffer *)NULL);
986         if (!HeapTupleIsValid(tuple)) {
987             break;
988         }
989         
990         index_destroy(((IndexTupleForm)GETSTRUCT(tuple))->indexrelid);
991     }
992     
993     heap_endscan(scan);
994     heap_close(indexRelation);
995 }
996
997 /* --------------------------------
998  *      DeletePgRelationTuple
999  *
1000  * --------------------------------
1001  */
1002 void
1003 DeletePgRelationTuple(Relation rdesc)
1004 {
1005     Relation            pg_class_desc;
1006     HeapScanDesc        pg_class_scan;
1007     ScanKeyData         key;
1008     HeapTuple           tup;
1009     
1010     /* ----------------
1011      *  open pg_class
1012      * ----------------
1013      */
1014     pg_class_desc = heap_openr(RelationRelationName);
1015     
1016     /* ----------------
1017      *  create a scan key to locate the relation oid of the
1018      *  relation to delete
1019      * ----------------
1020      */
1021     ScanKeyEntryInitialize(&key, 0, ObjectIdAttributeNumber,
1022                            F_INT4EQ, rdesc->rd_att->attrs[0]->attrelid);
1023     
1024     pg_class_scan =  heap_beginscan(pg_class_desc,
1025                                     0,
1026                                     NowTimeQual,
1027                                     1,
1028                                     &key);
1029     
1030     /* ----------------
1031      *  use heap_getnext() to fetch the pg_class tuple.  If this
1032      *  tuple is not valid then something's wrong.
1033      * ----------------
1034      */
1035     tup = heap_getnext(pg_class_scan, 0, (Buffer *) NULL);
1036     
1037     if (! PointerIsValid(tup)) {
1038         heap_endscan(pg_class_scan);
1039         heap_close(pg_class_desc);
1040         elog(WARN, "DeletePgRelationTuple: %s relation nonexistent",
1041              &rdesc->rd_rel->relname);
1042     }
1043     
1044     /* ----------------
1045      *  delete the relation tuple from pg_class, and finish up.
1046      * ----------------
1047      */
1048     heap_endscan(pg_class_scan);
1049     heap_delete(pg_class_desc, &tup->t_ctid);
1050     
1051     heap_close(pg_class_desc);
1052 }
1053
1054 /* --------------------------------
1055  *      DeletePgAttributeTuples
1056  *
1057  * --------------------------------
1058  */
1059 void
1060 DeletePgAttributeTuples(Relation rdesc)
1061 {
1062     Relation            pg_attribute_desc;
1063     HeapScanDesc        pg_attribute_scan;
1064     ScanKeyData         key;
1065     HeapTuple           tup;
1066     
1067     /* ----------------
1068      *  open pg_attribute
1069      * ----------------
1070      */
1071     pg_attribute_desc = heap_openr(AttributeRelationName);
1072     
1073     /* ----------------
1074      *  create a scan key to locate the attribute tuples to delete
1075      *  and begin the scan.
1076      * ----------------
1077      */
1078     ScanKeyEntryInitialize(&key, 0, Anum_pg_attribute_attrelid,
1079                            F_INT4EQ, rdesc->rd_att->attrs[0]->attrelid);
1080     
1081     /* -----------------
1082      * Get a write lock _before_ getting the read lock in the scan
1083      * ----------------
1084      */
1085     RelationSetLockForWrite(pg_attribute_desc);
1086     
1087     pg_attribute_scan = heap_beginscan(pg_attribute_desc,
1088                                        0,
1089                                        NowTimeQual,
1090                                        1,
1091                                        &key);
1092     
1093     /* ----------------
1094      *  use heap_getnext() / amdelete() until all attribute tuples
1095      *  have been deleted.
1096      * ----------------
1097      */
1098     while (tup = heap_getnext(pg_attribute_scan, 0, (Buffer *)NULL),
1099            PointerIsValid(tup)) {
1100         
1101         heap_delete(pg_attribute_desc, &tup->t_ctid);
1102     }
1103     
1104     /* ----------------
1105      *  finish up.
1106      * ----------------
1107      */
1108     heap_endscan(pg_attribute_scan);
1109     
1110     /* ----------------
1111      * Release the write lock 
1112      * ----------------
1113      */
1114     RelationUnsetLockForWrite(pg_attribute_desc);
1115     heap_close(pg_attribute_desc);
1116 }
1117
1118
1119 /* --------------------------------
1120  *      DeletePgTypeTuple
1121  *
1122  *      If the user attempts to destroy a relation and there
1123  *      exists attributes in other relations of type
1124  *      "relation we are deleting", then we have to do something
1125  *      special.  presently we disallow the destroy.
1126  * --------------------------------
1127  */
1128 void
1129 DeletePgTypeTuple(Relation rdesc)
1130 {
1131     Relation            pg_type_desc;
1132     HeapScanDesc        pg_type_scan;
1133     Relation            pg_attribute_desc;
1134     HeapScanDesc        pg_attribute_scan;
1135     ScanKeyData         key;
1136     ScanKeyData         attkey;
1137     HeapTuple           tup;
1138     HeapTuple           atttup;
1139     Oid         typoid;
1140     
1141     /* ----------------
1142      *  open pg_type
1143      * ----------------
1144      */
1145     pg_type_desc = heap_openr(TypeRelationName);
1146     
1147     /* ----------------
1148      *  create a scan key to locate the type tuple corresponding
1149      *  to this relation.
1150      * ----------------
1151      */
1152     ScanKeyEntryInitialize(&key, 0, Anum_pg_type_typrelid, F_INT4EQ,
1153                            rdesc->rd_att->attrs[0]->attrelid);
1154     
1155     pg_type_scan =  heap_beginscan(pg_type_desc,
1156                                    0,
1157                                    NowTimeQual,
1158                                    1,
1159                                    &key);
1160     
1161     /* ----------------
1162      *  use heap_getnext() to fetch the pg_type tuple.  If this
1163      *  tuple is not valid then something's wrong.
1164      * ----------------
1165      */
1166     tup = heap_getnext(pg_type_scan, 0, (Buffer *)NULL);
1167     
1168     if (! PointerIsValid(tup)) {
1169         heap_endscan(pg_type_scan);
1170         heap_close(pg_type_desc);
1171         elog(WARN, "DeletePgTypeTuple: %s type nonexistent",
1172              &rdesc->rd_rel->relname);
1173     }
1174     
1175     /* ----------------
1176      *  now scan pg_attribute.  if any other relations have
1177      *  attributes of the type of the relation we are deleteing
1178      *  then we have to disallow the deletion.  should talk to
1179      *  stonebraker about this.  -cim 6/19/90
1180      * ----------------
1181      */
1182     typoid = tup->t_oid;
1183     
1184     pg_attribute_desc = heap_openr(AttributeRelationName);
1185     
1186     ScanKeyEntryInitialize(&attkey,
1187                            0, Anum_pg_attribute_atttypid, F_INT4EQ,
1188                            typoid);
1189     
1190     pg_attribute_scan = heap_beginscan(pg_attribute_desc,
1191                                        0,
1192                                        NowTimeQual,
1193                                        1,
1194                                        &attkey);
1195     
1196     /* ----------------
1197      *  try and get a pg_attribute tuple.  if we succeed it means
1198      *  we cant delete the relation because something depends on
1199      *  the schema.
1200      * ----------------
1201      */
1202     atttup = heap_getnext(pg_attribute_scan, 0, (Buffer *)NULL);
1203     
1204     if (PointerIsValid(atttup)) {
1205         Oid relid = ((AttributeTupleForm) GETSTRUCT(atttup))->attrelid;
1206         
1207         heap_endscan(pg_type_scan);
1208         heap_close(pg_type_desc);
1209         heap_endscan(pg_attribute_scan);
1210         heap_close(pg_attribute_desc);
1211         
1212         elog(WARN, "DeletePgTypeTuple: att of type %s exists in relation %d",
1213              &rdesc->rd_rel->relname, relid);   
1214     }
1215     heap_endscan(pg_attribute_scan);
1216     heap_close(pg_attribute_desc);
1217     
1218     /* ----------------
1219      *  Ok, it's safe so we delete the relation tuple
1220      *  from pg_type and finish up.  But first end the scan so that
1221      *  we release the read lock on pg_type.  -mer 13 Aug 1991
1222      * ----------------
1223      */
1224     heap_endscan(pg_type_scan);
1225     heap_delete(pg_type_desc, &tup->t_ctid);
1226     
1227     heap_close(pg_type_desc);
1228 }
1229
1230 /* --------------------------------
1231  *      heap_destroy
1232  *
1233  * --------------------------------
1234  */
1235 void
1236 heap_destroy(char *relname)
1237 {
1238     Relation    rdesc;
1239     
1240     /* ----------------
1241      *  first open the relation.  if the relation does exist,
1242      *  heap_openr() returns NULL.
1243      * ----------------
1244      */
1245     rdesc = heap_openr(relname);
1246     if (rdesc == NULL)
1247         elog(WARN,"Relation %s Does Not Exist!", relname);
1248     
1249     /* ----------------
1250      *  prevent deletion of system relations
1251      * ----------------
1252      */
1253     if (IsSystemRelationName(RelationGetRelationName(rdesc)->data))
1254         elog(WARN, "amdestroy: cannot destroy %s relation",
1255              &rdesc->rd_rel->relname);
1256     
1257     /* ----------------
1258      *  remove inheritance information
1259      * ----------------
1260      */
1261     RelationRemoveInheritance(rdesc);
1262     
1263     /* ----------------
1264      *  remove indexes if necessary
1265      * ----------------
1266      */
1267     if (rdesc->rd_rel->relhasindex) {
1268         RelationRemoveIndexes(rdesc);
1269     }
1270
1271     /* ----------------
1272      *  remove rules if necessary
1273      * ----------------
1274      */
1275     if (rdesc->rd_rules != NULL) {
1276         RelationRemoveRules(rdesc->rd_id);
1277     }
1278     
1279     /* ----------------
1280      *  delete attribute tuples
1281      * ----------------
1282      */
1283     DeletePgAttributeTuples(rdesc);
1284     
1285     /* ----------------
1286      *  delete type tuple.  here we want to see the effects
1287      *  of the deletions we just did, so we use setheapoverride().
1288      * ----------------
1289      */
1290     setheapoverride(true);
1291     DeletePgTypeTuple(rdesc);
1292     setheapoverride(false);
1293     
1294     /* ----------------
1295      *  delete relation tuple
1296      * ----------------
1297      */
1298     DeletePgRelationTuple(rdesc);
1299     
1300     /* ----------------
1301      *  flush the relation from the relcache
1302      * ----------------
1303      */
1304     RelationIdInvalidateRelationCacheByRelationId(rdesc->rd_id);
1305
1306     /* ----------------
1307      *  unlink the relation and finish up.
1308      * ----------------
1309      */
1310     (void) smgrunlink(rdesc->rd_rel->relsmgr, rdesc);
1311     if(rdesc->rd_istemp) {
1312         rdesc->rd_tmpunlinked = TRUE;
1313     }
1314     heap_close(rdesc);
1315 }
1316
1317 /*
1318  * heap_destroyr
1319  *    destroy and close temporary relations
1320  *
1321  */
1322
1323 void 
1324 heap_destroyr(Relation rdesc)
1325 {
1326     ReleaseTmpRelBuffers(rdesc);
1327     (void) smgrunlink(rdesc->rd_rel->relsmgr, rdesc);
1328     if(rdesc->rd_istemp) {
1329         rdesc->rd_tmpunlinked = TRUE;
1330     }
1331     heap_close(rdesc);
1332     RemoveFromTempRelList(rdesc);
1333 }
1334
1335
1336 /**************************************************************
1337   functions to deal with the list of temporary relations 
1338 **************************************************************/
1339
1340 /* --------------
1341    InitTempRellist():
1342
1343    initialize temporary relations list
1344    the tempRelList is a list of temporary relations that
1345    are created in the course of the transactions
1346    they need to be destroyed properly at the end of the transactions
1347
1348    MODIFIES the global variable tempRels
1349
1350  >> NOTE <<
1351
1352    malloc is used instead of palloc because we KNOW when we are
1353    going to free these things.  Keeps us away from the memory context
1354    hairyness
1355
1356 */
1357 void
1358 InitTempRelList()
1359 {
1360     if (tempRels) {
1361         free(tempRels->rels);
1362         free(tempRels);
1363     };
1364
1365     tempRels = (TempRelList*)malloc(sizeof(TempRelList));
1366     tempRels->size = TEMP_REL_LIST_SIZE;
1367     tempRels->rels = (Relation*)malloc(sizeof(Relation) * tempRels->size);
1368     memset(tempRels->rels, 0, sizeof(Relation) * tempRels->size);
1369     tempRels->num = 0;
1370 }
1371
1372 /*
1373    removes a relation from the TempRelList
1374
1375    MODIFIES the global variable tempRels
1376       we don't really remove it, just mark it as NULL
1377       and DestroyTempRels will look for NULLs
1378 */
1379 void
1380 RemoveFromTempRelList(Relation r)
1381 {
1382     int i;
1383
1384     if (!tempRels)
1385         return;
1386
1387     for (i=0; i<tempRels->num; i++) {
1388         if (tempRels->rels[i] == r) {
1389             tempRels->rels[i] = NULL;
1390             break;
1391         }
1392     }
1393 }
1394
1395 /*
1396    add a temporary relation to the TempRelList
1397
1398    MODIFIES the global variable tempRels
1399 */
1400 void
1401 AddToTempRelList(Relation r)
1402 {
1403     if (!tempRels)
1404         return;
1405
1406     if (tempRels->num == tempRels->size) {
1407         tempRels->size += TEMP_REL_LIST_SIZE;
1408         tempRels->rels = realloc(tempRels->rels, tempRels->size);
1409     }
1410     tempRels->rels[tempRels->num] = r;
1411     tempRels->num++;
1412 }
1413
1414 /*
1415    go through the tempRels list and destroy each of the relations
1416 */
1417 void
1418 DestroyTempRels()
1419 {
1420     int i;
1421     Relation rdesc;
1422
1423     if (!tempRels)
1424         return;
1425
1426     for (i=0;i<tempRels->num;i++) {
1427         rdesc = tempRels->rels[i];
1428         /* rdesc may be NULL if it has been removed from the list already */
1429         if (rdesc)
1430             heap_destroyr(rdesc);
1431     }
1432     free(tempRels->rels);
1433     free(tempRels);
1434     tempRels = NULL;
1435 }
1436