PostgreSQL Source Code  git master
typcache.c File Reference
#include "postgres.h"
#include <limits.h>
#include "access/hash.h"
#include "access/htup_details.h"
#include "access/nbtree.h"
#include "access/parallel.h"
#include "access/relation.h"
#include "access/session.h"
#include "access/table.h"
#include "catalog/pg_am.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_enum.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_range.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "common/int.h"
#include "executor/executor.h"
#include "lib/dshash.h"
#include "optimizer/optimizer.h"
#include "port/pg_bitutils.h"
#include "storage/lwlock.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
Include dependency graph for typcache.c:

Go to the source code of this file.

Data Structures

struct  DomainConstraintCache
 
struct  EnumItem
 
struct  TypeCacheEnumData
 
struct  RecordCacheEntry
 
struct  SharedRecordTypmodRegistry
 
struct  SharedRecordTableKey
 
struct  SharedRecordTableEntry
 
struct  SharedTypmodTableEntry
 
struct  RecordCacheArrayEntry
 

Macros

#define TCFLAGS_HAVE_PG_TYPE_DATA   0x000001
 
#define TCFLAGS_CHECKED_BTREE_OPCLASS   0x000002
 
#define TCFLAGS_CHECKED_HASH_OPCLASS   0x000004
 
#define TCFLAGS_CHECKED_EQ_OPR   0x000008
 
#define TCFLAGS_CHECKED_LT_OPR   0x000010
 
#define TCFLAGS_CHECKED_GT_OPR   0x000020
 
#define TCFLAGS_CHECKED_CMP_PROC   0x000040
 
#define TCFLAGS_CHECKED_HASH_PROC   0x000080
 
#define TCFLAGS_CHECKED_HASH_EXTENDED_PROC   0x000100
 
#define TCFLAGS_CHECKED_ELEM_PROPERTIES   0x000200
 
#define TCFLAGS_HAVE_ELEM_EQUALITY   0x000400
 
#define TCFLAGS_HAVE_ELEM_COMPARE   0x000800
 
#define TCFLAGS_HAVE_ELEM_HASHING   0x001000
 
#define TCFLAGS_HAVE_ELEM_EXTENDED_HASHING   0x002000
 
#define TCFLAGS_CHECKED_FIELD_PROPERTIES   0x004000
 
#define TCFLAGS_HAVE_FIELD_EQUALITY   0x008000
 
#define TCFLAGS_HAVE_FIELD_COMPARE   0x010000
 
#define TCFLAGS_HAVE_FIELD_HASHING   0x020000
 
#define TCFLAGS_HAVE_FIELD_EXTENDED_HASHING   0x040000
 
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS   0x080000
 
#define TCFLAGS_DOMAIN_BASE_IS_COMPOSITE   0x100000
 
#define TCFLAGS_OPERATOR_FLAGS
 

Typedefs

typedef struct TypeCacheEnumData TypeCacheEnumData
 
typedef struct RecordCacheEntry RecordCacheEntry
 
typedef struct SharedRecordTableKey SharedRecordTableKey
 
typedef struct SharedRecordTableEntry SharedRecordTableEntry
 
typedef struct SharedTypmodTableEntry SharedTypmodTableEntry
 
typedef struct RecordCacheArrayEntry RecordCacheArrayEntry
 

Functions

static int shared_record_table_compare (const void *a, const void *b, size_t size, void *arg)
 
static uint32 shared_record_table_hash (const void *a, size_t size, void *arg)
 
static void load_typcache_tupdesc (TypeCacheEntry *typentry)
 
static void load_rangetype_info (TypeCacheEntry *typentry)
 
static void load_multirangetype_info (TypeCacheEntry *typentry)
 
static void load_domaintype_info (TypeCacheEntry *typentry)
 
static int dcs_cmp (const void *a, const void *b)
 
static void decr_dcc_refcount (DomainConstraintCache *dcc)
 
static void dccref_deletion_callback (void *arg)
 
static Listprep_domain_constraints (List *constraints, MemoryContext execctx)
 
static bool array_element_has_equality (TypeCacheEntry *typentry)
 
static bool array_element_has_compare (TypeCacheEntry *typentry)
 
static bool array_element_has_hashing (TypeCacheEntry *typentry)
 
static bool array_element_has_extended_hashing (TypeCacheEntry *typentry)
 
static void cache_array_element_properties (TypeCacheEntry *typentry)
 
static bool record_fields_have_equality (TypeCacheEntry *typentry)
 
static bool record_fields_have_compare (TypeCacheEntry *typentry)
 
static bool record_fields_have_hashing (TypeCacheEntry *typentry)
 
static bool record_fields_have_extended_hashing (TypeCacheEntry *typentry)
 
static void cache_record_field_properties (TypeCacheEntry *typentry)
 
static bool range_element_has_hashing (TypeCacheEntry *typentry)
 
static bool range_element_has_extended_hashing (TypeCacheEntry *typentry)
 
static void cache_range_element_properties (TypeCacheEntry *typentry)
 
static bool multirange_element_has_hashing (TypeCacheEntry *typentry)
 
static bool multirange_element_has_extended_hashing (TypeCacheEntry *typentry)
 
static void cache_multirange_element_properties (TypeCacheEntry *typentry)
 
static void TypeCacheRelCallback (Datum arg, Oid relid)
 
static void TypeCacheTypCallback (Datum arg, int cacheid, uint32 hashvalue)
 
static void TypeCacheOpcCallback (Datum arg, int cacheid, uint32 hashvalue)
 
static void TypeCacheConstrCallback (Datum arg, int cacheid, uint32 hashvalue)
 
static void load_enum_cache_data (TypeCacheEntry *tcache)
 
static EnumItemfind_enumitem (TypeCacheEnumData *enumdata, Oid arg)
 
static int enum_oid_cmp (const void *left, const void *right)
 
static void shared_record_typmod_registry_detach (dsm_segment *segment, Datum datum)
 
static TupleDesc find_or_make_matching_shared_tupledesc (TupleDesc tupdesc)
 
static dsa_pointer share_tupledesc (dsa_area *area, TupleDesc tupdesc, uint32 typmod)
 
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)
 
static void ensure_record_cache_typmod_slot_exists (int32 typmod)
 
static TupleDesc lookup_rowtype_tupdesc_internal (Oid type_id, int32 typmod, bool noError)
 
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)
 
static uint32 record_type_typmod_hash (const void *data, size_t size)
 
static int record_type_typmod_compare (const void *a, const void *b, size_t size)
 
void assign_record_type_typmod (TupleDesc tupDesc)
 
uint64 assign_record_type_identifier (Oid type_id, int32 typmod)
 
size_t SharedRecordTypmodRegistryEstimate (void)
 
void SharedRecordTypmodRegistryInit (SharedRecordTypmodRegistry *registry, dsm_segment *segment, dsa_area *area)
 
void SharedRecordTypmodRegistryAttach (SharedRecordTypmodRegistry *registry)
 
static bool enum_known_sorted (TypeCacheEnumData *enumdata, Oid arg)
 
int compare_values_of_enum (TypeCacheEntry *tcache, Oid arg1, Oid arg2)
 

Variables

static HTABTypeCacheHash = NULL
 
static TypeCacheEntryfirstDomainTypeEntry = NULL
 
static const dshash_parameters srtr_record_table_params
 
static const dshash_parameters srtr_typmod_table_params
 
static HTABRecordCacheHash = NULL
 
static RecordCacheArrayEntryRecordCacheArray = NULL
 
static int32 RecordCacheArrayLen = 0
 
static int32 NextRecordTypmod = 0
 
static uint64 tupledesc_id_counter = INVALID_TUPLEDESC_IDENTIFIER
 

Macro Definition Documentation

◆ TCFLAGS_CHECKED_BTREE_OPCLASS

#define TCFLAGS_CHECKED_BTREE_OPCLASS   0x000002

Definition at line 86 of file typcache.c.

◆ TCFLAGS_CHECKED_CMP_PROC

#define TCFLAGS_CHECKED_CMP_PROC   0x000040

Definition at line 91 of file typcache.c.

◆ TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS

#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS   0x080000

Definition at line 104 of file typcache.c.

◆ TCFLAGS_CHECKED_ELEM_PROPERTIES

#define TCFLAGS_CHECKED_ELEM_PROPERTIES   0x000200

Definition at line 94 of file typcache.c.

◆ TCFLAGS_CHECKED_EQ_OPR

#define TCFLAGS_CHECKED_EQ_OPR   0x000008

Definition at line 88 of file typcache.c.

◆ TCFLAGS_CHECKED_FIELD_PROPERTIES

#define TCFLAGS_CHECKED_FIELD_PROPERTIES   0x004000

Definition at line 99 of file typcache.c.

◆ TCFLAGS_CHECKED_GT_OPR

#define TCFLAGS_CHECKED_GT_OPR   0x000020

Definition at line 90 of file typcache.c.

◆ TCFLAGS_CHECKED_HASH_EXTENDED_PROC

#define TCFLAGS_CHECKED_HASH_EXTENDED_PROC   0x000100

Definition at line 93 of file typcache.c.

◆ TCFLAGS_CHECKED_HASH_OPCLASS

#define TCFLAGS_CHECKED_HASH_OPCLASS   0x000004

Definition at line 87 of file typcache.c.

◆ TCFLAGS_CHECKED_HASH_PROC

#define TCFLAGS_CHECKED_HASH_PROC   0x000080

Definition at line 92 of file typcache.c.

◆ TCFLAGS_CHECKED_LT_OPR

#define TCFLAGS_CHECKED_LT_OPR   0x000010

Definition at line 89 of file typcache.c.

◆ TCFLAGS_DOMAIN_BASE_IS_COMPOSITE

#define TCFLAGS_DOMAIN_BASE_IS_COMPOSITE   0x100000

Definition at line 105 of file typcache.c.

◆ TCFLAGS_HAVE_ELEM_COMPARE

#define TCFLAGS_HAVE_ELEM_COMPARE   0x000800

Definition at line 96 of file typcache.c.

◆ TCFLAGS_HAVE_ELEM_EQUALITY

#define TCFLAGS_HAVE_ELEM_EQUALITY   0x000400

Definition at line 95 of file typcache.c.

◆ TCFLAGS_HAVE_ELEM_EXTENDED_HASHING

#define TCFLAGS_HAVE_ELEM_EXTENDED_HASHING   0x002000

Definition at line 98 of file typcache.c.

◆ TCFLAGS_HAVE_ELEM_HASHING

#define TCFLAGS_HAVE_ELEM_HASHING   0x001000

Definition at line 97 of file typcache.c.

◆ TCFLAGS_HAVE_FIELD_COMPARE

#define TCFLAGS_HAVE_FIELD_COMPARE   0x010000

Definition at line 101 of file typcache.c.

◆ TCFLAGS_HAVE_FIELD_EQUALITY

#define TCFLAGS_HAVE_FIELD_EQUALITY   0x008000

Definition at line 100 of file typcache.c.

◆ TCFLAGS_HAVE_FIELD_EXTENDED_HASHING

#define TCFLAGS_HAVE_FIELD_EXTENDED_HASHING   0x040000

Definition at line 103 of file typcache.c.

◆ TCFLAGS_HAVE_FIELD_HASHING

#define TCFLAGS_HAVE_FIELD_HASHING   0x020000

Definition at line 102 of file typcache.c.

◆ TCFLAGS_HAVE_PG_TYPE_DATA

#define TCFLAGS_HAVE_PG_TYPE_DATA   0x000001

Definition at line 85 of file typcache.c.

◆ TCFLAGS_OPERATOR_FLAGS

#define TCFLAGS_OPERATOR_FLAGS
Value:
TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS | \
TCFLAGS_DOMAIN_BASE_IS_COMPOSITE))
#define TCFLAGS_HAVE_PG_TYPE_DATA
Definition: typcache.c:85

Definition at line 108 of file typcache.c.

Typedef Documentation

◆ RecordCacheArrayEntry

◆ RecordCacheEntry

◆ SharedRecordTableEntry

◆ SharedRecordTableKey

◆ SharedTypmodTableEntry

◆ TypeCacheEnumData

Function Documentation

◆ array_element_has_compare()

static bool array_element_has_compare ( TypeCacheEntry typentry)
static

Definition at line 1434 of file typcache.c.

1435 {
1436  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1438  return (typentry->flags & TCFLAGS_HAVE_ELEM_COMPARE) != 0;
1439 }
#define TCFLAGS_HAVE_ELEM_COMPARE
Definition: typcache.c:96
static void cache_array_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1458
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:94

References cache_array_element_properties(), TypeCacheEntry::flags, TCFLAGS_CHECKED_ELEM_PROPERTIES, and TCFLAGS_HAVE_ELEM_COMPARE.

Referenced by lookup_type_cache().

◆ array_element_has_equality()

static bool array_element_has_equality ( TypeCacheEntry typentry)
static

Definition at line 1426 of file typcache.c.

1427 {
1428  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1430  return (typentry->flags & TCFLAGS_HAVE_ELEM_EQUALITY) != 0;
1431 }
#define TCFLAGS_HAVE_ELEM_EQUALITY
Definition: typcache.c:95

References cache_array_element_properties(), TypeCacheEntry::flags, TCFLAGS_CHECKED_ELEM_PROPERTIES, and TCFLAGS_HAVE_ELEM_EQUALITY.

Referenced by lookup_type_cache().

◆ array_element_has_extended_hashing()

static bool array_element_has_extended_hashing ( TypeCacheEntry typentry)
static

