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