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   0x00001
 
#define TYPECACHE_LT_OPR   0x00002
 
#define TYPECACHE_GT_OPR   0x00004
 
#define TYPECACHE_CMP_PROC   0x00008
 
#define TYPECACHE_HASH_PROC   0x00010
 
#define TYPECACHE_EQ_OPR_FINFO   0x00020
 
#define TYPECACHE_CMP_PROC_FINFO   0x00040
 
#define TYPECACHE_HASH_PROC_FINFO   0x00080
 
#define TYPECACHE_TUPDESC   0x00100
 
#define TYPECACHE_BTREE_OPFAMILY   0x00200
 
#define TYPECACHE_HASH_OPFAMILY   0x00400
 
#define TYPECACHE_RANGE_INFO   0x00800
 
#define TYPECACHE_DOMAIN_BASE_INFO   0x01000
 
#define TYPECACHE_DOMAIN_CONSTR_INFO   0x02000
 
#define TYPECACHE_HASH_EXTENDED_PROC   0x04000
 
#define TYPECACHE_HASH_EXTENDED_PROC_FINFO   0x08000
 
#define TYPECACHE_MULTIRANGE_INFO   0x10000
 
#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   0x00200

Definition at line 145 of file typcache.h.

Referenced by lookup_type_cache().

◆ TYPECACHE_CMP_PROC

◆ TYPECACHE_CMP_PROC_FINFO

#define TYPECACHE_CMP_PROC_FINFO   0x00040

◆ TYPECACHE_DOMAIN_BASE_INFO

◆ TYPECACHE_DOMAIN_CONSTR_INFO

#define TYPECACHE_DOMAIN_CONSTR_INFO   0x02000

Definition at line 149 of file typcache.h.

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

◆ TYPECACHE_EQ_OPR

◆ TYPECACHE_EQ_OPR_FINFO

#define TYPECACHE_EQ_OPR_FINFO   0x00020

◆ TYPECACHE_GT_OPR

#define TYPECACHE_GT_OPR   0x00004

◆ TYPECACHE_HASH_EXTENDED_PROC

◆ TYPECACHE_HASH_EXTENDED_PROC_FINFO

#define TYPECACHE_HASH_EXTENDED_PROC_FINFO   0x08000

◆ TYPECACHE_HASH_OPFAMILY

#define TYPECACHE_HASH_OPFAMILY   0x00400

Definition at line 146 of file typcache.h.

Referenced by lookup_type_cache().

◆ TYPECACHE_HASH_PROC

◆ TYPECACHE_HASH_PROC_FINFO

#define TYPECACHE_HASH_PROC_FINFO   0x00080

◆ TYPECACHE_LT_OPR

◆ TYPECACHE_MULTIRANGE_INFO

#define TYPECACHE_MULTIRANGE_INFO   0x10000

Definition at line 152 of file typcache.h.

Referenced by get_multirange_io_data(), lookup_type_cache(), and multirange_get_typcache().

◆ TYPECACHE_RANGE_INFO

#define TYPECACHE_RANGE_INFO   0x00800

◆ TYPECACHE_TUPDESC

Typedef Documentation

◆ DomainConstraintCache

Definition at line 26 of file typcache.h.

◆ DomainConstraintRef

◆ SharedRecordTypmodRegistry

Definition at line 175 of file typcache.h.

◆ TypeCacheEntry

Function Documentation

◆ assign_record_type_identifier()

uint64 assign_record_type_identifier ( Oid  type_id,
int32  typmod 
)

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

2021 {
2022  if (type_id != RECORDOID)
2023  {
2024  /*
2025  * It's a named composite type, so use the regular typcache.
2026  */
2027  TypeCacheEntry *typentry;
2028 
2029  typentry = lookup_type_cache(type_id, TYPECACHE_TUPDESC);
2030  if (typentry->tupDesc == NULL)
2031  ereport(ERROR,
2032  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2033  errmsg("type %s is not composite",
2034  format_type_be(type_id))));
2035  Assert(typentry->tupDesc_identifier != 0);
2036  return typentry->tupDesc_identifier;
2037  }
2038  else
2039  {
2040  /*
2041  * It's a transient record type, so look in our record-type table.
2042  */
2043  if (typmod >= 0 && typmod < RecordCacheArrayLen &&
2044  RecordCacheArray[typmod] != NULL)
2045  {
2046  Assert(RecordIdentifierArray[typmod] != 0);
2047  return RecordIdentifierArray[typmod];
2048  }
2049 
2050  /* For anonymous or unrecognized record type, generate a new ID */
2051  return ++tupledesc_id_counter;
2052  }
2053 }
int errcode(int sqlerrcode)
Definition: elog.c:704
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
static uint64 tupledesc_id_counter
Definition: typcache.c:286
static TupleDesc * RecordCacheArray
Definition: typcache.c:276
#define ERROR
Definition: elog.h:45
static int32 RecordCacheArrayLen
Definition: typcache.c:278
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:338
#define ereport(elevel,...)
Definition: elog.h:155
#define Assert(condition)
Definition: c.h:792
uint64 tupDesc_identifier
Definition: typcache.h:90
int errmsg(const char *fmt,...)
Definition: elog.c:915
TupleDesc tupDesc
Definition: typcache.h:89
#define TYPECACHE_TUPDESC
Definition: typcache.h:144
static uint64 * RecordIdentifierArray
Definition: typcache.c:277

◆ assign_record_type_typmod()

void assign_record_type_typmod ( TupleDesc  tupDesc)

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

