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

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
 

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 TupleDescRecordCacheArray = NULL
 
static uint64 * RecordIdentifierArray = 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 85 of file typcache.c.

◆ TCFLAGS_CHECKED_CMP_PROC

#define TCFLAGS_CHECKED_CMP_PROC   0x000040

Definition at line 90 of file typcache.c.

◆ TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS

#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS   0x080000

Definition at line 103 of file typcache.c.

◆ TCFLAGS_CHECKED_ELEM_PROPERTIES

#define TCFLAGS_CHECKED_ELEM_PROPERTIES   0x000200

Definition at line 93 of file typcache.c.

◆ TCFLAGS_CHECKED_EQ_OPR

#define TCFLAGS_CHECKED_EQ_OPR   0x000008

Definition at line 87 of file typcache.c.

◆ TCFLAGS_CHECKED_FIELD_PROPERTIES

#define TCFLAGS_CHECKED_FIELD_PROPERTIES   0x004000

Definition at line 98 of file typcache.c.

◆ TCFLAGS_CHECKED_GT_OPR

#define TCFLAGS_CHECKED_GT_OPR   0x000020

Definition at line 89 of file typcache.c.

◆ TCFLAGS_CHECKED_HASH_EXTENDED_PROC

#define TCFLAGS_CHECKED_HASH_EXTENDED_PROC   0x000100

Definition at line 92 of file typcache.c.

◆ TCFLAGS_CHECKED_HASH_OPCLASS

#define TCFLAGS_CHECKED_HASH_OPCLASS   0x000004

Definition at line 86 of file typcache.c.

◆ TCFLAGS_CHECKED_HASH_PROC

#define TCFLAGS_CHECKED_HASH_PROC   0x000080

Definition at line 91 of file typcache.c.

◆ TCFLAGS_CHECKED_LT_OPR

#define TCFLAGS_CHECKED_LT_OPR   0x000010

Definition at line 88 of file typcache.c.

◆ TCFLAGS_DOMAIN_BASE_IS_COMPOSITE

#define TCFLAGS_DOMAIN_BASE_IS_COMPOSITE   0x100000

Definition at line 104 of file typcache.c.

◆ TCFLAGS_HAVE_ELEM_COMPARE

#define TCFLAGS_HAVE_ELEM_COMPARE   0x000800

Definition at line 95 of file typcache.c.

◆ TCFLAGS_HAVE_ELEM_EQUALITY

#define TCFLAGS_HAVE_ELEM_EQUALITY   0x000400

Definition at line 94 of file typcache.c.

◆ TCFLAGS_HAVE_ELEM_EXTENDED_HASHING

#define TCFLAGS_HAVE_ELEM_EXTENDED_HASHING   0x002000

Definition at line 97 of file typcache.c.

◆ TCFLAGS_HAVE_ELEM_HASHING

#define TCFLAGS_HAVE_ELEM_HASHING   0x001000

Definition at line 96 of file typcache.c.

◆ TCFLAGS_HAVE_FIELD_COMPARE

#define TCFLAGS_HAVE_FIELD_COMPARE   0x010000

Definition at line 100 of file typcache.c.

◆ TCFLAGS_HAVE_FIELD_EQUALITY

#define TCFLAGS_HAVE_FIELD_EQUALITY   0x008000

Definition at line 99 of file typcache.c.

◆ TCFLAGS_HAVE_FIELD_EXTENDED_HASHING

#define TCFLAGS_HAVE_FIELD_EXTENDED_HASHING   0x040000

Definition at line 102 of file typcache.c.

◆ TCFLAGS_HAVE_FIELD_HASHING

#define TCFLAGS_HAVE_FIELD_HASHING   0x020000

Definition at line 101 of file typcache.c.

◆ TCFLAGS_HAVE_PG_TYPE_DATA

#define TCFLAGS_HAVE_PG_TYPE_DATA   0x000001

Definition at line 84 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:84

Definition at line 107 of file typcache.c.

Typedef Documentation

◆ RecordCacheEntry

◆ SharedRecordTableEntry

◆ SharedRecordTableKey

◆ SharedTypmodTableEntry

◆ TypeCacheEnumData

Function Documentation

◆ array_element_has_compare()

static bool array_element_has_compare ( TypeCacheEntry typentry)
static