Definition at line 1450 of file typcache.c.

1451 {
1452  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1454  return (typentry->flags & TCFLAGS_HAVE_ELEM_EXTENDED_HASHING) != 0;
1455 }
#define TCFLAGS_HAVE_ELEM_EXTENDED_HASHING
Definition: typcache.c:98

References cache_array_element_properties(), TypeCacheEntry::flags, TCFLAGS_CHECKED_ELEM_PROPERTIES, and TCFLAGS_HAVE_ELEM_EXTENDED_HASHING.

Referenced by lookup_type_cache().

◆ array_element_has_hashing()

static bool array_element_has_hashing ( TypeCacheEntry typentry)
static

Definition at line 1442 of file typcache.c.

1443 {
1444  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1446  return (typentry->flags & TCFLAGS_HAVE_ELEM_HASHING) != 0;
1447 }
#define TCFLAGS_HAVE_ELEM_HASHING
Definition: typcache.c:97

References cache_array_element_properties(), TypeCacheEntry::flags, TCFLAGS_CHECKED_ELEM_PROPERTIES, and TCFLAGS_HAVE_ELEM_HASHING.

Referenced by lookup_type_cache().

◆ assign_record_type_identifier()

uint64 assign_record_type_identifier ( Oid  type_id,
int32  typmod 
)

Definition at line 2044 of file typcache.c.

2045 {
2046  if (type_id != RECORDOID)
2047  {
2048  /*
2049  * It's a named composite type, so use the regular typcache.
2050  */
2051  TypeCacheEntry *typentry;
2052 
2053  typentry = lookup_type_cache(type_id, TYPECACHE_TUPDESC);
2054  if (typentry->tupDesc == NULL)
2055  ereport(ERROR,
2056  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2057  errmsg("type %s is not composite",
2058  format_type_be(type_id))));
2059  Assert(typentry->tupDesc_identifier != 0);
2060  return typentry->tupDesc_identifier;
2061  }
2062  else
2063  {
2064  /*
2065  * It's a transient record type, so look in our record-type table.
2066  */
2067  if (typmod >= 0 && typmod < RecordCacheArrayLen &&
2068  RecordCacheArray[typmod].tupdesc != NULL)
2069  {
2070  Assert(RecordCacheArray[typmod].id != 0);
2071  return RecordCacheArray[typmod].id;
2072  }
2073 
2074  /* For anonymous or unrecognized record type, generate a new ID */
2075  return ++tupledesc_id_counter;
2076  }
2077 }
int errcode(int sqlerrcode)
Definition: elog.c:860
int errmsg(const char *fmt,...)
Definition: elog.c:1075
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
Assert(fmt[strlen(fmt) - 1] !='\n')
uint64 tupDesc_identifier
Definition: typcache.h:90
TupleDesc tupDesc
Definition: typcache.h:89
static RecordCacheArrayEntry * RecordCacheArray
Definition: typcache.c:284
static int32 RecordCacheArrayLen
Definition: typcache.c:285
static uint64 tupledesc_id_counter
Definition: typcache.c:293
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:345
#define TYPECACHE_TUPDESC
Definition: typcache.h:145

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

1953 {
1954  RecordCacheEntry *recentry;
1955  TupleDesc entDesc;
1956  bool found;
1957  MemoryContext oldcxt;
1958 
1959  Assert(tupDesc->tdtypeid == RECORDOID);
1960 
1961  if (RecordCacheHash == NULL)
1962  {
1963  /* First time through: initialize the hash table */
1964  HASHCTL ctl;
1965 
1966  ctl.keysize = sizeof(TupleDesc); /* just the pointer */
1967  ctl.entrysize = sizeof(RecordCacheEntry);
1970  RecordCacheHash = hash_create("Record information cache", 64,
1971  &ctl,
1973 
1974  /* Also make sure CacheMemoryContext exists */
1975  if (!CacheMemoryContext)
1977  }
1978 
1979  /*
1980  * Find a hashtable entry for this tuple descriptor. We don't use
1981  * HASH_ENTER yet, because if it's missing, we need to make sure that all
1982  * the allocations succeed before we create the new entry.
1983  */
1985  &tupDesc,
1986  HASH_FIND, &found);
1987  if (found && recentry->tupdesc != NULL)
1988  {
1989  tupDesc->tdtypmod = recentry->tupdesc->tdtypmod;
1990  return;
1991  }
1992 
1993  /* Not present, so need to manufacture an entry */
1995 
1996  /* Look in the SharedRecordTypmodRegistry, if attached */
1997  entDesc = find_or_make_matching_shared_tupledesc(tupDesc);
1998  if (entDesc == NULL)
1999  {
2000  /*
2001  * Make sure we have room before we CreateTupleDescCopy() or advance
2002  * NextRecordTypmod.
2003  */
2005 
2006  /* Reference-counted local cache only. */
2007  entDesc = CreateTupleDescCopy(tupDesc);
2008  entDesc->tdrefcount = 1;
2009  entDesc->tdtypmod = NextRecordTypmod++;
2010  }
2011  else
2012  {
2014  }
2015 
2016  RecordCacheArray[entDesc->tdtypmod].tupdesc = entDesc;
2017 
2018  /* Assign a unique tupdesc identifier, too. */
2020 
2021  /* Fully initialized; create the hash table entry */
2023  &tupDesc,
2024  HASH_ENTER, NULL);
2025  recentry->tupdesc = entDesc;
2026 
2027  /* Update the caller's tuple descriptor. */
2028  tupDesc->tdtypmod = entDesc->tdtypmod;
2029 
2030  MemoryContextSwitchTo(oldcxt);
2031 }
void CreateCacheMemoryContext(void)
Definition: catcache.c:668
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:953
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:350
@ 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:144
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
Size keysize
Definition: hsearch.h:75
HashValueFunc hash
Definition: hsearch.h:78
Size entrysize
Definition: hsearch.h:76
HashCompareFunc match
Definition: hsearch.h:80
TupleDesc tupdesc
Definition: typcache.c:160
int tdrefcount
Definition: tupdesc.h:84
int32 tdtypmod
Definition: tupdesc.h:83
Oid tdtypeid
Definition: tupdesc.h:82
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:133
struct TupleDescData * TupleDesc
Definition: tupdesc.h:89
static TupleDesc find_or_make_matching_shared_tupledesc(TupleDesc tupdesc)
Definition: typcache.c:2755
static int32 NextRecordTypmod
Definition: typcache.c:286
static HTAB * RecordCacheHash
Definition: typcache.c:275
struct RecordCacheEntry RecordCacheEntry
static int record_type_typmod_compare(const void *a, const void *b, size_t size)
Definition: typcache.c:1936
static void ensure_record_cache_typmod_slot_exists(int32 typmod)
Definition: typcache.c:1709
static uint32 record_type_typmod_hash(const void *data, size_t size)
Definition: typcache.c:1925

References Assert(), CacheMemoryContext, CreateCacheMemoryContext(), CreateTupleDescCopy(), ensure_record_cache_typmod_slot_exists(), HASHCTL::entrysize, find_or_make_matching_shared_tupledesc(), HASHCTL::hash, HASH_COMPARE, hash_create(), HASH_ELEM, HASH_ENTER, HASH_FIND, HASH_FUNCTION, hash_search(), RecordCacheArrayEntry::id, HASHCTL::keysize, HASHCTL::match, 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().

◆ cache_array_element_properties()

static void cache_array_element_properties ( TypeCacheEntry typentry)
static

Definition at line 1458 of file typcache.c.

