PostgreSQL Source Code  git master
tupdesc.c File Reference
#include "postgres.h"
#include "access/hash.h"
#include "access/htup_details.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "miscadmin.h"
#include "parser/parse_type.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/hashutils.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, bool hasoid)
 
TupleDesc CreateTupleDesc (int natts, bool hasoid, 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 727 of file tupdesc.c.

References ACL_USAGE, aclcheck_error_type(), ACLCHECK_OK, TypeName::arrayBounds, tupleConstr::check, ColumnDef::colname, tupleDesc::constr, CreateTemplateTupleDesc(), tupleConstr::defval, ereport, errcode(), errmsg(), ERROR, GetColumnDefCollation(), GetUserId(), tupleConstr::has_not_null, ColumnDef::inhcount, ColumnDef::is_local, ColumnDef::is_not_null, lfirst, list_length(), tupleConstr::num_check, tupleConstr::num_defval, palloc0(), pg_type_aclcheck(), TypeName::setof, ColumnDef::storage, TupleDescAttr, TupleDescInitEntry(), TupleDescInitEntryCollation(), ColumnDef::typeName, and typenameTypeIdAndMod().

Referenced by DefineRelation(), and DefineVirtualRelation().

728 {
729  int natts;
730  AttrNumber attnum;
731  ListCell *l;
732  TupleDesc desc;
733  bool has_not_null;
734  char *attname;
735  Oid atttypid;
736  int32 atttypmod;
737  Oid attcollation;
738  int attdim;
739 
740  /*
741  * allocate a new tuple descriptor
742  */
743  natts = list_length(schema);
744  desc = CreateTemplateTupleDesc(natts, false);
745  has_not_null = false;
746 
747  attnum = 0;
748 
749  foreach(l, schema)
750  {
751  ColumnDef *entry = lfirst(l);
752  AclResult aclresult;
753  Form_pg_attribute att;
754 
755  /*
756  * for each entry in the list, get the name and type information from
757  * the list and have TupleDescInitEntry fill in the attribute
758  * information we need.
759  */
760  attnum++;
761 
762  attname = entry->colname;
763  typenameTypeIdAndMod(NULL, entry->typeName, &atttypid, &atttypmod);
764 
765  aclresult = pg_type_aclcheck(atttypid, GetUserId(), ACL_USAGE);
766  if (aclresult != ACLCHECK_OK)
767  aclcheck_error_type(aclresult, atttypid);
768 
769  attcollation = GetColumnDefCollation(NULL, entry, atttypid);
770  attdim = list_length(entry->typeName->arrayBounds);
771 
772  if (entry->typeName->setof)
773  ereport(ERROR,
774  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
775  errmsg("column \"%s\" cannot be declared SETOF",
776  attname)));
777 
778  TupleDescInitEntry(desc, attnum, attname,
779  atttypid, atttypmod, attdim);
780  att = TupleDescAttr(desc, attnum - 1);
781 
782  /* Override TupleDescInitEntry's settings as requested */
783  TupleDescInitEntryCollation(desc, attnum, attcollation);
784  if (entry->storage)
785  att->attstorage = entry->storage;
786 
787  /* Fill in additional stuff not handled by TupleDescInitEntry */
788  att->attnotnull = entry->is_not_null;
789  has_not_null |= entry->is_not_null;
790  att->attislocal = entry->is_local;
791  att->attinhcount = entry->inhcount;
792  }
793 
794  if (has_not_null)
795  {
796  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
797 
798  constr->has_not_null = true;
799  constr->defval = NULL;
800  constr->num_defval = 0;
801  constr->check = NULL;
802  constr->num_check = 0;
803  desc->constr = constr;
804  }
805  else
806  {
807  desc->constr = NULL;
808  }
809 
810  return desc;
811 }
char storage
Definition: parsenodes.h:652
bool is_local
Definition: parsenodes.h:648
Oid GetUserId(void)
Definition: miscinit.c:284
ConstrCheck * check
Definition: tupdesc.h:40
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
int errcode(int sqlerrcode)
Definition: elog.c:575
bool is_not_null
Definition: parsenodes.h:649
unsigned int Oid
Definition: postgres_ext.h:31
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3663
signed int int32
Definition: c.h:302
AttrDefault * defval
Definition: tupdesc.h:39
#define ERROR
Definition: elog.h:43
bool setof
Definition: parsenodes.h:210
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition: tupdesc.c:702
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define ACL_USAGE
Definition: parsenodes.h:80
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:543
#define ereport(elevel, rest)
Definition: elog.h:122
bool has_not_null
Definition: tupdesc.h:43
Oid GetColumnDefCollation(ParseState *pstate, ColumnDef *coldef, Oid typeOid)
Definition: parse_type.c:521
void * palloc0(Size size)
Definition: mcxt.c:864
AclResult
Definition: acl.h:178
void typenameTypeIdAndMod(ParseState *pstate, const TypeName *typeName, Oid *typeid_p, int32 *typmod_p)
Definition: parse_type.c:293
uint16 num_defval
Definition: tupdesc.h:41
#define lfirst(lc)
Definition: pg_list.h:106
TupleConstr * constr
Definition: tupdesc.h:84
static int list_length(const List *l)
Definition: pg_list.h:89
TypeName * typeName
Definition: parsenodes.h:646
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:43
List * arrayBounds
Definition: parsenodes.h:214
int errmsg(const char *fmt,...)
Definition: elog.c:797
int inhcount
Definition: parsenodes.h:647
uint16 num_check
Definition: tupdesc.h:42
char * colname
Definition: parsenodes.h:645
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4740
int16 AttrNumber
Definition: attnum.h:21

