PostgreSQL Source Code  git master
tupdesc.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/toast_compression.h"
#include "access/tupdesc_details.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "common/hashfn.h"
#include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/resowner.h"
#include "utils/syscache.h"
Include dependency graph for tupdesc.c:

Go to the source code of this file.

Functions

static void ResOwnerReleaseTupleDesc (Datum res)
 
static char * ResOwnerPrintTupleDesc (Datum res)
 
static void ResourceOwnerRememberTupleDesc (ResourceOwner owner, TupleDesc tupdesc)
 
static void ResourceOwnerForgetTupleDesc (ResourceOwner owner, TupleDesc tupdesc)
 
TupleDesc CreateTemplateTupleDesc (int natts)
 
TupleDesc CreateTupleDesc (int natts, Form_pg_attribute *attrs)
 
TupleDesc CreateTupleDescCopy (TupleDesc tupdesc)
 
TupleDesc CreateTupleDescCopyConstr (TupleDesc tupdesc)
 
void TupleDescCopy (TupleDesc dst, TupleDesc src)
 
void TupleDescCopyEntry (TupleDesc dst, AttrNumber dstAttno, TupleDesc src, AttrNumber srcAttno)
 
void FreeTupleDesc (TupleDesc tupdesc)
 
void IncrTupleDescRefCount (TupleDesc tupdesc)
 
void DecrTupleDescRefCount (TupleDesc tupdesc)
 
bool equalTupleDescs (TupleDesc tupdesc1, TupleDesc tupdesc2)
 
bool equalRowTypes (TupleDesc tupdesc1, TupleDesc tupdesc2)
 
uint32 hashRowType (TupleDesc desc)
 
void TupleDescInitEntry (TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
 
void TupleDescInitBuiltinEntry (TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
 
void TupleDescInitEntryCollation (TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
 
TupleDesc BuildDescFromLists (const List *names, const List *types, const List *typmods, const List *collations)
 
NodeTupleDescGetDefault (TupleDesc tupdesc, AttrNumber attnum)
 

Variables

static const ResourceOwnerDesc tupdesc_resowner_desc
 

Function Documentation

◆ BuildDescFromLists()

TupleDesc BuildDescFromLists ( const List names,
const List types,
const List typmods,
const List collations 
)

Definition at line 858 of file tupdesc.c.

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 }
int16 AttrNumber
Definition: attnum.h:21
signed int int32
Definition: c.h:497
#define Assert(condition)
Definition: c.h:861
struct typedefs * types
Definition: ecpg.c:29
NameData attname
Definition: pg_attribute.h:41
int16 attnum
Definition: pg_attribute.h:74
#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
unsigned int Oid
Definition: postgres_ext.h:31
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:67
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition: tupdesc.c:833
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:651
#define strVal(v)
Definition: value.h:82

References Assert, attname, attnum, CreateTemplateTupleDesc(), forfour, lfirst, lfirst_int, lfirst_oid, list_length(), strVal, TupleDescInitEntry(), TupleDescInitEntryCollation(), and types.

Referenced by ExecInitFunctionScan(), ExecInitTableFuncScan(), and inline_set_returning_function().

◆ CreateTemplateTupleDesc()

TupleDesc CreateTemplateTupleDesc ( int  natts)

Definition at line 67 of file tupdesc.c.

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 }
void * palloc(Size size)
Definition: mcxt.c:1317
FormData_pg_attribute
Definition: pg_attribute.h:193
int tdrefcount
Definition: tupdesc.h:84
TupleConstr * constr
Definition: tupdesc.h:85
int32 tdtypmod
Definition: tupdesc.h:83
Oid tdtypeid
Definition: tupdesc.h:82
struct TupleDescData * TupleDesc
Definition: tupdesc.h:89

References Assert, TupleDescData::constr, FormData_pg_attribute, TupleDescData::natts, palloc(), TupleDescData::tdrefcount, TupleDescData::tdtypeid, and TupleDescData::tdtypmod.

Referenced by aclexplode(), addRangeTableEntryForFunction(), AllocateRelationDesc(), brtuple_disk_tupdesc(), build_function_result_tupdesc_d(), build_row_from_vars(), BuildDescForRelation(), BuildDescFromLists(), BuildHardcodedDescriptor(), ConstructTupleDescriptor(), create_toast_table(), CreateReplicationSlot(), CreateTupleDesc(), CreateTupleDescCopy(), CreateTupleDescCopyConstr(), dblink_get_pkey(), ExecInitFunctionScan(), ExecMakeTableFunctionResult(), ExecTypeFromExprList(), ExecTypeFromTLInternal(), expandRecordVariable(), ExplainResultDesc(), formrdesc(), get_expr_result_type(), GetPGVariableResultDesc(), gistrescan(), IdentifySystem(), init_sexpr(), initGinState(), injection_points_stats_fixed(), libpqrcv_processTuples(), load_relcache_init_file(), materializeResult(), ordered_set_startup(), pg_buffercache_pages(), pg_get_publication_tables(), pg_get_sequence_data(), pg_lock_status(), pg_prepared_xact(), pg_stat_file(), pg_stat_get_archiver(), pg_stat_get_backend_subxact(), pg_stat_get_replication_slot(), pg_stat_get_subscription_stats(), pg_stat_get_wal(), pg_visibility_tupdesc(), pg_walfile_name_offset(), ReadReplicationSlot(), SendTablespaceList(), SendTimeLineHistory(), SendXlogRecPtrResult(), show_all_settings(), ShowAllGUCConfig(), ShowGUCConfigOption(), StartReplication(), test_predtest(), tsvector_unnest(), and TypeGetTupleDesc().

◆ CreateTupleDesc()

TupleDesc CreateTupleDesc ( int  natts,
Form_pg_attribute attrs 
)

Definition at line 112 of file tupdesc.c.

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 }
int i
Definition: isn.c:73
#define ATTRIBUTE_FIXED_PART_SIZE
Definition: pg_attribute.h:201
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92