1459 {
1460  Oid elem_type = get_base_element_type(typentry->type_id);
1461 
1462  if (OidIsValid(elem_type))
1463  {
1464  TypeCacheEntry *elementry;
1465 
1466  elementry = lookup_type_cache(elem_type,
1471  if (OidIsValid(elementry->eq_opr))
1472  typentry->flags |= TCFLAGS_HAVE_ELEM_EQUALITY;
1473  if (OidIsValid(elementry->cmp_proc))
1474  typentry->flags |= TCFLAGS_HAVE_ELEM_COMPARE;
1475  if (OidIsValid(elementry->hash_proc))
1476  typentry->flags |= TCFLAGS_HAVE_ELEM_HASHING;
1477  if (OidIsValid(elementry->hash_extended_proc))
1479  }
1481 }
#define OidIsValid(objectId)
Definition: c.h:764
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2787
unsigned int Oid
Definition: postgres_ext.h:31
Oid hash_extended_proc
Definition: typcache.h:66
#define TYPECACHE_EQ_OPR
Definition: typcache.h:137
#define TYPECACHE_HASH_EXTENDED_PROC
Definition: typcache.h:151
#define TYPECACHE_CMP_PROC
Definition: typcache.h:140
#define TYPECACHE_HASH_PROC
Definition: typcache.h:141

References TypeCacheEntry::cmp_proc, TypeCacheEntry::eq_opr, TypeCacheEntry::flags, get_base_element_type(), TypeCacheEntry::hash_extended_proc, TypeCacheEntry::hash_proc, lookup_type_cache(), OidIsValid, TCFLAGS_CHECKED_ELEM_PROPERTIES, TCFLAGS_HAVE_ELEM_COMPARE, TCFLAGS_HAVE_ELEM_EQUALITY, TCFLAGS_HAVE_ELEM_EXTENDED_HASHING, TCFLAGS_HAVE_ELEM_HASHING, TypeCacheEntry::type_id, TYPECACHE_CMP_PROC, TYPECACHE_EQ_OPR, TYPECACHE_HASH_EXTENDED_PROC, and TYPECACHE_HASH_PROC.

Referenced by array_element_has_compare(), array_element_has_equality(), array_element_has_extended_hashing(), and array_element_has_hashing().

◆ cache_multirange_element_properties()

static void cache_multirange_element_properties ( TypeCacheEntry typentry)
static

Definition at line 1681 of file typcache.c.

1682 {
1683  /* load up range link if we didn't already */
1684  if (typentry->rngtype == NULL &&
1685  typentry->typtype == TYPTYPE_MULTIRANGE)
1686  load_multirangetype_info(typentry);
1687 
1688  if (typentry->rngtype != NULL && typentry->rngtype->rngelemtype != NULL)
1689  {
1690  TypeCacheEntry *elementry;
1691 
1692  /* might need to calculate subtype's hash function properties */
1693  elementry = lookup_type_cache(typentry->rngtype->rngelemtype->type_id,
1696  if (OidIsValid(elementry->hash_proc))
1697  typentry->flags |= TCFLAGS_HAVE_ELEM_HASHING;
1698  if (OidIsValid(elementry->hash_extended_proc))
1700  }
1702 }
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:98
char typtype
Definition: typcache.h:43
struct TypeCacheEntry * rngtype
Definition: typcache.h:108
static void load_multirangetype_info(TypeCacheEntry *typentry)
Definition: typcache.c:971

References TypeCacheEntry::flags, TypeCacheEntry::hash_extended_proc, TypeCacheEntry::hash_proc, load_multirangetype_info(), lookup_type_cache(), OidIsValid, TypeCacheEntry::rngelemtype, TypeCacheEntry::rngtype, TCFLAGS_CHECKED_ELEM_PROPERTIES, TCFLAGS_HAVE_ELEM_EXTENDED_HASHING, TCFLAGS_HAVE_ELEM_HASHING, TypeCacheEntry::type_id, TYPECACHE_HASH_EXTENDED_PROC, TYPECACHE_HASH_PROC, and TypeCacheEntry::typtype.

Referenced by multirange_element_has_extended_hashing(), and multirange_element_has_hashing().

◆ cache_range_element_properties()

static void cache_range_element_properties ( TypeCacheEntry typentry)
static

Definition at line 1641 of file typcache.c.

1642 {
1643  /* load up subtype link if we didn't already */
1644  if (typentry->rngelemtype == NULL &&
1645  typentry->typtype == TYPTYPE_RANGE)
1646  load_rangetype_info(typentry);
1647 
1648  if (typentry->rngelemtype != NULL)
1649  {
1650  TypeCacheEntry *elementry;
1651 
1652  /* might need to calculate subtype's hash function properties */
1653  elementry = lookup_type_cache(typentry->rngelemtype->type_id,
1656  if (OidIsValid(elementry->hash_proc))
1657  typentry->flags |= TCFLAGS_HAVE_ELEM_HASHING;
1658  if (OidIsValid(elementry->hash_extended_proc))
1660  }
1662 }
static void load_rangetype_info(TypeCacheEntry *typentry)
Definition: typcache.c:913

References TypeCacheEntry::flags, TypeCacheEntry::hash_extended_proc, TypeCacheEntry::hash_proc, load_rangetype_info(), lookup_type_cache(), OidIsValid, TypeCacheEntry::rngelemtype, TCFLAGS_CHECKED_ELEM_PROPERTIES, TCFLAGS_HAVE_ELEM_EXTENDED_HASHING, TCFLAGS_HAVE_ELEM_HASHING, TypeCacheEntry::type_id, TYPECACHE_HASH_EXTENDED_PROC, TYPECACHE_HASH_PROC, and TypeCacheEntry::typtype.

Referenced by range_element_has_extended_hashing(), and range_element_has_hashing().

◆ cache_record_field_properties()

static void cache_record_field_properties ( TypeCacheEntry typentry)
static

Definition at line 1520 of file typcache.c.

1521 {
1522  /*
1523  * For type RECORD, we can't really tell what will work, since we don't
1524  * have access here to the specific anonymous type. Just assume that
1525  * equality and comparison will (we may get a failure at runtime). We
1526  * could also claim that hashing works, but then if code that has the
1527  * option between a comparison-based (sort-based) and a hash-based plan
1528  * chooses hashing, stuff could fail that would otherwise work if it chose
1529  * a comparison-based plan. In practice more types support comparison
1530  * than hashing.
1531  */
1532  if (typentry->type_id == RECORDOID)
1533  {
1534  typentry->flags |= (TCFLAGS_HAVE_FIELD_EQUALITY |
1536  }
1537  else if (typentry->typtype == TYPTYPE_COMPOSITE)
1538  {
1539  TupleDesc tupdesc;
1540  int newflags;
1541  int i;
1542 
1543  /* Fetch composite type's tupdesc if we don't have it already */
1544  if (typentry->tupDesc == NULL)
1545  load_typcache_tupdesc(typentry);
1546  tupdesc = typentry->tupDesc;
1547 
1548  /* Must bump the refcount while we do additional catalog lookups */
1549  IncrTupleDescRefCount(tupdesc);
1550 
1551  /* Have each property if all non-dropped fields have the property */
1552  newflags = (TCFLAGS_HAVE_FIELD_EQUALITY |
1556  for (i = 0; i < tupdesc->natts; i++)
1557  {
1558  TypeCacheEntry *fieldentry;
1559  Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
1560 
1561  if (attr->attisdropped)
1562  continue;
1563 
1564  fieldentry = lookup_type_cache(attr->atttypid,
1569  if (!OidIsValid(fieldentry->eq_opr))
1570  newflags &= ~TCFLAGS_HAVE_FIELD_EQUALITY;
1571  if (!OidIsValid(fieldentry->cmp_proc))
1572  newflags &= ~TCFLAGS_HAVE_FIELD_COMPARE;
1573  if (!OidIsValid(fieldentry->hash_proc))
1574  newflags &= ~TCFLAGS_HAVE_FIELD_HASHING;
1575  if (!OidIsValid(fieldentry->hash_extended_proc))
1577 
1578  /* We can drop out of the loop once we disprove all bits */
1579  if (newflags == 0)
1580  break;
1581  }
1582  typentry->flags |= newflags;
1583 
1584  DecrTupleDescRefCount(tupdesc);
1585  }
1586  else if (typentry->typtype == TYPTYPE_DOMAIN)
1587  {
1588  /* If it's domain over composite, copy base type's properties */
1589  TypeCacheEntry *baseentry;
1590 
1591  /* load up basetype info if we didn't already */
1592  if (typentry->domainBaseType == InvalidOid)
1593  {
1594  typentry->domainBaseTypmod = -1;
1595  typentry->domainBaseType =
1596  getBaseTypeAndTypmod(typentry->type_id,
1597  &typentry->domainBaseTypmod);
1598  }
1599  baseentry = lookup_type_cache(typentry->domainBaseType,
1604  if (baseentry->typtype == TYPTYPE_COMPOSITE)
1605  {
1607  typentry->flags |= baseentry->flags & (TCFLAGS_HAVE_FIELD_EQUALITY |
1611  }
1612  }
1614 }
int i
Definition: isn.c:73
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition: lsyscache.c:2493
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
#define InvalidOid
Definition: postgres_ext.h:36
int32 domainBaseTypmod
Definition: typcache.h:115
Oid domainBaseType
Definition: typcache.h:114
void DecrTupleDescRefCount(TupleDesc tupdesc)
Definition: tupdesc.c:406
void IncrTupleDescRefCount(TupleDesc tupdesc)
Definition: tupdesc.c:388
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define TCFLAGS_CHECKED_FIELD_PROPERTIES
Definition: typcache.c:99
#define TCFLAGS_HAVE_FIELD_COMPARE
Definition: typcache.c:101
#define TCFLAGS_DOMAIN_BASE_IS_COMPOSITE
Definition: typcache.c:105
#define TCFLAGS_HAVE_FIELD_EQUALITY
Definition: typcache.c:100
#define TCFLAGS_HAVE_FIELD_EXTENDED_HASHING
Definition: typcache.c:103
#define TCFLAGS_HAVE_FIELD_HASHING
Definition: typcache.c:102
static void load_typcache_tupdesc(TypeCacheEntry *typentry)
Definition: typcache.c:879

References TypeCacheEntry::cmp_proc, DecrTupleDescRefCount(), TypeCacheEntry::domainBaseType, TypeCacheEntry::domainBaseTypmod, TypeCacheEntry::eq_opr, TypeCacheEntry::flags, getBaseTypeAndTypmod(), TypeCacheEntry::hash_extended_proc, TypeCacheEntry::hash_proc, i, IncrTupleDescRefCount(), InvalidOid, load_typcache_tupdesc(), lookup_type_cache(), TupleDescData::natts, OidIsValid, TCFLAGS_CHECKED_FIELD_PROPERTIES, TCFLAGS_DOMAIN_BASE_IS_COMPOSITE, TCFLAGS_HAVE_FIELD_COMPARE, TCFLAGS_HAVE_FIELD_EQUALITY, TCFLAGS_HAVE_FIELD_EXTENDED_HASHING, TCFLAGS_HAVE_FIELD_HASHING, TypeCacheEntry::tupDesc, TupleDescAttr, TypeCacheEntry::type_id, TYPECACHE_CMP_PROC, TYPECACHE_EQ_OPR, TYPECACHE_HASH_EXTENDED_PROC, TYPECACHE_HASH_PROC, and TypeCacheEntry::typtype.

Referenced by record_fields_have_compare(), record_fields_have_equality(), record_fields_have_extended_hashing(), and record_fields_have_hashing().

◆ compare_values_of_enum()

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

Definition at line 2476 of file typcache.c.

2477 {
2478  TypeCacheEnumData *enumdata;
2479  EnumItem *item1;
2480  EnumItem *item2;
2481 
2482  /*
2483  * Equal OIDs are certainly equal --- this case was probably handled by
2484  * our caller, but we may as well check.
2485  */
2486  if (arg1 == arg2)
2487  return 0;
2488 
2489  /* Load up the cache if first time through */
2490  if (tcache->enumData == NULL)
2491  load_enum_cache_data(tcache);
2492  enumdata = tcache->enumData;
2493 
2494  /*
2495  * If both OIDs are known-sorted, we can just compare them directly.
2496  */
2497  if (enum_known_sorted(enumdata, arg1) &&
2498  enum_known_sorted(enumdata, arg2))
2499  {
2500  if (arg1 < arg2)
2501  return -1;
2502  else
2503  return 1;
2504  }
2505 
2506  /*
2507  * Slow path: we have to identify their actual sort-order positions.
2508  */
2509  item1 = find_enumitem(enumdata, arg1);
2510  item2 = find_enumitem(enumdata, arg2);
2511 
2512  if (item1 == NULL || item2 == NULL)
2513  {
2514  /*
2515  * We couldn't find one or both values. That means the enum has
2516  * changed under us, so re-initialize the cache and try again. We
2517  * don't bother retrying the known-sorted case in this path.
2518  */
2519  load_enum_cache_data(tcache);
2520  enumdata = tcache->enumData;
2521 
2522  item1 = find_enumitem(enumdata, arg1);
2523  item2 = find_enumitem(enumdata, arg2);
2524 
2525  /*
2526  * If we still can't find the values, complain: we must have corrupt
2527  * data.
2528  */
2529  if (item1 == NULL)
2530  elog(ERROR, "enum value %u not found in cache for enum %s",
2531  arg1, format_type_be(tcache->type_id));
2532  if (item2 == NULL)
2533  elog(ERROR, "enum value %u not found in cache for enum %s",
2534  arg2, format_type_be(tcache->type_id));
2535  }
2536 
2537  if (item1->sort_order < item2->sort_order)
2538  return -1;
2539  else if (item1->sort_order > item2->sort_order)
2540  return 1;
2541  else
2542  return 0;
2543 }
float4 sort_order
Definition: typcache.c:136
struct TypeCacheEnumData * enumData
Definition: typcache.h:130
static void load_enum_cache_data(TypeCacheEntry *tcache)
Definition: typcache.c:2549
static EnumItem * find_enumitem(TypeCacheEnumData *enumdata, Oid arg)
Definition: typcache.c:2704
static bool enum_known_sorted(TypeCacheEnumData *enumdata, Oid arg)
Definition: typcache.c:2447

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

◆ dccref_deletion_callback()

static void dccref_deletion_callback ( void *  arg)
static

Definition at line 1253 of file typcache.c.

1254 {
1256  DomainConstraintCache *dcc = ref->dcc;
1257 
1258  /* Paranoia --- be sure link is nulled before trying to release */
1259  if (dcc)
1260  {
1261  ref->constraints = NIL;
1262  ref->dcc = NULL;
1263  decr_dcc_refcount(dcc);
1264  }
1265 }
void * arg
#define NIL
Definition: pg_list.h:68
DomainConstraintCache * dcc
Definition: typcache.h:172
static void decr_dcc_refcount(DomainConstraintCache *dcc)
Definition: typcache.c:1242

References arg, DomainConstraintRef::constraints, DomainConstraintRef::dcc, decr_dcc_refcount(), and NIL.

Referenced by InitDomainConstraintRef().

◆ dcs_cmp()

static int dcs_cmp ( const void *  a,
const void *  b 
)
static

Definition at line 1229 of file typcache.c.

1230 {
1231  const DomainConstraintState *const *ca = (const DomainConstraintState *const *) a;
1232  const DomainConstraintState *const *cb = (const DomainConstraintState *const *) b;
1233 
1234  return strcmp((*ca)->name, (*cb)->name);
1235 }
int b
Definition: isn.c:70
int a
Definition: isn.c:69

References a, and b.

Referenced by load_domaintype_info().

◆ decr_dcc_refcount()

static void decr_dcc_refcount ( DomainConstraintCache dcc)
static

Definition at line 1242 of file typcache.c.

1243 {
1244  Assert(dcc->dccRefCount > 0);
1245  if (--(dcc->dccRefCount) <= 0)
1247 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:403
MemoryContext dccContext
Definition: typcache.c:128

References Assert(), DomainConstraintCache::dccContext, DomainConstraintCache::dccRefCount, and MemoryContextDelete().

Referenced by dccref_deletion_callback(), load_domaintype_info(), and UpdateDomainConstraintRef().

◆ DomainHasConstraints()

bool DomainHasConstraints ( Oid  type_id)

Definition at line 1399 of file typcache.c.

1400 {
1401  TypeCacheEntry *typentry;
1402 
1403  /*
1404  * Note: a side effect is to cause the typcache's domain data to become
1405  * valid. This is fine since we'll likely need it soon if there is any.
1406  */
1407  typentry = lookup_type_cache(type_id, TYPECACHE_DOMAIN_CONSTR_INFO);
1408 
1409  return (typentry->domainData != NULL);
1410 }
DomainConstraintCache * domainData
Definition: typcache.h:121
#define TYPECACHE_DOMAIN_CONSTR_INFO
Definition: typcache.h:150

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

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

◆ ensure_record_cache_typmod_slot_exists()

static void ensure_record_cache_typmod_slot_exists ( int32  typmod)
static

Definition at line 1709 of file typcache.c.

1710 {
1711  if (RecordCacheArray == NULL)
1712  {
1715  64 * sizeof(RecordCacheArrayEntry));
1716  RecordCacheArrayLen = 64;
1717  }
1718 
1719  if (typmod >= RecordCacheArrayLen)
1720  {
1721  int32 newlen = pg_nextpower2_32(typmod + 1);
1722 
1726  newlen);
1727  RecordCacheArrayLen = newlen;
1728  }
1729 }
signed int int32
Definition: c.h:483
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1077
#define repalloc0_array(pointer, type, oldcount, count)
Definition: palloc.h:109
static uint32 pg_nextpower2_32(uint32 num)
Definition: pg_bitutils.h:189

References CacheMemoryContext, MemoryContextAllocZero(), pg_nextpower2_32(), RecordCacheArray, RecordCacheArrayLen, and repalloc0_array.

Referenced by assign_record_type_typmod(), and lookup_rowtype_tupdesc_internal().

◆ enum_known_sorted()

static bool enum_known_sorted ( TypeCacheEnumData enumdata,
Oid  arg 
)
inlinestatic

Definition at line 2447 of file typcache.c.

2448 {
2449  Oid offset;
2450 
2451  if (arg < enumdata->bitmap_base)
2452  return false;
2453  offset = arg - enumdata->bitmap_base;
2454  if (offset > (Oid) INT_MAX)
2455  return false;
2456  return bms_is_member((int) offset, enumdata->sorted_values);
2457 }
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:523
Bitmapset * sorted_values
Definition: typcache.c:142

References arg, TypeCacheEnumData::bitmap_base, bms_is_member(), and TypeCacheEnumData::sorted_values.

Referenced by compare_values_of_enum().

◆ enum_oid_cmp()

static int enum_oid_cmp ( const void *  left,
const void *  right 
)
static

Definition at line 2721 of file typcache.c.

2722 {
2723  const EnumItem *l = (const EnumItem *) left;
2724  const EnumItem *r = (const EnumItem *) right;
2725 
2726  return pg_cmp_u32(l->enum_oid, r->enum_oid);
2727 }
static int pg_cmp_u32(uint32 a, uint32 b)
Definition: int.h:489
Oid enum_oid
Definition: typcache.c:135

References EnumItem::enum_oid, and pg_cmp_u32().

Referenced by find_enumitem(), and load_enum_cache_data().

◆ find_enumitem()

static EnumItem * find_enumitem ( TypeCacheEnumData enumdata,
Oid  arg 
)
static

Definition at line 2704 of file typcache.c.

2705 {
2706  EnumItem srch;
2707 
2708  /* On some versions of Solaris, bsearch of zero items dumps core */
2709  if (enumdata->num_values <= 0)
2710  return NULL;
2711 
2712  srch.enum_oid = arg;
2713  return bsearch(&srch, enumdata->enum_values, enumdata->num_values,
2714  sizeof(EnumItem), enum_oid_cmp);
2715 }
EnumItem enum_values[FLEXIBLE_ARRAY_MEMBER]
Definition: typcache.c:144
static int enum_oid_cmp(const void *left, const void *right)
Definition: typcache.c:2721

References arg, EnumItem::enum_oid, enum_oid_cmp(), TypeCacheEnumData::enum_values, and TypeCacheEnumData::num_values.

Referenced by compare_values_of_enum().

◆ find_or_make_matching_shared_tupledesc()

static TupleDesc find_or_make_matching_shared_tupledesc ( TupleDesc  tupdesc)
static

Definition at line 2755 of file typcache.c.

2756 {
2757  TupleDesc result;
2759  SharedRecordTableEntry *record_table_entry;
2760  SharedTypmodTableEntry *typmod_table_entry;
2761  dsa_pointer shared_dp;
2762  bool found;
2763  uint32 typmod;
2764 
2765  /* If not even attached, nothing to do. */
2767  return NULL;
2768 
2769  /* Try to find a matching tuple descriptor in the record table. */
2770  key.shared = false;
2771  key.u.local_tupdesc = tupdesc;
2772  record_table_entry = (SharedRecordTableEntry *)
2774  if (record_table_entry)
2775  {
2776  Assert(record_table_entry->key.shared);
2778  record_table_entry);
2779  result = (TupleDesc)
2781  record_table_entry->key.u.shared_tupdesc);
2782  Assert(result->tdrefcount == -1);
2783 
2784  return result;
2785  }
2786 
2787  /* Allocate a new typmod number. This will be wasted if we error out. */
2788  typmod = (int)
2790  1);
2791 
2792  /* Copy the TupleDesc into shared memory. */
2793  shared_dp = share_tupledesc(CurrentSession->area, tupdesc, typmod);
2794 
2795  /*
2796  * Create an entry in the typmod table so that others will understand this
2797  * typmod number.
2798  */
2799  PG_TRY();
2800  {
2801  typmod_table_entry = (SharedTypmodTableEntry *)
2803  &typmod, &found);
2804  if (found)
2805  elog(ERROR, "cannot create duplicate shared record typmod");
2806  }
2807  PG_CATCH();
2808  {
2809  dsa_free(CurrentSession->area, shared_dp);
2810  PG_RE_THROW();
2811  }
2812  PG_END_TRY();
2813  typmod_table_entry->typmod = typmod;
2814  typmod_table_entry->shared_tupdesc = shared_dp;
2816  typmod_table_entry);
2817 
2818  /*
2819  * Finally create an entry in the record table so others with matching
2820  * tuple descriptors can reuse the typmod.
2821  */
2822  record_table_entry = (SharedRecordTableEntry *)
2824  &found);
2825  if (found)
2826  {
2827  /*
2828  * Someone concurrently inserted a matching tuple descriptor since the
2829  * first time we checked. Use that one instead.
2830  */
2832  record_table_entry);
2833 
2834  /* Might as well free up the space used by the one we created. */
2836  &typmod);
2837  Assert(found);
2838  dsa_free(CurrentSession->area, shared_dp);
2839 
2840  /* Return the one we found. */
2841  Assert(record_table_entry->key.shared);
2842  result = (TupleDesc)
2844  record_table_entry->key.u.shared_tupdesc);
2845  Assert(result->tdrefcount == -1);
2846 
2847  return result;
2848  }
2849 
2850  /* Store it and return it. */
2851  record_table_entry->key.shared = true;
2852  record_table_entry->key.u.shared_tupdesc = shared_dp;
2854  record_table_entry);
2855  result = (TupleDesc)
2856  dsa_get_address(CurrentSession->area, shared_dp);
2857  Assert(result->tdrefcount == -1);
2858 
2859  return result;
2860 }
static uint32 pg_atomic_fetch_add_u32(volatile pg_atomic_uint32 *ptr, int32 add_)
Definition: atomics.h:323
unsigned int uint32
Definition: c.h:495
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:957
void dsa_free(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:841
uint64 dsa_pointer
Definition: dsa.h:62
bool dshash_delete_key(dshash_table *hash_table, const void *key)
Definition: dshash.c:503
void dshash_release_lock(dshash_table *hash_table, void *entry)
Definition: dshash.c:558
void * dshash_find(dshash_table *hash_table, const void *key, bool exclusive)
Definition: dshash.c:390
void * dshash_find_or_insert(dshash_table *hash_table, const void *key, bool *found)
Definition: dshash.c:433
#define PG_RE_THROW()
Definition: elog.h:411
#define PG_TRY(...)
Definition: elog.h:370
#define PG_END_TRY(...)
Definition: elog.h:395
#define PG_CATCH(...)
Definition: elog.h:380
Session * CurrentSession
Definition: session.c:48
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
SharedRecordTableKey key
Definition: typcache.c:199
union SharedRecordTableKey::@30 u
dsa_pointer shared_tupdesc
Definition: typcache.c:188
pg_atomic_uint32 next_typmod
Definition: typcache.c:174
dsa_pointer shared_tupdesc
Definition: typcache.c:209
static dsa_pointer share_tupledesc(dsa_area *area, TupleDesc tupdesc, uint32 typmod)
Definition: typcache.c:2734

References Session::area, Assert(), CurrentSession, dsa_free(), dsa_get_address(), dshash_delete_key(), dshash_find(), dshash_find_or_insert(), dshash_release_lock(), elog(), ERROR, SharedRecordTableEntry::key, sort-test::key, SharedRecordTypmodRegistry::next_typmod, pg_atomic_fetch_add_u32(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, share_tupledesc(), SharedRecordTableKey::shared, Session::shared_record_table, SharedRecordTableKey::shared_tupdesc, SharedTypmodTableEntry::shared_tupdesc, Session::shared_typmod_registry, Session::shared_typmod_table, TupleDescData::tdrefcount, SharedTypmodTableEntry::typmod, and SharedRecordTableKey::u.

Referenced by assign_record_type_typmod().

◆ InitDomainConstraintRef()

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

Definition at line 1312 of file typcache.c.

1314 {
1315  /* Look up the typcache entry --- we assume it survives indefinitely */
1317  ref->need_exprstate = need_exprstate;
1318  /* For safety, establish the callback before acquiring a refcount */
1319  ref->refctx = refctx;
1320  ref->dcc = NULL;
1322  ref->callback.arg = (void *) ref;
1324  /* Acquire refcount if there are constraints, and set up exported list */
1325  if (ref->tcache->domainData)
1326  {
1327  ref->dcc = ref->tcache->domainData;
1328  ref->dcc->dccRefCount++;
1329  if (ref->need_exprstate)
1331  ref->refctx);
1332  else
1333  ref->constraints = ref->dcc->constraints;
1334  }
1335  else
1336  ref->constraints = NIL;
1337 }
void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)
Definition: mcxt.c:477
MemoryContext refctx
Definition: typcache.h:167
MemoryContextCallback callback
Definition: typcache.h:173
TypeCacheEntry * tcache
Definition: typcache.h:168
MemoryContextCallbackFunction func
Definition: palloc.h:49
static List * prep_domain_constraints(List *constraints, MemoryContext execctx)
Definition: typcache.c:1274
static void dccref_deletion_callback(void *arg)
Definition: typcache.c:1253

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

