1/*-------------------------------------------------------------------------
2 *
3 * tupdesc.c
4 * POSTGRES tuple descriptor support code
5 *
6 * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/access/common/tupdesc.c
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 "access/htup_details.h"
23#include "access/tupdesc_details.h"
24#include "catalog/pg_collation.h"
25#include "catalog/pg_type.h"
26#include "miscadmin.h"
27#include "parser/parse_type.h"
28#include "utils/acl.h"
29#include "utils/builtins.h"
30#include "utils/datum.h"
31#include "utils/hashutils.h"
32#include "utils/resowner_private.h"
33#include "utils/syscache.h"
34
35
36/*
37 * CreateTemplateTupleDesc
38 * This function allocates an empty tuple descriptor structure.
39 *
40 * Tuple type ID information is initially set for an anonymous record type;
41 * caller can overwrite this if needed.
42 */
43TupleDesc
44CreateTemplateTupleDesc(int natts)
45{
46 TupleDesc desc;
47
48 /*
49 * sanity checks
50 */
51 AssertArg(natts >= 0);
52
53 /*
54 * Allocate enough memory for the tuple descriptor, including the
55 * attribute rows.
56 *
57 * Note: the attribute array stride is sizeof(FormData_pg_attribute),
58 * since we declare the array elements as FormData_pg_attribute for
59 * notational convenience. However, we only guarantee that the first
60 * ATTRIBUTE_FIXED_PART_SIZE bytes of each entry are valid; most code that
61 * copies tupdesc entries around copies just that much. In principle that
62 * could be less due to trailing padding, although with the current
63 * definition of pg_attribute there probably isn't any padding.
64 */
65 desc = (TupleDesc) palloc(offsetof(struct TupleDescData, attrs) +
66 natts * sizeof(FormData_pg_attribute));
67
68 /*
69 * Initialize other fields of the tupdesc.
70 */
71 desc->natts = natts;
72 desc->constr = NULL;
73 desc->tdtypeid = RECORDOID;
74 desc->tdtypmod = -1;
75 desc->tdrefcount = -1; /* assume not reference-counted */
76
77 return desc;
78}
79
80/*
81 * CreateTupleDesc
82 * This function allocates a new TupleDesc by copying a given
83 * Form_pg_attribute array.
84 *
85 * Tuple type ID information is initially set for an anonymous record type;
86 * caller can overwrite this if needed.
87 */
88TupleDesc
89CreateTupleDesc(int natts, Form_pg_attribute *attrs)
90{
91 TupleDesc desc;
92 int i;
93
94 desc = CreateTemplateTupleDesc(natts);
95
96 for (i = 0; i < natts; ++i)
97 memcpy(TupleDescAttr(desc, i), attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
98
99 return desc;
100}
101
102/*
103 * CreateTupleDescCopy
104 * This function creates a new TupleDesc by copying from an existing
105 * TupleDesc.
106 *
107 * !!! Constraints and defaults are not copied !!!
108 */
109TupleDesc
110CreateTupleDescCopy(TupleDesc tupdesc)
111{
112 TupleDesc desc;
113 int i;
114
115 desc = CreateTemplateTupleDesc(tupdesc->natts);
116
117 /* Flat-copy the attribute array */
118 memcpy(TupleDescAttr(desc, 0),
119 TupleDescAttr(tupdesc, 0),
120 desc->natts * sizeof(FormData_pg_attribute));
121
122 /*
123 * Since we're not copying constraints and defaults, clear fields
124 * associated with them.
125 */
126 for (i = 0; i < desc->natts; i++)
127 {
128 Form_pg_attribute att = TupleDescAttr(desc, i);
129
130 att->attnotnull = false;
131 att->atthasdef = false;
132 att->atthasmissing = false;
133 att->attidentity = '\0';
134 att->attgenerated = '\0';
135 }
136
137 /* We can copy the tuple type identification, too */
138 desc->tdtypeid = tupdesc->tdtypeid;
139 desc->tdtypmod = tupdesc->tdtypmod;
140
141 return desc;
142}
143
144/*
145 * CreateTupleDescCopyConstr
146 * This function creates a new TupleDesc by copying from an existing
147 * TupleDesc (including its constraints and defaults).
148 */
149TupleDesc
150CreateTupleDescCopyConstr(TupleDesc tupdesc)
151{
152 TupleDesc desc;
153 TupleConstr *constr = tupdesc->constr;
154 int i;
155
156 desc = CreateTemplateTupleDesc(tupdesc->natts);
157
158 /* Flat-copy the attribute array */
159 memcpy(TupleDescAttr(desc, 0),
160 TupleDescAttr(tupdesc, 0),
161 desc->natts * sizeof(FormData_pg_attribute));
162
163 /* Copy the TupleConstr data structure, if any */
164 if (constr)
165 {
166 TupleConstr *cpy = (TupleConstr *) palloc0(sizeof(TupleConstr));
167
168 cpy->has_not_null = constr->has_not_null;
169 cpy->has_generated_stored = constr->has_generated_stored;
170
171 if ((cpy->num_defval = constr->num_defval) > 0)
172 {
173 cpy->defval = (AttrDefault *) palloc(cpy->num_defval * sizeof(AttrDefault));
174 memcpy(cpy->defval, constr->defval, cpy->num_defval * sizeof(AttrDefault));
175 for (i = cpy->num_defval - 1; i >= 0; i--)
176 {
177 if (constr->defval[i].adbin)
178 cpy->defval[i].adbin = pstrdup(constr->defval[i].adbin);
179 }
180 }
181
182 if (constr->missing)
183 {
184 cpy->missing = (AttrMissing *) palloc(tupdesc->natts * sizeof(AttrMissing));
185 memcpy(cpy->missing, constr->missing, tupdesc->natts * sizeof(AttrMissing));
186 for (i = tupdesc->natts - 1; i >= 0; i--)
187 {
188 if (constr->missing[i].am_present)
189 {
190 Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
191
192 cpy->missing[i].am_value = datumCopy(constr->missing[i].am_value,
193 attr->attbyval,
194 attr->attlen);
195 }
196 }
197 }
198
199 if ((cpy->num_check = constr->num_check) > 0)
200 {
201 cpy->check = (ConstrCheck *) palloc(cpy->num_check * sizeof(ConstrCheck));
202 memcpy(cpy->check, constr->check, cpy->num_check * sizeof(ConstrCheck));
203 for (i = cpy->num_check - 1; i >= 0; i--)
204 {
205 if (constr->check[i].ccname)
206 cpy->check[i].ccname = pstrdup(constr->check[i].ccname);
207 if (constr->check[i].ccbin)
208 cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin);
209 cpy->check[i].ccvalid = constr->check[i].ccvalid;
210 cpy->check[i].ccnoinherit = constr->check[i].ccnoinherit;
211 }
212 }
213
214 desc->constr = cpy;
215 }
216
217 /* We can copy the tuple type identification, too */
218 desc->tdtypeid = tupdesc->tdtypeid;
219 desc->tdtypmod = tupdesc->tdtypmod;
220
221 return desc;
222}
223
224/*
225 * TupleDescCopy
226 * Copy a tuple descriptor into caller-supplied memory.
227 * The memory may be shared memory mapped at any address, and must
228 * be sufficient to hold TupleDescSize(src) bytes.
229 *
230 * !!! Constraints and defaults are not copied !!!
231 */
232void
233TupleDescCopy(TupleDesc dst, TupleDesc src)
234{
235 int i;
236
237 /* Flat-copy the header and attribute array */
238 memcpy(dst, src, TupleDescSize(src));
239
240 /*
241 * Since we're not copying constraints and defaults, clear fields
242 * associated with them.
243 */
244 for (i = 0; i < dst->natts; i++)
245 {
246 Form_pg_attribute att = TupleDescAttr(dst, i);
247
248 att->attnotnull = false;
249 att->atthasdef = false;
250 att->atthasmissing = false;
251 att->attidentity = '\0';
252 att->attgenerated = '\0';
253 }
254 dst->constr = NULL;
255
256 /*
257 * Also, assume the destination is not to be ref-counted. (Copying the
258 * source's refcount would be wrong in any case.)
259 */
260 dst->tdrefcount = -1;
261}
262
263/*
264 * TupleDescCopyEntry
265 * This function copies a single attribute structure from one tuple
266 * descriptor to another.
267 *
268 * !!! Constraints and defaults are not copied !!!
269 */
270void
271TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno,
272 TupleDesc src, AttrNumber srcAttno)
273{
274 Form_pg_attribute dstAtt = TupleDescAttr(dst, dstAttno - 1);
275 Form_pg_attribute srcAtt = TupleDescAttr(src, srcAttno - 1);
276
277 /*
278 * sanity checks
279 */
280 AssertArg(PointerIsValid(src));
281 AssertArg(PointerIsValid(dst));
282 AssertArg(srcAttno >= 1);
283 AssertArg(srcAttno <= src->natts);
284 AssertArg(dstAttno >= 1);
285 AssertArg(dstAttno <= dst->natts);
286
287 memcpy(dstAtt, srcAtt, ATTRIBUTE_FIXED_PART_SIZE);
288
289 /*
290 * Aside from updating the attno, we'd better reset attcacheoff.
291 *
292 * XXX Actually, to be entirely safe we'd need to reset the attcacheoff of
293 * all following columns in dst as well. Current usage scenarios don't
294 * require that though, because all following columns will get initialized
295 * by other uses of this function or TupleDescInitEntry. So we cheat a
296 * bit to avoid a useless O(N^2) penalty.
297 */
298 dstAtt->attnum = dstAttno;
299 dstAtt->attcacheoff = -1;
300
301 /* since we're not copying constraints or defaults, clear these */
302 dstAtt->attnotnull = false;
303 dstAtt->atthasdef = false;
304 dstAtt->atthasmissing = false;
305 dstAtt->attidentity = '\0';
306 dstAtt->attgenerated = '\0';
307}
308
309/*
310 * Free a TupleDesc including all substructure
311 */
312void
313FreeTupleDesc(TupleDesc tupdesc)
314{
315 int i;
316
317 /*
318 * Possibly this should assert tdrefcount == 0, to disallow explicit
319 * freeing of un-refcounted tupdescs?
320 */
321 Assert(tupdesc->tdrefcount <= 0);
322
323 if (tupdesc->constr)
324 {
325 if (tupdesc->constr->num_defval > 0)
326 {
327 AttrDefault *attrdef = tupdesc->constr->defval;
328
329 for (i = tupdesc->constr->num_defval - 1; i >= 0; i--)
330 {
331 if (attrdef[i].adbin)
332 pfree(attrdef[i].adbin);
333 }
334 pfree(attrdef);
335 }
336 if (tupdesc->constr->missing)
337 {
338 AttrMissing *attrmiss = tupdesc->constr->missing;
339
340 for (i = tupdesc->natts - 1; i >= 0; i--)
341 {
342 if (attrmiss[i].am_present
343 && !TupleDescAttr(tupdesc, i)->attbyval)
344 pfree(DatumGetPointer(attrmiss[i].am_value));
345 }
346 pfree(attrmiss);
347 }
348 if (tupdesc->constr->num_check > 0)
349 {
350 ConstrCheck *check = tupdesc->constr->check;
351
352 for (i = tupdesc->constr->num_check - 1; i >= 0; i--)
353 {
354 if (check[i].ccname)
355 pfree(check[i].ccname);
356 if (check[i].ccbin)
357 pfree(check[i].ccbin);
358 }
359 pfree(check);
360 }
361 pfree(tupdesc->constr);
362 }
363
364 pfree(tupdesc);
365}
366
367/*
368 * Increment the reference count of a tupdesc, and log the reference in
369 * CurrentResourceOwner.
370 *
371 * Do not apply this to tupdescs that are not being refcounted. (Use the
372 * macro PinTupleDesc for tupdescs of uncertain status.)
373 */
374void
375IncrTupleDescRefCount(TupleDesc tupdesc)
376{
377 Assert(tupdesc->tdrefcount >= 0);
378
379 ResourceOwnerEnlargeTupleDescs(CurrentResourceOwner);
380 tupdesc->tdrefcount++;
381 ResourceOwnerRememberTupleDesc(CurrentResourceOwner, tupdesc);
382}
383
384/*
385 * Decrement the reference count of a tupdesc, remove the corresponding
386 * reference from CurrentResourceOwner, and free the tupdesc if no more
387 * references remain.
388 *
389 * Do not apply this to tupdescs that are not being refcounted. (Use the
390 * macro ReleaseTupleDesc for tupdescs of uncertain status.)
391 */
392void
393DecrTupleDescRefCount(TupleDesc tupdesc)
394{
395 Assert(tupdesc->tdrefcount > 0);
396
397 ResourceOwnerForgetTupleDesc(CurrentResourceOwner, tupdesc);
398 if (--tupdesc->tdrefcount == 0)
399 FreeTupleDesc(tupdesc);
400}
401
402/*
403 * Compare two TupleDesc structures for logical equality
404 *
405 * Note: we deliberately do not check the attrelid and tdtypmod fields.
406 * This allows typcache.c to use this routine to see if a cached record type
407 * matches a requested type, and is harmless for relcache.c's uses.
408 * We don't compare tdrefcount, either.
409 */
410bool
411equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
412{
413 int i,
414 j,
415 n;
416
417 if (tupdesc1->natts != tupdesc2->natts)
418 return false;
419 if (tupdesc1->tdtypeid != tupdesc2->tdtypeid)
420 return false;
421
422 for (i = 0; i < tupdesc1->natts; i++)
423 {
424 Form_pg_attribute attr1 = TupleDescAttr(tupdesc1, i);
425 Form_pg_attribute attr2 = TupleDescAttr(tupdesc2, i);
426
427 /*
428 * We do not need to check every single field here: we can disregard
429 * attrelid and attnum (which were used to place the row in the attrs
430 * array in the first place). It might look like we could dispense
431 * with checking attlen/attbyval/attalign, since these are derived
432 * from atttypid; but in the case of dropped columns we must check
433 * them (since atttypid will be zero for all dropped columns) and in
434 * general it seems safer to check them always.
435 *
436 * attcacheoff must NOT be checked since it's possibly not set in both
437 * copies.
438 */
439 if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0)
440 return false;
441 if (attr1->atttypid != attr2->atttypid)
442 return false;
443 if (attr1->attstattarget != attr2->attstattarget)
444 return false;
445 if (attr1->attlen != attr2->attlen)
446 return false;
447 if (attr1->attndims != attr2->attndims)
448 return false;
449 if (attr1->atttypmod != attr2->atttypmod)
450 return false;
451 if (attr1->attbyval != attr2->attbyval)
452 return false;
453 if (attr1->attstorage != attr2->attstorage)
454 return false;
455 if (attr1->attalign != attr2->attalign)
456 return false;
457 if (attr1->attnotnull != attr2->attnotnull)
458 return false;
459 if (attr1->atthasdef != attr2->atthasdef)
460 return false;
461 if (attr1->attidentity != attr2->attidentity)
462 return false;
463 if (attr1->attgenerated != attr2->attgenerated)
464 return false;
465 if (attr1->attisdropped != attr2->attisdropped)
466 return false;
467 if (attr1->attislocal != attr2->attislocal)
468 return false;
469 if (attr1->attinhcount != attr2->attinhcount)
470 return false;
471 if (attr1->attcollation != attr2->attcollation)
472 return false;
473 /* attacl, attoptions and attfdwoptions are not even present... */
474 }
475
476 if (tupdesc1->constr != NULL)
477 {
478 TupleConstr *constr1 = tupdesc1->constr;
479 TupleConstr *constr2 = tupdesc2->constr;
480
481 if (constr2 == NULL)
482 return false;
483 if (constr1->has_not_null != constr2->has_not_null)
484 return false;
485 if (constr1->has_generated_stored != constr2->has_generated_stored)
486 return false;
487 n = constr1->num_defval;
488 if (n != (int) constr2->num_defval)
489 return false;
490 for (i = 0; i < n; i++)
491 {
492 AttrDefault *defval1 = constr1->defval + i;
493 AttrDefault *defval2 = constr2->defval;
494
495 /*
496 * We can't assume that the items are always read from the system
497 * catalogs in the same order; so use the adnum field to identify
498 * the matching item to compare.
499 */
500 for (j = 0; j < n; defval2++, j++)
501 {
502 if (defval1->adnum == defval2->adnum)
503 break;
504 }
505 if (j >= n)
506 return false;
507 if (strcmp(defval1->adbin, defval2->adbin) != 0)
508 return false;
509 }
510 if (constr1->missing)
511 {
512 if (!constr2->missing)
513 return false;
514 for (i = 0; i < tupdesc1->natts; i++)
515 {
516 AttrMissing *missval1 = constr1->missing + i;
517 AttrMissing *missval2 = constr2->missing + i;
518
519 if (missval1->am_present != missval2->am_present)
520 return false;
521 if (missval1->am_present)
522 {
523 Form_pg_attribute missatt1 = TupleDescAttr(tupdesc1, i);
524
525 if (!datumIsEqual(missval1->am_value, missval2->am_value,
526 missatt1->attbyval, missatt1->attlen))
527 return false;
528 }
529 }
530 }
531 else if (constr2->missing)
532 return false;
533 n = constr1->num_check;
534 if (n != (int) constr2->num_check)
535 return false;
536 for (i = 0; i < n; i++)
537 {
538 ConstrCheck *check1 = constr1->check + i;
539 ConstrCheck *check2 = constr2->check;
540
541 /*
542 * Similarly, don't assume that the checks are always read in the
543 * same order; match them up by name and contents. (The name
544 * *should* be unique, but...)
545 */
546 for (j = 0; j < n; check2++, j++)
547 {
548 if (strcmp(check1->ccname, check2->ccname) == 0 &&
549 strcmp(check1->ccbin, check2->ccbin) == 0 &&
550 check1->ccvalid == check2->ccvalid &&
551 check1->ccnoinherit == check2->ccnoinherit)
552 break;
553 }
554 if (j >= n)
555 return false;
556 }
557 }
558 else if (tupdesc2->constr != NULL)
559 return false;
560 return true;
561}
562
563/*
564 * hashTupleDesc
565 * Compute a hash value for a tuple descriptor.
566 *
567 * If two tuple descriptors would be considered equal by equalTupleDescs()
568 * then their hash value will be equal according to this function.
569 *
570 * Note that currently contents of constraint are not hashed - it'd be a bit
571 * painful to do so, and conflicts just due to constraints are unlikely.
572 */
573uint32
574hashTupleDesc(TupleDesc desc)
575{
576 uint32 s;
577 int i;
578
579 s = hash_combine(0, hash_uint32(desc->natts));
580 s = hash_combine(s, hash_uint32(desc->tdtypeid));
581 for (i = 0; i < desc->natts; ++i)
582 s = hash_combine(s, hash_uint32(TupleDescAttr(desc, i)->atttypid));
583
584 return s;
585}
586
587/*
588 * TupleDescInitEntry
589 * This function initializes a single attribute structure in
590 * a previously allocated tuple descriptor.
591 *
592 * If attributeName is NULL, the attname field is set to an empty string
593 * (this is for cases where we don't know or need a name for the field).
594 * Also, some callers use this function to change the datatype-related fields
595 * in an existing tupdesc; they pass attributeName = NameStr(att->attname)
596 * to indicate that the attname field shouldn't be modified.
597 *
598 * Note that attcollation is set to the default for the specified datatype.
599 * If a nondefault collation is needed, insert it afterwards using
600 * TupleDescInitEntryCollation.
601 */
602void
603TupleDescInitEntry(TupleDesc desc,
604 AttrNumber attributeNumber,
605 const char *attributeName,
606 Oid oidtypeid,
607 int32 typmod,
608 int attdim)
609{
610 HeapTuple tuple;
611 Form_pg_type typeForm;
612 Form_pg_attribute att;
613
614 /*
615 * sanity checks
616 */
617 AssertArg(PointerIsValid(desc));
618 AssertArg(attributeNumber >= 1);
619 AssertArg(attributeNumber <= desc->natts);
620
621 /*
622 * initialize the attribute fields
623 */
624 att = TupleDescAttr(desc, attributeNumber - 1);
625
626 att->attrelid = 0; /* dummy value */
627
628 /*
629 * Note: attributeName can be NULL, because the planner doesn't always
630 * fill in valid resname values in targetlists, particularly for resjunk
631 * attributes. Also, do nothing if caller wants to re-use the old attname.
632 */
633 if (attributeName == NULL)
634 MemSet(NameStr(att->attname), 0, NAMEDATALEN);
635 else if (attributeName != NameStr(att->attname))
636 namestrcpy(&(att->attname), attributeName);
637
638 att->attstattarget = -1;
639 att->attcacheoff = -1;
640 att->atttypmod = typmod;
641
642 att->attnum = attributeNumber;
643 att->attndims = attdim;
644
645 att->attnotnull = false;
646 att->atthasdef = false;
647 att->atthasmissing = false;
648 att->attidentity = '\0';
649 att->attgenerated = '\0';
650 att->attisdropped = false;
651 att->attislocal = true;
652 att->attinhcount = 0;
653 /* attacl, attoptions and attfdwoptions are not present in tupledescs */
654
655 tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(oidtypeid));
656 if (!HeapTupleIsValid(tuple))
657 elog(ERROR, "cache lookup failed for type %u", oidtypeid);
658 typeForm = (Form_pg_type) GETSTRUCT(tuple);
659
660 att->atttypid = oidtypeid;
661 att->attlen = typeForm->typlen;
662 att->attbyval = typeForm->typbyval;
663 att->attalign = typeForm->typalign;
664 att->attstorage = typeForm->typstorage;
665 att->attcollation = typeForm->typcollation;
666
667 ReleaseSysCache(tuple);
668}
669
670/*
671 * TupleDescInitBuiltinEntry
672 * Initialize a tuple descriptor without catalog access. Only
673 * a limited range of builtin types are supported.
674 */
675void
676TupleDescInitBuiltinEntry(TupleDesc desc,
677 AttrNumber attributeNumber,
678 const char *attributeName,
679 Oid oidtypeid,
680 int32 typmod,
681 int attdim)
682{
683 Form_pg_attribute att;
684
685 /* sanity checks */
686 AssertArg(PointerIsValid(desc));
687 AssertArg(attributeNumber >= 1);
688 AssertArg(attributeNumber <= desc->natts);
689
690 /* initialize the attribute fields */
691 att = TupleDescAttr(desc, attributeNumber - 1);
692 att->attrelid = 0; /* dummy value */
693
694 /* unlike TupleDescInitEntry, we require an attribute name */
695 Assert(attributeName != NULL);
696 namestrcpy(&(att->attname), attributeName);
697
698 att->attstattarget = -1;
699 att->attcacheoff = -1;
700 att->atttypmod = typmod;
701
702 att->attnum = attributeNumber;
703 att->attndims = attdim;
704
705 att->attnotnull = false;
706 att->atthasdef = false;
707 att->atthasmissing = false;
708 att->attidentity = '\0';
709 att->attgenerated = '\0';
710 att->attisdropped = false;
711 att->attislocal = true;
712 att->attinhcount = 0;
713 /* attacl, attoptions and attfdwoptions are not present in tupledescs */
714
715 att->atttypid = oidtypeid;
716
717 /*
718 * Our goal here is to support just enough types to let basic builtin
719 * commands work without catalog access - e.g. so that we can do certain
720 * things even in processes that are not connected to a database.
721 */
722 switch (oidtypeid)
723 {
724 case TEXTOID:
725 case TEXTARRAYOID:
726 att->attlen = -1;
727 att->attbyval = false;
728 att->attalign = 'i';
729 att->attstorage = 'x';
730 att->attcollation = DEFAULT_COLLATION_OID;
731 break;
732
733 case BOOLOID:
734 att->attlen = 1;
735 att->attbyval = true;
736 att->attalign = 'c';
737 att->attstorage = 'p';
738 att->attcollation = InvalidOid;
739 break;
740
741 case INT4OID:
742 att->attlen = 4;
743 att->attbyval = true;
744 att->attalign = 'i';
745 att->attstorage = 'p';
746 att->attcollation = InvalidOid;
747 break;
748
749 case INT8OID:
750 att->attlen = 8;
751 att->attbyval = FLOAT8PASSBYVAL;
752 att->attalign = 'd';
753 att->attstorage = 'p';
754 att->attcollation = InvalidOid;
755 break;
756
757 default:
758 elog(ERROR, "unsupported type %u", oidtypeid);
759 }
760}
761
762/*
763 * TupleDescInitEntryCollation
764 *
765 * Assign a nondefault collation to a previously initialized tuple descriptor
766 * entry.
767 */
768void
769TupleDescInitEntryCollation(TupleDesc desc,
770 AttrNumber attributeNumber,
771 Oid collationid)
772{
773 /*
774 * sanity checks
775 */
776 AssertArg(PointerIsValid(desc));
777 AssertArg(attributeNumber >= 1);
778 AssertArg(attributeNumber <= desc->natts);
779
780 TupleDescAttr(desc, attributeNumber - 1)->attcollation = collationid;
781}
782
783
784/*
785 * BuildDescForRelation
786 *
787 * Given a relation schema (list of ColumnDef nodes), build a TupleDesc.
788 *
789 * Note: the default assumption is no OIDs; caller may modify the returned
790 * TupleDesc if it wants OIDs. Also, tdtypeid will need to be filled in
791 * later on.
792 */
793TupleDesc
794BuildDescForRelation(List *schema)
795{
796 int natts;
797 AttrNumber attnum;
798 ListCell *l;
799 TupleDesc desc;
800 bool has_not_null;
801 char *attname;
802 Oid atttypid;
803 int32 atttypmod;
804 Oid attcollation;
805 int attdim;
806
807 /*
808 * allocate a new tuple descriptor
809 */
810 natts = list_length(schema);
811 desc = CreateTemplateTupleDesc(natts);
812 has_not_null = false;
813
814 attnum = 0;
815
816 foreach(l, schema)
817 {
818 ColumnDef *entry = lfirst(l);
819 AclResult aclresult;
820 Form_pg_attribute att;
821
822 /*
823 * for each entry in the list, get the name and type information from
824 * the list and have TupleDescInitEntry fill in the attribute
825 * information we need.
826 */
827 attnum++;
828
829 attname = entry->colname;
830 typenameTypeIdAndMod(NULL, entry->typeName, &atttypid, &atttypmod);
831
832 aclresult = pg_type_aclcheck(atttypid, GetUserId(), ACL_USAGE);
833 if (aclresult != ACLCHECK_OK)
834 aclcheck_error_type(aclresult, atttypid);
835
836 attcollation = GetColumnDefCollation(NULL, entry, atttypid);
837 attdim = list_length(entry->typeName->arrayBounds);
838
839 if (entry->typeName->setof)
840 ereport(ERROR,
841 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
842 errmsg("column \"%s\" cannot be declared SETOF",
843 attname)));
844
845 TupleDescInitEntry(desc, attnum, attname,
846 atttypid, atttypmod, attdim);
847 att = TupleDescAttr(desc, attnum - 1);
848
849 /* Override TupleDescInitEntry's settings as requested */
850 TupleDescInitEntryCollation(desc, attnum, attcollation);
851 if (entry->storage)
852 att->attstorage = entry->storage;
853
854 /* Fill in additional stuff not handled by TupleDescInitEntry */
855 att->attnotnull = entry->is_not_null;
856 has_not_null |= entry->is_not_null;
857 att->attislocal = entry->is_local;
858 att->attinhcount = entry->inhcount;
859 }
860
861 if (has_not_null)
862 {
863 TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
864
865 constr->has_not_null = true;
866 constr->has_generated_stored = false;
867 constr->defval = NULL;
868 constr->missing = NULL;
869 constr->num_defval = 0;
870 constr->check = NULL;
871 constr->num_check = 0;
872 desc->constr = constr;
873 }
874 else
875 {
876 desc->constr = NULL;
877 }
878
879 return desc;
880}
881
882/*
883 * BuildDescFromLists
884 *
885 * Build a TupleDesc given lists of column names (as String nodes),
886 * column type OIDs, typmods, and collation OIDs.
887 *
888 * No constraints are generated.
889 *
890 * This is essentially a cut-down version of BuildDescForRelation for use
891 * with functions returning RECORD.
892 */
893TupleDesc
894BuildDescFromLists(List *names, List *types, List *typmods, List *collations)
895{
896 int natts;
897 AttrNumber attnum;
898 ListCell *l1;
899 ListCell *l2;
900 ListCell *l3;
901 ListCell *l4;
902 TupleDesc desc;
903
904 natts = list_length(names);
905 Assert(natts == list_length(types));
906 Assert(natts == list_length(typmods));
907 Assert(natts == list_length(collations));
908
909 /*
910 * allocate a new tuple descriptor
911 */
912 desc = CreateTemplateTupleDesc(natts);
913
914 attnum = 0;
915 forfour(l1, names, l2, types, l3, typmods, l4, collations)
916 {
917 char *attname = strVal(lfirst(l1));
918 Oid atttypid = lfirst_oid(l2);
919 int32 atttypmod = lfirst_int(l3);
920 Oid attcollation = lfirst_oid(l4);
921
922 attnum++;
923
924 TupleDescInitEntry(desc, attnum, attname, atttypid, atttypmod, 0);
925 TupleDescInitEntryCollation(desc, attnum, attcollation);
926 }
927
928 return desc;
929}
930