Definition at line 1427 of file typcache.c.

1428 {
1429  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1431  return (typentry->flags & TCFLAGS_HAVE_ELEM_COMPARE) != 0;
1432 }
#define TCFLAGS_HAVE_ELEM_COMPARE
Definition: typcache.c:95
static void cache_array_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1451
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:93

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

1420 {
1421  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1423  return (typentry->flags & TCFLAGS_HAVE_ELEM_EQUALITY) != 0;
1424 }
#define TCFLAGS_HAVE_ELEM_EQUALITY
Definition: typcache.c:94

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

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

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

1436 {
1437  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1439  return (typentry->flags & TCFLAGS_HAVE_ELEM_HASHING) != 0;
1440 }
#define TCFLAGS_HAVE_ELEM_HASHING
Definition: typcache.c:96

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

2043 {
2044  if (type_id != RECORDOID)
2045  {
2046  /*
2047  * It's a named composite type, so use the regular typcache.
2048  */
2049  TypeCacheEntry *typentry;
2050 
2051  typentry = lookup_type_cache(type_id, TYPECACHE_TUPDESC);
2052  if (typentry->tupDesc == NULL)
2053  ereport(ERROR,
2054  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2055  errmsg("type %s is not composite",
2056  format_type_be(type_id))));
2057  Assert(typentry->tupDesc_identifier != 0);
2058  return typentry->tupDesc_identifier;
2059  }
2060  else
2061  {
2062  /*
2063  * It's a transient record type, so look in our record-type table.
2064  */
2065  if (typmod >= 0 && typmod < RecordCacheArrayLen &&
2066  RecordCacheArray[typmod] != NULL)
2067  {
2068  Assert(RecordIdentifierArray[typmod] != 0);
2069  return RecordIdentifierArray[typmod];
2070  }
2071 
2072  /* For anonymous or unrecognized record type, generate a new ID */
2073  return ++tupledesc_id_counter;
2074  }
2075 }
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143
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 TupleDesc * RecordCacheArray
Definition: typcache.c:277
static uint64 * RecordIdentifierArray
Definition: typcache.c:278
static int32 RecordCacheArrayLen
Definition: typcache.c:279
static uint64 tupledesc_id_counter
Definition: typcache.c:287
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:339
#define TYPECACHE_TUPDESC
Definition: typcache.h:144

References Assert(), ereport, errcode(), errmsg(), ERROR, format_type_be(), lookup_type_cache(), RecordCacheArray, RecordCacheArrayLen, RecordIdentifierArray, 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 1950 of file typcache.c.