◆ load_domaintype_info()

static void load_domaintype_info ( TypeCacheEntry typentry)
static

Definition at line 993 of file typcache.c.

994 {
995  Oid typeOid = typentry->type_id;
997  bool notNull = false;
998  DomainConstraintState **ccons;
999  int cconslen;
1000  Relation conRel;
1001  MemoryContext oldcxt;
1002 
1003  /*
1004  * If we're here, any existing constraint info is stale, so release it.
1005  * For safety, be sure to null the link before trying to delete the data.
1006  */
1007  if (typentry->domainData)
1008  {
1009  dcc = typentry->domainData;
1010  typentry->domainData = NULL;
1011  decr_dcc_refcount(dcc);
1012  }
1013 
1014  /*
1015  * We try to optimize the common case of no domain constraints, so don't
1016  * create the dcc object and context until we find a constraint. Likewise
1017  * for the temp sorting array.
1018  */
1019  dcc = NULL;
1020  ccons = NULL;
1021  cconslen = 0;
1022 
1023  /*
1024  * Scan pg_constraint for relevant constraints. We want to find
1025  * constraints for not just this domain, but any ancestor domains, so the
1026  * outer loop crawls up the domain stack.
1027  */
1028  conRel = table_open(ConstraintRelationId, AccessShareLock);
1029 
1030  for (;;)
1031  {
1032  HeapTuple tup;
1033  HeapTuple conTup;
1034  Form_pg_type typTup;
1035  int nccons = 0;
1036  ScanKeyData key[1];
1037  SysScanDesc scan;
1038 
1039  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
1040  if (!HeapTupleIsValid(tup))
1041  elog(ERROR, "cache lookup failed for type %u", typeOid);
1042  typTup = (Form_pg_type) GETSTRUCT(tup);
1043 
1044  if (typTup->typtype != TYPTYPE_DOMAIN)
1045  {
1046  /* Not a domain, so done */
1047  ReleaseSysCache(tup);
1048  break;
1049  }
1050 
1051  /* Test for NOT NULL Constraint */
1052  if (typTup->typnotnull)
1053  notNull = true;
1054 
1055  /* Look for CHECK Constraints on this domain */
1056  ScanKeyInit(&key[0],
1057  Anum_pg_constraint_contypid,
1058  BTEqualStrategyNumber, F_OIDEQ,
1059  ObjectIdGetDatum(typeOid));
1060 
1061  scan = systable_beginscan(conRel, ConstraintTypidIndexId, true,
1062  NULL, 1, key);
1063 
1064  while (HeapTupleIsValid(conTup = systable_getnext(scan)))
1065  {
1067  Datum val;
1068  bool isNull;
1069  char *constring;
1070  Expr *check_expr;
1072 
1073  /* Ignore non-CHECK constraints (presently, shouldn't be any) */
1074  if (c->contype != CONSTRAINT_CHECK)
1075  continue;
1076 
1077  /* Not expecting conbin to be NULL, but we'll test for it anyway */
1078  val = fastgetattr(conTup, Anum_pg_constraint_conbin,
1079  conRel->rd_att, &isNull);
1080  if (isNull)
1081  elog(ERROR, "domain \"%s\" constraint \"%s\" has NULL conbin",
1082  NameStr(typTup->typname), NameStr(c->conname));
1083 
1084  /* Convert conbin to C string in caller context */
1085  constring = TextDatumGetCString(val);
1086 
1087  /* Create the DomainConstraintCache object and context if needed */
1088  if (dcc == NULL)
1089  {
1090  MemoryContext cxt;
1091 
1093  "Domain constraints",
1095  dcc = (DomainConstraintCache *)
1097  dcc->constraints = NIL;
1098  dcc->dccContext = cxt;
1099  dcc->dccRefCount = 0;
1100  }
1101 
1102  /* Create node trees in DomainConstraintCache's context */
1103  oldcxt = MemoryContextSwitchTo(dcc->dccContext);
1104 
1105  check_expr = (Expr *) stringToNode(constring);
1106 
1107  /*
1108  * Plan the expression, since ExecInitExpr will expect that.
1109  *
1110  * Note: caching the result of expression_planner() is not very
1111  * good practice. Ideally we'd use a CachedExpression here so
1112  * that we would react promptly to, eg, changes in inlined
1113  * functions. However, because we don't support mutable domain
1114  * CHECK constraints, it's not really clear that it's worth the
1115  * extra overhead to do that.
1116  */
1117  check_expr = expression_planner(check_expr);
1118 
1121  r->name = pstrdup(NameStr(c->conname));
1122  r->check_expr = check_expr;
1123  r->check_exprstate = NULL;
1124 
1125  MemoryContextSwitchTo(oldcxt);
1126 
1127  /* Accumulate constraints in an array, for sorting below */
1128  if (ccons == NULL)
1129  {
1130  cconslen = 8;
1131  ccons = (DomainConstraintState **)
1132  palloc(cconslen * sizeof(DomainConstraintState *));
1133  }
1134  else if (nccons >= cconslen)
1135  {
1136  cconslen *= 2;
1137  ccons = (DomainConstraintState **)
1138  repalloc(ccons, cconslen * sizeof(DomainConstraintState *));
1139  }
1140  ccons[nccons++] = r;
1141  }
1142 
1143  systable_endscan(scan);
1144 
1145  if (nccons > 0)
1146  {
1147  /*
1148  * Sort the items for this domain, so that CHECKs are applied in a
1149  * deterministic order.
1150  */
1151  if (nccons > 1)
1152  qsort(ccons, nccons, sizeof(DomainConstraintState *), dcs_cmp);
1153 
1154  /*
1155  * Now attach them to the overall list. Use lcons() here because
1156  * constraints of parent domains should be applied earlier.
1157  */
1158  oldcxt = MemoryContextSwitchTo(dcc->dccContext);
1159  while (nccons > 0)
1160  dcc->constraints = lcons(ccons[--nccons], dcc->constraints);
1161  MemoryContextSwitchTo(oldcxt);
1162  }
1163 
1164  /* loop to next domain in stack */
1165  typeOid = typTup->typbasetype;
1166  ReleaseSysCache(tup);
1167  }
1168 
1169  table_close(conRel, AccessShareLock);
1170 
1171  /*
1172  * Only need to add one NOT NULL check regardless of how many domains in
1173  * the stack request it.
1174  */
1175  if (notNull)
1176  {
1178 
1179  /* Create the DomainConstraintCache object and context if needed */
1180  if (dcc == NULL)
1181  {
1182  MemoryContext cxt;
1183 
1185  "Domain constraints",
1187  dcc = (DomainConstraintCache *)
1189  dcc->constraints = NIL;
1190  dcc->dccContext = cxt;
1191  dcc->dccRefCount = 0;
1192  }
1193 
1194  /* Create node trees in DomainConstraintCache's context */
1195  oldcxt = MemoryContextSwitchTo(dcc->dccContext);
1196 
1198 
1200  r->name = pstrdup("NOT NULL");
1201  r->check_expr = NULL;
1202  r->check_exprstate = NULL;
1203 
1204  /* lcons to apply the nullness check FIRST */
1205  dcc->constraints = lcons(r, dcc->constraints);
1206 
1207  MemoryContextSwitchTo(oldcxt);
1208  }
1209 
1210  /*
1211  * If we made a constraint object, move it into CacheMemoryContext and
1212  * attach it to the typcache entry.
1213  */
1214  if (dcc)
1215  {
1217  typentry->domainData = dcc;
1218  dcc->dccRefCount++; /* count the typcache's reference */
1219  }
1220 
1221  /* Either way, the typcache entry's domain data is now valid. */
1223 }
#define TextDatumGetCString(d)
Definition: builtins.h:98
#define NameStr(name)
Definition: c.h:735
@ DOM_CONSTRAINT_CHECK
Definition: execnodes.h:999
@ DOM_CONSTRAINT_NOTNULL
Definition: execnodes.h:998
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:599
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:506
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:387
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
static Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:749
long val
Definition: informix.c:664
List * lcons(void *datum, List *list)
Definition: list.c:495
#define AccessShareLock
Definition: lockdefs.h:36
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:546
char * pstrdup(const char *in)
Definition: mcxt.c:1619
MemoryContext CurrentMemoryContext
Definition: mcxt.c:135
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1451
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1034
void * palloc(Size size)
Definition: mcxt.c:1201
#define AllocSetContextCreate
Definition: memutils.h:128
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:162
#define makeNode(_type_)
Definition: nodes.h:155
FormData_pg_constraint * Form_pg_constraint
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
Expr * expression_planner(Expr *expr)
Definition: planner.c:6407
#define qsort(a, b, c, d)
Definition: port.h:449
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
char * c
void * stringToNode(const char *str)
Definition: read.c:90
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31
DomainConstraintType constrainttype
Definition: execnodes.h:1005
ExprState * check_exprstate
Definition: execnodes.h:1008
TupleDesc rd_att
Definition: rel.h:112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:267
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:219
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
static int dcs_cmp(const void *a, const void *b)
Definition: typcache.c:1229
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:104