◆ BuildDescFromLists()

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

Definition at line 825 of file tupdesc.c.

References Assert, CreateTemplateTupleDesc(), lfirst, lfirst_int, lfirst_oid, list_head(), list_length(), lnext, strVal, TupleDescInitEntry(), and TupleDescInitEntryCollation().

Referenced by ExecInitFunctionScan(), and ExecInitTableFuncScan().

826 {
827  int natts;
828  AttrNumber attnum;
829  ListCell *l1;
830  ListCell *l2;
831  ListCell *l3;
832  ListCell *l4;
833  TupleDesc desc;
834 
835  natts = list_length(names);
836  Assert(natts == list_length(types));
837  Assert(natts == list_length(typmods));
838  Assert(natts == list_length(collations));
839 
840  /*
841  * allocate a new tuple descriptor
842  */
843  desc = CreateTemplateTupleDesc(natts, false);
844 
845  attnum = 0;
846 
847  l2 = list_head(types);
848  l3 = list_head(typmods);
849  l4 = list_head(collations);
850  foreach(l1, names)
851  {
852  char *attname = strVal(lfirst(l1));
853  Oid atttypid;
854  int32 atttypmod;
855  Oid attcollation;
856 
857  atttypid = lfirst_oid(l2);
858  l2 = lnext(l2);
859  atttypmod = lfirst_int(l3);
860  l3 = lnext(l3);
861  attcollation = lfirst_oid(l4);
862  l4 = lnext(l4);
863 
864  attnum++;
865 
866  TupleDescInitEntry(desc, attnum, attname, atttypid, atttypmod, 0);
867  TupleDescInitEntryCollation(desc, attnum, attcollation);
868  }
869 
870  return desc;
871 }
#define strVal(v)
Definition: value.h:54
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:302
#define lfirst_int(lc)
Definition: pg_list.h:107
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition: tupdesc.c:702
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:543
#define lnext(lc)
Definition: pg_list.h:105
#define Assert(condition)
Definition: c.h:688
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:43
int16 AttrNumber
Definition: attnum.h:21
#define lfirst_oid(lc)
Definition: pg_list.h:108

◆ CreateTemplateTupleDesc()

TupleDesc CreateTemplateTupleDesc ( int  natts,
bool  hasoid 
)

Definition at line 43 of file tupdesc.c.

References AssertArg, tupleDesc::constr, FormData_pg_attribute, tupleDesc::natts, offsetof, palloc(), RECORDOID, tupleDesc::tdhasoid, tupleDesc::tdrefcount, tupleDesc::tdtypeid, and tupleDesc::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_notify(), dblink_get_pkey(), ExecInitFunctionScan(), ExecMakeTableFunctionResult(), ExecTypeFromExprList(), ExecTypeFromTLInternal(), expandRecordVariable(), ExplainResultDesc(), formrdesc(), GetPGVariableResultDesc(), gistrescan(), IdentifySystem(), init_sexpr(), initGinState(), libpqrcv_processTuples(), load_relcache_init_file(), materializeQueryResult(), materializeResult(), ordered_set_startup(), pg_buffercache_pages(), pg_control_checkpoint(), pg_control_init(), pg_control_recovery(), pg_control_system(), pg_cursor(), pg_get_keywords(), pg_get_multixact_members(), pg_get_object_address(), pg_identify_object(), pg_identify_object_as_address(), pg_last_committed_xact(), pg_lock_status(), pg_logdir_ls(), pg_ls_dir_files(), pg_prepared_statement(), pg_prepared_xact(), pg_sequence_parameters(), pg_stat_file(), pg_stat_get_archiver(), pg_timezone_abbrevs(), pg_timezone_names(), pg_visibility_map_summary(), pg_visibility_tupdesc(), pg_walfile_name_offset(), prs_setup_firstcall(), show_all_file_settings(), show_all_settings(), ShowAllGUCConfig(), ShowGUCConfigOption(), StartReplication(), ts_setup_firstcall(), tsvector_unnest(), tt_setup_firstcall(), and TypeGetTupleDesc().

