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 "miscadmin.h"
#include "parser/parse_type.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/resowner_private.h"
#include "utils/syscache.h"
Include dependency graph for tupdesc.c:

Go to the source code of this file.

Functions

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)
 
uint32 hashTupleDesc (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 BuildDescForRelation (List *schema)
 
TupleDesc BuildDescFromLists (List *names, List *types, List *typmods, List *collations)
 

Function Documentation

◆ BuildDescForRelation()

TupleDesc BuildDescForRelation ( List schema)

Definition at line 790 of file tupdesc.c.

791 {
792  int natts;
794  ListCell *l;
795  TupleDesc desc;
796  bool has_not_null;
797  char *attname;
798  Oid atttypid;
799  int32 atttypmod;
800  Oid attcollation;
801  int attdim;
802 
803  /*
804  * allocate a new tuple descriptor
805  */
806  natts = list_length(schema);
807  desc = CreateTemplateTupleDesc(natts);
808  has_not_null = false;
809 
810  attnum = 0;
811 
812  foreach(l, schema)
813  {
814  ColumnDef *entry = lfirst(l);
815  AclResult aclresult;
816  Form_pg_attribute att;
817 
818  /*
819  * for each entry in the list, get the name and type information from
820  * the list and have TupleDescInitEntry fill in the attribute
821  * information we need.
822  */
823  attnum++;
824 
825  attname = entry->colname;
826  typenameTypeIdAndMod(NULL, entry->typeName, &atttypid, &atttypmod);
827 
828  aclresult = object_aclcheck(TypeRelationId, atttypid, GetUserId(), ACL_USAGE);
829  if (aclresult != ACLCHECK_OK)
830  aclcheck_error_type(aclresult, atttypid);
831 
832  attcollation = GetColumnDefCollation(NULL, entry, atttypid);
833  attdim = list_length(entry->typeName->arrayBounds);
834  if (attdim > PG_INT16_MAX)
835  ereport(ERROR,
836  errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
837  errmsg("too many array dimensions"));
838 
839  if (entry->typeName->setof)
840  ereport(ERROR,
841  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
842  errmsg("column \"%s\" cannot be declared SETOF",
843  attname)));
844 
846  atttypid, atttypmod, attdim);
847  att = TupleDescAttr(desc, attnum - 1);
848 
849  /* Override TupleDescInitEntry's settings as requested */
850  TupleDescInitEntryCollation(desc, attnum, attcollation);
851  if (entry->storage)
852  att->attstorage = entry->storage;
853 
854  /* Fill in additional stuff not handled by TupleDescInitEntry */
855  att->attnotnull = entry->is_not_null;
856  has_not_null |= entry->is_not_null;
857  att->attislocal = entry->is_local;
858  att->attinhcount = entry->inhcount;
859  }
860 
861  if (has_not_null)
862  {
863  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
864 
865  constr->has_not_null = true;
866  constr->has_generated_stored = false;
867  constr->defval = NULL;
868  constr->missing = NULL;
869  constr->num_defval = 0;
870  constr->check = NULL;
871  constr->num_check = 0;
872  desc->constr = constr;
873  }
874  else
875  {
876  desc->constr = NULL;
877  }
878 
879  return desc;
880 }
AclResult
Definition: acl.h:181
@ ACLCHECK_OK
Definition: acl.h:182
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3760
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:2988
int16 AttrNumber
Definition: attnum.h:21
signed int int32
Definition: c.h:483
#define PG_INT16_MAX
Definition: c.h:575
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
void * palloc0(Size size)
Definition: mcxt.c:1257
Oid GetUserId(void)
Definition: miscinit.c:509
void typenameTypeIdAndMod(ParseState *pstate, const TypeName *typeName, Oid *typeid_p, int32 *typmod_p)
Definition: parse_type.c:310
Oid GetColumnDefCollation(ParseState *pstate, ColumnDef *coldef, Oid typeOid)
Definition: parse_type.c:540
#define ACL_USAGE
Definition: parsenodes.h:91
NameData attname
Definition: pg_attribute.h:41
int16 attnum
Definition: pg_attribute.h:74
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
unsigned int Oid
Definition: postgres_ext.h:31
bool is_not_null
Definition: parsenodes.h:725
int inhcount
Definition: parsenodes.h:723
char * colname
Definition: parsenodes.h:720
TypeName * typeName
Definition: parsenodes.h:721
char storage
Definition: parsenodes.h:727
bool is_local
Definition: parsenodes.h:724
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
TupleConstr * constr
Definition: tupdesc.h:85
bool setof
Definition: parsenodes.h:267
List * arrayBounds
Definition: parsenodes.h:271
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:45
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition: tupdesc.c:767
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:583
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92

