PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 *)
 
void AtEOXact_TypeCache (void)
 
void AtEOSubXact_TypeCache (void)
 

Macro Definition Documentation

◆ INVALID_TUPLEDESC_IDENTIFIER

#define INVALID_TUPLEDESC_IDENTIFIER   ((uint64) 1)

Definition at line 157 of file typcache.h.

◆ TYPECACHE_BTREE_OPFAMILY

#define TYPECACHE_BTREE_OPFAMILY   0x00200

Definition at line 147 of file typcache.h.

◆ TYPECACHE_CMP_PROC

#define TYPECACHE_CMP_PROC   0x00008

Definition at line 141 of file typcache.h.

◆ TYPECACHE_CMP_PROC_FINFO

#define TYPECACHE_CMP_PROC_FINFO   0x00040

Definition at line 144 of file typcache.h.

◆ TYPECACHE_DOMAIN_BASE_INFO

#define TYPECACHE_DOMAIN_BASE_INFO   0x01000

Definition at line 150 of file typcache.h.

◆ TYPECACHE_DOMAIN_CONSTR_INFO

#define TYPECACHE_DOMAIN_CONSTR_INFO   0x02000

Definition at line 151 of file typcache.h.

◆ TYPECACHE_EQ_OPR

#define TYPECACHE_EQ_OPR   0x00001

Definition at line 138 of file typcache.h.

◆ TYPECACHE_EQ_OPR_FINFO

#define TYPECACHE_EQ_OPR_FINFO   0x00020

Definition at line 143 of file typcache.h.

◆ TYPECACHE_GT_OPR

#define TYPECACHE_GT_OPR   0x00004

Definition at line 140 of file typcache.h.

◆ TYPECACHE_HASH_EXTENDED_PROC

#define TYPECACHE_HASH_EXTENDED_PROC   0x04000

Definition at line 152 of file typcache.h.

◆ TYPECACHE_HASH_EXTENDED_PROC_FINFO

#define TYPECACHE_HASH_EXTENDED_PROC_FINFO   0x08000

Definition at line 153 of file typcache.h.

◆ TYPECACHE_HASH_OPFAMILY

#define TYPECACHE_HASH_OPFAMILY   0x00400

Definition at line 148 of file typcache.h.

◆ TYPECACHE_HASH_PROC

#define TYPECACHE_HASH_PROC   0x00010

Definition at line 142 of file typcache.h.

◆ TYPECACHE_HASH_PROC_FINFO

#define TYPECACHE_HASH_PROC_FINFO   0x00080

Definition at line 145 of file typcache.h.

◆ TYPECACHE_LT_OPR

#define TYPECACHE_LT_OPR   0x00002

Definition at line 139 of file typcache.h.

◆ TYPECACHE_MULTIRANGE_INFO

#define TYPECACHE_MULTIRANGE_INFO   0x10000

Definition at line 154 of file typcache.h.

◆ TYPECACHE_RANGE_INFO

#define TYPECACHE_RANGE_INFO   0x00800

Definition at line 149 of file typcache.h.

◆ TYPECACHE_TUPDESC

#define TYPECACHE_TUPDESC   0x00100

Definition at line 146 of file typcache.h.

Typedef Documentation

◆ DomainConstraintCache

Definition at line 26 of file typcache.h.

◆ DomainConstraintRef

◆ SharedRecordTypmodRegistry

Definition at line 177 of file typcache.h.

◆ TypeCacheEntry

Function Documentation

◆ assign_record_type_identifier()

uint64 assign_record_type_identifier ( Oid  type_id,
int32  typmod 
)

Definition at line 2134 of file typcache.c.

2135{
2136 if (type_id != RECORDOID)
2137 {
2138 /*
2139 * It's a named composite type, so use the regular typcache.
2140 */
2141 TypeCacheEntry *typentry;
2142
2143 typentry = lookup_type_cache(type_id, TYPECACHE_TUPDESC);
2144 if (typentry->tupDesc == NULL)
2145 ereport(ERROR,
2146 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2147 errmsg("type %s is not composite",
2148 format_type_be(type_id))));
2149 Assert(typentry->tupDesc_identifier != 0);
2150 return typentry->tupDesc_identifier;
2151 }
2152 else
2153 {
2154 /*
2155 * It's a transient record type, so look in our record-type table.
2156 */
2157 if (typmod >= 0 && typmod < RecordCacheArrayLen &&
2158 RecordCacheArray[typmod].tupdesc != NULL)
2159 {
2160 Assert(RecordCacheArray[typmod].id != 0);
2161 return RecordCacheArray[typmod].id;
2162 }
2163
2164 /* For anonymous or unrecognized record type, generate a new ID */
2165 return ++tupledesc_id_counter;
2166 }
2167}
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
Assert(PointerIsAligned(start, uint64))
uint64 tupDesc_identifier
Definition: typcache.h:91
TupleDesc tupDesc
Definition: typcache.h:90
static RecordCacheArrayEntry * RecordCacheArray
Definition: typcache.c:304
static int32 RecordCacheArrayLen
Definition: typcache.c:305
static uint64 tupledesc_id_counter
Definition: typcache.c:313
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:386
#define TYPECACHE_TUPDESC
Definition: typcache.h:146

References Assert(), ereport, errcode(), errmsg(), ERROR, format_type_be(), RecordCacheArrayEntry::id, lookup_type_cache(), RecordCacheArray, RecordCacheArrayLen, 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().

◆ assign_record_type_typmod()

void assign_record_type_typmod ( TupleDesc  tupDesc)

Definition at line 2042 of file typcache.c.