44 {
45  TupleDesc desc;
46 
47  /*
48  * sanity checks
49  */
50  AssertArg(natts >= 0);
51 
52  /*
53  * Allocate enough memory for the tuple descriptor, including the
54  * attribute rows.
55  *
56  * Note: the attribute array stride is sizeof(FormData_pg_attribute),
57  * since we declare the array elements as FormData_pg_attribute for
58  * notational convenience. However, we only guarantee that the first
59  * ATTRIBUTE_FIXED_PART_SIZE bytes of each entry are valid; most code that
60  * copies tupdesc entries around copies just that much. In principle that
61  * could be less due to trailing padding, although with the current
62  * definition of pg_attribute there probably isn't any padding.
63  */
64  desc = (TupleDesc) palloc(offsetof(struct tupleDesc, attrs) +
65  natts * sizeof(FormData_pg_attribute));
66 
67  /*
68  * Initialize other fields of the tupdesc.
69  */
70  desc->natts = natts;
71  desc->constr = NULL;
72  desc->tdtypeid = RECORDOID;
73  desc->tdtypmod = -1;
74  desc->tdhasoid = hasoid;
75  desc->tdrefcount = -1; /* assume not reference-counted */
76 
77  return desc;
78 }
Oid tdtypeid
Definition: tupdesc.h:80
bool tdhasoid
Definition: tupdesc.h:82
int natts
Definition: tupdesc.h:79
int32 tdtypmod
Definition: tupdesc.h:81
#define RECORDOID
Definition: pg_type.h:680
#define AssertArg(condition)
Definition: c.h:690
FormData_pg_attribute
Definition: pg_attribute.h:171
struct tupleDesc * TupleDesc
TupleConstr * constr
Definition: tupdesc.h:84
void * palloc(Size size)
Definition: mcxt.c:835
int tdrefcount
Definition: tupdesc.h:83
#define offsetof(type, field)
Definition: c.h:611

◆ CreateTupleDesc()

TupleDesc CreateTupleDesc ( int  natts,
bool  hasoid,
Form_pg_attribute attrs 
)

Definition at line 89 of file tupdesc.c.

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

Referenced by InsertOneTuple().

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

◆ CreateTupleDescCopy()

TupleDesc CreateTupleDescCopy ( TupleDesc  tupdesc)

Definition at line 110 of file tupdesc.c.

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

Referenced by assign_record_type_typmod(), ATGetQueueEntry(), BuildTupleHashTable(), check_default_allows_bound(), check_sql_fn_retval(), connectby_text(), connectby_text_serial(), CopyCachedPlan(), crosstab(), crosstab_hash(), database_to_xmlschema_internal(), DefineIndex(), deflist_to_tuplestore(), do_autovacuum(), each_worker(), each_worker_jsonb(), elements_worker(), elements_worker_jsonb(), ExecEvalWholeRowVar(), ExecInitFunctionScan(), ExecPrepareTuplestoreResult(), FetchPreparedStatementResultDesc(), fmgr_sql(), init_sexpr(), make_expanded_record_from_exprecord(), make_expanded_record_from_tupdesc(), materializeResult(), PersistHoldablePortal(), pg_config(), plperl_return_next_internal(), plpgsql_exec_function(), pltcl_func_handler(), PLy_spi_execute_fetch_result(), populate_record_worker(), populate_recordset_worker(), RelationBuildLocalRelation(), RelationNameGetTupleDesc(), RevalidateCachedQuery(), schema_to_xmlschema_internal(), spi_dest_startup(), storeRow(), update_cached_tupdesc(), UtilityTupleDescriptor(), and xpath_table().

111 {
112  TupleDesc desc;
113  int i;
114 
115  desc = CreateTemplateTupleDesc(tupdesc->natts, tupdesc->tdhasoid);
116 
117  /* Flat-copy the attribute array */
118  memcpy(TupleDescAttr(desc, 0),
119  TupleDescAttr(tupdesc, 0),
120  desc->natts * sizeof(FormData_pg_attribute));
121 
122  /*
123  * Since we're not copying constraints and defaults, clear fields
124  * associated with them.
125  */
126  for (i = 0; i < desc->natts; i++)
127  {
128  Form_pg_attribute att = TupleDescAttr(desc, i);
129 
130  att->attnotnull = false;
131  att->atthasdef = false;
132  att->attidentity = '\0';
133  }
134 
135  /* We can copy the tuple type identification, too */
136  desc->tdtypeid = tupdesc->tdtypeid;
137  desc->tdtypmod = tupdesc->tdtypmod;
138 
139  return desc;
140 }
Oid tdtypeid
Definition: tupdesc.h:80
bool tdhasoid
Definition: tupdesc.h:82
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
int natts
Definition: tupdesc.h:79
int32 tdtypmod
Definition: tupdesc.h:81
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
FormData_pg_attribute
Definition: pg_attribute.h:171
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:43
int i

◆ CreateTupleDescCopyConstr()

TupleDesc CreateTupleDescCopyConstr ( TupleDesc  tupdesc)

Definition at line 148 of file tupdesc.c.

References attrDefault::adbin, constrCheck::ccbin, constrCheck::ccname, constrCheck::ccnoinherit, constrCheck::ccvalid, tupleConstr::check, tupleDesc::constr, CreateTemplateTupleDesc(), tupleConstr::defval, FormData_pg_attribute, tupleConstr::has_not_null, i, tupleDesc::natts, tupleConstr::num_check, tupleConstr::num_defval, palloc(), palloc0(), pstrdup(), tupleDesc::tdhasoid, tupleDesc::tdtypeid, tupleDesc::tdtypmod, and TupleDescAttr.