References ACL_USAGE, aclcheck_error_type(), ACLCHECK_OK, TypeName::arrayBounds, attname, attnum, TupleConstr::check, ColumnDef::colname, TupleDescData::constr, CreateTemplateTupleDesc(), TupleConstr::defval, ereport, errcode(), errmsg(), ERROR, GetColumnDefCollation(), GetUserId(), TupleConstr::has_generated_stored, TupleConstr::has_not_null, ColumnDef::inhcount, ColumnDef::is_local, ColumnDef::is_not_null, lfirst, list_length(), TupleConstr::missing, TupleConstr::num_check, TupleConstr::num_defval, object_aclcheck(), palloc0(), PG_INT16_MAX, TypeName::setof, ColumnDef::storage, TupleDescAttr, TupleDescInitEntry(), TupleDescInitEntryCollation(), ColumnDef::typeName, and typenameTypeIdAndMod().

Referenced by DefineRelation(), and DefineVirtualRelation().

◆ BuildDescFromLists()

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

Definition at line 894 of file tupdesc.c.

895 {
896  int natts;
898  ListCell *l1;
899  ListCell *l2;
900  ListCell *l3;
901  ListCell *l4;
902  TupleDesc desc;
903 
904  natts = list_length(names);
905  Assert(natts == list_length(types));
906  Assert(natts == list_length(typmods));
907  Assert(natts == list_length(collations));
908 
909  /*
910  * allocate a new tuple descriptor
911  */
912  desc = CreateTemplateTupleDesc(natts);
913 
914  attnum = 0;
915  forfour(l1, names, l2, types, l3, typmods, l4, collations)
916  {
917  char *attname = strVal(lfirst(l1));
918  Oid atttypid = lfirst_oid(l2);
919  int32 atttypmod = lfirst_int(l3);
920  Oid attcollation = lfirst_oid(l4);
921 
922  attnum++;
923 
924  TupleDescInitEntry(desc, attnum, attname, atttypid, atttypmod, 0);
925  TupleDescInitEntryCollation(desc, attnum, attcollation);
926  }
927 
928  return desc;
929 }
struct typedefs * types
Definition: ecpg.c:29
Assert(fmt[strlen(fmt) - 1] !='\n')
#define lfirst_int(lc)
Definition: pg_list.h:173
#define forfour(cell1, list1, cell2, list2, cell3, list3, cell4, list4)
Definition: pg_list.h:524
#define lfirst_oid(lc)
Definition: pg_list.h:174
#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 45 of file tupdesc.c.

46 {
47  TupleDesc desc;
48 
49  /*
50  * sanity checks
51  */
52  Assert(natts >= 0);
53 
54  /*
55  * Allocate enough memory for the tuple descriptor, including the
56  * attribute rows.
57  *
58  * Note: the attribute array stride is sizeof(FormData_pg_attribute),
59  * since we declare the array elements as FormData_pg_attribute for
60  * notational convenience. However, we only guarantee that the first
61  * ATTRIBUTE_FIXED_PART_SIZE bytes of each entry are valid; most code that
62  * copies tupdesc entries around copies just that much. In principle that
63  * could be less due to trailing padding, although with the current
64  * definition of pg_attribute there probably isn't any padding.
65  */
66  desc = (TupleDesc) palloc(offsetof(struct TupleDescData, attrs) +
67  natts * sizeof(FormData_pg_attribute));
68 
69  /*
70  * Initialize other fields of the tupdesc.
71  */
72  desc->natts = natts;
73  desc->constr = NULL;
74  desc->tdtypeid = RECORDOID;
75  desc->tdtypmod = -1;
76  desc->tdrefcount = -1; /* assume not reference-counted */
77 
78  return desc;
79 }
void * palloc(Size size)
Definition: mcxt.c:1226
FormData_pg_attribute
Definition: pg_attribute.h:193
int tdrefcount
Definition: tupdesc.h:84
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(), libpqrcv_processTuples(), load_relcache_init_file(), materializeResult(), ordered_set_startup(), pg_buffercache_pages(), pg_get_publication_tables(), pg_lock_status(), pg_logdir_ls_internal(), 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 90 of file tupdesc.c.

