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 bool
420 {
421  int i,
422  n;
423 
424  if (tupdesc1->natts != tupdesc2->natts)
425  return false;
426  if (tupdesc1->tdtypeid != tupdesc2->tdtypeid)
427  return false;
428 
429  /* tdtypmod and tdrefcount are not checked */
430 
431  for (i = 0; i < tupdesc1->natts; i++)
432  {
433  Form_pg_attribute attr1 = TupleDescAttr(tupdesc1, i);
434  Form_pg_attribute attr2 = TupleDescAttr(tupdesc2, i);
435 
436  /*
437  * We do not need to check every single field here: we can disregard
438  * attrelid and attnum (which were used to place the row in the attrs
439  * array in the first place). It might look like we could dispense
440  * with checking attlen/attbyval/attalign, since these are derived
441  * from atttypid; but in the case of dropped columns we must check
442  * them (since atttypid will be zero for all dropped columns) and in
443  * general it seems safer to check them always.
444  *
445  * attcacheoff must NOT be checked since it's possibly not set in both
446  * copies. We also intentionally ignore atthasmissing, since that's
447  * not very relevant in tupdescs, which lack the attmissingval field.
448  */
449  if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0)
450  return false;
451  if (attr1->atttypid != attr2->atttypid)
452  return false;
453  if (attr1->attlen != attr2->attlen)
454  return false;
455  if (attr1->attndims != attr2->attndims)
456  return false;
457  if (attr1->atttypmod != attr2->atttypmod)
458  return false;
459  if (attr1->attbyval != attr2->attbyval)
460  return false;
461  if (attr1->attalign != attr2->attalign)
462  return false;
463  if (attr1->attstorage != attr2->attstorage)
464  return false;
465  if (attr1->attcompression != attr2->attcompression)
466  return false;
467  if (attr1->attnotnull != attr2->attnotnull)
468  return false;
469  if (attr1->atthasdef != attr2->atthasdef)
470  return false;
471  if (attr1->attidentity != attr2->attidentity)
472  return false;
473  if (attr1->attgenerated != attr2->attgenerated)
474  return false;
475  if (attr1->attisdropped != attr2->attisdropped)
476  return false;
477  if (attr1->attislocal != attr2->attislocal)
478  return false;
479  if (attr1->attinhcount != attr2->attinhcount)
480  return false;
481  if (attr1->attcollation != attr2->attcollation)
482  return false;
483  /* variable-length fields are not even present... */
484  }
485 
486  if (tupdesc1->constr != NULL)
487  {
488  TupleConstr *constr1 = tupdesc1->constr;
489  TupleConstr *constr2 = tupdesc2->constr;
490 
491  if (constr2 == NULL)
492  return false;
493  if (constr1->has_not_null != constr2->has_not_null)
494  return false;
495  if (constr1->has_generated_stored != constr2->has_generated_stored)
496  return false;
497  n = constr1->num_defval;
498  if (n != (int) constr2->num_defval)
499  return false;
500  /* We assume here that both AttrDefault arrays are in adnum order */
501  for (i = 0; i < n; i++)
502  {
503  AttrDefault *defval1 = constr1->defval + i;
504  AttrDefault *defval2 = constr2->defval + i;
505 
506  if (defval1->adnum != defval2->adnum)
507  return false;
508  if (strcmp(defval1->adbin, defval2->adbin) != 0)
509  return false;
510  }
511  if (constr1->missing)
512  {
513  if (!constr2->missing)
514  return false;
515  for (i = 0; i < tupdesc1->natts; i++)
516  {
517  AttrMissing *missval1 = constr1->missing + i;
518  AttrMissing *missval2 = constr2->missing + i;
519 
520  if (missval1->am_present != missval2->am_present)
521  return false;
522  if (missval1->am_present)
523  {
524  Form_pg_attribute missatt1 = TupleDescAttr(tupdesc1, i);
525 
526  if (!datumIsEqual(missval1->am_value, missval2->am_value,
527  missatt1->attbyval, missatt1->attlen))
528  return false;
529  }
530  }
531  }
532  else if (constr2->missing)
533  return false;
534  n = constr1->num_check;
535  if (n != (int) constr2->num_check)
536  return false;
537 
538  /*
539  * Similarly, we rely here on the ConstrCheck entries being sorted by
540  * name. If there are duplicate names, the outcome of the comparison
541  * is uncertain, but that should not happen.
542  */
543  for (i = 0; i < n; i++)
544  {
545  ConstrCheck *check1 = constr1->check + i;
546  ConstrCheck *check2 = constr2->check + i;
547 
548  if (!(strcmp(check1->ccname, check2->ccname) == 0 &&
549  strcmp(check1->ccbin, check2->ccbin) == 0 &&
550  check1->ccvalid == check2->ccvalid &&
551  check1->ccnoinherit == check2->ccnoinherit))
552  return false;
553  }
554  }
555  else if (tupdesc2->constr != NULL)
556  return false;
557  return true;
558 }
559 
560 /*
561  * equalRowTypes
562  *
563  * This determines whether two tuple descriptors have equal row types. This
564  * only checks those fields in pg_attribute that are applicable for row types,
565  * while ignoring those fields that define the physical row storage or those
566  * that define table column metadata.
567  *
568  * Specifically, this checks:
569  *
570  * - same number of attributes
571  * - same composite type ID (but could both be zero)
572  * - corresponding attributes (in order) have same the name, type, typmod,
573  * collation
574  *
575  * This is used to check whether two record types are compatible, whether
576  * function return row types are the same, and other similar situations.
577  *
578  * (XXX There was some discussion whether attndims should be checked here, but
579  * for now it has been decided not to.)
580  *
581  * Note: We deliberately do not check the tdtypmod field. This allows
582  * typcache.c to use this routine to see if a cached record type matches a
583  * requested type.
584  */
585 bool
586 equalRowTypes(TupleDesc tupdesc1, TupleDesc tupdesc2)
587 {
588  if (tupdesc1->natts != tupdesc2->natts)
589  return false;
590  if (tupdesc1->tdtypeid != tupdesc2->tdtypeid)
591  return false;
592 
593  for (int i = 0; i < tupdesc1->natts; i++)
594  {
595  Form_pg_attribute attr1 = TupleDescAttr(tupdesc1, i);
596  Form_pg_attribute attr2 = TupleDescAttr(tupdesc2, i);
597 
598  if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0)
599  return false;
600  if (attr1->atttypid != attr2->atttypid)
601  return false;
602  if (attr1->atttypmod != attr2->atttypmod)
603  return false;
604  if (attr1->attcollation != attr2->attcollation)
605  return false;
606 
607  /* Record types derived from tables could have dropped fields. */
608  if (attr1->attisdropped != attr2->attisdropped)
609  return false;
610  }
611 
612  return true;
613 }
614 
615 /*
616  * hashRowType
617  *
618  * If two tuple descriptors would be considered equal by equalRowTypes()
619  * then their hash value will be equal according to this function.
620  */
621 uint32
623 {
624  uint32 s;
625  int i;
626 
627  s = hash_combine(0, hash_uint32(desc->natts));
628  s = hash_combine(s, hash_uint32(desc->tdtypeid));
629  for (i = 0; i < desc->natts; ++i)
630  s = hash_combine(s, hash_uint32(TupleDescAttr(desc, i)->atttypid));
631 
632  return s;
633 }
634 
635 /*
636  * TupleDescInitEntry
637  * This function initializes a single attribute structure in
638  * a previously allocated tuple descriptor.
639  *
640  * If attributeName is NULL, the attname field is set to an empty string
641  * (this is for cases where we don't know or need a name for the field).
642  * Also, some callers use this function to change the datatype-related fields
643  * in an existing tupdesc; they pass attributeName = NameStr(att->attname)
644  * to indicate that the attname field shouldn't be modified.
645  *
646  * Note that attcollation is set to the default for the specified datatype.
647  * If a nondefault collation is needed, insert it afterwards using
648  * TupleDescInitEntryCollation.
649  */
650 void
652  AttrNumber attributeNumber,
653  const char *attributeName,
654  Oid oidtypeid,
655  int32 typmod,
656  int attdim)
657 {
658  HeapTuple tuple;
659  Form_pg_type typeForm;
660  Form_pg_attribute att;
661 
662  /*
663  * sanity checks
664  */
665  Assert(PointerIsValid(desc));
666  Assert(attributeNumber >= 1);
667  Assert(attributeNumber <= desc->natts);
668  Assert(attdim >= 0);
669  Assert(attdim <= PG_INT16_MAX);
670 
671  /*
672  * initialize the attribute fields
673  */
674  att = TupleDescAttr(desc, attributeNumber - 1);
675 
676  att->attrelid = 0; /* dummy value */
677 
678  /*
679  * Note: attributeName can be NULL, because the planner doesn't always
680  * fill in valid resname values in targetlists, particularly for resjunk
681  * attributes. Also, do nothing if caller wants to re-use the old attname.
682  */
683  if (attributeName == NULL)
684  MemSet(NameStr(att->attname), 0, NAMEDATALEN);
685  else if (attributeName != NameStr(att->attname))
686  namestrcpy(&(att->attname), attributeName);
687 
688  att->attcacheoff = -1;
689  att->atttypmod = typmod;
690 
691  att->attnum = attributeNumber;
692  att->attndims = attdim;
693 
694  att->attnotnull = false;
695  att->atthasdef = false;
696  att->atthasmissing = false;
697  att->attidentity = '\0';
698  att->attgenerated = '\0';
699  att->attisdropped = false;
700  att->attislocal = true;
701  att->attinhcount = 0;
702  /* variable-length fields are not present in tupledescs */
703 
704  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(oidtypeid));
705  if (!HeapTupleIsValid(tuple))
706  elog(ERROR, "cache lookup failed for type %u", oidtypeid);
707  typeForm = (Form_pg_type) GETSTRUCT(tuple);
708 
709  att->atttypid = oidtypeid;
710  att->attlen = typeForm->typlen;
711  att->attbyval = typeForm->typbyval;
712  att->attalign = typeForm->typalign;
713  att->attstorage = typeForm->typstorage;
714  att->attcompression = InvalidCompressionMethod;
715  att->attcollation = typeForm->typcollation;
716 
717  ReleaseSysCache(tuple);
718 }
719 
720 /*
721  * TupleDescInitBuiltinEntry
722  * Initialize a tuple descriptor without catalog access. Only
723  * a limited range of builtin types are supported.
724  */
725 void
727  AttrNumber attributeNumber,
728  const char *attributeName,
729  Oid oidtypeid,
730  int32 typmod,
731  int attdim)
732 {
733  Form_pg_attribute att;
734 
735  /* sanity checks */
736  Assert(PointerIsValid(desc));
737  Assert(attributeNumber >= 1);
738  Assert(attributeNumber <= desc->natts);
739  Assert(attdim >= 0);
740  Assert(attdim <= PG_INT16_MAX);
741 
742  /* initialize the attribute fields */
743  att = TupleDescAttr(desc, attributeNumber - 1);
744  att->attrelid = 0; /* dummy value */
745 
746  /* unlike TupleDescInitEntry, we require an attribute name */
747  Assert(attributeName != NULL);
748  namestrcpy(&(att->attname), attributeName);
749 
750  att->attcacheoff = -1;
751  att->atttypmod = typmod;
752 
753  att->attnum = attributeNumber;
754  att->attndims = attdim;
755 
756  att->attnotnull = false;
757  att->atthasdef = false;
758  att->atthasmissing = false;
759  att->attidentity = '\0';
760  att->attgenerated = '\0';
761  att->attisdropped = false;
762  att->attislocal = true;
763  att->attinhcount = 0;
764  /* variable-length fields are not present in tupledescs */
765 
766  att->atttypid = oidtypeid;
767 
768  /*
769  * Our goal here is to support just enough types to let basic builtin
770  * commands work without catalog access - e.g. so that we can do certain
771  * things even in processes that are not connected to a database.
772  */
773  switch (oidtypeid)
774  {
775  case TEXTOID:
776  case TEXTARRAYOID:
777  att->attlen = -1;
778  att->attbyval = false;
779  att->attalign = TYPALIGN_INT;
780  att->attstorage = TYPSTORAGE_EXTENDED;
781  att->attcompression = InvalidCompressionMethod;
782  att->attcollation = DEFAULT_COLLATION_OID;
783  break;
784 
785  case BOOLOID:
786  att->attlen = 1;
787  att->attbyval = true;
788  att->attalign = TYPALIGN_CHAR;
789  att->attstorage = TYPSTORAGE_PLAIN;
790  att->attcompression = InvalidCompressionMethod;
791  att->attcollation = InvalidOid;
792  break;
793 
794  case INT4OID:
795  att->attlen = 4;
796  att->attbyval = true;
797  att->attalign = TYPALIGN_INT;
798  att->attstorage = TYPSTORAGE_PLAIN;
799  att->attcompression = InvalidCompressionMethod;
800  att->attcollation = InvalidOid;
801  break;
802 
803  case INT8OID:
804  att->attlen = 8;
805  att->attbyval = FLOAT8PASSBYVAL;
806  att->attalign = TYPALIGN_DOUBLE;
807  att->attstorage = TYPSTORAGE_PLAIN;
808  att->attcompression = InvalidCompressionMethod;
809  att->attcollation = InvalidOid;
810  break;
811 
812  case OIDOID:
813  att->attlen = 4;
814  att->attbyval = true;
815  att->attalign = TYPALIGN_INT;
816  att->attstorage = TYPSTORAGE_PLAIN;
817  att->attcompression = InvalidCompressionMethod;
818  att->attcollation = InvalidOid;
819  break;
820 
821  default:
822  elog(ERROR, "unsupported type %u", oidtypeid);
823  }
824 }
825 
826 /*
827  * TupleDescInitEntryCollation
828  *
829  * Assign a nondefault collation to a previously initialized tuple descriptor
830  * entry.
831  */
832 void
834  AttrNumber attributeNumber,
835  Oid collationid)
836 {
837  /*
838  * sanity checks
839  */
840  Assert(PointerIsValid(desc));
841  Assert(attributeNumber >= 1);
842  Assert(attributeNumber <= desc->natts);
843 
844  TupleDescAttr(desc, attributeNumber - 1)->attcollation = collationid;
845 }
846 
847 /*
848  * BuildDescFromLists
849  *
850  * Build a TupleDesc given lists of column names (as String nodes),
851  * column type OIDs, typmods, and collation OIDs.
852  *
853  * No constraints are generated.
854  *
855  * This is for use with functions returning RECORD.
856  */
857 TupleDesc
858 BuildDescFromLists(const List *names, const List *types, const List *typmods, const List *collations)
859 {
860  int natts;
862  ListCell *l1;
863  ListCell *l2;
864  ListCell *l3;
865  ListCell *l4;
866  TupleDesc desc;
867 
868  natts = list_length(names);
869  Assert(natts == list_length(types));
870  Assert(natts == list_length(typmods));
871  Assert(natts == list_length(collations));
872 
873  /*
874  * allocate a new tuple descriptor
875  */
876  desc = CreateTemplateTupleDesc(natts);
877 
878  attnum = 0;
879  forfour(l1, names, l2, types, l3, typmods, l4, collations)
880  {
881  char *attname = strVal(lfirst(l1));
882  Oid atttypid = lfirst_oid(l2);
883  int32 atttypmod = lfirst_int(l3);
884  Oid attcollation = lfirst_oid(l4);
885 
886  attnum++;
887 
888  TupleDescInitEntry(desc, attnum, attname, atttypid, atttypmod, 0);
889  TupleDescInitEntryCollation(desc, attnum, attcollation);
890  }
891 
892  return desc;
893 }
894 
895 /*
896  * Get default expression (or NULL if none) for the given attribute number.
897  */
898 Node *
900 {
901  Node *result = NULL;
902 
903  if (tupdesc->constr)
904  {
905  AttrDefault *attrdef = tupdesc->constr->defval;
906 
907  for (int i = 0; i < tupdesc->constr->num_defval; i++)
908  {
909  if (attrdef[i].adnum == attnum)
910  {
911  result = stringToNode(attrdef[i].adbin);
912  break;
913  }
914  }
915  }
916 
917  return result;
918 }
919 
920 /* ResourceOwner callbacks */
921 
922 static void
924 {
925  TupleDesc tupdesc = (TupleDesc) DatumGetPointer(res);
926 
927  /* Like DecrTupleDescRefCount, but don't call ResourceOwnerForget() */
928  Assert(tupdesc->tdrefcount > 0);
929  if (--tupdesc->tdrefcount == 0)
930  FreeTupleDesc(tupdesc);
931 }
932 
933 static char *
935 {
936  TupleDesc tupdesc = (TupleDesc) DatumGetPointer(res);
937 
938  return psprintf("TupleDesc %p (%u,%d)",
939  tupdesc, tupdesc->tdtypeid, tupdesc->tdtypmod);
940 }
int16 AttrNumber
Definition: attnum.h:21
#define NameStr(name)
Definition: c.h:733
unsigned int uint32
Definition: c.h:493
signed int int32
Definition: c.h:481
#define PointerIsValid(pointer)
Definition: c.h:750
#define FLOAT8PASSBYVAL
Definition: c.h:622
#define MemSet(start, val, len)
Definition: c.h:1007
#define PG_INT16_MAX
Definition: c.h:573
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
#define elog(elevel,...)
Definition: elog.h:224
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:1683
void pfree(void *pointer)
Definition: mcxt.c:1508
void * palloc0(Size size)
Definition: mcxt.c:1334
void * palloc(Size size)
Definition: mcxt.c:1304
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:266
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:218
#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:899
static void ResOwnerReleaseTupleDesc(Datum res)
Definition: tupdesc.c:923
uint32 hashRowType(TupleDesc desc)
Definition: tupdesc.c:622
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:726
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:858
bool equalRowTypes(TupleDesc tupdesc1, TupleDesc tupdesc2)
Definition: tupdesc.c:586
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition: tupdesc.c:833
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:651
bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
Definition: tupdesc.c:419
void TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno, TupleDesc src, AttrNumber srcAttno)
Definition: tupdesc.c:289
static char * ResOwnerPrintTupleDesc(Datum res)
Definition: tupdesc.c:934
#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