References AccessShareLock, ALLOCSET_SMALL_SIZES, AllocSetContextCreate, BTEqualStrategyNumber, CacheMemoryContext, DomainConstraintState::check_expr, DomainConstraintState::check_exprstate, DomainConstraintCache::constraints, DomainConstraintState::constrainttype, CurrentMemoryContext, DomainConstraintCache::dccContext, DomainConstraintCache::dccRefCount, dcs_cmp(), decr_dcc_refcount(), DOM_CONSTRAINT_CHECK, DOM_CONSTRAINT_NOTNULL, TypeCacheEntry::domainData, elog(), ERROR, expression_planner(), fastgetattr(), TypeCacheEntry::flags, GETSTRUCT, HeapTupleIsValid, sort-test::key, lcons(), makeNode, MemoryContextAlloc(), MemoryContextSetParent(), MemoryContextSwitchTo(), DomainConstraintState::name, NameStr, NIL, ObjectIdGetDatum(), palloc(), pstrdup(), qsort, RelationData::rd_att, ReleaseSysCache(), repalloc(), ScanKeyInit(), SearchSysCache1(), stringToNode(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS, TextDatumGetCString, TypeCacheEntry::type_id, and val.

Referenced by lookup_type_cache(), and UpdateDomainConstraintRef().

◆ load_enum_cache_data()

static void load_enum_cache_data ( TypeCacheEntry tcache)
static

Definition at line 2549 of file typcache.c.

2550 {
2551  TypeCacheEnumData *enumdata;
2552  Relation enum_rel;
2553  SysScanDesc enum_scan;
2554  HeapTuple enum_tuple;
2555  ScanKeyData skey;
2556  EnumItem *items;
2557  int numitems;
2558  int maxitems;
2559  Oid bitmap_base;
2560  Bitmapset *bitmap;
2561  MemoryContext oldcxt;
2562  int bm_size,
2563  start_pos;
2564 
2565  /* Check that this is actually an enum */
2566  if (tcache->typtype != TYPTYPE_ENUM)
2567  ereport(ERROR,
2568  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2569  errmsg("%s is not an enum",
2570  format_type_be(tcache->type_id))));
2571 
2572  /*
2573  * Read all the information for members of the enum type. We collect the
2574  * info in working memory in the caller's context, and then transfer it to
2575  * permanent memory in CacheMemoryContext. This minimizes the risk of
2576  * leaking memory from CacheMemoryContext in the event of an error partway
2577  * through.
2578  */
2579  maxitems = 64;
2580  items = (EnumItem *) palloc(sizeof(EnumItem) * maxitems);
2581  numitems = 0;
2582 
2583  /* Scan pg_enum for the members of the target enum type. */
2584  ScanKeyInit(&skey,
2585  Anum_pg_enum_enumtypid,
2586  BTEqualStrategyNumber, F_OIDEQ,
2587  ObjectIdGetDatum(tcache->type_id));
2588 
2589  enum_rel = table_open(EnumRelationId, AccessShareLock);
2590  enum_scan = systable_beginscan(enum_rel,
2591  EnumTypIdLabelIndexId,
2592  true, NULL,
2593  1, &skey);
2594 
2595  while (HeapTupleIsValid(enum_tuple = systable_getnext(enum_scan)))
2596  {
2597  Form_pg_enum en = (Form_pg_enum) GETSTRUCT(enum_tuple);
2598 
2599  if (numitems >= maxitems)
2600  {
2601  maxitems *= 2;
2602  items = (EnumItem *) repalloc(items, sizeof(EnumItem) * maxitems);
2603  }
2604  items[numitems].enum_oid = en->oid;
2605  items[numitems].sort_order = en->enumsortorder;
2606  numitems++;
2607  }
2608 
2609  systable_endscan(enum_scan);
2610  table_close(enum_rel, AccessShareLock);
2611 
2612  /* Sort the items into OID order */
2613  qsort(items, numitems, sizeof(EnumItem), enum_oid_cmp);
2614 
2615  /*
2616  * Here, we create a bitmap listing a subset of the enum's OIDs that are
2617  * known to be in order and can thus be compared with just OID comparison.
2618  *
2619  * The point of this is that the enum's initial OIDs were certainly in
2620  * order, so there is some subset that can be compared via OID comparison;
2621  * and we'd rather not do binary searches unnecessarily.
2622  *
2623  * This is somewhat heuristic, and might identify a subset of OIDs that
2624  * isn't exactly what the type started with. That's okay as long as the
2625  * subset is correctly sorted.
2626  */
2627  bitmap_base = InvalidOid;
2628  bitmap = NULL;
2629  bm_size = 1; /* only save sets of at least 2 OIDs */
2630 
2631  for (start_pos = 0; start_pos < numitems - 1; start_pos++)
2632  {
2633  /*
2634  * Identify longest sorted subsequence starting at start_pos
2635  */
2636  Bitmapset *this_bitmap = bms_make_singleton(0);
2637  int this_bm_size = 1;
2638  Oid start_oid = items[start_pos].enum_oid;
2639  float4 prev_order = items[start_pos].sort_order;
2640  int i;
2641 
2642  for (i = start_pos + 1; i < numitems; i++)
2643  {
2644  Oid offset;
2645 
2646  offset = items[i].enum_oid - start_oid;
2647  /* quit if bitmap would be too large; cutoff is arbitrary */
2648  if (offset >= 8192)
2649  break;
2650  /* include the item if it's in-order */
2651  if (items[i].sort_order > prev_order)
2652  {
2653  prev_order = items[i].sort_order;
2654  this_bitmap = bms_add_member(this_bitmap, (int) offset);
2655  this_bm_size++;
2656  }
2657  }
2658 
2659  /* Remember it if larger than previous best */
2660  if (this_bm_size > bm_size)
2661  {
2662  bms_free(bitmap);
2663  bitmap_base = start_oid;
2664  bitmap = this_bitmap;
2665  bm_size = this_bm_size;
2666  }
2667  else
2668  bms_free(this_bitmap);
2669 
2670  /*
2671  * Done if it's not possible to find a longer sequence in the rest of
2672  * the list. In typical cases this will happen on the first
2673  * iteration, which is why we create the bitmaps on the fly instead of
2674  * doing a second pass over the list.
2675  */
2676  if (bm_size >= (numitems - start_pos - 1))
2677  break;
2678  }
2679 
2680  /* OK, copy the data into CacheMemoryContext */
2682  enumdata = (TypeCacheEnumData *)
2683  palloc(offsetof(TypeCacheEnumData, enum_values) +
2684  numitems * sizeof(EnumItem));
2685  enumdata->bitmap_base = bitmap_base;
2686  enumdata->sorted_values = bms_copy(bitmap);
2687  enumdata->num_values = numitems;
2688  memcpy(enumdata->enum_values, items, numitems * sizeof(EnumItem));
2689  MemoryContextSwitchTo(oldcxt);
2690 
2691  pfree(items);
2692  bms_free(bitmap);
2693 
2694  /* And link the finished cache struct into the typcache */
2695  if (tcache->enumData != NULL)
2696  pfree(tcache->enumData);
2697  tcache->enumData = enumdata;
2698 }
void bms_free(Bitmapset *a)
Definition: bitmapset.c:252
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:229
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:828
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:135
float float4
Definition: c.h:618
void pfree(void *pointer)
Definition: mcxt.c:1431
FormData_pg_enum * Form_pg_enum
Definition: pg_enum.h:44

References AccessShareLock, TypeCacheEnumData::bitmap_base, bms_add_member(), bms_copy(), bms_free(), bms_make_singleton(), BTEqualStrategyNumber, CacheMemoryContext, EnumItem::enum_oid, enum_oid_cmp(), TypeCacheEnumData::enum_values, TypeCacheEntry::enumData, ereport, errcode(), errmsg(), ERROR, format_type_be(), GETSTRUCT, HeapTupleIsValid, i, InvalidOid, MemoryContextSwitchTo(), TypeCacheEnumData::num_values, ObjectIdGetDatum(), palloc(), pfree(), qsort, repalloc(), ScanKeyInit(), EnumItem::sort_order, TypeCacheEnumData::sorted_values, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), TypeCacheEntry::type_id, and TypeCacheEntry::typtype.

Referenced by compare_values_of_enum().

◆ load_multirangetype_info()

static void load_multirangetype_info ( TypeCacheEntry typentry)
static

Definition at line 971 of file typcache.c.

972 {
973  Oid rangetypeOid;
974 
975  rangetypeOid = get_multirange_range(typentry->type_id);
976  if (!OidIsValid(rangetypeOid))
977  elog(ERROR, "cache lookup failed for multirange type %u",
978  typentry->type_id);
979 
980  typentry->rngtype = lookup_type_cache(rangetypeOid, TYPECACHE_RANGE_INFO);
981 }
Oid get_multirange_range(Oid multirangeOid)
Definition: lsyscache.c:3438
#define TYPECACHE_RANGE_INFO
Definition: typcache.h:148

References elog(), ERROR, get_multirange_range(), lookup_type_cache(), OidIsValid, TypeCacheEntry::rngtype, TypeCacheEntry::type_id, and TYPECACHE_RANGE_INFO.

Referenced by cache_multirange_element_properties(), and lookup_type_cache().

◆ load_rangetype_info()

static void load_rangetype_info ( TypeCacheEntry typentry)
static

Definition at line 913 of file typcache.c.