91 {
92  TupleDesc desc;
93  int i;
94 
95  desc = CreateTemplateTupleDesc(natts);
96 
97  for (i = 0; i < natts; ++i)
98  memcpy(TupleDescAttr(desc, i), attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
99 
100  return desc;
101 }
int i
Definition: isn.c:73
#define ATTRIBUTE_FIXED_PART_SIZE
Definition: pg_attribute.h:201

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

Referenced by AddNewAttributeTuples(), ATExecAddColumn(), and InsertOneTuple().

◆ CreateTupleDescCopy()

TupleDesc CreateTupleDescCopy ( TupleDesc  tupdesc)

Definition at line 111 of file tupdesc.c.

112 {
113  TupleDesc desc;
114  int i;
115 
116  desc = CreateTemplateTupleDesc(tupdesc->natts);
117 
118  /* Flat-copy the attribute array */
119  memcpy(TupleDescAttr(desc, 0),
120  TupleDescAttr(tupdesc, 0),
121  desc->natts * sizeof(FormData_pg_attribute));
122 
123  /*
124  * Since we're not copying constraints and defaults, clear fields
125  * associated with them.
126  */
127  for (i = 0; i < desc->natts; i++)
128  {
129  Form_pg_attribute att = TupleDescAttr(desc, i);
130 
131  att->attnotnull = false;
132  att->atthasdef = false;
133  att->atthasmissing = false;
134  att->attidentity = '\0';
135  att->attgenerated = '\0';
136  }
137 
138  /* We can copy the tuple type identification, too */
139  desc->tdtypeid = tupdesc->tdtypeid;
140  desc->tdtypmod = tupdesc->tdtypmod;
141 
142  return desc;
143 }

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(), init_tuple_slot(), 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 151 of file tupdesc.c.

152 {
153  TupleDesc desc;
154  TupleConstr *constr = tupdesc->constr;
155  int i;
156 
157  desc = CreateTemplateTupleDesc(tupdesc->natts);
158 
159  /* Flat-copy the attribute array */
160  memcpy(TupleDescAttr(desc, 0),
161  TupleDescAttr(tupdesc, 0),
162  desc->natts * sizeof(FormData_pg_attribute));
163 
164  /* Copy the TupleConstr data structure, if any */
165  if (constr)
166  {
167  TupleConstr *cpy = (TupleConstr *) palloc0(sizeof(TupleConstr));
168 
169  cpy->has_not_null = constr->has_not_null;
171 
172  if ((cpy->num_defval = constr->num_defval) > 0)
173  {
174  cpy->defval = (AttrDefault *) palloc(cpy->num_defval * sizeof(AttrDefault));
175  memcpy(cpy->defval, constr->defval, cpy->num_defval * sizeof(AttrDefault));
176  for (i = cpy->num_defval - 1; i >= 0; i--)
177  cpy->defval[i].adbin = pstrdup(constr->defval[i].adbin);
178  }
179 
180  if (constr->missing)
181  {
182  cpy->missing = (AttrMissing *) palloc(tupdesc->natts * sizeof(AttrMissing));
183  memcpy(cpy->missing, constr->missing, tupdesc->natts * sizeof(AttrMissing));
184  for (i = tupdesc->natts - 1; i >= 0; i--)
185  {
186  if (constr->missing[i].am_present)
187  {
188  Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
189 
190  cpy->missing[i].am_value = datumCopy(constr->missing[i].am_value,
191  attr->attbyval,
192  attr->attlen);
193  }
194  }
195  }
196 
197  if ((cpy->num_check = constr->num_check) > 0)
198  {
199  cpy->check = (ConstrCheck *) palloc(cpy->num_check * sizeof(ConstrCheck));
200  memcpy(cpy->check, constr->check, cpy->num_check * sizeof(ConstrCheck));
201  for (i = cpy->num_check - 1; i >= 0; i--)
202  {
203  cpy->check[i].ccname = pstrdup(constr->check[i].ccname);
204  cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin);
205  cpy->check[i].ccvalid = constr->check[i].ccvalid;
206  cpy->check[i].ccnoinherit = constr->check[i].ccnoinherit;
207  }
208  }
209 
210  desc->constr = cpy;
211  }
212 
213  /* We can copy the tuple type identification, too */
214  desc->tdtypeid = tupdesc->tdtypeid;
215  desc->tdtypmod = tupdesc->tdtypmod;
216 
217  return desc;
218 }
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:132
char * pstrdup(const char *in)
Definition: mcxt.c:1644
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

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(), initGISTstate(), and lookup_rowtype_tupdesc_copy().

