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 139 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 143 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 145 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 140 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 137 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 141 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 168 of file typcache.h.

◆ TypeCacheEntry

Function Documentation

◆ assign_record_type_identifier()

uint64 assign_record_type_identifier ( Oid  type_id,
int32  typmod 
)

Definition at line 1905 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().

1906 {
1907  if (type_id != RECORDOID)
1908  {
1909  /*
1910  * It's a named composite type, so use the regular typcache.
1911  */
1912  TypeCacheEntry *typentry;
1913 
1914  typentry = lookup_type_cache(type_id, TYPECACHE_TUPDESC);
1915  if (typentry->tupDesc == NULL)
1916  ereport(ERROR,
1917  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1918  errmsg("type %s is not composite",
1919  format_type_be(type_id))));
1920  Assert(typentry->tupDesc_identifier != 0);
1921  return typentry->tupDesc_identifier;
1922  }
1923  else
1924  {
1925  /*
1926  * It's a transient record type, so look in our record-type table.
1927  */
1928  if (typmod >= 0 && typmod < RecordCacheArrayLen &&
1929  RecordCacheArray[typmod] != NULL)
1930  {
1931  Assert(RecordIdentifierArray[typmod] != 0);
1932  return RecordIdentifierArray[typmod];
1933  }
1934 
1935  /* For anonymous or unrecognized record type, generate a new ID */
1936  return ++tupledesc_id_counter;
1937  }
1938 }
int errcode(int sqlerrcode)
Definition: elog.c:610
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
static uint64 tupledesc_id_counter
Definition: typcache.c:285
static TupleDesc * RecordCacheArray
Definition: typcache.c:275
#define ERROR
Definition: elog.h:43
static int32 RecordCacheArrayLen
Definition: typcache.c:277
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:331
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:745
uint64 tupDesc_identifier
Definition: typcache.h:89
int errmsg(const char *fmt,...)
Definition: elog.c:824
TupleDesc tupDesc
Definition: typcache.h:88
#define TYPECACHE_TUPDESC
Definition: typcache.h:138
static uint64 * RecordIdentifierArray
Definition: typcache.c:276

◆ assign_record_type_typmod()

void assign_record_type_typmod ( TupleDesc  tupDesc)

Definition at line 1830 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().

1831 {
1832  RecordCacheEntry *recentry;
1833  TupleDesc entDesc;
1834  bool found;
1835  MemoryContext oldcxt;
1836 
1837  Assert(tupDesc->tdtypeid == RECORDOID);
1838 
1839  if (RecordCacheHash == NULL)
1840  {
1841  /* First time through: initialize the hash table */
1842  HASHCTL ctl;
1843 
1844  MemSet(&ctl, 0, sizeof(ctl));
1845  ctl.keysize = sizeof(TupleDesc); /* just the pointer */
1846  ctl.entrysize = sizeof(RecordCacheEntry);
1849  RecordCacheHash = hash_create("Record information cache", 64,
1850  &ctl,
1852 
1853  /* Also make sure CacheMemoryContext exists */
1854  if (!CacheMemoryContext)
1856  }
1857 
1858  /* Find or create a hashtable entry for this tuple descriptor */
1860  (void *) &tupDesc,
1861  HASH_ENTER, &found);
1862  if (found && recentry->tupdesc != NULL)
1863  {
1864  tupDesc->tdtypmod = recentry->tupdesc->tdtypmod;
1865  return;
1866  }
1867 
1868  /* Not present, so need to manufacture an entry */
1869  recentry->tupdesc = NULL;
1871 
1872  /* Look in the SharedRecordTypmodRegistry, if attached */
1873  entDesc = find_or_make_matching_shared_tupledesc(tupDesc);
1874  if (entDesc == NULL)
1875  {
1876  /* Reference-counted local cache only. */
1877  entDesc = CreateTupleDescCopy(tupDesc);
1878  entDesc->tdrefcount = 1;
1879  entDesc->tdtypmod = NextRecordTypmod++;
1880  }
1882  RecordCacheArray[entDesc->tdtypmod] = entDesc;
1883  recentry->tupdesc = entDesc;
1884 
1885  /* Assign a unique tupdesc identifier, too. */
1887 
1888  /* Update the caller's tuple descriptor. */
1889  tupDesc->tdtypmod = entDesc->tdtypmod;
1890 
1891  MemoryContextSwitchTo(oldcxt);
1892 }
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:2621
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:978
static uint64 tupledesc_id_counter
Definition: typcache.c:285
static HTAB * RecordCacheHash
Definition: typcache.c:272
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:927
static TupleDesc * RecordCacheArray
Definition: typcache.c:275
int32 tdtypmod
Definition: tupdesc.h:83
static int32 NextRecordTypmod
Definition: typcache.c:278
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:328
static void ensure_record_cache_typmod_slot_exists(int32 typmod)
Definition: typcache.c:1582
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:1803
#define Assert(condition)
Definition: c.h:745
#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:1814
TupleDesc tupdesc
Definition: typcache.c:157
int tdrefcount
Definition: tupdesc.h:84
static uint64 * RecordIdentifierArray
Definition: typcache.c:276
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 2337 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().

