PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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, bool *has_volatile)
 
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

◆ TypeCacheEntry

Function Documentation

◆ assign_record_type_identifier()

uint64 assign_record_type_identifier ( Oid  type_id,
int32  typmod 
)
extern

Definition at line 2175 of file typcache.c.

2176{
2177 if (type_id != RECORDOID)
2178 {
2179 /*
2180 * It's a named composite type, so use the regular typcache.
2181 */
2182 TypeCacheEntry *typentry;
2183
2184 typentry = lookup_type_cache(type_id, TYPECACHE_TUPDESC);
2185 if (typentry->tupDesc == NULL)
2186 ereport(ERROR,
2188 errmsg("type %s is not composite",
2189 format_type_be(type_id))));
2190 Assert(typentry->tupDesc_identifier != 0);
2191 return typentry->tupDesc_identifier;
2192 }
2193 else
2194 {
2195 /*
2196 * It's a transient record type, so look in our record-type table.
2197 */
2198 if (typmod >= 0 && typmod < RecordCacheArrayLen &&
2199 RecordCacheArray[typmod].tupdesc != NULL)
2200 {
2201 Assert(RecordCacheArray[typmod].id != 0);
2202 return RecordCacheArray[typmod].id;
2203 }
2204
2205 /* For anonymous or unrecognized record type, generate a new ID */
2206 return ++tupledesc_id_counter;
2207 }
2208}
#define Assert(condition)
Definition c.h:1002
int errcode(int sqlerrcode)
Definition elog.c:875
#define ERROR
Definition elog.h:40
#define ereport(elevel,...)
Definition elog.h:152
char * format_type_be(Oid type_oid)
static char * errmsg
static int fb(int x)
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:389
#define TYPECACHE_TUPDESC
Definition typcache.h:146

References Assert, ereport, errcode(), errmsg, ERROR, fb(), 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)
extern

Definition at line 2083 of file typcache.c.

2084{
2087 bool found;
2089
2090 Assert(tupDesc->tdtypeid == RECORDOID);
2091
2092 if (RecordCacheHash == NULL)
2093 {
2094 /* First time through: initialize the hash table */
2095 HASHCTL ctl;
2096
2097 ctl.keysize = sizeof(TupleDesc); /* just the pointer */
2098 ctl.entrysize = sizeof(RecordCacheEntry);
2101 RecordCacheHash = hash_create("Record information cache", 64,
2102 &ctl,
2104
2105 /* Also make sure CacheMemoryContext exists */
2106 if (!CacheMemoryContext)
2108 }
2109
2110 /*
2111 * Find a hashtable entry for this tuple descriptor. We don't use
2112 * HASH_ENTER yet, because if it's missing, we need to make sure that all
2113 * the allocations succeed before we create the new entry.
2114 */
2116 &tupDesc,
2117 HASH_FIND, &found);
2118 if (found && recentry->tupdesc != NULL)
2119 {
2120 tupDesc->tdtypmod = recentry->tupdesc->tdtypmod;
2121 return;
2122 }
2123
2124 /* Not present, so need to manufacture an entry */
2126
2127 /* Look in the SharedRecordTypmodRegistry, if attached */
2129 if (entDesc == NULL)
2130 {
2131 /*
2132 * Make sure we have room before we CreateTupleDescCopy() or advance
2133 * NextRecordTypmod.
2134 */
2136
2137 /* Reference-counted local cache only. */
2138 entDesc = CreateTupleDescCopy(tupDesc);
2139 entDesc->tdrefcount = 1;
2140 entDesc->tdtypmod = NextRecordTypmod++;
2141 }
2142 else
2143 {
2145 }
2146
2148
2149 /* Assign a unique tupdesc identifier, too. */
2151
2152 /* Fully initialized; create the hash table entry */
2154 &tupDesc,
2155 HASH_ENTER, NULL);
2156 recentry->tupdesc = entDesc;
2157
2158 /* Update the caller's tuple descriptor. */
2159 tupDesc->tdtypmod = entDesc->tdtypmod;
2160
2162}
void CreateCacheMemoryContext(void)
Definition catcache.c:726
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition dynahash.c:889
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
Definition dynahash.c:360
@ HASH_FIND
Definition hsearch.h:108
@ HASH_ENTER
Definition hsearch.h:109
#define HASH_ELEM
Definition hsearch.h:90
#define HASH_COMPARE
Definition hsearch.h:94
#define HASH_FUNCTION
Definition hsearch.h:93
MemoryContext CacheMemoryContext
Definition mcxt.c:170
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:138
tree ctl
Definition radixtree.h:1838
Size keysize
Definition hsearch.h:69
int32 tdtypmod
Definition tupdesc.h:152
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition tupdesc.c:242
struct TupleDescData * TupleDesc
Definition tupdesc.h:163
static TupleDesc find_or_make_matching_shared_tupledesc(TupleDesc tupdesc)
Definition typcache.c:2984
static int32 NextRecordTypmod
Definition typcache.c:306
static HTAB * RecordCacheHash
Definition typcache.c:295
static int record_type_typmod_compare(const void *a, const void *b, size_t size)
Definition typcache.c:2067
static void ensure_record_cache_typmod_slot_exists(int32 typmod)
Definition typcache.c:1840
static uint32 record_type_typmod_hash(const void *data, size_t size)
Definition typcache.c:2056

References Assert, CacheMemoryContext, CreateCacheMemoryContext(), CreateTupleDescCopy(), ctl, ensure_record_cache_typmod_slot_exists(), fb(), find_or_make_matching_shared_tupledesc(), HASH_COMPARE, hash_create(), HASH_ELEM, HASH_ENTER, HASH_FIND, HASH_FUNCTION, hash_search(), RecordCacheArrayEntry::id, HASHCTL::keysize, MemoryContextSwitchTo(), NextRecordTypmod, record_type_typmod_compare(), record_type_typmod_hash(), RecordCacheArray, RecordCacheHash, TupleDescData::tdtypeid, TupleDescData::tdtypmod, 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  )
extern