◆ DecrTupleDescRefCount()

void DecrTupleDescRefCount ( TupleDesc  tupdesc)

Definition at line 384 of file tupdesc.c.

385 {
386  Assert(tupdesc->tdrefcount > 0);
387 
389  if (--tupdesc->tdrefcount == 0)
390  FreeTupleDesc(tupdesc);
391 }
ResourceOwner CurrentResourceOwner
Definition: resowner.c:147
void ResourceOwnerForgetTupleDesc(ResourceOwner owner, TupleDesc tupdesc)
Definition: resowner.c:1278
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:309

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

Referenced by cache_record_field_properties(), ExecEvalConvertRowtype(), and ResourceOwnerReleaseInternal().

◆ equalTupleDescs()

bool equalTupleDescs ( TupleDesc  tupdesc1,
TupleDesc  tupdesc2 
)

Definition at line 402 of file tupdesc.c.

403 {
404  int i,
405  n;
406 
407  if (tupdesc1->natts != tupdesc2->natts)
408  return false;
409  if (tupdesc1->tdtypeid != tupdesc2->tdtypeid)
410  return false;
411 
412  for (i = 0; i < tupdesc1->natts; i++)
413  {
414  Form_pg_attribute attr1 = TupleDescAttr(tupdesc1, i);
415  Form_pg_attribute attr2 = TupleDescAttr(tupdesc2, i);
416 
417  /*
418  * We do not need to check every single field here: we can disregard
419  * attrelid and attnum (which were used to place the row in the attrs
420  * array in the first place). It might look like we could dispense
421  * with checking attlen/attbyval/attalign, since these are derived
422  * from atttypid; but in the case of dropped columns we must check
423  * them (since atttypid will be zero for all dropped columns) and in
424  * general it seems safer to check them always.
425  *
426  * attcacheoff must NOT be checked since it's possibly not set in both
427  * copies. We also intentionally ignore atthasmissing, since that's
428  * not very relevant in tupdescs, which lack the attmissingval field.
429  */
430  if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0)
431  return false;
432  if (attr1->atttypid != attr2->atttypid)
433  return false;
434  if (attr1->attstattarget != attr2->attstattarget)
435  return false;
436  if (attr1->attlen != attr2->attlen)
437  return false;
438  if (attr1->attndims != attr2->attndims)
439  return false;
440  if (attr1->atttypmod != attr2->atttypmod)
441  return false;
442  if (attr1->attbyval != attr2->attbyval)
443  return false;
444  if (attr1->attalign != attr2->attalign)
445  return false;
446  if (attr1->attstorage != attr2->attstorage)
447  return false;
448  if (attr1->attcompression != attr2->attcompression)
449  return false;
450  if (attr1->attnotnull != attr2->attnotnull)
451  return false;
452  if (attr1->atthasdef != attr2->atthasdef)
453  return false;
454  if (attr1->attidentity != attr2->attidentity)
455  return false;
456  if (attr1->attgenerated != attr2->attgenerated)
457  return false;
458  if (attr1->attisdropped != attr2->attisdropped)
459  return false;
460  if (attr1->attislocal != attr2->attislocal)
461  return false;
462  if (attr1->attinhcount != attr2->attinhcount)
463  return false;
464  if (attr1->attcollation != attr2->attcollation)
465  return false;
466  /* variable-length fields are not even present... */
467  }
468 
469  if (tupdesc1->constr != NULL)
470  {
471  TupleConstr *constr1 = tupdesc1->constr;
472  TupleConstr *constr2 = tupdesc2->constr;
473 
474  if (constr2 == NULL)
475  return false;
476  if (constr1->has_not_null != constr2->has_not_null)
477  return false;
478  if (constr1->has_generated_stored != constr2->has_generated_stored)
479  return false;
480  n = constr1->num_defval;
481  if (n != (int) constr2->num_defval)
482  return false;
483  /* We assume here that both AttrDefault arrays are in adnum order */
484  for (i = 0; i < n; i++)
485  {
486  AttrDefault *defval1 = constr1->defval + i;
487  AttrDefault *defval2 = constr2->defval + i;
488 
489  if (defval1->adnum != defval2->adnum)
490  return false;
491  if (strcmp(defval1->adbin, defval2->adbin) != 0)
492  return false;
493  }
494  if (constr1->missing)
495  {
496  if (!constr2->missing)
497  return false;
498  for (i = 0; i < tupdesc1->natts; i++)
499  {
500  AttrMissing *missval1 = constr1->missing + i;
501  AttrMissing *missval2 = constr2->missing + i;
502 
503  if (missval1->am_present != missval2->am_present)
504  return false;
505  if (missval1->am_present)
506  {
507  Form_pg_attribute missatt1 = TupleDescAttr(tupdesc1, i);
508 
509  if (!datumIsEqual(missval1->am_value, missval2->am_value,
510  missatt1->attbyval, missatt1->attlen))
511  return false;
512  }
513  }
514  }
515  else if (constr2->missing)
516  return false;
517  n = constr1->num_check;
518  if (n != (int) constr2->num_check)
519  return false;
520 
521  /*
522  * Similarly, we rely here on the ConstrCheck entries being sorted by
523  * name. If there are duplicate names, the outcome of the comparison
524  * is uncertain, but that should not happen.
525  */
526  for (i = 0; i < n; i++)
527  {
528  ConstrCheck *check1 = constr1->check + i;
529  ConstrCheck *check2 = constr2->check + i;
530 
531  if (!(strcmp(check1->ccname, check2->ccname) == 0 &&
532  strcmp(check1->ccbin, check2->ccbin) == 0 &&
533  check1->ccvalid == check2->ccvalid &&
534  check1->ccnoinherit == check2->ccnoinherit))
535  return false;
536  }
537  }
538  else if (tupdesc2->constr != NULL)
539  return false;
540  return true;
541 }
#define NameStr(name)
Definition: c.h:735
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 acquire_inherited_sample_rows(), ProcedureCreate(), record_type_typmod_compare(), RelationClearRelation(), RelationFindReplTupleSeq(), RevalidateCachedQuery(), and shared_record_table_compare().