914 {
915  Form_pg_range pg_range;
916  HeapTuple tup;
917  Oid subtypeOid;
918  Oid opclassOid;
919  Oid canonicalOid;
920  Oid subdiffOid;
921  Oid opfamilyOid;
922  Oid opcintype;
923  Oid cmpFnOid;
924 
925  /* get information from pg_range */
926  tup = SearchSysCache1(RANGETYPE, ObjectIdGetDatum(typentry->type_id));
927  /* should not fail, since we already checked typtype ... */
928  if (!HeapTupleIsValid(tup))
929  elog(ERROR, "cache lookup failed for range type %u",
930  typentry->type_id);
931  pg_range = (Form_pg_range) GETSTRUCT(tup);
932 
933  subtypeOid = pg_range->rngsubtype;
934  typentry->rng_collation = pg_range->rngcollation;
935  opclassOid = pg_range->rngsubopc;
936  canonicalOid = pg_range->rngcanonical;
937  subdiffOid = pg_range->rngsubdiff;
938 
939  ReleaseSysCache(tup);
940 
941  /* get opclass properties and look up the comparison function */
942  opfamilyOid = get_opclass_family(opclassOid);
943  opcintype = get_opclass_input_type(opclassOid);
944  typentry->rng_opfamily = opfamilyOid;
945 
946  cmpFnOid = get_opfamily_proc(opfamilyOid, opcintype, opcintype,
947  BTORDER_PROC);
948  if (!RegProcedureIsValid(cmpFnOid))
949  elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
950  BTORDER_PROC, opcintype, opcintype, opfamilyOid);
951 
952  /* set up cached fmgrinfo structs */
953  fmgr_info_cxt(cmpFnOid, &typentry->rng_cmp_proc_finfo,
955  if (OidIsValid(canonicalOid))
956  fmgr_info_cxt(canonicalOid, &typentry->rng_canonical_finfo,
958  if (OidIsValid(subdiffOid))
959  fmgr_info_cxt(subdiffOid, &typentry->rng_subdiff_finfo,
961 
962  /* Lastly, set up link to the element type --- this marks data valid */
963  typentry->rngelemtype = lookup_type_cache(subtypeOid, 0);
964 }
#define RegProcedureIsValid(p)
Definition: c.h:766
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:137
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1189
Oid get_opclass_family(Oid opclass)
Definition: lsyscache.c:1167
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition: lsyscache.c:795
#define BTORDER_PROC
Definition: nbtree.h:707
FormData_pg_range * Form_pg_range
Definition: pg_range.h:58
FmgrInfo rng_cmp_proc_finfo
Definition: typcache.h:101
Oid rng_collation
Definition: typcache.h:100
FmgrInfo rng_subdiff_finfo
Definition: typcache.h:103
FmgrInfo rng_canonical_finfo
Definition: typcache.h:102
Oid rng_opfamily
Definition: typcache.h:99

References BTORDER_PROC, CacheMemoryContext, elog(), ERROR, fmgr_info_cxt(), get_opclass_family(), get_opclass_input_type(), get_opfamily_proc(), GETSTRUCT, HeapTupleIsValid, lookup_type_cache(), ObjectIdGetDatum(), OidIsValid, RegProcedureIsValid, ReleaseSysCache(), TypeCacheEntry::rng_canonical_finfo, TypeCacheEntry::rng_cmp_proc_finfo, TypeCacheEntry::rng_collation, TypeCacheEntry::rng_opfamily, TypeCacheEntry::rng_subdiff_finfo, TypeCacheEntry::rngelemtype, SearchSysCache1(), and TypeCacheEntry::type_id.

Referenced by cache_range_element_properties(), and lookup_type_cache().

◆ load_typcache_tupdesc()

static void load_typcache_tupdesc ( TypeCacheEntry typentry)
static

Definition at line 879 of file typcache.c.

880 {
881  Relation rel;
882 
883  if (!OidIsValid(typentry->typrelid)) /* should not happen */
884  elog(ERROR, "invalid typrelid for composite type %u",
885  typentry->type_id);
886  rel = relation_open(typentry->typrelid, AccessShareLock);
887  Assert(rel->rd_rel->reltype == typentry->type_id);
888 
889  /*
890  * Link to the tupdesc and increment its refcount (we assert it's a
891  * refcounted descriptor). We don't use IncrTupleDescRefCount() for this,
892  * because the reference mustn't be entered in the current resource owner;
893  * it can outlive the current query.
894  */
895  typentry->tupDesc = RelationGetDescr(rel);
896 
897  Assert(typentry->tupDesc->tdrefcount > 0);
898  typentry->tupDesc->tdrefcount++;
899 
900  /*
901  * In future, we could take some pains to not change tupDesc_identifier if
902  * the tupdesc didn't really change; but for now it's not worth it.
903  */
905 
907 }
#define RelationGetDescr(relation)
Definition: rel.h:530
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
Form_pg_class rd_rel
Definition: rel.h:111

References AccessShareLock, Assert(), elog(), ERROR, OidIsValid, RelationData::rd_rel, relation_close(), relation_open(), RelationGetDescr, TupleDescData::tdrefcount, TypeCacheEntry::tupDesc, TypeCacheEntry::tupDesc_identifier, tupledesc_id_counter, TypeCacheEntry::type_id, and TypeCacheEntry::typrelid.

Referenced by cache_record_field_properties(), and lookup_type_cache().

◆ lookup_rowtype_tupdesc()

◆ lookup_rowtype_tupdesc_copy()

TupleDesc lookup_rowtype_tupdesc_copy ( Oid  type_id,
int32  typmod 
)

Definition at line 1866 of file typcache.c.

1867 {
1868  TupleDesc tmp;
1869 
1870  tmp = lookup_rowtype_tupdesc_internal(type_id, typmod, false);
1871  return CreateTupleDescCopyConstr(tmp);
1872 }
TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc)
Definition: tupdesc.c:173

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

1889 {
1890  TupleDesc tupDesc;
1891 
1892  if (type_id != RECORDOID)
1893  {
1894  /*
1895  * Check for domain or named composite type. We might as well load
1896  * whichever data is needed.
1897  */
1898  TypeCacheEntry *typentry;
1899 
1900  typentry = lookup_type_cache(type_id,
1903  if (typentry->typtype == TYPTYPE_DOMAIN)
1905  typentry->domainBaseTypmod,
1906  noError);
1907  if (typentry->tupDesc == NULL && !noError)
1908  ereport(ERROR,
1909  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1910  errmsg("type %s is not composite",
1911  format_type_be(type_id))));
1912  tupDesc = typentry->tupDesc;
1913  }
1914  else
1915  tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, noError);
1916  if (tupDesc != NULL)
1917  PinTupleDesc(tupDesc);
1918  return tupDesc;
1919 }
TupleDesc lookup_rowtype_tupdesc_noerror(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1849
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:149

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

static TupleDesc lookup_rowtype_tupdesc_internal ( Oid  type_id,
int32  typmod,
bool  noError 
)
static

Definition at line 1738 of file typcache.c.

1739 {
1740  if (type_id != RECORDOID)
1741  {
1742  /*
1743  * It's a named composite type, so use the regular typcache.
1744  */
1745  TypeCacheEntry *typentry;
1746 
1747  typentry = lookup_type_cache(type_id, TYPECACHE_TUPDESC);
1748  if (typentry->tupDesc == NULL && !noError)
1749  ereport(ERROR,
1750  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1751  errmsg("type %s is not composite",
1752  format_type_be(type_id))));
1753  return typentry->tupDesc;
1754  }
1755  else
1756  {
1757  /*
1758  * It's a transient record type, so look in our record-type table.
1759  */
1760  if (typmod >= 0)
1761  {
1762  /* It is already in our local cache? */
1763  if (typmod < RecordCacheArrayLen &&
1764  RecordCacheArray[typmod].tupdesc != NULL)
1765  return RecordCacheArray[typmod].tupdesc;
1766 
1767  /* Are we attached to a shared record typmod registry? */
1769  {
1770  SharedTypmodTableEntry *entry;
1771 
1772  /* Try to find it in the shared typmod index. */
1774  &typmod, false);
1775  if (entry != NULL)
1776  {
1777  TupleDesc tupdesc;
1778 
1779  tupdesc = (TupleDesc)
1781  entry->shared_tupdesc);
1782  Assert(typmod == tupdesc->tdtypmod);
1783 
1784  /* We may need to extend the local RecordCacheArray. */
1786 
1787  /*
1788  * Our local array can now point directly to the TupleDesc
1789  * in shared memory, which is non-reference-counted.
1790  */
1791  RecordCacheArray[typmod].tupdesc = tupdesc;
1792  Assert(tupdesc->tdrefcount == -1);
1793 
1794  /*
1795  * We don't share tupdesc identifiers across processes, so
1796  * assign one locally.
1797  */
1799 
1801  entry);
1802 
1803  return RecordCacheArray[typmod].tupdesc;
1804  }
1805  }
1806  }
1807 
1808  if (!noError)
1809  ereport(ERROR,
1810  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1811  errmsg("record type has not been registered")));
1812  return NULL;
1813  }
1814 }

References Session::area, Assert(), CurrentSession, dsa_get_address(), dshash_find(), dshash_release_lock(), ensure_record_cache_typmod_slot_exists(), ereport, errcode(), errmsg(), ERROR, format_type_be(), RecordCacheArrayEntry::id, lookup_type_cache(), RecordCacheArray, RecordCacheArrayLen, SharedTypmodTableEntry::shared_tupdesc, Session::shared_typmod_registry, Session::shared_typmod_table, TupleDescData::tdrefcount, TupleDescData::tdtypmod, RecordCacheArrayEntry::tupdesc, TypeCacheEntry::tupDesc, tupledesc_id_counter, and TYPECACHE_TUPDESC.

Referenced by lookup_rowtype_tupdesc(), lookup_rowtype_tupdesc_copy(), lookup_rowtype_tupdesc_domain(), and lookup_rowtype_tupdesc_noerror().

◆ lookup_rowtype_tupdesc_noerror()

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

Definition at line 1849 of file typcache.c.

1850 {
1851  TupleDesc tupDesc;
1852 
1853  tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, noError);
1854  if (tupDesc != NULL)
1855  PinTupleDesc(tupDesc);
1856  return tupDesc;
1857 }

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

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

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(), TypeCacheEntry::domainBaseType, TypeCacheEntry::domainBaseTypmod, HASHCTL::entrysize, TypeCacheEntry::eq_opr, TypeCacheEntry::eq_opr_finfo, ereport, errcode(), errmsg(), ERROR, firstDomainTypeEntry, TypeCacheEntry::flags, fmgr_info_cxt(), FmgrInfo::fn_oid, get_opclass_family(), get_opclass_input_type(), get_opcode(), get_opfamily_member(), get_opfamily_proc(), getBaseTypeAndTypmod(), GetDefaultOpClass(), GETSTRUCT, GetSysCacheHashValue1, TypeCacheEntry::gt_opr, HASH_BLOBS, hash_create(), HASH_ELEM, HASH_ENTER, TypeCacheEntry::hash_extended_proc, TypeCacheEntry::hash_extended_proc_finfo, HASH_FIND, TypeCacheEntry::hash_opf, TypeCacheEntry::hash_opintype, TypeCacheEntry::hash_proc, TypeCacheEntry::hash_proc_finfo, hash_search(), HASHEXTENDED_PROC, HASHSTANDARD_PROC, HeapTupleIsValid, HTEqualStrategyNumber, InvalidOid, HASHCTL::keysize, load_domaintype_info(), load_multirangetype_info(), load_rangetype_info(), load_typcache_tupdesc(), TypeCacheEntry::lt_opr, MemSet, multirange_element_has_extended_hashing(), multirange_element_has_hashing(), NameStr, TypeCacheEntry::nextDomain, ObjectIdGetDatum(), OidIsValid, range_element_has_extended_hashing(), range_element_has_hashing(), record_fields_have_compare(), record_fields_have_equality(), record_fields_have_extended_hashing(), record_fields_have_hashing(), ReleaseSysCache(), TypeCacheEntry::rngelemtype, TypeCacheEntry::rngtype, SearchSysCache1(), TCFLAGS_CHECKED_BTREE_OPCLASS, TCFLAGS_CHECKED_CMP_PROC, TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS, TCFLAGS_CHECKED_EQ_OPR, TCFLAGS_CHECKED_GT_OPR, TCFLAGS_CHECKED_HASH_EXTENDED_PROC, TCFLAGS_CHECKED_HASH_OPCLASS, TCFLAGS_CHECKED_HASH_PROC, TCFLAGS_CHECKED_LT_OPR, TCFLAGS_HAVE_PG_TYPE_DATA, TypeCacheEntry::tupDesc, TypeCacheEntry::typalign, TypeCacheEntry::typbyval, TypeCacheEntry::typcollation, TypeCacheEntry::type_id, TypeCacheEntry::type_id_hash, TYPECACHE_BTREE_OPFAMILY, TYPECACHE_CMP_PROC, TYPECACHE_CMP_PROC_FINFO, TYPECACHE_DOMAIN_BASE_INFO, TYPECACHE_DOMAIN_CONSTR_INFO, TYPECACHE_EQ_OPR, TYPECACHE_EQ_OPR_FINFO, TYPECACHE_GT_OPR, TYPECACHE_HASH_EXTENDED_PROC, TYPECACHE_HASH_EXTENDED_PROC_FINFO, TYPECACHE_HASH_OPFAMILY, TYPECACHE_HASH_PROC, TYPECACHE_HASH_PROC_FINFO, TYPECACHE_LT_OPR, TYPECACHE_MULTIRANGE_INFO, TYPECACHE_RANGE_INFO, TYPECACHE_TUPDESC, TypeCacheConstrCallback(), 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_sample(), array_shuffle(), 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_memoizable(), contain_leaked_vars_walker(), CreateStatistics(), dependency_degree(), domain_state_setup(), DomainHasConstraints(), enum_cmp_internal(), ExecInitExprRec(), find_simplified_clause(), foreign_expr_walker(), get_cached_rowtype(), get_multirange_io_data(), get_range_io_data(), get_rule_orderby(), get_sort_group_operators(), hash_array(), hash_array_extended(), hash_multirange(), hash_multirange_extended(), hash_range(), hash_range_extended(), hash_record(), hash_record_extended(), InitDomainConstraintRef(), initGinState(), load_multirangetype_info(), load_rangetype_info(), lookup_rowtype_tupdesc_domain(), lookup_rowtype_tupdesc_internal(), 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_get_typcache(), record_cmp(), record_eq(), revalidate_rectypeid(), scalararraysel(), scalararraysel_containment(), show_sortorder_options(), statext_mcv_serialize(), tuples_equal(), and width_bucket_array().

