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