PostgreSQL Source Code git master
Data Structures | Macros | Typedefs | Functions
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
 
 

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 TypeCacheEntry  TypeCacheEntry
 
 
 

Functions

TypeCacheEntrylookup_type_cache (Oid type_id, int flags)
 
void  InitDomainConstraintRef (Oid type_id, DomainConstraintRef *ref, MemoryContext refctx, bool need_exprstate)
 
 
bool  DomainHasConstraints (Oid type_id)
 
 
TupleDesc  lookup_rowtype_tupdesc_noerror (Oid type_id, int32 typmod, bool noError)
 
 
TupleDesc  lookup_rowtype_tupdesc_domain (Oid type_id, int32 typmod, bool noError)
 
 
 
int  compare_values_of_enum (TypeCacheEntry *tcache, Oid arg1, Oid arg2)
 
 
 
 
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 2133 of file typcache.c.

2134{
2135 if (type_id != RECORDOID)
2136 {
2137 /*
2138 * It's a named composite type, so use the regular typcache.
2139 */
2140 TypeCacheEntry *typentry;
2141
2142 typentry = lookup_type_cache(type_id, TYPECACHE_TUPDESC);
2143 if (typentry->tupDesc == NULL)
2144 ereport(ERROR,
2145 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2146 errmsg("type %s is not composite",
2147 format_type_be(type_id))));
2148 Assert(typentry->tupDesc_identifier != 0);
2149 return typentry->tupDesc_identifier;
2150 }
2151 else
2152 {
2153 /*
2154 * It's a transient record type, so look in our record-type table.
2155 */
2156 if (typmod >= 0 && typmod < RecordCacheArrayLen &&
2157 RecordCacheArray[typmod].tupdesc != NULL)
2158 {
2159 Assert(RecordCacheArray[typmod].id != 0);
2160 return RecordCacheArray[typmod].id;
2161 }
2162
2163 /* For anonymous or unrecognized record type, generate a new ID */
2164 return ++tupledesc_id_counter;
2165 }
2166}
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:150
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 2041 of file typcache.c.

2042{
2043 RecordCacheEntry *recentry;
2044 TupleDesc entDesc;
2045 bool found;
2046 MemoryContext oldcxt;
2047
2048 Assert(tupDesc->tdtypeid == RECORDOID);
2049
2050 if (RecordCacheHash == NULL)
2051 {
2052 /* First time through: initialize the hash table */
2053 HASHCTL ctl;
2054
2055 ctl.keysize = sizeof(TupleDesc); /* just the pointer */
2056 ctl.entrysize = sizeof(RecordCacheEntry);
2059 RecordCacheHash = hash_create("Record information cache", 64,
2060 &ctl,
2062
2063 /* Also make sure CacheMemoryContext exists */
2064 if (!CacheMemoryContext)
2066 }
2067
2068 /*
2069 * Find a hashtable entry for this tuple descriptor. We don't use
2070 * HASH_ENTER yet, because if it's missing, we need to make sure that all
2071 * the allocations succeed before we create the new entry.
2072 */
2074 &tupDesc,
2075 HASH_FIND, &found);
2076 if (found && recentry->tupdesc != NULL)
2077 {
2078 tupDesc->tdtypmod = recentry->tupdesc->tdtypmod;
2079 return;
2080 }
2081
2082 /* Not present, so need to manufacture an entry */
2084
2085 /* Look in the SharedRecordTypmodRegistry, if attached */
2086 entDesc = find_or_make_matching_shared_tupledesc(tupDesc);
2087 if (entDesc == NULL)
2088 {
2089 /*
2090 * Make sure we have room before we CreateTupleDescCopy() or advance
2091 * NextRecordTypmod.
2092 */
2094
2095 /* Reference-counted local cache only. */
2096 entDesc = CreateTupleDescCopy(tupDesc);
2097 entDesc->tdrefcount = 1;
2098 entDesc->tdtypmod = NextRecordTypmod++;
2099 }
2100 else
2101 {
2103 }
2104
2105 RecordCacheArray[entDesc->tdtypmod].tupdesc = entDesc;
2106
2107 /* Assign a unique tupdesc identifier, too. */
2109
2110 /* Fully initialized; create the hash table entry */
2112 &tupDesc,
2113 HASH_ENTER, NULL);
2114 recentry->tupdesc = entDesc;
2115
2116 /* Update the caller's tuple descriptor. */
2117 tupDesc->tdtypmod = entDesc->tdtypmod;
2118
2119 MemoryContextSwitchTo(oldcxt);
2120}
void CreateCacheMemoryContext(void)
Definition: catcache.c:709
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:952
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:358
@ 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:169
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
tree ctl
Definition: radixtree.h:1838
Definition: hsearch.h:66
TupleDesc tupdesc
Definition: typcache.c:300
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:252
struct TupleDescData * TupleDesc
Definition: tupdesc.h:145
static TupleDesc find_or_make_matching_shared_tupledesc(TupleDesc tupdesc)
Definition: typcache.c:2942
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:2025
static void ensure_record_cache_typmod_slot_exists(int32 typmod)
Definition: typcache.c:1798
static uint32 record_type_typmod_hash(const void *data, size_t size)
Definition: typcache.c:2014

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 3197 of file typcache.c.