◆ multirange_element_has_extended_hashing()

static bool multirange_element_has_extended_hashing ( TypeCacheEntry typentry)
static

Definition at line 1673 of file typcache.c.

1674 {
1675  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1677  return (typentry->flags & TCFLAGS_HAVE_ELEM_EXTENDED_HASHING) != 0;
1678 }
static void cache_multirange_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1681

References cache_multirange_element_properties(), TypeCacheEntry::flags, TCFLAGS_CHECKED_ELEM_PROPERTIES, and TCFLAGS_HAVE_ELEM_EXTENDED_HASHING.

Referenced by lookup_type_cache().

◆ multirange_element_has_hashing()

static bool multirange_element_has_hashing ( TypeCacheEntry typentry)
static

Definition at line 1665 of file typcache.c.

1666 {
1667  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1669  return (typentry->flags & TCFLAGS_HAVE_ELEM_HASHING) != 0;
1670 }

References cache_multirange_element_properties(), TypeCacheEntry::flags, TCFLAGS_CHECKED_ELEM_PROPERTIES, and TCFLAGS_HAVE_ELEM_HASHING.

Referenced by lookup_type_cache().

◆ prep_domain_constraints()

static List * prep_domain_constraints ( List constraints,
MemoryContext  execctx 
)
static

Definition at line 1274 of file typcache.c.

1275 {
1276  List *result = NIL;
1277  MemoryContext oldcxt;
1278  ListCell *lc;
1279 
1280  oldcxt = MemoryContextSwitchTo(execctx);
1281 
1282  foreach(lc, constraints)
1283  {
1285  DomainConstraintState *newr;
1286 
1288  newr->constrainttype = r->constrainttype;
1289  newr->name = r->name;
1290  newr->check_expr = r->check_expr;
1291  newr->check_exprstate = ExecInitExpr(r->check_expr, NULL);
1292 
1293  result = lappend(result, newr);
1294  }
1295 
1296  MemoryContextSwitchTo(oldcxt);
1297 
1298  return result;
1299 }
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:128
List * lappend(List *list, void *datum)
Definition: list.c:339
#define lfirst(lc)
Definition: pg_list.h:172
Definition: pg_list.h:54

References DomainConstraintState::check_expr, DomainConstraintState::check_exprstate, DomainConstraintState::constrainttype, ExecInitExpr(), lappend(), lfirst, makeNode, MemoryContextSwitchTo(), DomainConstraintState::name, and NIL.

Referenced by InitDomainConstraintRef(), and UpdateDomainConstraintRef().

◆ range_element_has_extended_hashing()

static bool range_element_has_extended_hashing ( TypeCacheEntry typentry)
static

Definition at line 1633 of file typcache.c.

1634 {
1635  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1637  return (typentry->flags & TCFLAGS_HAVE_ELEM_EXTENDED_HASHING) != 0;
1638 }
static void cache_range_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1641

References cache_range_element_properties(), TypeCacheEntry::flags, TCFLAGS_CHECKED_ELEM_PROPERTIES, and TCFLAGS_HAVE_ELEM_EXTENDED_HASHING.

Referenced by lookup_type_cache().

◆ range_element_has_hashing()

static bool range_element_has_hashing ( TypeCacheEntry typentry)
static

Definition at line 1625 of file typcache.c.

1626 {
1627  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1629  return (typentry->flags & TCFLAGS_HAVE_ELEM_HASHING) != 0;
1630 }

References cache_range_element_properties(), TypeCacheEntry::flags, TCFLAGS_CHECKED_ELEM_PROPERTIES, and TCFLAGS_HAVE_ELEM_HASHING.

Referenced by lookup_type_cache().

◆ record_fields_have_compare()

static bool record_fields_have_compare ( TypeCacheEntry typentry)
static

Definition at line 1496 of file typcache.c.

1497 {
1498  if (!(typentry->flags & TCFLAGS_CHECKED_FIELD_PROPERTIES))
1500  return (typentry->flags & TCFLAGS_HAVE_FIELD_COMPARE) != 0;
1501 }
static void cache_record_field_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1520

References cache_record_field_properties(), TypeCacheEntry::flags, TCFLAGS_CHECKED_FIELD_PROPERTIES, and TCFLAGS_HAVE_FIELD_COMPARE.

Referenced by lookup_type_cache().

◆ record_fields_have_equality()

static bool record_fields_have_equality ( TypeCacheEntry typentry)
static

Definition at line 1488 of file typcache.c.

1489 {
1490  if (!(typentry->flags & TCFLAGS_CHECKED_FIELD_PROPERTIES))
1492  return (typentry->flags & TCFLAGS_HAVE_FIELD_EQUALITY) != 0;
1493 }

References cache_record_field_properties(), TypeCacheEntry::flags, TCFLAGS_CHECKED_FIELD_PROPERTIES, and TCFLAGS_HAVE_FIELD_EQUALITY.

Referenced by lookup_type_cache().

◆ record_fields_have_extended_hashing()

static bool record_fields_have_extended_hashing ( TypeCacheEntry typentry)
static

◆ record_fields_have_hashing()

static bool record_fields_have_hashing ( TypeCacheEntry typentry)
static

Definition at line 1504 of file typcache.c.

1505 {
1506  if (!(typentry->flags & TCFLAGS_CHECKED_FIELD_PROPERTIES))
1508  return (typentry->flags & TCFLAGS_HAVE_FIELD_HASHING) != 0;
1509 }

References cache_record_field_properties(), TypeCacheEntry::flags, TCFLAGS_CHECKED_FIELD_PROPERTIES, and TCFLAGS_HAVE_FIELD_HASHING.

Referenced by lookup_type_cache().

◆ record_type_typmod_compare()

static int record_type_typmod_compare ( const void *  a,
const void *  b,
size_t  size 
)
static

Definition at line 1936 of file typcache.c.

1937 {
1938  RecordCacheEntry *left = (RecordCacheEntry *) a;
1939  RecordCacheEntry *right = (RecordCacheEntry *) b;
1940 
1941  return equalTupleDescs(left->tupdesc, right->tupdesc) ? 0 : 1;
1942 }
bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
Definition: tupdesc.c:424

References a, b, equalTupleDescs(), and RecordCacheEntry::tupdesc.

Referenced by assign_record_type_typmod().

◆ record_type_typmod_hash()

static uint32 record_type_typmod_hash ( const void *  data,
size_t  size 
)
static

Definition at line 1925 of file typcache.c.

1926 {
1927  RecordCacheEntry *entry = (RecordCacheEntry *) data;
1928 
1929  return hashTupleDesc(entry->tupdesc);
1930 }
const void * data
uint32 hashTupleDesc(TupleDesc desc)
Definition: tupdesc.c:574

References data, hashTupleDesc(), and RecordCacheEntry::tupdesc.

Referenced by assign_record_type_typmod().

◆ share_tupledesc()

static dsa_pointer share_tupledesc ( dsa_area area,
TupleDesc  tupdesc,
uint32  typmod 
)
static

Definition at line 2734 of file typcache.c.

2735 {
2736  dsa_pointer shared_dp;
2737  TupleDesc shared;
2738 
2739  shared_dp = dsa_allocate(area, TupleDescSize(tupdesc));
2740  shared = (TupleDesc) dsa_get_address(area, shared_dp);
2741  TupleDescCopy(shared, tupdesc);
2742  shared->tdtypmod = typmod;
2743 
2744  return shared_dp;
2745 }
#define dsa_allocate(area, size)
Definition: dsa.h:84
void TupleDescCopy(TupleDesc dst, TupleDesc src)
Definition: tupdesc.c:251
#define TupleDescSize(src)
Definition: tupdesc.h:102

References dsa_allocate, dsa_get_address(), TupleDescData::tdtypmod, TupleDescCopy(), and TupleDescSize.

Referenced by find_or_make_matching_shared_tupledesc(), and SharedRecordTypmodRegistryInit().

◆ shared_record_table_compare()

static int shared_record_table_compare ( const void *  a,
const void *  b,
size_t  size,
void *  arg 
)
static

Definition at line 216 of file typcache.c.

218 {
219  dsa_area *area = (dsa_area *) arg;
222  TupleDesc t1;
223  TupleDesc t2;
224 
225  if (k1->shared)
226  t1 = (TupleDesc) dsa_get_address(area, k1->u.shared_tupdesc);
227  else
228  t1 = k1->u.local_tupdesc;
229 
230  if (k2->shared)
231  t2 = (TupleDesc) dsa_get_address(area, k2->u.shared_tupdesc);
232  else
233  t2 = k2->u.local_tupdesc;
234 
235  return equalTupleDescs(t1, t2) ? 0 : 1;
236 }
TupleDesc local_tupdesc
Definition: typcache.c:187
Definition: dsa.c:368

References a, arg, b, dsa_get_address(), equalTupleDescs(), SharedRecordTableKey::local_tupdesc, SharedRecordTableKey::shared, SharedRecordTableKey::shared_tupdesc, and SharedRecordTableKey::u.

◆ shared_record_table_hash()

static uint32 shared_record_table_hash ( const void *  a,
size_t  size,
void *  arg 
)
static

Definition at line 242 of file typcache.c.

243 {
244  dsa_area *area = (dsa_area *) arg;
246  TupleDesc t;
247 
248  if (k->shared)
249  t = (TupleDesc) dsa_get_address(area, k->u.shared_tupdesc);
250  else
251  t = k->u.local_tupdesc;
252 
253  return hashTupleDesc(t);
254 }

References a, arg, dsa_get_address(), hashTupleDesc(), SharedRecordTableKey::local_tupdesc, SharedRecordTableKey::shared, SharedRecordTableKey::shared_tupdesc, and SharedRecordTableKey::u.

◆ shared_record_typmod_registry_detach()

static void shared_record_typmod_registry_detach ( dsm_segment segment,
Datum  datum 
)
static

Definition at line 2867 of file typcache.c.

2868 {
2869  /* Be cautious here: maybe we didn't finish initializing. */
2870  if (CurrentSession->shared_record_table != NULL)
2871  {
2874  }
2875  if (CurrentSession->shared_typmod_table != NULL)
2876  {
2879  }
2881 }
void dshash_detach(dshash_table *hash_table)
Definition: dshash.c:307

References CurrentSession, dshash_detach(), Session::shared_record_table, Session::shared_typmod_registry, and Session::shared_typmod_table.

Referenced by SharedRecordTypmodRegistryAttach(), and SharedRecordTypmodRegistryInit().

◆ SharedRecordTypmodRegistryAttach()

void SharedRecordTypmodRegistryAttach ( SharedRecordTypmodRegistry registry)

Definition at line 2206 of file typcache.c.

2207 {
2208  MemoryContext old_context;
2209  dshash_table *record_table;
2210  dshash_table *typmod_table;
2211 
2213 
2214  /* We can't already be attached to a shared registry. */
2215  Assert(CurrentSession != NULL);
2216  Assert(CurrentSession->segment != NULL);
2217  Assert(CurrentSession->area != NULL);
2221 
2222  /*
2223  * We can't already have typmods in our local cache, because they'd clash
2224  * with those imported by SharedRecordTypmodRegistryInit. This should be
2225  * a freshly started parallel worker. If we ever support worker
2226  * recycling, a worker would need to zap its local cache in between
2227  * servicing different queries, in order to be able to call this and
2228  * synchronize typmods with a new leader; but that's problematic because
2229  * we can't be very sure that record-typmod-related state hasn't escaped
2230  * to anywhere else in the process.
2231  */
2232  Assert(NextRecordTypmod == 0);
2233 
2234  old_context = MemoryContextSwitchTo(TopMemoryContext);
2235 
2236  /* Attach to the two hash tables. */
2237  record_table = dshash_attach(CurrentSession->area,
2239  registry->record_table_handle,
2240  CurrentSession->area);
2241  typmod_table = dshash_attach(CurrentSession->area,
2243  registry->typmod_table_handle,
2244  NULL);
2245 
2246  MemoryContextSwitchTo(old_context);
2247 
2248  /*
2249  * Set up detach hook to run at worker exit. Currently this is the same
2250  * as the leader's detach hook, but in future they might need to be
2251  * different.
2252  */
2255  PointerGetDatum(registry));
2256 
2257  /*
2258  * Set up the session state that will tell assign_record_type_typmod and
2259  * lookup_rowtype_tupdesc_internal about the shared registry.
2260  */
2262  CurrentSession->shared_record_table = record_table;
2263  CurrentSession->shared_typmod_table = typmod_table;
2264 }
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:1133
#define IsParallelWorker()
Definition: parallel.h:61
MemoryContext TopMemoryContext
Definition: mcxt.c:141
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
dsm_segment * segment
Definition: session.h:27
dshash_table_handle typmod_table_handle
Definition: typcache.c:172
dshash_table_handle record_table_handle
Definition: typcache.c:170
static const dshash_parameters srtr_typmod_table_params
Definition: typcache.c:266
static void shared_record_typmod_registry_detach(dsm_segment *segment, Datum datum)
Definition: typcache.c:2867
static const dshash_parameters srtr_record_table_params
Definition: typcache.c:257

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

2086 {
2087  return sizeof(SharedRecordTypmodRegistry);
2088 }
struct SharedRecordTypmodRegistry SharedRecordTypmodRegistry
Definition: typcache.h:176