1951 {
1952  RecordCacheEntry *recentry;
1953  TupleDesc entDesc;
1954  bool found;
1955  MemoryContext oldcxt;
1956 
1957  Assert(tupDesc->tdtypeid == RECORDOID);
1958 
1959  if (RecordCacheHash == NULL)
1960  {
1961  /* First time through: initialize the hash table */
1962  HASHCTL ctl;
1963 
1964  ctl.keysize = sizeof(TupleDesc); /* just the pointer */
1965  ctl.entrysize = sizeof(RecordCacheEntry);
1968  RecordCacheHash = hash_create("Record information cache", 64,
1969  &ctl,
1971 
1972  /* Also make sure CacheMemoryContext exists */
1973  if (!CacheMemoryContext)
1975  }
1976 
1977  /*
1978  * Find a hashtable entry for this tuple descriptor. We don't use
1979  * HASH_ENTER yet, because if it's missing, we need to make sure that all
1980  * the allocations succeed before we create the new entry.
1981  */
1983  (void *) &tupDesc,
1984  HASH_FIND, &found);
1985  if (found && recentry->tupdesc != NULL)
1986  {
1987  tupDesc->tdtypmod = recentry->tupdesc->tdtypmod;
1988  return;
1989  }
1990 
1991  /* Not present, so need to manufacture an entry */
1993 
1994  /* Look in the SharedRecordTypmodRegistry, if attached */
1995  entDesc = find_or_make_matching_shared_tupledesc(tupDesc);
1996  if (entDesc == NULL)
1997  {
1998  /*
1999  * Make sure we have room before we CreateTupleDescCopy() or advance
2000  * NextRecordTypmod.
2001  */
2003 
2004  /* Reference-counted local cache only. */
2005  entDesc = CreateTupleDescCopy(tupDesc);
2006  entDesc->tdrefcount = 1;
2007  entDesc->tdtypmod = NextRecordTypmod++;
2008  }
2009  else
2010  {
2012  }
2013 
2014  RecordCacheArray[entDesc->tdtypmod] = entDesc;
2015 
2016  /* Assign a unique tupdesc identifier, too. */
2018 
2019  /* Fully initialized; create the hash table entry */
2021  (void *) &tupDesc,
2022  HASH_ENTER, NULL);
2023  recentry->tupdesc = entDesc;
2024 
2025  /* Update the caller's tuple descriptor. */
2026  tupDesc->tdtypmod = entDesc->tdtypmod;
2027 
2028  MemoryContextSwitchTo(oldcxt);
2029 }
void CreateCacheMemoryContext(void)
Definition: catcache.c:614
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:349
@ 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:51
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
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:159
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:111
struct TupleDescData * TupleDesc
Definition: tupdesc.h:89
static TupleDesc find_or_make_matching_shared_tupledesc(TupleDesc tupdesc)
Definition: typcache.c:2758
static int32 NextRecordTypmod
Definition: typcache.c:280
static HTAB * RecordCacheHash
Definition: typcache.c:274
struct RecordCacheEntry RecordCacheEntry
static int record_type_typmod_compare(const void *a, const void *b, size_t size)
Definition: typcache.c:1934
static void ensure_record_cache_typmod_slot_exists(int32 typmod)
Definition: typcache.c:1702
static uint32 record_type_typmod_hash(const void *data, size_t size)
Definition: typcache.c:1923

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(), HASHCTL::keysize, HASHCTL::match, MemoryContextSwitchTo(), NextRecordTypmod, record_type_typmod_compare(), record_type_typmod_hash(), RecordCacheArray, RecordCacheHash, RecordIdentifierArray, TupleDescData::tdrefcount, TupleDescData::tdtypeid, TupleDescData::tdtypmod, RecordCacheEntry::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 1451 of file typcache.c.

