]> granicus.if.org Git - postgresql/blob - src/backend/access/common/tupdesc.c
Remove tqual.h includes not needed.
[postgresql] / src / backend / access / common / tupdesc.c
1 /*-------------------------------------------------------------------------
2  *
3  * tupdesc.c--
4  *        POSTGRES tuple descriptor support code
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.28 1997/11/24 05:07:42 momjian Exp $
11  *
12  * NOTES
13  *        some of the executor utility code such as "ExecTypeFromTL" should be
14  *        moved here.
15  *
16  *-------------------------------------------------------------------------
17  */
18
19 #include <stdio.h>
20
21 #include <postgres.h>
22
23 #include <parser/catalog_utils.h>
24 #include <nodes/parsenodes.h>
25 #include <utils/builtins.h>
26 #include <utils/fcache.h>
27 #include <utils/syscache.h>
28
29 #ifndef HAVE_MEMMOVE
30 #include <regex/utils.h>
31 #else
32 #include <string.h>
33 #endif
34
35 /* ----------------------------------------------------------------
36  *              CreateTemplateTupleDesc
37  *
38  *              This function allocates and zeros a tuple descriptor structure.
39  * ----------------------------------------------------------------
40  */
41 TupleDesc
42 CreateTemplateTupleDesc(int natts)
43 {
44         uint32          size;
45         TupleDesc       desc;
46
47         /* ----------------
48          *      sanity checks
49          * ----------------
50          */
51         AssertArg(natts >= 1);
52
53         /* ----------------
54          *      allocate enough memory for the tuple descriptor and
55          *      zero it as TupleDescInitEntry assumes that the descriptor
56          *      is filled with NULL pointers.
57          * ----------------
58          */
59         size = natts * sizeof(AttributeTupleForm);
60         desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
61         desc->attrs = (AttributeTupleForm *) palloc(size);
62         desc->constr = NULL;
63         MemSet(desc->attrs, 0, size);
64
65         desc->natts = natts;
66
67         return (desc);
68 }
69
70 /* ----------------------------------------------------------------
71  *              CreateTupleDesc
72  *
73  *              This function allocates a new TupleDesc from AttributeTupleForm array
74  * ----------------------------------------------------------------
75  */
76 TupleDesc
77 CreateTupleDesc(int natts, AttributeTupleForm *attrs)
78 {
79         TupleDesc       desc;
80
81         /* ----------------
82          *      sanity checks
83          * ----------------
84          */
85         AssertArg(natts >= 1);
86
87         desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
88         desc->attrs = attrs;
89         desc->natts = natts;
90         desc->constr = NULL;
91
92         return (desc);
93 }
94
95 /* ----------------------------------------------------------------
96  *              CreateTupleDescCopy
97  *
98  *              This function creates a new TupleDesc by copying from an existing
99  *              TupleDesc
100  *
101  *              !!! Constraints are not copied !!!
102  * ----------------------------------------------------------------
103  */
104 TupleDesc
105 CreateTupleDescCopy(TupleDesc tupdesc)
106 {
107         TupleDesc       desc;
108         int                     i,
109                                 size;
110
111         desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
112         desc->natts = tupdesc->natts;
113         size = desc->natts * sizeof(AttributeTupleForm);
114         desc->attrs = (AttributeTupleForm *) palloc(size);
115         for (i = 0; i < desc->natts; i++)
116         {
117                 desc->attrs[i] =
118                         (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE);
119                 memmove(desc->attrs[i],
120                                 tupdesc->attrs[i],
121                                 ATTRIBUTE_TUPLE_SIZE);
122                 desc->attrs[i]->attnotnull = false;
123                 desc->attrs[i]->atthasdef = false;
124         }
125         desc->constr = NULL;
126
127         return desc;
128 }
129
130 /* ----------------------------------------------------------------
131  *              CreateTupleDescCopyConstr
132  *
133  *              This function creates a new TupleDesc by copying from an existing
134  *              TupleDesc (with Constraints)
135  *
136  * ----------------------------------------------------------------
137  */
138 TupleDesc
139 CreateTupleDescCopyConstr(TupleDesc tupdesc)
140 {
141         TupleDesc       desc;
142         TupleConstr *constr = tupdesc->constr;
143         int                     i,
144                                 size;
145
146         desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
147         desc->natts = tupdesc->natts;
148         size = desc->natts * sizeof(AttributeTupleForm);
149         desc->attrs = (AttributeTupleForm *) palloc(size);
150         for (i = 0; i < desc->natts; i++)
151         {
152                 desc->attrs[i] =
153                         (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE);
154                 memmove(desc->attrs[i],
155                                 tupdesc->attrs[i],
156                                 ATTRIBUTE_TUPLE_SIZE);
157         }
158         if (constr)
159         {
160                 TupleConstr *cpy = (TupleConstr *) palloc(sizeof(TupleConstr));
161
162                 cpy->has_not_null = constr->has_not_null;
163
164                 if ((cpy->num_defval = constr->num_defval) > 0)
165                 {
166                         cpy->defval = (AttrDefault *) palloc(cpy->num_defval * sizeof(AttrDefault));
167                         memcpy(cpy->defval, constr->defval, cpy->num_defval * sizeof(AttrDefault));
168                         for (i = cpy->num_defval - 1; i >= 0; i--)
169                         {
170                                 if (constr->defval[i].adbin)
171                                         cpy->defval[i].adbin = pstrdup(constr->defval[i].adbin);
172                                 if (constr->defval[i].adsrc)
173                                         cpy->defval[i].adsrc = pstrdup(constr->defval[i].adsrc);
174                         }
175                 }
176
177                 if ((cpy->num_check = constr->num_check) > 0)
178                 {
179                         cpy->check = (ConstrCheck *) palloc(cpy->num_check * sizeof(ConstrCheck));
180                         memcpy(cpy->check, constr->check, cpy->num_check * sizeof(ConstrCheck));
181                         for (i = cpy->num_check - 1; i >= 0; i--)
182                         {
183                                 if (constr->check[i].ccname)
184                                         cpy->check[i].ccname = pstrdup(constr->check[i].ccname);
185                                 if (constr->check[i].ccbin)
186                                         cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin);
187                                 if (constr->check[i].ccsrc)
188                                         cpy->check[i].ccsrc = pstrdup(constr->check[i].ccsrc);
189                         }
190                 }
191
192                 desc->constr = cpy;
193         }
194         else
195                 desc->constr = NULL;
196
197         return desc;
198 }
199
200 void
201 FreeTupleDesc(TupleDesc tupdesc)
202 {
203         int                     i;
204
205         for (i = 0; i < tupdesc->natts; i++)
206                 pfree(tupdesc->attrs[i]);
207         pfree(tupdesc->attrs);
208         if (tupdesc->constr)
209         {
210                 if (tupdesc->constr->num_defval > 0)
211                 {
212                         AttrDefault *attrdef = tupdesc->constr->defval;
213
214                         for (i = tupdesc->constr->num_defval - 1; i >= 0; i--)
215                         {
216                                 if (attrdef[i].adbin)
217                                         pfree(attrdef[i].adbin);
218                                 if (attrdef[i].adsrc)
219                                         pfree(attrdef[i].adsrc);
220                         }
221                         pfree(attrdef);
222                 }
223                 if (tupdesc->constr->num_check > 0)
224                 {
225                         ConstrCheck *check = tupdesc->constr->check;
226
227                         for (i = tupdesc->constr->num_check - 1; i >= 0; i--)
228                         {
229                                 if (check[i].ccname)
230                                         pfree(check[i].ccname);
231                                 if (check[i].ccbin)
232                                         pfree(check[i].ccbin);
233                                 if (check[i].ccsrc)
234                                         pfree(check[i].ccsrc);
235                         }
236                         pfree(check);
237                 }
238                 pfree(tupdesc->constr);
239         }
240
241         pfree(tupdesc);
242
243 }
244
245 /* ----------------------------------------------------------------
246  *              TupleDescInitEntry
247  *
248  *              This function initializes a single attribute structure in
249  *              a preallocated tuple descriptor.
250  * ----------------------------------------------------------------
251  */
252 bool
253 TupleDescInitEntry(TupleDesc desc,
254                                    AttrNumber attributeNumber,
255                                    char *attributeName,
256                                    char *typeName,
257                                    int attdim,
258                                    bool attisset)
259 {
260         HeapTuple       tuple;
261         TypeTupleForm typeForm;
262         AttributeTupleForm att;
263
264         /* ----------------
265          *      sanity checks
266          * ----------------
267          */
268         AssertArg(PointerIsValid(desc));
269         AssertArg(attributeNumber >= 1);
270
271         /*
272          * attributeName's are sometimes NULL, from resdom's.  I don't know
273          * why that is, though -- Jolly
274          */
275 /*        AssertArg(NameIsValid(attributeName));*/
276 /*        AssertArg(NameIsValid(typeName));*/
277
278         AssertArg(!PointerIsValid(desc->attrs[attributeNumber - 1]));
279
280
281         /* ----------------
282          *      allocate storage for this attribute
283          * ----------------
284          */
285
286         att = (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE);
287         desc->attrs[attributeNumber - 1] = att;
288
289         /* ----------------
290          *      initialize some of the attribute fields
291          * ----------------
292          */
293         att->attrelid = 0;                      /* dummy value */
294
295         if (attributeName != NULL)
296                 namestrcpy(&(att->attname), attributeName);
297         else
298                 MemSet(att->attname.data, 0, NAMEDATALEN);
299
300
301         att->attdisbursion = 0;         /* dummy value */
302         att->attcacheoff = -1;
303
304         att->attnum = attributeNumber;
305         att->attnelems = attdim;
306         att->attisset = attisset;
307
308         att->attnotnull = false;
309         att->atthasdef = false;
310
311         /* ----------------
312          *      search the system cache for the type tuple of the attribute
313          *      we are creating so that we can get the typeid and some other
314          *      stuff.
315          *
316          *      Note: in the special case of
317          *
318          *              create EMP (name = char16, manager = EMP)
319          *
320          *      RelationNameCreateHeapRelation() calls BuildDesc() which
321          *      calls this routine and since EMP does not exist yet, the
322          *      system cache lookup below fails.  That's fine, but rather
323          *      then doing a elog(WARN) we just leave that information
324          *      uninitialized, return false, then fix things up later.
325          *      -cim 6/14/90
326          * ----------------
327          */
328         tuple = SearchSysCacheTuple(TYPNAME, PointerGetDatum(typeName),
329                                                                 0, 0, 0);
330         if (!HeapTupleIsValid(tuple))
331         {
332                 /* ----------------
333                  *       here type info does not exist yet so we just fill
334                  *       the attribute with dummy information and return false.
335                  * ----------------
336                  */
337                 att->atttypid = InvalidOid;
338                 att->attlen = (int16) 0;
339                 att->attbyval = (bool) 0;
340                 att->attalign = 'i';
341                 return false;
342         }
343
344         /* ----------------
345          *      type info exists so we initialize our attribute
346          *      information from the type tuple we found..
347          * ----------------
348          */
349         typeForm = (TypeTupleForm) GETSTRUCT(tuple);
350
351         att->atttypid = tuple->t_oid;
352         att->attalign = typeForm->typalign;
353
354         /* ------------------------
355            If this attribute is a set, what is really stored in the
356            attribute is the OID of a tuple in the pg_proc catalog.
357            The pg_proc tuple contains the query string which defines
358            this set - i.e., the query to run to get the set.
359            So the atttypid (just assigned above) refers to the type returned
360            by this query, but the actual length of this attribute is the
361            length (size) of an OID.
362
363            Why not just make the atttypid point to the OID type, instead
364            of the type the query returns?  Because the executor uses the atttypid
365            to tell the front end what type will be returned (in BeginCommand),
366            and in the end the type returned will be the result of the query, not
367            an OID.
368
369            Why not wait until the return type of the set is known (i.e., the
370            recursive call to the executor to execute the set has returned)
371            before telling the front end what the return type will be?  Because
372            the executor is a delicate thing, and making sure that the correct
373            order of front-end commands is maintained is messy, especially
374            considering that target lists may change as inherited attributes
375            are considered, etc.  Ugh.
376            -----------------------------------------
377            */
378         if (attisset)
379         {
380                 Type            t = type("oid");
381
382                 att->attlen = tlen(t);
383                 att->attbyval = tbyval(t);
384         }
385         else
386         {
387                 att->attlen = typeForm->typlen;
388                 att->attbyval = typeForm->typbyval;
389         }
390
391
392         return true;
393 }
394
395
396 /* ----------------------------------------------------------------
397  *              TupleDescMakeSelfReference
398  *
399  *              This function initializes a "self-referential" attribute like
400  *              manager in "create EMP (name=text, manager = EMP)".
401  *              It calls TypeShellMake() which inserts a "shell" type
402  *              tuple into pg_type.  A self-reference is one kind of set, so
403  *              its size and byval are the same as for a set.  See the comments
404  *              above in TupleDescInitEntry.
405  * ----------------------------------------------------------------
406  */
407 static void
408 TupleDescMakeSelfReference(TupleDesc desc,
409                                                    AttrNumber attnum,
410                                                    char *relname)
411 {
412         AttributeTupleForm att;
413         Type            t = type("oid");
414
415         att = desc->attrs[attnum - 1];
416         att->atttypid = TypeShellMake(relname);
417         att->attlen = tlen(t);
418         att->attbyval = tbyval(t);
419         att->attnelems = 0;
420 }
421
422 /* ----------------------------------------------------------------
423  *              BuildDescForRelation
424  *
425  *              This is a general purpose function identical to BuildDesc
426  *              but is used by the DefineRelation() code to catch the
427  *              special case where you
428  *
429  *                              create FOO ( ..., x = FOO )
430  *
431  *              here, the initial type lookup for "x = FOO" will fail
432  *              because FOO isn't in the catalogs yet.  But since we
433  *              are creating FOO, instead of doing an elog() we add
434  *              a shell type tuple to pg_type and fix things later
435  *              in amcreate().
436  * ----------------------------------------------------------------
437  */
438 TupleDesc
439 BuildDescForRelation(List *schema, char *relname)
440 {
441         int                     natts;
442         AttrNumber      attnum;
443         List       *p;
444         TupleDesc       desc;
445         AttrDefault *attrdef = NULL;
446         TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr));
447         char       *attname;
448         char       *typename;
449         int                     attdim;
450         int                     ndef = 0;
451         bool            attisset;
452
453         /* ----------------
454          *      allocate a new tuple descriptor
455          * ----------------
456          */
457         natts = length(schema);
458         desc = CreateTemplateTupleDesc(natts);
459         constr->has_not_null = false;
460
461         attnum = 0;
462
463         typename = palloc(NAMEDATALEN);
464
465         foreach(p, schema)
466         {
467                 ColumnDef  *entry;
468                 List       *arry;
469
470                 /* ----------------
471                  *              for each entry in the list, get the name and type
472                  *              information from the list and have TupleDescInitEntry
473                  *              fill in the attribute information we need.
474                  * ----------------
475                  */
476                 attnum++;
477
478                 entry = lfirst(p);
479                 attname = entry->colname;
480                 arry = entry->typename->arrayBounds;
481                 attisset = entry->typename->setof;
482
483                 if (arry != NIL)
484                 {
485                         /* array of XXX is _XXX */
486                         sprintf(typename, "_%.*s", NAMEDATALEN-2,entry->typename->name);
487                         attdim = length(arry);
488                 }
489                 else
490                 {
491                         StrNCpy(typename, entry->typename->name, NAMEDATALEN);
492                         attdim = 0;
493                 }
494
495                 if (!TupleDescInitEntry(desc, attnum, attname,
496                                                                 typename, attdim, attisset))
497                 {
498                         /* ----------------
499                          *      if TupleDescInitEntry() fails, it means there is
500                          *      no type in the system catalogs.  So now we check if
501                          *      the type name equals the relation name.  If so we
502                          *      have a self reference, otherwise it's an error.
503                          * ----------------
504                          */
505                         if (!strcmp(typename, relname))
506                         {
507                                 TupleDescMakeSelfReference(desc, attnum, relname);
508                         }
509                         else
510                                 elog(WARN, "DefineRelation: no such type %s",
511                                          typename);
512                 }
513
514                 /*
515                  * this is for char() and varchar(). When an entry is of type
516                  * char() or varchar(), typlen is set to the appropriate length,
517                  * which we'll use here instead. (The catalog lookup only returns
518                  * the length of bpchar and varchar which is not what we want!) -
519                  * ay 6/95
520                  */
521                 if (entry->typename->typlen > 0)
522                 {
523                         desc->attrs[attnum - 1]->attlen = entry->typename->typlen;
524                 }
525
526                 /* This is for constraints */
527                 if (entry->is_not_null)
528                         constr->has_not_null = true;
529                 desc->attrs[attnum - 1]->attnotnull = entry->is_not_null;
530
531                 if (entry->defval != NULL)
532                 {
533                         if (attrdef == NULL)
534                                 attrdef = (AttrDefault *) palloc(natts * sizeof(AttrDefault));
535                         attrdef[ndef].adnum = attnum;
536                         attrdef[ndef].adbin = NULL;
537                         attrdef[ndef].adsrc = entry->defval;
538                         ndef++;
539                         desc->attrs[attnum - 1]->atthasdef = true;
540                 }
541
542         }
543         if (constr->has_not_null || ndef > 0)
544         {
545                 desc->constr = constr;
546
547                 if (ndef > 0)                   /* DEFAULTs */
548                 {
549                         if (ndef < natts)
550                                 constr->defval = (AttrDefault *)
551                                         repalloc(attrdef, ndef * sizeof(AttrDefault));
552                         else
553                                 constr->defval = attrdef;
554                         constr->num_defval = ndef;
555                 }
556                 else
557                         constr->num_defval = 0;
558                 constr->num_check = 0;
559         }
560         else
561         {
562                 pfree(constr);
563                 desc->constr = NULL;
564         }
565         return desc;
566 }