Referenced by CatalogCacheInitializeCache(), lookup_rowtype_tupdesc_copy(), and tuple_data_split_internal().

149 {
150  TupleDesc desc;
151  TupleConstr *constr = tupdesc->constr;
152  int i;
153 
154  desc = CreateTemplateTupleDesc(tupdesc->natts, tupdesc->tdhasoid);
155 
156  /* Flat-copy the attribute array */
157  memcpy(TupleDescAttr(desc, 0),
158  TupleDescAttr(tupdesc, 0),
159  desc->natts * sizeof(FormData_pg_attribute));
160 
161  /* Copy the TupleConstr data structure, if any */
162  if (constr)
163  {
164  TupleConstr *cpy = (TupleConstr *) palloc0(sizeof(TupleConstr));
165 
166  cpy->has_not_null = constr->has_not_null;
167 
168  if ((cpy->num_defval = constr->num_defval) > 0)
169  {
170  cpy->defval = (AttrDefault *) palloc(cpy->num_defval * sizeof(AttrDefault));
171  memcpy(cpy->defval, constr->defval, cpy->num_defval * sizeof(AttrDefault));
172  for (i = cpy->num_defval - 1; i >= 0; i--)
173  {
174  if (constr->defval[i].adbin)
175  cpy->defval[i].adbin = pstrdup(constr->defval[i].adbin);
176  }
177  }
178 
179  if ((cpy->num_check = constr->num_check) > 0)
180  {
181  cpy->check = (ConstrCheck *) palloc(cpy->num_check * sizeof(ConstrCheck));
182  memcpy(cpy->check, constr->check, cpy->num_check * sizeof(ConstrCheck));
183  for (i = cpy->num_check - 1; i >= 0; i--)
184  {
185  if (constr->check[i].ccname)
186  cpy->check[i].ccname = pstrdup(constr->check[i].ccname);
187  if (constr->check[i].ccbin)
188  cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin);
189  cpy->check[i].ccvalid = constr->check[i].ccvalid;
190  cpy->check[i].ccnoinherit = constr->check[i].ccnoinherit;
191  }
192  }
193 
194  desc->constr = cpy;
195  }
196 
197  /* We can copy the tuple type identification, too */
198  desc->tdtypeid = tupdesc->tdtypeid;
199  desc->tdtypmod = tupdesc->tdtypmod;
200 
201  return desc;
202 }
Oid tdtypeid
Definition: tupdesc.h:80
char * ccname
Definition: tupdesc.h:30
bool tdhasoid
Definition: tupdesc.h:82
bool ccnoinherit
Definition: tupdesc.h:33
ConstrCheck * check
Definition: tupdesc.h:40
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
char * pstrdup(const char *in)
Definition: mcxt.c:1063
char * ccbin
Definition: tupdesc.h:31
int natts
Definition: tupdesc.h:79
int32 tdtypmod
Definition: tupdesc.h:81
AttrDefault * defval
Definition: tupdesc.h:39
char * adbin
Definition: tupdesc.h:25
bool has_not_null
Definition: tupdesc.h:43
void * palloc0(Size size)
Definition: mcxt.c:864
FormData_pg_attribute
Definition: pg_attribute.h:171
uint16 num_defval
Definition: tupdesc.h:41
TupleConstr * constr
Definition: tupdesc.h:84
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:43
void * palloc(Size size)
Definition: mcxt.c:835
bool ccvalid
Definition: tupdesc.h:32
int i
uint16 num_check
Definition: tupdesc.h:42

◆ DecrTupleDescRefCount()

void DecrTupleDescRefCount ( TupleDesc  tupdesc)

Definition at line 357 of file tupdesc.c.

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

Referenced by ATExecAddOf(), cache_record_field_properties(), ExecInitExprRec(), expanded_record_fetch_tupdesc(), make_expanded_record_from_typeid(), ResourceOwnerReleaseInternal(), and transformOfType().

358 {
359  Assert(tupdesc->tdrefcount > 0);
360 
362  if (--tupdesc->tdrefcount == 0)
363  FreeTupleDesc(tupdesc);
364 }
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
void ResourceOwnerForgetTupleDesc(ResourceOwner owner, TupleDesc tupdesc)
Definition: resowner.c:1103
#define Assert(condition)
Definition: c.h:688
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:289
int tdrefcount
Definition: tupdesc.h:83

◆ equalTupleDescs()

bool equalTupleDescs ( TupleDesc  tupdesc1,
TupleDesc  tupdesc2 
)

Definition at line 375 of file tupdesc.c.

References attrDefault::adbin, attrDefault::adnum, constrCheck::ccbin, constrCheck::ccname, constrCheck::ccnoinherit, constrCheck::ccvalid, tupleConstr::check, tupleDesc::constr, tupleConstr::defval, tupleConstr::has_not_null, i, NameStr, tupleDesc::natts, tupleConstr::num_check, tupleConstr::num_defval, tupleDesc::tdhasoid, tupleDesc::tdtypeid, and TupleDescAttr.

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