1452 {
1453  Oid elem_type = get_base_element_type(typentry->type_id);
1454 
1455  if (OidIsValid(elem_type))
1456  {
1457  TypeCacheEntry *elementry;
1458 
1459  elementry = lookup_type_cache(elem_type,
1464  if (OidIsValid(elementry->eq_opr))
1465  typentry->flags |= TCFLAGS_HAVE_ELEM_EQUALITY;
1466  if (OidIsValid(elementry->cmp_proc))
1467  typentry->flags |= TCFLAGS_HAVE_ELEM_COMPARE;
1468  if (OidIsValid(elementry->hash_proc))
1469  typentry->flags |= TCFLAGS_HAVE_ELEM_HASHING;
1470  if (OidIsValid(elementry->hash_extended_proc))
1472  }
1474 }
#define OidIsValid(objectId)
Definition: c.h:710
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2789
unsigned int Oid
Definition: postgres_ext.h:31
Oid hash_extended_proc
Definition: typcache.h:66
#define TYPECACHE_EQ_OPR
Definition: typcache.h:136
#define TYPECACHE_HASH_EXTENDED_PROC
Definition: typcache.h:150
#define TYPECACHE_CMP_PROC
Definition: typcache.h:139
#define TYPECACHE_HASH_PROC
Definition: typcache.h:140

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

1675 {
1676  /* load up range link if we didn't already */
1677  if (typentry->rngtype == NULL &&
1678  typentry->typtype == TYPTYPE_MULTIRANGE)
1679  load_multirangetype_info(typentry);
1680 
1681  if (typentry->rngtype != NULL && typentry->rngtype->rngelemtype != NULL)
1682  {
1683  TypeCacheEntry *elementry;
1684 
1685  /* might need to calculate subtype's hash function properties */
1686  elementry = lookup_type_cache(typentry->rngtype->rngelemtype->type_id,
1689  if (OidIsValid(elementry->hash_proc))
1690  typentry->flags |= TCFLAGS_HAVE_ELEM_HASHING;
1691  if (OidIsValid(elementry->hash_extended_proc))
1693  }
1695 }
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:98
char typtype
Definition: typcache.h:43
struct TypeCacheEntry * rngtype
Definition: typcache.h:107
static void load_multirangetype_info(TypeCacheEntry *typentry)
Definition: typcache.c:964

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

1635 {
1636  /* load up subtype link if we didn't already */
1637  if (typentry->rngelemtype == NULL &&
1638  typentry->typtype == TYPTYPE_RANGE)
1639  load_rangetype_info(typentry);
1640 
1641  if (typentry->rngelemtype != NULL)
1642  {
1643  TypeCacheEntry *elementry;
1644 
1645  /* might need to calculate subtype's hash function properties */
1646  elementry = lookup_type_cache(typentry->rngelemtype->type_id,
1649  if (OidIsValid(elementry->hash_proc))
1650  typentry->flags |= TCFLAGS_HAVE_ELEM_HASHING;
1651  if (OidIsValid(elementry->hash_extended_proc))
1653  }
1655 }
static void load_rangetype_info(TypeCacheEntry *typentry)
Definition: typcache.c:907

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

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

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

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

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

1247 {
1249  DomainConstraintCache *dcc = ref->dcc;
1250 
1251  /* Paranoia --- be sure link is nulled before trying to release */
1252  if (dcc)
1253  {
1254  ref->constraints = NIL;
1255  ref->dcc = NULL;
1256  decr_dcc_refcount(dcc);
1257  }
1258 }
void * arg
#define NIL
Definition: pg_list.h:65
DomainConstraintCache * dcc
Definition: typcache.h:171
static void decr_dcc_refcount(DomainConstraintCache *dcc)
Definition: typcache.c:1235

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

1223 {
1224  const DomainConstraintState *const *ca = (const DomainConstraintState *const *) a;
1225  const DomainConstraintState *const *cb = (const DomainConstraintState *const *) b;
1226 
1227  return strcmp((*ca)->name, (*cb)->name);
1228 }
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 1235 of file typcache.c.

1236 {
1237  Assert(dcc->dccRefCount > 0);
1238  if (--(dcc->dccRefCount) <= 0)
1240 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
MemoryContext dccContext
Definition: typcache.c:127

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

1393 {
1394  TypeCacheEntry *typentry;
1395 
1396  /*
1397  * Note: a side effect is to cause the typcache's domain data to become
1398  * valid. This is fine since we'll likely need it soon if there is any.
1399  */
1400  typentry = lookup_type_cache(type_id, TYPECACHE_DOMAIN_CONSTR_INFO);
1401 
1402  return (typentry->domainData != NULL);
1403 }
DomainConstraintCache * domainData
Definition: typcache.h:120
#define TYPECACHE_DOMAIN_CONSTR_INFO
Definition: typcache.h:149

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

1703 {
1704  if (RecordCacheArray == NULL)
1705  {
1708  RecordIdentifierArray = (uint64 *)
1709  MemoryContextAllocZero(CacheMemoryContext, 64 * sizeof(uint64));
1710  RecordCacheArrayLen = 64;
1711  }
1712 
1713  if (typmod >= RecordCacheArrayLen)
1714  {
1715  int32 newlen = pg_nextpower2_32(typmod + 1);
1716 
1718  newlen * sizeof(TupleDesc));
1720  (newlen - RecordCacheArrayLen) * sizeof(TupleDesc));
1722  newlen * sizeof(uint64));
1724  (newlen - RecordCacheArrayLen) * sizeof(uint64));
1725  RecordCacheArrayLen = newlen;
1726  }
1727 }
signed int int32
Definition: c.h:429
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:906
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1188
static uint32 pg_nextpower2_32(uint32 num)
Definition: pg_bitutils.h:140

References CacheMemoryContext, MemoryContextAllocZero(), pg_nextpower2_32(), RecordCacheArray, RecordCacheArrayLen, RecordIdentifierArray, and repalloc().

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

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

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

2720 {
2721  const EnumItem *l = (const EnumItem *) left;
2722  const EnumItem *r = (const EnumItem *) right;
2723 
2724  if (l->enum_oid < r->enum_oid)
2725  return -1;
2726  else if (l->enum_oid > r->enum_oid)
2727  return 1;
2728  else
2729  return 0;
2730 }
Oid enum_oid
Definition: typcache.c:134

References EnumItem::enum_oid.

Referenced by find_enumitem(), and load_enum_cache_data().

◆ find_enumitem()

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