Definition at line 3239 of file typcache.c.

3240{
3242}
static void finalize_in_progress_typentries(void)
Definition typcache.c:3214

References finalize_in_progress_typentries().

Referenced by AbortSubTransaction(), and CommitSubTransaction().

◆ AtEOXact_TypeCache()

void AtEOXact_TypeCache ( void  )
extern

◆ compare_values_of_enum()

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

Definition at line 2705 of file typcache.c.

2706{
2708 EnumItem *item1;
2709 EnumItem *item2;
2710
2711 /*
2712 * Equal OIDs are certainly equal --- this case was probably handled by
2713 * our caller, but we may as well check.
2714 */
2715 if (arg1 == arg2)
2716 return 0;
2717
2718 /* Load up the cache if first time through */
2719 if (tcache->enumData == NULL)
2720 load_enum_cache_data(tcache);
2721 enumdata = tcache->enumData;
2722
2723 /*
2724 * If both OIDs are known-sorted, we can just compare them directly.
2725 */
2728 {
2729 if (arg1 < arg2)
2730 return -1;
2731 else
2732 return 1;
2733 }
2734
2735 /*
2736 * Slow path: we have to identify their actual sort-order positions.
2737 */
2740
2741 if (item1 == NULL || item2 == NULL)
2742 {
2743 /*
2744 * We couldn't find one or both values. That means the enum has
2745 * changed under us, so re-initialize the cache and try again. We
2746 * don't bother retrying the known-sorted case in this path.
2747 */
2748 load_enum_cache_data(tcache);
2749 enumdata = tcache->enumData;
2750
2753
2754 /*
2755 * If we still can't find the values, complain: we must have corrupt
2756 * data.
2757 */
2758 if (item1 == NULL)
2759 elog(ERROR, "enum value %u not found in cache for enum %s",
2760 arg1, format_type_be(tcache->type_id));
2761 if (item2 == NULL)
2762 elog(ERROR, "enum value %u not found in cache for enum %s",
2763 arg2, format_type_be(tcache->type_id));
2764 }
2765
2766 if (item1->sort_order < item2->sort_order)
2767 return -1;
2768 else if (item1->sort_order > item2->sort_order)
2769 return 1;
2770 else
2771 return 0;
2772}
#define elog(elevel,...)
Definition elog.h:228
struct TypeCacheEnumData * enumData
Definition typcache.h:131
static void load_enum_cache_data(TypeCacheEntry *tcache)
Definition typcache.c:2778
static EnumItem * find_enumitem(TypeCacheEnumData *enumdata, Oid arg)
Definition typcache.c:2933
static bool enum_known_sorted(TypeCacheEnumData *enumdata, Oid arg)
Definition typcache.c:2676

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

Referenced by enum_cmp_internal().

◆ DomainHasConstraints()

bool DomainHasConstraints ( Oid  type_id,
bool has_volatile 
)
extern

Definition at line 1511 of file typcache.c.

1512{
1513 TypeCacheEntry *typentry;
1514
1515 /*
1516 * Note: a side effect is to cause the typcache's domain data to become
1517 * valid. This is fine since we'll likely need it soon if there is any.
1518 */
1520
1521 if (typentry->domainData == NULL)
1522 return false;
1523
1524 if (has_volatile)
1525 {
1526 *has_volatile = false;
1527
1529 typentry->domainData->constraints)
1530 {
1531 if (constrstate->constrainttype == DOM_CONSTRAINT_CHECK &&
1533 {
1534 *has_volatile = true;
1535 break;
1536 }
1537 }
1538 }
1539
1540 return true;
1541}
bool contain_volatile_functions(Node *clause)
Definition clauses.c:567
@ DOM_CONSTRAINT_CHECK
Definition execnodes.h:1087
#define foreach_node(type, var, lst)
Definition pg_list.h:528
Definition nodes.h:133
DomainConstraintCache * domainData
Definition typcache.h:122
#define TYPECACHE_DOMAIN_CONSTR_INFO
Definition typcache.h:151

References DomainConstraintCache::constraints, contain_volatile_functions(), DOM_CONSTRAINT_CHECK, TypeCacheEntry::domainData, fb(), foreach_node, lookup_type_cache(), and TYPECACHE_DOMAIN_CONSTR_INFO.

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

◆ InitDomainConstraintRef()

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

Definition at line 1420 of file typcache.c.

1422{
1423 /* Look up the typcache entry --- we assume it survives indefinitely */
1425 ref->need_exprstate = need_exprstate;
1426 /* For safety, establish the callback before acquiring a refcount */
1427 ref->refctx = refctx;
1428 ref->dcc = NULL;
1429 ref->callback.func = dccref_deletion_callback;
1430 ref->callback.arg = ref;
1431 MemoryContextRegisterResetCallback(refctx, &ref->callback);
1432 /* Acquire refcount if there are constraints, and set up exported list */
1433 if (ref->tcache->domainData)
1434 {
1435 ref->dcc = ref->tcache->domainData;
1436 ref->dcc->dccRefCount++;
1437 if (ref->need_exprstate)
1438 ref->constraints = prep_domain_constraints(ref->dcc->constraints,
1439 ref->refctx);
1440 else
1441 ref->constraints = ref->dcc->constraints;
1442 }
1443 else
1444 ref->constraints = NIL;
1445}
void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)
Definition mcxt.c:585
#define NIL
Definition pg_list.h:68
static List * prep_domain_constraints(List *constraints, MemoryContext execctx)
Definition typcache.c:1382
static void dccref_deletion_callback(void *arg)
Definition typcache.c:1361

