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-2023, 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  Assert(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  */
276  Assert(PointerIsValid(src));
277  Assert(PointerIsValid(dst));
278  Assert(srcAttno >= 1);
279  Assert(srcAttno <= src->natts);
280  Assert(dstAttno >= 1);
281  Assert(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  Assert(PointerIsValid(desc));
598  Assert(attributeNumber >= 1);
599  Assert(attributeNumber <= desc->natts);
600  Assert(attdim >= 0);
601  Assert(attdim <= PG_INT16_MAX);
602 
603  /*
604  * initialize the attribute fields
605  */
606  att = TupleDescAttr(desc, attributeNumber - 1);
607 
608  att->attrelid = 0; /* dummy value */
609 
610  /*
611  * Note: attributeName can be NULL, because the planner doesn't always
612  * fill in valid resname values in targetlists, particularly for resjunk
613  * attributes. Also, do nothing if caller wants to re-use the old attname.
614  */
615  if (attributeName == NULL)
616  MemSet(NameStr(att->attname), 0, NAMEDATALEN);
617  else if (attributeName != NameStr(att->attname))
618  namestrcpy(&(att->attname), attributeName);
619 
620  att->attstattarget = -1;
621  att->attcacheoff = -1;
622  att->atttypmod = typmod;
623 
624  att->attnum = attributeNumber;
625  att->attndims = attdim;
626 
627  att->attnotnull = false;
628  att->atthasdef = false;
629  att->atthasmissing = false;
630  att->attidentity = '\0';
631  att->attgenerated = '\0';
632  att->attisdropped = false;
633  att->attislocal = true;
634  att->attinhcount = 0;
635  /* variable-length fields are not present in tupledescs */
636 
637  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(oidtypeid));
638  if (!HeapTupleIsValid(tuple))
639  elog(ERROR, "cache lookup failed for type %u", oidtypeid);
640  typeForm = (Form_pg_type) GETSTRUCT(tuple);
641 
642  att->atttypid = oidtypeid;
643  att->attlen = typeForm->typlen;
644  att->attbyval = typeForm->typbyval;
645  att->attalign = typeForm->typalign;
646  att->attstorage = typeForm->typstorage;
647  att->attcompression = InvalidCompressionMethod;
648  att->attcollation = typeForm->typcollation;
649 
650  ReleaseSysCache(tuple);
651 }
652 
653 /*
654  * TupleDescInitBuiltinEntry
655  * Initialize a tuple descriptor without catalog access. Only
656  * a limited range of builtin types are supported.
657  */
658 void
660  AttrNumber attributeNumber,
661  const char *attributeName,
662  Oid oidtypeid,
663  int32 typmod,
664  int attdim)
665 {
666  Form_pg_attribute att;
667 
668  /* sanity checks */
669  Assert(PointerIsValid(desc));
670  Assert(attributeNumber >= 1);
671  Assert(attributeNumber <= desc->natts);
672  Assert(attdim >= 0);
673  Assert(attdim <= PG_INT16_MAX);
674 
675  /* initialize the attribute fields */
676  att = TupleDescAttr(desc, attributeNumber - 1);
677  att->attrelid = 0; /* dummy value */
678 
679  /* unlike TupleDescInitEntry, we require an attribute name */
680  Assert(attributeName != NULL);
681  namestrcpy(&(att->attname), attributeName);
682 
683  att->attstattarget = -1;
684  att->attcacheoff = -1;
685  att->atttypmod = typmod;
686 
687  att->attnum = attributeNumber;
688  att->attndims = attdim;
689 
690  att->attnotnull = false;
691  att->atthasdef = false;
692  att->atthasmissing = false;
693  att->attidentity = '\0';
694  att->attgenerated = '\0';
695  att->attisdropped = false;
696  att->attislocal = true;
697  att->attinhcount = 0;
698  /* variable-length fields are not present in tupledescs */
699 
700  att->atttypid = oidtypeid;
701 
702  /*
703  * Our goal here is to support just enough types to let basic builtin
704  * commands work without catalog access - e.g. so that we can do certain
705  * things even in processes that are not connected to a database.
706  */
707  switch (oidtypeid)
708  {
709  case TEXTOID:
710  case TEXTARRAYOID:
711  att->attlen = -1;
712  att->attbyval = false;
713  att->attalign = TYPALIGN_INT;
714  att->attstorage = TYPSTORAGE_EXTENDED;
715  att->attcompression = InvalidCompressionMethod;
716  att->attcollation = DEFAULT_COLLATION_OID;
717  break;
718 
719  case BOOLOID:
720  att->attlen = 1;
721  att->attbyval = true;
722  att->attalign = TYPALIGN_CHAR;
723  att->attstorage = TYPSTORAGE_PLAIN;
724  att->attcompression = InvalidCompressionMethod;
725  att->attcollation = InvalidOid;
726  break;
727 
728  case INT4OID:
729  att->attlen = 4;
730  att->attbyval = true;
731  att->attalign = TYPALIGN_INT;
732  att->attstorage = TYPSTORAGE_PLAIN;
733  att->attcompression = InvalidCompressionMethod;
734  att->attcollation = InvalidOid;
735  break;
736 
737  case INT8OID:
738  att->attlen = 8;
739  att->attbyval = FLOAT8PASSBYVAL;
740  att->attalign = TYPALIGN_DOUBLE;
741  att->attstorage = TYPSTORAGE_PLAIN;
742  att->attcompression = InvalidCompressionMethod;
743  att->attcollation = InvalidOid;
744  break;
745 
746  case OIDOID:
747  att->attlen = 4;
748  att->attbyval = true;
749  att->attalign = TYPALIGN_INT;
750  att->attstorage = TYPSTORAGE_PLAIN;
751  att->attcompression = InvalidCompressionMethod;
752  att->attcollation = InvalidOid;
753  break;
754 
755  default:
756  elog(ERROR, "unsupported type %u", oidtypeid);
757  }
758 }
759 
760 /*
761  * TupleDescInitEntryCollation
762  *
763  * Assign a nondefault collation to a previously initialized tuple descriptor
764  * entry.
765  */
766 void
768  AttrNumber attributeNumber,
769  Oid collationid)
770 {
771  /*
772  * sanity checks
773  */
774  Assert(PointerIsValid(desc));
775  Assert(attributeNumber >= 1);
776  Assert(attributeNumber <= desc->natts);
777 
778  TupleDescAttr(desc, attributeNumber - 1)->attcollation = collationid;
779 }
780 
781 
782 /*
783  * BuildDescForRelation
784  *
785  * Given a list of ColumnDef nodes, build a TupleDesc.
786  *
787  * Note: tdtypeid will need to be filled in later on.
788  */
789 TupleDesc
790 BuildDescForRelation(const List *columns)
791 {
792  int natts;
794  ListCell *l;
795  TupleDesc desc;
796  bool has_not_null;
797  char *attname;
798  Oid atttypid;
799  int32 atttypmod;
800  Oid attcollation;
801  int attdim;
802 
803  /*
804  * allocate a new tuple descriptor
805  */
806  natts = list_length(columns);
807  desc = CreateTemplateTupleDesc(natts);
808  has_not_null = false;
809 
810  attnum = 0;
811 
812  foreach(l, columns)
813  {
814  ColumnDef *entry = lfirst(l);
815  AclResult aclresult;
816  Form_pg_attribute att;
817 
818  /*
819  * for each entry in the list, get the name and type information from
820  * the list and have TupleDescInitEntry fill in the attribute
821  * information we need.
822  */
823  attnum++;
824 
825  attname = entry->colname;
826  typenameTypeIdAndMod(NULL, entry->typeName, &atttypid, &atttypmod);
827 
828  aclresult = object_aclcheck(TypeRelationId, atttypid, GetUserId(), ACL_USAGE);
829  if (aclresult != ACLCHECK_OK)
830  aclcheck_error_type(aclresult, atttypid);
831 
832  attcollation = GetColumnDefCollation(NULL, entry, atttypid);
833  attdim = list_length(entry->typeName->arrayBounds);
834  if (attdim > PG_INT16_MAX)
835  ereport(ERROR,
836  errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
837  errmsg("too many array dimensions"));
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 
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  */
893 TupleDesc
894 BuildDescFromLists(const List *names, const List *types, const List *typmods, const List *collations)
895 {
896  int natts;
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 
931 /*
932  * Get default expression (or NULL if none) for the given attribute number.
933  */
934 Node *
936 {
937  Node *result = NULL;
938 
939  if (tupdesc->constr)
940  {
941  AttrDefault *attrdef = tupdesc->constr->defval;
942 
943  for (int i = 0; i < tupdesc->constr->num_defval; i++)
944  {
945  if (attrdef[i].adnum == attnum)
946  {
947  result = stringToNode(attrdef[i].adbin);
948  break;
949  }
950  }
951  }
952 
953  return result;
954 }
AclResult
Definition: acl.h:181
@ ACLCHECK_OK
Definition: acl.h:182
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3760
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:2988
int16 AttrNumber
Definition: attnum.h:21
#define NameStr(name)
Definition: c.h:735
unsigned int uint32
Definition: c.h:495
signed int int32
Definition: c.h:483
#define PointerIsValid(pointer)
Definition: c.h:752
#define FLOAT8PASSBYVAL
Definition: c.h:624
#define MemSet(start, val, len)
Definition: c.h:1009
#define PG_INT16_MAX
Definition: c.h:575
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:132
bool datumIsEqual(Datum value1, Datum value2, bool typByVal, int typLen)
Definition: datum.c:223
struct typedefs * types
Definition: ecpg.c:29
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
static Datum hash_uint32(uint32 k)
Definition: hashfn.h:43
static uint32 hash_combine(uint32 a, uint32 b)
Definition: hashfn.h:68
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')
char * pstrdup(const char *in)
Definition: mcxt.c:1644
void pfree(void *pointer)
Definition: mcxt.c:1456
void * palloc0(Size size)
Definition: mcxt.c:1257
void * palloc(Size size)
Definition: mcxt.c:1226
Oid GetUserId(void)
Definition: miscinit.c:509
void namestrcpy(Name name, const char *str)
Definition: name.c:233
void typenameTypeIdAndMod(ParseState *pstate, const TypeName *typeName, Oid *typeid_p, int32 *typmod_p)
Definition: parse_type.c:310
Oid GetColumnDefCollation(ParseState *pstate, ColumnDef *coldef, Oid typeOid)
Definition: parse_type.c:540
#define ACL_USAGE
Definition: parsenodes.h:91
FormData_pg_attribute
Definition: pg_attribute.h:193
NameData attname
Definition: pg_attribute.h:41
bool attbyval
Definition: pg_attribute.h:103
#define ATTRIBUTE_FIXED_PART_SIZE
Definition: pg_attribute.h:201
int16 attnum
Definition: pg_attribute.h:74
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
#define NAMEDATALEN
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
#define lfirst_int(lc)
Definition: pg_list.h:173
#define forfour(cell1, list1, cell2, list2, cell3, list3, cell4, list4)
Definition: pg_list.h:524
#define lfirst_oid(lc)
Definition: pg_list.h:174
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
void * stringToNode(const char *str)
Definition: read.c:90
ResourceOwner CurrentResourceOwner
Definition: resowner.c:147
void ResourceOwnerForgetTupleDesc(ResourceOwner owner, TupleDesc tupdesc)
Definition: resowner.c:1278
void ResourceOwnerRememberTupleDesc(ResourceOwner owner, TupleDesc tupdesc)
Definition: resowner.c:1269
void ResourceOwnerEnlargeTupleDescs(ResourceOwner owner)
Definition: resowner.c:1258
AttrNumber adnum
Definition: tupdesc.h:24
char * adbin
Definition: tupdesc.h:25
bool is_not_null
Definition: parsenodes.h:725
int inhcount
Definition: parsenodes.h:723
char * colname
Definition: parsenodes.h:720
TypeName * typeName
Definition: parsenodes.h:721
char storage
Definition: parsenodes.h:727
bool is_local
Definition: parsenodes.h:724
char * ccname
Definition: tupdesc.h:30
bool ccnoinherit
Definition: tupdesc.h:33
bool ccvalid
Definition: tupdesc.h:32
char * ccbin
Definition: tupdesc.h:31
Definition: pg_list.h:54
Definition: nodes.h:129
bool has_not_null
Definition: tupdesc.h:44
AttrDefault * defval
Definition: tupdesc.h:39
bool has_generated_stored
Definition: tupdesc.h:45
struct AttrMissing * missing
Definition: tupdesc.h:41
ConstrCheck * check
Definition: tupdesc.h:40
uint16 num_defval
Definition: tupdesc.h:42
uint16 num_check
Definition: tupdesc.h:43
int tdrefcount
Definition: tupdesc.h:84
TupleConstr * constr
Definition: tupdesc.h:85
int32 tdtypmod
Definition: tupdesc.h:83
Oid tdtypeid
Definition: tupdesc.h:82
bool setof
Definition: parsenodes.h:267
List * arrayBounds
Definition: parsenodes.h:271
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:868
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:820
@ TYPEOID
Definition: syscache.h:114
#define InvalidCompressionMethod
TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc)
Definition: tupdesc.c:151
void TupleDescCopy(TupleDesc dst, TupleDesc src)
Definition: tupdesc.c:229
void DecrTupleDescRefCount(TupleDesc tupdesc)
Definition: tupdesc.c:384
TupleDesc BuildDescForRelation(const List *columns)
Definition: tupdesc.c:790
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:309
void IncrTupleDescRefCount(TupleDesc tupdesc)
Definition: tupdesc.c:366
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:45
Node * TupleDescGetDefault(TupleDesc tupdesc, AttrNumber attnum)
Definition: tupdesc.c:935
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111
void TupleDescInitBuiltinEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:659
uint32 hashTupleDesc(TupleDesc desc)
Definition: tupdesc.c:554
TupleDesc BuildDescFromLists(const List *names, const List *types, const List *typmods, const List *collations)
Definition: tupdesc.c:894
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition: tupdesc.c:767
TupleDesc CreateTupleDesc(int natts, Form_pg_attribute *attrs)
Definition: tupdesc.c:90
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:583
bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
Definition: tupdesc.c:402
void TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno, TupleDesc src, AttrNumber srcAttno)
Definition: tupdesc.c:267
#define TupleDescSize(src)
Definition: tupdesc.h:102
struct TupleDescData * TupleDesc
Definition: tupdesc.h:89
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define strVal(v)
Definition: value.h:82