376 {
377  int i,
378  j,
379  n;
380 
381  if (tupdesc1->natts != tupdesc2->natts)
382  return false;
383  if (tupdesc1->tdtypeid != tupdesc2->tdtypeid)
384  return false;
385  if (tupdesc1->tdhasoid != tupdesc2->tdhasoid)
386  return false;
387 
388  for (i = 0; i < tupdesc1->natts; i++)
389  {
390  Form_pg_attribute attr1 = TupleDescAttr(tupdesc1, i);
391  Form_pg_attribute attr2 = TupleDescAttr(tupdesc2, i);
392 
393  /*
394  * We do not need to check every single field here: we can disregard
395  * attrelid and attnum (which were used to place the row in the attrs
396  * array in the first place). It might look like we could dispense
397  * with checking attlen/attbyval/attalign, since these are derived
398  * from atttypid; but in the case of dropped columns we must check
399  * them (since atttypid will be zero for all dropped columns) and in
400  * general it seems safer to check them always.
401  *
402  * attcacheoff must NOT be checked since it's possibly not set in both
403  * copies.
404  */
405  if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0)
406  return false;
407  if (attr1->atttypid != attr2->atttypid)
408  return false;
409  if (attr1->attstattarget != attr2->attstattarget)
410  return false;
411  if (attr1->attlen != attr2->attlen)
412  return false;
413  if (attr1->attndims != attr2->attndims)
414  return false;
415  if (attr1->atttypmod != attr2->atttypmod)
416  return false;
417  if (attr1->attbyval != attr2->attbyval)
418  return false;
419  if (attr1->attstorage != attr2->attstorage)
420  return false;
421  if (attr1->attalign != attr2->attalign)
422  return false;
423  if (attr1->attnotnull != attr2->attnotnull)
424  return false;
425  if (attr1->atthasdef != attr2->atthasdef)
426  return false;
427  if (attr1->attidentity != attr2->attidentity)
428  return false;
429  if (attr1->attisdropped != attr2->attisdropped)
430  return false;
431  if (attr1->attislocal != attr2->attislocal)
432  return false;
433  if (attr1->attinhcount != attr2->attinhcount)
434  return false;
435  if (attr1->attcollation != attr2->attcollation)
436  return false;
437  /* attacl, attoptions and attfdwoptions are not even present... */
438  }
439 
440  if (tupdesc1->constr != NULL)
441  {
442  TupleConstr *constr1 = tupdesc1->constr;
443  TupleConstr *constr2 = tupdesc2->constr;
444 
445  if (constr2 == NULL)
446  return false;
447  if (constr1->has_not_null != constr2->has_not_null)
448  return false;
449  n = constr1->num_defval;
450  if (n != (int) constr2->num_defval)
451  return false;
452  for (i = 0; i < n; i++)
453  {
454  AttrDefault *defval1 = constr1->defval + i;
455  AttrDefault *defval2 = constr2->defval;
456 
457  /*
458  * We can't assume that the items are always read from the system
459  * catalogs in the same order; so use the adnum field to identify
460  * the matching item to compare.
461  */
462  for (j = 0; j < n; defval2++, j++)
463  {
464  if (defval1->adnum == defval2->adnum)
465  break;
466  }
467  if (j >= n)
468  return false;
469  if (strcmp(defval1->adbin, defval2->adbin) != 0)
470  return false;
471  }
472  n = constr1->num_check;
473  if (n != (int) constr2->num_check)
474  return false;
475  for (i = 0; i < n; i++)
476  {
477  ConstrCheck *check1 = constr1->check + i;
478  ConstrCheck *check2 = constr2->check;
479 
480  /*
481  * Similarly, don't assume that the checks are always read in the
482  * same order; match them up by name and contents. (The name
483  * *should* be unique, but...)
484  */
485  for (j = 0; j < n; check2++, j++)
486  {
487  if (strcmp(check1->ccname, check2->ccname) == 0 &&
488  strcmp(check1->ccbin, check2->ccbin) == 0 &&
489  check1->ccvalid == check2->ccvalid &&
490  check1->ccnoinherit == check2->ccnoinherit)
491  break;
492  }
493  if (j >= n)
494  return false;
495  }
496  }
497  else if (tupdesc2->constr != NULL)
498  return false;
499  return true;
500 }
Oid tdtypeid
Definition: tupdesc.h:80
char * ccname
Definition: tupdesc.h:30
bool tdhasoid
Definition: tupdesc.h:82
bool ccnoinherit
Definition: tupdesc.h:33
ConstrCheck * check
Definition: tupdesc.h:40
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
char * ccbin
Definition: tupdesc.h:31
int natts
Definition: tupdesc.h:79
AttrDefault * defval
Definition: tupdesc.h:39
AttrNumber adnum
Definition: tupdesc.h:24
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
char * adbin
Definition: tupdesc.h:25
bool has_not_null
Definition: tupdesc.h:43
uint16 num_defval
Definition: tupdesc.h:41
TupleConstr * constr
Definition: tupdesc.h:84
bool ccvalid
Definition: tupdesc.h:32
int i
#define NameStr(name)
Definition: c.h:565
uint16 num_check
Definition: tupdesc.h:42

