PostgreSQL Source Code  git master
typcache.h File Reference
#include "access/tupdesc.h"
#include "fmgr.h"
#include "storage/dsm.h"
#include "utils/dsa.h"
Include dependency graph for typcache.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  TypeCacheEntry
 
struct  DomainConstraintRef
 

Macros

#define TYPECACHE_EQ_OPR   0x0001
 
#define TYPECACHE_LT_OPR   0x0002
 
#define TYPECACHE_GT_OPR   0x0004
 
#define TYPECACHE_CMP_PROC   0x0008
 
#define TYPECACHE_HASH_PROC   0x0010
 
#define TYPECACHE_EQ_OPR_FINFO   0x0020
 
#define TYPECACHE_CMP_PROC_FINFO   0x0040
 
#define TYPECACHE_HASH_PROC_FINFO   0x0080
 
#define TYPECACHE_TUPDESC   0x0100
 
#define TYPECACHE_BTREE_OPFAMILY   0x0200
 
#define TYPECACHE_HASH_OPFAMILY   0x0400
 
#define TYPECACHE_RANGE_INFO   0x0800
 
#define TYPECACHE_DOMAIN_BASE_INFO   0x1000
 
#define TYPECACHE_DOMAIN_CONSTR_INFO   0x2000
 
#define TYPECACHE_HASH_EXTENDED_PROC   0x4000
 
#define TYPECACHE_HASH_EXTENDED_PROC_FINFO   0x8000
 
#define INVALID_TUPLEDESC_IDENTIFIER   ((uint64) 1)
 

Typedefs

typedef struct DomainConstraintCache DomainConstraintCache
 
typedef struct TypeCacheEntry TypeCacheEntry
 
typedef struct DomainConstraintRef DomainConstraintRef
 
typedef struct SharedRecordTypmodRegistry SharedRecordTypmodRegistry
 

Functions

TypeCacheEntrylookup_type_cache (Oid type_id, int flags)
 
void InitDomainConstraintRef (Oid type_id, DomainConstraintRef *ref, MemoryContext refctx, bool need_exprstate)
 
void UpdateDomainConstraintRef (DomainConstraintRef *ref)
 
bool DomainHasConstraints (Oid type_id)
 
TupleDesc lookup_rowtype_tupdesc (Oid type_id, int32 typmod)
 
TupleDesc lookup_rowtype_tupdesc_noerror (Oid type_id, int32 typmod, bool noError)
 
TupleDesc lookup_rowtype_tupdesc_copy (Oid type_id, int32 typmod)
 
TupleDesc lookup_rowtype_tupdesc_domain (Oid type_id, int32 typmod, bool noError)
 
void assign_record_type_typmod (TupleDesc tupDesc)
 
uint64 assign_record_type_identifier (Oid type_id, int32 typmod)
 
int compare_values_of_enum (TypeCacheEntry *tcache, Oid arg1, Oid arg2)
 
size_t SharedRecordTypmodRegistryEstimate (void)
 
void SharedRecordTypmodRegistryInit (SharedRecordTypmodRegistry *, dsm_segment *segment, dsa_area *area)
 
void SharedRecordTypmodRegistryAttach (SharedRecordTypmodRegistry *)
 

Macro Definition Documentation

◆ INVALID_TUPLEDESC_IDENTIFIER

#define INVALID_TUPLEDESC_IDENTIFIER   ((uint64) 1)

◆ TYPECACHE_BTREE_OPFAMILY

#define TYPECACHE_BTREE_OPFAMILY   0x0200

Definition at line 137 of file typcache.h.

Referenced by lookup_type_cache().

◆ TYPECACHE_CMP_PROC

◆ TYPECACHE_CMP_PROC_FINFO

#define TYPECACHE_CMP_PROC_FINFO   0x0040

◆ TYPECACHE_DOMAIN_BASE_INFO

◆ TYPECACHE_DOMAIN_CONSTR_INFO

#define TYPECACHE_DOMAIN_CONSTR_INFO   0x2000

Definition at line 141 of file typcache.h.

Referenced by DomainHasConstraints(), InitDomainConstraintRef(), and lookup_type_cache().

◆ TYPECACHE_EQ_OPR

◆ TYPECACHE_EQ_OPR_FINFO

#define TYPECACHE_EQ_OPR_FINFO   0x0020

◆ TYPECACHE_GT_OPR

#define TYPECACHE_GT_OPR   0x0004

◆ TYPECACHE_HASH_EXTENDED_PROC

#define TYPECACHE_HASH_EXTENDED_PROC   0x4000

◆ TYPECACHE_HASH_EXTENDED_PROC_FINFO

#define TYPECACHE_HASH_EXTENDED_PROC_FINFO   0x8000

Definition at line 143 of file typcache.h.

Referenced by hash_array_extended(), hash_range_extended(), and lookup_type_cache().

◆ TYPECACHE_HASH_OPFAMILY

#define TYPECACHE_HASH_OPFAMILY   0x0400

Definition at line 138 of file typcache.h.

Referenced by lookup_type_cache().

◆ TYPECACHE_HASH_PROC

#define TYPECACHE_HASH_PROC   0x0010

◆ TYPECACHE_HASH_PROC_FINFO

#define TYPECACHE_HASH_PROC_FINFO   0x0080

Definition at line 135 of file typcache.h.

Referenced by array_typanalyze(), hash_array(), hash_range(), and lookup_type_cache().

◆ TYPECACHE_LT_OPR

◆ TYPECACHE_RANGE_INFO

#define TYPECACHE_RANGE_INFO   0x0800

Definition at line 139 of file typcache.h.

Referenced by get_range_io_data(), lookup_type_cache(), and range_get_typcache().

◆ TYPECACHE_TUPDESC

Typedef Documentation

◆ DomainConstraintCache

Definition at line 26 of file typcache.h.

◆ DomainConstraintRef

◆ SharedRecordTypmodRegistry

Definition at line 166 of file typcache.h.

◆ TypeCacheEntry

Function Documentation

◆ assign_record_type_identifier()

uint64 assign_record_type_identifier ( Oid  type_id,
int32  typmod 
)

Definition at line 1847 of file typcache.c.

References Assert, ereport, errcode(), errmsg(), ERROR, format_type_be(), lookup_type_cache(), RecordCacheArrayLen, RecordIdentifierArray, TypeCacheEntry::tupDesc, TypeCacheEntry::tupDesc_identifier, tupledesc_id_counter, and TYPECACHE_TUPDESC.

Referenced by expanded_record_fetch_tupdesc(), make_expanded_record_from_tupdesc(), and make_expanded_record_from_typeid().

1848 {
1849  if (type_id != RECORDOID)
1850  {
1851  /*
1852  * It's a named composite type, so use the regular typcache.
1853  */
1854  TypeCacheEntry *typentry;
1855 
1856  typentry = lookup_type_cache(type_id, TYPECACHE_TUPDESC);
1857  if (typentry->tupDesc == NULL)
1858  ereport(ERROR,
1859  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1860  errmsg("type %s is not composite",
1861  format_type_be(type_id))));
1862  Assert(typentry->tupDesc_identifier != 0);
1863  return typentry->tupDesc_identifier;
1864  }
1865  else
1866  {
1867  /*
1868  * It's a transient record type, so look in our record-type table.
1869  */
1870  if (typmod >= 0 && typmod < RecordCacheArrayLen &&
1871  RecordCacheArray[typmod] != NULL)
1872  {
1873  Assert(RecordIdentifierArray[typmod] != 0);
1874  return RecordIdentifierArray[typmod];
1875  }
1876 
1877  /* For anonymous or unrecognized record type, generate a new ID */
1878  return ++tupledesc_id_counter;
1879  }
1880 }
int errcode(int sqlerrcode)
Definition: elog.c:570
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
static uint64 tupledesc_id_counter
Definition: typcache.c:277
static TupleDesc * RecordCacheArray
Definition: typcache.c:267
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
static int32 RecordCacheArrayLen
Definition: typcache.c:269
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:322
#define Assert(condition)
Definition: c.h:732
uint64 tupDesc_identifier
Definition: typcache.h:87
int errmsg(const char *fmt,...)
Definition: elog.c:784
TupleDesc tupDesc
Definition: typcache.h:86
#define TYPECACHE_TUPDESC
Definition: typcache.h:136
static uint64 * RecordIdentifierArray
Definition: typcache.c:268