Definition at line 2702 of file typcache.c.

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

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

2759 {
2760  TupleDesc result;
2762  SharedRecordTableEntry *record_table_entry;
2763  SharedTypmodTableEntry *typmod_table_entry;
2764  dsa_pointer shared_dp;
2765  bool found;
2766  uint32 typmod;
2767 
2768  /* If not even attached, nothing to do. */
2770  return NULL;
2771 
2772  /* Try to find a matching tuple descriptor in the record table. */
2773  key.shared = false;
2774  key.u.local_tupdesc = tupdesc;
2775  record_table_entry = (SharedRecordTableEntry *)
2777  if (record_table_entry)
2778  {
2779  Assert(record_table_entry->key.shared);
2781  record_table_entry);
2782  result = (TupleDesc)
2784  record_table_entry->key.u.shared_tupdesc);
2785  Assert(result->tdrefcount == -1);
2786 
2787  return result;
2788  }
2789 
2790  /* Allocate a new typmod number. This will be wasted if we error out. */
2791  typmod = (int)
2793  1);
2794 
2795  /* Copy the TupleDesc into shared memory. */
2796  shared_dp = share_tupledesc(CurrentSession->area, tupdesc, typmod);
2797 
2798  /*
2799  * Create an entry in the typmod table so that others will understand this
2800  * typmod number.
2801  */
2802  PG_TRY();
2803  {
2804  typmod_table_entry = (SharedTypmodTableEntry *)
2806  &typmod, &found);
2807  if (found)
2808  elog(ERROR, "cannot create duplicate shared record typmod");
2809  }
2810  PG_CATCH();
2811  {
2812  dsa_free(CurrentSession->area, shared_dp);
2813  PG_RE_THROW();
2814  }
2815  PG_END_TRY();
2816  typmod_table_entry->typmod = typmod;
2817  typmod_table_entry->shared_tupdesc = shared_dp;
2819  typmod_table_entry);
2820 
2821  /*
2822  * Finally create an entry in the record table so others with matching
2823  * tuple descriptors can reuse the typmod.
2824  */
2825  record_table_entry = (SharedRecordTableEntry *)
2827  &found);
2828  if (found)
2829  {
2830  /*
2831  * Someone concurrently inserted a matching tuple descriptor since the
2832  * first time we checked. Use that one instead.
2833  */
2835  record_table_entry);
2836 
2837  /* Might as well free up the space used by the one we created. */
2839  &typmod);
2840  Assert(found);
2841  dsa_free(CurrentSession->area, shared_dp);
2842 
2843  /* Return the one we found. */
2844  Assert(record_table_entry->key.shared);
2845  result = (TupleDesc)
2847  record_table_entry->key.u.shared_tupdesc);
2848  Assert(result->tdrefcount == -1);
2849 
2850  return result;
2851  }
2852 
2853  /* Store it and return it. */
2854  record_table_entry->key.shared = true;
2855  record_table_entry->key.u.shared_tupdesc = shared_dp;
2857  record_table_entry);
2858  result = (TupleDesc)
2859  dsa_get_address(CurrentSession->area, shared_dp);
2860  Assert(result->tdrefcount == -1);
2861 
2862  return result;
2863 }
static uint32 pg_atomic_fetch_add_u32(volatile pg_atomic_uint32 *ptr, int32 add_)
Definition: atomics.h:328
unsigned int uint32
Definition: c.h:441
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:932
void dsa_free(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:820
uint64 dsa_pointer
Definition: dsa.h:62
bool dshash_delete_key(dshash_table *hash_table, const void *key)
Definition: dshash.c:510
void dshash_release_lock(dshash_table *hash_table, void *entry)
Definition: dshash.c:569
void * dshash_find(dshash_table *hash_table, const void *key, bool exclusive)
Definition: dshash.c:393
void * dshash_find_or_insert(dshash_table *hash_table, const void *key, bool *found)
Definition: dshash.c:438
#define PG_RE_THROW()
Definition: elog.h:340
#define PG_END_TRY()
Definition: elog.h:324
#define PG_TRY()
Definition: elog.h:299
#define PG_CATCH()
Definition: elog.h:309
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:198
dsa_pointer shared_tupdesc
Definition: typcache.c:187
union SharedRecordTableKey::@31 u
pg_atomic_uint32 next_typmod
Definition: typcache.c:173
dsa_pointer shared_tupdesc
Definition: typcache.c:208
static dsa_pointer share_tupledesc(dsa_area *area, TupleDesc tupdesc, uint32 typmod)
Definition: typcache.c:2737

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

1307 {
1308  /* Look up the typcache entry --- we assume it survives indefinitely */
1310  ref->need_exprstate = need_exprstate;
1311  /* For safety, establish the callback before acquiring a refcount */
1312  ref->refctx = refctx;
1313  ref->dcc = NULL;
1315  ref->callback.arg = (void *) ref;
1317  /* Acquire refcount if there are constraints, and set up exported list */
1318  if (ref->tcache->domainData)
1319  {
1320  ref->dcc = ref->tcache->domainData;
1321  ref->dcc->dccRefCount++;
1322  if (ref->need_exprstate)
1324  ref->refctx);
1325  else
1326  ref->constraints = ref->dcc->constraints;
1327  }
1328  else
1329  ref->constraints = NIL;
1330 }
void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)
Definition: mcxt.c:292
MemoryContext refctx
Definition: typcache.h:166
MemoryContextCallback callback
Definition: typcache.h:172
TypeCacheEntry * tcache
Definition: typcache.h:167
MemoryContextCallbackFunction func
Definition: palloc.h:49
static List * prep_domain_constraints(List *constraints, MemoryContext execctx)
Definition: typcache.c:1267
static void dccref_deletion_callback(void *arg)
Definition: typcache.c:1246

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

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

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, TYPEOID, 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 2547 of file typcache.c.

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