References ATTRIBUTE_FIXED_PART_SIZE, CreateTemplateTupleDesc(), i, and TupleDescAttr.

Referenced by AddNewAttributeTuples(), and InsertOneTuple().

◆ CreateTupleDescCopy()

TupleDesc CreateTupleDescCopy ( TupleDesc  tupdesc)

Definition at line 133 of file tupdesc.c.

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 }
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209

References CreateTemplateTupleDesc(), FormData_pg_attribute, i, TupleDescData::natts, TupleDescData::tdtypeid, TupleDescData::tdtypmod, and TupleDescAttr.

Referenced by assign_record_type_typmod(), BuildTupleHashTableExt(), connectby_text(), connectby_text_serial(), CopyCachedPlan(), crosstab(), crosstab_hash(), database_to_xmlschema_internal(), do_autovacuum(), ExecEvalWholeRowVar(), ExecInitForeignScan(), ExecInitFunctionScan(), ExecInsert(), ExecPrepareTuplestoreResult(), FetchPreparedStatementResultDesc(), fmgr_sql(), get_record_type_from_query(), get_tupdesc_for_join_scan_tuples(), GetAfterTriggersStoreSlot(), getSpGistTupleDesc(), gist_page_items(), init_sexpr(), InitMaterializedSRF(), make_expanded_record_from_exprecord(), make_expanded_record_from_tupdesc(), materializeResult(), PersistHoldablePortal(), plperl_return_next_internal(), plpgsql_exec_function(), pltcl_func_handler(), PLy_spi_execute_fetch_result(), populate_recordset_worker(), RelationBuildLocalRelation(), RelationNameGetTupleDesc(), RevalidateCachedQuery(), schema_to_xmlschema_internal(), spi_dest_startup(), storeRow(), update_cached_tupdesc(), and UtilityTupleDescriptor().

◆ CreateTupleDescCopyConstr()

TupleDesc CreateTupleDescCopyConstr ( TupleDesc  tupdesc)

Definition at line 173 of file tupdesc.c.

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 }
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:132
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void * palloc0(Size size)
Definition: mcxt.c:1347
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
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

References AttrDefault::adbin, AttrMissing::am_present, AttrMissing::am_value, ConstrCheck::ccbin, ConstrCheck::ccname, ConstrCheck::ccnoinherit, ConstrCheck::ccvalid, TupleConstr::check, TupleDescData::constr, CreateTemplateTupleDesc(), datumCopy(), TupleConstr::defval, FormData_pg_attribute, TupleConstr::has_generated_stored, TupleConstr::has_not_null, i, TupleConstr::missing, TupleDescData::natts, TupleConstr::num_check, TupleConstr::num_defval, palloc(), palloc0(), pstrdup(), TupleDescData::tdtypeid, TupleDescData::tdtypmod, and TupleDescAttr.

