PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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_INFO   0x1000
 
#define TYPECACHE_HASH_EXTENDED_PROC   0x2000
 
#define TYPECACHE_HASH_EXTENDED_PROC_FINFO   0x4000
 

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)
 
void assign_record_type_typmod (TupleDesc tupDesc)
 
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

#define TYPECACHE_BTREE_OPFAMILY   0x0200

Definition at line 123 of file typcache.h.

Referenced by lookup_type_cache().

#define TYPECACHE_CMP_PROC   0x0008
#define TYPECACHE_CMP_PROC_FINFO   0x0040
#define TYPECACHE_DOMAIN_INFO   0x1000

Definition at line 126 of file typcache.h.

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

#define TYPECACHE_EQ_OPR_FINFO   0x0020
#define TYPECACHE_GT_OPR   0x0004
#define TYPECACHE_HASH_EXTENDED_PROC   0x2000
#define TYPECACHE_HASH_EXTENDED_PROC_FINFO   0x4000

Definition at line 128 of file typcache.h.

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

#define TYPECACHE_HASH_OPFAMILY   0x0400

Definition at line 124 of file typcache.h.

Referenced by lookup_type_cache().

#define TYPECACHE_HASH_PROC   0x0010
#define TYPECACHE_HASH_PROC_FINFO   0x0080

Definition at line 121 of file typcache.h.

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

#define TYPECACHE_RANGE_INFO   0x0800

Definition at line 125 of file typcache.h.

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

#define TYPECACHE_TUPDESC   0x0100

Definition at line 122 of file typcache.h.

Referenced by lookup_rowtype_tupdesc_internal(), and lookup_type_cache().

Typedef Documentation

Definition at line 26 of file typcache.h.

Function Documentation

void assign_record_type_typmod ( TupleDesc  tupDesc)

Definition at line 1652 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(), RECORDOID, tupleDesc::tdrefcount, tupleDesc::tdtypeid, tupleDesc::tdtypmod, and RecordCacheEntry::tupdesc.

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