1947 {
1948  RecordCacheEntry *recentry;
1949  TupleDesc entDesc;
1950  bool found;
1951  MemoryContext oldcxt;
1952 
1953  Assert(tupDesc->tdtypeid == RECORDOID);
1954 
1955  if (RecordCacheHash == NULL)
1956  {
1957  /* First time through: initialize the hash table */
1958  HASHCTL ctl;
1959 
1960  ctl.keysize = sizeof(TupleDesc); /* just the pointer */
1961  ctl.entrysize = sizeof(RecordCacheEntry);
1964  RecordCacheHash = hash_create("Record information cache", 64,
1965  &ctl,
1967 
1968  /* Also make sure CacheMemoryContext exists */
1969  if (!CacheMemoryContext)
1971  }
1972 
1973  /* Find or create a hashtable entry for this tuple descriptor */
1975  (void *) &tupDesc,
1976  HASH_ENTER, &found);
1977  if (found && recentry->tupdesc != NULL)
1978  {
1979  tupDesc->tdtypmod = recentry->tupdesc->tdtypmod;
1980  return;
1981  }
1982 
1983  /* Not present, so need to manufacture an entry */
1984  recentry->tupdesc = NULL;
1986 
1987  /* Look in the SharedRecordTypmodRegistry, if attached */
1988  entDesc = find_or_make_matching_shared_tupledesc(tupDesc);
1989  if (entDesc == NULL)
1990  {
1991  /* Reference-counted local cache only. */
1992  entDesc = CreateTupleDescCopy(tupDesc);
1993  entDesc->tdrefcount = 1;
1994  entDesc->tdtypmod = NextRecordTypmod++;
1995  }
1997  RecordCacheArray[entDesc->tdtypmod] = entDesc;
1998  recentry->tupdesc = entDesc;
1999 
2000  /* Assign a unique tupdesc identifier, too. */
2002 
2003  /* Update the caller's tuple descriptor. */
2004  tupDesc->tdtypmod = entDesc->tdtypmod;
2005 
2006  MemoryContextSwitchTo(oldcxt);
2007 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
#define HASH_ELEM
Definition: hsearch.h:95
static TupleDesc find_or_make_matching_shared_tupledesc(TupleDesc tupdesc)
Definition: typcache.c:2736
struct RecordCacheEntry RecordCacheEntry
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Size entrysize
Definition: hsearch.h:76
static uint64 tupledesc_id_counter
Definition: typcache.c:286
static HTAB * RecordCacheHash
Definition: typcache.c:273
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
static TupleDesc * RecordCacheArray
Definition: typcache.c:276
int32 tdtypmod
Definition: tupdesc.h:83
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:349
static int32 NextRecordTypmod
Definition: typcache.c:279
static void ensure_record_cache_typmod_slot_exists(int32 typmod)
Definition: typcache.c:1698
Size keysize
Definition: hsearch.h:75
HashCompareFunc match
Definition: hsearch.h:80
static uint32 record_type_typmod_hash(const void *data, size_t size)
Definition: typcache.c:1919
#define Assert(condition)
Definition: c.h:792
#define HASH_COMPARE
Definition: hsearch.h:99
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:1930
TupleDesc tupdesc
Definition: typcache.c:158
int tdrefcount
Definition: tupdesc.h:84
static uint64 * RecordIdentifierArray
Definition: typcache.c:277
HashValueFunc hash
Definition: hsearch.h:78
#define HASH_FUNCTION
Definition: hsearch.h:98
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ compare_values_of_enum()

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

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

2453 {
2454  TypeCacheEnumData *enumdata;
2455  EnumItem *item1;
2456  EnumItem *item2;
2457 
2458  /*
2459  * Equal OIDs are certainly equal --- this case was probably handled by
2460  * our caller, but we may as well check.
2461  */
2462  if (arg1 == arg2)
2463  return 0;
2464 
2465  /* Load up the cache if first time through */
2466  if (tcache->enumData == NULL)
2467  load_enum_cache_data(tcache);
2468  enumdata = tcache->enumData;
2469 
2470  /*
2471  * If both OIDs are known-sorted, we can just compare them directly.
2472  */
2473  if (enum_known_sorted(enumdata, arg1) &&
2474  enum_known_sorted(enumdata, arg2))
2475  {
2476  if (arg1 < arg2)
2477  return -1;
2478  else
2479  return 1;
2480  }
2481 
2482  /*
2483  * Slow path: we have to identify their actual sort-order positions.
2484  */
2485  item1 = find_enumitem(enumdata, arg1);
2486  item2 = find_enumitem(enumdata, arg2);
2487 
2488  if (item1 == NULL || item2 == NULL)
2489  {
2490  /*
2491  * We couldn't find one or both values. That means the enum has
2492  * changed under us, so re-initialize the cache and try again. We
2493  * don't bother retrying the known-sorted case in this path.
2494  */
2495  load_enum_cache_data(tcache);
2496  enumdata = tcache->enumData;
2497 
2498  item1 = find_enumitem(enumdata, arg1);
2499  item2 = find_enumitem(enumdata, arg2);
2500 
2501  /*
2502  * If we still can't find the values, complain: we must have corrupt
2503  * data.
2504  */
2505  if (item1 == NULL)
2506  elog(ERROR, "enum value %u not found in cache for enum %s",
2507  arg1, format_type_be(tcache->type_id));
2508  if (item2 == NULL)
2509  elog(ERROR, "enum value %u not found in cache for enum %s",
2510  arg2, format_type_be(tcache->type_id));
2511  }
2512 
2513  if (item1->sort_order < item2->sort_order)
2514  return -1;
2515  else if (item1->sort_order > item2->sort_order)
2516  return 1;
2517  else
2518  return 0;
2519 }
struct TypeCacheEnumData * enumData
Definition: typcache.h:129
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
#define ERROR
Definition: elog.h:45
static bool enum_known_sorted(TypeCacheEnumData *enumdata, Oid arg)
Definition: typcache.c:2423
static EnumItem * find_enumitem(TypeCacheEnumData *enumdata, Oid arg)
Definition: typcache.c:2680
static void load_enum_cache_data(TypeCacheEntry *tcache)
Definition: typcache.c:2525
float4 sort_order
Definition: typcache.c:134
#define elog(elevel,...)
Definition: elog.h:228

◆ DomainHasConstraints()

bool DomainHasConstraints ( Oid  type_id)

Definition at line 1391 of file typcache.c.

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

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

1392 {
1393  TypeCacheEntry *typentry;
1394 
1395  /*
1396  * Note: a side effect is to cause the typcache's domain data to become
1397  * valid. This is fine since we'll likely need it soon if there is any.
1398  */
1399  typentry = lookup_type_cache(type_id, TYPECACHE_DOMAIN_CONSTR_INFO);
1400 
1401  return (typentry->domainData != NULL);
1402 }
DomainConstraintCache * domainData
Definition: typcache.h:120
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:338
#define TYPECACHE_DOMAIN_CONSTR_INFO
Definition: typcache.h:149

◆ InitDomainConstraintRef()

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

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

1306 {
1307  /* Look up the typcache entry --- we assume it survives indefinitely */
1309  ref->need_exprstate = need_exprstate;
1310  /* For safety, establish the callback before acquiring a refcount */
1311  ref->refctx = refctx;
1312  ref->dcc = NULL;
1314  ref->callback.arg = (void *) ref;
1316  /* Acquire refcount if there are constraints, and set up exported list */
1317  if (ref->tcache->domainData)
1318  {
1319  ref->dcc = ref->tcache->domainData;
1320  ref->dcc->dccRefCount++;
1321  if (ref->need_exprstate)
1323  ref->refctx);
1324  else
1325  ref->constraints = ref->dcc->constraints;
1326  }
1327  else
1328  ref->constraints = NIL;
1329 }
MemoryContextCallback callback
Definition: typcache.h:172
MemoryContextCallbackFunction func
Definition: palloc.h:49
#define NIL
Definition: pg_list.h:65
DomainConstraintCache * dcc
Definition: typcache.h:171
static void dccref_deletion_callback(void *arg)
Definition: typcache.c:1245
DomainConstraintCache * domainData
Definition: typcache.h:120
MemoryContext refctx
Definition: typcache.h:166
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:338
static List * prep_domain_constraints(List *constraints, MemoryContext execctx)
Definition: typcache.c:1266
#define TYPECACHE_DOMAIN_CONSTR_INFO
Definition: typcache.h:149
TypeCacheEntry * tcache
Definition: typcache.h:167
void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)
Definition: mcxt.c:286