◆ FreeTupleDesc()

void FreeTupleDesc ( TupleDesc  tupdesc)

Definition at line 289 of file tupdesc.c.

References Assert, tupleConstr::check, tupleDesc::constr, tupleConstr::defval, i, tupleConstr::num_check, tupleConstr::num_defval, pfree(), and tupleDesc::tdrefcount.

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

290 {
291  int i;
292 
293  /*
294  * Possibly this should assert tdrefcount == 0, to disallow explicit
295  * freeing of un-refcounted tupdescs?
296  */
297  Assert(tupdesc->tdrefcount <= 0);
298 
299  if (tupdesc->constr)
300  {
301  if (tupdesc->constr->num_defval > 0)
302  {
303  AttrDefault *attrdef = tupdesc->constr->defval;
304 
305  for (i = tupdesc->constr->num_defval - 1; i >= 0; i--)
306  {
307  if (attrdef[i].adbin)
308  pfree(attrdef[i].adbin);
309  }
310  pfree(attrdef);
311  }
312  if (tupdesc->constr->num_check > 0)
313  {
314  ConstrCheck *check = tupdesc->constr->check;
315 
316  for (i = tupdesc->constr->num_check - 1; i >= 0; i--)
317  {
318  if (check[i].ccname)
319  pfree(check[i].ccname);
320  if (check[i].ccbin)
321  pfree(check[i].ccbin);
322  }
323  pfree(check);
324  }
325  pfree(tupdesc->constr);
326  }
327 
328  pfree(tupdesc);
329 }
ConstrCheck * check
Definition: tupdesc.h:40
void pfree(void *pointer)
Definition: mcxt.c:936
AttrDefault * defval
Definition: tupdesc.h:39
uint16 num_defval
Definition: tupdesc.h:41
#define Assert(condition)
Definition: c.h:688
TupleConstr * constr
Definition: tupdesc.h:84
int tdrefcount
Definition: tupdesc.h:83
int i
uint16 num_check
Definition: tupdesc.h:42

◆ hashTupleDesc()

uint32 hashTupleDesc ( TupleDesc  desc)

Definition at line 513 of file tupdesc.c.

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

Referenced by record_type_typmod_hash(), and shared_record_table_hash().

514 {
515  uint32 s;
516  int i;
517 
518  s = hash_combine(0, hash_uint32(desc->natts));
519  s = hash_combine(s, hash_uint32(desc->tdtypeid));
520  s = hash_combine(s, hash_uint32(desc->tdhasoid));
521  for (i = 0; i < desc->natts; ++i)
522  s = hash_combine(s, hash_uint32(TupleDescAttr(desc, i)->atttypid));
523 
524  return s;
525 }
static uint32 hash_combine(uint32 a, uint32 b)
Definition: hashutils.h:17
Oid tdtypeid
Definition: tupdesc.h:80
bool tdhasoid
Definition: tupdesc.h:82
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
int natts
Definition: tupdesc.h:79
unsigned int uint32
Definition: c.h:314
Datum hash_uint32(uint32 k)
Definition: hashfunc.c:853
int i

◆ IncrTupleDescRefCount()

void IncrTupleDescRefCount ( TupleDesc  tupdesc)

Definition at line 339 of file tupdesc.c.

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

Referenced by cache_record_field_properties().

340 {
341  Assert(tupdesc->tdrefcount >= 0);
342 
344  tupdesc->tdrefcount++;
346 }
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
void ResourceOwnerRememberTupleDesc(ResourceOwner owner, TupleDesc tupdesc)
Definition: resowner.c:1094
void ResourceOwnerEnlargeTupleDescs(ResourceOwner owner)
Definition: resowner.c:1083
#define Assert(condition)
Definition: c.h:688
int tdrefcount
Definition: tupdesc.h:83

◆ TupleDescCopy()

void TupleDescCopy ( TupleDesc  dst,
TupleDesc  src 
)

Definition at line 213 of file tupdesc.c.

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

Referenced by share_tupledesc().

214 {
215  int i;
216 
217  /* Flat-copy the header and attribute array */
218  memcpy(dst, src, TupleDescSize(src));
219 
220  /*
221  * Since we're not copying constraints and defaults, clear fields
222  * associated with them.
223  */
224  for (i = 0; i < dst->natts; i++)
225  {
226  Form_pg_attribute att = TupleDescAttr(dst, i);
227 
228  att->attnotnull = false;
229  att->atthasdef = false;
230  att->attidentity = '\0';
231  }
232  dst->constr = NULL;
233 
234  /*
235  * Also, assume the destination is not to be ref-counted. (Copying the
236  * source's refcount would be wrong in any case.)
237  */
238  dst->tdrefcount = -1;
239 }
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
#define TupleDescSize(src)
Definition: tupdesc.h:101
int natts
Definition: tupdesc.h:79
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
TupleConstr * constr
Definition: tupdesc.h:84
int tdrefcount
Definition: tupdesc.h:83
int i