965 {
966  Oid rangetypeOid;
967 
968  rangetypeOid = get_multirange_range(typentry->type_id);
969  if (!OidIsValid(rangetypeOid))
970  elog(ERROR, "cache lookup failed for multirange type %u",
971  typentry->type_id);
972 
973  typentry->rngtype = lookup_type_cache(rangetypeOid, TYPECACHE_RANGE_INFO);
974 }
Oid get_multirange_range(Oid multirangeOid)
Definition: lsyscache.c:3443
#define TYPECACHE_RANGE_INFO
Definition: typcache.h:147

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

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

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, RANGETYPE, RegProcedureIsValid, ReleaseSysCache(), TypeCacheEntry::rng_canonical_finfo, TypeCacheEntry::rng_cmp_proc_finfo, TypeCacheEntry::rng_collation, 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 873 of file typcache.c.

874 {
875  Relation rel;
876 
877  if (!OidIsValid(typentry->typrelid)) /* should not happen */
878  elog(ERROR, "invalid typrelid for composite type %u",
879  typentry->type_id);
880  rel = relation_open(typentry->typrelid, AccessShareLock);
881  Assert(rel->rd_rel->reltype == typentry->type_id);
882 
883  /*
884  * Link to the tupdesc and increment its refcount (we assert it's a
885  * refcounted descriptor). We don't use IncrTupleDescRefCount() for this,
886  * because the reference mustn't be entered in the current resource owner;
887  * it can outlive the current query.
888  */
889  typentry->tupDesc = RelationGetDescr(rel);
890 
891  Assert(typentry->tupDesc->tdrefcount > 0);
892  typentry->tupDesc->tdrefcount++;
893 
894  /*
895  * In future, we could take some pains to not change tupDesc_identifier if
896  * the tupdesc didn't really change; but for now it's not worth it.
897  */
899 
901 }
#define RelationGetDescr(relation)
Definition: rel.h:515
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:109

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

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

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

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

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

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

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(), lookup_type_cache(), RecordCacheArray, RecordCacheArrayLen, RecordIdentifierArray, SharedTypmodTableEntry::shared_tupdesc, Session::shared_typmod_registry, Session::shared_typmod_table, TupleDescData::tdrefcount, TupleDescData::tdtypmod, 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 1847 of file typcache.c.

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

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

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

References array_element_has_compare(), array_element_has_equality(), array_element_has_extended_hashing(), array_element_has_hashing(), Assert(), BTEqualStrategyNumber, BTGreaterStrategyNumber, BTLessStrategyNumber, BTORDER_PROC, TypeCacheEntry::btree_opf, TypeCacheEntry::btree_opintype, CacheMemoryContext, CacheRegisterRelcacheCallback(), CacheRegisterSyscacheCallback(), CLAOID, TypeCacheEntry::cmp_proc, TypeCacheEntry::cmp_proc_finfo, CONSTROID, 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, TYPEOID, 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_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(), 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 1666 of file typcache.c.