1653 {
1654  RecordCacheEntry *recentry;
1655  TupleDesc entDesc;
1656  bool found;
1657  MemoryContext oldcxt;
1658 
1659  Assert(tupDesc->tdtypeid == RECORDOID);
1660 
1661  if (RecordCacheHash == NULL)
1662  {
1663  /* First time through: initialize the hash table */
1664  HASHCTL ctl;
1665 
1666  MemSet(&ctl, 0, sizeof(ctl));
1667  ctl.keysize = sizeof(TupleDesc); /* just the pointer */
1668  ctl.entrysize = sizeof(RecordCacheEntry);
1671  RecordCacheHash = hash_create("Record information cache", 64,
1672  &ctl,
1674 
1675  /* Also make sure CacheMemoryContext exists */
1676  if (!CacheMemoryContext)
1678  }
1679 
1680  /* Find or create a hashtable entry for this tuple descriptor */
1682  (void *) &tupDesc,
1683  HASH_ENTER, &found);
1684  if (found && recentry->tupdesc != NULL)
1685  {
1686  tupDesc->tdtypmod = recentry->tupdesc->tdtypmod;
1687  return;
1688  }
1689 
1690  /* Not present, so need to manufacture an entry */
1691  recentry->tupdesc = NULL;
1693 
1694  /* Look in the SharedRecordTypmodRegistry, if attached */
1695  entDesc = find_or_make_matching_shared_tupledesc(tupDesc);
1696  if (entDesc == NULL)
1697  {
1698  /* Reference-counted local cache only. */
1699  entDesc = CreateTupleDescCopy(tupDesc);
1700  entDesc->tdrefcount = 1;
1701  entDesc->tdtypmod = NextRecordTypmod++;
1702  }
1704  RecordCacheArray[entDesc->tdtypmod] = entDesc;
1705  recentry->tupdesc = entDesc;
1706 
1707  /* Update the caller's tuple descriptor. */
1708  tupDesc->tdtypmod = entDesc->tdtypmod;
1709 
1710  MemoryContextSwitchTo(oldcxt);
1711 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:102
Oid tdtypeid
Definition: tupdesc.h:74
#define HASH_ELEM
Definition: hsearch.h:87
static TupleDesc find_or_make_matching_shared_tupledesc(TupleDesc tupdesc)
Definition: typcache.c:2341
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:863
static HTAB * RecordCacheHash
Definition: typcache.c:261
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
int32 tdtypmod
Definition: tupdesc.h:75
static TupleDesc * RecordCacheArray
Definition: typcache.c:263
#define RECORDOID
Definition: pg_type.h:680
static int32 NextRecordTypmod
Definition: typcache.c:265
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
static void ensure_record_cache_typmod_slot_exists(int32 typmod)
Definition: typcache.c:1463
Size keysize
Definition: hsearch.h:72
HashCompareFunc match
Definition: hsearch.h:75
struct tupleDesc * TupleDesc
static uint32 record_type_typmod_hash(const void *data, size_t size)
Definition: typcache.c:1625
#define Assert(condition)
Definition: c.h:681
#define HASH_COMPARE
Definition: hsearch.h:90
void CreateCacheMemoryContext(void)
Definition: catcache.c:636
static int record_type_typmod_compare(const void *a, const void *b, size_t size)
Definition: typcache.c:1636
int tdrefcount
Definition: tupdesc.h:77
TupleDesc tupdesc
Definition: typcache.c:147
HashValueFunc hash
Definition: hsearch.h:74
#define HASH_FUNCTION
Definition: hsearch.h:89
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
int compare_values_of_enum ( TypeCacheEntry tcache,
Oid  arg1,
Oid  arg2 
)

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

2058 {
2059  TypeCacheEnumData *enumdata;
2060  EnumItem *item1;
2061  EnumItem *item2;
2062 
2063  /*
2064  * Equal OIDs are certainly equal --- this case was probably handled by
2065  * our caller, but we may as well check.
2066  */
2067  if (arg1 == arg2)
2068  return 0;
2069 
2070  /* Load up the cache if first time through */
2071  if (tcache->enumData == NULL)
2072  load_enum_cache_data(tcache);
2073  enumdata = tcache->enumData;
2074 
2075  /*
2076  * If both OIDs are known-sorted, we can just compare them directly.
2077  */
2078  if (enum_known_sorted(enumdata, arg1) &&
2079  enum_known_sorted(enumdata, arg2))
2080  {
2081  if (arg1 < arg2)
2082  return -1;
2083  else
2084  return 1;
2085  }
2086 
2087  /*
2088  * Slow path: we have to identify their actual sort-order positions.
2089  */
2090  item1 = find_enumitem(enumdata, arg1);
2091  item2 = find_enumitem(enumdata, arg2);
2092 
2093  if (item1 == NULL || item2 == NULL)
2094  {
2095  /*
2096  * We couldn't find one or both values. That means the enum has
2097  * changed under us, so re-initialize the cache and try again. We
2098  * don't bother retrying the known-sorted case in this path.
2099  */
2100  load_enum_cache_data(tcache);
2101  enumdata = tcache->enumData;
2102 
2103  item1 = find_enumitem(enumdata, arg1);
2104  item2 = find_enumitem(enumdata, arg2);
2105 
2106  /*
2107  * If we still can't find the values, complain: we must have corrupt
2108  * data.
2109  */
2110  if (item1 == NULL)
2111  elog(ERROR, "enum value %u not found in cache for enum %s",
2112  arg1, format_type_be(tcache->type_id));
2113  if (item2 == NULL)
2114  elog(ERROR, "enum value %u not found in cache for enum %s",
2115  arg2, format_type_be(tcache->type_id));
2116  }
2117 
2118  if (item1->sort_order < item2->sort_order)
2119  return -1;
2120  else if (item1->sort_order > item2->sort_order)
2121  return 1;
2122  else
2123  return 0;
2124 }
struct TypeCacheEnumData * enumData
Definition: typcache.h:107
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
#define ERROR
Definition: elog.h:43
static bool enum_known_sorted(TypeCacheEnumData *enumdata, Oid arg)
Definition: typcache.c:2028
static EnumItem * find_enumitem(TypeCacheEnumData *enumdata, Oid arg)
Definition: typcache.c:2285
static void load_enum_cache_data(TypeCacheEntry *tcache)
Definition: typcache.c:2130
float4 sort_order
Definition: typcache.c:123
#define elog
Definition: elog.h:219
bool DomainHasConstraints ( Oid  type_id)

Definition at line 1252 of file typcache.c.

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

Referenced by ATColumnChangeRequiresRewrite(), and ATExecAddColumn().

1253 {
1254  TypeCacheEntry *typentry;
1255 
1256  /*
1257  * Note: a side effect is to cause the typcache's domain data to become
1258  * valid. This is fine since we'll likely need it soon if there is any.
1259  */
1260  typentry = lookup_type_cache(type_id, TYPECACHE_DOMAIN_INFO);
1261 
1262  return (typentry->domainData != NULL);
1263 }
DomainConstraintCache * domainData
Definition: typcache.h:98
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:310
#define TYPECACHE_DOMAIN_INFO
Definition: typcache.h:126
void InitDomainConstraintRef ( Oid  type_id,
DomainConstraintRef ref,
MemoryContext  refctx,
bool  need_exprstate 
)

Definition at line 1165 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_INFO.

Referenced by domain_state_setup(), and ExecInitCoerceToDomain().

1167 {
1168  /* Look up the typcache entry --- we assume it survives indefinitely */
1170  ref->need_exprstate = need_exprstate;
1171  /* For safety, establish the callback before acquiring a refcount */
1172  ref->refctx = refctx;
1173  ref->dcc = NULL;
1175  ref->callback.arg = (void *) ref;
1177  /* Acquire refcount if there are constraints, and set up exported list */
1178  if (ref->tcache->domainData)
1179  {
1180  ref->dcc = ref->tcache->domainData;
1181  ref->dcc->dccRefCount++;
1182  if (ref->need_exprstate)
1184  ref->refctx);
1185  else
1186  ref->constraints = ref->dcc->constraints;
1187  }
1188  else
1189  ref->constraints = NIL;
1190 }
MemoryContextCallback callback
Definition: typcache.h:145
MemoryContextCallbackFunction func
Definition: palloc.h:49
#define NIL
Definition: pg_list.h:69
DomainConstraintCache * dcc
Definition: typcache.h:144
static void dccref_deletion_callback(void *arg)
Definition: typcache.c:1106
DomainConstraintCache * domainData
Definition: typcache.h:98
MemoryContext refctx
Definition: typcache.h:139
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:310
static List * prep_domain_constraints(List *constraints, MemoryContext execctx)
Definition: typcache.c:1127
TypeCacheEntry * tcache
Definition: typcache.h:140
void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)
Definition: mcxt.c:265
#define TYPECACHE_DOMAIN_INFO
Definition: typcache.h:126
TupleDesc lookup_rowtype_tupdesc_copy ( Oid  type_id,
int32  typmod 
)

Definition at line 1613 of file typcache.c.

References CreateTupleDescCopyConstr(), and lookup_rowtype_tupdesc_internal().

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

1614 {
1615  TupleDesc tmp;
1616 
1617  tmp = lookup_rowtype_tupdesc_internal(type_id, typmod, false);
1618  return CreateTupleDescCopyConstr(tmp);
1619 }
TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc)
Definition: tupdesc.c:131
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1494
TupleDesc lookup_rowtype_tupdesc_noerror ( Oid  type_id,
int32  typmod,
bool  noError 
)

Definition at line 1596 of file typcache.c.

References lookup_rowtype_tupdesc_internal(), and PinTupleDesc.

Referenced by plperl_sv_to_datum().

1597 {
1598  TupleDesc tupDesc;
1599 
1600  tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, noError);
1601  if (tupDesc != NULL)
1602  PinTupleDesc(tupDesc);
1603  return tupDesc;
1604 }
#define PinTupleDesc(tupdesc)
Definition: tupdesc.h:109
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1494
TypeCacheEntry* lookup_type_cache ( Oid  type_id,
int  flags 
)

Definition at line 310 of file typcache.c.

