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