◆ TupleDescCopyEntry()

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

Definition at line 249 of file tupdesc.c.

References AssertArg, ATTRIBUTE_FIXED_PART_SIZE, PointerIsValid, and TupleDescAttr.

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

251 {
252  Form_pg_attribute dstAtt = TupleDescAttr(dst, dstAttno - 1);
253  Form_pg_attribute srcAtt = TupleDescAttr(src, srcAttno - 1);
254 
255  /*
256  * sanity checks
257  */
260  AssertArg(srcAttno >= 1);
261  AssertArg(srcAttno <= src->natts);
262  AssertArg(dstAttno >= 1);
263  AssertArg(dstAttno <= dst->natts);
264 
265  memcpy(dstAtt, srcAtt, ATTRIBUTE_FIXED_PART_SIZE);
266 
267  /*
268  * Aside from updating the attno, we'd better reset attcacheoff.
269  *
270  * XXX Actually, to be entirely safe we'd need to reset the attcacheoff of
271  * all following columns in dst as well. Current usage scenarios don't
272  * require that though, because all following columns will get initialized
273  * by other uses of this function or TupleDescInitEntry. So we cheat a
274  * bit to avoid a useless O(N^2) penalty.
275  */
276  dstAtt->attnum = dstAttno;
277  dstAtt->attcacheoff = -1;
278 
279  /* since we're not copying constraints or defaults, clear these */
280  dstAtt->attnotnull = false;
281  dstAtt->atthasdef = false;
282  dstAtt->attidentity = '\0';
283 }
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define ATTRIBUTE_FIXED_PART_SIZE
Definition: pg_attribute.h:179
#define AssertArg(condition)
Definition: c.h:690
#define PointerIsValid(pointer)
Definition: c.h:582

◆ TupleDescInitBuiltinEntry()

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

Definition at line 614 of file tupdesc.c.

References Assert, AssertArg, BOOLOID, DEFAULT_COLLATION_OID, INT4OID, INT8OID, InvalidOid, namestrcpy(), PointerIsValid, TEXTARRAYOID, TEXTOID, and TupleDescAttr.

Referenced by CreateReplicationSlot(), IdentifySystem(), ShowAllGUCConfig(), ShowGUCConfigOption(), and StartReplication().

620 {
621  Form_pg_attribute att;
622 
623  /* sanity checks */
624  AssertArg(PointerIsValid(desc));
625  AssertArg(attributeNumber >= 1);
626  AssertArg(attributeNumber <= desc->natts);
627 
628  /* initialize the attribute fields */
629  att = TupleDescAttr(desc, attributeNumber - 1);
630  att->attrelid = 0; /* dummy value */
631 
632  /* unlike TupleDescInitEntry, we require an attribute name */
633  Assert(attributeName != NULL);
634  namestrcpy(&(att->attname), attributeName);
635 
636  att->attstattarget = -1;
637  att->attcacheoff = -1;
638  att->atttypmod = typmod;
639 
640  att->attnum = attributeNumber;
641  att->attndims = attdim;
642 
643  att->attnotnull = false;
644  att->atthasdef = false;
645  att->attidentity = '\0';
646  att->attisdropped = false;
647  att->attislocal = true;
648  att->attinhcount = 0;
649  /* attacl, attoptions and attfdwoptions are not present in tupledescs */
650 
651  att->atttypid = oidtypeid;
652 
653  /*
654  * Our goal here is to support just enough types to let basic builtin
655  * commands work without catalog access - e.g. so that we can do certain
656  * things even in processes that are not connected to a database.
657  */
658  switch (oidtypeid)
659  {
660  case TEXTOID:
661  case TEXTARRAYOID:
662  att->attlen = -1;
663  att->attbyval = false;
664  att->attalign = 'i';
665  att->attstorage = 'x';
666  att->attcollation = DEFAULT_COLLATION_OID;
667  break;
668 
669  case BOOLOID:
670  att->attlen = 1;
671  att->attbyval = true;
672  att->attalign = 'c';
673  att->attstorage = 'p';
674  att->attcollation = InvalidOid;
675  break;
676 
677  case INT4OID:
678  att->attlen = 4;
679  att->attbyval = true;
680  att->attalign = 'i';
681  att->attstorage = 'p';
682  att->attcollation = InvalidOid;
683  break;
684 
685  case INT8OID:
686  att->attlen = 8;
687  att->attbyval = FLOAT8PASSBYVAL;
688  att->attalign = 'd';
689  att->attstorage = 'p';
690  att->attcollation = InvalidOid;
691  break;
692  }
693 }
#define TEXTOID
Definition: pg_type.h:324
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
#define INT4OID
Definition: pg_type.h:316
int namestrcpy(Name name, const char *str)
Definition: name.c:216
#define TEXTARRAYOID
Definition: pg_type.h:470
#define DEFAULT_COLLATION_OID
Definition: pg_collation.h:75
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define AssertArg(condition)
Definition: c.h:690
#define InvalidOid
Definition: postgres_ext.h:36
#define INT8OID
Definition: pg_type.h:304
#define Assert(condition)
Definition: c.h:688
#define BOOLOID
Definition: pg_type.h:288
#define PointerIsValid(pointer)
Definition: c.h:582