2338 {
2339  TypeCacheEnumData *enumdata;
2340  EnumItem *item1;
2341  EnumItem *item2;
2342 
2343  /*
2344  * Equal OIDs are certainly equal --- this case was probably handled by
2345  * our caller, but we may as well check.
2346  */
2347  if (arg1 == arg2)
2348  return 0;
2349 
2350  /* Load up the cache if first time through */
2351  if (tcache->enumData == NULL)
2352  load_enum_cache_data(tcache);
2353  enumdata = tcache->enumData;
2354 
2355  /*
2356  * If both OIDs are known-sorted, we can just compare them directly.
2357  */
2358  if (enum_known_sorted(enumdata, arg1) &&
2359  enum_known_sorted(enumdata, arg2))
2360  {
2361  if (arg1 < arg2)
2362  return -1;
2363  else
2364  return 1;
2365  }
2366 
2367  /*
2368  * Slow path: we have to identify their actual sort-order positions.
2369  */
2370  item1 = find_enumitem(enumdata, arg1);
2371  item2 = find_enumitem(enumdata, arg2);
2372 
2373  if (item1 == NULL || item2 == NULL)
2374  {
2375  /*
2376  * We couldn't find one or both values. That means the enum has
2377  * changed under us, so re-initialize the cache and try again. We
2378  * don't bother retrying the known-sorted case in this path.
2379  */
2380  load_enum_cache_data(tcache);
2381  enumdata = tcache->enumData;
2382 
2383  item1 = find_enumitem(enumdata, arg1);
2384  item2 = find_enumitem(enumdata, arg2);
2385 
2386  /*
2387  * If we still can't find the values, complain: we must have corrupt
2388  * data.
2389  */
2390  if (item1 == NULL)
2391  elog(ERROR, "enum value %u not found in cache for enum %s",
2392  arg1, format_type_be(tcache->type_id));
2393  if (item2 == NULL)
2394  elog(ERROR, "enum value %u not found in cache for enum %s",
2395  arg2, format_type_be(tcache->type_id));
2396  }
2397 
2398  if (item1->sort_order < item2->sort_order)
2399  return -1;
2400  else if (item1->sort_order > item2->sort_order)
2401  return 1;
2402  else
2403  return 0;
2404 }
struct TypeCacheEnumData * enumData
Definition: typcache.h:123
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
#define ERROR
Definition: elog.h:43
static bool enum_known_sorted(TypeCacheEnumData *enumdata, Oid arg)
Definition: typcache.c:2308
static EnumItem * find_enumitem(TypeCacheEnumData *enumdata, Oid arg)
Definition: typcache.c:2565
static void load_enum_cache_data(TypeCacheEntry *tcache)
Definition: typcache.c:2410
float4 sort_order
Definition: typcache.c:133
#define elog(elevel,...)
Definition: elog.h:214

◆ DomainHasConstraints()

bool DomainHasConstraints ( Oid  type_id)

Definition at line 1347 of file typcache.c.

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

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

1348 {
1349  TypeCacheEntry *typentry;
1350 
1351  /*
1352  * Note: a side effect is to cause the typcache's domain data to become
1353  * valid. This is fine since we'll likely need it soon if there is any.
1354  */
1355  typentry = lookup_type_cache(type_id, TYPECACHE_DOMAIN_CONSTR_INFO);
1356 
1357  return (typentry->domainData != NULL);
1358 }
DomainConstraintCache * domainData
Definition: typcache.h:114
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:331
#define TYPECACHE_DOMAIN_CONSTR_INFO
Definition: typcache.h:143

◆ InitDomainConstraintRef()

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

Definition at line 1260 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().

1262 {
1263  /* Look up the typcache entry --- we assume it survives indefinitely */
1265  ref->need_exprstate = need_exprstate;
1266  /* For safety, establish the callback before acquiring a refcount */
1267  ref->refctx = refctx;
1268  ref->dcc = NULL;
1270  ref->callback.arg = (void *) ref;
1272  /* Acquire refcount if there are constraints, and set up exported list */
1273  if (ref->tcache->domainData)
1274  {
1275  ref->dcc = ref->tcache->domainData;
1276  ref->dcc->dccRefCount++;
1277  if (ref->need_exprstate)
1279  ref->refctx);
1280  else
1281  ref->constraints = ref->dcc->constraints;
1282  }
1283  else
1284  ref->constraints = NIL;
1285 }
MemoryContextCallback callback
Definition: typcache.h:165
MemoryContextCallbackFunction func
Definition: palloc.h:49
#define NIL
Definition: pg_list.h:65
DomainConstraintCache * dcc
Definition: typcache.h:164
static void dccref_deletion_callback(void *arg)
Definition: typcache.c:1201
DomainConstraintCache * domainData
Definition: typcache.h:114
MemoryContext refctx
Definition: typcache.h:159
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:331
static List * prep_domain_constraints(List *constraints, MemoryContext execctx)
Definition: typcache.c:1222
#define TYPECACHE_DOMAIN_CONSTR_INFO
Definition: typcache.h:143
TypeCacheEntry * tcache
Definition: typcache.h:160
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 1744 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().

1745 {
1746  TupleDesc tmp;
1747 
1748  tmp = lookup_rowtype_tupdesc_internal(type_id, typmod, false);
1749  return CreateTupleDescCopyConstr(tmp);
1750 }
TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc)
Definition: tupdesc.c:150
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1619

◆ lookup_rowtype_tupdesc_domain()

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

Definition at line 1766 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().

1767 {
1768  TupleDesc tupDesc;
1769 
1770  if (type_id != RECORDOID)
1771  {
1772  /*
1773  * Check for domain or named composite type. We might as well load
1774  * whichever data is needed.
1775  */
1776  TypeCacheEntry *typentry;
1777 
1778  typentry = lookup_type_cache(type_id,
1781  if (typentry->typtype == TYPTYPE_DOMAIN)
1783  typentry->domainBaseTypmod,
1784  noError);
1785  if (typentry->tupDesc == NULL && !noError)
1786  ereport(ERROR,
1787  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1788  errmsg("type %s is not composite",
1789  format_type_be(type_id))));
1790  tupDesc = typentry->tupDesc;
1791  }
1792  else
1793  tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, noError);
1794  if (tupDesc != NULL)
1795  PinTupleDesc(tupDesc);
1796  return tupDesc;
1797 }
int errcode(int sqlerrcode)
Definition: elog.c:610
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
Oid domainBaseType
Definition: typcache.h:107
#define ERROR
Definition: elog.h:43
int32 domainBaseTypmod
Definition: typcache.h:108
TupleDesc lookup_rowtype_tupdesc_noerror(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1727
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:142
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:331
#define ereport(elevel,...)
Definition: elog.h:144
char typtype
Definition: typcache.h:43
#define PinTupleDesc(tupdesc)
Definition: tupdesc.h:116
int errmsg(const char *fmt,...)
Definition: elog.c:824
TupleDesc tupDesc
Definition: typcache.h:88
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1619
#define TYPECACHE_TUPDESC
Definition: typcache.h:138

◆ lookup_rowtype_tupdesc_noerror()

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

Definition at line 1727 of file typcache.c.

References lookup_rowtype_tupdesc_internal(), and PinTupleDesc.

Referenced by lookup_rowtype_tupdesc_domain().

1728 {
1729  TupleDesc tupDesc;
1730 
1731  tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, noError);
1732  if (tupDesc != NULL)
1733  PinTupleDesc(tupDesc);
1734  return tupDesc;
1735 }
#define PinTupleDesc(tupdesc)
Definition: tupdesc.h:116
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1619