◆ FreeTupleDesc()

void FreeTupleDesc ( TupleDesc  tupdesc)

Definition at line 309 of file tupdesc.c.

310 {
311  int i;
312 
313  /*
314  * Possibly this should assert tdrefcount == 0, to disallow explicit
315  * freeing of un-refcounted tupdescs?
316  */
317  Assert(tupdesc->tdrefcount <= 0);
318 
319  if (tupdesc->constr)
320  {
321  if (tupdesc->constr->num_defval > 0)
322  {
323  AttrDefault *attrdef = tupdesc->constr->defval;
324 
325  for (i = tupdesc->constr->num_defval - 1; i >= 0; i--)
326  pfree(attrdef[i].adbin);
327  pfree(attrdef);
328  }
329  if (tupdesc->constr->missing)
330  {
331  AttrMissing *attrmiss = tupdesc->constr->missing;
332 
333  for (i = tupdesc->natts - 1; i >= 0; i--)
334  {
335  if (attrmiss[i].am_present
336  && !TupleDescAttr(tupdesc, i)->attbyval)
337  pfree(DatumGetPointer(attrmiss[i].am_value));
338  }
339  pfree(attrmiss);
340  }
341  if (tupdesc->constr->num_check > 0)
342  {
343  ConstrCheck *check = tupdesc->constr->check;
344 
345  for (i = tupdesc->constr->num_check - 1; i >= 0; i--)
346  {
347  pfree(check[i].ccname);
348  pfree(check[i].ccbin);
349  }
350  pfree(check);
351  }
352  pfree(tupdesc->constr);
353  }
354 
355  pfree(tupdesc);
356 }
void pfree(void *pointer)
Definition: mcxt.c:1456
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(), RevalidateCachedQuery(), spgendscan(), TypeCacheRelCallback(), update_cached_tupdesc(), and walrcv_clear_result().