2043{
2044 RecordCacheEntry *recentry;
2045 TupleDesc entDesc;
2046 bool found;
2047 MemoryContext oldcxt;
2048
2049 Assert(tupDesc->tdtypeid == RECORDOID);
2050
2051 if (RecordCacheHash == NULL)
2052 {
2053 /* First time through: initialize the hash table */
2054 HASHCTL ctl;
2055
2056 ctl.keysize = sizeof(TupleDesc); /* just the pointer */
2057 ctl.entrysize = sizeof(RecordCacheEntry);
2060 RecordCacheHash = hash_create("Record information cache", 64,
2061 &ctl,
2063
2064 /* Also make sure CacheMemoryContext exists */
2065 if (!CacheMemoryContext)
2067 }
2068
2069 /*
2070 * Find a hashtable entry for this tuple descriptor. We don't use
2071 * HASH_ENTER yet, because if it's missing, we need to make sure that all
2072 * the allocations succeed before we create the new entry.
2073 */
2075 &tupDesc,
2076 HASH_FIND, &found);
2077 if (found && recentry->tupdesc != NULL)
2078 {
2079 tupDesc->tdtypmod = recentry->tupdesc->tdtypmod;
2080 return;
2081 }
2082
2083 /* Not present, so need to manufacture an entry */
2085
2086 /* Look in the SharedRecordTypmodRegistry, if attached */
2087 entDesc = find_or_make_matching_shared_tupledesc(tupDesc);
2088 if (entDesc == NULL)
2089 {
2090 /*
2091 * Make sure we have room before we CreateTupleDescCopy() or advance
2092 * NextRecordTypmod.
2093 */
2095
2096 /* Reference-counted local cache only. */
2097 entDesc = CreateTupleDescCopy(tupDesc);
2098 entDesc->tdrefcount = 1;
2099 entDesc->tdtypmod = NextRecordTypmod++;
2100 }
2101 else
2102 {
2104 }
2105
2106 RecordCacheArray[entDesc->tdtypmod].tupdesc = entDesc;
2107
2108 /* Assign a unique tupdesc identifier, too. */
2110
2111 /* Fully initialized; create the hash table entry */
2113 &tupDesc,
2114 HASH_ENTER, NULL);
2115 recentry->tupdesc = entDesc;
2116
2117 /* Update the caller's tuple descriptor. */
2118 tupDesc->tdtypmod = entDesc->tdtypmod;
2119
2120 MemoryContextSwitchTo(oldcxt);
2121}
void CreateCacheMemoryContext(void)
Definition: catcache.c:708
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
@ HASH_FIND
Definition: hsearch.h:113
@ HASH_ENTER
Definition: hsearch.h:114
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_COMPARE
Definition: hsearch.h:99
#define HASH_FUNCTION
Definition: hsearch.h:98
MemoryContext CacheMemoryContext
Definition: mcxt.c:152
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
tree ctl
Definition: radixtree.h:1838
TupleDesc tupdesc
Definition: typcache.c:174
int tdrefcount
Definition: tupdesc.h:140
int32 tdtypmod
Definition: tupdesc.h:139
Oid tdtypeid
Definition: tupdesc.h:138
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:245
struct TupleDescData * TupleDesc
Definition: tupdesc.h:145
static TupleDesc find_or_make_matching_shared_tupledesc(TupleDesc tupdesc)
Definition: typcache.c:2931
static int32 NextRecordTypmod
Definition: typcache.c:306
static HTAB * RecordCacheHash
Definition: typcache.c:295
struct RecordCacheEntry RecordCacheEntry
static int record_type_typmod_compare(const void *a, const void *b, size_t size)
Definition: typcache.c:2026
static void ensure_record_cache_typmod_slot_exists(int32 typmod)
Definition: typcache.c:1799
static uint32 record_type_typmod_hash(const void *data, size_t size)
Definition: typcache.c:2015

References Assert(), CacheMemoryContext, CreateCacheMemoryContext(), CreateTupleDescCopy(), ctl, ensure_record_cache_typmod_slot_exists(), find_or_make_matching_shared_tupledesc(), HASH_COMPARE, hash_create(), HASH_ELEM, HASH_ENTER, HASH_FIND, HASH_FUNCTION, hash_search(), RecordCacheArrayEntry::id, MemoryContextSwitchTo(), NextRecordTypmod, record_type_typmod_compare(), record_type_typmod_hash(), RecordCacheArray, RecordCacheHash, TupleDescData::tdrefcount, TupleDescData::tdtypeid, TupleDescData::tdtypmod, RecordCacheEntry::tupdesc, RecordCacheArrayEntry::tupdesc, and tupledesc_id_counter.

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

◆ AtEOSubXact_TypeCache()

void AtEOSubXact_TypeCache ( void  )

Definition at line 3186 of file typcache.c.

3187{
3189}
static void finalize_in_progress_typentries(void)
Definition: typcache.c:3161

References finalize_in_progress_typentries().

Referenced by AbortSubTransaction(), and CommitSubTransaction().

◆ AtEOXact_TypeCache()

void AtEOXact_TypeCache ( void  )

◆ compare_values_of_enum()

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

Definition at line 2652 of file typcache.c.

2653{
2654 TypeCacheEnumData *enumdata;
2655 EnumItem *item1;
2656 EnumItem *item2;
2657
2658 /*
2659 * Equal OIDs are certainly equal --- this case was probably handled by
2660 * our caller, but we may as well check.
2661 */
2662 if (arg1 == arg2)
2663 return 0;
2664
2665 /* Load up the cache if first time through */
2666 if (tcache->enumData == NULL)
2667 load_enum_cache_data(tcache);
2668 enumdata = tcache->enumData;
2669
2670 /*
2671 * If both OIDs are known-sorted, we can just compare them directly.
2672 */
2673 if (enum_known_sorted(enumdata, arg1) &&
2674 enum_known_sorted(enumdata, arg2))
2675 {
2676 if (arg1 < arg2)
2677 return -1;
2678 else
2679 return 1;
2680 }
2681
2682 /*
2683 * Slow path: we have to identify their actual sort-order positions.
2684 */
2685 item1 = find_enumitem(enumdata, arg1);
2686 item2 = find_enumitem(enumdata, arg2);
2687
2688 if (item1 == NULL || item2 == NULL)
2689 {
2690 /*
2691 * We couldn't find one or both values. That means the enum has
2692 * changed under us, so re-initialize the cache and try again. We
2693 * don't bother retrying the known-sorted case in this path.
2694 */
2695 load_enum_cache_data(tcache);
2696 enumdata = tcache->enumData;
2697
2698 item1 = find_enumitem(enumdata, arg1);
2699 item2 = find_enumitem(enumdata, arg2);
2700
2701 /*
2702 * If we still can't find the values, complain: we must have corrupt
2703 * data.
2704 */
2705 if (item1 == NULL)
2706 elog(ERROR, "enum value %u not found in cache for enum %s",
2707 arg1, format_type_be(tcache->type_id));
2708 if (item2 == NULL)
2709 elog(ERROR, "enum value %u not found in cache for enum %s",
2710 arg2, format_type_be(tcache->type_id));
2711 }
2712
2713 if (item1->sort_order < item2->sort_order)
2714 return -1;
2715 else if (item1->sort_order > item2->sort_order)
2716 return 1;
2717 else
2718 return 0;
2719}
#define elog(elevel,...)
Definition: elog.h:226
float4 sort_order
Definition: typcache.c:150
struct TypeCacheEnumData * enumData
Definition: typcache.h:131
static void load_enum_cache_data(TypeCacheEntry *tcache)
Definition: typcache.c:2725
static EnumItem * find_enumitem(TypeCacheEnumData *enumdata, Oid arg)
Definition: typcache.c:2880
static bool enum_known_sorted(TypeCacheEnumData *enumdata, Oid arg)
Definition: typcache.c:2623

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().

◆ DomainHasConstraints()

bool DomainHasConstraints ( Oid  type_id)

Definition at line 1489 of file typcache.c.

1490{
1491 TypeCacheEntry *typentry;
1492
1493 /*
1494 * Note: a side effect is to cause the typcache's domain data to become
1495 * valid. This is fine since we'll likely need it soon if there is any.
1496 */
1498
1499 return (typentry->domainData != NULL);
1500}
DomainConstraintCache * domainData
Definition: typcache.h:122
#define TYPECACHE_DOMAIN_CONSTR_INFO
Definition: typcache.h:151

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

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

◆ InitDomainConstraintRef()

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

Definition at line 1402 of file typcache.c.