1667 {
1668  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1670  return (typentry->flags & TCFLAGS_HAVE_ELEM_EXTENDED_HASHING) != 0;
1671 }
static void cache_multirange_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1674

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

1659 {
1660  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1662  return (typentry->flags & TCFLAGS_HAVE_ELEM_HASHING) != 0;
1663 }

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

1268 {
1269  List *result = NIL;
1270  MemoryContext oldcxt;
1271  ListCell *lc;
1272 
1273  oldcxt = MemoryContextSwitchTo(execctx);
1274 
1275  foreach(lc, constraints)
1276  {
1278  DomainConstraintState *newr;
1279 
1281  newr->constrainttype = r->constrainttype;
1282  newr->name = r->name;
1283  newr->check_expr = r->check_expr;
1284  newr->check_exprstate = ExecInitExpr(r->check_expr, NULL);
1285 
1286  result = lappend(result, newr);
1287  }
1288 
1289  MemoryContextSwitchTo(oldcxt);
1290 
1291  return result;
1292 }
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:160
List * lappend(List *list, void *datum)
Definition: list.c:336
#define lfirst(lc)
Definition: pg_list.h:169
Definition: pg_list.h:51

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

1627 {
1628  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1630  return (typentry->flags & TCFLAGS_HAVE_ELEM_EXTENDED_HASHING) != 0;
1631 }
static void cache_range_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1634

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

1619 {
1620  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1622  return (typentry->flags & TCFLAGS_HAVE_ELEM_HASHING) != 0;
1623 }

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

1490 {
1491  if (!(typentry->flags & TCFLAGS_CHECKED_FIELD_PROPERTIES))
1493  return (typentry->flags & TCFLAGS_HAVE_FIELD_COMPARE) != 0;
1494 }
static void cache_record_field_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1513

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

1482 {
1483  if (!(typentry->flags & TCFLAGS_CHECKED_FIELD_PROPERTIES))
1485  return (typentry->flags & TCFLAGS_HAVE_FIELD_EQUALITY) != 0;
1486 }

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

1498 {
1499  if (!(typentry->flags & TCFLAGS_CHECKED_FIELD_PROPERTIES))
1501  return (typentry->flags & TCFLAGS_HAVE_FIELD_HASHING) != 0;
1502 }

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

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

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

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

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

2738 {
2739  dsa_pointer shared_dp;
2740  TupleDesc shared;
2741 
2742  shared_dp = dsa_allocate(area, TupleDescSize(tupdesc));
2743  shared = (TupleDesc) dsa_get_address(area, shared_dp);
2744  TupleDescCopy(shared, tupdesc);
2745  shared->tdtypmod = typmod;
2746 
2747  return shared_dp;
2748 }
#define dsa_allocate(area, size)
Definition: dsa.h:84
void TupleDescCopy(TupleDesc dst, TupleDesc src)
Definition: tupdesc.c:229
#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 215 of file typcache.c.

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

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

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

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

2871 {
2872  /* Be cautious here: maybe we didn't finish initializing. */
2873  if (CurrentSession->shared_record_table != NULL)
2874  {
2877  }
2878  if (CurrentSession->shared_typmod_table != NULL)
2879  {
2882  }
2884 }
void dshash_detach(dshash_table *hash_table)
Definition: dshash.c:310

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