◆ lookup_type_cache()

TypeCacheEntry* lookup_type_cache ( Oid  type_id,
int  flags 
)

Definition at line 331 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, GetSysCacheHashValue1, 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(), lookup_type_cache(), 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, TCFLAGS_HAVE_PG_TYPE_DATA, TypeCacheEntry::tupDesc, TypeCacheEntry::typalign, TypeCacheEntry::typbyval, TypeCacheEntry::typcollation, TypeCacheEntry::type_id, TypeCacheEntry::type_id_hash, 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(), TypeCacheTypCallback(), 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(), lookup_type_cache(), 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().

332 {
333  TypeCacheEntry *typentry;
334  bool found;
335 
336  if (TypeCacheHash == NULL)
337  {
338  /* First time through: initialize the hash table */
339  HASHCTL ctl;
340 
341  MemSet(&ctl, 0, sizeof(ctl));
342  ctl.keysize = sizeof(Oid);
343  ctl.entrysize = sizeof(TypeCacheEntry);
344  TypeCacheHash = hash_create("Type information cache", 64,
345  &ctl, HASH_ELEM | HASH_BLOBS);
346 
347  /* Also set up callbacks for SI invalidations */
352 
353  /* Also make sure CacheMemoryContext exists */
354  if (!CacheMemoryContext)
356  }
357 
358  /* Try to look up an existing entry */
360  (void *) &type_id,
361  HASH_FIND, NULL);
362  if (typentry == NULL)
363  {
364  /*
365  * If we didn't find one, we want to make one. But first look up the
366  * pg_type row, just to make sure we don't make a cache entry for an
367  * invalid type OID. If the type OID is not valid, present a
368  * user-facing error, since some code paths such as domain_in() allow
369  * this function to be reached with a user-supplied OID.
370  */
371  HeapTuple tp;
372  Form_pg_type typtup;
373 
374  tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_id));
375  if (!HeapTupleIsValid(tp))
376  ereport(ERROR,
377  (errcode(ERRCODE_UNDEFINED_OBJECT),
378  errmsg("type with OID %u does not exist", type_id)));
379  typtup = (Form_pg_type) GETSTRUCT(tp);
380  if (!typtup->typisdefined)
381  ereport(ERROR,
382  (errcode(ERRCODE_UNDEFINED_OBJECT),
383  errmsg("type \"%s\" is only a shell",
384  NameStr(typtup->typname))));
385 
386  /* Now make the typcache entry */
388  (void *) &type_id,
389  HASH_ENTER, &found);
390  Assert(!found); /* it wasn't there a moment ago */
391 
392  MemSet(typentry, 0, sizeof(TypeCacheEntry));
393 
394  /* These fields can never change, by definition */
395  typentry->type_id = type_id;
397  ObjectIdGetDatum(type_id));
398 
399  /* Keep this part in sync with the code below */
400  typentry->typlen = typtup->typlen;
401  typentry->typbyval = typtup->typbyval;
402  typentry->typalign = typtup->typalign;
403  typentry->typstorage = typtup->typstorage;
404  typentry->typtype = typtup->typtype;
405  typentry->typrelid = typtup->typrelid;
406  typentry->typelem = typtup->typelem;
407  typentry->typcollation = typtup->typcollation;
408  typentry->flags |= TCFLAGS_HAVE_PG_TYPE_DATA;
409 
410  /* If it's a domain, immediately thread it into the domain cache list */
411  if (typentry->typtype == TYPTYPE_DOMAIN)
412  {
413  typentry->nextDomain = firstDomainTypeEntry;
414  firstDomainTypeEntry = typentry;
415  }
416 
417  ReleaseSysCache(tp);
418  }
419  else if (!(typentry->flags & TCFLAGS_HAVE_PG_TYPE_DATA))
420  {
421  /*
422  * We have an entry, but its pg_type row got changed, so reload the
423  * data obtained directly from pg_type.
424  */
425  HeapTuple tp;
426  Form_pg_type typtup;
427 
428  tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_id));
429  if (!HeapTupleIsValid(tp))
430  ereport(ERROR,
431  (errcode(ERRCODE_UNDEFINED_OBJECT),
432  errmsg("type with OID %u does not exist", type_id)));
433  typtup = (Form_pg_type) GETSTRUCT(tp);
434  if (!typtup->typisdefined)
435  ereport(ERROR,
436  (errcode(ERRCODE_UNDEFINED_OBJECT),
437  errmsg("type \"%s\" is only a shell",
438  NameStr(typtup->typname))));
439 
440  /*
441  * Keep this part in sync with the code above. Many of these fields
442  * shouldn't ever change, particularly typtype, but copy 'em anyway.
443  */
444  typentry->typlen = typtup->typlen;
445  typentry->typbyval = typtup->typbyval;
446  typentry->typalign = typtup->typalign;
447  typentry->typstorage = typtup->typstorage;
448  typentry->typtype = typtup->typtype;
449  typentry->typrelid = typtup->typrelid;
450  typentry->typelem = typtup->typelem;
451  typentry->typcollation = typtup->typcollation;
452  typentry->flags |= TCFLAGS_HAVE_PG_TYPE_DATA;
453 
454  ReleaseSysCache(tp);
455  }
456 
457  /*
458  * Look up opclasses if we haven't already and any dependent info is
459  * requested.
460  */
465  !(typentry->flags & TCFLAGS_CHECKED_BTREE_OPCLASS))
466  {
467  Oid opclass;
468 
469  opclass = GetDefaultOpClass(type_id, BTREE_AM_OID);
470  if (OidIsValid(opclass))
471  {
472  typentry->btree_opf = get_opclass_family(opclass);
473  typentry->btree_opintype = get_opclass_input_type(opclass);
474  }
475  else
476  {
477  typentry->btree_opf = typentry->btree_opintype = InvalidOid;
478  }
479 
480  /*
481  * Reset information derived from btree opclass. Note in particular
482  * that we'll redetermine the eq_opr even if we previously found one;
483  * this matters in case a btree opclass has been added to a type that
484  * previously had only a hash opclass.
485  */
486  typentry->flags &= ~(TCFLAGS_CHECKED_EQ_OPR |
491  }
492 
493  /*
494  * If we need to look up equality operator, and there's no btree opclass,
495  * force lookup of hash opclass.
496  */
497  if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO)) &&
498  !(typentry->flags & TCFLAGS_CHECKED_EQ_OPR) &&
499  typentry->btree_opf == InvalidOid)
500  flags |= TYPECACHE_HASH_OPFAMILY;
501 
506  !(typentry->flags & TCFLAGS_CHECKED_HASH_OPCLASS))
507  {
508  Oid opclass;
509 
510  opclass = GetDefaultOpClass(type_id, HASH_AM_OID);
511  if (OidIsValid(opclass))
512  {
513  typentry->hash_opf = get_opclass_family(opclass);
514  typentry->hash_opintype = get_opclass_input_type(opclass);
515  }
516  else
517  {
518  typentry->hash_opf = typentry->hash_opintype = InvalidOid;
519  }
520 
521  /*
522  * Reset information derived from hash opclass. We do *not* reset the
523  * eq_opr; if we already found one from the btree opclass, that
524  * decision is still good.
525  */
526  typentry->flags &= ~(TCFLAGS_CHECKED_HASH_PROC |
528  typentry->flags |= TCFLAGS_CHECKED_HASH_OPCLASS;
529  }
530 
531  /*
532  * Look for requested operators and functions, if we haven't already.
533  */
534  if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO)) &&
535  !(typentry->flags & TCFLAGS_CHECKED_EQ_OPR))
536  {
537  Oid eq_opr = InvalidOid;
538 
539  if (typentry->btree_opf != InvalidOid)
540  eq_opr = get_opfamily_member(typentry->btree_opf,
541  typentry->btree_opintype,
542  typentry->btree_opintype,
544  if (eq_opr == InvalidOid &&
545  typentry->hash_opf != InvalidOid)
546  eq_opr = get_opfamily_member(typentry->hash_opf,
547  typentry->hash_opintype,
548  typentry->hash_opintype,
550 
551  /*
552  * If the proposed equality operator is array_eq or record_eq, check
553  * to see if the element type or column types support equality. If
554  * not, array_eq or record_eq would fail at runtime, so we don't want
555  * to report that the type has equality. (We can omit similar
556  * checking for ranges because ranges can't be created in the first
557  * place unless their subtypes support equality.)
558  */
559  if (eq_opr == ARRAY_EQ_OP &&
560  !array_element_has_equality(typentry))
561  eq_opr = InvalidOid;
562  else if (eq_opr == RECORD_EQ_OP &&
563  !record_fields_have_equality(typentry))
564  eq_opr = InvalidOid;
565 
566  /* Force update of eq_opr_finfo only if we're changing state */
567  if (typentry->eq_opr != eq_opr)
568  typentry->eq_opr_finfo.fn_oid = InvalidOid;
569 
570  typentry->eq_opr = eq_opr;
571 
572  /*
573  * Reset info about hash functions whenever we pick up new info about
574  * equality operator. This is so we can ensure that the hash
575  * functions match the operator.
576  */
577  typentry->flags &= ~(TCFLAGS_CHECKED_HASH_PROC |
579  typentry->flags |= TCFLAGS_CHECKED_EQ_OPR;
580  }
581  if ((flags & TYPECACHE_LT_OPR) &&
582  !(typentry->flags & TCFLAGS_CHECKED_LT_OPR))
583  {
584  Oid lt_opr = InvalidOid;
585 
586  if (typentry->btree_opf != InvalidOid)
587  lt_opr = get_opfamily_member(typentry->btree_opf,
588  typentry->btree_opintype,
589  typentry->btree_opintype,
591 
592  /*
593  * As above, make sure array_cmp or record_cmp will succeed; but again
594  * we need no special check for ranges.
595  */
596  if (lt_opr == ARRAY_LT_OP &&
597  !array_element_has_compare(typentry))
598  lt_opr = InvalidOid;
599  else if (lt_opr == RECORD_LT_OP &&
600  !record_fields_have_compare(typentry))
601  lt_opr = InvalidOid;
602 
603  typentry->lt_opr = lt_opr;
604  typentry->flags |= TCFLAGS_CHECKED_LT_OPR;
605  }
606  if ((flags & TYPECACHE_GT_OPR) &&
607  !(typentry->flags & TCFLAGS_CHECKED_GT_OPR))
608  {
609  Oid gt_opr = InvalidOid;
610 
611  if (typentry->btree_opf != InvalidOid)
612  gt_opr = get_opfamily_member(typentry->btree_opf,
613  typentry->btree_opintype,
614  typentry->btree_opintype,
616 
617  /*
618  * As above, make sure array_cmp or record_cmp will succeed; but again
619  * we need no special check for ranges.
620  */
621  if (gt_opr == ARRAY_GT_OP &&
622  !array_element_has_compare(typentry))
623  gt_opr = InvalidOid;
624  else if (gt_opr == RECORD_GT_OP &&
625  !record_fields_have_compare(typentry))
626  gt_opr = InvalidOid;
627 
628  typentry->gt_opr = gt_opr;
629  typentry->flags |= TCFLAGS_CHECKED_GT_OPR;
630  }
631  if ((flags & (TYPECACHE_CMP_PROC | TYPECACHE_CMP_PROC_FINFO)) &&
632  !(typentry->flags & TCFLAGS_CHECKED_CMP_PROC))
633  {
634  Oid cmp_proc = InvalidOid;
635 
636  if (typentry->btree_opf != InvalidOid)
637  cmp_proc = get_opfamily_proc(typentry->btree_opf,
638  typentry->btree_opintype,
639  typentry->btree_opintype,
640  BTORDER_PROC);
641 
642  /*
643  * As above, make sure array_cmp or record_cmp will succeed; but again
644  * we need no special check for ranges.
645  */
646  if (cmp_proc == F_BTARRAYCMP &&
647  !array_element_has_compare(typentry))
648  cmp_proc = InvalidOid;
649  else if (cmp_proc == F_BTRECORDCMP &&
650  !record_fields_have_compare(typentry))
651  cmp_proc = InvalidOid;
652 
653  /* Force update of cmp_proc_finfo only if we're changing state */
654  if (typentry->cmp_proc != cmp_proc)
655  typentry->cmp_proc_finfo.fn_oid = InvalidOid;
656 
657  typentry->cmp_proc = cmp_proc;
658  typentry->flags |= TCFLAGS_CHECKED_CMP_PROC;
659  }
661  !(typentry->flags & TCFLAGS_CHECKED_HASH_PROC))
662  {
663  Oid hash_proc = InvalidOid;
664 
665  /*
666  * We insist that the eq_opr, if one has been determined, match the
667  * hash opclass; else report there is no hash function.
668  */
669  if (typentry->hash_opf != InvalidOid &&
670  (!OidIsValid(typentry->eq_opr) ||
671  typentry->eq_opr == get_opfamily_member(typentry->hash_opf,
672  typentry->hash_opintype,
673  typentry->hash_opintype,
675  hash_proc = get_opfamily_proc(typentry->hash_opf,
676  typentry->hash_opintype,
677  typentry->hash_opintype,
679 
680  /*
681  * As above, make sure hash_array will succeed. We don't currently
682  * support hashing for composite types, but when we do, we'll need
683  * more logic here to check that case too.
684  */
685  if (hash_proc == F_HASH_ARRAY &&
686  !array_element_has_hashing(typentry))
687  hash_proc = InvalidOid;
688 
689  /*
690  * Likewise for hash_range.
691  */
692  if (hash_proc == F_HASH_RANGE &&
693  !range_element_has_hashing(typentry))
694  hash_proc = InvalidOid;
695 
696  /* Force update of hash_proc_finfo only if we're changing state */
697  if (typentry->hash_proc != hash_proc)
698  typentry->hash_proc_finfo.fn_oid = InvalidOid;
699 
700  typentry->hash_proc = hash_proc;
701  typentry->flags |= TCFLAGS_CHECKED_HASH_PROC;
702  }
703  if ((flags & (TYPECACHE_HASH_EXTENDED_PROC |
706  {
707  Oid hash_extended_proc = InvalidOid;
708 
709  /*
710  * We insist that the eq_opr, if one has been determined, match the
711  * hash opclass; else report there is no hash function.
712  */
713  if (typentry->hash_opf != InvalidOid &&
714  (!OidIsValid(typentry->eq_opr) ||
715  typentry->eq_opr == get_opfamily_member(typentry->hash_opf,
716  typentry->hash_opintype,
717  typentry->hash_opintype,
719  hash_extended_proc = get_opfamily_proc(typentry->hash_opf,
720  typentry->hash_opintype,
721  typentry->hash_opintype,
723 
724  /*
725  * As above, make sure hash_array_extended will succeed. We don't
726  * currently support hashing for composite types, but when we do,
727  * we'll need more logic here to check that case too.
728  */
729  if (hash_extended_proc == F_HASH_ARRAY_EXTENDED &&
731  hash_extended_proc = InvalidOid;
732 
733  /*
734  * Likewise for hash_range_extended.
735  */
736  if (hash_extended_proc == F_HASH_RANGE_EXTENDED &&
738  hash_extended_proc = InvalidOid;
739 
740  /* Force update of proc finfo only if we're changing state */
741  if (typentry->hash_extended_proc != hash_extended_proc)
743 
744  typentry->hash_extended_proc = hash_extended_proc;
746  }
747 
748  /*
749  * Set up fmgr lookup info as requested
750  *
751  * Note: we tell fmgr the finfo structures live in CacheMemoryContext,
752  * which is not quite right (they're really in the hash table's private
753  * memory context) but this will do for our purposes.
754  *
755  * Note: the code above avoids invalidating the finfo structs unless the
756  * referenced operator/function OID actually changes. This is to prevent
757  * unnecessary leakage of any subsidiary data attached to an finfo, since
758  * that would cause session-lifespan memory leaks.
759  */
760  if ((flags & TYPECACHE_EQ_OPR_FINFO) &&
761  typentry->eq_opr_finfo.fn_oid == InvalidOid &&
762  typentry->eq_opr != InvalidOid)
763  {
764  Oid eq_opr_func;
765 
766  eq_opr_func = get_opcode(typentry->eq_opr);
767  if (eq_opr_func != InvalidOid)
768  fmgr_info_cxt(eq_opr_func, &typentry->eq_opr_finfo,
770  }
771  if ((flags & TYPECACHE_CMP_PROC_FINFO) &&
772  typentry->cmp_proc_finfo.fn_oid == InvalidOid &&
773  typentry->cmp_proc != InvalidOid)
774  {
775  fmgr_info_cxt(typentry->cmp_proc, &typentry->cmp_proc_finfo,
777  }
778  if ((flags & TYPECACHE_HASH_PROC_FINFO) &&
779  typentry->hash_proc_finfo.fn_oid == InvalidOid &&
780  typentry->hash_proc != InvalidOid)
781  {
782  fmgr_info_cxt(typentry->hash_proc, &typentry->hash_proc_finfo,
784  }
785  if ((flags & TYPECACHE_HASH_EXTENDED_PROC_FINFO) &&
787  typentry->hash_extended_proc != InvalidOid)
788  {
790  &typentry->hash_extended_proc_finfo,
792  }
793 
794  /*
795  * If it's a composite type (row type), get tupdesc if requested
796  */
797  if ((flags & TYPECACHE_TUPDESC) &&
798  typentry->tupDesc == NULL &&
799  typentry->typtype == TYPTYPE_COMPOSITE)
800  {
801  load_typcache_tupdesc(typentry);
802  }
803 
804  /*
805  * If requested, get information about a range type
806  *
807  * This includes making sure that the basic info about the range element
808  * type is up-to-date.
809  */
810  if ((flags & TYPECACHE_RANGE_INFO) &&
811  typentry->typtype == TYPTYPE_RANGE)
812  {
813  if (typentry->rngelemtype == NULL)
814  load_rangetype_info(typentry);
815  else if (!(typentry->rngelemtype->flags & TCFLAGS_HAVE_PG_TYPE_DATA))
816  (void) lookup_type_cache(typentry->rngelemtype->type_id, 0);
817  }
818 
819  /*
820  * If requested, get information about a domain type
821  */
822  if ((flags & TYPECACHE_DOMAIN_BASE_INFO) &&
823  typentry->domainBaseType == InvalidOid &&
824  typentry->typtype == TYPTYPE_DOMAIN)
825  {
826  typentry->domainBaseTypmod = -1;
827  typentry->domainBaseType =
828  getBaseTypeAndTypmod(type_id, &typentry->domainBaseTypmod);
829  }
830  if ((flags & TYPECACHE_DOMAIN_CONSTR_INFO) &&
831  (typentry->flags & TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS) == 0 &&
832  typentry->typtype == TYPTYPE_DOMAIN)
833  {
834  load_domaintype_info(typentry);
835  }
836 
837  return typentry;
838 }
static bool array_element_has_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1390
static void load_typcache_tupdesc(TypeCacheEntry *typentry)
Definition: typcache.c:844
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition: lsyscache.c:2426
#define BTORDER_PROC
Definition: nbtree.h:575
#define TYPECACHE_RANGE_INFO
Definition: typcache.h:141
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:2045
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Oid hash_opintype
Definition: typcache.h:59
#define TCFLAGS_CHECKED_EQ_OPR
Definition: typcache.c:87
#define HASH_ELEM
Definition: hsearch.h:87
static TypeCacheEntry * firstDomainTypeEntry
Definition: typcache.c:81
uint32 type_id_hash
Definition: typcache.h:36
#define TYPECACHE_HASH_EXTENDED_PROC_FINFO
Definition: typcache.h:145
#define TCFLAGS_CHECKED_HASH_EXTENDED_PROC
Definition: typcache.c:92
struct TypeCacheEntry TypeCacheEntry
Oid typcollation
Definition: typcache.h:46
#define TYPECACHE_EQ_OPR_FINFO
Definition: typcache.h:135
#define TYPECACHE_HASH_PROC_FINFO
Definition: typcache.h:137
Size entrysize
Definition: hsearch.h:73
#define TYPECACHE_EQ_OPR
Definition: typcache.h:130
int errcode(int sqlerrcode)
Definition: elog.c:610
#define HASHEXTENDED_PROC
Definition: hash.h:354
#define MemSet(start, val, len)
Definition: c.h:978
#define GetSysCacheHashValue1(cacheId, key1)
Definition: syscache.h:201
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:927
unsigned int Oid
Definition: postgres_ext.h:31
int16 typlen
Definition: typcache.h:39
#define OidIsValid(objectId)
Definition: c.h:651
bool typbyval
Definition: typcache.h:40
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
Definition: inval.c:1476
Oid domainBaseType
Definition: typcache.h:107
FmgrInfo cmp_proc_finfo
Definition: typcache.h:75
struct TypeCacheEntry * nextDomain
Definition: typcache.h:126
#define TCFLAGS_CHECKED_GT_OPR
Definition: typcache.c:89
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define TCFLAGS_HAVE_PG_TYPE_DATA
Definition: typcache.c:84
#define HTEqualStrategyNumber
Definition: stratnum.h:41
char typstorage
Definition: typcache.h:42
static void TypeCacheRelCallback(Datum arg, Oid relid)
Definition: typcache.c:2150
static bool array_element_has_compare(TypeCacheEntry *typentry)
Definition: typcache.c:1382
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:164
int32 domainBaseTypmod
Definition: typcache.h:108
Oid hash_extended_proc
Definition: typcache.h:65
FmgrInfo hash_proc_finfo
Definition: typcache.h:76
#define TYPECACHE_GT_OPR
Definition: typcache.h:132
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:136
#define HASHSTANDARD_PROC
Definition: hash.h:353
#define TYPECACHE_BTREE_OPFAMILY
Definition: typcache.h:139
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:97
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:142
static void TypeCacheTypCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: typcache.c:2215
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
static bool range_element_has_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1538
#define HASH_BLOBS
Definition: hsearch.h:88
FmgrInfo hash_extended_proc_finfo
Definition: typcache.h:77
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1434
#define TYPECACHE_HASH_EXTENDED_PROC
Definition: typcache.h:144
uintptr_t Datum
Definition: postgres.h:367
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:328
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
Oid btree_opintype
Definition: typcache.h:57
Size keysize
Definition: hsearch.h:72
FmgrInfo eq_opr_finfo
Definition: typcache.h:74
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:331
#define InvalidOid
Definition: postgres_ext.h:36
static void load_rangetype_info(TypeCacheEntry *typentry)
Definition: typcache.c:878
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1202
Oid fn_oid
Definition: fmgr.h:59
#define ereport(elevel,...)
Definition: elog.h:144
#define TYPECACHE_CMP_PROC
Definition: typcache.h:133
char typtype
Definition: typcache.h:43
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:745
#define TYPECACHE_DOMAIN_CONSTR_INFO
Definition: typcache.h:143
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition: lsyscache.c:794
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
FormData_pg_type * Form_pg_type
Definition: pg_type.h:255
#define TCFLAGS_CHECKED_BTREE_OPCLASS
Definition: typcache.c:85
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:101
static bool record_fields_have_compare(TypeCacheEntry *typentry)
Definition: typcache.c:1444
Oid get_opclass_family(Oid opclass)
Definition: lsyscache.c:1129
static bool array_element_has_equality(TypeCacheEntry *typentry)
Definition: typcache.c:1374
static void load_domaintype_info(TypeCacheEntry *typentry)
Definition: typcache.c:941
#define TCFLAGS_CHECKED_HASH_PROC
Definition: typcache.c:91
char typalign
Definition: typcache.h:41
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define TYPECACHE_LT_OPR
Definition: typcache.h:131
#define TCFLAGS_CHECKED_LT_OPR
Definition: typcache.c:88
#define NameStr(name)
Definition: c.h:622
#define TYPECACHE_CMP_PROC_FINFO
Definition: typcache.h:136
#define TCFLAGS_CHECKED_HASH_OPCLASS
Definition: typcache.c:86
static bool range_element_has_extended_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1546
#define TYPECACHE_HASH_OPFAMILY
Definition: typcache.h:140
static bool record_fields_have_equality(TypeCacheEntry *typentry)
Definition: typcache.c:1436
#define TCFLAGS_CHECKED_CMP_PROC
Definition: typcache.c:90
#define BTLessStrategyNumber
Definition: stratnum.h:29
static bool array_element_has_extended_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1398
TupleDesc tupDesc
Definition: typcache.h:88
static void TypeCacheConstrCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: typcache.c:2284
static HTAB * TypeCacheHash
Definition: typcache.c:78
#define TYPECACHE_HASH_PROC
Definition: typcache.h:134
#define TYPECACHE_TUPDESC
Definition: typcache.h:138
#define BTEqualStrategyNumber
Definition: stratnum.h:31
static void TypeCacheOpcCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: typcache.c:2255
MemoryContext CacheMemoryContext
Definition: mcxt.c:47
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1151

◆ SharedRecordTypmodRegistryAttach()

void SharedRecordTypmodRegistryAttach ( SharedRecordTypmodRegistry )

Definition at line 2067 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().

2068 {
2069  MemoryContext old_context;
2070  dshash_table *record_table;
2071  dshash_table *typmod_table;
2072 
2074 
2075  /* We can't already be attached to a shared registry. */
2076  Assert(CurrentSession != NULL);
2077  Assert(CurrentSession->segment != NULL);
2078  Assert(CurrentSession->area != NULL);
2082 
2083  /*
2084  * We can't already have typmods in our local cache, because they'd clash
2085  * with those imported by SharedRecordTypmodRegistryInit. This should be
2086  * a freshly started parallel worker. If we ever support worker
2087  * recycling, a worker would need to zap its local cache in between
2088  * servicing different queries, in order to be able to call this and
2089  * synchronize typmods with a new leader; but that's problematic because
2090  * we can't be very sure that record-typmod-related state hasn't escaped
2091  * to anywhere else in the process.
2092  */
2093  Assert(NextRecordTypmod == 0);
2094 
2095  old_context = MemoryContextSwitchTo(TopMemoryContext);
2096 
2097  /* Attach to the two hash tables. */
2098  record_table = dshash_attach(CurrentSession->area,
2100  registry->record_table_handle,
2101  CurrentSession->area);
2102  typmod_table = dshash_attach(CurrentSession->area,
2104  registry->typmod_table_handle,
2105  NULL);
2106 
2107  MemoryContextSwitchTo(old_context);
2108 
2109  /*
2110  * Set up detach hook to run at worker exit. Currently this is the same
2111  * as the leader's detach hook, but in future they might need to be
2112  * different.
2113  */
2116  PointerGetDatum(registry));
2117 
2118  /*
2119  * Set up the session state that will tell assign_record_type_typmod and
2120  * lookup_rowtype_tupdesc_internal about the shared registry.
2121  */
2123  CurrentSession->shared_record_table = record_table;
2124  CurrentSession->shared_typmod_table = typmod_table;
2125 }
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:254
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:1091
dsa_area * area
Definition: session.h:28
#define IsParallelWorker()
Definition: parallel.h:61
MemoryContext TopMemoryContext
Definition: mcxt.c:44
static const dshash_parameters srtr_typmod_table_params
Definition: typcache.c:263
static void shared_record_typmod_registry_detach(dsm_segment *segment, Datum datum)
Definition: typcache.c:2733
static int32 NextRecordTypmod
Definition: typcache.c:278
struct SharedRecordTypmodRegistry * shared_typmod_registry
Definition: session.h:31
dshash_table * shared_typmod_table
Definition: session.h:33
#define Assert(condition)
Definition: c.h:745
dsm_segment * segment
Definition: session.h:27

◆ SharedRecordTypmodRegistryEstimate()

size_t SharedRecordTypmodRegistryEstimate ( void  )

Definition at line 1946 of file typcache.c.

Referenced by GetSessionDsmHandle().

1947 {
1948  return sizeof(SharedRecordTypmodRegistry);
1949 }
struct SharedRecordTypmodRegistry SharedRecordTypmodRegistry
Definition: typcache.h:168

◆ SharedRecordTypmodRegistryInit()

void SharedRecordTypmodRegistryInit ( SharedRecordTypmodRegistry ,
dsm_segment segment,
dsa_area area 
)

Definition at line 1968 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().

1971 {
1972  MemoryContext old_context;
1973  dshash_table *record_table;
1974  dshash_table *typmod_table;
1975  int32 typmod;
1976 
1978 
1979  /* We can't already be attached to a shared registry. */
1983 
1984  old_context = MemoryContextSwitchTo(TopMemoryContext);
1985 
1986  /* Create the hash table of tuple descriptors indexed by themselves. */
1987  record_table = dshash_create(area, &srtr_record_table_params, area);
1988 
1989  /* Create the hash table of tuple descriptors indexed by typmod. */
1990  typmod_table = dshash_create(area, &srtr_typmod_table_params, NULL);
1991 
1992  MemoryContextSwitchTo(old_context);
1993 
1994  /* Initialize the SharedRecordTypmodRegistry. */
1995  registry->record_table_handle = dshash_get_hash_table_handle(record_table);
1996  registry->typmod_table_handle = dshash_get_hash_table_handle(typmod_table);
1997  pg_atomic_init_u32(&registry->next_typmod, NextRecordTypmod);
1998 
1999  /*
2000  * Copy all entries from this backend's private registry into the shared
2001  * registry.
2002  */
2003  for (typmod = 0; typmod < NextRecordTypmod; ++typmod)
2004  {
2005  SharedTypmodTableEntry *typmod_table_entry;
2006  SharedRecordTableEntry *record_table_entry;
2007  SharedRecordTableKey record_table_key;
2008  dsa_pointer shared_dp;
2009  TupleDesc tupdesc;
2010  bool found;
2011 
2012  tupdesc = RecordCacheArray[typmod];
2013  if (tupdesc == NULL)
2014  continue;
2015 
2016  /* Copy the TupleDesc into shared memory. */
2017  shared_dp = share_tupledesc(area, tupdesc, typmod);
2018 
2019  /* Insert into the typmod table. */
2020  typmod_table_entry = dshash_find_or_insert(typmod_table,
2021  &tupdesc->tdtypmod,
2022  &found);
2023  if (found)
2024  elog(ERROR, "cannot create duplicate shared record typmod");
2025  typmod_table_entry->typmod = tupdesc->tdtypmod;
2026  typmod_table_entry->shared_tupdesc = shared_dp;
2027  dshash_release_lock(typmod_table, typmod_table_entry);
2028 
2029  /* Insert into the record table. */
2030  record_table_key.shared = false;
2031  record_table_key.u.local_tupdesc = tupdesc;
2032  record_table_entry = dshash_find_or_insert(record_table,
2033  &record_table_key,
2034  &found);
2035  if (!found)
2036  {
2037  record_table_entry->key.shared = true;
2038  record_table_entry->key.u.shared_tupdesc = shared_dp;
2039  }
2040  dshash_release_lock(record_table, record_table_entry);
2041  }
2042 
2043  /*
2044  * Set up the global state that will tell assign_record_type_typmod and
2045  * lookup_rowtype_tupdesc_internal about the shared registry.
2046  */
2047  CurrentSession->shared_record_table = record_table;
2048  CurrentSession->shared_typmod_table = typmod_table;
2050 
2051  /*
2052  * We install a detach hook in the leader, but only to handle cleanup on
2053  * failure during GetSessionDsmHandle(). Once GetSessionDsmHandle() pins
2054  * the memory, the leader process will use a shared registry until it
2055  * exits.
2056  */
2058 }
Session * CurrentSession
Definition: session.c:48
static const dshash_parameters srtr_record_table_params
Definition: typcache.c:254
dshash_table * shared_record_table
Definition: session.h:32
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
SharedRecordTableKey key
Definition: typcache.c:196
void on_dsm_detach(dsm_segment *seg, on_dsm_detach_callback function, Datum arg)
Definition: dsm.c:1091
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:362
static TupleDesc * RecordCacheArray
Definition: typcache.c:275
dsa_pointer shared_tupdesc
Definition: typcache.c:206
#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:185
union SharedRecordTableKey::@35 u
#define IsParallelWorker()
Definition: parallel.h:61
MemoryContext TopMemoryContext
Definition: mcxt.c:44
static const dshash_parameters srtr_typmod_table_params
Definition: typcache.c:263
static void shared_record_typmod_registry_detach(dsm_segment *segment, Datum datum)
Definition: typcache.c:2733
static int32 NextRecordTypmod
Definition: typcache.c:278
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
#define Assert(condition)
Definition: c.h:745
static dsa_pointer share_tupledesc(dsa_area *area, TupleDesc tupdesc, uint32 typmod)
Definition: typcache.c:2600
#define elog(elevel,...)
Definition: elog.h:214
void * dshash_find_or_insert(dshash_table *hash_table, const void *key, bool *found)
Definition: dshash.c:430
TupleDesc local_tupdesc
Definition: typcache.c:184
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:223

◆ UpdateDomainConstraintRef()

void UpdateDomainConstraintRef ( DomainConstraintRef ref)

Definition at line 1298 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().

1299 {
1300  TypeCacheEntry *typentry = ref->tcache;
1301 
1302  /* Make sure typcache entry's data is up to date */
1303  if ((typentry->flags & TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS) == 0 &&
1304  typentry->typtype == TYPTYPE_DOMAIN)
1305  load_domaintype_info(typentry);
1306 
1307  /* Transfer to ref object if there's new info, adjusting refcounts */
1308  if (ref->dcc != typentry->domainData)
1309  {
1310  /* Paranoia --- be sure link is nulled before trying to release */
1311  DomainConstraintCache *dcc = ref->dcc;
1312 
1313  if (dcc)
1314  {
1315  /*
1316  * Note: we just leak the previous list of executable domain
1317  * constraints. Alternatively, we could keep those in a child
1318  * context of ref->refctx and free that context at this point.
1319  * However, in practice this code path will be taken so seldom
1320  * that the extra bookkeeping for a child context doesn't seem
1321  * worthwhile; we'll just allow a leak for the lifespan of refctx.
1322  */
1323  ref->constraints = NIL;
1324  ref->dcc = NULL;
1325  decr_dcc_refcount(dcc);
1326  }
1327  dcc = typentry->domainData;
1328  if (dcc)
1329  {
1330  ref->dcc = dcc;
1331  dcc->dccRefCount++;
1332  if (ref->need_exprstate)
1334  ref->refctx);
1335  else
1336  ref->constraints = dcc->constraints;
1337  }
1338  }
1339 }
#define NIL
Definition: pg_list.h:65
DomainConstraintCache * dcc
Definition: typcache.h:164
DomainConstraintCache * domainData
Definition: typcache.h:114
MemoryContext refctx
Definition: typcache.h:159
char typtype
Definition: typcache.h:43
static List * prep_domain_constraints(List *constraints, MemoryContext execctx)
Definition: typcache.c:1222
TypeCacheEntry * tcache
Definition: typcache.h:160
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:101
static void load_domaintype_info(TypeCacheEntry *typentry)
Definition: typcache.c:941
static void decr_dcc_refcount(DomainConstraintCache *dcc)
Definition: typcache.c:1190