◆ hashTupleDesc()

uint32 hashTupleDesc ( TupleDesc  desc)

Definition at line 554 of file tupdesc.c.

555 {
556  uint32 s;
557  int i;
558 
559  s = hash_combine(0, hash_uint32(desc->natts));
560  s = hash_combine(s, hash_uint32(desc->tdtypeid));
561  for (i = 0; i < desc->natts; ++i)
562  s = hash_combine(s, hash_uint32(TupleDescAttr(desc, i)->atttypid));
563 
564  return s;
565 }
unsigned int uint32
Definition: c.h:495
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 366 of file tupdesc.c.

367 {
368  Assert(tupdesc->tdrefcount >= 0);
369 
371  tupdesc->tdrefcount++;
373 }
void ResourceOwnerRememberTupleDesc(ResourceOwner owner, TupleDesc tupdesc)
Definition: resowner.c:1269
void ResourceOwnerEnlargeTupleDescs(ResourceOwner owner)
Definition: resowner.c:1258

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

Referenced by cache_record_field_properties(), and ExecEvalConvertRowtype().

◆ TupleDescCopy()

void TupleDescCopy ( TupleDesc  dst,
TupleDesc  src 
)

Definition at line 229 of file tupdesc.c.

230 {
231  int i;
232 
233  /* Flat-copy the header and attribute array */
234  memcpy(dst, src, TupleDescSize(src));
235 
236  /*
237  * Since we're not copying constraints and defaults, clear fields
238  * associated with them.
239  */
240  for (i = 0; i < dst->natts; i++)
241  {
242  Form_pg_attribute att = TupleDescAttr(dst, i);
243 
244  att->attnotnull = false;
245  att->atthasdef = false;
246  att->atthasmissing = false;
247  att->attidentity = '\0';
248  att->attgenerated = '\0';
249  }
250  dst->constr = NULL;
251 
252  /*
253  * Also, assume the destination is not to be ref-counted. (Copying the
254  * source's refcount would be wrong in any case.)
255  */
256  dst->tdrefcount = -1;
257 }
#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 267 of file tupdesc.c.