References array_element_has_compare(), array_element_has_equality(), array_element_has_extended_hashing(), array_element_has_hashing(), ARRAY_EQ_OP, ARRAY_GT_OP, ARRAY_LT_OP, Assert, BTEqualStrategyNumber, BTGreaterStrategyNumber, BTLessStrategyNumber, BTORDER_PROC, BTREE_AM_OID, TypeCacheEntry::btree_opf, TypeCacheEntry::btree_opintype, CacheMemoryContext, CacheRegisterRelcacheCallback(), CacheRegisterSyscacheCallback(), CLAOID, TypeCacheEntry::cmp_proc, TypeCacheEntry::cmp_proc_finfo, CONSTROID, CreateCacheMemoryContext(), 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(), GetDefaultOpClass(), GETSTRUCT, TypeCacheEntry::gt_opr, HASH_AM_OID, HASH_BLOBS, hash_create(), HASH_ELEM, HASH_ENTER, TypeCacheEntry::hash_extended_proc, TypeCacheEntry::hash_extended_proc_finfo, HASH_FIND, TypeCacheEntry::hash_opf, TypeCacheEntry::hash_opintype, TypeCacheEntry::hash_proc, TypeCacheEntry::hash_proc_finfo, hash_search(), HASHEXTENDED_PROC, HASHSTANDARD_PROC, HeapTupleIsValid, HTEqualStrategyNumber, InvalidOid, HASHCTL::keysize, load_domaintype_info(), load_rangetype_info(), load_typcache_tupdesc(), TypeCacheEntry::lt_opr, MemSet, NameStr, TypeCacheEntry::nextDomain, ObjectIdGetDatum, OidIsValid, range_element_has_extended_hashing(), range_element_has_hashing(), RECORD_EQ_OP, record_fields_have_compare(), record_fields_have_equality(), RECORD_GT_OP, RECORD_LT_OP, ReleaseSysCache(), TypeCacheEntry::rngelemtype, SearchSysCache1(), TCFLAGS_CHECKED_BTREE_OPCLASS, TCFLAGS_CHECKED_CMP_PROC, TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS, TCFLAGS_CHECKED_EQ_OPR, TCFLAGS_CHECKED_GT_OPR, TCFLAGS_CHECKED_HASH_EXTENDED_PROC, TCFLAGS_CHECKED_HASH_OPCLASS, TCFLAGS_CHECKED_HASH_PROC, TCFLAGS_CHECKED_LT_OPR, TypeCacheEntry::tupDesc, TypeCacheEntry::typalign, TypeCacheEntry::typbyval, TypeCacheEntry::type_id, TYPECACHE_BTREE_OPFAMILY, TYPECACHE_CMP_PROC, TYPECACHE_CMP_PROC_FINFO, TYPECACHE_DOMAIN_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(), TYPEOID, TypeCacheEntry::typlen, TypeCacheEntry::typrelid, TypeCacheEntry::typstorage, TypeCacheEntry::typtype, TYPTYPE_COMPOSITE, TYPTYPE_DOMAIN, and TYPTYPE_RANGE.

Referenced by appendAggOrderBy(), array_cmp(), array_contain_compare(), array_eq(), array_position_common(), array_positions(), array_replace_internal(), array_typanalyze(), brin_inclusion_opcinfo(), brin_minmax_opcinfo(), cache_array_element_properties(), cache_range_element_properties(), cache_record_field_properties(), calc_arraycontsel(), 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_internal(), ndistinct_for_combination(), op_hashjoinable(), op_mergejoinable(), range_get_typcache(), record_cmp(), record_eq(), refresh_by_match_merge(), scalararraysel(), scalararraysel_containment(), show_sortorder_options(), tuple_equals_slot(), and width_bucket_array().