◆ assign_record_type_typmod()

void assign_record_type_typmod ( TupleDesc  tupDesc)

Definition at line 1772 of file typcache.c.

References Assert, CacheMemoryContext, CreateCacheMemoryContext(), CreateTupleDescCopy(), ensure_record_cache_typmod_slot_exists(), HASHCTL::entrysize, find_or_make_matching_shared_tupledesc(), HASHCTL::hash, HASH_COMPARE, hash_create(), HASH_ELEM, HASH_ENTER, HASH_FUNCTION, hash_search(), HASHCTL::keysize, HASHCTL::match, MemoryContextSwitchTo(), MemSet, NextRecordTypmod, record_type_typmod_compare(), record_type_typmod_hash(), RecordIdentifierArray, TupleDescData::tdrefcount, TupleDescData::tdtypeid, TupleDescData::tdtypmod, RecordCacheEntry::tupdesc, and tupledesc_id_counter.

Referenced by BlessTupleDesc(), ER_get_flat_size(), internal_get_result_type(), and SPI_returntuple().

1773 {
1774  RecordCacheEntry *recentry;
1775  TupleDesc entDesc;
1776  bool found;
1777  MemoryContext oldcxt;
1778 
1779  Assert(tupDesc->tdtypeid == RECORDOID);
1780 
1781  if (RecordCacheHash == NULL)
1782  {
1783  /* First time through: initialize the hash table */
1784  HASHCTL ctl;
1785 
1786  MemSet(&ctl, 0, sizeof(ctl));
1787  ctl.keysize = sizeof(TupleDesc); /* just the pointer */
1788  ctl.entrysize = sizeof(RecordCacheEntry);
1791  RecordCacheHash = hash_create("Record information cache", 64,
1792  &ctl,
1794 
1795  /* Also make sure CacheMemoryContext exists */
1796  if (!CacheMemoryContext)
1798  }
1799 
1800  /* Find or create a hashtable entry for this tuple descriptor */
1802  (void *) &tupDesc,
1803  HASH_ENTER, &found);
1804  if (found && recentry->tupdesc != NULL)
1805  {
1806  tupDesc->tdtypmod = recentry->tupdesc->tdtypmod;
1807  return;
1808  }
1809 
1810  /* Not present, so need to manufacture an entry */
1811  recentry->tupdesc = NULL;
1813 
1814  /* Look in the SharedRecordTypmodRegistry, if attached */
1815  entDesc = find_or_make_matching_shared_tupledesc(tupDesc);
1816  if (entDesc == NULL)
1817  {
1818  /* Reference-counted local cache only. */
1819  entDesc = CreateTupleDescCopy(tupDesc);
1820  entDesc->tdrefcount = 1;
1821  entDesc->tdtypmod = NextRecordTypmod++;
1822  }
1824  RecordCacheArray[entDesc->tdtypmod] = entDesc;
1825  recentry->tupdesc = entDesc;
1826 
1827  /* Assign a unique tupdesc identifier, too. */
1829 
1830  /* Update the caller's tuple descriptor. */
1831  tupDesc->tdtypmod = entDesc->tdtypmod;
1832 
1833  MemoryContextSwitchTo(oldcxt);
1834 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
#define HASH_ELEM
Definition: hsearch.h:87
static TupleDesc find_or_make_matching_shared_tupledesc(TupleDesc tupdesc)
Definition: typcache.c:2531
struct RecordCacheEntry RecordCacheEntry
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:955
static uint64 tupledesc_id_counter
Definition: typcache.c:277
static HTAB * RecordCacheHash
Definition: typcache.c:264
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
static TupleDesc * RecordCacheArray
Definition: typcache.c:267
int32 tdtypmod
Definition: tupdesc.h:83
static int32 NextRecordTypmod
Definition: typcache.c:270
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
static void ensure_record_cache_typmod_slot_exists(int32 typmod)
Definition: typcache.c:1524
Size keysize
Definition: hsearch.h:72
HashCompareFunc match
Definition: hsearch.h:75
static uint32 record_type_typmod_hash(const void *data, size_t size)
Definition: typcache.c:1745
#define Assert(condition)
Definition: c.h:732
#define HASH_COMPARE
Definition: hsearch.h:90
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
Oid tdtypeid
Definition: tupdesc.h:82
struct TupleDescData * TupleDesc
Definition: tupdesc.h:89
static int record_type_typmod_compare(const void *a, const void *b, size_t size)
Definition: typcache.c:1756
TupleDesc tupdesc
Definition: typcache.c:149
int tdrefcount
Definition: tupdesc.h:84
static uint64 * RecordIdentifierArray
Definition: typcache.c:268
HashValueFunc hash
Definition: hsearch.h:74
#define HASH_FUNCTION
Definition: hsearch.h:89
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ compare_values_of_enum()

int compare_values_of_enum ( TypeCacheEntry tcache,
Oid  arg1,
Oid  arg2 
)

Definition at line 2247 of file typcache.c.

References elog, enum_known_sorted(), TypeCacheEntry::enumData, ERROR, find_enumitem(), format_type_be(), load_enum_cache_data(), EnumItem::sort_order, and TypeCacheEntry::type_id.

Referenced by enum_cmp_internal().

2248 {
2249  TypeCacheEnumData *enumdata;
2250  EnumItem *item1;
2251  EnumItem *item2;
2252 
2253  /*
2254  * Equal OIDs are certainly equal --- this case was probably handled by
2255  * our caller, but we may as well check.
2256  */
2257  if (arg1 == arg2)
2258  return 0;
2259 
2260  /* Load up the cache if first time through */
2261  if (tcache->enumData == NULL)
2262  load_enum_cache_data(tcache);
2263  enumdata = tcache->enumData;
2264 
2265  /*
2266  * If both OIDs are known-sorted, we can just compare them directly.
2267  */
2268  if (enum_known_sorted(enumdata, arg1) &&
2269  enum_known_sorted(enumdata, arg2))
2270  {
2271  if (arg1 < arg2)
2272  return -1;
2273  else
2274  return 1;
2275  }
2276 
2277  /*
2278  * Slow path: we have to identify their actual sort-order positions.
2279  */
2280  item1 = find_enumitem(enumdata, arg1);
2281  item2 = find_enumitem(enumdata, arg2);
2282 
2283  if (item1 == NULL || item2 == NULL)
2284  {
2285  /*
2286  * We couldn't find one or both values. That means the enum has
2287  * changed under us, so re-initialize the cache and try again. We
2288  * don't bother retrying the known-sorted case in this path.
2289  */
2290  load_enum_cache_data(tcache);
2291  enumdata = tcache->enumData;
2292 
2293  item1 = find_enumitem(enumdata, arg1);
2294  item2 = find_enumitem(enumdata, arg2);
2295 
2296  /*
2297  * If we still can't find the values, complain: we must have corrupt
2298  * data.
2299  */
2300  if (item1 == NULL)
2301  elog(ERROR, "enum value %u not found in cache for enum %s",
2302  arg1, format_type_be(tcache->type_id));
2303  if (item2 == NULL)
2304  elog(ERROR, "enum value %u not found in cache for enum %s",
2305  arg2, format_type_be(tcache->type_id));
2306  }
2307 
2308  if (item1->sort_order < item2->sort_order)
2309  return -1;
2310  else if (item1->sort_order > item2->sort_order)
2311  return 1;
2312  else
2313  return 0;
2314 }
struct TypeCacheEnumData * enumData
Definition: typcache.h:121
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
#define ERROR
Definition: elog.h:43
static bool enum_known_sorted(TypeCacheEnumData *enumdata, Oid arg)
Definition: typcache.c:2218
static EnumItem * find_enumitem(TypeCacheEnumData *enumdata, Oid arg)
Definition: typcache.c:2475
static void load_enum_cache_data(TypeCacheEntry *tcache)
Definition: typcache.c:2320
float4 sort_order
Definition: typcache.c:125
#define elog(elevel,...)
Definition: elog.h:226

◆ DomainHasConstraints()

bool DomainHasConstraints ( Oid  type_id)

Definition at line 1289 of file typcache.c.

References TypeCacheEntry::domainData, lookup_type_cache(), and TYPECACHE_DOMAIN_CONSTR_INFO.

Referenced by ATColumnChangeRequiresRewrite(), ATExecAddColumn(), and eval_const_expressions_mutator().

1290 {
1291  TypeCacheEntry *typentry;
1292 
1293  /*
1294  * Note: a side effect is to cause the typcache's domain data to become
1295  * valid. This is fine since we'll likely need it soon if there is any.
1296  */
1297  typentry = lookup_type_cache(type_id, TYPECACHE_DOMAIN_CONSTR_INFO);
1298 
1299  return (typentry->domainData != NULL);
1300 }
DomainConstraintCache * domainData
Definition: typcache.h:112
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:322
#define TYPECACHE_DOMAIN_CONSTR_INFO
Definition: typcache.h:141

◆ InitDomainConstraintRef()

void InitDomainConstraintRef ( Oid  type_id,
DomainConstraintRef ref,
MemoryContext  refctx,
bool  need_exprstate 
)

Definition at line 1202 of file typcache.c.

References MemoryContextCallback::arg, DomainConstraintRef::callback, DomainConstraintCache::constraints, DomainConstraintRef::constraints, DomainConstraintRef::dcc, dccref_deletion_callback(), DomainConstraintCache::dccRefCount, TypeCacheEntry::domainData, MemoryContextCallback::func, lookup_type_cache(), MemoryContextRegisterResetCallback(), DomainConstraintRef::need_exprstate, NIL, prep_domain_constraints(), DomainConstraintRef::refctx, DomainConstraintRef::tcache, and TYPECACHE_DOMAIN_CONSTR_INFO.

Referenced by domain_state_setup(), and ExecInitCoerceToDomain().

1204 {
1205  /* Look up the typcache entry --- we assume it survives indefinitely */
1207  ref->need_exprstate = need_exprstate;
1208  /* For safety, establish the callback before acquiring a refcount */
1209  ref->refctx = refctx;
1210  ref->dcc = NULL;
1212  ref->callback.arg = (void *) ref;
1214  /* Acquire refcount if there are constraints, and set up exported list */
1215  if (ref->tcache->domainData)
1216  {
1217  ref->dcc = ref->tcache->domainData;
1218  ref->dcc->dccRefCount++;
1219  if (ref->need_exprstate)
1221  ref->refctx);
1222  else
1223  ref->constraints = ref->dcc->constraints;
1224  }
1225  else
1226  ref->constraints = NIL;
1227 }
MemoryContextCallback callback
Definition: typcache.h:163
MemoryContextCallbackFunction func
Definition: palloc.h:49
#define NIL
Definition: pg_list.h:65
DomainConstraintCache * dcc
Definition: typcache.h:162
static void dccref_deletion_callback(void *arg)
Definition: typcache.c:1143
DomainConstraintCache * domainData
Definition: typcache.h:112
MemoryContext refctx
Definition: typcache.h:157
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:322
static List * prep_domain_constraints(List *constraints, MemoryContext execctx)
Definition: typcache.c:1164
#define TYPECACHE_DOMAIN_CONSTR_INFO
Definition: typcache.h:141
TypeCacheEntry * tcache
Definition: typcache.h:158
void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)
Definition: mcxt.c:285