2205 {
2206  MemoryContext old_context;
2207  dshash_table *record_table;
2208  dshash_table *typmod_table;
2209 
2211 
2212  /* We can't already be attached to a shared registry. */
2213  Assert(CurrentSession != NULL);
2214  Assert(CurrentSession->segment != NULL);
2215  Assert(CurrentSession->area != NULL);
2219 
2220  /*
2221  * We can't already have typmods in our local cache, because they'd clash
2222  * with those imported by SharedRecordTypmodRegistryInit. This should be
2223  * a freshly started parallel worker. If we ever support worker
2224  * recycling, a worker would need to zap its local cache in between
2225  * servicing different queries, in order to be able to call this and
2226  * synchronize typmods with a new leader; but that's problematic because
2227  * we can't be very sure that record-typmod-related state hasn't escaped
2228  * to anywhere else in the process.
2229  */
2230  Assert(NextRecordTypmod == 0);
2231 
2232  old_context = MemoryContextSwitchTo(TopMemoryContext);
2233 
2234  /* Attach to the two hash tables. */
2235  record_table = dshash_attach(CurrentSession->area,
2237  registry->record_table_handle,
2238  CurrentSession->area);
2239  typmod_table = dshash_attach(CurrentSession->area,
2241  registry->typmod_table_handle,
2242  NULL);
2243 
2244  MemoryContextSwitchTo(old_context);
2245 
2246  /*
2247  * Set up detach hook to run at worker exit. Currently this is the same
2248  * as the leader's detach hook, but in future they might need to be
2249  * different.
2250  */
2253  PointerGetDatum(registry));
2254 
2255  /*
2256  * Set up the session state that will tell assign_record_type_typmod and
2257  * lookup_rowtype_tupdesc_internal about the shared registry.
2258  */
2260  CurrentSession->shared_record_table = record_table;
2261  CurrentSession->shared_typmod_table = typmod_table;
2262 }
dshash_table * dshash_attach(dsa_area *area, const dshash_parameters *params, dshash_table_handle handle, void *arg)
Definition: dshash.c:271
void on_dsm_detach(dsm_segment *seg, on_dsm_detach_callback function, Datum arg)
Definition: dsm.c:1104
#define IsParallelWorker()
Definition: parallel.h:61
MemoryContext TopMemoryContext
Definition: mcxt.c:48
#define PointerGetDatum(X)
Definition: postgres.h:600
dsm_segment * segment
Definition: session.h:27
dshash_table_handle typmod_table_handle
Definition: typcache.c:171
dshash_table_handle record_table_handle
Definition: typcache.c:169
static const dshash_parameters srtr_typmod_table_params
Definition: typcache.c:265
static void shared_record_typmod_registry_detach(dsm_segment *segment, Datum datum)
Definition: typcache.c:2870
static const dshash_parameters srtr_record_table_params
Definition: typcache.c:256

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

2084 {
2085  return sizeof(SharedRecordTypmodRegistry);
2086 }
struct SharedRecordTypmodRegistry SharedRecordTypmodRegistry
Definition: typcache.h:175

Referenced by GetSessionDsmHandle().

◆ SharedRecordTypmodRegistryInit()

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

Definition at line 2105 of file typcache.c.

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

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

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

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

2393 {
2395  TypeCacheEntry *typentry;
2396 
2397  /* TypeCacheHash must exist, else this callback wouldn't be registered */
2399  while ((typentry = (TypeCacheEntry *) hash_seq_search(&status)) != NULL)
2400  {
2401  /* Reset equality/comparison/hashing validity information */
2402  typentry->flags &= ~TCFLAGS_OPERATOR_FLAGS;
2403  }
2404 }
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1436
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1426
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:229
#define TCFLAGS_OPERATOR_FLAGS
Definition: typcache.c:107

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

Referenced by lookup_type_cache().

◆ TypeCacheRelCallback()

static void TypeCacheRelCallback ( Datum  arg,
Oid  relid 
)
static

Definition at line 2287 of file typcache.c.

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

References Assert(), TypeCacheEntry::flags, FreeTupleDesc(), hash_seq_init(), hash_seq_search(), InvalidOid, status(), 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 2352 of file typcache.c.

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

References TypeCacheEntry::flags, hash_seq_init(), hash_seq_search(), status(), 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 1343 of file typcache.c.

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

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

Referenced by assign_record_type_typmod().

◆ RecordIdentifierArray

uint64* RecordIdentifierArray = NULL
static

◆ srtr_record_table_params

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

Definition at line 256 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:598
int dshash_memcmp(const void *a, const void *b, size_t size, void *arg)
Definition: dshash.c:589
@ LWTRANCHE_PER_SESSION_RECORD_TYPMOD
Definition: lwlock.h:188

Definition at line 265 of file typcache.c.

Referenced by SharedRecordTypmodRegistryAttach(), and SharedRecordTypmodRegistryInit().

◆ tupledesc_id_counter

◆ TypeCacheHash

HTAB* TypeCacheHash = NULL
static