◆ TupleDescInitEntry()

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

Definition at line 543 of file tupdesc.c.

References AssertArg, elog, ERROR, GETSTRUCT, HeapTupleIsValid, MemSet, NAMEDATALEN, NameStr, namestrcpy(), ObjectIdGetDatum, 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_notify(), dblink_get_pkey(), ExecInitFunctionScan(), ExecMakeTableFunctionResult(), ExecTypeFromExprList(), ExecTypeFromTLInternal(), expandRecordVariable(), ExplainResultDesc(), GetPGVariableResultDesc(), gistrescan(), init_sexpr(), initGinState(), libpqrcv_processTuples(), materializeQueryResult(), materializeResult(), ordered_set_startup(), pg_buffercache_pages(), pg_control_checkpoint(), pg_control_init(), pg_control_recovery(), pg_control_system(), pg_cursor(), pg_get_keywords(), pg_get_multixact_members(), pg_get_object_address(), pg_identify_object(), pg_identify_object_as_address(), pg_last_committed_xact(), pg_lock_status(), pg_logdir_ls(), pg_ls_dir_files(), pg_prepared_statement(), pg_prepared_xact(), pg_sequence_parameters(), pg_stat_file(), pg_stat_get_archiver(), pg_timezone_abbrevs(), pg_timezone_names(), pg_visibility_map_summary(), pg_visibility_tupdesc(), pg_walfile_name_offset(), prs_setup_firstcall(), resolve_polymorphic_tupdesc(), show_all_file_settings(), show_all_settings(), ts_setup_firstcall(), tsvector_unnest(), tt_setup_firstcall(), and TypeGetTupleDesc().

549 {
550  HeapTuple tuple;
551  Form_pg_type typeForm;
552  Form_pg_attribute att;
553 
554  /*
555  * sanity checks
556  */
557  AssertArg(PointerIsValid(desc));
558  AssertArg(attributeNumber >= 1);
559  AssertArg(attributeNumber <= desc->natts);
560 
561  /*
562  * initialize the attribute fields
563  */
564  att = TupleDescAttr(desc, attributeNumber - 1);
565 
566  att->attrelid = 0; /* dummy value */
567 
568  /*
569  * Note: attributeName can be NULL, because the planner doesn't always
570  * fill in valid resname values in targetlists, particularly for resjunk
571  * attributes. Also, do nothing if caller wants to re-use the old attname.
572  */
573  if (attributeName == NULL)
574  MemSet(NameStr(att->attname), 0, NAMEDATALEN);
575  else if (attributeName != NameStr(att->attname))
576  namestrcpy(&(att->attname), attributeName);
577 
578  att->attstattarget = -1;
579  att->attcacheoff = -1;
580  att->atttypmod = typmod;
581 
582  att->attnum = attributeNumber;
583  att->attndims = attdim;
584 
585  att->attnotnull = false;
586  att->atthasdef = false;
587  att->attidentity = '\0';
588  att->attisdropped = false;
589  att->attislocal = true;
590  att->attinhcount = 0;
591  /* attacl, attoptions and attfdwoptions are not present in tupledescs */
592 
593  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(oidtypeid));
594  if (!HeapTupleIsValid(tuple))
595  elog(ERROR, "cache lookup failed for type %u", oidtypeid);
596  typeForm = (Form_pg_type) GETSTRUCT(tuple);
597 
598  att->atttypid = oidtypeid;
599  att->attlen = typeForm->typlen;
600  att->attbyval = typeForm->typbyval;
601  att->attalign = typeForm->typalign;
602  att->attstorage = typeForm->typstorage;
603  att->attcollation = typeForm->typcollation;
604 
605  ReleaseSysCache(tuple);
606 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
#define MemSet(start, val, len)
Definition: c.h:897
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
int namestrcpy(Name name, const char *str)
Definition: name.c:216
#define NAMEDATALEN
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define AssertArg(condition)
Definition: c.h:690
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NameStr(name)
Definition: c.h:565
#define elog
Definition: elog.h:219
#define PointerIsValid(pointer)
Definition: c.h:582

◆ TupleDescInitEntryCollation()

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

Definition at line 702 of file tupdesc.c.

References AssertArg, PointerIsValid, and TupleDescAttr.

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

705 {
706  /*
707  * sanity checks
708  */
709  AssertArg(PointerIsValid(desc));
710  AssertArg(attributeNumber >= 1);
711  AssertArg(attributeNumber <= desc->natts);
712 
713  TupleDescAttr(desc, attributeNumber - 1)->attcollation = collationid;
714 }
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
#define AssertArg(condition)
Definition: c.h:690
#define PointerIsValid(pointer)
Definition: c.h:582