◆ lookup_rowtype_tupdesc()

◆ lookup_rowtype_tupdesc_copy()

TupleDesc lookup_rowtype_tupdesc_copy ( Oid  type_id,
int32  typmod 
)

Definition at line 1686 of file typcache.c.

References CreateTupleDescCopyConstr(), and lookup_rowtype_tupdesc_internal().

Referenced by ExecInitExprRec(), ExecMakeTableFunctionResult(), get_expr_result_type(), internal_get_result_type(), and TypeGetTupleDesc().

1687 {
1688  TupleDesc tmp;
1689 
1690  tmp = lookup_rowtype_tupdesc_internal(type_id, typmod, false);
1691  return CreateTupleDescCopyConstr(tmp);
1692 }
TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc)
Definition: tupdesc.c:150
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1561

◆ lookup_rowtype_tupdesc_domain()

TupleDesc lookup_rowtype_tupdesc_domain ( Oid  type_id,
int32  typmod,
bool  noError 
)

Definition at line 1708 of file typcache.c.

References TypeCacheEntry::domainBaseType, TypeCacheEntry::domainBaseTypmod, ereport, errcode(), errmsg(), ERROR, format_type_be(), lookup_rowtype_tupdesc_internal(), lookup_rowtype_tupdesc_noerror(), lookup_type_cache(), PinTupleDesc, TypeCacheEntry::tupDesc, TYPECACHE_DOMAIN_BASE_INFO, TYPECACHE_TUPDESC, and TypeCacheEntry::typtype.

Referenced by ExecEvalWholeRowVar(), hstore_from_record(), hstore_populate_record(), plperl_sv_to_datum(), and rowtype_field_matches().

1709 {
1710  TupleDesc tupDesc;
1711 
1712  if (type_id != RECORDOID)
1713  {
1714  /*
1715  * Check for domain or named composite type. We might as well load
1716  * whichever data is needed.
1717  */
1718  TypeCacheEntry *typentry;
1719 
1720  typentry = lookup_type_cache(type_id,
1723  if (typentry->typtype == TYPTYPE_DOMAIN)
1725  typentry->domainBaseTypmod,
1726  noError);
1727  if (typentry->tupDesc == NULL && !noError)
1728  ereport(ERROR,
1729  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1730  errmsg("type %s is not composite",
1731  format_type_be(type_id))));
1732  tupDesc = typentry->tupDesc;
1733  }
1734  else
1735  tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, noError);
1736  if (tupDesc != NULL)
1737  PinTupleDesc(tupDesc);
1738  return tupDesc;
1739 }
int errcode(int sqlerrcode)
Definition: elog.c:570
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
Oid domainBaseType
Definition: typcache.h:105
#define ERROR
Definition: elog.h:43
int32 domainBaseTypmod
Definition: typcache.h:106
TupleDesc lookup_rowtype_tupdesc_noerror(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1669
#define ereport(elevel, rest)
Definition: elog.h:141
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:140
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:322
char typtype
Definition: typcache.h:41
#define PinTupleDesc(tupdesc)
Definition: tupdesc.h:116
int errmsg(const char *fmt,...)
Definition: elog.c:784
TupleDesc tupDesc
Definition: typcache.h:86
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1561
#define TYPECACHE_TUPDESC
Definition: typcache.h:136

◆ lookup_rowtype_tupdesc_noerror()

TupleDesc lookup_rowtype_tupdesc_noerror ( Oid  type_id,
int32  typmod,
bool  noError 
)

Definition at line 1669 of file typcache.c.

References lookup_rowtype_tupdesc_internal(), and PinTupleDesc.

Referenced by lookup_rowtype_tupdesc_domain().

1670 {
1671  TupleDesc tupDesc;
1672 
1673  tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, noError);
1674  if (tupDesc != NULL)
1675  PinTupleDesc(tupDesc);
1676  return tupDesc;
1677 }
#define PinTupleDesc(tupdesc)
Definition: tupdesc.h:116
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1561

◆ lookup_type_cache()

TypeCacheEntry* lookup_type_cache ( Oid  type_id,
int  flags 
)

Definition at line 322 of file typcache.c.