269 {
270  Form_pg_attribute dstAtt = TupleDescAttr(dst, dstAttno - 1);
271  Form_pg_attribute srcAtt = TupleDescAttr(src, srcAttno - 1);
272 
273  /*
274  * sanity checks
275  */
276  Assert(PointerIsValid(src));
277  Assert(PointerIsValid(dst));
278  Assert(srcAttno >= 1);
279  Assert(srcAttno <= src->natts);
280  Assert(dstAttno >= 1);
281  Assert(dstAttno <= dst->natts);
282 
283  memcpy(dstAtt, srcAtt, ATTRIBUTE_FIXED_PART_SIZE);
284 
285  /*
286  * Aside from updating the attno, we'd better reset attcacheoff.
287  *
288  * XXX Actually, to be entirely safe we'd need to reset the attcacheoff of
289  * all following columns in dst as well. Current usage scenarios don't
290  * require that though, because all following columns will get initialized
291  * by other uses of this function or TupleDescInitEntry. So we cheat a
292  * bit to avoid a useless O(N^2) penalty.
293  */
294  dstAtt->attnum = dstAttno;
295  dstAtt->attcacheoff = -1;
296 
297  /* since we're not copying constraints or defaults, clear these */
298  dstAtt->attnotnull = false;
299  dstAtt->atthasdef = false;
300  dstAtt->atthasmissing = false;
301  dstAtt->attidentity = '\0';
302  dstAtt->attgenerated = '\0';
303 }
#define PointerIsValid(pointer)
Definition: c.h:752

References Assert(), ATTRIBUTE_FIXED_PART_SIZE, PointerIsValid, and TupleDescAttr.

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

◆ TupleDescInitBuiltinEntry()

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

Definition at line 659 of file tupdesc.c.

665 {
666  Form_pg_attribute att;
667 
668  /* sanity checks */
669  Assert(PointerIsValid(desc));
670  Assert(attributeNumber >= 1);
671  Assert(attributeNumber <= desc->natts);
672  Assert(attdim >= 0);
673  Assert(attdim <= PG_INT16_MAX);
674 
675  /* initialize the attribute fields */
676  att = TupleDescAttr(desc, attributeNumber - 1);
677  att->attrelid = 0; /* dummy value */
678 
679  /* unlike TupleDescInitEntry, we require an attribute name */
680  Assert(attributeName != NULL);
681  namestrcpy(&(att->attname), attributeName);
682 
683  att->attstattarget = -1;
684  att->attcacheoff = -1;
685  att->atttypmod = typmod;
686 
687  att->attnum = attributeNumber;
688  att->attndims = attdim;
689 
690  att->attnotnull = false;
691  att->atthasdef = false;
692  att->atthasmissing = false;
693  att->attidentity = '\0';
694  att->attgenerated = '\0';
695  att->attisdropped = false;
696  att->attislocal = true;
697  att->attinhcount = 0;
698  /* variable-length fields are not present in tupledescs */
699 
700  att->atttypid = oidtypeid;
701 
702  /*
703  * Our goal here is to support just enough types to let basic builtin
704  * commands work without catalog access - e.g. so that we can do certain
705  * things even in processes that are not connected to a database.
706  */
707  switch (oidtypeid)
708  {
709  case TEXTOID:
710  case TEXTARRAYOID:
711  att->attlen = -1;
712  att->attbyval = false;
713  att->attalign = TYPALIGN_INT;
714  att->attstorage = TYPSTORAGE_EXTENDED;
715  att->attcompression = InvalidCompressionMethod;
716  att->attcollation = DEFAULT_COLLATION_OID;
717  break;
718 
719  case BOOLOID:
720  att->attlen = 1;
721  att->attbyval = true;
722  att->attalign = TYPALIGN_CHAR;
723  att->attstorage = TYPSTORAGE_PLAIN;
724  att->attcompression = InvalidCompressionMethod;
725  att->attcollation = InvalidOid;
726  break;
727 
728  case INT4OID:
729  att->attlen = 4;
730  att->attbyval = true;
731  att->attalign = TYPALIGN_INT;
732  att->attstorage = TYPSTORAGE_PLAIN;
733  att->attcompression = InvalidCompressionMethod;
734  att->attcollation = InvalidOid;
735  break;
736 
737  case INT8OID:
738  att->attlen = 8;
739  att->attbyval = FLOAT8PASSBYVAL;
740  att->attalign = TYPALIGN_DOUBLE;
741  att->attstorage = TYPSTORAGE_PLAIN;
742  att->attcompression = InvalidCompressionMethod;
743  att->attcollation = InvalidOid;
744  break;
745 
746  case OIDOID:
747  att->attlen = 4;
748  att->attbyval = true;
749  att->attalign = TYPALIGN_INT;
750  att->attstorage = TYPSTORAGE_PLAIN;
751  att->attcompression = InvalidCompressionMethod;
752  att->attcollation = InvalidOid;
753  break;
754 
755  default:
756  elog(ERROR, "unsupported type %u", oidtypeid);
757  }
758 }
#define FLOAT8PASSBYVAL
Definition: c.h:624
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 583 of file tupdesc.c.