Referenced by ATGetQueueEntry(), CatalogCacheInitializeCache(), init_tuple_slot(), initGISTstate(), and lookup_rowtype_tupdesc_copy().

◆ DecrTupleDescRefCount()

void DecrTupleDescRefCount ( TupleDesc  tupdesc)

Definition at line 406 of file tupdesc.c.

407 {
408  Assert(tupdesc->tdrefcount > 0);
409 
411  if (--tupdesc->tdrefcount == 0)
412  FreeTupleDesc(tupdesc);
413 }
ResourceOwner CurrentResourceOwner
Definition: resowner.c:165
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:331
static void ResourceOwnerForgetTupleDesc(ResourceOwner owner, TupleDesc tupdesc)
Definition: tupdesc.c:54

References Assert, CurrentResourceOwner, FreeTupleDesc(), ResourceOwnerForgetTupleDesc(), and TupleDescData::tdrefcount.

Referenced by cache_record_field_properties(), and ExecEvalConvertRowtype().

◆ equalRowTypes()

bool equalRowTypes ( TupleDesc  tupdesc1,
TupleDesc  tupdesc2 
)

Definition at line 586 of file tupdesc.c.

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 }
#define NameStr(name)
Definition: c.h:749

References i, NameStr, TupleDescData::natts, TupleDescData::tdtypeid, and TupleDescAttr.

Referenced by acquire_inherited_sample_rows(), ProcedureCreate(), record_type_typmod_compare(), RevalidateCachedQuery(), and shared_record_table_compare().

◆ equalTupleDescs()

bool equalTupleDescs ( TupleDesc  tupdesc1,
TupleDesc  tupdesc2 
)

Definition at line 419 of file tupdesc.c.

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 }
bool datumIsEqual(Datum value1, Datum value2, bool typByVal, int typLen)
Definition: datum.c:223
AttrNumber adnum
Definition: tupdesc.h:24

References AttrDefault::adbin, AttrDefault::adnum, AttrMissing::am_present, AttrMissing::am_value, ConstrCheck::ccbin, ConstrCheck::ccname, ConstrCheck::ccnoinherit, ConstrCheck::ccvalid, TupleConstr::check, TupleDescData::constr, datumIsEqual(), TupleConstr::defval, TupleConstr::has_generated_stored, TupleConstr::has_not_null, i, TupleConstr::missing, NameStr, TupleDescData::natts, TupleConstr::num_check, TupleConstr::num_defval, TupleDescData::tdtypeid, and TupleDescAttr.

Referenced by RelationClearRelation(), and RelationFindReplTupleSeq().

◆ FreeTupleDesc()

void FreeTupleDesc ( TupleDesc  tupdesc)

Definition at line 331 of file tupdesc.c.

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 }
void pfree(void *pointer)
Definition: mcxt.c:1521
bool attbyval
Definition: pg_attribute.h:103
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312

References Assert, attbyval, TupleConstr::check, TupleDescData::constr, DatumGetPointer(), TupleConstr::defval, i, TupleConstr::missing, TupleDescData::natts, TupleConstr::num_check, TupleConstr::num_defval, pfree(), TupleDescData::tdrefcount, and TupleDescAttr.

Referenced by AddNewAttributeTuples(), AtEOXact_RelationCache(), DecrTupleDescRefCount(), ER_mc_callback(), ExecMakeTableFunctionResult(), ExecPrepareTuplestoreResult(), get_record_type_from_query(), ordered_set_startup(), PLy_result_dealloc(), RelationDestroyRelation(), ResOwnerReleaseTupleDesc(), RevalidateCachedQuery(), spgendscan(), TypeCacheRelCallback(), update_cached_tupdesc(), and walrcv_clear_result().

◆ hashRowType()

uint32 hashRowType ( TupleDesc  desc)

Definition at line 622 of file tupdesc.c.

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 }
unsigned int uint32
Definition: c.h:509
static Datum hash_uint32(uint32 k)
Definition: hashfn.h:43
static uint32 hash_combine(uint32 a, uint32 b)
Definition: hashfn.h:68

References hash_combine(), hash_uint32(), i, TupleDescData::natts, TupleDescData::tdtypeid, and TupleDescAttr.

Referenced by record_type_typmod_hash(), and shared_record_table_hash().

◆ IncrTupleDescRefCount()