◆ lookup_rowtype_tupdesc()

◆ lookup_rowtype_tupdesc_copy()

TupleDesc lookup_rowtype_tupdesc_copy ( Oid  type_id,
int32  typmod 
)

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

1861 {
1862  TupleDesc tmp;
1863 
1864  tmp = lookup_rowtype_tupdesc_internal(type_id, typmod, false);
1865  return CreateTupleDescCopyConstr(tmp);
1866 }
TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc)
Definition: tupdesc.c:150
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1735

◆ lookup_rowtype_tupdesc_domain()

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

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

1883 {
1884  TupleDesc tupDesc;
1885 
1886  if (type_id != RECORDOID)
1887  {
1888  /*
1889  * Check for domain or named composite type. We might as well load
1890  * whichever data is needed.
1891  */
1892  TypeCacheEntry *typentry;
1893 
1894  typentry = lookup_type_cache(type_id,
1897  if (typentry->typtype == TYPTYPE_DOMAIN)
1899  typentry->domainBaseTypmod,
1900  noError);
1901  if (typentry->tupDesc == NULL && !noError)
1902  ereport(ERROR,
1903  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1904  errmsg("type %s is not composite",
1905  format_type_be(type_id))));
1906  tupDesc = typentry->tupDesc;
1907  }
1908  else
1909  tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, noError);
1910  if (tupDesc != NULL)
1911  PinTupleDesc(tupDesc);
1912  return tupDesc;
1913 }
int errcode(int sqlerrcode)
Definition: elog.c:704
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
Oid domainBaseType
Definition: typcache.h:113
#define ERROR
Definition: elog.h:45
int32 domainBaseTypmod
Definition: typcache.h:114
TupleDesc lookup_rowtype_tupdesc_noerror(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1843
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:148
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:338
#define ereport(elevel,...)
Definition: elog.h:155
char typtype
Definition: typcache.h:43
#define PinTupleDesc(tupdesc)
Definition: tupdesc.h:116
int errmsg(const char *fmt,...)
Definition: elog.c:915
TupleDesc tupDesc
Definition: typcache.h:89
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1735
#define TYPECACHE_TUPDESC
Definition: typcache.h:144

◆ lookup_rowtype_tupdesc_noerror()

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

Definition at line 1843 of file typcache.c.

References lookup_rowtype_tupdesc_internal(), and PinTupleDesc.

Referenced by lookup_rowtype_tupdesc_domain().

1844 {
1845  TupleDesc tupDesc;
1846 
1847  tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, noError);
1848  if (tupDesc != NULL)
1849  PinTupleDesc(tupDesc);
1850  return tupDesc;
1851 }
#define PinTupleDesc(tupdesc)
Definition: tupdesc.h:116
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1735

◆ lookup_type_cache()

TypeCacheEntry* lookup_type_cache ( Oid  type_id,
int  flags 
)

Definition at line 338 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_multirangetype_info(), load_rangetype_info(), load_typcache_tupdesc(), lookup_type_cache(), TypeCacheEntry::lt_opr, MemSet, multirange_element_has_extended_hashing(), multirange_element_has_hashing(), NameStr, TypeCacheEntry::nextDomain, ObjectIdGetDatum, OidIsValid, range_element_has_extended_hashing(), range_element_has_hashing(), record_fields_have_compare(), record_fields_have_equality(), record_fields_have_extended_hashing(), record_fields_have_hashing(), ReleaseSysCache(), TypeCacheEntry::rngelemtype, TypeCacheEntry::rngtype, 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_MULTIRANGE_INFO, TYPECACHE_RANGE_INFO, TYPECACHE_TUPDESC, TypeCacheConstrCallback(), TypeCacheOpcCallback(), TypeCacheRelCallback(), TypeCacheTypCallback(), TypeCacheEntry::typelem, TYPEOID, TypeCacheEntry::typlen, TypeCacheEntry::typrelid, TypeCacheEntry::typstorage, TypeCacheEntry::typsubscript, 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_multirange_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_multirange_io_data(), get_range_io_data(), get_rule_orderby(), get_sort_group_operators(), hash_array(), hash_array_extended(), hash_multirange(), hash_multirange_extended(), hash_range(), hash_range_extended(), hash_record(), hash_record_extended(), InitDomainConstraintRef(), initGinState(), load_multirangetype_info(), load_rangetype_info(), lookup_rowtype_tupdesc_domain(), lookup_rowtype_tupdesc_internal(), lookup_type_cache(), make_expanded_record_from_tupdesc(), make_expanded_record_from_typeid(), multirange_get_typcache(), 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().