311 {
312  TypeCacheEntry *typentry;
313  bool found;
314 
315  if (TypeCacheHash == NULL)
316  {
317  /* First time through: initialize the hash table */
318  HASHCTL ctl;
319 
320  MemSet(&ctl, 0, sizeof(ctl));
321  ctl.keysize = sizeof(Oid);
322  ctl.entrysize = sizeof(TypeCacheEntry);
323  TypeCacheHash = hash_create("Type information cache", 64,
324  &ctl, HASH_ELEM | HASH_BLOBS);
325 
326  /* Also set up callbacks for SI invalidations */
331 
332  /* Also make sure CacheMemoryContext exists */
333  if (!CacheMemoryContext)
335  }
336 
337  /* Try to look up an existing entry */
339  (void *) &type_id,
340  HASH_FIND, NULL);
341  if (typentry == NULL)
342  {
343  /*
344  * If we didn't find one, we want to make one. But first look up the
345  * pg_type row, just to make sure we don't make a cache entry for an
346  * invalid type OID. If the type OID is not valid, present a
347  * user-facing error, since some code paths such as domain_in() allow
348  * this function to be reached with a user-supplied OID.
349  */
350  HeapTuple tp;
351  Form_pg_type typtup;
352 
353  tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_id));
354  if (!HeapTupleIsValid(tp))
355  ereport(ERROR,
356  (errcode(ERRCODE_UNDEFINED_OBJECT),
357  errmsg("type with OID %u does not exist", type_id)));
358  typtup = (Form_pg_type) GETSTRUCT(tp);
359  if (!typtup->typisdefined)
360  ereport(ERROR,
361  (errcode(ERRCODE_UNDEFINED_OBJECT),
362  errmsg("type \"%s\" is only a shell",
363  NameStr(typtup->typname))));
364 
365  /* Now make the typcache entry */
367  (void *) &type_id,
368  HASH_ENTER, &found);
369  Assert(!found); /* it wasn't there a moment ago */
370 
371  MemSet(typentry, 0, sizeof(TypeCacheEntry));
372  typentry->type_id = type_id;
373  typentry->typlen = typtup->typlen;
374  typentry->typbyval = typtup->typbyval;
375  typentry->typalign = typtup->typalign;
376  typentry->typstorage = typtup->typstorage;
377  typentry->typtype = typtup->typtype;
378  typentry->typrelid = typtup->typrelid;
379 
380  /* If it's a domain, immediately thread it into the domain cache list */
381  if (typentry->typtype == TYPTYPE_DOMAIN)
382  {
383  typentry->nextDomain = firstDomainTypeEntry;
384  firstDomainTypeEntry = typentry;
385  }
386 
387  ReleaseSysCache(tp);
388  }
389 
390  /*
391  * Look up opclasses if we haven't already and any dependent info is
392  * requested.
393  */
398  !(typentry->flags & TCFLAGS_CHECKED_BTREE_OPCLASS))
399  {
400  Oid opclass;
401 
402  opclass = GetDefaultOpClass(type_id, BTREE_AM_OID);
403  if (OidIsValid(opclass))
404  {
405  typentry->btree_opf = get_opclass_family(opclass);
406  typentry->btree_opintype = get_opclass_input_type(opclass);
407  }
408  else
409  {
410  typentry->btree_opf = typentry->btree_opintype = InvalidOid;
411  }
412 
413  /*
414  * Reset information derived from btree opclass. Note in particular
415  * that we'll redetermine the eq_opr even if we previously found one;
416  * this matters in case a btree opclass has been added to a type that
417  * previously had only a hash opclass.
418  */
419  typentry->flags &= ~(TCFLAGS_CHECKED_EQ_OPR |
424  }
425 
426  /*
427  * If we need to look up equality operator, and there's no btree opclass,
428  * force lookup of hash opclass.
429  */
430  if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO)) &&
431  !(typentry->flags & TCFLAGS_CHECKED_EQ_OPR) &&
432  typentry->btree_opf == InvalidOid)
433  flags |= TYPECACHE_HASH_OPFAMILY;
434 
439  !(typentry->flags & TCFLAGS_CHECKED_HASH_OPCLASS))
440  {
441  Oid opclass;
442 
443  opclass = GetDefaultOpClass(type_id, HASH_AM_OID);
444  if (OidIsValid(opclass))
445  {
446  typentry->hash_opf = get_opclass_family(opclass);
447  typentry->hash_opintype = get_opclass_input_type(opclass);
448  }
449  else
450  {
451  typentry->hash_opf = typentry->hash_opintype = InvalidOid;
452  }
453 
454  /*
455  * Reset information derived from hash opclass. We do *not* reset the
456  * eq_opr; if we already found one from the btree opclass, that
457  * decision is still good.
458  */
459  typentry->flags &= ~(TCFLAGS_CHECKED_HASH_PROC |
461  typentry->flags |= TCFLAGS_CHECKED_HASH_OPCLASS;
462  }
463 
464  /*
465  * Look for requested operators and functions, if we haven't already.
466  */
467  if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO)) &&
468  !(typentry->flags & TCFLAGS_CHECKED_EQ_OPR))
469  {
470  Oid eq_opr = InvalidOid;
471 
472  if (typentry->btree_opf != InvalidOid)
473  eq_opr = get_opfamily_member(typentry->btree_opf,
474  typentry->btree_opintype,
475  typentry->btree_opintype,
477  if (eq_opr == InvalidOid &&
478  typentry->hash_opf != InvalidOid)
479  eq_opr = get_opfamily_member(typentry->hash_opf,
480  typentry->hash_opintype,
481  typentry->hash_opintype,
483 
484  /*
485  * If the proposed equality operator is array_eq or record_eq, check
486  * to see if the element type or column types support equality. If
487  * not, array_eq or record_eq would fail at runtime, so we don't want
488  * to report that the type has equality. (We can omit similar
489  * checking for ranges because ranges can't be created in the first
490  * place unless their subtypes support equality.)
491  */
492  if (eq_opr == ARRAY_EQ_OP &&
493  !array_element_has_equality(typentry))
494  eq_opr = InvalidOid;
495  else if (eq_opr == RECORD_EQ_OP &&
496  !record_fields_have_equality(typentry))
497  eq_opr = InvalidOid;
498 
499  /* Force update of eq_opr_finfo only if we're changing state */
500  if (typentry->eq_opr != eq_opr)
501  typentry->eq_opr_finfo.fn_oid = InvalidOid;
502 
503  typentry->eq_opr = eq_opr;
504 
505  /*
506  * Reset info about hash functions whenever we pick up new info about
507  * equality operator. This is so we can ensure that the hash
508  * functions match the operator.
509  */
510  typentry->flags &= ~(TCFLAGS_CHECKED_HASH_PROC |
512  typentry->flags |= TCFLAGS_CHECKED_EQ_OPR;
513  }
514  if ((flags & TYPECACHE_LT_OPR) &&
515  !(typentry->flags & TCFLAGS_CHECKED_LT_OPR))
516  {
517  Oid lt_opr = InvalidOid;
518 
519  if (typentry->btree_opf != InvalidOid)
520  lt_opr = get_opfamily_member(typentry->btree_opf,
521  typentry->btree_opintype,
522  typentry->btree_opintype,
524 
525  /*
526  * As above, make sure array_cmp or record_cmp will succeed; but again
527  * we need no special check for ranges.
528  */
529  if (lt_opr == ARRAY_LT_OP &&
530  !array_element_has_compare(typentry))
531  lt_opr = InvalidOid;
532  else if (lt_opr == RECORD_LT_OP &&
533  !record_fields_have_compare(typentry))
534  lt_opr = InvalidOid;
535 
536  typentry->lt_opr = lt_opr;
537  typentry->flags |= TCFLAGS_CHECKED_LT_OPR;
538  }
539  if ((flags & TYPECACHE_GT_OPR) &&
540  !(typentry->flags & TCFLAGS_CHECKED_GT_OPR))
541  {
542  Oid gt_opr = InvalidOid;
543 
544  if (typentry->btree_opf != InvalidOid)
545  gt_opr = get_opfamily_member(typentry->btree_opf,
546  typentry->btree_opintype,
547  typentry->btree_opintype,
549 
550  /*
551  * As above, make sure array_cmp or record_cmp will succeed; but again
552  * we need no special check for ranges.
553  */
554  if (gt_opr == ARRAY_GT_OP &&
555  !array_element_has_compare(typentry))
556  gt_opr = InvalidOid;
557  else if (gt_opr == RECORD_GT_OP &&
558  !record_fields_have_compare(typentry))
559  gt_opr = InvalidOid;
560 
561  typentry->gt_opr = gt_opr;
562  typentry->flags |= TCFLAGS_CHECKED_GT_OPR;
563  }
564  if ((flags & (TYPECACHE_CMP_PROC | TYPECACHE_CMP_PROC_FINFO)) &&
565  !(typentry->flags & TCFLAGS_CHECKED_CMP_PROC))
566  {
567  Oid cmp_proc = InvalidOid;
568 
569  if (typentry->btree_opf != InvalidOid)
570  cmp_proc = get_opfamily_proc(typentry->btree_opf,
571  typentry->btree_opintype,
572  typentry->btree_opintype,
573  BTORDER_PROC);
574 
575  /*
576  * As above, make sure array_cmp or record_cmp will succeed; but again
577  * we need no special check for ranges.
578  */
579  if (cmp_proc == F_BTARRAYCMP &&
580  !array_element_has_compare(typentry))
581  cmp_proc = InvalidOid;
582  else if (cmp_proc == F_BTRECORDCMP &&
583  !record_fields_have_compare(typentry))
584  cmp_proc = InvalidOid;
585 
586  /* Force update of cmp_proc_finfo only if we're changing state */
587  if (typentry->cmp_proc != cmp_proc)
588  typentry->cmp_proc_finfo.fn_oid = InvalidOid;
589 
590  typentry->cmp_proc = cmp_proc;
591  typentry->flags |= TCFLAGS_CHECKED_CMP_PROC;
592  }
594  !(typentry->flags & TCFLAGS_CHECKED_HASH_PROC))
595  {
596  Oid hash_proc = InvalidOid;
597 
598  /*
599  * We insist that the eq_opr, if one has been determined, match the
600  * hash opclass; else report there is no hash function.
601  */
602  if (typentry->hash_opf != InvalidOid &&
603  (!OidIsValid(typentry->eq_opr) ||
604  typentry->eq_opr == get_opfamily_member(typentry->hash_opf,
605  typentry->hash_opintype,
606  typentry->hash_opintype,
608  hash_proc = get_opfamily_proc(typentry->hash_opf,
609  typentry->hash_opintype,
610  typentry->hash_opintype,
612 
613  /*
614  * As above, make sure hash_array will succeed. We don't currently
615  * support hashing for composite types, but when we do, we'll need
616  * more logic here to check that case too.
617  */
618  if (hash_proc == F_HASH_ARRAY &&
619  !array_element_has_hashing(typentry))
620  hash_proc = InvalidOid;
621 
622  /*
623  * Likewise for hash_range.
624  */
625  if (hash_proc == F_HASH_RANGE &&
626  !range_element_has_hashing(typentry))
627  hash_proc = InvalidOid;
628 
629  /* Force update of hash_proc_finfo only if we're changing state */
630  if (typentry->hash_proc != hash_proc)
631  typentry->hash_proc_finfo.fn_oid = InvalidOid;
632 
633  typentry->hash_proc = hash_proc;
634  typentry->flags |= TCFLAGS_CHECKED_HASH_PROC;
635  }
636  if ((flags & (TYPECACHE_HASH_EXTENDED_PROC |
639  {
640  Oid hash_extended_proc = InvalidOid;
641 
642  /*
643  * We insist that the eq_opr, if one has been determined, match the
644  * hash opclass; else report there is no hash function.
645  */
646  if (typentry->hash_opf != InvalidOid &&
647  (!OidIsValid(typentry->eq_opr) ||
648  typentry->eq_opr == get_opfamily_member(typentry->hash_opf,
649  typentry->hash_opintype,
650  typentry->hash_opintype,
652  hash_extended_proc = get_opfamily_proc(typentry->hash_opf,
653  typentry->hash_opintype,
654  typentry->hash_opintype,
656 
657  /*
658  * As above, make sure hash_array_extended will succeed. We don't
659  * currently support hashing for composite types, but when we do,
660  * we'll need more logic here to check that case too.
661  */
662  if (hash_extended_proc == F_HASH_ARRAY_EXTENDED &&
664  hash_extended_proc = InvalidOid;
665 
666  /*
667  * Likewise for hash_range_extended.
668  */
669  if (hash_extended_proc == F_HASH_RANGE_EXTENDED &&
671  hash_extended_proc = InvalidOid;
672 
673  /* Force update of proc finfo only if we're changing state */
674  if (typentry->hash_extended_proc != hash_extended_proc)
676 
677  typentry->hash_extended_proc = hash_extended_proc;
679  }
680 
681  /*
682  * Set up fmgr lookup info as requested
683  *
684  * Note: we tell fmgr the finfo structures live in CacheMemoryContext,
685  * which is not quite right (they're really in the hash table's private
686  * memory context) but this will do for our purposes.
687  *
688  * Note: the code above avoids invalidating the finfo structs unless the
689  * referenced operator/function OID actually changes. This is to prevent
690  * unnecessary leakage of any subsidiary data attached to an finfo, since
691  * that would cause session-lifespan memory leaks.
692  */
693  if ((flags & TYPECACHE_EQ_OPR_FINFO) &&
694  typentry->eq_opr_finfo.fn_oid == InvalidOid &&
695  typentry->eq_opr != InvalidOid)
696  {
697  Oid eq_opr_func;
698 
699  eq_opr_func = get_opcode(typentry->eq_opr);
700  if (eq_opr_func != InvalidOid)
701  fmgr_info_cxt(eq_opr_func, &typentry->eq_opr_finfo,
703  }
704  if ((flags & TYPECACHE_CMP_PROC_FINFO) &&
705  typentry->cmp_proc_finfo.fn_oid == InvalidOid &&
706  typentry->cmp_proc != InvalidOid)
707  {
708  fmgr_info_cxt(typentry->cmp_proc, &typentry->cmp_proc_finfo,
710  }
711  if ((flags & TYPECACHE_HASH_PROC_FINFO) &&
712  typentry->hash_proc_finfo.fn_oid == InvalidOid &&
713  typentry->hash_proc != InvalidOid)
714  {
715  fmgr_info_cxt(typentry->hash_proc, &typentry->hash_proc_finfo,
717  }
718  if ((flags & TYPECACHE_HASH_EXTENDED_PROC_FINFO) &&
720  typentry->hash_extended_proc != InvalidOid)
721  {
723  &typentry->hash_extended_proc_finfo,
725  }
726 
727  /*
728  * If it's a composite type (row type), get tupdesc if requested
729  */
730  if ((flags & TYPECACHE_TUPDESC) &&
731  typentry->tupDesc == NULL &&
732  typentry->typtype == TYPTYPE_COMPOSITE)
733  {
734  load_typcache_tupdesc(typentry);
735  }
736 
737  /*
738  * If requested, get information about a range type
739  */
740  if ((flags & TYPECACHE_RANGE_INFO) &&
741  typentry->rngelemtype == NULL &&
742  typentry->typtype == TYPTYPE_RANGE)
743  {
744  load_rangetype_info(typentry);
745  }
746 
747  /*
748  * If requested, get information about a domain type
749  */
750  if ((flags & TYPECACHE_DOMAIN_INFO) &&
751  (typentry->flags & TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS) == 0 &&
752  typentry->typtype == TYPTYPE_DOMAIN)
753  {
754  load_domaintype_info(typentry);
755  }
756 
757  return typentry;
758 }
static bool array_element_has_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1295
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
static void load_typcache_tupdesc(TypeCacheEntry *typentry)
Definition: typcache.c:764
#define BTORDER_PROC
Definition: nbtree.h:229
#define TYPECACHE_RANGE_INFO
Definition: typcache.h:125
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:1390
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid hash_opintype
Definition: typcache.h:55
#define TCFLAGS_CHECKED_EQ_OPR
Definition: typcache.c:84
#define HASH_ELEM
Definition: hsearch.h:87
static TypeCacheEntry * firstDomainTypeEntry
Definition: typcache.c:79
#define TYPECACHE_HASH_EXTENDED_PROC_FINFO
Definition: typcache.h:128
#define TCFLAGS_CHECKED_HASH_EXTENDED_PROC
Definition: typcache.c:89
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:721
struct TypeCacheEntry TypeCacheEntry
#define HTEqualStrategyNumber
Definition: hash.h:336
#define TYPECACHE_EQ_OPR_FINFO
Definition: typcache.h:119
#define BTREE_AM_OID
Definition: pg_am.h:70
#define TYPECACHE_HASH_PROC_FINFO
Definition: typcache.h:121
Size entrysize
Definition: hsearch.h:73
#define TYPECACHE_EQ_OPR
Definition: typcache.h:114
int errcode(int sqlerrcode)
Definition: elog.c:575
#define HASHEXTENDED_PROC
Definition: hash.h:352
#define MemSet(start, val, len)
Definition: c.h:863
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
unsigned int Oid
Definition: postgres_ext.h:31
#define RECORD_EQ_OP
Definition: pg_operator.h:1720
int16 typlen
Definition: typcache.h:37
#define OidIsValid(objectId)
Definition: c.h:532
bool typbyval
Definition: typcache.h:38
#define HASH_AM_OID
Definition: pg_am.h:73
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
Definition: inval.c:1431
FmgrInfo cmp_proc_finfo
Definition: typcache.h:71
struct TypeCacheEntry * nextDomain
Definition: typcache.h:110
#define TCFLAGS_CHECKED_GT_OPR
Definition: typcache.c:86
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ARRAY_LT_OP
Definition: pg_operator.h:781
char typstorage
Definition: typcache.h:40
static void TypeCacheRelCallback(Datum arg, Oid relid)
Definition: typcache.c:1923
static bool array_element_has_compare(TypeCacheEntry *typentry)
Definition: typcache.c:1287
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:163
Oid hash_extended_proc
Definition: typcache.h:61
FmgrInfo hash_proc_finfo
Definition: typcache.h:72
#define RECORD_LT_OP
Definition: pg_operator.h:1725
#define TYPECACHE_GT_OPR
Definition: typcache.h:116
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:132
#define HASHSTANDARD_PROC
Definition: hash.h:351
#define ereport(elevel, rest)
Definition: elog.h:122
#define TYPECACHE_BTREE_OPFAMILY
Definition: typcache.h:123
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:88
#define RECORD_GT_OP
Definition: pg_operator.h:1728
#define TYPTYPE_RANGE
Definition: pg_type.h:725
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
static bool range_element_has_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1420
#define HASH_BLOBS
Definition: hsearch.h:88
FmgrInfo hash_extended_proc_finfo
Definition: typcache.h:73
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1389
#define TYPECACHE_HASH_EXTENDED_PROC
Definition: typcache.h:127
uintptr_t Datum
Definition: postgres.h:372
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Oid btree_opintype
Definition: typcache.h:53
Size keysize
Definition: hsearch.h:72
FmgrInfo eq_opr_finfo
Definition: typcache.h:70
#define InvalidOid
Definition: postgres_ext.h:36
static void load_rangetype_info(TypeCacheEntry *typentry)
Definition: typcache.c:792
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1094
Oid fn_oid
Definition: fmgr.h:59
#define TYPECACHE_CMP_PROC
Definition: typcache.h:117
char typtype
Definition: typcache.h:41
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:681
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition: lsyscache.c:744
#define ARRAY_GT_OP
Definition: pg_operator.h:784
void CreateCacheMemoryContext(void)
Definition: catcache.c:636
#define TCFLAGS_CHECKED_BTREE_OPCLASS
Definition: typcache.c:82
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:98
static bool record_fields_have_compare(TypeCacheEntry *typentry)
Definition: typcache.c:1349
#define ARRAY_EQ_OP
Definition: pg_operator.h:776
Oid get_opclass_family(Oid opclass)
Definition: lsyscache.c:1047
static bool array_element_has_equality(TypeCacheEntry *typentry)
Definition: typcache.c:1279
static void load_domaintype_info(TypeCacheEntry *typentry)
Definition: typcache.c:855
#define TCFLAGS_CHECKED_HASH_PROC
Definition: typcache.c:88
char typalign
Definition: typcache.h:39
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define TYPECACHE_LT_OPR
Definition: typcache.h:115
#define TCFLAGS_CHECKED_LT_OPR
Definition: typcache.c:85
#define NameStr(name)
Definition: c.h:493
#define TYPECACHE_CMP_PROC_FINFO
Definition: typcache.h:120
#define TCFLAGS_CHECKED_HASH_OPCLASS
Definition: typcache.c:83
static bool range_element_has_extended_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1428
#define TYPECACHE_HASH_OPFAMILY
Definition: typcache.h:124
#define TYPECACHE_DOMAIN_INFO
Definition: typcache.h:126
static bool record_fields_have_equality(TypeCacheEntry *typentry)
Definition: typcache.c:1341
#define TCFLAGS_CHECKED_CMP_PROC
Definition: typcache.c:87
#define BTLessStrategyNumber
Definition: stratnum.h:29
static bool array_element_has_extended_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1303
TupleDesc tupDesc
Definition: typcache.h:80
static void TypeCacheConstrCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: typcache.c:2004
static HTAB * TypeCacheHash
Definition: typcache.c:76
#define TYPECACHE_HASH_PROC
Definition: typcache.h:118
#define TYPECACHE_TUPDESC
Definition: typcache.h:122
#define BTEqualStrategyNumber
Definition: stratnum.h:31
static void TypeCacheOpcCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: typcache.c:1975
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1069
void SharedRecordTypmodRegistryAttach ( SharedRecordTypmodRegistry )

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

1841 {
1842  MemoryContext old_context;
1843  dshash_table *record_table;
1844  dshash_table *typmod_table;
1845 
1847 
1848  /* We can't already be attached to a shared registry. */
1849  Assert(CurrentSession != NULL);
1850  Assert(CurrentSession->segment != NULL);
1851  Assert(CurrentSession->area != NULL);
1855 
1856  /*
1857  * We can't already have typmods in our local cache, because they'd clash
1858  * with those imported by SharedRecordTypmodRegistryInit. This should be
1859  * a freshly started parallel worker. If we ever support worker
1860  * recycling, a worker would need to zap its local cache in between
1861  * servicing different queries, in order to be able to call this and
1862  * synchronize typmods with a new leader; but that's problematic because
1863  * we can't be very sure that record-typmod-related state hasn't escaped
1864  * to anywhere else in the process.
1865  */
1866  Assert(NextRecordTypmod == 0);
1867 
1868  old_context = MemoryContextSwitchTo(TopMemoryContext);
1869 
1870  /* Attach to the two hash tables. */
1871  record_table = dshash_attach(CurrentSession->area,
1873  registry->record_table_handle,
1874  CurrentSession->area);
1875  typmod_table = dshash_attach(CurrentSession->area,
1877  registry->typmod_table_handle,
1878  NULL);
1879 
1880  MemoryContextSwitchTo(old_context);
1881 
1882  /*
1883  * Set up detach hook to run at worker exit. Currently this is the same
1884  * as the leader's detach hook, but in future they might need to be
1885  * different.
1886  */
1889  PointerGetDatum(registry));
1890 
1891  /*
1892  * Set up the session state that will tell assign_record_type_typmod and
1893  * lookup_rowtype_tupdesc_internal about the shared registry.
1894  */
1896  CurrentSession->shared_record_table = record_table;
1897  CurrentSession->shared_typmod_table = typmod_table;
1898 }
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:562
Session * CurrentSession
Definition: session.c:48
static const dshash_parameters srtr_record_table_params
Definition: typcache.c:244
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:1037
dsa_area * area
Definition: session.h:28
#define IsParallelWorker()
Definition: parallel.h:52
MemoryContext TopMemoryContext
Definition: mcxt.c:43
static const dshash_parameters srtr_typmod_table_params
Definition: typcache.c:253
static void shared_record_typmod_registry_detach(dsm_segment *segment, Datum datum)
Definition: typcache.c:2453
static int32 NextRecordTypmod
Definition: typcache.c:265
struct SharedRecordTypmodRegistry * shared_typmod_registry
Definition: session.h:31
dshash_table * shared_typmod_table
Definition: session.h:33
#define Assert(condition)
Definition: c.h:681
dsm_segment * segment
Definition: session.h:27
size_t SharedRecordTypmodRegistryEstimate ( void  )

Definition at line 1719 of file typcache.c.

Referenced by GetSessionDsmHandle().

1720 {
1721  return sizeof(SharedRecordTypmodRegistry);
1722 }
struct SharedRecordTypmodRegistry SharedRecordTypmodRegistry
Definition: typcache.h:148
void SharedRecordTypmodRegistryInit ( SharedRecordTypmodRegistry ,
dsm_segment segment,
dsa_area area 
)

Definition at line 1741 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, tupleDesc::tdtypmod, TopMemoryContext, SharedTypmodTableEntry::typmod, SharedRecordTypmodRegistry::typmod_table_handle, and SharedRecordTableKey::u.

Referenced by GetSessionDsmHandle().

1744 {
1745  MemoryContext old_context;
1746  dshash_table *record_table;
1747  dshash_table *typmod_table;
1748  int32 typmod;
1749 
1751 
1752  /* We can't already be attached to a shared registry. */
1756 
1757  old_context = MemoryContextSwitchTo(TopMemoryContext);
1758 
1759  /* Create the hash table of tuple descriptors indexed by themselves. */
1760  record_table = dshash_create(area, &srtr_record_table_params, area);
1761 
1762  /* Create the hash table of tuple descriptors indexed by typmod. */
1763  typmod_table = dshash_create(area, &srtr_typmod_table_params, NULL);
1764 
1765  MemoryContextSwitchTo(old_context);
1766 
1767  /* Initialize the SharedRecordTypmodRegistry. */
1768  registry->record_table_handle = dshash_get_hash_table_handle(record_table);
1769  registry->typmod_table_handle = dshash_get_hash_table_handle(typmod_table);
1770  pg_atomic_init_u32(&registry->next_typmod, NextRecordTypmod);
1771 
1772  /*
1773  * Copy all entries from this backend's private registry into the shared
1774  * registry.
1775  */
1776  for (typmod = 0; typmod < NextRecordTypmod; ++typmod)
1777  {
1778  SharedTypmodTableEntry *typmod_table_entry;
1779  SharedRecordTableEntry *record_table_entry;
1780  SharedRecordTableKey record_table_key;
1781  dsa_pointer shared_dp;
1782  TupleDesc tupdesc;
1783  bool found;
1784 
1785  tupdesc = RecordCacheArray[typmod];
1786  if (tupdesc == NULL)
1787  continue;
1788 
1789  /* Copy the TupleDesc into shared memory. */
1790  shared_dp = share_tupledesc(area, tupdesc, typmod);
1791 
1792  /* Insert into the typmod table. */
1793  typmod_table_entry = dshash_find_or_insert(typmod_table,
1794  &tupdesc->tdtypmod,
1795  &found);
1796  if (found)
1797  elog(ERROR, "cannot create duplicate shared record typmod");
1798  typmod_table_entry->typmod = tupdesc->tdtypmod;
1799  typmod_table_entry->shared_tupdesc = shared_dp;
1800  dshash_release_lock(typmod_table, typmod_table_entry);
1801 
1802  /* Insert into the record table. */
1803  record_table_key.shared = false;
1804  record_table_key.u.local_tupdesc = tupdesc;
1805  record_table_entry = dshash_find_or_insert(record_table,
1806  &record_table_key,
1807  &found);
1808  if (!found)
1809  {
1810  record_table_entry->key.shared = true;
1811  record_table_entry->key.u.shared_tupdesc = shared_dp;
1812  }
1813  dshash_release_lock(record_table, record_table_entry);
1814  }
1815 
1816  /*
1817  * Set up the global state that will tell assign_record_type_typmod and
1818  * lookup_rowtype_tupdesc_internal about the shared registry.
1819  */
1820  CurrentSession->shared_record_table = record_table;
1821  CurrentSession->shared_typmod_table = typmod_table;
1823 
1824  /*
1825  * We install a detach hook in the leader, but only to handle cleanup on
1826  * failure during GetSessionDsmHandle(). Once GetSessionDsmHandle() pins
1827  * the memory, the leader process will use a shared registry until it
1828  * exits.
1829  */
1831 }
Session * CurrentSession
Definition: session.c:48
static const dshash_parameters srtr_record_table_params
Definition: typcache.c:244
dshash_table * shared_record_table
Definition: session.h:32
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
SharedRecordTableKey key
Definition: typcache.c:186
void on_dsm_detach(dsm_segment *seg, on_dsm_detach_callback function, Datum arg)
Definition: dsm.c:1037
void dshash_release_lock(dshash_table *hash_table, void *entry)
Definition: dshash.c:561
uint64 dsa_pointer
Definition: dsa.h:62
int32 tdtypmod
Definition: tupdesc.h:75
signed int int32
Definition: c.h:246
static TupleDesc * RecordCacheArray
Definition: typcache.c:263
dsa_pointer shared_tupdesc
Definition: typcache.c:196
#define ERROR
Definition: elog.h:43
dshash_table_handle dshash_get_hash_table_handle(dshash_table *hash_table)
Definition: dshash.c:362
dsa_pointer shared_tupdesc
Definition: typcache.c:175
#define IsParallelWorker()
Definition: parallel.h:52
MemoryContext TopMemoryContext
Definition: mcxt.c:43
static const dshash_parameters srtr_typmod_table_params
Definition: typcache.c:253
static void shared_record_typmod_registry_detach(dsm_segment *segment, Datum datum)
Definition: typcache.c:2453
static int32 NextRecordTypmod
Definition: typcache.c:265
struct SharedRecordTypmodRegistry * shared_typmod_registry
Definition: session.h:31
uintptr_t Datum
Definition: postgres.h:372
dshash_table * dshash_create(dsa_area *area, const dshash_parameters *params, void *arg)
Definition: dshash.c:196
dshash_table * shared_typmod_table
Definition: session.h:33
union SharedRecordTableKey::@36 u
#define Assert(condition)
Definition: c.h:681
static dsa_pointer share_tupledesc(dsa_area *area, TupleDesc tupdesc, uint32 typmod)
Definition: typcache.c:2320
void * dshash_find_or_insert(dshash_table *hash_table, const void *key, bool *found)
Definition: dshash.c:430
TupleDesc local_tupdesc
Definition: typcache.c:174
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:234
#define elog
Definition: elog.h:219
void UpdateDomainConstraintRef ( DomainConstraintRef ref)

Definition at line 1203 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, TypeCacheEntry::typtype, and TYPTYPE_DOMAIN.

Referenced by domain_check_input().

1204 {
1205  TypeCacheEntry *typentry = ref->tcache;
1206 
1207  /* Make sure typcache entry's data is up to date */
1208  if ((typentry->flags & TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS) == 0 &&
1209  typentry->typtype == TYPTYPE_DOMAIN)
1210  load_domaintype_info(typentry);
1211 
1212  /* Transfer to ref object if there's new info, adjusting refcounts */
1213  if (ref->dcc != typentry->domainData)
1214  {
1215  /* Paranoia --- be sure link is nulled before trying to release */
1216  DomainConstraintCache *dcc = ref->dcc;
1217 
1218  if (dcc)
1219  {
1220  /*
1221  * Note: we just leak the previous list of executable domain
1222  * constraints. Alternatively, we could keep those in a child
1223  * context of ref->refctx and free that context at this point.
1224  * However, in practice this code path will be taken so seldom
1225  * that the extra bookkeeping for a child context doesn't seem
1226  * worthwhile; we'll just allow a leak for the lifespan of refctx.
1227  */
1228  ref->constraints = NIL;
1229  ref->dcc = NULL;
1230  decr_dcc_refcount(dcc);
1231  }
1232  dcc = typentry->domainData;
1233  if (dcc)
1234  {
1235  ref->dcc = dcc;
1236  dcc->dccRefCount++;
1237  if (ref->need_exprstate)
1239  ref->refctx);
1240  else
1241  ref->constraints = dcc->constraints;
1242  }
1243  }
1244 }
#define NIL
Definition: pg_list.h:69
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
DomainConstraintCache * dcc
Definition: typcache.h:144
DomainConstraintCache * domainData
Definition: typcache.h:98
MemoryContext refctx
Definition: typcache.h:139
char typtype
Definition: typcache.h:41
static List * prep_domain_constraints(List *constraints, MemoryContext execctx)
Definition: typcache.c:1127
TypeCacheEntry * tcache
Definition: typcache.h:140
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:98
static void load_domaintype_info(TypeCacheEntry *typentry)
Definition: typcache.c:855
static void decr_dcc_refcount(DomainConstraintCache *dcc)
Definition: typcache.c:1095