3198{
3200}
static void finalize_in_progress_typentries(void)
Definition: typcache.c:3172

References finalize_in_progress_typentries().

Referenced by AbortSubTransaction(), and CommitSubTransaction().

AtEOXact_TypeCache()

void AtEOXact_TypeCache ( void  )

Definition at line 3191 of file typcache.c.

3192{
3194}

References finalize_in_progress_typentries().

Referenced by AbortTransaction(), CommitTransaction(), and PrepareTransaction().

compare_values_of_enum()

int compare_values_of_enum ( TypeCacheEntrytcache,
Oid  arg1,
Oid  arg2 
)

Definition at line 2663 of file typcache.c.

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

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 1488 of file typcache.c.

1489{
1490 TypeCacheEntry *typentry;
1491
1492 /*
1493 * Note: a side effect is to cause the typcache's domain data to become
1494 * valid. This is fine since we'll likely need it soon if there is any.
1495 */
1497
1498 return (typentry->domainData != NULL);
1499}
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,
MemoryContext  refctx,
bool  need_exprstate 
)

Definition at line 1401 of file typcache.c.

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

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

TupleDesc lookup_rowtype_tupdesc ( Oid  type_id,
int32  typmod 
)

Definition at line 1921 of file typcache.c.

1922{
1923 TupleDesc tupDesc;
1924
1925 tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, false);
1926 PinTupleDesc(tupDesc);
1927 return tupDesc;
1928}
#define PinTupleDesc(tupdesc)
Definition: tupdesc.h:213
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1827

References lookup_rowtype_tupdesc_internal(), and PinTupleDesc.

Referenced by ATExecAddOf(), coerce_record_to_complex(), composite_to_json(), composite_to_jsonb(), deconstruct_composite_datum(), exec_move_row_from_datum(), ExecInitExprRec(), ExecuteCallStmt(), expanded_record_fetch_tupdesc(), get_cached_rowtype(), get_rule_expr(), GetAttributeByName(), GetAttributeByNum(), hash_record(), hash_record_extended(), HeapTupleHeaderGetDatum(), make_expanded_record_from_typeid(), make_tuple_indirect(), plperl_hash_from_datum(), pltcl_func_handler(), PLyDict_FromComposite(), PLyObject_ToComposite(), record_cmp(), record_eq(), record_image_cmp(), record_image_eq(), record_in(), record_out(), record_recv(), record_send(), transformOfType(), and update_cached_tupdesc().

lookup_rowtype_tupdesc_copy()

TupleDesc lookup_rowtype_tupdesc_copy ( Oid  type_id,
int32  typmod 
)

Definition at line 1955 of file typcache.c.

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

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 1977 of file typcache.c.