339 {
340  TypeCacheEntry *typentry;
341  bool found;
342 
343  if (TypeCacheHash == NULL)
344  {
345  /* First time through: initialize the hash table */
346  HASHCTL ctl;
347 
348  ctl.keysize = sizeof(Oid);
349  ctl.entrysize = sizeof(TypeCacheEntry);
350  TypeCacheHash = hash_create("Type information cache", 64,
351  &ctl, HASH_ELEM | HASH_BLOBS);
352 
353  /* Also set up callbacks for SI invalidations */
358 
359  /* Also make sure CacheMemoryContext exists */
360  if (!CacheMemoryContext)
362  }
363 
364  /* Try to look up an existing entry */
366  (void *) &type_id,
367  HASH_FIND, NULL);
368  if (typentry == NULL)
369  {
370  /*
371  * If we didn't find one, we want to make one. But first look up the
372  * pg_type row, just to make sure we don't make a cache entry for an
373  * invalid type OID. If the type OID is not valid, present a
374  * user-facing error, since some code paths such as domain_in() allow
375  * this function to be reached with a user-supplied OID.
376  */
377  HeapTuple tp;
378  Form_pg_type typtup;
379 
380  tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_id));
381  if (!HeapTupleIsValid(tp))
382  ereport(ERROR,
383  (errcode(ERRCODE_UNDEFINED_OBJECT),
384  errmsg("type with OID %u does not exist", type_id)));
385  typtup = (Form_pg_type) GETSTRUCT(tp);
386  if (!typtup->typisdefined)
387  ereport(ERROR,
388  (errcode(ERRCODE_UNDEFINED_OBJECT),
389  errmsg("type \"%s\" is only a shell",
390  NameStr(typtup->typname))));
391 
392  /* Now make the typcache entry */
394  (void *) &type_id,
395  HASH_ENTER, &found);
396  Assert(!found); /* it wasn't there a moment ago */
397 
398  MemSet(typentry, 0, sizeof(TypeCacheEntry));
399 
400  /* These fields can never change, by definition */
401  typentry->type_id = type_id;
403  ObjectIdGetDatum(type_id));
404 
405  /* Keep this part in sync with the code below */
406  typentry->typlen = typtup->typlen;
407  typentry->typbyval = typtup->typbyval;
408  typentry->typalign = typtup->typalign;
409  typentry->typstorage = typtup->typstorage;
410  typentry->typtype = typtup->typtype;
411  typentry->typrelid = typtup->typrelid;
412  typentry->typsubscript = typtup->typsubscript;
413  typentry->typelem = typtup->typelem;
414  typentry->typcollation = typtup->typcollation;
415  typentry->flags |= TCFLAGS_HAVE_PG_TYPE_DATA;
416 
417  /* If it's a domain, immediately thread it into the domain cache list */
418  if (typentry->typtype == TYPTYPE_DOMAIN)
419  {
420  typentry->nextDomain = firstDomainTypeEntry;
421  firstDomainTypeEntry = typentry;
422  }
423 
424  ReleaseSysCache(tp);
425  }
426  else if (!(typentry->flags & TCFLAGS_HAVE_PG_TYPE_DATA))
427  {
428  /*
429  * We have an entry, but its pg_type row got changed, so reload the
430  * data obtained directly from pg_type.
431  */
432  HeapTuple tp;
433  Form_pg_type typtup;
434 
435  tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_id));
436  if (!HeapTupleIsValid(tp))
437  ereport(ERROR,
438  (errcode(ERRCODE_UNDEFINED_OBJECT),
439  errmsg("type with OID %u does not exist", type_id)));
440  typtup = (Form_pg_type) GETSTRUCT(tp);
441  if (!typtup->typisdefined)
442  ereport(ERROR,
443  (errcode(ERRCODE_UNDEFINED_OBJECT),
444  errmsg("type \"%s\" is only a shell",
445  NameStr(typtup->typname))));
446 
447  /*
448  * Keep this part in sync with the code above. Many of these fields
449  * shouldn't ever change, particularly typtype, but copy 'em anyway.
450  */
451  typentry->typlen = typtup->typlen;
452  typentry->typbyval = typtup->typbyval;
453  typentry->typalign = typtup->typalign;
454  typentry->typstorage = typtup->typstorage;
455  typentry->typtype = typtup->typtype;
456  typentry->typrelid = typtup->typrelid;
457  typentry->typsubscript = typtup->typsubscript;
458  typentry->typelem = typtup->typelem;
459  typentry->typcollation = typtup->typcollation;
460  typentry->flags |= TCFLAGS_HAVE_PG_TYPE_DATA;
461 
462  ReleaseSysCache(tp);
463  }
464 
465  /*
466  * Look up opclasses if we haven't already and any dependent info is
467  * requested.
468  */
473  !(typentry->flags & TCFLAGS_CHECKED_BTREE_OPCLASS))
474  {
475  Oid opclass;
476 
477  opclass = GetDefaultOpClass(type_id, BTREE_AM_OID);
478  if (OidIsValid(opclass))
479  {
480  typentry->btree_opf = get_opclass_family(opclass);
481  typentry->btree_opintype = get_opclass_input_type(opclass);
482  }
483  else
484  {
485  typentry->btree_opf = typentry->btree_opintype = InvalidOid;
486  }
487 
488  /*
489  * Reset information derived from btree opclass. Note in particular
490  * that we'll redetermine the eq_opr even if we previously found one;
491  * this matters in case a btree opclass has been added to a type that
492  * previously had only a hash opclass.
493  */
494  typentry->flags &= ~(TCFLAGS_CHECKED_EQ_OPR |
499  }
500 
501  /*
502  * If we need to look up equality operator, and there's no btree opclass,
503  * force lookup of hash opclass.
504  */
505  if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO)) &&
506  !(typentry->flags & TCFLAGS_CHECKED_EQ_OPR) &&
507  typentry->btree_opf == InvalidOid)
508  flags |= TYPECACHE_HASH_OPFAMILY;
509 
514  !(typentry->flags & TCFLAGS_CHECKED_HASH_OPCLASS))
515  {
516  Oid opclass;
517 
518  opclass = GetDefaultOpClass(type_id, HASH_AM_OID);
519  if (OidIsValid(opclass))
520  {
521  typentry->hash_opf = get_opclass_family(opclass);
522  typentry->hash_opintype = get_opclass_input_type(opclass);
523  }
524  else
525  {
526  typentry->hash_opf = typentry->hash_opintype = InvalidOid;
527  }
528 
529  /*
530  * Reset information derived from hash opclass. We do *not* reset the
531  * eq_opr; if we already found one from the btree opclass, that
532  * decision is still good.
533  */
534  typentry->flags &= ~(TCFLAGS_CHECKED_HASH_PROC |
536  typentry->flags |= TCFLAGS_CHECKED_HASH_OPCLASS;
537  }
538 
539  /*
540  * Look for requested operators and functions, if we haven't already.
541  */
542  if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO)) &&
543  !(typentry->flags & TCFLAGS_CHECKED_EQ_OPR))
544  {
545  Oid eq_opr = InvalidOid;
546 
547  if (typentry->btree_opf != InvalidOid)
548  eq_opr = get_opfamily_member(typentry->btree_opf,
549  typentry->btree_opintype,
550  typentry->btree_opintype,
552  if (eq_opr == InvalidOid &&
553  typentry->hash_opf != InvalidOid)
554  eq_opr = get_opfamily_member(typentry->hash_opf,
555  typentry->hash_opintype,
556  typentry->hash_opintype,
558 
559  /*
560  * If the proposed equality operator is array_eq or record_eq, check
561  * to see if the element type or column types support equality. If
562  * not, array_eq or record_eq would fail at runtime, so we don't want
563  * to report that the type has equality. (We can omit similar
564  * checking for ranges and multiranges because ranges can't be created
565  * in the first place unless their subtypes support equality.)
566  */
567  if (eq_opr == ARRAY_EQ_OP &&
568  !array_element_has_equality(typentry))
569  eq_opr = InvalidOid;
570  else if (eq_opr == RECORD_EQ_OP &&
571  !record_fields_have_equality(typentry))
572  eq_opr = InvalidOid;
573 
574  /* Force update of eq_opr_finfo only if we're changing state */
575  if (typentry->eq_opr != eq_opr)
576  typentry->eq_opr_finfo.fn_oid = InvalidOid;
577 
578  typentry->eq_opr = eq_opr;
579 
580  /*
581  * Reset info about hash functions whenever we pick up new info about
582  * equality operator. This is so we can ensure that the hash
583  * functions match the operator.
584  */
585  typentry->flags &= ~(TCFLAGS_CHECKED_HASH_PROC |
587  typentry->flags |= TCFLAGS_CHECKED_EQ_OPR;
588  }
589  if ((flags & TYPECACHE_LT_OPR) &&
590  !(typentry->flags & TCFLAGS_CHECKED_LT_OPR))
591  {
592  Oid lt_opr = InvalidOid;
593 
594  if (typentry->btree_opf != InvalidOid)
595  lt_opr = get_opfamily_member(typentry->btree_opf,
596  typentry->btree_opintype,
597  typentry->btree_opintype,
599 
600  /*
601  * As above, make sure array_cmp or record_cmp will succeed; but again
602  * we need no special check for ranges or multiranges.
603  */
604  if (lt_opr == ARRAY_LT_OP &&
605  !array_element_has_compare(typentry))
606  lt_opr = InvalidOid;
607  else if (lt_opr == RECORD_LT_OP &&
608  !record_fields_have_compare(typentry))
609  lt_opr = InvalidOid;
610 
611  typentry->lt_opr = lt_opr;
612  typentry->flags |= TCFLAGS_CHECKED_LT_OPR;
613  }
614  if ((flags & TYPECACHE_GT_OPR) &&
615  !(typentry->flags & TCFLAGS_CHECKED_GT_OPR))
616  {
617  Oid gt_opr = InvalidOid;
618 
619  if (typentry->btree_opf != InvalidOid)
620  gt_opr = get_opfamily_member(typentry->btree_opf,
621  typentry->btree_opintype,
622  typentry->btree_opintype,
624 
625  /*
626  * As above, make sure array_cmp or record_cmp will succeed; but again
627  * we need no special check for ranges or multiranges.
628  */
629  if (gt_opr == ARRAY_GT_OP &&
630  !array_element_has_compare(typentry))
631  gt_opr = InvalidOid;
632  else if (gt_opr == RECORD_GT_OP &&
633  !record_fields_have_compare(typentry))
634  gt_opr = InvalidOid;
635 
636  typentry->gt_opr = gt_opr;
637  typentry->flags |= TCFLAGS_CHECKED_GT_OPR;
638  }
639  if ((flags & (TYPECACHE_CMP_PROC | TYPECACHE_CMP_PROC_FINFO)) &&
640  !(typentry->flags & TCFLAGS_CHECKED_CMP_PROC))
641  {
642  Oid cmp_proc = InvalidOid;
643 
644  if (typentry->btree_opf != InvalidOid)
645  cmp_proc = get_opfamily_proc(typentry->btree_opf,
646  typentry->btree_opintype,
647  typentry->btree_opintype,
648  BTORDER_PROC);
649 
650  /*
651  * As above, make sure array_cmp or record_cmp will succeed; but again
652  * we need no special check for ranges or multiranges.
653  */
654  if (cmp_proc == F_BTARRAYCMP &&
655  !array_element_has_compare(typentry))
656  cmp_proc = InvalidOid;
657  else if (cmp_proc == F_BTRECORDCMP &&
658  !record_fields_have_compare(typentry))
659  cmp_proc = InvalidOid;
660 
661  /* Force update of cmp_proc_finfo only if we're changing state */
662  if (typentry->cmp_proc != cmp_proc)
663  typentry->cmp_proc_finfo.fn_oid = InvalidOid;
664 
665  typentry->cmp_proc = cmp_proc;
666  typentry->flags |= TCFLAGS_CHECKED_CMP_PROC;
667  }
669  !(typentry->flags & TCFLAGS_CHECKED_HASH_PROC))
670  {
671  Oid hash_proc = InvalidOid;
672 
673  /*
674  * We insist that the eq_opr, if one has been determined, match the
675  * hash opclass; else report there is no hash function.
676  */
677  if (typentry->hash_opf != InvalidOid &&
678  (!OidIsValid(typentry->eq_opr) ||
679  typentry->eq_opr == get_opfamily_member(typentry->hash_opf,
680  typentry->hash_opintype,
681  typentry->hash_opintype,
683  hash_proc = get_opfamily_proc(typentry->hash_opf,
684  typentry->hash_opintype,
685  typentry->hash_opintype,
687 
688  /*
689  * As above, make sure hash_array, hash_record, or hash_range will
690  * succeed.
691  */
692  if (hash_proc == F_HASH_ARRAY &&
693  !array_element_has_hashing(typentry))
694  hash_proc = InvalidOid;
695  else if (hash_proc == F_HASH_RECORD &&
696  !record_fields_have_hashing(typentry))
697  hash_proc = InvalidOid;
698  else if (hash_proc == F_HASH_RANGE &&
699  !range_element_has_hashing(typentry))
700  hash_proc = InvalidOid;
701 
702  /*
703  * Likewise for hash_multirange.
704  */
705  if (hash_proc == F_HASH_MULTIRANGE &&
707  hash_proc = InvalidOid;
708 
709  /* Force update of hash_proc_finfo only if we're changing state */
710  if (typentry->hash_proc != hash_proc)
711  typentry->hash_proc_finfo.fn_oid = InvalidOid;
712 
713  typentry->hash_proc = hash_proc;
714  typentry->flags |= TCFLAGS_CHECKED_HASH_PROC;
715  }
716  if ((flags & (TYPECACHE_HASH_EXTENDED_PROC |
719  {
720  Oid hash_extended_proc = InvalidOid;
721 
722  /*
723  * We insist that the eq_opr, if one has been determined, match the
724  * hash opclass; else report there is no hash function.
725  */
726  if (typentry->hash_opf != InvalidOid &&
727  (!OidIsValid(typentry->eq_opr) ||
728  typentry->eq_opr == get_opfamily_member(typentry->hash_opf,
729  typentry->hash_opintype,
730  typentry->hash_opintype,
732  hash_extended_proc = get_opfamily_proc(typentry->hash_opf,
733  typentry->hash_opintype,
734  typentry->hash_opintype,
736 
737  /*
738  * As above, make sure hash_array_extended, hash_record_extended, or
739  * hash_range_extended will succeed.
740  */
741  if (hash_extended_proc == F_HASH_ARRAY_EXTENDED &&
743  hash_extended_proc = InvalidOid;
744  else if (hash_extended_proc == F_HASH_RECORD_EXTENDED &&
746  hash_extended_proc = InvalidOid;
747  else if (hash_extended_proc == F_HASH_RANGE_EXTENDED &&
749  hash_extended_proc = InvalidOid;
750 
751  /*
752  * Likewise for hash_multirange_extended.
753  */
754  if (hash_extended_proc == F_HASH_MULTIRANGE_EXTENDED &&
756  hash_extended_proc = InvalidOid;
757 
758  /* Force update of proc finfo only if we're changing state */
759  if (typentry->hash_extended_proc != hash_extended_proc)
761 
762  typentry->hash_extended_proc = hash_extended_proc;
764  }
765 
766  /*
767  * Set up fmgr lookup info as requested
768  *
769  * Note: we tell fmgr the finfo structures live in CacheMemoryContext,
770  * which is not quite right (they're really in the hash table's private
771  * memory context) but this will do for our purposes.
772  *
773  * Note: the code above avoids invalidating the finfo structs unless the
774  * referenced operator/function OID actually changes. This is to prevent
775  * unnecessary leakage of any subsidiary data attached to an finfo, since
776  * that would cause session-lifespan memory leaks.
777  */
778  if ((flags & TYPECACHE_EQ_OPR_FINFO) &&
779  typentry->eq_opr_finfo.fn_oid == InvalidOid &&
780  typentry->eq_opr != InvalidOid)
781  {
782  Oid eq_opr_func;
783 
784  eq_opr_func = get_opcode(typentry->eq_opr);
785  if (eq_opr_func != InvalidOid)
786  fmgr_info_cxt(eq_opr_func, &typentry->eq_opr_finfo,
788  }
789  if ((flags & TYPECACHE_CMP_PROC_FINFO) &&
790  typentry->cmp_proc_finfo.fn_oid == InvalidOid &&
791  typentry->cmp_proc != InvalidOid)
792  {
793  fmgr_info_cxt(typentry->cmp_proc, &typentry->cmp_proc_finfo,
795  }
796  if ((flags & TYPECACHE_HASH_PROC_FINFO) &&
797  typentry->hash_proc_finfo.fn_oid == InvalidOid &&
798  typentry->hash_proc != InvalidOid)
799  {
800  fmgr_info_cxt(typentry->hash_proc, &typentry->hash_proc_finfo,
802  }
803  if ((flags & TYPECACHE_HASH_EXTENDED_PROC_FINFO) &&
805  typentry->hash_extended_proc != InvalidOid)
806  {
808  &typentry->hash_extended_proc_finfo,
810  }
811 
812  /*
813  * If it's a composite type (row type), get tupdesc if requested
814  */
815  if ((flags & TYPECACHE_TUPDESC) &&
816  typentry->tupDesc == NULL &&
817  typentry->typtype == TYPTYPE_COMPOSITE)
818  {
819  load_typcache_tupdesc(typentry);
820  }
821 
822  /*
823  * If requested, get information about a range type
824  *
825  * This includes making sure that the basic info about the range element
826  * type is up-to-date.
827  */
828  if ((flags & TYPECACHE_RANGE_INFO) &&
829  typentry->typtype == TYPTYPE_RANGE)
830  {
831  if (typentry->rngelemtype == NULL)
832  load_rangetype_info(typentry);
833  else if (!(typentry->rngelemtype->flags & TCFLAGS_HAVE_PG_TYPE_DATA))
834  (void) lookup_type_cache(typentry->rngelemtype->type_id, 0);
835  }
836 
837  /*
838  * If requested, get information about a multirange type
839  */
840  if ((flags & TYPECACHE_MULTIRANGE_INFO) &&
841  typentry->rngtype == NULL &&
842  typentry->typtype == TYPTYPE_MULTIRANGE)
843  {
844  load_multirangetype_info(typentry);
845  }
846 
847  /*
848  * If requested, get information about a domain type
849  */
850  if ((flags & TYPECACHE_DOMAIN_BASE_INFO) &&
851  typentry->domainBaseType == InvalidOid &&
852  typentry->typtype == TYPTYPE_DOMAIN)
853  {
854  typentry->domainBaseTypmod = -1;
855  typentry->domainBaseType =
856  getBaseTypeAndTypmod(type_id, &typentry->domainBaseTypmod);
857  }
858  if ((flags & TYPECACHE_DOMAIN_CONSTR_INFO) &&
859  (typentry->flags & TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS) == 0 &&
860  typentry->typtype == TYPTYPE_DOMAIN)
861  {
862  load_domaintype_info(typentry);
863  }
864 
865  return typentry;
866 }
static bool array_element_has_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1434
static void load_typcache_tupdesc(TypeCacheEntry *typentry)
Definition: typcache.c:872
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition: lsyscache.c:2458
#define BTORDER_PROC
Definition: nbtree.h:576
#define TYPECACHE_RANGE_INFO
Definition: typcache.h:147
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:2090
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Oid hash_opintype
Definition: typcache.h:60
#define TCFLAGS_CHECKED_EQ_OPR
Definition: typcache.c:86
#define HASH_ELEM
Definition: hsearch.h:95
static TypeCacheEntry * firstDomainTypeEntry
Definition: typcache.c:80
uint32 type_id_hash
Definition: typcache.h:36
#define TYPECACHE_HASH_EXTENDED_PROC_FINFO
Definition: typcache.h:151
static bool multirange_element_has_extended_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1662
static bool record_fields_have_extended_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1504
#define TCFLAGS_CHECKED_HASH_EXTENDED_PROC
Definition: typcache.c:91
#define TYPECACHE_MULTIRANGE_INFO
Definition: typcache.h:152
struct TypeCacheEntry TypeCacheEntry
Oid typcollation
Definition: typcache.h:47
#define TYPECACHE_EQ_OPR_FINFO
Definition: typcache.h:141
#define TYPECACHE_HASH_PROC_FINFO
Definition: typcache.h:143
Size entrysize
Definition: hsearch.h:76
#define TYPECACHE_EQ_OPR
Definition: typcache.h:136
int errcode(int sqlerrcode)
Definition: elog.c:704
#define HASHEXTENDED_PROC
Definition: hash.h:354
#define MemSet(start, val, len)
Definition: c.h:996
#define GetSysCacheHashValue1(cacheId, key1)
Definition: syscache.h:202
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
unsigned int Oid
Definition: postgres_ext.h:31
int16 typlen
Definition: typcache.h:39
#define OidIsValid(objectId)
Definition: c.h:698
bool typbyval
Definition: typcache.h:40
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
Definition: inval.c:1476
Oid domainBaseType
Definition: typcache.h:113
FmgrInfo cmp_proc_finfo
Definition: typcache.h:76
struct TypeCacheEntry * nextDomain
Definition: typcache.h:132
#define TCFLAGS_CHECKED_GT_OPR
Definition: typcache.c:88
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
#define TCFLAGS_HAVE_PG_TYPE_DATA
Definition: typcache.c:83
#define HTEqualStrategyNumber
Definition: stratnum.h:41
static void load_multirangetype_info(TypeCacheEntry *typentry)
Definition: typcache.c:963
char typstorage
Definition: typcache.h:42
static void TypeCacheRelCallback(Datum arg, Oid relid)
Definition: typcache.c:2265
static bool array_element_has_compare(TypeCacheEntry *typentry)
Definition: typcache.c:1426
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:164
int32 domainBaseTypmod
Definition: typcache.h:114
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:349
Oid hash_extended_proc
Definition: typcache.h:66
FmgrInfo hash_proc_finfo
Definition: typcache.h:77
#define TYPECACHE_GT_OPR
Definition: typcache.h:138
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:145
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:98
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:148
static void TypeCacheTypCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: typcache.c:2330
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
static bool range_element_has_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1614
#define HASH_BLOBS
Definition: hsearch.h:97
FmgrInfo hash_extended_proc_finfo
Definition: typcache.h:78
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1434
#define TYPECACHE_HASH_EXTENDED_PROC
Definition: typcache.h:150
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Oid btree_opintype
Definition: typcache.h:58
Size keysize
Definition: hsearch.h:75
FmgrInfo eq_opr_finfo
Definition: typcache.h:75
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:338
#define InvalidOid
Definition: postgres_ext.h:36
static void load_rangetype_info(TypeCacheEntry *typentry)
Definition: typcache.c:906
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1229
static bool multirange_element_has_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1654
Oid fn_oid
Definition: fmgr.h:59
#define ereport(elevel,...)
Definition: elog.h:155
#define TYPECACHE_CMP_PROC
Definition: typcache.h:139
char typtype
Definition: typcache.h:43
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:792
#define TYPECACHE_DOMAIN_CONSTR_INFO
Definition: typcache.h:149
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:261
#define TCFLAGS_CHECKED_BTREE_OPCLASS
Definition: typcache.c:84
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:102
struct TypeCacheEntry * rngtype
Definition: typcache.h:107
static bool record_fields_have_compare(TypeCacheEntry *typentry)
Definition: typcache.c:1488
Oid get_opclass_family(Oid opclass)
Definition: lsyscache.c:1156
static bool record_fields_have_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1496
static bool array_element_has_equality(TypeCacheEntry *typentry)
Definition: typcache.c:1418
static void load_domaintype_info(TypeCacheEntry *typentry)
Definition: typcache.c:985
Oid typsubscript
Definition: typcache.h:45
#define TCFLAGS_CHECKED_HASH_PROC
Definition: typcache.c:90
char typalign
Definition: typcache.h:41
int errmsg(const char *fmt,...)
Definition: elog.c:915
#define TYPECACHE_LT_OPR
Definition: typcache.h:137
#define TCFLAGS_CHECKED_LT_OPR
Definition: typcache.c:87
#define NameStr(name)
Definition: c.h:669
#define TYPECACHE_CMP_PROC_FINFO
Definition: typcache.h:142
#define TCFLAGS_CHECKED_HASH_OPCLASS
Definition: typcache.c:85
static bool range_element_has_extended_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1622
#define TYPECACHE_HASH_OPFAMILY
Definition: typcache.h:146
static bool record_fields_have_equality(TypeCacheEntry *typentry)
Definition: typcache.c:1480
#define TCFLAGS_CHECKED_CMP_PROC
Definition: typcache.c:89
#define BTLessStrategyNumber
Definition: stratnum.h:29
static bool array_element_has_extended_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1442
TupleDesc tupDesc
Definition: typcache.h:89
static void TypeCacheConstrCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: typcache.c:2399
static HTAB * TypeCacheHash
Definition: typcache.c:77
#define TYPECACHE_HASH_PROC
Definition: typcache.h:140
#define TYPECACHE_TUPDESC
Definition: typcache.h:144
#define BTEqualStrategyNumber
Definition: stratnum.h:31
static void TypeCacheOpcCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: typcache.c:2370
MemoryContext CacheMemoryContext
Definition: mcxt.c:47
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1178

◆ SharedRecordTypmodRegistryAttach()

void SharedRecordTypmodRegistryAttach ( SharedRecordTypmodRegistry )

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

2183 {
2184  MemoryContext old_context;
2185  dshash_table *record_table;
2186  dshash_table *typmod_table;
2187 
2189 
2190  /* We can't already be attached to a shared registry. */
2191  Assert(CurrentSession != NULL);
2192  Assert(CurrentSession->segment != NULL);
2193  Assert(CurrentSession->area != NULL);
2197 
2198  /*
2199  * We can't already have typmods in our local cache, because they'd clash
2200  * with those imported by SharedRecordTypmodRegistryInit. This should be
2201  * a freshly started parallel worker. If we ever support worker
2202  * recycling, a worker would need to zap its local cache in between
2203  * servicing different queries, in order to be able to call this and
2204  * synchronize typmods with a new leader; but that's problematic because
2205  * we can't be very sure that record-typmod-related state hasn't escaped
2206  * to anywhere else in the process.
2207  */
2208  Assert(NextRecordTypmod == 0);
2209 
2210  old_context = MemoryContextSwitchTo(TopMemoryContext);
2211 
2212  /* Attach to the two hash tables. */
2213  record_table = dshash_attach(CurrentSession->area,
2215  registry->record_table_handle,
2216  CurrentSession->area);
2217  typmod_table = dshash_attach(CurrentSession->area,
2219  registry->typmod_table_handle,
2220  NULL);
2221 
2222  MemoryContextSwitchTo(old_context);
2223 
2224  /*
2225  * Set up detach hook to run at worker exit. Currently this is the same
2226  * as the leader's detach hook, but in future they might need to be
2227  * different.
2228  */
2231  PointerGetDatum(registry));
2232 
2233  /*
2234  * Set up the session state that will tell assign_record_type_typmod and
2235  * lookup_rowtype_tupdesc_internal about the shared registry.
2236  */
2238  CurrentSession->shared_record_table = record_table;
2239  CurrentSession->shared_typmod_table = typmod_table;
2240 }
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:255
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:264
static void shared_record_typmod_registry_detach(dsm_segment *segment, Datum datum)
Definition: typcache.c:2848
static int32 NextRecordTypmod
Definition: typcache.c:279
struct SharedRecordTypmodRegistry * shared_typmod_registry
Definition: session.h:31
dshash_table * shared_typmod_table
Definition: session.h:33
#define Assert(condition)
Definition: c.h:792
dsm_segment * segment
Definition: session.h:27

◆ SharedRecordTypmodRegistryEstimate()

size_t SharedRecordTypmodRegistryEstimate ( void  )

Definition at line 2061 of file typcache.c.

Referenced by GetSessionDsmHandle().

2062 {
2063  return sizeof(SharedRecordTypmodRegistry);
2064 }
struct SharedRecordTypmodRegistry SharedRecordTypmodRegistry
Definition: typcache.h:175

◆ SharedRecordTypmodRegistryInit()

void SharedRecordTypmodRegistryInit ( SharedRecordTypmodRegistry ,
dsm_segment segment,
dsa_area area 
)

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

2086 {
2087  MemoryContext old_context;
2088  dshash_table *record_table;
2089  dshash_table *typmod_table;
2090  int32 typmod;
2091 
2093 
2094  /* We can't already be attached to a shared registry. */
2098 
2099  old_context = MemoryContextSwitchTo(TopMemoryContext);
2100 
2101  /* Create the hash table of tuple descriptors indexed by themselves. */
2102  record_table = dshash_create(area, &srtr_record_table_params, area);
2103 
2104  /* Create the hash table of tuple descriptors indexed by typmod. */
2105  typmod_table = dshash_create(area, &srtr_typmod_table_params, NULL);
2106 
2107  MemoryContextSwitchTo(old_context);
2108 
2109  /* Initialize the SharedRecordTypmodRegistry. */
2110  registry->record_table_handle = dshash_get_hash_table_handle(record_table);
2111  registry->typmod_table_handle = dshash_get_hash_table_handle(typmod_table);
2112  pg_atomic_init_u32(&registry->next_typmod, NextRecordTypmod);
2113 
2114  /*
2115  * Copy all entries from this backend's private registry into the shared
2116  * registry.
2117  */
2118  for (typmod = 0; typmod < NextRecordTypmod; ++typmod)
2119  {
2120  SharedTypmodTableEntry *typmod_table_entry;
2121  SharedRecordTableEntry *record_table_entry;
2122  SharedRecordTableKey record_table_key;
2123  dsa_pointer shared_dp;
2124  TupleDesc tupdesc;
2125  bool found;
2126 
2127  tupdesc = RecordCacheArray[typmod];
2128  if (tupdesc == NULL)
2129  continue;
2130 
2131  /* Copy the TupleDesc into shared memory. */
2132  shared_dp = share_tupledesc(area, tupdesc, typmod);
2133 
2134  /* Insert into the typmod table. */
2135  typmod_table_entry = dshash_find_or_insert(typmod_table,
2136  &tupdesc->tdtypmod,
2137  &found);
2138  if (found)
2139  elog(ERROR, "cannot create duplicate shared record typmod");
2140  typmod_table_entry->typmod = tupdesc->tdtypmod;
2141  typmod_table_entry->shared_tupdesc = shared_dp;
2142  dshash_release_lock(typmod_table, typmod_table_entry);
2143 
2144  /* Insert into the record table. */
2145  record_table_key.shared = false;
2146  record_table_key.u.local_tupdesc = tupdesc;
2147  record_table_entry = dshash_find_or_insert(record_table,
2148  &record_table_key,
2149  &found);
2150  if (!found)
2151  {
2152  record_table_entry->key.shared = true;
2153  record_table_entry->key.u.shared_tupdesc = shared_dp;
2154  }
2155  dshash_release_lock(record_table, record_table_entry);
2156  }
2157 
2158  /*
2159  * Set up the global state that will tell assign_record_type_typmod and
2160  * lookup_rowtype_tupdesc_internal about the shared registry.
2161  */
2162  CurrentSession->shared_record_table = record_table;
2163  CurrentSession->shared_typmod_table = typmod_table;
2165 
2166  /*
2167  * We install a detach hook in the leader, but only to handle cleanup on
2168  * failure during GetSessionDsmHandle(). Once GetSessionDsmHandle() pins
2169  * the memory, the leader process will use a shared registry until it
2170  * exits.
2171  */
2173 }
Session * CurrentSession
Definition: session.c:48
static const dshash_parameters srtr_record_table_params
Definition: typcache.c:255
dshash_table * shared_record_table
Definition: session.h:32
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
SharedRecordTableKey key
Definition: typcache.c:197
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:417
static TupleDesc * RecordCacheArray
Definition: typcache.c:276
dsa_pointer shared_tupdesc
Definition: typcache.c:207
#define ERROR
Definition: elog.h:45
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:186
#define IsParallelWorker()
Definition: parallel.h:61
MemoryContext TopMemoryContext
Definition: mcxt.c:44
static const dshash_parameters srtr_typmod_table_params
Definition: typcache.c:264
static void shared_record_typmod_registry_detach(dsm_segment *segment, Datum datum)
Definition: typcache.c:2848
static int32 NextRecordTypmod
Definition: typcache.c:279
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:792
static dsa_pointer share_tupledesc(dsa_area *area, TupleDesc tupdesc, uint32 typmod)
Definition: typcache.c:2715
#define elog(elevel,...)
Definition: elog.h:228
void * dshash_find_or_insert(dshash_table *hash_table, const void *key, bool *found)
Definition: dshash.c:430
TupleDesc local_tupdesc
Definition: typcache.c:185
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:223
union SharedRecordTableKey::@33 u

◆ UpdateDomainConstraintRef()

void UpdateDomainConstraintRef ( DomainConstraintRef ref)

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

1343 {
1344  TypeCacheEntry *typentry = ref->tcache;
1345 
1346  /* Make sure typcache entry's data is up to date */
1347  if ((typentry->flags & TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS) == 0 &&
1348  typentry->typtype == TYPTYPE_DOMAIN)
1349  load_domaintype_info(typentry);
1350 
1351  /* Transfer to ref object if there's new info, adjusting refcounts */
1352  if (ref->dcc != typentry->domainData)
1353  {
1354  /* Paranoia --- be sure link is nulled before trying to release */
1355  DomainConstraintCache *dcc = ref->dcc;
1356 
1357  if (dcc)
1358  {
1359  /*
1360  * Note: we just leak the previous list of executable domain
1361  * constraints. Alternatively, we could keep those in a child
1362  * context of ref->refctx and free that context at this point.
1363  * However, in practice this code path will be taken so seldom
1364  * that the extra bookkeeping for a child context doesn't seem
1365  * worthwhile; we'll just allow a leak for the lifespan of refctx.
1366  */
1367  ref->constraints = NIL;
1368  ref->dcc = NULL;
1369  decr_dcc_refcount(dcc);
1370  }
1371  dcc = typentry->domainData;
1372  if (dcc)
1373  {
1374  ref->dcc = dcc;
1375  dcc->dccRefCount++;
1376  if (ref->need_exprstate)
1378  ref->refctx);
1379  else
1380  ref->constraints = dcc->constraints;
1381  }
1382  }
1383 }
#define NIL
Definition: pg_list.h:65
DomainConstraintCache * dcc
Definition: typcache.h:171
DomainConstraintCache * domainData
Definition: typcache.h:120
MemoryContext refctx
Definition: typcache.h:166
char typtype
Definition: typcache.h:43
static List * prep_domain_constraints(List *constraints, MemoryContext execctx)
Definition: typcache.c:1266
TypeCacheEntry * tcache
Definition: typcache.h:167
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:102
static void load_domaintype_info(TypeCacheEntry *typentry)
Definition: typcache.c:985
static void decr_dcc_refcount(DomainConstraintCache *dcc)
Definition: typcache.c:1234