1404{
1405 /* Look up the typcache entry --- we assume it survives indefinitely */
1407 ref->need_exprstate = need_exprstate;
1408 /* For safety, establish the callback before acquiring a refcount */
1409 ref->refctx = refctx;
1410 ref->dcc = NULL;
1412 ref->callback.arg = ref;
1414 /* Acquire refcount if there are constraints, and set up exported list */
1415 if (ref->tcache->domainData)
1416 {
1417 ref->dcc = ref->tcache->domainData;
1418 ref->dcc->dccRefCount++;
1419 if (ref->need_exprstate)
1421 ref->refctx);
1422 else
1423 ref->constraints = ref->dcc->constraints;
1424 }
1425 else
1426 ref->constraints = NIL;
1427}
void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)
Definition: mcxt.c:568
#define NIL
Definition: pg_list.h:68
DomainConstraintCache * dcc
Definition: typcache.h:173
MemoryContext refctx
Definition: typcache.h:168
MemoryContextCallback callback
Definition: typcache.h:174
TypeCacheEntry * tcache
Definition: typcache.h:169
MemoryContextCallbackFunction func
Definition: palloc.h:49
static List * prep_domain_constraints(List *constraints, MemoryContext execctx)
Definition: typcache.c:1364
static void dccref_deletion_callback(void *arg)
Definition: typcache.c:1343

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().

◆ lookup_rowtype_tupdesc()

◆ lookup_rowtype_tupdesc_copy()

TupleDesc lookup_rowtype_tupdesc_copy ( Oid  type_id,
int32  typmod 
)

Definition at line 1956 of file typcache.c.

1957{
1958 TupleDesc tmp;
1959
1960 tmp = lookup_rowtype_tupdesc_internal(type_id, typmod, false);
1961 return CreateTupleDescCopyConstr(tmp);
1962}
TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc)
Definition: tupdesc.c:333

References CreateTupleDescCopyConstr(), and lookup_rowtype_tupdesc_internal().

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

◆ lookup_rowtype_tupdesc_domain()

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

Definition at line 1978 of file typcache.c.

1979{
1980 TupleDesc tupDesc;
1981
1982 if (type_id != RECORDOID)
1983 {
1984 /*
1985 * Check for domain or named composite type. We might as well load
1986 * whichever data is needed.
1987 */
1988 TypeCacheEntry *typentry;
1989
1990 typentry = lookup_type_cache(type_id,
1993 if (typentry->typtype == TYPTYPE_DOMAIN)
1995 typentry->domainBaseTypmod,
1996 noError);
1997 if (typentry->tupDesc == NULL && !noError)
1998 ereport(ERROR,
1999 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2000 errmsg("type %s is not composite",
2001 format_type_be(type_id))));
2002 tupDesc = typentry->tupDesc;
2003 }
2004 else
2005 tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, noError);
2006 if (tupDesc != NULL)
2007 PinTupleDesc(tupDesc);
2008 return tupDesc;
2009}
int32 domainBaseTypmod
Definition: typcache.h:116
char typtype
Definition: typcache.h:43
Oid domainBaseType
Definition: typcache.h:115
TupleDesc lookup_rowtype_tupdesc_noerror(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1939
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:150

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().

◆ lookup_rowtype_tupdesc_noerror()

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

Definition at line 1939 of file typcache.c.

1940{
1941 TupleDesc tupDesc;
1942
1943 tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, noError);
1944 if (tupDesc != NULL)
1945 PinTupleDesc(tupDesc);
1946 return tupDesc;
1947}

References lookup_rowtype_tupdesc_internal(), and PinTupleDesc.

Referenced by lookup_rowtype_tupdesc_domain().

◆ lookup_type_cache()

TypeCacheEntry * lookup_type_cache ( Oid  type_id,
int  flags 
)

Definition at line 386 of file typcache.c.