References array_element_has_compare(), array_element_has_equality(), array_element_has_extended_hashing(), array_element_has_hashing(), Assert, BTEqualStrategyNumber, BTGreaterStrategyNumber, BTLessStrategyNumber, BTORDER_PROC, TypeCacheEntry::btree_opf, TypeCacheEntry::btree_opintype, CacheMemoryContext, CacheRegisterRelcacheCallback(), CacheRegisterSyscacheCallback(), CLAOID, TypeCacheEntry::cmp_proc, TypeCacheEntry::cmp_proc_finfo, CONSTROID, CreateCacheMemoryContext(), TypeCacheEntry::domainBaseType, TypeCacheEntry::domainBaseTypmod, HASHCTL::entrysize, TypeCacheEntry::eq_opr, TypeCacheEntry::eq_opr_finfo, ereport, errcode(), errmsg(), ERROR, firstDomainTypeEntry, TypeCacheEntry::flags, fmgr_info_cxt(), FmgrInfo::fn_oid, get_opclass_family(), get_opclass_input_type(), get_opcode(), get_opfamily_member(), get_opfamily_proc(), getBaseTypeAndTypmod(), GetDefaultOpClass(), GETSTRUCT, TypeCacheEntry::gt_opr, HASH_BLOBS, hash_create(), HASH_ELEM, HASH_ENTER, TypeCacheEntry::hash_extended_proc, TypeCacheEntry::hash_extended_proc_finfo, HASH_FIND, TypeCacheEntry::hash_opf, TypeCacheEntry::hash_opintype, TypeCacheEntry::hash_proc, TypeCacheEntry::hash_proc_finfo, hash_search(), HASHEXTENDED_PROC, HASHSTANDARD_PROC, HeapTupleIsValid, HTEqualStrategyNumber, InvalidOid, HASHCTL::keysize, load_domaintype_info(), load_rangetype_info(), load_typcache_tupdesc(), TypeCacheEntry::lt_opr, MemSet, NameStr, TypeCacheEntry::nextDomain, ObjectIdGetDatum, OidIsValid, range_element_has_extended_hashing(), range_element_has_hashing(), record_fields_have_compare(), record_fields_have_equality(), ReleaseSysCache(), TypeCacheEntry::rngelemtype, SearchSysCache1(), TCFLAGS_CHECKED_BTREE_OPCLASS, TCFLAGS_CHECKED_CMP_PROC, TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS, TCFLAGS_CHECKED_EQ_OPR, TCFLAGS_CHECKED_GT_OPR, TCFLAGS_CHECKED_HASH_EXTENDED_PROC, TCFLAGS_CHECKED_HASH_OPCLASS, TCFLAGS_CHECKED_HASH_PROC, TCFLAGS_CHECKED_LT_OPR, TypeCacheEntry::tupDesc, TypeCacheEntry::typalign, TypeCacheEntry::typbyval, TypeCacheEntry::typcollation, TypeCacheEntry::type_id, TYPECACHE_BTREE_OPFAMILY, TYPECACHE_CMP_PROC, TYPECACHE_CMP_PROC_FINFO, TYPECACHE_DOMAIN_BASE_INFO, TYPECACHE_DOMAIN_CONSTR_INFO, TYPECACHE_EQ_OPR, TYPECACHE_EQ_OPR_FINFO, TYPECACHE_GT_OPR, TYPECACHE_HASH_EXTENDED_PROC, TYPECACHE_HASH_EXTENDED_PROC_FINFO, TYPECACHE_HASH_OPFAMILY, TYPECACHE_HASH_PROC, TYPECACHE_HASH_PROC_FINFO, TYPECACHE_LT_OPR, TYPECACHE_RANGE_INFO, TYPECACHE_TUPDESC, TypeCacheConstrCallback(), TypeCacheOpcCallback(), TypeCacheRelCallback(), TypeCacheEntry::typelem, TYPEOID, TypeCacheEntry::typlen, TypeCacheEntry::typrelid, TypeCacheEntry::typstorage, and TypeCacheEntry::typtype.

Referenced by appendAggOrderBy(), array_cmp(), array_contain_compare(), array_eq(), array_position_common(), array_positions(), array_replace_internal(), array_typanalyze(), assign_record_type_identifier(), brin_inclusion_opcinfo(), brin_minmax_opcinfo(), build_datatype(), build_mss(), cache_array_element_properties(), cache_range_element_properties(), cache_record_field_properties(), calc_arraycontsel(), contain_leaked_vars_walker(), CreateStatistics(), dependency_degree(), domain_state_setup(), DomainHasConstraints(), enum_cmp_internal(), ExecInitExprRec(), foreign_expr_walker(), get_range_io_data(), get_rule_orderby(), get_sort_group_operators(), hash_array(), hash_array_extended(), hash_range(), hash_range_extended(), InitDomainConstraintRef(), initGinState(), load_rangetype_info(), lookup_rowtype_tupdesc_domain(), lookup_rowtype_tupdesc_internal(), make_expanded_record_from_tupdesc(), make_expanded_record_from_typeid(), ndistinct_for_combination(), op_hashjoinable(), op_mergejoinable(), PLy_input_setup_func(), PLy_output_setup_func(), range_get_typcache(), record_cmp(), record_eq(), revalidate_rectypeid(), scalararraysel(), scalararraysel_containment(), show_sortorder_options(), statext_mcv_serialize(), tuples_equal(), and width_bucket_array().