void IncrTupleDescRefCount ( TupleDesc  tupdesc)

Definition at line 388 of file tupdesc.c.

389 {
390  Assert(tupdesc->tdrefcount >= 0);
391 
393  tupdesc->tdrefcount++;
395 }
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition: resowner.c:442
static void ResourceOwnerRememberTupleDesc(ResourceOwner owner, TupleDesc tupdesc)
Definition: tupdesc.c:48

References Assert, CurrentResourceOwner, ResourceOwnerEnlarge(), ResourceOwnerRememberTupleDesc(), and TupleDescData::tdrefcount.

Referenced by cache_record_field_properties(), and ExecEvalConvertRowtype().

◆ ResourceOwnerForgetTupleDesc()

static void ResourceOwnerForgetTupleDesc ( ResourceOwner  owner,
TupleDesc  tupdesc 
)
inlinestatic

Definition at line 54 of file tupdesc.c.

55 {
57 }
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:554
static const ResourceOwnerDesc tupdesc_resowner_desc
Definition: tupdesc.c:37

References PointerGetDatum(), ResourceOwnerForget(), and tupdesc_resowner_desc.

Referenced by DecrTupleDescRefCount().

◆ ResourceOwnerRememberTupleDesc()

static void ResourceOwnerRememberTupleDesc ( ResourceOwner  owner,
TupleDesc  tupdesc 
)
inlinestatic

Definition at line 48 of file tupdesc.c.

49 {
51 }
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:514

References PointerGetDatum(), ResourceOwnerRemember(), and tupdesc_resowner_desc.

Referenced by IncrTupleDescRefCount().

◆ ResOwnerPrintTupleDesc()

static char * ResOwnerPrintTupleDesc ( Datum  res)
static

Definition at line 934 of file tupdesc.c.

935 {
936  TupleDesc tupdesc = (TupleDesc) DatumGetPointer(res);
937 
938  return psprintf("TupleDesc %p (%u,%d)",
939  tupdesc, tupdesc->tdtypeid, tupdesc->tdtypmod);
940 }
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46

References DatumGetPointer(), psprintf(), res, TupleDescData::tdtypeid, and TupleDescData::tdtypmod.

◆ ResOwnerReleaseTupleDesc()

static void ResOwnerReleaseTupleDesc ( Datum  res)
static

Definition at line 923 of file tupdesc.c.

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 }

References Assert, DatumGetPointer(), FreeTupleDesc(), res, and TupleDescData::tdrefcount.

◆ TupleDescCopy()

void TupleDescCopy ( TupleDesc  dst,
TupleDesc  src 
)

Definition at line 251 of file tupdesc.c.

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 }
#define TupleDescSize(src)
Definition: tupdesc.h:102

References TupleDescData::constr, i, TupleDescData::natts, TupleDescData::tdrefcount, TupleDescAttr, and TupleDescSize.

Referenced by index_truncate_tuple(), and share_tupledesc().

◆ TupleDescCopyEntry()

void TupleDescCopyEntry ( TupleDesc  dst,
AttrNumber  dstAttno,
TupleDesc  src,
AttrNumber  srcAttno 
)

Definition at line 289 of file tupdesc.c.

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 }
#define PointerIsValid(pointer)
Definition: c.h:766

References Assert, ATTRIBUTE_FIXED_PART_SIZE, PointerIsValid, and TupleDescAttr.

Referenced by addRangeTableEntryForFunction(), ExecInitFunctionScan(), and ordered_set_startup().

◆ TupleDescGetDefault()

Node* TupleDescGetDefault ( TupleDesc  tupdesc,
AttrNumber  attnum 
)

Definition at line 899 of file tupdesc.c.

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 }
void * stringToNode(const char *str)
Definition: read.c:90
Definition: nodes.h:129

References attnum, TupleDescData::constr, TupleConstr::defval, i, TupleConstr::num_defval, and stringToNode().

Referenced by build_column_default(), expandTableLikeClause(), and MergeAttributes().

◆ TupleDescInitBuiltinEntry()

void TupleDescInitBuiltinEntry ( TupleDesc  desc,
AttrNumber  attributeNumber,
const char *  attributeName,
Oid  oidtypeid,
int32  typmod,
int  attdim 
)