387{
388 TypeCacheEntry *typentry;
389 bool found;
390 int in_progress_offset;
391
392 if (TypeCacheHash == NULL)
393 {
394 /* First time through: initialize the hash table */
395 HASHCTL ctl;
396 int allocsize;
397
398 ctl.keysize = sizeof(Oid);
399 ctl.entrysize = sizeof(TypeCacheEntry);
400
401 /*
402 * TypeCacheEntry takes hash value from the system cache. For
403 * TypeCacheHash we use the same hash in order to speedup search by
404 * hash value. This is used by hash_seq_init_with_hash_value().
405 */
406 ctl.hash = type_cache_syshash;
407
408 TypeCacheHash = hash_create("Type information cache", 64,
410
412
413 ctl.keysize = sizeof(Oid);
414 ctl.entrysize = sizeof(RelIdToTypeIdCacheEntry);
415 RelIdToTypeIdCacheHash = hash_create("Map from relid to OID of cached composite type", 64,
417
418 /* Also set up callbacks for SI invalidations */
423
424 /* Also make sure CacheMemoryContext exists */
427
428 /*
429 * reserve enough in_progress_list slots for many cases
430 */
431 allocsize = 4;
434 allocsize * sizeof(*in_progress_list));
435 in_progress_list_maxlen = allocsize;
436 }
437
438 Assert(TypeCacheHash != NULL && RelIdToTypeIdCacheHash != NULL);
439
440 /* Register to catch invalidation messages */
442 {
443 int allocsize;
444
445 allocsize = in_progress_list_maxlen * 2;
447 allocsize * sizeof(*in_progress_list));
448 in_progress_list_maxlen = allocsize;
449 }
450 in_progress_offset = in_progress_list_len++;
451 in_progress_list[in_progress_offset] = type_id;
452
453 /* Try to look up an existing entry */
455 &type_id,
456 HASH_FIND, NULL);
457 if (typentry == NULL)
458 {
459 /*
460 * If we didn't find one, we want to make one. But first look up the
461 * pg_type row, just to make sure we don't make a cache entry for an
462 * invalid type OID. If the type OID is not valid, present a
463 * user-facing error, since some code paths such as domain_in() allow
464 * this function to be reached with a user-supplied OID.
465 */
466 HeapTuple tp;
467 Form_pg_type typtup;
468
469 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_id));
470 if (!HeapTupleIsValid(tp))
472 (errcode(ERRCODE_UNDEFINED_OBJECT),
473 errmsg("type with OID %u does not exist", type_id)));
474 typtup = (Form_pg_type) GETSTRUCT(tp);
475 if (!typtup->typisdefined)
477 (errcode(ERRCODE_UNDEFINED_OBJECT),
478 errmsg("type \"%s\" is only a shell",
479 NameStr(typtup->typname))));
480
481 /* Now make the typcache entry */
483 &type_id,
484 HASH_ENTER, &found);
485 Assert(!found); /* it wasn't there a moment ago */
486
487 MemSet(typentry, 0, sizeof(TypeCacheEntry));
488
489 /* These fields can never change, by definition */
490 typentry->type_id = type_id;
491 typentry->type_id_hash = get_hash_value(TypeCacheHash, &type_id);
492
493 /* Keep this part in sync with the code below */
494 typentry->typlen = typtup->typlen;
495 typentry->typbyval = typtup->typbyval;
496 typentry->typalign = typtup->typalign;
497 typentry->typstorage = typtup->typstorage;
498 typentry->typtype = typtup->typtype;
499 typentry->typrelid = typtup->typrelid;
500 typentry->typsubscript = typtup->typsubscript;
501 typentry->typelem = typtup->typelem;
502 typentry->typarray = typtup->typarray;
503 typentry->typcollation = typtup->typcollation;
504 typentry->flags |= TCFLAGS_HAVE_PG_TYPE_DATA;
505
506 /* If it's a domain, immediately thread it into the domain cache list */
507 if (typentry->typtype == TYPTYPE_DOMAIN)
508 {
510 firstDomainTypeEntry = typentry;
511 }
512
513 ReleaseSysCache(tp);
514 }
515 else if (!(typentry->flags & TCFLAGS_HAVE_PG_TYPE_DATA))
516 {
517 /*
518 * We have an entry, but its pg_type row got changed, so reload the
519 * data obtained directly from pg_type.
520 */
521 HeapTuple tp;
522 Form_pg_type typtup;
523
524 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_id));
525 if (!HeapTupleIsValid(tp))
527 (errcode(ERRCODE_UNDEFINED_OBJECT),
528 errmsg("type with OID %u does not exist", type_id)));
529 typtup = (Form_pg_type) GETSTRUCT(tp);
530 if (!typtup->typisdefined)
532 (errcode(ERRCODE_UNDEFINED_OBJECT),
533 errmsg("type \"%s\" is only a shell",
534 NameStr(typtup->typname))));
535
536 /*
537 * Keep this part in sync with the code above. Many of these fields
538 * shouldn't ever change, particularly typtype, but copy 'em anyway.
539 */
540 typentry->typlen = typtup->typlen;
541 typentry->typbyval = typtup->typbyval;
542 typentry->typalign = typtup->typalign;
543 typentry->typstorage = typtup->typstorage;
544 typentry->typtype = typtup->typtype;
545 typentry->typrelid = typtup->typrelid;
546 typentry->typsubscript = typtup->typsubscript;
547 typentry->typelem = typtup->typelem;
548 typentry->typarray = typtup->typarray;
549 typentry->typcollation = typtup->typcollation;
550 typentry->flags |= TCFLAGS_HAVE_PG_TYPE_DATA;
551
552 ReleaseSysCache(tp);
553 }
554
555 /*
556 * Look up opclasses if we haven't already and any dependent info is
557 * requested.
558 */
564 {
565 Oid opclass;
566
567 opclass = GetDefaultOpClass(type_id, BTREE_AM_OID);
568 if (OidIsValid(opclass))
569 {
570 typentry->btree_opf = get_opclass_family(opclass);
571 typentry->btree_opintype = get_opclass_input_type(opclass);
572 }
573 else
574 {
575 typentry->btree_opf = typentry->btree_opintype = InvalidOid;
576 }
577
578 /*
579 * Reset information derived from btree opclass. Note in particular
580 * that we'll redetermine the eq_opr even if we previously found one;
581 * this matters in case a btree opclass has been added to a type that
582 * previously had only a hash opclass.
583 */
584 typentry->flags &= ~(TCFLAGS_CHECKED_EQ_OPR |
589 }
590
591 /*
592 * If we need to look up equality operator, and there's no btree opclass,
593 * force lookup of hash opclass.
594 */
595 if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO)) &&
596 !(typentry->flags & TCFLAGS_CHECKED_EQ_OPR) &&
597 typentry->btree_opf == InvalidOid)
599
604 !(typentry->flags & TCFLAGS_CHECKED_HASH_OPCLASS))
605 {
606 Oid opclass;
607
608 opclass = GetDefaultOpClass(type_id, HASH_AM_OID);
609 if (OidIsValid(opclass))
610 {
611 typentry->hash_opf = get_opclass_family(opclass);
612 typentry->hash_opintype = get_opclass_input_type(opclass);
613 }
614 else
615 {
616 typentry->hash_opf = typentry->hash_opintype = InvalidOid;
617 }
618
619 /*
620 * Reset information derived from hash opclass. We do *not* reset the
621 * eq_opr; if we already found one from the btree opclass, that
622 * decision is still good.
623 */
624 typentry->flags &= ~(TCFLAGS_CHECKED_HASH_PROC |
627 }
628
629 /*
630 * Look for requested operators and functions, if we haven't already.
631 */
632 if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO)) &&
633 !(typentry->flags & TCFLAGS_CHECKED_EQ_OPR))
634 {
635 Oid eq_opr = InvalidOid;
636
637 if (typentry->btree_opf != InvalidOid)
638 eq_opr = get_opfamily_member(typentry->btree_opf,
639 typentry->btree_opintype,
640 typentry->btree_opintype,
642 if (eq_opr == InvalidOid &&
643 typentry->hash_opf != InvalidOid)
644 eq_opr = get_opfamily_member(typentry->hash_opf,
645 typentry->hash_opintype,
646 typentry->hash_opintype,
648
649 /*
650 * If the proposed equality operator is array_eq or record_eq, check
651 * to see if the element type or column types support equality. If
652 * not, array_eq or record_eq would fail at runtime, so we don't want
653 * to report that the type has equality. (We can omit similar
654 * checking for ranges and multiranges because ranges can't be created
655 * in the first place unless their subtypes support equality.)
656 */
657 if (eq_opr == ARRAY_EQ_OP &&
659 eq_opr = InvalidOid;
660 else if (eq_opr == RECORD_EQ_OP &&
662 eq_opr = InvalidOid;
663
664 /* Force update of eq_opr_finfo only if we're changing state */
665 if (typentry->eq_opr != eq_opr)
666 typentry->eq_opr_finfo.fn_oid = InvalidOid;
667
668 typentry->eq_opr = eq_opr;
669
670 /*
671 * Reset info about hash functions whenever we pick up new info about
672 * equality operator. This is so we can ensure that the hash
673 * functions match the operator.
674 */
675 typentry->flags &= ~(TCFLAGS_CHECKED_HASH_PROC |
677 typentry->flags |= TCFLAGS_CHECKED_EQ_OPR;
678 }
679 if ((flags & TYPECACHE_LT_OPR) &&
680 !(typentry->flags & TCFLAGS_CHECKED_LT_OPR))
681 {
682 Oid lt_opr = InvalidOid;
683
684 if (typentry->btree_opf != InvalidOid)
685 lt_opr = get_opfamily_member(typentry->btree_opf,
686 typentry->btree_opintype,
687 typentry->btree_opintype,
689
690 /*
691 * As above, make sure array_cmp or record_cmp will succeed; but again
692 * we need no special check for ranges or multiranges.
693 */
694 if (lt_opr == ARRAY_LT_OP &&
695 !array_element_has_compare(typentry))
696 lt_opr = InvalidOid;
697 else if (lt_opr == RECORD_LT_OP &&
699 lt_opr = InvalidOid;
700
701 typentry->lt_opr = lt_opr;
702 typentry->flags |= TCFLAGS_CHECKED_LT_OPR;
703 }
704 if ((flags & TYPECACHE_GT_OPR) &&
705 !(typentry->flags & TCFLAGS_CHECKED_GT_OPR))
706 {
707 Oid gt_opr = InvalidOid;
708
709 if (typentry->btree_opf != InvalidOid)
710 gt_opr = get_opfamily_member(typentry->btree_opf,
711 typentry->btree_opintype,
712 typentry->btree_opintype,
714
715 /*
716 * As above, make sure array_cmp or record_cmp will succeed; but again
717 * we need no special check for ranges or multiranges.
718 */
719 if (gt_opr == ARRAY_GT_OP &&
720 !array_element_has_compare(typentry))
721 gt_opr = InvalidOid;
722 else if (gt_opr == RECORD_GT_OP &&
724 gt_opr = InvalidOid;
725
726 typentry->gt_opr = gt_opr;
727 typentry->flags |= TCFLAGS_CHECKED_GT_OPR;
728 }
730 !(typentry->flags & TCFLAGS_CHECKED_CMP_PROC))
731 {
732 Oid cmp_proc = InvalidOid;
733
734 if (typentry->btree_opf != InvalidOid)
735 cmp_proc = get_opfamily_proc(typentry->btree_opf,
736 typentry->btree_opintype,
737 typentry->btree_opintype,
739
740 /*
741 * As above, make sure array_cmp or record_cmp will succeed; but again
742 * we need no special check for ranges or multiranges.
743 */
744 if (cmp_proc == F_BTARRAYCMP &&
745 !array_element_has_compare(typentry))
746 cmp_proc = InvalidOid;
747 else if (cmp_proc == F_BTRECORDCMP &&
749 cmp_proc = InvalidOid;
750
751 /* Force update of cmp_proc_finfo only if we're changing state */
752 if (typentry->cmp_proc != cmp_proc)
753 typentry->cmp_proc_finfo.fn_oid = InvalidOid;
754
755 typentry->cmp_proc = cmp_proc;
756 typentry->flags |= TCFLAGS_CHECKED_CMP_PROC;
757 }
759 !(typentry->flags & TCFLAGS_CHECKED_HASH_PROC))
760 {
761 Oid hash_proc = InvalidOid;
762
763 /*
764 * We insist that the eq_opr, if one has been determined, match the
765 * hash opclass; else report there is no hash function.
766 */
767 if (typentry->hash_opf != InvalidOid &&
768 (!OidIsValid(typentry->eq_opr) ||
769 typentry->eq_opr == get_opfamily_member(typentry->hash_opf,
770 typentry->hash_opintype,
771 typentry->hash_opintype,
773 hash_proc = get_opfamily_proc(typentry->hash_opf,
774 typentry->hash_opintype,
775 typentry->hash_opintype,
777
778 /*
779 * As above, make sure hash_array, hash_record, or hash_range will
780 * succeed.
781 */
782 if (hash_proc == F_HASH_ARRAY &&
783 !array_element_has_hashing(typentry))
784 hash_proc = InvalidOid;
785 else if (hash_proc == F_HASH_RECORD &&
787 hash_proc = InvalidOid;
788 else if (hash_proc == F_HASH_RANGE &&
789 !range_element_has_hashing(typentry))
790 hash_proc = InvalidOid;
791
792 /*
793 * Likewise for hash_multirange.
794 */
795 if (hash_proc == F_HASH_MULTIRANGE &&
797 hash_proc = InvalidOid;
798
799 /* Force update of hash_proc_finfo only if we're changing state */
800 if (typentry->hash_proc != hash_proc)
802
803 typentry->hash_proc = hash_proc;
804 typentry->flags |= TCFLAGS_CHECKED_HASH_PROC;
805 }
806 if ((flags & (TYPECACHE_HASH_EXTENDED_PROC |
809 {
810 Oid hash_extended_proc = InvalidOid;
811
812 /*
813 * We insist that the eq_opr, if one has been determined, match the
814 * hash opclass; else report there is no hash function.
815 */
816 if (typentry->hash_opf != InvalidOid &&
817 (!OidIsValid(typentry->eq_opr) ||
818 typentry->eq_opr == get_opfamily_member(typentry->hash_opf,
819 typentry->hash_opintype,
820 typentry->hash_opintype,
822 hash_extended_proc = get_opfamily_proc(typentry->hash_opf,
823 typentry->hash_opintype,
824 typentry->hash_opintype,
826
827 /*
828 * As above, make sure hash_array_extended, hash_record_extended, or
829 * hash_range_extended will succeed.
830 */
831 if (hash_extended_proc == F_HASH_ARRAY_EXTENDED &&
833 hash_extended_proc = InvalidOid;
834 else if (hash_extended_proc == F_HASH_RECORD_EXTENDED &&
836 hash_extended_proc = InvalidOid;
837 else if (hash_extended_proc == F_HASH_RANGE_EXTENDED &&
839 hash_extended_proc = InvalidOid;
840
841 /*
842 * Likewise for hash_multirange_extended.
843 */
844 if (hash_extended_proc == F_HASH_MULTIRANGE_EXTENDED &&
846 hash_extended_proc = InvalidOid;
847
848 /* Force update of proc finfo only if we're changing state */
849 if (typentry->hash_extended_proc != hash_extended_proc)
851
852 typentry->hash_extended_proc = hash_extended_proc;
854 }
855
856 /*
857 * Set up fmgr lookup info as requested
858 *
859 * Note: we tell fmgr the finfo structures live in CacheMemoryContext,
860 * which is not quite right (they're really in the hash table's private
861 * memory context) but this will do for our purposes.
862 *
863 * Note: the code above avoids invalidating the finfo structs unless the
864 * referenced operator/function OID actually changes. This is to prevent
865 * unnecessary leakage of any subsidiary data attached to an finfo, since
866 * that would cause session-lifespan memory leaks.
867 */
868 if ((flags & TYPECACHE_EQ_OPR_FINFO) &&
869 typentry->eq_opr_finfo.fn_oid == InvalidOid &&
870 typentry->eq_opr != InvalidOid)
871 {
872 Oid eq_opr_func;
873
874 eq_opr_func = get_opcode(typentry->eq_opr);
875 if (eq_opr_func != InvalidOid)
876 fmgr_info_cxt(eq_opr_func, &typentry->eq_opr_finfo,
878 }
879 if ((flags & TYPECACHE_CMP_PROC_FINFO) &&
880 typentry->cmp_proc_finfo.fn_oid == InvalidOid &&
881 typentry->cmp_proc != InvalidOid)
882 {
883 fmgr_info_cxt(typentry->cmp_proc, &typentry->cmp_proc_finfo,
885 }
886 if ((flags & TYPECACHE_HASH_PROC_FINFO) &&
887 typentry->hash_proc_finfo.fn_oid == InvalidOid &&
888 typentry->hash_proc != InvalidOid)
889 {
890 fmgr_info_cxt(typentry->hash_proc, &typentry->hash_proc_finfo,
892 }
895 typentry->hash_extended_proc != InvalidOid)
896 {
898 &typentry->hash_extended_proc_finfo,
900 }
901
902 /*
903 * If it's a composite type (row type), get tupdesc if requested
904 */
905 if ((flags & TYPECACHE_TUPDESC) &&
906 typentry->tupDesc == NULL &&
907 typentry->typtype == TYPTYPE_COMPOSITE)
908 {
909 load_typcache_tupdesc(typentry);
910 }
911
912 /*
913 * If requested, get information about a range type
914 *
915 * This includes making sure that the basic info about the range element
916 * type is up-to-date.
917 */
918 if ((flags & TYPECACHE_RANGE_INFO) &&
919 typentry->typtype == TYPTYPE_RANGE)
920 {
921 if (typentry->rngelemtype == NULL)
922 load_rangetype_info(typentry);
923 else if (!(typentry->rngelemtype->flags & TCFLAGS_HAVE_PG_TYPE_DATA))
924 (void) lookup_type_cache(typentry->rngelemtype->type_id, 0);
925 }
926
927 /*
928 * If requested, get information about a multirange type
929 */
930 if ((flags & TYPECACHE_MULTIRANGE_INFO) &&
931 typentry->rngtype == NULL &&
932 typentry->typtype == TYPTYPE_MULTIRANGE)
933 {
934 load_multirangetype_info(typentry);
935 }
936
937 /*
938 * If requested, get information about a domain type
939 */
940 if ((flags & TYPECACHE_DOMAIN_BASE_INFO) &&
941 typentry->domainBaseType == InvalidOid &&
942 typentry->typtype == TYPTYPE_DOMAIN)
943 {
944 typentry->domainBaseTypmod = -1;
945 typentry->domainBaseType =
946 getBaseTypeAndTypmod(type_id, &typentry->domainBaseTypmod);
947 }
948 if ((flags & TYPECACHE_DOMAIN_CONSTR_INFO) &&
949 (typentry->flags & TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS) == 0 &&
950 typentry->typtype == TYPTYPE_DOMAIN)
951 {
952 load_domaintype_info(typentry);
953 }
954
955 INJECTION_POINT("typecache-before-rel-type-cache-insert");
956
957 Assert(in_progress_offset + 1 == in_progress_list_len);
959
961
962 return typentry;
963}
#define NameStr(name)
Definition: c.h:717
#define MemSet(start, val, len)
Definition: c.h:991
#define OidIsValid(objectId)
Definition: c.h:746
uint32 get_hash_value(HTAB *hashp, const void *keyPtr)
Definition: dynahash.c:911
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:137
#define HASHSTANDARD_PROC
Definition: hash.h:355
#define HASHEXTENDED_PROC
Definition: hash.h:356
#define HASH_BLOBS
Definition: hsearch.h:97
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:2345
#define INJECTION_POINT(name)
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
Definition: inval.c:1844
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1802
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1304
Oid get_opclass_family(Oid opclass)
Definition: lsyscache.c:1282
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition: lsyscache.c:888
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1425
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:167
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition: lsyscache.c:2678
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1181
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1544
#define BTORDER_PROC
Definition: nbtree.h:717
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
uintptr_t Datum
Definition: postgres.h:69
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
#define InvalidOid
Definition: postgres_ext.h:35
unsigned int Oid
Definition: postgres_ext.h:30
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
#define HTEqualStrategyNumber
Definition: stratnum.h:41
#define BTLessStrategyNumber
Definition: stratnum.h:29
#define BTEqualStrategyNumber
Definition: stratnum.h:31
Oid fn_oid
Definition: fmgr.h:59
uint32 type_id_hash
Definition: typcache.h:36
FmgrInfo hash_proc_finfo
Definition: typcache.h:78
Oid hash_extended_proc
Definition: typcache.h:67
Oid typsubscript
Definition: typcache.h:45
FmgrInfo cmp_proc_finfo
Definition: typcache.h:77
char typalign
Definition: typcache.h:41
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:99
FmgrInfo hash_extended_proc_finfo
Definition: typcache.h:79
struct TypeCacheEntry * rngtype
Definition: typcache.h:109
FmgrInfo eq_opr_finfo
Definition: typcache.h:76
Oid btree_opintype
Definition: typcache.h:59
struct TypeCacheEntry * nextDomain
Definition: typcache.h:134
bool typbyval
Definition: typcache.h:40
int16 typlen
Definition: typcache.h:39
Oid hash_opintype
Definition: typcache.h:61
Oid typcollation
Definition: typcache.h:48
char typstorage
Definition: typcache.h:42
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221
#define TCFLAGS_CHECKED_BTREE_OPCLASS
Definition: typcache.c:100
#define TCFLAGS_CHECKED_HASH_OPCLASS
Definition: typcache.c:101
static bool range_element_has_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1715
static void insert_rel_type_cache_if_needed(TypeCacheEntry *typentry)
Definition: typcache.c:3063
static bool record_fields_have_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1594
static HTAB * RelIdToTypeIdCacheHash
Definition: typcache.c:87
static bool record_fields_have_extended_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1602
static int in_progress_list_maxlen
Definition: typcache.c:228
static Oid * in_progress_list
Definition: typcache.c:226
#define TCFLAGS_CHECKED_GT_OPR
Definition: typcache.c:104
static bool multirange_element_has_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1755
static bool record_fields_have_equality(TypeCacheEntry *typentry)
Definition: typcache.c:1578
#define TCFLAGS_CHECKED_LT_OPR
Definition: typcache.c:103
#define TCFLAGS_CHECKED_HASH_PROC
Definition: typcache.c:106
static bool array_element_has_extended_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1540
static bool array_element_has_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1532
static void load_multirangetype_info(TypeCacheEntry *typentry)
Definition: typcache.c:1061
static uint32 type_cache_syshash(const void *key, Size keysize)
Definition: typcache.c:359
#define TCFLAGS_CHECKED_CMP_PROC
Definition: typcache.c:105
static bool multirange_element_has_extended_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1763
static int in_progress_list_len
Definition: typcache.c:227
static bool array_element_has_equality(TypeCacheEntry *typentry)
Definition: typcache.c:1516
static void load_rangetype_info(TypeCacheEntry *typentry)
Definition: typcache.c:1003
static bool range_element_has_extended_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1723
static TypeCacheEntry * firstDomainTypeEntry
Definition: typcache.c:96
struct RelIdToTypeIdCacheEntry RelIdToTypeIdCacheEntry
#define TCFLAGS_CHECKED_HASH_EXTENDED_PROC
Definition: typcache.c:107
static void TypeCacheTypCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: typcache.c:2513
static void TypeCacheConstrCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: typcache.c:2599
static void TypeCacheOpcCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: typcache.c:2570
static void load_domaintype_info(TypeCacheEntry *typentry)
Definition: typcache.c:1083
static void TypeCacheRelCallback(Datum arg, Oid relid)
Definition: typcache.c:2417
static bool array_element_has_compare(TypeCacheEntry *typentry)
Definition: typcache.c:1524
#define TCFLAGS_HAVE_PG_TYPE_DATA
Definition: typcache.c:99
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:118
static HTAB * TypeCacheHash
Definition: typcache.c:79
static bool record_fields_have_compare(TypeCacheEntry *typentry)
Definition: typcache.c:1586
#define TCFLAGS_CHECKED_EQ_OPR
Definition: typcache.c:102
static void load_typcache_tupdesc(TypeCacheEntry *typentry)
Definition: typcache.c:969
#define TYPECACHE_HASH_PROC_FINFO
Definition: typcache.h:145
#define TYPECACHE_EQ_OPR
Definition: typcache.h:138
#define TYPECACHE_HASH_OPFAMILY
Definition: typcache.h:148
#define TYPECACHE_MULTIRANGE_INFO
Definition: typcache.h:154
#define TYPECACHE_EQ_OPR_FINFO
Definition: typcache.h:143
#define TYPECACHE_HASH_EXTENDED_PROC
Definition: typcache.h:152
#define TYPECACHE_BTREE_OPFAMILY
Definition: typcache.h:147
#define TYPECACHE_RANGE_INFO
Definition: typcache.h:149
#define TYPECACHE_GT_OPR
Definition: typcache.h:140
#define TYPECACHE_CMP_PROC
Definition: typcache.h:141
struct TypeCacheEntry TypeCacheEntry
#define TYPECACHE_LT_OPR
Definition: typcache.h:139
#define TYPECACHE_HASH_EXTENDED_PROC_FINFO
Definition: typcache.h:153
#define TYPECACHE_CMP_PROC_FINFO
Definition: typcache.h:144
#define TYPECACHE_HASH_PROC
Definition: typcache.h:142

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(), TypeCacheEntry::cmp_proc, TypeCacheEntry::cmp_proc_finfo, CreateCacheMemoryContext(), ctl, TypeCacheEntry::domainBaseType, TypeCacheEntry::domainBaseTypmod, TypeCacheEntry::eq_opr, TypeCacheEntry::eq_opr_finfo, ereport, errcode(), errmsg(), ERROR, firstDomainTypeEntry, TypeCacheEntry::flags, fmgr_info_cxt(), FmgrInfo::fn_oid, get_hash_value(), get_opclass_family(), get_opclass_input_type(), get_opcode(), get_opfamily_member(), get_opfamily_proc(), getBaseTypeAndTypmod(), GetDefaultOpClass(), GETSTRUCT(), TypeCacheEntry::gt_opr, HASH_BLOBS, hash_create(), HASH_ELEM, HASH_ENTER, TypeCacheEntry::hash_extended_proc, TypeCacheEntry::hash_extended_proc_finfo, HASH_FIND, HASH_FUNCTION, TypeCacheEntry::hash_opf, TypeCacheEntry::hash_opintype, TypeCacheEntry::hash_proc, TypeCacheEntry::hash_proc_finfo, hash_search(), HASHEXTENDED_PROC, HASHSTANDARD_PROC, HeapTupleIsValid, HTEqualStrategyNumber, in_progress_list, in_progress_list_len, in_progress_list_maxlen, INJECTION_POINT, insert_rel_type_cache_if_needed(), InvalidOid, load_domaintype_info(), load_multirangetype_info(), load_rangetype_info(), load_typcache_tupdesc(), lookup_type_cache(), TypeCacheEntry::lt_opr, MemoryContextAlloc(), 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(), RelIdToTypeIdCacheHash, repalloc(), 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::typarray, TypeCacheEntry::typbyval, TypeCacheEntry::typcollation, type_cache_syshash(), 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(), TypeCacheHash, TypeCacheOpcCallback(), TypeCacheRelCallback(), TypeCacheTypCallback(), TypeCacheEntry::typelem, TypeCacheEntry::typlen, TypeCacheEntry::typrelid, TypeCacheEntry::typstorage, TypeCacheEntry::typsubscript, and TypeCacheEntry::typtype.

Referenced by analyzeCTE(), appendOrderBySuffix(), array_cmp(), array_contain_compare(), array_eq(), array_position_common(), array_positions(), array_replace_internal(), array_reverse(), array_sample(), array_shuffle(), array_sort_internal(), array_typanalyze(), assign_record_type_identifier(), brin_bloom_opcinfo(), brin_inclusion_opcinfo(), brin_minmax_multi_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(), check_exclusion_or_unique_constraint(), check_memoizable(), contain_leaked_vars_walker(), CreateStatistics(), dependency_degree(), domain_state_setup(), DomainHasConstraints(), enum_cmp_internal(), ExecInitExprRec(), find_simplified_clause(), foreign_expr_walker(), get_attr_stat_type(), get_cached_rowtype(), get_elem_stat_type(), get_multirange_io_data(), get_range_io_data(), get_rule_orderby(), get_sort_group_operators(), GinBufferInit(), hash_array(), hash_array_extended(), hash_multirange(), hash_multirange_extended(), hash_range(), hash_range_extended(), hash_record(), hash_record_extended(), InitDomainConstraintRef(), initGinState(), IsIndexUsableForReplicaIdentityFull(), 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(), multirange_unnest(), ndistinct_for_combination(), op_hashjoinable(), op_mergejoinable(), paraminfo_get_equal_hashops(), PLy_input_setup_func(), PLy_output_setup_func(), range_fast_cmp(), range_get_typcache(), record_cmp(), record_eq(), revalidate_rectypeid(), scalararraysel(), scalararraysel_containment(), show_sortorder_options(), statext_mcv_serialize(), tuples_equal(), tuplesort_begin_index_gin(), and width_bucket_array().

◆ SharedRecordTypmodRegistryAttach()

void SharedRecordTypmodRegistryAttach ( SharedRecordTypmodRegistry registry)

Definition at line 2296 of file typcache.c.

2297{
2298 MemoryContext old_context;
2299 dshash_table *record_table;
2300 dshash_table *typmod_table;
2301
2303
2304 /* We can't already be attached to a shared registry. */
2305 Assert(CurrentSession != NULL);
2306 Assert(CurrentSession->segment != NULL);
2307 Assert(CurrentSession->area != NULL);
2311
2312 /*
2313 * We can't already have typmods in our local cache, because they'd clash
2314 * with those imported by SharedRecordTypmodRegistryInit. This should be
2315 * a freshly started parallel worker. If we ever support worker
2316 * recycling, a worker would need to zap its local cache in between
2317 * servicing different queries, in order to be able to call this and
2318 * synchronize typmods with a new leader; but that's problematic because
2319 * we can't be very sure that record-typmod-related state hasn't escaped
2320 * to anywhere else in the process.
2321 */
2323
2325
2326 /* Attach to the two hash tables. */
2327 record_table = dshash_attach(CurrentSession->area,
2329 registry->record_table_handle,
2331 typmod_table = dshash_attach(CurrentSession->area,
2333 registry->typmod_table_handle,
2334 NULL);
2335
2336 MemoryContextSwitchTo(old_context);
2337
2338 /*
2339 * Set up detach hook to run at worker exit. Currently this is the same
2340 * as the leader's detach hook, but in future they might need to be
2341 * different.
2342 */
2345 PointerGetDatum(registry));
2346
2347 /*
2348 * Set up the session state that will tell assign_record_type_typmod and
2349 * lookup_rowtype_tupdesc_internal about the shared registry.
2350 */
2352 CurrentSession->shared_record_table = record_table;
2353 CurrentSession->shared_typmod_table = typmod_table;
2354}
dshash_table * dshash_attach(dsa_area *area, const dshash_parameters *params, dshash_table_handle handle, void *arg)
Definition: dshash.c:270
void on_dsm_detach(dsm_segment *seg, on_dsm_detach_callback function, Datum arg)
Definition: dsm.c:1132
#define IsParallelWorker()
Definition: parallel.h:60
MemoryContext TopMemoryContext
Definition: mcxt.c:149
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
Session * CurrentSession
Definition: session.c:48
dsm_segment * segment
Definition: session.h:27
dshash_table * shared_record_table
Definition: session.h:32
struct SharedRecordTypmodRegistry * shared_typmod_registry
Definition: session.h:31
dsa_area * area
Definition: session.h:28
dshash_table * shared_typmod_table
Definition: session.h:33
dshash_table_handle typmod_table_handle
Definition: typcache.c:186
dshash_table_handle record_table_handle
Definition: typcache.c:184
static const dshash_parameters srtr_typmod_table_params
Definition: typcache.c:285
static void shared_record_typmod_registry_detach(dsm_segment *segment, Datum datum)
Definition: typcache.c:3043
static const dshash_parameters srtr_record_table_params
Definition: typcache.c:275

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, srtr_record_table_params, srtr_typmod_table_params, TopMemoryContext, and SharedRecordTypmodRegistry::typmod_table_handle.

Referenced by AttachSession().

◆ SharedRecordTypmodRegistryEstimate()

size_t SharedRecordTypmodRegistryEstimate ( void  )

Definition at line 2175 of file typcache.c.

2176{
2177 return sizeof(SharedRecordTypmodRegistry);
2178}
struct SharedRecordTypmodRegistry SharedRecordTypmodRegistry
Definition: typcache.h:177

Referenced by GetSessionDsmHandle().

◆ SharedRecordTypmodRegistryInit()

void SharedRecordTypmodRegistryInit ( SharedRecordTypmodRegistry registry,
dsm_segment segment,
dsa_area area 
)

Definition at line 2197 of file typcache.c.

2200{
2201 MemoryContext old_context;
2202 dshash_table *record_table;
2203 dshash_table *typmod_table;
2204 int32 typmod;
2205
2207
2208 /* We can't already be attached to a shared registry. */
2212
2214
2215 /* Create the hash table of tuple descriptors indexed by themselves. */
2216 record_table = dshash_create(area, &srtr_record_table_params, area);
2217
2218 /* Create the hash table of tuple descriptors indexed by typmod. */
2219 typmod_table = dshash_create(area, &srtr_typmod_table_params, NULL);
2220
2221 MemoryContextSwitchTo(old_context);
2222
2223 /* Initialize the SharedRecordTypmodRegistry. */
2224 registry->record_table_handle = dshash_get_hash_table_handle(record_table);
2225 registry->typmod_table_handle = dshash_get_hash_table_handle(typmod_table);
2227
2228 /*
2229 * Copy all entries from this backend's private registry into the shared
2230 * registry.
2231 */
2232 for (typmod = 0; typmod < NextRecordTypmod; ++typmod)
2233 {
2234 SharedTypmodTableEntry *typmod_table_entry;
2235 SharedRecordTableEntry *record_table_entry;
2236 SharedRecordTableKey record_table_key;
2237 dsa_pointer shared_dp;
2238 TupleDesc tupdesc;
2239 bool found;
2240
2241 tupdesc = RecordCacheArray[typmod].tupdesc;
2242 if (tupdesc == NULL)
2243 continue;
2244
2245 /* Copy the TupleDesc into shared memory. */
2246 shared_dp = share_tupledesc(area, tupdesc, typmod);
2247
2248 /* Insert into the typmod table. */
2249 typmod_table_entry = dshash_find_or_insert(typmod_table,
2250 &tupdesc->tdtypmod,
2251 &found);
2252 if (found)
2253 elog(ERROR, "cannot create duplicate shared record typmod");
2254 typmod_table_entry->typmod = tupdesc->tdtypmod;
2255 typmod_table_entry->shared_tupdesc = shared_dp;
2256 dshash_release_lock(typmod_table, typmod_table_entry);
2257
2258 /* Insert into the record table. */
2259 record_table_key.shared = false;
2260 record_table_key.u.local_tupdesc = tupdesc;
2261 record_table_entry = dshash_find_or_insert(record_table,
2262 &record_table_key,
2263 &found);
2264 if (!found)
2265 {
2266 record_table_entry->key.shared = true;
2267 record_table_entry->key.u.shared_tupdesc = shared_dp;
2268 }
2269 dshash_release_lock(record_table, record_table_entry);
2270 }
2271
2272 /*
2273 * Set up the global state that will tell assign_record_type_typmod and
2274 * lookup_rowtype_tupdesc_internal about the shared registry.
2275 */
2276 CurrentSession->shared_record_table = record_table;
2277 CurrentSession->shared_typmod_table = typmod_table;
2279
2280 /*
2281 * We install a detach hook in the leader, but only to handle cleanup on
2282 * failure during GetSessionDsmHandle(). Once GetSessionDsmHandle() pins
2283 * the memory, the leader process will use a shared registry until it
2284 * exits.
2285 */
2287}
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:221
int32_t int32
Definition: c.h:498
uint64 dsa_pointer
Definition: dsa.h:62
void dshash_release_lock(dshash_table *hash_table, void *entry)
Definition: dshash.c:558
dshash_table_handle dshash_get_hash_table_handle(dshash_table *hash_table)
Definition: dshash.c:367
void * dshash_find_or_insert(dshash_table *hash_table, const void *key, bool *found)
Definition: dshash.c:433
dshash_table * dshash_create(dsa_area *area, const dshash_parameters *params, void *arg)
Definition: dshash.c:206
SharedRecordTableKey key
Definition: typcache.c:213
TupleDesc local_tupdesc
Definition: typcache.c:201
dsa_pointer shared_tupdesc
Definition: typcache.c:202
union SharedRecordTableKey::@31 u
pg_atomic_uint32 next_typmod
Definition: typcache.c:188
dsa_pointer shared_tupdesc
Definition: typcache.c:223
static dsa_pointer share_tupledesc(dsa_area *area, TupleDesc tupdesc, uint32 typmod)
Definition: typcache.c:2910

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, RecordCacheArray, 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, srtr_record_table_params, srtr_typmod_table_params, TupleDescData::tdtypmod, TopMemoryContext, RecordCacheArrayEntry::tupdesc, SharedTypmodTableEntry::typmod, SharedRecordTypmodRegistry::typmod_table_handle, and SharedRecordTableKey::u.

Referenced by GetSessionDsmHandle().

◆ UpdateDomainConstraintRef()

void UpdateDomainConstraintRef ( DomainConstraintRef ref)

Definition at line 1440 of file typcache.c.

1441{
1442 TypeCacheEntry *typentry = ref->tcache;
1443
1444 /* Make sure typcache entry's data is up to date */
1445 if ((typentry->flags & TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS) == 0 &&
1446 typentry->typtype == TYPTYPE_DOMAIN)
1447 load_domaintype_info(typentry);
1448
1449 /* Transfer to ref object if there's new info, adjusting refcounts */
1450 if (ref->dcc != typentry->domainData)
1451 {
1452 /* Paranoia --- be sure link is nulled before trying to release */
1453 DomainConstraintCache *dcc = ref->dcc;
1454
1455 if (dcc)
1456 {
1457 /*
1458 * Note: we just leak the previous list of executable domain
1459 * constraints. Alternatively, we could keep those in a child
1460 * context of ref->refctx and free that context at this point.
1461 * However, in practice this code path will be taken so seldom
1462 * that the extra bookkeeping for a child context doesn't seem
1463 * worthwhile; we'll just allow a leak for the lifespan of refctx.
1464 */
1465 ref->constraints = NIL;
1466 ref->dcc = NULL;
1467 decr_dcc_refcount(dcc);
1468 }
1469 dcc = typentry->domainData;
1470 if (dcc)
1471 {
1472 ref->dcc = dcc;
1473 dcc->dccRefCount++;
1474 if (ref->need_exprstate)
1476 ref->refctx);
1477 else
1478 ref->constraints = dcc->constraints;
1479 }
1480 }
1481}
static void decr_dcc_refcount(DomainConstraintCache *dcc)
Definition: typcache.c:1332

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().