323 {
324  TypeCacheEntry *typentry;
325  bool found;
326 
327  if (TypeCacheHash == NULL)
328  {
329  /* First time through: initialize the hash table */
330  HASHCTL ctl;
331 
332  MemSet(&ctl, 0, sizeof(ctl));
333  ctl.keysize = sizeof(Oid);
334  ctl.entrysize = sizeof(TypeCacheEntry);
335  TypeCacheHash = hash_create("Type information cache", 64,
336  &ctl, HASH_ELEM | HASH_BLOBS);
337 
338  /* Also set up callbacks for SI invalidations */
343 
344  /* Also make sure CacheMemoryContext exists */
345  if (!CacheMemoryContext)
347  }
348 
349  /* Try to look up an existing entry */
351  (void *) &type_id,
352  HASH_FIND, NULL);
353  if (typentry == NULL)
354  {
355  /*
356  * If we didn't find one, we want to make one. But first look up the
357  * pg_type row, just to make sure we don't make a cache entry for an
358  * invalid type OID. If the type OID is not valid, present a
359  * user-facing error, since some code paths such as domain_in() allow
360  * this function to be reached with a user-supplied OID.
361  */
362  HeapTuple tp;
363  Form_pg_type typtup;
364 
365  tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_id));
366  if (!HeapTupleIsValid(tp))
367  ereport(ERROR,
368  (errcode(ERRCODE_UNDEFINED_OBJECT),
369  errmsg("type with OID %u does not exist", type_id)));
370  typtup = (Form_pg_type) GETSTRUCT(tp);
371  if (!typtup->typisdefined)
372  ereport(ERROR,
373  (errcode(ERRCODE_UNDEFINED_OBJECT),
374  errmsg("type \"%s\" is only a shell",
375  NameStr(typtup->typname))));
376 
377  /* Now make the typcache entry */
379  (void *) &type_id,
380  HASH_ENTER, &found);
381  Assert(!found); /* it wasn't there a moment ago */
382 
383  MemSet(typentry, 0, sizeof(TypeCacheEntry));
384  typentry->type_id = type_id;
385  typentry->typlen = typtup->typlen;
386  typentry->typbyval = typtup->typbyval;
387  typentry->typalign = typtup->typalign;
388  typentry->typstorage = typtup->typstorage;
389  typentry->typtype = typtup->typtype;
390  typentry->typrelid = typtup->typrelid;
391  typentry->typelem = typtup->typelem;
392  typentry->typcollation = typtup->typcollation;
393 
394  /* If it's a domain, immediately thread it into the domain cache list */
395  if (typentry->typtype == TYPTYPE_DOMAIN)
396  {
397  typentry->nextDomain = firstDomainTypeEntry;
398  firstDomainTypeEntry = typentry;
399  }
400 
401  ReleaseSysCache(tp);
402  }
403 
404  /*
405  * Look up opclasses if we haven't already and any dependent info is
406  * requested.
407  */
412  !(typentry->flags & TCFLAGS_CHECKED_BTREE_OPCLASS))
413  {
414  Oid opclass;
415 
416  opclass = GetDefaultOpClass(type_id, BTREE_AM_OID);
417  if (OidIsValid(opclass))
418  {
419  typentry->btree_opf = get_opclass_family(opclass);
420  typentry->btree_opintype = get_opclass_input_type(opclass);
421  }
422  else
423  {
424  typentry->btree_opf = typentry->btree_opintype = InvalidOid;
425  }
426 
427  /*
428  * Reset information derived from btree opclass. Note in particular
429  * that we'll redetermine the eq_opr even if we previously found one;
430  * this matters in case a btree opclass has been added to a type that
431  * previously had only a hash opclass.
432  */
433  typentry->flags &= ~(TCFLAGS_CHECKED_EQ_OPR |
438  }
439 
440  /*
441  * If we need to look up equality operator, and there's no btree opclass,
442  * force lookup of hash opclass.
443  */
444  if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO)) &&
445  !(typentry->flags & TCFLAGS_CHECKED_EQ_OPR) &&
446  typentry->btree_opf == InvalidOid)
447  flags |= TYPECACHE_HASH_OPFAMILY;
448 
453  !(typentry->flags & TCFLAGS_CHECKED_HASH_OPCLASS))
454  {
455  Oid opclass;
456 
457  opclass = GetDefaultOpClass(type_id, HASH_AM_OID);
458  if (OidIsValid(opclass))
459  {
460  typentry->hash_opf = get_opclass_family(opclass);
461  typentry->hash_opintype = get_opclass_input_type(opclass);
462  }
463  else
464  {
465  typentry->hash_opf = typentry->hash_opintype = InvalidOid;
466  }
467 
468  /*
469  * Reset information derived from hash opclass. We do *not* reset the
470  * eq_opr; if we already found one from the btree opclass, that
471  * decision is still good.
472  */
473  typentry->flags &= ~(TCFLAGS_CHECKED_HASH_PROC |
475  typentry->flags |= TCFLAGS_CHECKED_HASH_OPCLASS;
476  }
477 
478  /*
479  * Look for requested operators and functions, if we haven't already.
480  */
481  if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO)) &&
482  !(typentry->flags & TCFLAGS_CHECKED_EQ_OPR))
483  {
484  Oid eq_opr = InvalidOid;
485 
486  if (typentry->btree_opf != InvalidOid)
487  eq_opr = get_opfamily_member(typentry->btree_opf,
488  typentry->btree_opintype,
489  typentry->btree_opintype,
491  if (eq_opr == InvalidOid &&
492  typentry->hash_opf != InvalidOid)
493  eq_opr = get_opfamily_member(typentry->hash_opf,
494  typentry->hash_opintype,
495  typentry->hash_opintype,
497 
498  /*
499  * If the proposed equality operator is array_eq or record_eq, check
500  * to see if the element type or column types support equality. If
501  * not, array_eq or record_eq would fail at runtime, so we don't want
502  * to report that the type has equality. (We can omit similar
503  * checking for ranges because ranges can't be created in the first
504  * place unless their subtypes support equality.)
505  */
506  if (eq_opr == ARRAY_EQ_OP &&
507  !array_element_has_equality(typentry))
508  eq_opr = InvalidOid;
509  else if (eq_opr == RECORD_EQ_OP &&
510  !record_fields_have_equality(typentry))
511  eq_opr = InvalidOid;
512 
513  /* Force update of eq_opr_finfo only if we're changing state */
514  if (typentry->eq_opr != eq_opr)
515  typentry->eq_opr_finfo.fn_oid = InvalidOid;
516 
517  typentry->eq_opr = eq_opr;
518 
519  /*
520  * Reset info about hash functions whenever we pick up new info about
521  * equality operator. This is so we can ensure that the hash
522  * functions match the operator.
523  */
524  typentry->flags &= ~(TCFLAGS_CHECKED_HASH_PROC |
526  typentry->flags |= TCFLAGS_CHECKED_EQ_OPR;
527  }
528  if ((flags & TYPECACHE_LT_OPR) &&
529  !(typentry->flags & TCFLAGS_CHECKED_LT_OPR))
530  {
531  Oid lt_opr = InvalidOid;
532 
533  if (typentry->btree_opf != InvalidOid)
534  lt_opr = get_opfamily_member(typentry->btree_opf,
535  typentry->btree_opintype,
536  typentry->btree_opintype,
538 
539  /*
540  * As above, make sure array_cmp or record_cmp will succeed; but again
541  * we need no special check for ranges.
542  */
543  if (lt_opr == ARRAY_LT_OP &&
544  !array_element_has_compare(typentry))
545  lt_opr = InvalidOid;
546  else if (lt_opr == RECORD_LT_OP &&
547  !record_fields_have_compare(typentry))
548  lt_opr = InvalidOid;
549 
550  typentry->lt_opr = lt_opr;
551  typentry->flags |= TCFLAGS_CHECKED_LT_OPR;
552  }
553  if ((flags & TYPECACHE_GT_OPR) &&
554  !(typentry->flags & TCFLAGS_CHECKED_GT_OPR))
555  {
556  Oid gt_opr = InvalidOid;
557 
558  if (typentry->btree_opf != InvalidOid)
559  gt_opr = get_opfamily_member(typentry->btree_opf,
560  typentry->btree_opintype,
561  typentry->btree_opintype,
563 
564  /*
565  * As above, make sure array_cmp or record_cmp will succeed; but again
566  * we need no special check for ranges.
567  */
568  if (gt_opr == ARRAY_GT_OP &&
569  !array_element_has_compare(typentry))
570  gt_opr = InvalidOid;
571  else if (gt_opr == RECORD_GT_OP &&
572  !record_fields_have_compare(typentry))
573  gt_opr = InvalidOid;
574 
575  typentry->gt_opr = gt_opr;
576  typentry->flags |= TCFLAGS_CHECKED_GT_OPR;
577  }
578  if ((flags & (TYPECACHE_CMP_PROC | TYPECACHE_CMP_PROC_FINFO)) &&
579  !(typentry->flags & TCFLAGS_CHECKED_CMP_PROC))
580  {
581  Oid cmp_proc = InvalidOid;
582 
583  if (typentry->btree_opf != InvalidOid)
584  cmp_proc = get_opfamily_proc(typentry->btree_opf,
585  typentry->btree_opintype,
586  typentry->btree_opintype,
587  BTORDER_PROC);
588 
589  /*
590  * As above, make sure array_cmp or record_cmp will succeed; but again
591  * we need no special check for ranges.
592  */
593  if (cmp_proc == F_BTARRAYCMP &&
594  !array_element_has_compare(typentry))
595  cmp_proc = InvalidOid;
596  else if (cmp_proc == F_BTRECORDCMP &&
597  !record_fields_have_compare(typentry))
598  cmp_proc = InvalidOid;
599 
600  /* Force update of cmp_proc_finfo only if we're changing state */
601  if (typentry->cmp_proc != cmp_proc)
602  typentry->cmp_proc_finfo.fn_oid = InvalidOid;
603 
604  typentry->cmp_proc = cmp_proc;
605  typentry->flags |= TCFLAGS_CHECKED_CMP_PROC;
606  }
608  !(typentry->flags & TCFLAGS_CHECKED_HASH_PROC))
609  {
610  Oid hash_proc = InvalidOid;
611 
612  /*
613  * We insist that the eq_opr, if one has been determined, match the
614  * hash opclass; else report there is no hash function.
615  */
616  if (typentry->hash_opf != InvalidOid &&
617  (!OidIsValid(typentry->eq_opr) ||
618  typentry->eq_opr == get_opfamily_member(typentry->hash_opf,
619  typentry->hash_opintype,
620  typentry->hash_opintype,
622  hash_proc = get_opfamily_proc(typentry->hash_opf,
623  typentry->hash_opintype,
624  typentry->hash_opintype,
626 
627  /*
628  * As above, make sure hash_array will succeed. We don't currently
629  * support hashing for composite types, but when we do, we'll need
630  * more logic here to check that case too.
631  */
632  if (hash_proc == F_HASH_ARRAY &&
633  !array_element_has_hashing(typentry))
634  hash_proc = InvalidOid;
635 
636  /*
637  * Likewise for hash_range.
638  */
639  if (hash_proc == F_HASH_RANGE &&
640  !range_element_has_hashing(typentry))
641  hash_proc = InvalidOid;
642 
643  /* Force update of hash_proc_finfo only if we're changing state */
644  if (typentry->hash_proc != hash_proc)
645  typentry->hash_proc_finfo.fn_oid = InvalidOid;
646 
647  typentry->hash_proc = hash_proc;
648  typentry->flags |= TCFLAGS_CHECKED_HASH_PROC;
649  }
650  if ((flags & (TYPECACHE_HASH_EXTENDED_PROC |
653  {
654  Oid hash_extended_proc = InvalidOid;
655 
656  /*
657  * We insist that the eq_opr, if one has been determined, match the
658  * hash opclass; else report there is no hash function.
659  */
660  if (typentry->hash_opf != InvalidOid &&
661  (!OidIsValid(typentry->eq_opr) ||
662  typentry->eq_opr == get_opfamily_member(typentry->hash_opf,
663  typentry->hash_opintype,
664  typentry->hash_opintype,
666  hash_extended_proc = get_opfamily_proc(typentry->hash_opf,
667  typentry->hash_opintype,
668  typentry->hash_opintype,
670 
671  /*
672  * As above, make sure hash_array_extended will succeed. We don't
673  * currently support hashing for composite types, but when we do,
674  * we'll need more logic here to check that case too.
675  */
676  if (hash_extended_proc == F_HASH_ARRAY_EXTENDED &&
678  hash_extended_proc = InvalidOid;
679 
680  /*
681  * Likewise for hash_range_extended.
682  */
683  if (hash_extended_proc == F_HASH_RANGE_EXTENDED &&
685  hash_extended_proc = InvalidOid;
686 
687  /* Force update of proc finfo only if we're changing state */
688  if (typentry->hash_extended_proc != hash_extended_proc)
690 
691  typentry->hash_extended_proc = hash_extended_proc;
693  }
694 
695  /*
696  * Set up fmgr lookup info as requested
697  *
698  * Note: we tell fmgr the finfo structures live in CacheMemoryContext,
699  * which is not quite right (they're really in the hash table's private
700  * memory context) but this will do for our purposes.
701  *
702  * Note: the code above avoids invalidating the finfo structs unless the
703  * referenced operator/function OID actually changes. This is to prevent
704  * unnecessary leakage of any subsidiary data attached to an finfo, since
705  * that would cause session-lifespan memory leaks.
706  */
707  if ((flags & TYPECACHE_EQ_OPR_FINFO) &&
708  typentry->eq_opr_finfo.fn_oid == InvalidOid &&
709  typentry->eq_opr != InvalidOid)
710  {
711  Oid eq_opr_func;
712 
713  eq_opr_func = get_opcode(typentry->eq_opr);
714  if (eq_opr_func != InvalidOid)
715  fmgr_info_cxt(eq_opr_func, &typentry->eq_opr_finfo,
717  }
718  if ((flags & TYPECACHE_CMP_PROC_FINFO) &&
719  typentry->cmp_proc_finfo.fn_oid == InvalidOid &&
720  typentry->cmp_proc != InvalidOid)
721  {
722  fmgr_info_cxt(typentry->cmp_proc, &typentry->cmp_proc_finfo,
724  }
725  if ((flags & TYPECACHE_HASH_PROC_FINFO) &&
726  typentry->hash_proc_finfo.fn_oid == InvalidOid &&
727  typentry->hash_proc != InvalidOid)
728  {
729  fmgr_info_cxt(typentry->hash_proc, &typentry->hash_proc_finfo,
731  }
732  if ((flags & TYPECACHE_HASH_EXTENDED_PROC_FINFO) &&
734  typentry->hash_extended_proc != InvalidOid)
735  {
737  &typentry->hash_extended_proc_finfo,
739  }
740 
741  /*
742  * If it's a composite type (row type), get tupdesc if requested
743  */
744  if ((flags & TYPECACHE_TUPDESC) &&
745  typentry->tupDesc == NULL &&
746  typentry->typtype == TYPTYPE_COMPOSITE)
747  {
748  load_typcache_tupdesc(typentry);
749  }
750 
751  /*
752  * If requested, get information about a range type
753  */
754  if ((flags & TYPECACHE_RANGE_INFO) &&
755  typentry->rngelemtype == NULL &&
756  typentry->typtype == TYPTYPE_RANGE)
757  {
758  load_rangetype_info(typentry);
759  }
760 
761  /*
762  * If requested, get information about a domain type
763  */
764  if ((flags & TYPECACHE_DOMAIN_BASE_INFO) &&
765  typentry->domainBaseType == InvalidOid &&
766  typentry->typtype == TYPTYPE_DOMAIN)
767  {
768  typentry->domainBaseTypmod = -1;
769  typentry->domainBaseType =
770  getBaseTypeAndTypmod(type_id, &typentry->domainBaseTypmod);
771  }
772  if ((flags & TYPECACHE_DOMAIN_CONSTR_INFO) &&
773  (typentry->flags & TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS) == 0 &&
774  typentry->typtype == TYPTYPE_DOMAIN)
775  {
776  load_domaintype_info(typentry);
777  }
778 
779  return typentry;
780 }
static bool array_element_has_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1332
static void load_typcache_tupdesc(TypeCacheEntry *typentry)
Definition: typcache.c:786
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition: lsyscache.c:2316
#define BTORDER_PROC
Definition: nbtree.h:392
#define TYPECACHE_RANGE_INFO
Definition: typcache.h:139
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:1937
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Oid hash_opintype
Definition: typcache.h:57
#define TCFLAGS_CHECKED_EQ_OPR
Definition: typcache.c:85
#define HASH_ELEM
Definition: hsearch.h:87
static TypeCacheEntry * firstDomainTypeEntry
Definition: typcache.c:80
#define TYPECACHE_HASH_EXTENDED_PROC_FINFO
Definition: typcache.h:143
#define TCFLAGS_CHECKED_HASH_EXTENDED_PROC
Definition: typcache.c:90
struct TypeCacheEntry TypeCacheEntry
Oid typcollation
Definition: typcache.h:44
#define TYPECACHE_EQ_OPR_FINFO
Definition: typcache.h:133
#define TYPECACHE_HASH_PROC_FINFO
Definition: typcache.h:135
Size entrysize
Definition: hsearch.h:73
#define TYPECACHE_EQ_OPR
Definition: typcache.h:128
int errcode(int sqlerrcode)
Definition: elog.c:570
#define HASHEXTENDED_PROC
Definition: hash.h:338
#define MemSet(start, val, len)
Definition: c.h:955
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
unsigned int Oid
Definition: postgres_ext.h:31
int16 typlen
Definition: typcache.h:37
#define OidIsValid(objectId)
Definition: c.h:638
bool typbyval
Definition: typcache.h:38
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
Definition: inval.c:1468
Oid domainBaseType
Definition: typcache.h:105
FmgrInfo cmp_proc_finfo
Definition: typcache.h:73
struct TypeCacheEntry * nextDomain
Definition: typcache.h:124
#define TCFLAGS_CHECKED_GT_OPR
Definition: typcache.c:87
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define HTEqualStrategyNumber
Definition: stratnum.h:41
char typstorage
Definition: typcache.h:40
static void TypeCacheRelCallback(Datum arg, Oid relid)
Definition: typcache.c:2092
static bool array_element_has_compare(TypeCacheEntry *typentry)
Definition: typcache.c:1324
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:163
int32 domainBaseTypmod
Definition: typcache.h:106
Oid hash_extended_proc
Definition: typcache.h:63
FmgrInfo hash_proc_finfo
Definition: typcache.h:74
#define TYPECACHE_GT_OPR
Definition: typcache.h:130
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:134
#define HASHSTANDARD_PROC
Definition: hash.h:337
#define ereport(elevel, rest)
Definition: elog.h:141
#define TYPECACHE_BTREE_OPFAMILY
Definition: typcache.h:137
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:95
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:140
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
static bool range_element_has_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1480
#define HASH_BLOBS
Definition: hsearch.h:88
FmgrInfo hash_extended_proc_finfo
Definition: typcache.h:75
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1426
#define TYPECACHE_HASH_EXTENDED_PROC
Definition: typcache.h:142
uintptr_t Datum
Definition: postgres.h:367
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
Oid btree_opintype
Definition: typcache.h:55
Size keysize
Definition: hsearch.h:72
FmgrInfo eq_opr_finfo
Definition: typcache.h:72
#define InvalidOid
Definition: postgres_ext.h:36
static void load_rangetype_info(TypeCacheEntry *typentry)
Definition: typcache.c:820
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1092
Oid fn_oid
Definition: fmgr.h:59
#define TYPECACHE_CMP_PROC
Definition: typcache.h:131
char typtype
Definition: typcache.h:41
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:732
#define TYPECACHE_DOMAIN_CONSTR_INFO
Definition: typcache.h:141
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition: lsyscache.c:744
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
FormData_pg_type * Form_pg_type
Definition: pg_type.h:251
#define TCFLAGS_CHECKED_BTREE_OPCLASS
Definition: typcache.c:83
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:99
static bool record_fields_have_compare(TypeCacheEntry *typentry)
Definition: typcache.c:1386
Oid get_opclass_family(Oid opclass)
Definition: lsyscache.c:1019
static bool array_element_has_equality(TypeCacheEntry *typentry)
Definition: typcache.c:1316
static void load_domaintype_info(TypeCacheEntry *typentry)
Definition: typcache.c:883
#define TCFLAGS_CHECKED_HASH_PROC
Definition: typcache.c:89
char typalign
Definition: typcache.h:39
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define TYPECACHE_LT_OPR
Definition: typcache.h:129
#define TCFLAGS_CHECKED_LT_OPR
Definition: typcache.c:86
#define NameStr(name)
Definition: c.h:609
#define TYPECACHE_CMP_PROC_FINFO
Definition: typcache.h:134
#define TCFLAGS_CHECKED_HASH_OPCLASS
Definition: typcache.c:84
static bool range_element_has_extended_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1488
#define TYPECACHE_HASH_OPFAMILY
Definition: typcache.h:138
static bool record_fields_have_equality(TypeCacheEntry *typentry)
Definition: typcache.c:1378
#define TCFLAGS_CHECKED_CMP_PROC
Definition: typcache.c:88
#define BTLessStrategyNumber
Definition: stratnum.h:29
static bool array_element_has_extended_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1340
TupleDesc tupDesc
Definition: typcache.h:86
static void TypeCacheConstrCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: typcache.c:2194
static HTAB * TypeCacheHash
Definition: typcache.c:77
#define TYPECACHE_HASH_PROC
Definition: typcache.h:132
#define TYPECACHE_TUPDESC
Definition: typcache.h:136
#define BTEqualStrategyNumber
Definition: stratnum.h:31
static void TypeCacheOpcCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: typcache.c:2165
MemoryContext CacheMemoryContext
Definition: mcxt.c:47
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1041

◆ SharedRecordTypmodRegistryAttach()

void SharedRecordTypmodRegistryAttach ( SharedRecordTypmodRegistry )

Definition at line 2009 of file typcache.c.

References Session::area, Assert, CurrentSession, dshash_attach(), IsParallelWorker, MemoryContextSwitchTo(), NextRecordTypmod, on_dsm_detach(), PointerGetDatum, SharedRecordTypmodRegistry::record_table_handle, Session::segment, Session::shared_record_table, shared_record_typmod_registry_detach(), Session::shared_typmod_registry, Session::shared_typmod_table, TopMemoryContext, and SharedRecordTypmodRegistry::typmod_table_handle.

Referenced by AttachSession().

2010 {
2011  MemoryContext old_context;
2012  dshash_table *record_table;
2013  dshash_table *typmod_table;
2014 
2016 
2017  /* We can't already be attached to a shared registry. */
2018  Assert(CurrentSession != NULL);
2019  Assert(CurrentSession->segment != NULL);
2020  Assert(CurrentSession->area != NULL);
2024 
2025  /*
2026  * We can't already have typmods in our local cache, because they'd clash
2027  * with those imported by SharedRecordTypmodRegistryInit. This should be
2028  * a freshly started parallel worker. If we ever support worker
2029  * recycling, a worker would need to zap its local cache in between
2030  * servicing different queries, in order to be able to call this and
2031  * synchronize typmods with a new leader; but that's problematic because
2032  * we can't be very sure that record-typmod-related state hasn't escaped
2033  * to anywhere else in the process.
2034  */
2035  Assert(NextRecordTypmod == 0);
2036 
2037  old_context = MemoryContextSwitchTo(TopMemoryContext);
2038 
2039  /* Attach to the two hash tables. */
2040  record_table = dshash_attach(CurrentSession->area,
2042  registry->record_table_handle,
2043  CurrentSession->area);
2044  typmod_table = dshash_attach(CurrentSession->area,
2046  registry->typmod_table_handle,
2047  NULL);
2048 
2049  MemoryContextSwitchTo(old_context);
2050 
2051  /*
2052  * Set up detach hook to run at worker exit. Currently this is the same
2053  * as the leader's detach hook, but in future they might need to be
2054  * different.
2055  */
2058  PointerGetDatum(registry));
2059 
2060  /*
2061  * Set up the session state that will tell assign_record_type_typmod and
2062  * lookup_rowtype_tupdesc_internal about the shared registry.
2063  */
2065  CurrentSession->shared_record_table = record_table;
2066  CurrentSession->shared_typmod_table = typmod_table;
2067 }
dshash_table * dshash_attach(dsa_area *area, const dshash_parameters *params, dshash_table_handle handle, void *arg)
Definition: dshash.c:263
#define PointerGetDatum(X)
Definition: postgres.h:556
Session * CurrentSession
Definition: session.c:48
static const dshash_parameters srtr_record_table_params
Definition: typcache.c:246
dshash_table * shared_record_table
Definition: session.h:32
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void on_dsm_detach(dsm_segment *seg, on_dsm_detach_callback function, Datum arg)
Definition: dsm.c:975
dsa_area * area
Definition: session.h:28
#define IsParallelWorker()
Definition: parallel.h:60
MemoryContext TopMemoryContext
Definition: mcxt.c:44
static const dshash_parameters srtr_typmod_table_params
Definition: typcache.c:255
static void shared_record_typmod_registry_detach(dsm_segment *segment, Datum datum)
Definition: typcache.c:2643
static int32 NextRecordTypmod
Definition: typcache.c:270
struct SharedRecordTypmodRegistry * shared_typmod_registry
Definition: session.h:31
dshash_table * shared_typmod_table
Definition: session.h:33
#define Assert(condition)
Definition: c.h:732
dsm_segment * segment
Definition: session.h:27

◆ SharedRecordTypmodRegistryEstimate()

size_t SharedRecordTypmodRegistryEstimate ( void  )

Definition at line 1888 of file typcache.c.

Referenced by GetSessionDsmHandle().

1889 {
1890  return sizeof(SharedRecordTypmodRegistry);
1891 }
struct SharedRecordTypmodRegistry SharedRecordTypmodRegistry
Definition: typcache.h:166

◆ SharedRecordTypmodRegistryInit()

void SharedRecordTypmodRegistryInit ( SharedRecordTypmodRegistry ,
dsm_segment segment,
dsa_area area 
)

Definition at line 1910 of file typcache.c.

References Assert, CurrentSession, dshash_create(), dshash_find_or_insert(), dshash_get_hash_table_handle(), dshash_release_lock(), elog, ERROR, IsParallelWorker, SharedRecordTableEntry::key, SharedRecordTableKey::local_tupdesc, MemoryContextSwitchTo(), SharedRecordTypmodRegistry::next_typmod, NextRecordTypmod, on_dsm_detach(), pg_atomic_init_u32(), SharedRecordTypmodRegistry::record_table_handle, share_tupledesc(), SharedRecordTableKey::shared, Session::shared_record_table, shared_record_typmod_registry_detach(), SharedRecordTableKey::shared_tupdesc, SharedTypmodTableEntry::shared_tupdesc, Session::shared_typmod_registry, Session::shared_typmod_table, TupleDescData::tdtypmod, TopMemoryContext, SharedTypmodTableEntry::typmod, SharedRecordTypmodRegistry::typmod_table_handle, and SharedRecordTableKey::u.

Referenced by GetSessionDsmHandle().

1913 {
1914  MemoryContext old_context;
1915  dshash_table *record_table;
1916  dshash_table *typmod_table;
1917  int32 typmod;
1918 
1920 
1921  /* We can't already be attached to a shared registry. */
1925 
1926  old_context = MemoryContextSwitchTo(TopMemoryContext);
1927 
1928  /* Create the hash table of tuple descriptors indexed by themselves. */
1929  record_table = dshash_create(area, &srtr_record_table_params, area);
1930 
1931  /* Create the hash table of tuple descriptors indexed by typmod. */
1932  typmod_table = dshash_create(area, &srtr_typmod_table_params, NULL);
1933 
1934  MemoryContextSwitchTo(old_context);
1935 
1936  /* Initialize the SharedRecordTypmodRegistry. */
1937  registry->record_table_handle = dshash_get_hash_table_handle(record_table);
1938  registry->typmod_table_handle = dshash_get_hash_table_handle(typmod_table);
1939  pg_atomic_init_u32(&registry->next_typmod, NextRecordTypmod);
1940 
1941  /*
1942  * Copy all entries from this backend's private registry into the shared
1943  * registry.
1944  */
1945  for (typmod = 0; typmod < NextRecordTypmod; ++typmod)
1946  {
1947  SharedTypmodTableEntry *typmod_table_entry;
1948  SharedRecordTableEntry *record_table_entry;
1949  SharedRecordTableKey record_table_key;
1950  dsa_pointer shared_dp;
1951  TupleDesc tupdesc;
1952  bool found;
1953 
1954  tupdesc = RecordCacheArray[typmod];
1955  if (tupdesc == NULL)
1956  continue;
1957 
1958  /* Copy the TupleDesc into shared memory. */
1959  shared_dp = share_tupledesc(area, tupdesc, typmod);
1960 
1961  /* Insert into the typmod table. */
1962  typmod_table_entry = dshash_find_or_insert(typmod_table,
1963  &tupdesc->tdtypmod,
1964  &found);
1965  if (found)
1966  elog(ERROR, "cannot create duplicate shared record typmod");
1967  typmod_table_entry->typmod = tupdesc->tdtypmod;
1968  typmod_table_entry->shared_tupdesc = shared_dp;
1969  dshash_release_lock(typmod_table, typmod_table_entry);
1970 
1971  /* Insert into the record table. */
1972  record_table_key.shared = false;
1973  record_table_key.u.local_tupdesc = tupdesc;
1974  record_table_entry = dshash_find_or_insert(record_table,
1975  &record_table_key,
1976  &found);
1977  if (!found)
1978  {
1979  record_table_entry->key.shared = true;
1980  record_table_entry->key.u.shared_tupdesc = shared_dp;
1981  }
1982  dshash_release_lock(record_table, record_table_entry);
1983  }
1984 
1985  /*
1986  * Set up the global state that will tell assign_record_type_typmod and
1987  * lookup_rowtype_tupdesc_internal about the shared registry.
1988  */
1989  CurrentSession->shared_record_table = record_table;
1990  CurrentSession->shared_typmod_table = typmod_table;
1992 
1993  /*
1994  * We install a detach hook in the leader, but only to handle cleanup on
1995  * failure during GetSessionDsmHandle(). Once GetSessionDsmHandle() pins
1996  * the memory, the leader process will use a shared registry until it
1997  * exits.
1998  */
2000 }
Session * CurrentSession
Definition: session.c:48
static const dshash_parameters srtr_record_table_params
Definition: typcache.c:246
dshash_table * shared_record_table
Definition: session.h:32
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
SharedRecordTableKey key
Definition: typcache.c:188
void on_dsm_detach(dsm_segment *seg, on_dsm_detach_callback function, Datum arg)
Definition: dsm.c:975
void dshash_release_lock(dshash_table *hash_table, void *entry)
Definition: dshash.c:561
uint64 dsa_pointer
Definition: dsa.h:62
signed int int32
Definition: c.h:346
static TupleDesc * RecordCacheArray
Definition: typcache.c:267
dsa_pointer shared_tupdesc
Definition: typcache.c:198
#define ERROR
Definition: elog.h:43
int32 tdtypmod
Definition: tupdesc.h:83
dshash_table_handle dshash_get_hash_table_handle(dshash_table *hash_table)
Definition: dshash.c:362
dsa_pointer shared_tupdesc
Definition: typcache.c:177
#define IsParallelWorker()
Definition: parallel.h:60
MemoryContext TopMemoryContext
Definition: mcxt.c:44
static const dshash_parameters srtr_typmod_table_params
Definition: typcache.c:255
static void shared_record_typmod_registry_detach(dsm_segment *segment, Datum datum)
Definition: typcache.c:2643
static int32 NextRecordTypmod
Definition: typcache.c:270
struct SharedRecordTypmodRegistry * shared_typmod_registry
Definition: session.h:31
uintptr_t Datum
Definition: postgres.h:367
dshash_table * dshash_create(dsa_area *area, const dshash_parameters *params, void *arg)
Definition: dshash.c:196
dshash_table * shared_typmod_table
Definition: session.h:33
union SharedRecordTableKey::@36 u
#define Assert(condition)
Definition: c.h:732
static dsa_pointer share_tupledesc(dsa_area *area, TupleDesc tupdesc, uint32 typmod)
Definition: typcache.c:2510
#define elog(elevel,...)
Definition: elog.h:226
void * dshash_find_or_insert(dshash_table *hash_table, const void *key, bool *found)
Definition: dshash.c:430
TupleDesc local_tupdesc
Definition: typcache.c:176
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:226

◆ UpdateDomainConstraintRef()

void UpdateDomainConstraintRef ( DomainConstraintRef ref)

Definition at line 1240 of file typcache.c.

References DomainConstraintCache::constraints, DomainConstraintRef::constraints, DomainConstraintRef::dcc, DomainConstraintCache::dccRefCount, decr_dcc_refcount(), TypeCacheEntry::domainData, TypeCacheEntry::flags, load_domaintype_info(), DomainConstraintRef::need_exprstate, NIL, prep_domain_constraints(), DomainConstraintRef::refctx, DomainConstraintRef::tcache, TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS, and TypeCacheEntry::typtype.

Referenced by domain_check_input().

1241 {
1242  TypeCacheEntry *typentry = ref->tcache;
1243 
1244  /* Make sure typcache entry's data is up to date */
1245  if ((typentry->flags & TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS) == 0 &&
1246  typentry->typtype == TYPTYPE_DOMAIN)
1247  load_domaintype_info(typentry);
1248 
1249  /* Transfer to ref object if there's new info, adjusting refcounts */
1250  if (ref->dcc != typentry->domainData)
1251  {
1252  /* Paranoia --- be sure link is nulled before trying to release */
1253  DomainConstraintCache *dcc = ref->dcc;
1254 
1255  if (dcc)
1256  {
1257  /*
1258  * Note: we just leak the previous list of executable domain
1259  * constraints. Alternatively, we could keep those in a child
1260  * context of ref->refctx and free that context at this point.
1261  * However, in practice this code path will be taken so seldom
1262  * that the extra bookkeeping for a child context doesn't seem
1263  * worthwhile; we'll just allow a leak for the lifespan of refctx.
1264  */
1265  ref->constraints = NIL;
1266  ref->dcc = NULL;
1267  decr_dcc_refcount(dcc);
1268  }
1269  dcc = typentry->domainData;
1270  if (dcc)
1271  {
1272  ref->dcc = dcc;
1273  dcc->dccRefCount++;
1274  if (ref->need_exprstate)
1276  ref->refctx);
1277  else
1278  ref->constraints = dcc->constraints;
1279  }
1280  }
1281 }
#define NIL
Definition: pg_list.h:65
DomainConstraintCache * dcc
Definition: typcache.h:162
DomainConstraintCache * domainData
Definition: typcache.h:112
MemoryContext refctx
Definition: typcache.h:157
char typtype
Definition: typcache.h:41
static List * prep_domain_constraints(List *constraints, MemoryContext execctx)
Definition: typcache.c:1164
TypeCacheEntry * tcache
Definition: typcache.h:158
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:99
static void load_domaintype_info(TypeCacheEntry *typentry)
Definition: typcache.c:883
static void decr_dcc_refcount(DomainConstraintCache *dcc)
Definition: typcache.c:1132