Definition at line 726 of file tupdesc.c.

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 }
#define FLOAT8PASSBYVAL
Definition: c.h:638
#define PG_INT16_MAX
Definition: c.h:589
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
void namestrcpy(Name name, const char *str)
Definition: name.c:233
#define InvalidOid
Definition: postgres_ext.h:36
#define InvalidCompressionMethod

References Assert, elog, ERROR, FLOAT8PASSBYVAL, InvalidCompressionMethod, InvalidOid, namestrcpy(), PG_INT16_MAX, PointerIsValid, and TupleDescAttr.

Referenced by CreateReplicationSlot(), IdentifySystem(), ReadReplicationSlot(), SendTablespaceList(), SendTimeLineHistory(), SendXlogRecPtrResult(), ShowAllGUCConfig(), ShowGUCConfigOption(), and StartReplication().

◆ TupleDescInitEntry()

void TupleDescInitEntry ( TupleDesc  desc,
AttrNumber  attributeNumber,
const char *  attributeName,
Oid  oidtypeid,
int32  typmod,
int  attdim 
)

Definition at line 651 of file tupdesc.c.

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 }
#define MemSet(start, val, len)
Definition: c.h:1023
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
#define NAMEDATALEN
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221

References Assert, elog, ERROR, GETSTRUCT, HeapTupleIsValid, InvalidCompressionMethod, MemSet, NAMEDATALEN, NameStr, namestrcpy(), ObjectIdGetDatum(), PG_INT16_MAX, PointerIsValid, ReleaseSysCache(), SearchSysCache1(), and TupleDescAttr.

Referenced by aclexplode(), addRangeTableEntryForFunction(), brtuple_disk_tupdesc(), build_function_result_tupdesc_d(), build_row_from_vars(), BuildDescForRelation(), BuildDescFromLists(), CallStmtResultDesc(), create_toast_table(), dblink_get_pkey(), ExecInitFunctionScan(), ExecMakeTableFunctionResult(), ExecTypeFromExprList(), ExecTypeFromTLInternal(), expandRecordVariable(), ExplainResultDesc(), get_expr_result_type(), GetPGVariableResultDesc(), gistrescan(), init_sexpr(), initGinState(), injection_points_stats_fixed(), libpqrcv_processTuples(), materializeResult(), ordered_set_startup(), pg_buffercache_pages(), pg_get_publication_tables(), pg_get_sequence_data(), pg_lock_status(), pg_prepared_xact(), pg_stat_file(), pg_stat_get_archiver(), pg_stat_get_backend_subxact(), pg_stat_get_replication_slot(), pg_stat_get_subscription_stats(), pg_stat_get_wal(), pg_visibility_tupdesc(), pg_walfile_name_offset(), resolve_polymorphic_tupdesc(), show_all_settings(), test_predtest(), tsvector_unnest(), and TypeGetTupleDesc().

◆ TupleDescInitEntryCollation()

void TupleDescInitEntryCollation ( TupleDesc  desc,
AttrNumber  attributeNumber,
Oid  collationid 
)

Definition at line 833 of file tupdesc.c.

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 }

References Assert, PointerIsValid, and TupleDescAttr.

Referenced by addRangeTableEntryForFunction(), build_row_from_vars(), BuildDescForRelation(), BuildDescFromLists(), ExecInitFunctionScan(), ExecTypeFromExprList(), ExecTypeFromTLInternal(), expandRecordVariable(), get_expr_result_type(), initGinState(), and resolve_polymorphic_tupdesc().

Variable Documentation

◆ tupdesc_resowner_desc

const ResourceOwnerDesc tupdesc_resowner_desc
static
Initial value:
=
{
.name = "tupdesc reference",
.release_phase = RESOURCE_RELEASE_AFTER_LOCKS,
.release_priority = RELEASE_PRIO_TUPDESC_REFS,
.ReleaseResource = ResOwnerReleaseTupleDesc,
.DebugPrint = ResOwnerPrintTupleDesc
}
@ RESOURCE_RELEASE_AFTER_LOCKS
Definition: resowner.h:56
#define RELEASE_PRIO_TUPDESC_REFS
Definition: resowner.h:74
static void ResOwnerReleaseTupleDesc(Datum res)
Definition: tupdesc.c:923
static char * ResOwnerPrintTupleDesc(Datum res)
Definition: tupdesc.c:934

Definition at line 37 of file tupdesc.c.

Referenced by ResourceOwnerForgetTupleDesc(), and ResourceOwnerRememberTupleDesc().