Referenced by GetSessionDsmHandle().

◆ SharedRecordTypmodRegistryInit()

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

Definition at line 2107 of file typcache.c.

2110 {
2111  MemoryContext old_context;
2112  dshash_table *record_table;
2113  dshash_table *typmod_table;
2114  int32 typmod;
2115 
2117 
2118  /* We can't already be attached to a shared registry. */
2122 
2123  old_context = MemoryContextSwitchTo(TopMemoryContext);
2124 
2125  /* Create the hash table of tuple descriptors indexed by themselves. */
2126  record_table = dshash_create(area, &srtr_record_table_params, area);
2127 
2128  /* Create the hash table of tuple descriptors indexed by typmod. */
2129  typmod_table = dshash_create(area, &srtr_typmod_table_params, NULL);
2130 
2131  MemoryContextSwitchTo(old_context);
2132 
2133  /* Initialize the SharedRecordTypmodRegistry. */
2134  registry->record_table_handle = dshash_get_hash_table_handle(record_table);
2135  registry->typmod_table_handle = dshash_get_hash_table_handle(typmod_table);
2137 
2138  /*
2139  * Copy all entries from this backend's private registry into the shared
2140  * registry.
2141  */
2142  for (typmod = 0; typmod < NextRecordTypmod; ++typmod)
2143  {
2144  SharedTypmodTableEntry *typmod_table_entry;
2145  SharedRecordTableEntry *record_table_entry;
2146  SharedRecordTableKey record_table_key;
2147  dsa_pointer shared_dp;
2148  TupleDesc tupdesc;
2149  bool found;
2150 
2151  tupdesc = RecordCacheArray[typmod].tupdesc;
2152  if (tupdesc == NULL)
2153  continue;
2154 
2155  /* Copy the TupleDesc into shared memory. */
2156  shared_dp = share_tupledesc(area, tupdesc, typmod);
2157 
2158  /* Insert into the typmod table. */
2159  typmod_table_entry = dshash_find_or_insert(typmod_table,
2160  &tupdesc->tdtypmod,
2161  &found);
2162  if (found)
2163  elog(ERROR, "cannot create duplicate shared record typmod");
2164  typmod_table_entry->typmod = tupdesc->tdtypmod;
2165  typmod_table_entry->shared_tupdesc = shared_dp;
2166  dshash_release_lock(typmod_table, typmod_table_entry);
2167 
2168  /* Insert into the record table. */
2169  record_table_key.shared = false;
2170  record_table_key.u.local_tupdesc = tupdesc;
2171  record_table_entry = dshash_find_or_insert(record_table,
2172  &record_table_key,
2173  &found);
2174  if (!found)
2175  {
2176  record_table_entry->key.shared = true;
2177  record_table_entry->key.u.shared_tupdesc = shared_dp;
2178  }
2179  dshash_release_lock(record_table, record_table_entry);
2180  }
2181 
2182  /*
2183  * Set up the global state that will tell assign_record_type_typmod and
2184  * lookup_rowtype_tupdesc_internal about the shared registry.
2185  */
2186  CurrentSession->shared_record_table = record_table;
2187  CurrentSession->shared_typmod_table = typmod_table;
2189 
2190  /*
2191  * We install a detach hook in the leader, but only to handle cleanup on
2192  * failure during GetSessionDsmHandle(). Once GetSessionDsmHandle() pins
2193  * the memory, the leader process will use a shared registry until it
2194  * exits.
2195  */
2197 }
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:218
dshash_table_handle dshash_get_hash_table_handle(dshash_table *hash_table)
Definition: dshash.c:367
dshash_table * dshash_create(dsa_area *area, const dshash_parameters *params, void *arg)
Definition: dshash.c:206

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

◆ TypeCacheConstrCallback()

static void TypeCacheConstrCallback ( Datum  arg,
int  cacheid,
uint32  hashvalue 
)
static

Definition at line 2423 of file typcache.c.

2424 {
2425  TypeCacheEntry *typentry;
2426 
2427  /*
2428  * Because this is called very frequently, and typically very few of the
2429  * typcache entries are for domains, we don't use hash_seq_search here.
2430  * Instead we thread all the domain-type entries together so that we can
2431  * visit them cheaply.
2432  */
2433  for (typentry = firstDomainTypeEntry;
2434  typentry != NULL;
2435  typentry = typentry->nextDomain)
2436  {
2437  /* Reset domain constraint validity information */
2439  }
2440 }

References firstDomainTypeEntry, TypeCacheEntry::flags, TypeCacheEntry::nextDomain, and TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS.

Referenced by lookup_type_cache().

◆ TypeCacheOpcCallback()

static void TypeCacheOpcCallback ( Datum  arg,
int  cacheid,
uint32  hashvalue 
)
static

Definition at line 2394 of file typcache.c.

2395 {
2396  HASH_SEQ_STATUS status;
2397  TypeCacheEntry *typentry;
2398 
2399  /* TypeCacheHash must exist, else this callback wouldn't be registered */
2400  hash_seq_init(&status, TypeCacheHash);
2401  while ((typentry = (TypeCacheEntry *) hash_seq_search(&status)) != NULL)
2402  {
2403  /* Reset equality/comparison/hashing validity information */
2404  typentry->flags &= ~TCFLAGS_OPERATOR_FLAGS;
2405  }
2406 }
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1431
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1421
#define TCFLAGS_OPERATOR_FLAGS
Definition: typcache.c:108

References TypeCacheEntry::flags, hash_seq_init(), hash_seq_search(), TCFLAGS_OPERATOR_FLAGS, and TypeCacheHash.

Referenced by lookup_type_cache().

◆ TypeCacheRelCallback()

static void TypeCacheRelCallback ( Datum  arg,
Oid  relid 
)
static

Definition at line 2289 of file typcache.c.

2290 {
2291  HASH_SEQ_STATUS status;
2292  TypeCacheEntry *typentry;
2293 
2294  /* TypeCacheHash must exist, else this callback wouldn't be registered */
2295  hash_seq_init(&status, TypeCacheHash);
2296  while ((typentry = (TypeCacheEntry *) hash_seq_search(&status)) != NULL)
2297  {
2298  if (typentry->typtype == TYPTYPE_COMPOSITE)
2299  {
2300  /* Skip if no match, unless we're zapping all composite types */
2301  if (relid != typentry->typrelid && relid != InvalidOid)
2302  continue;
2303 
2304  /* Delete tupdesc if we have it */
2305  if (typentry->tupDesc != NULL)
2306  {
2307  /*
2308  * Release our refcount, and free the tupdesc if none remain.
2309  * (Can't use DecrTupleDescRefCount because this reference is
2310  * not logged in current resource owner.)
2311  */
2312  Assert(typentry->tupDesc->tdrefcount > 0);
2313  if (--typentry->tupDesc->tdrefcount == 0)
2314  FreeTupleDesc(typentry->tupDesc);
2315  typentry->tupDesc = NULL;
2316 
2317  /*
2318  * Also clear tupDesc_identifier, so that anything watching
2319  * that will realize that the tupdesc has possibly changed.
2320  * (Alternatively, we could specify that to detect possible
2321  * tupdesc change, one must check for tupDesc != NULL as well
2322  * as tupDesc_identifier being the same as what was previously
2323  * seen. That seems error-prone.)
2324  */
2325  typentry->tupDesc_identifier = 0;
2326  }
2327 
2328  /* Reset equality/comparison/hashing validity information */
2329  typentry->flags &= ~TCFLAGS_OPERATOR_FLAGS;
2330  }
2331  else if (typentry->typtype == TYPTYPE_DOMAIN)
2332  {
2333  /*
2334  * If it's domain over composite, reset flags. (We don't bother
2335  * trying to determine whether the specific base type needs a
2336  * reset.) Note that if we haven't determined whether the base
2337  * type is composite, we don't need to reset anything.
2338  */
2339  if (typentry->flags & TCFLAGS_DOMAIN_BASE_IS_COMPOSITE)
2340  typentry->flags &= ~TCFLAGS_OPERATOR_FLAGS;
2341  }
2342  }
2343 }
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:331

References Assert(), TypeCacheEntry::flags, FreeTupleDesc(), hash_seq_init(), hash_seq_search(), InvalidOid, TCFLAGS_DOMAIN_BASE_IS_COMPOSITE, TCFLAGS_OPERATOR_FLAGS, TupleDescData::tdrefcount, TypeCacheEntry::tupDesc, TypeCacheEntry::tupDesc_identifier, TypeCacheHash, TypeCacheEntry::typrelid, and TypeCacheEntry::typtype.

Referenced by lookup_type_cache().

◆ TypeCacheTypCallback()

static void TypeCacheTypCallback ( Datum  arg,
int  cacheid,
uint32  hashvalue 
)
static

Definition at line 2354 of file typcache.c.

2355 {
2356  HASH_SEQ_STATUS status;
2357  TypeCacheEntry *typentry;
2358 
2359  /* TypeCacheHash must exist, else this callback wouldn't be registered */
2360  hash_seq_init(&status, TypeCacheHash);
2361  while ((typentry = (TypeCacheEntry *) hash_seq_search(&status)) != NULL)
2362  {
2363  /* Is this the targeted type row (or it's a total cache flush)? */
2364  if (hashvalue == 0 || typentry->type_id_hash == hashvalue)
2365  {
2366  /*
2367  * Mark the data obtained directly from pg_type as invalid. Also,
2368  * if it's a domain, typnotnull might've changed, so we'll need to
2369  * recalculate its constraints.
2370  */
2371  typentry->flags &= ~(TCFLAGS_HAVE_PG_TYPE_DATA |
2373  }
2374  }
2375 }

References TypeCacheEntry::flags, hash_seq_init(), hash_seq_search(), TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS, TCFLAGS_HAVE_PG_TYPE_DATA, TypeCacheEntry::type_id_hash, and TypeCacheHash.

Referenced by lookup_type_cache().

◆ UpdateDomainConstraintRef()

void UpdateDomainConstraintRef ( DomainConstraintRef ref)

Definition at line 1350 of file typcache.c.

1351 {
1352  TypeCacheEntry *typentry = ref->tcache;
1353 
1354  /* Make sure typcache entry's data is up to date */
1355  if ((typentry->flags & TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS) == 0 &&
1356  typentry->typtype == TYPTYPE_DOMAIN)
1357  load_domaintype_info(typentry);
1358 
1359  /* Transfer to ref object if there's new info, adjusting refcounts */
1360  if (ref->dcc != typentry->domainData)
1361  {
1362  /* Paranoia --- be sure link is nulled before trying to release */
1363  DomainConstraintCache *dcc = ref->dcc;
1364 
1365  if (dcc)
1366  {
1367  /*
1368  * Note: we just leak the previous list of executable domain
1369  * constraints. Alternatively, we could keep those in a child
1370  * context of ref->refctx and free that context at this point.
1371  * However, in practice this code path will be taken so seldom
1372  * that the extra bookkeeping for a child context doesn't seem
1373  * worthwhile; we'll just allow a leak for the lifespan of refctx.
1374  */
1375  ref->constraints = NIL;
1376  ref->dcc = NULL;
1377  decr_dcc_refcount(dcc);
1378  }
1379  dcc = typentry->domainData;
1380  if (dcc)
1381  {
1382  ref->dcc = dcc;
1383  dcc->dccRefCount++;
1384  if (ref->need_exprstate)
1386  ref->refctx);
1387  else
1388  ref->constraints = dcc->constraints;
1389  }
1390  }
1391 }

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

Variable Documentation

◆ firstDomainTypeEntry

TypeCacheEntry* firstDomainTypeEntry = NULL
static

Definition at line 82 of file typcache.c.

Referenced by lookup_type_cache(), and TypeCacheConstrCallback().

◆ NextRecordTypmod

int32 NextRecordTypmod = 0
static

◆ RecordCacheArray

◆ RecordCacheArrayLen

int32 RecordCacheArrayLen = 0
static

◆ RecordCacheHash

HTAB* RecordCacheHash = NULL
static

Definition at line 275 of file typcache.c.

Referenced by assign_record_type_typmod().

◆ srtr_record_table_params

const dshash_parameters srtr_record_table_params
static
Initial value:
= {
}
@ LWTRANCHE_PER_SESSION_RECORD_TYPE
Definition: lwlock.h:199
static int shared_record_table_compare(const void *a, const void *b, size_t size, void *arg)
Definition: typcache.c:216
static uint32 shared_record_table_hash(const void *a, size_t size, void *arg)
Definition: typcache.c:242
struct SharedRecordTableKey SharedRecordTableKey

Definition at line 257 of file typcache.c.

Referenced by SharedRecordTypmodRegistryAttach(), and SharedRecordTypmodRegistryInit().

◆ srtr_typmod_table_params

const dshash_parameters srtr_typmod_table_params
static
Initial value:
= {
sizeof(uint32),
}
dshash_hash dshash_memhash(const void *v, size_t size, void *arg)
Definition: dshash.c:581
int dshash_memcmp(const void *a, const void *b, size_t size, void *arg)
Definition: dshash.c:572
@ LWTRANCHE_PER_SESSION_RECORD_TYPMOD
Definition: lwlock.h:200

Definition at line 266 of file typcache.c.

Referenced by SharedRecordTypmodRegistryAttach(), and SharedRecordTypmodRegistryInit().

◆ tupledesc_id_counter

◆ TypeCacheHash

HTAB* TypeCacheHash = NULL
static