References dccref_deletion_callback(), fb(), lookup_type_cache(), MemoryContextRegisterResetCallback(), NIL, prep_domain_constraints(), 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 
)
extern

Definition at line 1997 of file typcache.c.

1998{
1999 TupleDesc tmp;
2000
2001 tmp = lookup_rowtype_tupdesc_internal(type_id, typmod, false);
2002 return CreateTupleDescCopyConstr(tmp);
2003}
TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc)
Definition tupdesc.c:336

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 
)
extern

Definition at line 2019 of file typcache.c.

2020{
2021 TupleDesc tupDesc;
2022
2023 if (type_id != RECORDOID)
2024 {
2025 /*
2026 * Check for domain or named composite type. We might as well load
2027 * whichever data is needed.
2028 */
2029 TypeCacheEntry *typentry;
2030
2031 typentry = lookup_type_cache(type_id,
2034 if (typentry->typtype == TYPTYPE_DOMAIN)
2036 typentry->domainBaseTypmod,
2037 noError);
2038 if (typentry->tupDesc == NULL && !noError)
2039 ereport(ERROR,
2041 errmsg("type %s is not composite",
2042 format_type_be(type_id))));
2043 tupDesc = typentry->tupDesc;
2044 }
2045 else
2046 tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, noError);
2047 if (tupDesc != NULL)
2048 PinTupleDesc(tupDesc);
2049 return tupDesc;
2050}
int32 domainBaseTypmod
Definition typcache.h:116
TupleDesc lookup_rowtype_tupdesc_noerror(Oid type_id, int32 typmod, bool noError)
Definition typcache.c:1980
#define TYPECACHE_DOMAIN_BASE_INFO
Definition typcache.h:150

References TypeCacheEntry::domainBaseType, TypeCacheEntry::domainBaseTypmod, ereport, errcode(), errmsg, ERROR, fb(), 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 
)
extern

Definition at line 1980 of file typcache.c.

1981{
1982 TupleDesc tupDesc;
1983
1984 tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, noError);
1985 if (tupDesc != NULL)
1986 PinTupleDesc(tupDesc);
1987 return tupDesc;
1988}

References fb(), lookup_rowtype_tupdesc_internal(), and PinTupleDesc.

Referenced by lookup_rowtype_tupdesc_domain().

◆ lookup_type_cache()

TypeCacheEntry * lookup_type_cache ( Oid  type_id,
int  flags 
)
extern

Definition at line 389 of file typcache.c.