1978{
1979 TupleDesc tupDesc;
1980
1981 if (type_id != RECORDOID)
1982 {
1983 /*
1984 * Check for domain or named composite type. We might as well load
1985 * whichever data is needed.
1986 */
1987 TypeCacheEntry *typentry;
1988
1989 typentry = lookup_type_cache(type_id,
1992 if (typentry->typtype == TYPTYPE_DOMAIN)
1994 typentry->domainBaseTypmod,
1995 noError);
1996 if (typentry->tupDesc == NULL && !noError)
1997 ereport(ERROR,
1998 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1999 errmsg("type %s is not composite",
2000 format_type_be(type_id))));
2001 tupDesc = typentry->tupDesc;
2002 }
2003 else
2004 tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, noError);
2005 if (tupDesc != NULL)
2006 PinTupleDesc(tupDesc);
2007 return tupDesc;
2008}
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:1938
#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 1938 of file typcache.c.

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

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", NULL);
956
957 Assert(in_progress_offset + 1 == in_progress_list_len);
959
961
962 return typentry;
963}
#define NameStr(name)
Definition: c.h:751
#define MemSet(start, val, len)
Definition: c.h:1019
#define OidIsValid(objectId)
Definition: c.h:774
uint32 get_hash_value(HTAB *hashp, const void *keyPtr)
Definition: dynahash.c:908
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:2344
#define INJECTION_POINT(name, arg)
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
Definition: inval.c:1854
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1812
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1331
Oid get_opclass_family(Oid opclass)
Definition: lsyscache.c:1309
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition: lsyscache.c:889
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1452
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:168
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition: lsyscache.c:2705
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1229
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1610
#define BTORDER_PROC
Definition: nbtree.h:717
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:262
uint64_t Datum
Definition: postgres.h:70
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
#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 typelem
Definition: typcache.h:46
Oid hash_extended_proc
Definition: typcache.h:67
Oid typsubscript
Definition: typcache.h:45
FmgrInfo cmp_proc_finfo
Definition: typcache.h:77
Oid hash_proc
Definition: typcache.h:66
Oid lt_opr
Definition: typcache.h:63
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 hash_opf
Definition: typcache.h:60
Oid btree_opf
Definition: typcache.h:58
Oid typrelid
Definition: typcache.h:44
Oid btree_opintype
Definition: typcache.h:59
Oid cmp_proc
Definition: typcache.h:65
struct TypeCacheEntry * nextDomain
Definition: typcache.h:134
bool typbyval
Definition: typcache.h:40
int16 typlen
Definition: typcache.h:39
Oid typarray
Definition: typcache.h:47
Oid hash_opintype
Definition: typcache.h:61
Oid typcollation
Definition: typcache.h:48
char typstorage
Definition: typcache.h:42
Oid eq_opr
Definition: typcache.h:62
Oid gt_opr
Definition: typcache.h:64
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:264
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:220
#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:1714
static void insert_rel_type_cache_if_needed(TypeCacheEntry *typentry)
Definition: typcache.c:3074
static bool record_fields_have_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1593
static HTAB * RelIdToTypeIdCacheHash
Definition: typcache.c:87
static bool record_fields_have_extended_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1601
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:1754
static bool record_fields_have_equality(TypeCacheEntry *typentry)
Definition: typcache.c:1577
#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:1539
static bool array_element_has_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1531
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:1762
static int in_progress_list_len
Definition: typcache.c:227
static bool array_element_has_equality(TypeCacheEntry *typentry)
Definition: typcache.c:1515
static void load_rangetype_info(TypeCacheEntry *typentry)
Definition: typcache.c:1003
static bool range_element_has_extended_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1722
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:2515
static void TypeCacheConstrCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: typcache.c:2610
static void TypeCacheOpcCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: typcache.c:2572
static void load_domaintype_info(TypeCacheEntry *typentry)
Definition: typcache.c:1083
static void TypeCacheRelCallback(Datum arg, Oid relid)
Definition: typcache.c:2419
static bool array_element_has_compare(TypeCacheEntry *typentry)
Definition: typcache.c:1523
#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:1585
#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 ( SharedRecordTypmodRegistryregistry )

Definition at line 2295 of file typcache.c.

2296{
2297 MemoryContext old_context;
2298 dshash_table *record_table;
2299 dshash_table *typmod_table;
2300
2302
2303 /* We can't already be attached to a shared registry. */
2304 Assert(CurrentSession != NULL);
2305 Assert(CurrentSession->segment != NULL);
2306 Assert(CurrentSession->area != NULL);
2310
2311 /*
2312 * We can't already have typmods in our local cache, because they'd clash
2313 * with those imported by SharedRecordTypmodRegistryInit. This should be
2314 * a freshly started parallel worker. If we ever support worker
2315 * recycling, a worker would need to zap its local cache in between
2316 * servicing different queries, in order to be able to call this and
2317 * synchronize typmods with a new leader; but that's problematic because
2318 * we can't be very sure that record-typmod-related state hasn't escaped
2319 * to anywhere else in the process.
2320 */
2322
2324
2325 /* Attach to the two hash tables. */
2326 record_table = dshash_attach(CurrentSession->area,
2328 registry->record_table_handle,
2330 typmod_table = dshash_attach(CurrentSession->area,
2332 registry->typmod_table_handle,
2333 NULL);
2334
2335 MemoryContextSwitchTo(old_context);
2336
2337 /*
2338 * Set up detach hook to run at worker exit. Currently this is the same
2339 * as the leader's detach hook, but in future they might need to be
2340 * different.
2341 */
2344 PointerGetDatum(registry));
2345
2346 /*
2347 * Set up the session state that will tell assign_record_type_typmod and
2348 * lookup_rowtype_tupdesc_internal about the shared registry.
2349 */
2351 CurrentSession->shared_record_table = record_table;
2352 CurrentSession->shared_typmod_table = typmod_table;
2353}
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:166
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:332
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:3054
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 2174 of file typcache.c.

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

Referenced by GetSessionDsmHandle().

SharedRecordTypmodRegistryInit()

void SharedRecordTypmodRegistryInit ( SharedRecordTypmodRegistryregistry,
dsm_segmentsegment,
dsa_areaarea 
)

Definition at line 2196 of file typcache.c.

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

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

Definition at line 1439 of file typcache.c.

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

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

AltStyle によって変換されたページ (->オリジナル) /