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