]> granicus.if.org Git - postgresql/blob - src/backend/access/common/tupdesc.c
Update copyright for the year 2010.
[postgresql] / src / backend / access / common / tupdesc.c
1 /*-------------------------------------------------------------------------
2  *
3  * tupdesc.c
4  *        POSTGRES tuple descriptor support code
5  *
6  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.131 2010/01/02 16:57:33 momjian Exp $
12  *
13  * NOTES
14  *        some of the executor utility code such as "ExecTypeFromTL" should be
15  *        moved here.
16  *
17  *-------------------------------------------------------------------------
18  */
19
20 #include "postgres.h"
21
22 #include "catalog/pg_type.h"
23 #include "parser/parse_type.h"
24 #include "utils/builtins.h"
25 #include "utils/resowner.h"
26 #include "utils/syscache.h"
27
28
29 /*
30  * CreateTemplateTupleDesc
31  *              This function allocates an empty tuple descriptor structure.
32  *
33  * Tuple type ID information is initially set for an anonymous record type;
34  * caller can overwrite this if needed.
35  */
36 TupleDesc
37 CreateTemplateTupleDesc(int natts, bool hasoid)
38 {
39         TupleDesc       desc;
40         char       *stg;
41         int                     attroffset;
42
43         /*
44          * sanity checks
45          */
46         AssertArg(natts >= 0);
47
48         /*
49          * Allocate enough memory for the tuple descriptor, including the
50          * attribute rows, and set up the attribute row pointers.
51          *
52          * Note: we assume that sizeof(struct tupleDesc) is a multiple of the
53          * struct pointer alignment requirement, and hence we don't need to insert
54          * alignment padding between the struct and the array of attribute row
55          * pointers.
56          *
57          * Note: Only the fixed part of pg_attribute rows is included in tuple
58          * descriptors, so we only need ATTRIBUTE_FIXED_PART_SIZE space per attr.
59          * That might need alignment padding, however.
60          */
61         attroffset = sizeof(struct tupleDesc) + natts * sizeof(Form_pg_attribute);
62         attroffset = MAXALIGN(attroffset);
63         stg = palloc(attroffset + natts * MAXALIGN(ATTRIBUTE_FIXED_PART_SIZE));
64         desc = (TupleDesc) stg;
65
66         if (natts > 0)
67         {
68                 Form_pg_attribute *attrs;
69                 int                     i;
70
71                 attrs = (Form_pg_attribute *) (stg + sizeof(struct tupleDesc));
72                 desc->attrs = attrs;
73                 stg += attroffset;
74                 for (i = 0; i < natts; i++)
75                 {
76                         attrs[i] = (Form_pg_attribute) stg;
77                         stg += MAXALIGN(ATTRIBUTE_FIXED_PART_SIZE);
78                 }
79         }
80         else
81                 desc->attrs = NULL;
82
83         /*
84          * Initialize other fields of the tupdesc.
85          */
86         desc->natts = natts;
87         desc->constr = NULL;
88         desc->tdtypeid = RECORDOID;
89         desc->tdtypmod = -1;
90         desc->tdhasoid = hasoid;
91         desc->tdrefcount = -1;          /* assume not reference-counted */
92
93         return desc;
94 }
95
96 /*
97  * CreateTupleDesc
98  *              This function allocates a new TupleDesc pointing to a given
99  *              Form_pg_attribute array.
100  *
101  * Note: if the TupleDesc is ever freed, the Form_pg_attribute array
102  * will not be freed thereby.
103  *
104  * Tuple type ID information is initially set for an anonymous record type;
105  * caller can overwrite this if needed.
106  */
107 TupleDesc
108 CreateTupleDesc(int natts, bool hasoid, Form_pg_attribute *attrs)
109 {
110         TupleDesc       desc;
111
112         /*
113          * sanity checks
114          */
115         AssertArg(natts >= 0);
116
117         desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
118         desc->attrs = attrs;
119         desc->natts = natts;
120         desc->constr = NULL;
121         desc->tdtypeid = RECORDOID;
122         desc->tdtypmod = -1;
123         desc->tdhasoid = hasoid;
124         desc->tdrefcount = -1;          /* assume not reference-counted */
125
126         return desc;
127 }
128
129 /*
130  * CreateTupleDescCopy
131  *              This function creates a new TupleDesc by copying from an existing
132  *              TupleDesc.
133  *
134  * !!! Constraints and defaults are not copied !!!
135  */
136 TupleDesc
137 CreateTupleDescCopy(TupleDesc tupdesc)
138 {
139         TupleDesc       desc;
140         int                     i;
141
142         desc = CreateTemplateTupleDesc(tupdesc->natts, tupdesc->tdhasoid);
143
144         for (i = 0; i < desc->natts; i++)
145         {
146                 memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
147                 desc->attrs[i]->attnotnull = false;
148                 desc->attrs[i]->atthasdef = false;
149         }
150
151         desc->tdtypeid = tupdesc->tdtypeid;
152         desc->tdtypmod = tupdesc->tdtypmod;
153
154         return desc;
155 }
156
157 /*
158  * CreateTupleDescCopyConstr
159  *              This function creates a new TupleDesc by copying from an existing
160  *              TupleDesc (including its constraints and defaults).
161  */
162 TupleDesc
163 CreateTupleDescCopyConstr(TupleDesc tupdesc)
164 {
165         TupleDesc       desc;
166         TupleConstr *constr = tupdesc->constr;
167         int                     i;
168
169         desc = CreateTemplateTupleDesc(tupdesc->natts, tupdesc->tdhasoid);
170
171         for (i = 0; i < desc->natts; i++)
172         {
173                 memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
174         }
175
176         if (constr)
177         {
178                 TupleConstr *cpy = (TupleConstr *) palloc0(sizeof(TupleConstr));
179
180                 cpy->has_not_null = constr->has_not_null;
181
182                 if ((cpy->num_defval = constr->num_defval) > 0)
183                 {
184                         cpy->defval = (AttrDefault *) palloc(cpy->num_defval * sizeof(AttrDefault));
185                         memcpy(cpy->defval, constr->defval, cpy->num_defval * sizeof(AttrDefault));
186                         for (i = cpy->num_defval - 1; i >= 0; i--)
187                         {
188                                 if (constr->defval[i].adbin)
189                                         cpy->defval[i].adbin = pstrdup(constr->defval[i].adbin);
190                         }
191                 }
192
193                 if ((cpy->num_check = constr->num_check) > 0)
194                 {
195                         cpy->check = (ConstrCheck *) palloc(cpy->num_check * sizeof(ConstrCheck));
196                         memcpy(cpy->check, constr->check, cpy->num_check * sizeof(ConstrCheck));
197                         for (i = cpy->num_check - 1; i >= 0; i--)
198                         {
199                                 if (constr->check[i].ccname)
200                                         cpy->check[i].ccname = pstrdup(constr->check[i].ccname);
201                                 if (constr->check[i].ccbin)
202                                         cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin);
203                         }
204                 }
205
206                 desc->constr = cpy;
207         }
208
209         desc->tdtypeid = tupdesc->tdtypeid;
210         desc->tdtypmod = tupdesc->tdtypmod;
211
212         return desc;
213 }
214
215 /*
216  * Free a TupleDesc including all substructure
217  */
218 void
219 FreeTupleDesc(TupleDesc tupdesc)
220 {
221         int                     i;
222
223         /*
224          * Possibly this should assert tdrefcount == 0, to disallow explicit
225          * freeing of un-refcounted tupdescs?
226          */
227         Assert(tupdesc->tdrefcount <= 0);
228
229         if (tupdesc->constr)
230         {
231                 if (tupdesc->constr->num_defval > 0)
232                 {
233                         AttrDefault *attrdef = tupdesc->constr->defval;
234
235                         for (i = tupdesc->constr->num_defval - 1; i >= 0; i--)
236                         {
237                                 if (attrdef[i].adbin)
238                                         pfree(attrdef[i].adbin);
239                         }
240                         pfree(attrdef);
241                 }
242                 if (tupdesc->constr->num_check > 0)
243                 {
244                         ConstrCheck *check = tupdesc->constr->check;
245
246                         for (i = tupdesc->constr->num_check - 1; i >= 0; i--)
247                         {
248                                 if (check[i].ccname)
249                                         pfree(check[i].ccname);
250                                 if (check[i].ccbin)
251                                         pfree(check[i].ccbin);
252                         }
253                         pfree(check);
254                 }
255                 pfree(tupdesc->constr);
256         }
257
258         pfree(tupdesc);
259 }
260
261 /*
262  * Increment the reference count of a tupdesc, and log the reference in
263  * CurrentResourceOwner.
264  *
265  * Do not apply this to tupdescs that are not being refcounted.  (Use the
266  * macro PinTupleDesc for tupdescs of uncertain status.)
267  */
268 void
269 IncrTupleDescRefCount(TupleDesc tupdesc)
270 {
271         Assert(tupdesc->tdrefcount >= 0);
272
273         ResourceOwnerEnlargeTupleDescs(CurrentResourceOwner);
274         tupdesc->tdrefcount++;
275         ResourceOwnerRememberTupleDesc(CurrentResourceOwner, tupdesc);
276 }
277
278 /*
279  * Decrement the reference count of a tupdesc, remove the corresponding
280  * reference from CurrentResourceOwner, and free the tupdesc if no more
281  * references remain.
282  *
283  * Do not apply this to tupdescs that are not being refcounted.  (Use the
284  * macro ReleaseTupleDesc for tupdescs of uncertain status.)
285  */
286 void
287 DecrTupleDescRefCount(TupleDesc tupdesc)
288 {
289         Assert(tupdesc->tdrefcount > 0);
290
291         ResourceOwnerForgetTupleDesc(CurrentResourceOwner, tupdesc);
292         if (--tupdesc->tdrefcount == 0)
293                 FreeTupleDesc(tupdesc);
294 }
295
296 /*
297  * Compare two TupleDesc structures for logical equality
298  *
299  * Note: we deliberately do not check the attrelid and tdtypmod fields.
300  * This allows typcache.c to use this routine to see if a cached record type
301  * matches a requested type, and is harmless for relcache.c's uses.
302  * We don't compare tdrefcount, either.
303  */
304 bool
305 equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
306 {
307         int                     i,
308                                 j,
309                                 n;
310
311         if (tupdesc1->natts != tupdesc2->natts)
312                 return false;
313         if (tupdesc1->tdtypeid != tupdesc2->tdtypeid)
314                 return false;
315         if (tupdesc1->tdhasoid != tupdesc2->tdhasoid)
316                 return false;
317
318         for (i = 0; i < tupdesc1->natts; i++)
319         {
320                 Form_pg_attribute attr1 = tupdesc1->attrs[i];
321                 Form_pg_attribute attr2 = tupdesc2->attrs[i];
322
323                 /*
324                  * We do not need to check every single field here: we can disregard
325                  * attrelid and attnum (which were used to place the row in the attrs
326                  * array in the first place).  It might look like we could dispense
327                  * with checking attlen/attbyval/attalign, since these are derived
328                  * from atttypid; but in the case of dropped columns we must check
329                  * them (since atttypid will be zero for all dropped columns) and in
330                  * general it seems safer to check them always.
331                  *
332                  * attcacheoff must NOT be checked since it's possibly not set in both
333                  * copies.
334                  */
335                 if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0)
336                         return false;
337                 if (attr1->atttypid != attr2->atttypid)
338                         return false;
339                 if (attr1->attstattarget != attr2->attstattarget)
340                         return false;
341                 if (attr1->attdistinct != attr2->attdistinct)
342                         return false;
343                 if (attr1->attlen != attr2->attlen)
344                         return false;
345                 if (attr1->attndims != attr2->attndims)
346                         return false;
347                 if (attr1->atttypmod != attr2->atttypmod)
348                         return false;
349                 if (attr1->attbyval != attr2->attbyval)
350                         return false;
351                 if (attr1->attstorage != attr2->attstorage)
352                         return false;
353                 if (attr1->attalign != attr2->attalign)
354                         return false;
355                 if (attr1->attnotnull != attr2->attnotnull)
356                         return false;
357                 if (attr1->atthasdef != attr2->atthasdef)
358                         return false;
359                 if (attr1->attisdropped != attr2->attisdropped)
360                         return false;
361                 if (attr1->attislocal != attr2->attislocal)
362                         return false;
363                 if (attr1->attinhcount != attr2->attinhcount)
364                         return false;
365                 /* attacl is ignored, since it's not even present... */
366         }
367
368         if (tupdesc1->constr != NULL)
369         {
370                 TupleConstr *constr1 = tupdesc1->constr;
371                 TupleConstr *constr2 = tupdesc2->constr;
372
373                 if (constr2 == NULL)
374                         return false;
375                 if (constr1->has_not_null != constr2->has_not_null)
376                         return false;
377                 n = constr1->num_defval;
378                 if (n != (int) constr2->num_defval)
379                         return false;
380                 for (i = 0; i < n; i++)
381                 {
382                         AttrDefault *defval1 = constr1->defval + i;
383                         AttrDefault *defval2 = constr2->defval;
384
385                         /*
386                          * We can't assume that the items are always read from the system
387                          * catalogs in the same order; so use the adnum field to identify
388                          * the matching item to compare.
389                          */
390                         for (j = 0; j < n; defval2++, j++)
391                         {
392                                 if (defval1->adnum == defval2->adnum)
393                                         break;
394                         }
395                         if (j >= n)
396                                 return false;
397                         if (strcmp(defval1->adbin, defval2->adbin) != 0)
398                                 return false;
399                 }
400                 n = constr1->num_check;
401                 if (n != (int) constr2->num_check)
402                         return false;
403                 for (i = 0; i < n; i++)
404                 {
405                         ConstrCheck *check1 = constr1->check + i;
406                         ConstrCheck *check2 = constr2->check;
407
408                         /*
409                          * Similarly, don't assume that the checks are always read in the
410                          * same order; match them up by name and contents. (The name
411                          * *should* be unique, but...)
412                          */
413                         for (j = 0; j < n; check2++, j++)
414                         {
415                                 if (strcmp(check1->ccname, check2->ccname) == 0 &&
416                                         strcmp(check1->ccbin, check2->ccbin) == 0)
417                                         break;
418                         }
419                         if (j >= n)
420                                 return false;
421                 }
422         }
423         else if (tupdesc2->constr != NULL)
424                 return false;
425         return true;
426 }
427
428 /*
429  * TupleDescInitEntry
430  *              This function initializes a single attribute structure in
431  *              a previously allocated tuple descriptor.
432  */
433 void
434 TupleDescInitEntry(TupleDesc desc,
435                                    AttrNumber attributeNumber,
436                                    const char *attributeName,
437                                    Oid oidtypeid,
438                                    int32 typmod,
439                                    int attdim)
440 {
441         HeapTuple       tuple;
442         Form_pg_type typeForm;
443         Form_pg_attribute att;
444
445         /*
446          * sanity checks
447          */
448         AssertArg(PointerIsValid(desc));
449         AssertArg(attributeNumber >= 1);
450         AssertArg(attributeNumber <= desc->natts);
451
452         /*
453          * initialize the attribute fields
454          */
455         att = desc->attrs[attributeNumber - 1];
456
457         att->attrelid = 0;                      /* dummy value */
458
459         /*
460          * Note: attributeName can be NULL, because the planner doesn't always
461          * fill in valid resname values in targetlists, particularly for resjunk
462          * attributes.
463          */
464         if (attributeName != NULL)
465                 namestrcpy(&(att->attname), attributeName);
466         else
467                 MemSet(NameStr(att->attname), 0, NAMEDATALEN);
468
469         att->attstattarget = -1;
470         att->attdistinct = 0;
471         att->attcacheoff = -1;
472         att->atttypmod = typmod;
473
474         att->attnum = attributeNumber;
475         att->attndims = attdim;
476
477         att->attnotnull = false;
478         att->atthasdef = false;
479         att->attisdropped = false;
480         att->attislocal = true;
481         att->attinhcount = 0;
482         /* attacl is not set because it's not present in tupledescs */
483
484         tuple = SearchSysCache(TYPEOID,
485                                                    ObjectIdGetDatum(oidtypeid),
486                                                    0, 0, 0);
487         if (!HeapTupleIsValid(tuple))
488                 elog(ERROR, "cache lookup failed for type %u", oidtypeid);
489         typeForm = (Form_pg_type) GETSTRUCT(tuple);
490
491         att->atttypid = oidtypeid;
492         att->attlen = typeForm->typlen;
493         att->attbyval = typeForm->typbyval;
494         att->attalign = typeForm->typalign;
495         att->attstorage = typeForm->typstorage;
496
497         ReleaseSysCache(tuple);
498 }
499
500
501 /*
502  * BuildDescForRelation
503  *
504  * Given a relation schema (list of ColumnDef nodes), build a TupleDesc.
505  *
506  * Note: the default assumption is no OIDs; caller may modify the returned
507  * TupleDesc if it wants OIDs.  Also, tdtypeid will need to be filled in
508  * later on.
509  */
510 TupleDesc
511 BuildDescForRelation(List *schema)
512 {
513         int                     natts;
514         AttrNumber      attnum;
515         ListCell   *l;
516         TupleDesc       desc;
517         bool            has_not_null;
518         char       *attname;
519         Oid                     atttypid;
520         int32           atttypmod;
521         int                     attdim;
522
523         /*
524          * allocate a new tuple descriptor
525          */
526         natts = list_length(schema);
527         desc = CreateTemplateTupleDesc(natts, false);
528         has_not_null = false;
529
530         attnum = 0;
531
532         foreach(l, schema)
533         {
534                 ColumnDef  *entry = lfirst(l);
535
536                 /*
537                  * for each entry in the list, get the name and type information from
538                  * the list and have TupleDescInitEntry fill in the attribute
539                  * information we need.
540                  */
541                 attnum++;
542
543                 attname = entry->colname;
544                 atttypid = typenameTypeId(NULL, entry->typeName, &atttypmod);
545                 attdim = list_length(entry->typeName->arrayBounds);
546
547                 if (entry->typeName->setof)
548                         ereport(ERROR,
549                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
550                                          errmsg("column \"%s\" cannot be declared SETOF",
551                                                         attname)));
552
553                 TupleDescInitEntry(desc, attnum, attname,
554                                                    atttypid, atttypmod, attdim);
555
556                 /* Override TupleDescInitEntry's settings as requested */
557                 if (entry->storage)
558                         desc->attrs[attnum - 1]->attstorage = entry->storage;
559
560                 /* Fill in additional stuff not handled by TupleDescInitEntry */
561                 desc->attrs[attnum - 1]->attnotnull = entry->is_not_null;
562                 has_not_null |= entry->is_not_null;
563                 desc->attrs[attnum - 1]->attislocal = entry->is_local;
564                 desc->attrs[attnum - 1]->attinhcount = entry->inhcount;
565         }
566
567         if (has_not_null)
568         {
569                 TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
570
571                 constr->has_not_null = true;
572                 constr->defval = NULL;
573                 constr->num_defval = 0;
574                 constr->check = NULL;
575                 constr->num_check = 0;
576                 desc->constr = constr;
577         }
578         else
579         {
580                 desc->constr = NULL;
581         }
582
583         return desc;
584 }
585
586 /*
587  * BuildDescFromLists
588  *
589  * Build a TupleDesc given lists of column names (as String nodes),
590  * column type OIDs, and column typmods.  No constraints are generated.
591  *
592  * This is essentially a cut-down version of BuildDescForRelation for use
593  * with functions returning RECORD.
594  */
595 TupleDesc
596 BuildDescFromLists(List *names, List *types, List *typmods)
597 {
598         int                     natts;
599         AttrNumber      attnum;
600         ListCell   *l1;
601         ListCell   *l2;
602         ListCell   *l3;
603         TupleDesc       desc;
604
605         natts = list_length(names);
606         Assert(natts == list_length(types));
607         Assert(natts == list_length(typmods));
608
609         /*
610          * allocate a new tuple descriptor
611          */
612         desc = CreateTemplateTupleDesc(natts, false);
613
614         attnum = 0;
615
616         l2 = list_head(types);
617         l3 = list_head(typmods);
618         foreach(l1, names)
619         {
620                 char       *attname = strVal(lfirst(l1));
621                 Oid                     atttypid;
622                 int32           atttypmod;
623
624                 atttypid = lfirst_oid(l2);
625                 l2 = lnext(l2);
626                 atttypmod = lfirst_int(l3);
627                 l3 = lnext(l3);
628
629                 attnum++;
630
631                 TupleDescInitEntry(desc, attnum, attname, atttypid, atttypmod, 0);
632         }
633
634         return desc;
635 }