589 {
590  HeapTuple tuple;
591  Form_pg_type typeForm;
592  Form_pg_attribute att;
593 
594  /*
595  * sanity checks
596  */
597  Assert(PointerIsValid(desc));
598  Assert(attributeNumber >= 1);
599  Assert(attributeNumber <= desc->natts);
600  Assert(attdim >= 0);
601  Assert(attdim <= PG_INT16_MAX);
602 
603  /*
604  * initialize the attribute fields
605  */
606  att = TupleDescAttr(desc, attributeNumber - 1);
607 
608  att->attrelid = 0; /* dummy value */
609 
610  /*
611  * Note: attributeName can be NULL, because the planner doesn't always
612  * fill in valid resname values in targetlists, particularly for resjunk
613  * attributes. Also, do nothing if caller wants to re-use the old attname.
614  */
615  if (attributeName == NULL)
616  MemSet(NameStr(att->attname), 0, NAMEDATALEN);
617  else if (attributeName != NameStr(att->attname))
618  namestrcpy(&(att->attname), attributeName);
619 
620  att->attstattarget = -1;
621  att->attcacheoff = -1;
622  att->atttypmod = typmod;
623 
624  att->attnum = attributeNumber;
625  att->attndims = attdim;
626 
627  att->attnotnull = false;
628  att->atthasdef = false;
629  att->atthasmissing = false;
630  att->attidentity = '\0';
631  att->attgenerated = '\0';
632  att->attisdropped = false;
633  att->attislocal = true;
634  att->attinhcount = 0;
635  /* variable-length fields are not present in tupledescs */
636 
637  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(oidtypeid));
638  if (!HeapTupleIsValid(tuple))
639  elog(ERROR, "cache lookup failed for type %u", oidtypeid);
640  typeForm = (Form_pg_type) GETSTRUCT(tuple);
641 
642  att->atttypid = oidtypeid;
643  att->attlen = typeForm->typlen;
644  att->attbyval = typeForm->typbyval;
645  att->attalign = typeForm->typalign;
646  att->attstorage = typeForm->typstorage;
647  att->attcompression = InvalidCompressionMethod;
648  att->attcollation = typeForm->typcollation;
649 
650  ReleaseSysCache(tuple);
651 }
#define MemSet(start, val, len)
Definition: c.h:1009
#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:868
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:820
@ TYPEOID
Definition: syscache.h:114

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

Referenced by aclexplode(), addRangeTableEntryForFunction(), brtuple_disk_tupdesc(), build_function_result_tupdesc_d(), build_row_from_vars(), BuildDescForRelation(), BuildDescFromLists(), create_toast_table(), dblink_get_pkey(), ExecInitFunctionScan(), ExecMakeTableFunctionResult(), ExecTypeFromExprList(), ExecTypeFromTLInternal(), expandRecordVariable(), ExplainResultDesc(), get_expr_result_type(), GetPGVariableResultDesc(), gistrescan(), init_sexpr(), initGinState(), libpqrcv_processTuples(), materializeResult(), ordered_set_startup(), pg_buffercache_pages(), pg_get_publication_tables(), pg_lock_status(), pg_logdir_ls_internal(), 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 767 of file tupdesc.c.

770 {
771  /*
772  * sanity checks
773  */
774  Assert(PointerIsValid(desc));
775  Assert(attributeNumber >= 1);
776  Assert(attributeNumber <= desc->natts);
777 
778  TupleDescAttr(desc, attributeNumber - 1)->attcollation = collationid;
779 }

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().