390{
391 TypeCacheEntry *typentry;
392 bool found;
394
395 if (in_progress_list == NULL)
396 {
397 /* First time through: initialize the hash table */
398 HASHCTL ctl;
399 int allocsize;
400
401 if (TypeCacheHash == NULL)
402 {
403 ctl.keysize = sizeof(Oid);
404 ctl.entrysize = sizeof(TypeCacheEntry);
405
406 /*
407 * TypeCacheEntry takes hash value from the system cache. For
408 * TypeCacheHash we use the same hash in order to speedup search
409 * by hash value. This is used by hash_seq_init_with_hash_value().
410 */
411 ctl.hash = type_cache_syshash;
412
413 TypeCacheHash = hash_create("Type information cache", 64,
415 }
416
418 {
419 ctl.keysize = sizeof(Oid);
420 ctl.entrysize = sizeof(RelIdToTypeIdCacheEntry);
421 RelIdToTypeIdCacheHash = hash_create("Map from relid to OID of cached composite type", 64,
423 }
424
425 /* Also make sure CacheMemoryContext exists */
428
429 /*
430 * Reserve enough in_progress_list slots for many cases. This is the
431 * last allocation on purpose, done after the two others.
432 */
433 allocsize = 4;
436 allocsize * sizeof(*in_progress_list));
437 in_progress_list_maxlen = allocsize;
438
439 /*
440 * Set up callbacks for SI invalidations. These steps are done last,
441 * once all the other initializations are done, and can fail only with
442 * a FATAL error.
443 */
448 }
449
451
452 /* Register to catch invalidation messages */
454 {
455 int allocsize;
456
457 allocsize = in_progress_list_maxlen * 2;
459 allocsize * sizeof(*in_progress_list));
460 in_progress_list_maxlen = allocsize;
461 }
462
463 /* Try to look up an existing entry */
465 &type_id,
466 HASH_FIND, NULL);
467
468 /*
469 * Only mark the new entry as "in progress" after the initial entry
470 * lookup.
471 *
472 * TypeCacheHash uses type_cache_syshash(), potentially triggering the
473 * initialization of the TYPEOID catcache, where an out-of-memory failure
474 * is possible. If an out-of-memory happens, error recovery would call
475 * finalize_in_progress_typentries(), that could attempt a catcache
476 * initialization again outside a transaction context.
477 *
478 * See also ConditionalCatalogCacheInitializeCache().
479 */
482
483 if (typentry == NULL)
484 {
485 /*
486 * If we didn't find one, we want to make one. But first look up the
487 * pg_type row, just to make sure we don't make a cache entry for an
488 * invalid type OID. If the type OID is not valid, present a
489 * user-facing error, since some code paths such as domain_in() allow
490 * this function to be reached with a user-supplied OID.
491 */
492 HeapTuple tp;
494
496 if (!HeapTupleIsValid(tp))
499 errmsg("type with OID %u does not exist", type_id)));
501 if (!typtup->typisdefined)
504 errmsg("type \"%s\" is only a shell",
505 NameStr(typtup->typname))));
506
507 /* Now make the typcache entry */
509 &type_id,
510 HASH_ENTER, &found);
511 Assert(!found); /* it wasn't there a moment ago */
512
513 MemSet(typentry, 0, sizeof(TypeCacheEntry));
514
515 /* These fields can never change, by definition */
516 typentry->type_id = type_id;
517 typentry->type_id_hash = get_hash_value(TypeCacheHash, &type_id);
518
519 /* Keep this part in sync with the code below */
520 typentry->typlen = typtup->typlen;
521 typentry->typbyval = typtup->typbyval;
522 typentry->typalign = typtup->typalign;
523 typentry->typstorage = typtup->typstorage;
524 typentry->typtype = typtup->typtype;
525 typentry->typrelid = typtup->typrelid;
526 typentry->typsubscript = typtup->typsubscript;
527 typentry->typelem = typtup->typelem;
528 typentry->typarray = typtup->typarray;
529 typentry->typcollation = typtup->typcollation;
530 typentry->flags |= TCFLAGS_HAVE_PG_TYPE_DATA;
531
532 /* If it's a domain, immediately thread it into the domain cache list */
533 if (typentry->typtype == TYPTYPE_DOMAIN)
534 {
536 firstDomainTypeEntry = typentry;
537 }
538
539 ReleaseSysCache(tp);
540 }
541 else if (!(typentry->flags & TCFLAGS_HAVE_PG_TYPE_DATA))
542 {
543 /*
544 * We have an entry, but its pg_type row got changed, so reload the
545 * data obtained directly from pg_type.
546 */
547 HeapTuple tp;
549
551 if (!HeapTupleIsValid(tp))
554 errmsg("type with OID %u does not exist", type_id)));
556 if (!typtup->typisdefined)
559 errmsg("type \"%s\" is only a shell",
560 NameStr(typtup->typname))));
561
562 /*
563 * Keep this part in sync with the code above. Many of these fields
564 * shouldn't ever change, particularly typtype, but copy 'em anyway.
565 */
566 typentry->typlen = typtup->typlen;
567 typentry->typbyval = typtup->typbyval;
568 typentry->typalign = typtup->typalign;
569 typentry->typstorage = typtup->typstorage;
570 typentry->typtype = typtup->typtype;
571 typentry->typrelid = typtup->typrelid;
572 typentry->typsubscript = typtup->typsubscript;
573 typentry->typelem = typtup->typelem;
574 typentry->typarray = typtup->typarray;
575 typentry->typcollation = typtup->typcollation;
576 typentry->flags |= TCFLAGS_HAVE_PG_TYPE_DATA;
577
578 ReleaseSysCache(tp);
579 }
580
581 /*
582 * Look up opclasses if we haven't already and any dependent info is
583 * requested.
584 */
590 {
591 Oid opclass;
592
593 opclass = GetDefaultOpClass(type_id, BTREE_AM_OID);
594 if (OidIsValid(opclass))
595 {
596 typentry->btree_opf = get_opclass_family(opclass);
597 typentry->btree_opintype = get_opclass_input_type(opclass);
598 }
599 else
600 {
601 typentry->btree_opf = typentry->btree_opintype = InvalidOid;
602 }
603
604 /*
605 * Reset information derived from btree opclass. Note in particular
606 * that we'll redetermine the eq_opr even if we previously found one;
607 * this matters in case a btree opclass has been added to a type that
608 * previously had only a hash opclass.
609 */
610 typentry->flags &= ~(TCFLAGS_CHECKED_EQ_OPR |
615 }
616
617 /*
618 * If we need to look up equality operator, and there's no btree opclass,
619 * force lookup of hash opclass.
620 */
621 if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO)) &&
622 !(typentry->flags & TCFLAGS_CHECKED_EQ_OPR) &&
623 typentry->btree_opf == InvalidOid)
625
630 !(typentry->flags & TCFLAGS_CHECKED_HASH_OPCLASS))
631 {
632 Oid opclass;
633
634 opclass = GetDefaultOpClass(type_id, HASH_AM_OID);
635 if (OidIsValid(opclass))
636 {
637 typentry->hash_opf = get_opclass_family(opclass);
638 typentry->hash_opintype = get_opclass_input_type(opclass);
639 }
640 else
641 {
642 typentry->hash_opf = typentry->hash_opintype = InvalidOid;
643 }
644
645 /*
646 * Reset information derived from hash opclass. We do *not* reset the
647 * eq_opr; if we already found one from the btree opclass, that
648 * decision is still good.
649 */
650 typentry->flags &= ~(TCFLAGS_CHECKED_HASH_PROC |
653 }
654
655 /*
656 * Look for requested operators and functions, if we haven't already.
657 */
658 if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO)) &&
659 !(typentry->flags & TCFLAGS_CHECKED_EQ_OPR))
660 {
661 Oid eq_opr = InvalidOid;
662
663 if (typentry->btree_opf != InvalidOid)
664 eq_opr = get_opfamily_member(typentry->btree_opf,
665 typentry->btree_opintype,
666 typentry->btree_opintype,
668 if (eq_opr == InvalidOid &&
669 typentry->hash_opf != InvalidOid)
670 eq_opr = get_opfamily_member(typentry->hash_opf,
671 typentry->hash_opintype,
672 typentry->hash_opintype,
674
675 /*
676 * If the proposed equality operator is array_eq or record_eq, check
677 * to see if the element type or column types support equality. If
678 * not, array_eq or record_eq would fail at runtime, so we don't want
679 * to report that the type has equality. (We can omit similar
680 * checking for ranges and multiranges because ranges can't be created
681 * in the first place unless their subtypes support equality.)
682 */
683 if (eq_opr == ARRAY_EQ_OP &&
685 eq_opr = InvalidOid;
686 else if (eq_opr == RECORD_EQ_OP &&
688 eq_opr = InvalidOid;
689
690 /* Force update of eq_opr_finfo only if we're changing state */
691 if (typentry->eq_opr != eq_opr)
692 typentry->eq_opr_finfo.fn_oid = InvalidOid;
693
694 typentry->eq_opr = eq_opr;
695
696 /*
697 * Reset info about hash functions whenever we pick up new info about
698 * equality operator. This is so we can ensure that the hash
699 * functions match the operator.
700 */
701 typentry->flags &= ~(TCFLAGS_CHECKED_HASH_PROC |
703 typentry->flags |= TCFLAGS_CHECKED_EQ_OPR;
704 }
705 if ((flags & TYPECACHE_LT_OPR) &&
706 !(typentry->flags & TCFLAGS_CHECKED_LT_OPR))
707 {
708 Oid lt_opr = InvalidOid;
709
710 if (typentry->btree_opf != InvalidOid)
711 lt_opr = get_opfamily_member(typentry->btree_opf,
712 typentry->btree_opintype,
713 typentry->btree_opintype,
715
716 /*
717 * As above, make sure array_cmp or record_cmp will succeed; but again
718 * we need no special check for ranges or multiranges.
719 */
720 if (lt_opr == ARRAY_LT_OP &&
721 !array_element_has_compare(typentry))
722 lt_opr = InvalidOid;
723 else if (lt_opr == RECORD_LT_OP &&
725 lt_opr = InvalidOid;
726
727 typentry->lt_opr = lt_opr;
728 typentry->flags |= TCFLAGS_CHECKED_LT_OPR;
729 }
730 if ((flags & TYPECACHE_GT_OPR) &&
731 !(typentry->flags & TCFLAGS_CHECKED_GT_OPR))
732 {
733 Oid gt_opr = InvalidOid;
734
735 if (typentry->btree_opf != InvalidOid)
736 gt_opr = get_opfamily_member(typentry->btree_opf,
737 typentry->btree_opintype,
738 typentry->btree_opintype,
740
741 /*
742 * As above, make sure array_cmp or record_cmp will succeed; but again
743 * we need no special check for ranges or multiranges.
744 */
745 if (gt_opr == ARRAY_GT_OP &&
746 !array_element_has_compare(typentry))
747 gt_opr = InvalidOid;
748 else if (gt_opr == RECORD_GT_OP &&
750 gt_opr = InvalidOid;
751
752 typentry->gt_opr = gt_opr;
753 typentry->flags |= TCFLAGS_CHECKED_GT_OPR;
754 }
756 !(typentry->flags & TCFLAGS_CHECKED_CMP_PROC))
757 {
758 Oid cmp_proc = InvalidOid;
759
760 if (typentry->btree_opf != InvalidOid)
761 cmp_proc = get_opfamily_proc(typentry->btree_opf,
762 typentry->btree_opintype,
763 typentry->btree_opintype,
765
766 /*
767 * As above, make sure array_cmp or record_cmp will succeed; but again
768 * we need no special check for ranges or multiranges.
769 */
770 if (cmp_proc == F_BTARRAYCMP &&
771 !array_element_has_compare(typentry))
772 cmp_proc = InvalidOid;
773 else if (cmp_proc == F_BTRECORDCMP &&
775 cmp_proc = InvalidOid;
776
777 /* Force update of cmp_proc_finfo only if we're changing state */
778 if (typentry->cmp_proc != cmp_proc)
779 typentry->cmp_proc_finfo.fn_oid = InvalidOid;
780
781 typentry->cmp_proc = cmp_proc;
782 typentry->flags |= TCFLAGS_CHECKED_CMP_PROC;
783 }
785 !(typentry->flags & TCFLAGS_CHECKED_HASH_PROC))
786 {
787 Oid hash_proc = InvalidOid;
788
789 /*
790 * We insist that the eq_opr, if one has been determined, match the
791 * hash opclass; else report there is no hash function.
792 */
793 if (typentry->hash_opf != InvalidOid &&
794 (!OidIsValid(typentry->eq_opr) ||
795 typentry->eq_opr == get_opfamily_member(typentry->hash_opf,
796 typentry->hash_opintype,
797 typentry->hash_opintype,
799 hash_proc = get_opfamily_proc(typentry->hash_opf,
800 typentry->hash_opintype,
801 typentry->hash_opintype,
803
804 /*
805 * As above, make sure hash_array, hash_record, hash_range, or
806 * hash_multirange will succeed. Here we do need to check the range
807 * cases.
808 */
809 if (hash_proc == F_HASH_ARRAY &&
810 !array_element_has_hashing(typentry))
811 hash_proc = InvalidOid;
812 else if (hash_proc == F_HASH_RECORD &&
814 hash_proc = InvalidOid;
815 else if (hash_proc == F_HASH_RANGE &&
816 !range_element_has_hashing(typentry))
817 hash_proc = InvalidOid;
818 else if (hash_proc == F_HASH_MULTIRANGE &&
820 hash_proc = InvalidOid;
821
822 /* Force update of hash_proc_finfo only if we're changing state */
823 if (typentry->hash_proc != hash_proc)
825
826 typentry->hash_proc = hash_proc;
827 typentry->flags |= TCFLAGS_CHECKED_HASH_PROC;
828 }
829 if ((flags & (TYPECACHE_HASH_EXTENDED_PROC |
832 {
833 Oid hash_extended_proc = InvalidOid;
834
835 /*
836 * We insist that the eq_opr, if one has been determined, match the
837 * hash opclass; else report there is no hash function.
838 */
839 if (typentry->hash_opf != InvalidOid &&
840 (!OidIsValid(typentry->eq_opr) ||
841 typentry->eq_opr == get_opfamily_member(typentry->hash_opf,
842 typentry->hash_opintype,
843 typentry->hash_opintype,
845 hash_extended_proc = get_opfamily_proc(typentry->hash_opf,
846 typentry->hash_opintype,
847 typentry->hash_opintype,
849
850 /*
851 * As above, make sure hash_array_extended, hash_record_extended,
852 * hash_range_extended, or hash_multirange_extended will succeed.
853 */
854 if (hash_extended_proc == F_HASH_ARRAY_EXTENDED &&
856 hash_extended_proc = InvalidOid;
857 else if (hash_extended_proc == F_HASH_RECORD_EXTENDED &&
859 hash_extended_proc = InvalidOid;
860 else if (hash_extended_proc == F_HASH_RANGE_EXTENDED &&
862 hash_extended_proc = InvalidOid;
863 else if (hash_extended_proc == F_HASH_MULTIRANGE_EXTENDED &&
865 hash_extended_proc = InvalidOid;
866
867 /* Force update of proc finfo only if we're changing state */
868 if (typentry->hash_extended_proc != hash_extended_proc)
870
871 typentry->hash_extended_proc = hash_extended_proc;
873 }
874
875 /*
876 * Set up fmgr lookup info as requested
877 *
878 * Note: we tell fmgr the finfo structures live in CacheMemoryContext,
879 * which is not quite right (they're really in the hash table's private
880 * memory context) but this will do for our purposes.
881 *
882 * Note: the code above avoids invalidating the finfo structs unless the
883 * referenced operator/function OID actually changes. This is to prevent
884 * unnecessary leakage of any subsidiary data attached to an finfo, since
885 * that would cause session-lifespan memory leaks.
886 */
887 if ((flags & TYPECACHE_EQ_OPR_FINFO) &&
888 typentry->eq_opr_finfo.fn_oid == InvalidOid &&
889 typentry->eq_opr != InvalidOid)
890 {
892
893 eq_opr_func = get_opcode(typentry->eq_opr);
894 if (eq_opr_func != InvalidOid)
897 }
898 if ((flags & TYPECACHE_CMP_PROC_FINFO) &&
899 typentry->cmp_proc_finfo.fn_oid == InvalidOid &&
900 typentry->cmp_proc != InvalidOid)
901 {
902 fmgr_info_cxt(typentry->cmp_proc, &typentry->cmp_proc_finfo,
904 }
905 if ((flags & TYPECACHE_HASH_PROC_FINFO) &&
906 typentry->hash_proc_finfo.fn_oid == InvalidOid &&
907 typentry->hash_proc != InvalidOid)
908 {
909 fmgr_info_cxt(typentry->hash_proc, &typentry->hash_proc_finfo,
911 }
914 typentry->hash_extended_proc != InvalidOid)
915 {
917 &typentry->hash_extended_proc_finfo,
919 }
920
921 /*
922 * If it's a composite type (row type), get tupdesc if requested
923 */
924 if ((flags & TYPECACHE_TUPDESC) &&
925 typentry->tupDesc == NULL &&
926 typentry->typtype == TYPTYPE_COMPOSITE)
927 {
928 load_typcache_tupdesc(typentry);
929 }
930
931 /*
932 * If requested, get information about a range type
933 *
934 * This includes making sure that the basic info about the range element
935 * type is up-to-date.
936 */
937 if ((flags & TYPECACHE_RANGE_INFO) &&
938 typentry->typtype == TYPTYPE_RANGE)
939 {
940 if (typentry->rngelemtype == NULL)
941 load_rangetype_info(typentry);
942 else if (!(typentry->rngelemtype->flags & TCFLAGS_HAVE_PG_TYPE_DATA))
943 (void) lookup_type_cache(typentry->rngelemtype->type_id, 0);
944 }
945
946 /*
947 * If requested, get information about a multirange type
948 */
949 if ((flags & TYPECACHE_MULTIRANGE_INFO) &&
950 typentry->rngtype == NULL &&
951 typentry->typtype == TYPTYPE_MULTIRANGE)
952 {
953 load_multirangetype_info(typentry);
954 }
955
956 /*
957 * If requested, get information about a domain type
958 */
959 if ((flags & TYPECACHE_DOMAIN_BASE_INFO) &&
960 typentry->domainBaseType == InvalidOid &&
961 typentry->typtype == TYPTYPE_DOMAIN)
962 {
963 typentry->domainBaseTypmod = -1;
964 typentry->domainBaseType =
965 getBaseTypeAndTypmod(type_id, &typentry->domainBaseTypmod);
966 }
967 if ((flags & TYPECACHE_DOMAIN_CONSTR_INFO) &&
968 (typentry->flags & TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS) == 0 &&
969 typentry->typtype == TYPTYPE_DOMAIN)
970 {
971 load_domaintype_info(typentry);
972 }
973
974 INJECTION_POINT("typecache-before-rel-type-cache-insert", NULL);
975
978
980
981 return typentry;
982}
#define NameStr(name)
Definition c.h:894
#define MemSet(start, val, len)
Definition c.h:1147
#define OidIsValid(objectId)
Definition c.h:917
uint32 get_hash_value(HTAB *hashp, const void *keyPtr)
Definition dynahash.c:845
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition fmgr.c:139
#define HASHSTANDARD_PROC
Definition hash.h:355
#define HASHEXTENDED_PROC
Definition hash.h:356
#define HASH_BLOBS
Definition hsearch.h:92
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition indexcmds.c:2381
#define INJECTION_POINT(name, arg)
void CacheRegisterSyscacheCallback(SysCacheIdentifier cacheid, SyscacheCallbackFunction func, Datum arg)
Definition inval.c:1813
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
Definition inval.c:1855
Oid get_opclass_input_type(Oid opclass)
Definition lsyscache.c:1464
Oid get_opclass_family(Oid opclass)
Definition lsyscache.c:1442
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition lsyscache.c:1022
RegProcedure get_opcode(Oid opno)
Definition lsyscache.c:1585
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition lsyscache.c:170
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition lsyscache.c:2854
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition mcxt.c:1235
void * repalloc(void *pointer, Size size)
Definition mcxt.c:1635
#define BTORDER_PROC
Definition nbtree.h:717
END_CATALOG_STRUCT typedef FormData_pg_type * Form_pg_type
Definition pg_type.h:265
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
uint64_t Datum
Definition postgres.h:70
#define InvalidOid
unsigned int Oid
#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
FmgrInfo cmp_proc_finfo
Definition typcache.h:77
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
Oid hash_opintype
Definition typcache.h:61
char typstorage
Definition typcache.h:42
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
HeapTuple SearchSysCache1(SysCacheIdentifier 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:1756
static void insert_rel_type_cache_if_needed(TypeCacheEntry *typentry)
Definition typcache.c:3116
static void TypeCacheOpcCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
Definition typcache.c:2614
static bool record_fields_have_hashing(TypeCacheEntry *typentry)
Definition typcache.c:1635
static HTAB * RelIdToTypeIdCacheHash
Definition typcache.c:87
static bool record_fields_have_extended_hashing(TypeCacheEntry *typentry)
Definition typcache.c:1643
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:1796
static bool record_fields_have_equality(TypeCacheEntry *typentry)
Definition typcache.c:1619
#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:1581
static bool array_element_has_hashing(TypeCacheEntry *typentry)
Definition typcache.c:1573
static void load_multirangetype_info(TypeCacheEntry *typentry)
Definition typcache.c:1080
static uint32 type_cache_syshash(const void *key, Size keysize)
Definition typcache.c:362
#define TCFLAGS_CHECKED_CMP_PROC
Definition typcache.c:105
static bool multirange_element_has_extended_hashing(TypeCacheEntry *typentry)
Definition typcache.c:1804
static int in_progress_list_len
Definition typcache.c:227
static bool array_element_has_equality(TypeCacheEntry *typentry)
Definition typcache.c:1557
static void load_rangetype_info(TypeCacheEntry *typentry)
Definition typcache.c:1022
static bool range_element_has_extended_hashing(TypeCacheEntry *typentry)
Definition typcache.c:1764
static TypeCacheEntry * firstDomainTypeEntry
Definition typcache.c:96
#define TCFLAGS_CHECKED_HASH_EXTENDED_PROC
Definition typcache.c:107
static void load_domaintype_info(TypeCacheEntry *typentry)
Definition typcache.c:1102
static void TypeCacheRelCallback(Datum arg, Oid relid)
Definition typcache.c:2461
static void TypeCacheTypCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
Definition typcache.c:2557
static void TypeCacheConstrCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
Definition typcache.c:2652
static bool array_element_has_compare(TypeCacheEntry *typentry)
Definition typcache.c:1565
#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:1627
#define TCFLAGS_CHECKED_EQ_OPR
Definition typcache.c:102
static void load_typcache_tupdesc(TypeCacheEntry *typentry)
Definition typcache.c:988
#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
#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, fb(), firstDomainTypeEntry, TypeCacheEntry::flags, fmgr_info_cxt(), FmgrInfo::fn_oid, Form_pg_type, 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, HASHCTL::keysize, 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(), create_grouping_expr_infos(), CreateStatistics(), dependency_degree(), domain_state_setup(), DomainHasConstraints(), enum_cmp_internal(), ExecForPortionOfLeftovers(), ExecInitExprRec(), find_simplified_clause(), foreign_expr_walker(), get_cached_rowtype(), get_multirange_io_data(), get_op_hash_functions_ext(), 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(), import_pg_statistic(), init_grouping_targets(), 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_minus_multi(), 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(), range_minus_multi(), record_cmp(), record_eq(), revalidate_rectypeid(), scalararraysel(), scalararraysel_containment(), show_sortorder_options(), statatt_check_bounds_histogram(), statatt_get_elem_type(), statatt_get_type(), statext_mcv_serialize(), tuples_equal(), tuplesort_begin_index_gin(), and width_bucket_array().

◆ SharedRecordTypmodRegistryAttach()

void SharedRecordTypmodRegistryAttach ( SharedRecordTypmodRegistry registry)
extern

Definition at line 2337 of file typcache.c.

2338{
2342
2344
2345 /* We can't already be attached to a shared registry. */
2352
2353 /*
2354 * We can't already have typmods in our local cache, because they'd clash
2355 * with those imported by SharedRecordTypmodRegistryInit. This should be
2356 * a freshly started parallel worker. If we ever support worker
2357 * recycling, a worker would need to zap its local cache in between
2358 * servicing different queries, in order to be able to call this and
2359 * synchronize typmods with a new leader; but that's problematic because
2360 * we can't be very sure that record-typmod-related state hasn't escaped
2361 * to anywhere else in the process.
2362 */
2364
2366
2367 /* Attach to the two hash tables. */
2370 registry->record_table_handle,
2374 registry->typmod_table_handle,
2375 NULL);
2376
2378
2379 /*
2380 * Set up detach hook to run at worker exit. Currently this is the same
2381 * as the leader's detach hook, but in future they might need to be
2382 * different.
2383 */
2387
2388 /*
2389 * Set up the session state that will tell assign_record_type_typmod and
2390 * lookup_rowtype_tupdesc_internal about the shared registry.
2391 */
2395}
dshash_table * dshash_attach(dsa_area *area, const dshash_parameters *params, dshash_table_handle handle, void *arg)
Definition dshash.c:274
void on_dsm_detach(dsm_segment *seg, on_dsm_detach_callback function, Datum arg)
Definition dsm.c:1140
#define IsParallelWorker()
Definition parallel.h:62
MemoryContext TopMemoryContext
Definition mcxt.c:167
#define PointerGetDatum(X)
Definition postgres.h:354
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
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:3096
static const dshash_parameters srtr_record_table_params
Definition typcache.c:275

References Session::area, Assert, CurrentSession, dshash_attach(), fb(), IsParallelWorker, MemoryContextSwitchTo(), NextRecordTypmod, on_dsm_detach(), PointerGetDatum, 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, and TopMemoryContext.

Referenced by AttachSession().

◆ SharedRecordTypmodRegistryEstimate()

size_t SharedRecordTypmodRegistryEstimate ( void  )
extern

Definition at line 2216 of file typcache.c.

2217{
2218 return sizeof(SharedRecordTypmodRegistry);
2219}

Referenced by GetSessionDsmHandle().

◆ SharedRecordTypmodRegistryInit()

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

Definition at line 2238 of file typcache.c.

2241{
2245 int32 typmod;
2246
2248
2249 /* We can't already be attached to a shared registry. */
2253
2255
2256 /* Create the hash table of tuple descriptors indexed by themselves. */
2258
2259 /* Create the hash table of tuple descriptors indexed by typmod. */
2261
2263
2264 /* Initialize the SharedRecordTypmodRegistry. */
2265 registry->record_table_handle = dshash_get_hash_table_handle(record_table);
2266 registry->typmod_table_handle = dshash_get_hash_table_handle(typmod_table);
2268
2269 /*
2270 * Copy all entries from this backend's private registry into the shared
2271 * registry.
2272 */
2273 for (typmod = 0; typmod < NextRecordTypmod; ++typmod)
2274 {
2279 TupleDesc tupdesc;
2280 bool found;
2281
2282 tupdesc = RecordCacheArray[typmod].tupdesc;
2283 if (tupdesc == NULL)
2284 continue;
2285
2286 /* Copy the TupleDesc into shared memory. */
2287 shared_dp = share_tupledesc(area, tupdesc, typmod);
2288
2289 /* Insert into the typmod table. */
2291 &tupdesc->tdtypmod,
2292 &found);
2293 if (found)
2294 elog(ERROR, "cannot create duplicate shared record typmod");
2295 typmod_table_entry->typmod = tupdesc->tdtypmod;
2296 typmod_table_entry->shared_tupdesc = shared_dp;
2298
2299 /* Insert into the record table. */
2300 record_table_key.shared = false;
2301 record_table_key.u.local_tupdesc = tupdesc;
2304 &found);
2305 if (!found)
2306 {
2307 record_table_entry->key.shared = true;
2308 record_table_entry->key.u.shared_tupdesc = shared_dp;
2309 }
2311 }
2312
2313 /*
2314 * Set up the global state that will tell assign_record_type_typmod and
2315 * lookup_rowtype_tupdesc_internal about the shared registry.
2316 */
2320
2321 /*
2322 * We install a detach hook in the leader, but only to handle cleanup on
2323 * failure during GetSessionDsmHandle(). Once GetSessionDsmHandle() pins
2324 * the memory, the leader process will use a shared registry until it
2325 * exits.
2326 */
2328}
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition atomics.h:214
int32_t int32
Definition c.h:679
uint64 dsa_pointer
Definition dsa.h:62
void dshash_release_lock(dshash_table *hash_table, void *entry)
Definition dshash.c:579
dshash_table_handle dshash_get_hash_table_handle(dshash_table *hash_table)
Definition dshash.c:371
dshash_table * dshash_create(dsa_area *area, const dshash_parameters *params, void *arg)
Definition dshash.c:210
#define dshash_find_or_insert(hash_table, key, found)
Definition dshash.h:109
static dsa_pointer share_tupledesc(dsa_area *area, TupleDesc tupdesc, uint32 typmod)
Definition typcache.c:2963

References Assert, CurrentSession, dshash_create(), dshash_find_or_insert, dshash_get_hash_table_handle(), dshash_release_lock(), elog, ERROR, fb(), IsParallelWorker, MemoryContextSwitchTo(), NextRecordTypmod, on_dsm_detach(), pg_atomic_init_u32(), RecordCacheArray, share_tupledesc(), 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, TupleDescData::tdtypmod, TopMemoryContext, and RecordCacheArrayEntry::tupdesc.

Referenced by GetSessionDsmHandle().

◆ UpdateDomainConstraintRef()

void UpdateDomainConstraintRef ( DomainConstraintRef ref)
extern

Definition at line 1458 of file typcache.c.

1459{
1460 TypeCacheEntry *typentry = ref->tcache;
1461
1462 /* Make sure typcache entry's data is up to date */
1463 if ((typentry->flags & TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS) == 0 &&
1464 typentry->typtype == TYPTYPE_DOMAIN)
1465 load_domaintype_info(typentry);
1466
1467 /* Transfer to ref object if there's new info, adjusting refcounts */
1468 if (ref->dcc != typentry->domainData)
1469 {
1470 /* Paranoia --- be sure link is nulled before trying to release */
1471 DomainConstraintCache *dcc = ref->dcc;
1472
1473 if (dcc)
1474 {
1475 /*
1476 * Note: we just leak the previous list of executable domain
1477 * constraints. Alternatively, we could keep those in a child
1478 * context of ref->refctx and free that context at this point.
1479 * However, in practice this code path will be taken so seldom
1480 * that the extra bookkeeping for a child context doesn't seem
1481 * worthwhile; we'll just allow a leak for the lifespan of refctx.
1482 */
1483 ref->constraints = NIL;
1484 ref->dcc = NULL;
1485 decr_dcc_refcount(dcc);
1486 }
1487 dcc = typentry->domainData;
1488 if (dcc)
1489 {
1490 ref->dcc = dcc;
1491 dcc->dccRefCount++;
1492 if (ref->need_exprstate)
1493 ref->constraints = prep_domain_constraints(dcc->constraints,
1494 ref->refctx);
1495 else
1496 ref->constraints = dcc->constraints;
1497 }
1498 }
1499}
static void decr_dcc_refcount(DomainConstraintCache *dcc)
Definition typcache.c:1350

References DomainConstraintCache::constraints, DomainConstraintCache::dccRefCount, decr_dcc_refcount(), TypeCacheEntry::domainData, fb(), TypeCacheEntry::flags, load_domaintype_info(), NIL, prep_domain_constraints(), TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS, and TypeCacheEntry::typtype.

Referenced by domain_check_input().