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

Referenced by lookup_type_cache().

◆ TCFLAGS_CHECKED_CMP_PROC

#define TCFLAGS_CHECKED_CMP_PROC   0x000040

Definition at line 89 of file typcache.c.

Referenced by lookup_type_cache().

◆ TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS

#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS   0x080000

◆ TCFLAGS_CHECKED_ELEM_PROPERTIES

◆ TCFLAGS_CHECKED_EQ_OPR

#define TCFLAGS_CHECKED_EQ_OPR   0x000008

Definition at line 86 of file typcache.c.

Referenced by lookup_type_cache().

◆ TCFLAGS_CHECKED_FIELD_PROPERTIES

#define TCFLAGS_CHECKED_FIELD_PROPERTIES   0x004000

◆ TCFLAGS_CHECKED_GT_OPR

#define TCFLAGS_CHECKED_GT_OPR   0x000020

Definition at line 88 of file typcache.c.

Referenced by lookup_type_cache().

◆ TCFLAGS_CHECKED_HASH_EXTENDED_PROC

#define TCFLAGS_CHECKED_HASH_EXTENDED_PROC   0x000100

Definition at line 91 of file typcache.c.

Referenced by lookup_type_cache().

◆ TCFLAGS_CHECKED_HASH_OPCLASS

#define TCFLAGS_CHECKED_HASH_OPCLASS   0x000004

Definition at line 85 of file typcache.c.

Referenced by lookup_type_cache().

◆ TCFLAGS_CHECKED_HASH_PROC

#define TCFLAGS_CHECKED_HASH_PROC   0x000080

Definition at line 90 of file typcache.c.

Referenced by lookup_type_cache().

◆ TCFLAGS_CHECKED_LT_OPR

#define TCFLAGS_CHECKED_LT_OPR   0x000010

Definition at line 87 of file typcache.c.

Referenced by lookup_type_cache().

◆ TCFLAGS_DOMAIN_BASE_IS_COMPOSITE

#define TCFLAGS_DOMAIN_BASE_IS_COMPOSITE   0x100000

Definition at line 103 of file typcache.c.

Referenced by cache_record_field_properties(), and TypeCacheRelCallback().

◆ TCFLAGS_HAVE_ELEM_COMPARE

#define TCFLAGS_HAVE_ELEM_COMPARE   0x000800

Definition at line 94 of file typcache.c.

Referenced by array_element_has_compare(), and cache_array_element_properties().

◆ TCFLAGS_HAVE_ELEM_EQUALITY

#define TCFLAGS_HAVE_ELEM_EQUALITY   0x000400

Definition at line 93 of file typcache.c.

Referenced by array_element_has_equality(), and cache_array_element_properties().

◆ TCFLAGS_HAVE_ELEM_EXTENDED_HASHING

◆ TCFLAGS_HAVE_ELEM_HASHING

◆ TCFLAGS_HAVE_FIELD_COMPARE

#define TCFLAGS_HAVE_FIELD_COMPARE   0x010000

Definition at line 99 of file typcache.c.

Referenced by cache_record_field_properties(), and record_fields_have_compare().

◆ TCFLAGS_HAVE_FIELD_EQUALITY

#define TCFLAGS_HAVE_FIELD_EQUALITY   0x008000

Definition at line 98 of file typcache.c.

Referenced by cache_record_field_properties(), and record_fields_have_equality().

◆ TCFLAGS_HAVE_FIELD_EXTENDED_HASHING

#define TCFLAGS_HAVE_FIELD_EXTENDED_HASHING   0x040000

◆ TCFLAGS_HAVE_FIELD_HASHING

#define TCFLAGS_HAVE_FIELD_HASHING   0x020000

Definition at line 100 of file typcache.c.

Referenced by cache_record_field_properties(), and record_fields_have_hashing().

◆ TCFLAGS_HAVE_PG_TYPE_DATA

#define TCFLAGS_HAVE_PG_TYPE_DATA   0x000001

Definition at line 83 of file typcache.c.

Referenced by lookup_type_cache(), and TypeCacheTypCallback().

◆ 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:83

Definition at line 106 of file typcache.c.

Referenced by TypeCacheOpcCallback(), and TypeCacheRelCallback().

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

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

Referenced by lookup_type_cache().

1427 {
1428  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1430  return (typentry->flags & TCFLAGS_HAVE_ELEM_COMPARE) != 0;
1431 }
#define TCFLAGS_HAVE_ELEM_COMPARE
Definition: typcache.c:94
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:92
static void cache_array_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1450

◆ array_element_has_equality()

static bool array_element_has_equality ( TypeCacheEntry typentry)
static

Definition at line 1418 of file typcache.c.

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

Referenced by lookup_type_cache().

1419 {
1420  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1422  return (typentry->flags & TCFLAGS_HAVE_ELEM_EQUALITY) != 0;
1423 }
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:92
static void cache_array_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1450
#define TCFLAGS_HAVE_ELEM_EQUALITY
Definition: typcache.c:93

◆ array_element_has_extended_hashing()

static bool array_element_has_extended_hashing ( TypeCacheEntry typentry)
static

Definition at line 1442 of file typcache.c.

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

Referenced by lookup_type_cache().

1443 {
1444  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1446  return (typentry->flags & TCFLAGS_HAVE_ELEM_EXTENDED_HASHING) != 0;
1447 }
#define TCFLAGS_HAVE_ELEM_EXTENDED_HASHING
Definition: typcache.c:96
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:92
static void cache_array_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1450

◆ array_element_has_hashing()

static bool array_element_has_hashing ( TypeCacheEntry typentry)
static

Definition at line 1434 of file typcache.c.

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

Referenced by lookup_type_cache().

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

◆ assign_record_type_identifier()

uint64 assign_record_type_identifier ( Oid  type_id,
int32  typmod 
)

Definition at line 2020 of file typcache.c.

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

2021 {
2022  if (type_id != RECORDOID)
2023  {
2024  /*
2025  * It's a named composite type, so use the regular typcache.
2026  */
2027  TypeCacheEntry *typentry;
2028 
2029  typentry = lookup_type_cache(type_id, TYPECACHE_TUPDESC);
2030  if (typentry->tupDesc == NULL)
2031  ereport(ERROR,
2032  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2033  errmsg("type %s is not composite",
2034  format_type_be(type_id))));
2035  Assert(typentry->tupDesc_identifier != 0);
2036  return typentry->tupDesc_identifier;
2037  }
2038  else
2039  {
2040  /*
2041  * It's a transient record type, so look in our record-type table.
2042  */
2043  if (typmod >= 0 && typmod < RecordCacheArrayLen &&
2044  RecordCacheArray[typmod] != NULL)
2045  {
2046  Assert(RecordIdentifierArray[typmod] != 0);
2047  return RecordIdentifierArray[typmod];
2048  }
2049 
2050  /* For anonymous or unrecognized record type, generate a new ID */
2051  return ++tupledesc_id_counter;
2052  }
2053 }
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
static uint64 tupledesc_id_counter
Definition: typcache.c:286
static TupleDesc * RecordCacheArray
Definition: typcache.c:276
#define ERROR
Definition: elog.h:46
static int32 RecordCacheArrayLen
Definition: typcache.c:278
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:338
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
uint64 tupDesc_identifier
Definition: typcache.h:90
int errmsg(const char *fmt,...)
Definition: elog.c:909
TupleDesc tupDesc
Definition: typcache.h:89
#define TYPECACHE_TUPDESC
Definition: typcache.h:144
static uint64 * RecordIdentifierArray
Definition: typcache.c:277

◆ assign_record_type_typmod()

void assign_record_type_typmod ( TupleDesc  tupDesc)

Definition at line 1946 of file typcache.c.

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_FUNCTION, hash_search(), HASHCTL::keysize, HASHCTL::match, MemoryContextSwitchTo(), NextRecordTypmod, record_type_typmod_compare(), record_type_typmod_hash(), 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().

1947 {
1948  RecordCacheEntry *recentry;
1949  TupleDesc entDesc;
1950  bool found;
1951  MemoryContext oldcxt;
1952 
1953  Assert(tupDesc->tdtypeid == RECORDOID);
1954 
1955  if (RecordCacheHash == NULL)
1956  {
1957  /* First time through: initialize the hash table */
1958  HASHCTL ctl;
1959 
1960  ctl.keysize = sizeof(TupleDesc); /* just the pointer */
1961  ctl.entrysize = sizeof(RecordCacheEntry);
1964  RecordCacheHash = hash_create("Record information cache", 64,
1965  &ctl,
1967 
1968  /* Also make sure CacheMemoryContext exists */
1969  if (!CacheMemoryContext)
1971  }
1972 
1973  /* Find or create a hashtable entry for this tuple descriptor */
1975  (void *) &tupDesc,
1976  HASH_ENTER, &found);
1977  if (found && recentry->tupdesc != NULL)
1978  {
1979  tupDesc->tdtypmod = recentry->tupdesc->tdtypmod;
1980  return;
1981  }
1982 
1983  /* Not present, so need to manufacture an entry */
1984  recentry->tupdesc = NULL;
1986 
1987  /* Look in the SharedRecordTypmodRegistry, if attached */
1988  entDesc = find_or_make_matching_shared_tupledesc(tupDesc);
1989  if (entDesc == NULL)
1990  {
1991  /* Reference-counted local cache only. */
1992  entDesc = CreateTupleDescCopy(tupDesc);
1993  entDesc->tdrefcount = 1;
1994  entDesc->tdtypmod = NextRecordTypmod++;
1995  }
1997  RecordCacheArray[entDesc->tdtypmod] = entDesc;
1998  recentry->tupdesc = entDesc;
1999 
2000  /* Assign a unique tupdesc identifier, too. */
2002 
2003  /* Update the caller's tuple descriptor. */
2004  tupDesc->tdtypmod = entDesc->tdtypmod;
2005 
2006  MemoryContextSwitchTo(oldcxt);
2007 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111
#define HASH_ELEM
Definition: hsearch.h:95
static TupleDesc find_or_make_matching_shared_tupledesc(TupleDesc tupdesc)
Definition: typcache.c:2736
struct RecordCacheEntry RecordCacheEntry
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Size entrysize
Definition: hsearch.h:76
static uint64 tupledesc_id_counter
Definition: typcache.c:286
static HTAB * RecordCacheHash
Definition: typcache.c:273
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
static TupleDesc * RecordCacheArray
Definition: typcache.c:276
int32 tdtypmod
Definition: tupdesc.h:83
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:349
static int32 NextRecordTypmod
Definition: typcache.c:279
static void ensure_record_cache_typmod_slot_exists(int32 typmod)
Definition: typcache.c:1698
Size keysize
Definition: hsearch.h:75
HashCompareFunc match
Definition: hsearch.h:80
static uint32 record_type_typmod_hash(const void *data, size_t size)
Definition: typcache.c:1919
#define Assert(condition)
Definition: c.h:804
#define HASH_COMPARE
Definition: hsearch.h:99
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
Oid tdtypeid
Definition: tupdesc.h:82
struct TupleDescData * TupleDesc
Definition: tupdesc.h:89
static int record_type_typmod_compare(const void *a, const void *b, size_t size)
Definition: typcache.c:1930
TupleDesc tupdesc
Definition: typcache.c:158
int tdrefcount
Definition: tupdesc.h:84
static uint64 * RecordIdentifierArray
Definition: typcache.c:277
HashValueFunc hash
Definition: hsearch.h:78
#define HASH_FUNCTION
Definition: hsearch.h:98
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ cache_array_element_properties()

static void cache_array_element_properties ( TypeCacheEntry typentry)
static

Definition at line 1450 of file typcache.c.

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

1451 {
1452  Oid elem_type = get_base_element_type(typentry->type_id);
1453 
1454  if (OidIsValid(elem_type))
1455  {
1456  TypeCacheEntry *elementry;
1457 
1458  elementry = lookup_type_cache(elem_type,
1463  if (OidIsValid(elementry->eq_opr))
1464  typentry->flags |= TCFLAGS_HAVE_ELEM_EQUALITY;
1465  if (OidIsValid(elementry->cmp_proc))
1466  typentry->flags |= TCFLAGS_HAVE_ELEM_COMPARE;
1467  if (OidIsValid(elementry->hash_proc))
1468  typentry->flags |= TCFLAGS_HAVE_ELEM_HASHING;
1469  if (OidIsValid(elementry->hash_extended_proc))
1471  }
1473 }
#define TCFLAGS_HAVE_ELEM_COMPARE
Definition: typcache.c:94
#define TYPECACHE_EQ_OPR
Definition: typcache.h:136
#define TCFLAGS_HAVE_ELEM_EXTENDED_HASHING
Definition: typcache.c:96
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:92
Oid hash_extended_proc
Definition: typcache.h:66
#define TYPECACHE_HASH_EXTENDED_PROC
Definition: typcache.h:150
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:338
#define TYPECACHE_CMP_PROC
Definition: typcache.h:139
#define TCFLAGS_HAVE_ELEM_EQUALITY
Definition: typcache.c:93
#define TCFLAGS_HAVE_ELEM_HASHING
Definition: typcache.c:95
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2779
#define TYPECACHE_HASH_PROC
Definition: typcache.h:140

◆ cache_multirange_element_properties()

static void cache_multirange_element_properties ( TypeCacheEntry typentry)
static

Definition at line 1670 of file typcache.c.

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

1671 {
1672  /* load up range link if we didn't already */
1673  if (typentry->rngtype == NULL &&
1674  typentry->typtype == TYPTYPE_MULTIRANGE)
1675  load_multirangetype_info(typentry);
1676 
1677  if (typentry->rngtype != NULL && typentry->rngtype->rngelemtype != NULL)
1678  {
1679  TypeCacheEntry *elementry;
1680 
1681  /* might need to calculate subtype's hash function properties */
1682  elementry = lookup_type_cache(typentry->rngtype->rngelemtype->type_id,
1685  if (OidIsValid(elementry->hash_proc))
1686  typentry->flags |= TCFLAGS_HAVE_ELEM_HASHING;
1687  if (OidIsValid(elementry->hash_extended_proc))
1689  }
1691 }
#define TCFLAGS_HAVE_ELEM_EXTENDED_HASHING
Definition: typcache.c:96
#define OidIsValid(objectId)
Definition: c.h:710
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:92
static void load_multirangetype_info(TypeCacheEntry *typentry)
Definition: typcache.c:963
Oid hash_extended_proc
Definition: typcache.h:66
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:98
#define TYPECACHE_HASH_EXTENDED_PROC
Definition: typcache.h:150
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:338
char typtype
Definition: typcache.h:43
struct TypeCacheEntry * rngtype
Definition: typcache.h:107
#define TCFLAGS_HAVE_ELEM_HASHING
Definition: typcache.c:95
#define TYPECACHE_HASH_PROC
Definition: typcache.h:140

◆ cache_range_element_properties()

static void cache_range_element_properties ( TypeCacheEntry typentry)
static

Definition at line 1630 of file typcache.c.

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

1631 {
1632  /* load up subtype link if we didn't already */
1633  if (typentry->rngelemtype == NULL &&
1634  typentry->typtype == TYPTYPE_RANGE)
1635  load_rangetype_info(typentry);
1636 
1637  if (typentry->rngelemtype != NULL)
1638  {
1639  TypeCacheEntry *elementry;
1640 
1641  /* might need to calculate subtype's hash function properties */
1642  elementry = lookup_type_cache(typentry->rngelemtype->type_id,
1645  if (OidIsValid(elementry->hash_proc))
1646  typentry->flags |= TCFLAGS_HAVE_ELEM_HASHING;
1647  if (OidIsValid(elementry->hash_extended_proc))
1649  }
1651 }
#define TCFLAGS_HAVE_ELEM_EXTENDED_HASHING
Definition: typcache.c:96
#define OidIsValid(objectId)
Definition: c.h:710
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:92
Oid hash_extended_proc
Definition: typcache.h:66
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:98
#define TYPECACHE_HASH_EXTENDED_PROC
Definition: typcache.h:150
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:338
static void load_rangetype_info(TypeCacheEntry *typentry)
Definition: typcache.c:906
char typtype
Definition: typcache.h:43
#define TCFLAGS_HAVE_ELEM_HASHING
Definition: typcache.c:95
#define TYPECACHE_HASH_PROC
Definition: typcache.h:140

◆ cache_record_field_properties()

static void cache_record_field_properties ( TypeCacheEntry typentry)
static

Definition at line 1512 of file typcache.c.

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

1513 {
1514  /*
1515  * For type RECORD, we can't really tell what will work, since we don't
1516  * have access here to the specific anonymous type. Just assume that
1517  * everything will (we may get a failure at runtime ...)
1518  */
1519  if (typentry->type_id == RECORDOID)
1520  {
1521  typentry->flags |= (TCFLAGS_HAVE_FIELD_EQUALITY |
1525  }
1526  else if (typentry->typtype == TYPTYPE_COMPOSITE)
1527  {
1528  TupleDesc tupdesc;
1529  int newflags;
1530  int i;
1531 
1532  /* Fetch composite type's tupdesc if we don't have it already */
1533  if (typentry->tupDesc == NULL)
1534  load_typcache_tupdesc(typentry);
1535  tupdesc = typentry->tupDesc;
1536 
1537  /* Must bump the refcount while we do additional catalog lookups */
1538  IncrTupleDescRefCount(tupdesc);
1539 
1540  /* Have each property if all non-dropped fields have the property */
1541  newflags = (TCFLAGS_HAVE_FIELD_EQUALITY |
1545  for (i = 0; i < tupdesc->natts; i++)
1546  {
1547  TypeCacheEntry *fieldentry;
1548  Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
1549 
1550  if (attr->attisdropped)
1551  continue;
1552 
1553  fieldentry = lookup_type_cache(attr->atttypid,
1558  if (!OidIsValid(fieldentry->eq_opr))
1559  newflags &= ~TCFLAGS_HAVE_FIELD_EQUALITY;
1560  if (!OidIsValid(fieldentry->cmp_proc))
1561  newflags &= ~TCFLAGS_HAVE_FIELD_COMPARE;
1562  if (!OidIsValid(fieldentry->hash_proc))
1563  newflags &= ~TCFLAGS_HAVE_FIELD_HASHING;
1564  if (!OidIsValid(fieldentry->hash_extended_proc))
1566 
1567  /* We can drop out of the loop once we disprove all bits */
1568  if (newflags == 0)
1569  break;
1570  }
1571  typentry->flags |= newflags;
1572 
1573  DecrTupleDescRefCount(tupdesc);
1574  }
1575  else if (typentry->typtype == TYPTYPE_DOMAIN)
1576  {
1577  /* If it's domain over composite, copy base type's properties */
1578  TypeCacheEntry *baseentry;
1579 
1580  /* load up basetype info if we didn't already */
1581  if (typentry->domainBaseType == InvalidOid)
1582  {
1583  typentry->domainBaseTypmod = -1;
1584  typentry->domainBaseType =
1585  getBaseTypeAndTypmod(typentry->type_id,
1586  &typentry->domainBaseTypmod);
1587  }
1588  baseentry = lookup_type_cache(typentry->domainBaseType,
1593  if (baseentry->typtype == TYPTYPE_COMPOSITE)
1594  {
1596  typentry->flags |= baseentry->flags & (TCFLAGS_HAVE_FIELD_EQUALITY |
1600  }
1601  }
1603 }
static void load_typcache_tupdesc(TypeCacheEntry *typentry)
Definition: typcache.c:872
void IncrTupleDescRefCount(TupleDesc tupdesc)
Definition: tupdesc.c:366
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition: lsyscache.c:2485
#define TCFLAGS_CHECKED_FIELD_PROPERTIES
Definition: typcache.c:97
#define TCFLAGS_DOMAIN_BASE_IS_COMPOSITE
Definition: typcache.c:103
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define TYPECACHE_EQ_OPR
Definition: typcache.h:136
#define OidIsValid(objectId)
Definition: c.h:710
Oid domainBaseType
Definition: typcache.h:113
#define TCFLAGS_HAVE_FIELD_COMPARE
Definition: typcache.c:99
#define TCFLAGS_HAVE_FIELD_HASHING
Definition: typcache.c:100
int32 domainBaseTypmod
Definition: typcache.h:114
#define TCFLAGS_HAVE_FIELD_EXTENDED_HASHING
Definition: typcache.c:101
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:203
Oid hash_extended_proc
Definition: typcache.h:66
#define TCFLAGS_HAVE_FIELD_EQUALITY
Definition: typcache.c:98
#define TYPECACHE_HASH_EXTENDED_PROC
Definition: typcache.h:150
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:338
#define InvalidOid
Definition: postgres_ext.h:36
#define TYPECACHE_CMP_PROC
Definition: typcache.h:139
char typtype
Definition: typcache.h:43
void DecrTupleDescRefCount(TupleDesc tupdesc)
Definition: tupdesc.c:384
int i
TupleDesc tupDesc
Definition: typcache.h:89
#define TYPECACHE_HASH_PROC
Definition: typcache.h:140

◆ compare_values_of_enum()

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

Definition at line 2452 of file typcache.c.

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

2453 {
2454  TypeCacheEnumData *enumdata;
2455  EnumItem *item1;
2456  EnumItem *item2;
2457 
2458  /*
2459  * Equal OIDs are certainly equal --- this case was probably handled by
2460  * our caller, but we may as well check.
2461  */
2462  if (arg1 == arg2)
2463  return 0;
2464 
2465  /* Load up the cache if first time through */
2466  if (tcache->enumData == NULL)
2467  load_enum_cache_data(tcache);
2468  enumdata = tcache->enumData;
2469 
2470  /*
2471  * If both OIDs are known-sorted, we can just compare them directly.
2472  */
2473  if (enum_known_sorted(enumdata, arg1) &&
2474  enum_known_sorted(enumdata, arg2))
2475  {
2476  if (arg1 < arg2)
2477  return -1;
2478  else
2479  return 1;
2480  }
2481 
2482  /*
2483  * Slow path: we have to identify their actual sort-order positions.
2484  */
2485  item1 = find_enumitem(enumdata, arg1);
2486  item2 = find_enumitem(enumdata, arg2);
2487 
2488  if (item1 == NULL || item2 == NULL)
2489  {
2490  /*
2491  * We couldn't find one or both values. That means the enum has
2492  * changed under us, so re-initialize the cache and try again. We
2493  * don't bother retrying the known-sorted case in this path.
2494  */
2495  load_enum_cache_data(tcache);
2496  enumdata = tcache->enumData;
2497 
2498  item1 = find_enumitem(enumdata, arg1);
2499  item2 = find_enumitem(enumdata, arg2);
2500 
2501  /*
2502  * If we still can't find the values, complain: we must have corrupt
2503  * data.
2504  */
2505  if (item1 == NULL)
2506  elog(ERROR, "enum value %u not found in cache for enum %s",
2507  arg1, format_type_be(tcache->type_id));
2508  if (item2 == NULL)
2509  elog(ERROR, "enum value %u not found in cache for enum %s",
2510  arg2, format_type_be(tcache->type_id));
2511  }
2512 
2513  if (item1->sort_order < item2->sort_order)
2514  return -1;
2515  else if (item1->sort_order > item2->sort_order)
2516  return 1;
2517  else
2518  return 0;
2519 }
struct TypeCacheEnumData * enumData
Definition: typcache.h:129
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
#define ERROR
Definition: elog.h:46
static bool enum_known_sorted(TypeCacheEnumData *enumdata, Oid arg)
Definition: typcache.c:2423
static EnumItem * find_enumitem(TypeCacheEnumData *enumdata, Oid arg)
Definition: typcache.c:2680
static void load_enum_cache_data(TypeCacheEntry *tcache)
Definition: typcache.c:2525
float4 sort_order
Definition: typcache.c:134
#define elog(elevel,...)
Definition: elog.h:232

◆ dccref_deletion_callback()

static void dccref_deletion_callback ( void *  arg)
static

Definition at line 1245 of file typcache.c.

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

Referenced by InitDomainConstraintRef().

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

◆ dcs_cmp()

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

Definition at line 1221 of file typcache.c.

Referenced by load_domaintype_info().

1222 {
1223  const DomainConstraintState *const *ca = (const DomainConstraintState *const *) a;
1224  const DomainConstraintState *const *cb = (const DomainConstraintState *const *) b;
1225 
1226  return strcmp((*ca)->name, (*cb)->name);
1227 }

◆ decr_dcc_refcount()

static void decr_dcc_refcount ( DomainConstraintCache dcc)
static

Definition at line 1234 of file typcache.c.

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

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

1235 {
1236  Assert(dcc->dccRefCount > 0);
1237  if (--(dcc->dccRefCount) <= 0)
1239 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
MemoryContext dccContext
Definition: typcache.c:126
#define Assert(condition)
Definition: c.h:804

◆ DomainHasConstraints()

bool DomainHasConstraints ( Oid  type_id)

Definition at line 1391 of file typcache.c.

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

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

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

◆ ensure_record_cache_typmod_slot_exists()

static void ensure_record_cache_typmod_slot_exists ( int32  typmod)
static

Definition at line 1698 of file typcache.c.

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

Referenced by assign_record_type_typmod(), and lookup_rowtype_tupdesc_internal().

1699 {
1700  if (RecordCacheArray == NULL)
1701  {
1704  RecordIdentifierArray = (uint64 *)
1705  MemoryContextAllocZero(CacheMemoryContext, 64 * sizeof(uint64));
1706  RecordCacheArrayLen = 64;
1707  }
1708 
1709  if (typmod >= RecordCacheArrayLen)
1710  {
1711  int32 newlen = RecordCacheArrayLen * 2;
1712 
1713  while (typmod >= newlen)
1714  newlen *= 2;
1715 
1717  newlen * sizeof(TupleDesc));
1719  (newlen - RecordCacheArrayLen) * sizeof(TupleDesc));
1721  newlen * sizeof(uint64));
1723  (newlen - RecordCacheArrayLen) * sizeof(uint64));
1724  RecordCacheArrayLen = newlen;
1725  }
1726 }
signed int int32
Definition: c.h:429
static TupleDesc * RecordCacheArray
Definition: typcache.c:276
static int32 RecordCacheArrayLen
Definition: typcache.c:278
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:906
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182
static uint64 * RecordIdentifierArray
Definition: typcache.c:277
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ enum_known_sorted()

static bool enum_known_sorted ( TypeCacheEnumData enumdata,
Oid  arg 
)
inlinestatic

Definition at line 2423 of file typcache.c.

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

Referenced by compare_values_of_enum().

2424 {
2425  Oid offset;
2426 
2427  if (arg < enumdata->bitmap_base)
2428  return false;
2429  offset = arg - enumdata->bitmap_base;
2430  if (offset > (Oid) INT_MAX)
2431  return false;
2432  return bms_is_member((int) offset, enumdata->sorted_values);
2433 }
unsigned int Oid
Definition: postgres_ext.h:31
Bitmapset * sorted_values
Definition: typcache.c:140
void * arg
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427

◆ enum_oid_cmp()

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

Definition at line 2697 of file typcache.c.

References EnumItem::enum_oid.

Referenced by find_enumitem(), and load_enum_cache_data().

2698 {
2699  const EnumItem *l = (const EnumItem *) left;
2700  const EnumItem *r = (const EnumItem *) right;
2701 
2702  if (l->enum_oid < r->enum_oid)
2703  return -1;
2704  else if (l->enum_oid > r->enum_oid)
2705  return 1;
2706  else
2707  return 0;
2708 }
Oid enum_oid
Definition: typcache.c:133

◆ find_enumitem()

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

Definition at line 2680 of file typcache.c.

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

Referenced by compare_values_of_enum().

2681 {
2682  EnumItem srch;
2683 
2684  /* On some versions of Solaris, bsearch of zero items dumps core */
2685  if (enumdata->num_values <= 0)
2686  return NULL;
2687 
2688  srch.enum_oid = arg;
2689  return bsearch(&srch, enumdata->enum_values, enumdata->num_values,
2690  sizeof(EnumItem), enum_oid_cmp);
2691 }
EnumItem enum_values[FLEXIBLE_ARRAY_MEMBER]
Definition: typcache.c:142
Oid enum_oid
Definition: typcache.c:133
static int enum_oid_cmp(const void *left, const void *right)
Definition: typcache.c:2697
void * arg

◆ find_or_make_matching_shared_tupledesc()

static TupleDesc find_or_make_matching_shared_tupledesc ( TupleDesc  tupdesc)
static

Definition at line 2736 of file typcache.c.

References Session::area, Assert, CurrentSession, dsa_free(), dsa_get_address(), dshash_delete_key(), dshash_find(), dshash_find_or_insert(), dshash_release_lock(), elog, ERROR, sort-test::key, SharedRecordTableEntry::key, SharedRecordTableKey::local_tupdesc, 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().

2737 {
2738  TupleDesc result;
2740  SharedRecordTableEntry *record_table_entry;
2741  SharedTypmodTableEntry *typmod_table_entry;
2742  dsa_pointer shared_dp;
2743  bool found;
2744  uint32 typmod;
2745 
2746  /* If not even attached, nothing to do. */
2748  return NULL;
2749 
2750  /* Try to find a matching tuple descriptor in the record table. */
2751  key.shared = false;
2752  key.u.local_tupdesc = tupdesc;
2753  record_table_entry = (SharedRecordTableEntry *)
2755  if (record_table_entry)
2756  {
2757  Assert(record_table_entry->key.shared);
2759  record_table_entry);
2760  result = (TupleDesc)
2762  record_table_entry->key.u.shared_tupdesc);
2763  Assert(result->tdrefcount == -1);
2764 
2765  return result;
2766  }
2767 
2768  /* Allocate a new typmod number. This will be wasted if we error out. */
2769  typmod = (int)
2771  1);
2772 
2773  /* Copy the TupleDesc into shared memory. */
2774  shared_dp = share_tupledesc(CurrentSession->area, tupdesc, typmod);
2775 
2776  /*
2777  * Create an entry in the typmod table so that others will understand this
2778  * typmod number.
2779  */
2780  PG_TRY();
2781  {
2782  typmod_table_entry = (SharedTypmodTableEntry *)
2784  &typmod, &found);
2785  if (found)
2786  elog(ERROR, "cannot create duplicate shared record typmod");
2787  }
2788  PG_CATCH();
2789  {
2790  dsa_free(CurrentSession->area, shared_dp);
2791  PG_RE_THROW();
2792  }
2793  PG_END_TRY();
2794  typmod_table_entry->typmod = typmod;
2795  typmod_table_entry->shared_tupdesc = shared_dp;
2797  typmod_table_entry);
2798 
2799  /*
2800  * Finally create an entry in the record table so others with matching
2801  * tuple descriptors can reuse the typmod.
2802  */
2803  record_table_entry = (SharedRecordTableEntry *)
2805  &found);
2806  if (found)
2807  {
2808  /*
2809  * Someone concurrently inserted a matching tuple descriptor since the
2810  * first time we checked. Use that one instead.
2811  */
2813  record_table_entry);
2814 
2815  /* Might as well free up the space used by the one we created. */
2817  &typmod);
2818  Assert(found);
2819  dsa_free(CurrentSession->area, shared_dp);
2820 
2821  /* Return the one we found. */
2822  Assert(record_table_entry->key.shared);
2823  result = (TupleDesc)
2825  record_table_entry->key.shared);
2826  Assert(result->tdrefcount == -1);
2827 
2828  return result;
2829  }
2830 
2831  /* Store it and return it. */
2832  record_table_entry->key.shared = true;
2833  record_table_entry->key.u.shared_tupdesc = shared_dp;
2835  record_table_entry);
2836  result = (TupleDesc)
2837  dsa_get_address(CurrentSession->area, shared_dp);
2838  Assert(result->tdrefcount == -1);
2839 
2840  return result;
2841 }
Session * CurrentSession
Definition: session.c:48
dshash_table * shared_record_table
Definition: session.h:32
SharedRecordTableKey key
Definition: typcache.c:197
void dshash_release_lock(dshash_table *hash_table, void *entry)
Definition: dshash.c:561
uint64 dsa_pointer
Definition: dsa.h:62
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:932
dsa_pointer shared_tupdesc
Definition: typcache.c:207
pg_atomic_uint32 next_typmod
Definition: typcache.c:172
#define ERROR
Definition: elog.h:46
dsa_area * area
Definition: session.h:28
union SharedRecordTableKey::@28 u
unsigned int uint32
Definition: c.h:441
dsa_pointer shared_tupdesc
Definition: typcache.c:186
struct SharedRecordTypmodRegistry * shared_typmod_registry
Definition: session.h:31
dshash_table * shared_typmod_table
Definition: session.h:33
static uint32 pg_atomic_fetch_add_u32(volatile pg_atomic_uint32 *ptr, int32 add_)
Definition: atomics.h:328
#define PG_CATCH()
Definition: elog.h:323
bool dshash_delete_key(dshash_table *hash_table, const void *key)
Definition: dshash.c:502
#define Assert(condition)
Definition: c.h:804
static dsa_pointer share_tupledesc(dsa_area *area, TupleDesc tupdesc, uint32 typmod)
Definition: typcache.c:2715
#define PG_RE_THROW()
Definition: elog.h:354
void dsa_free(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:820
struct TupleDescData * TupleDesc
Definition: tupdesc.h:89
#define elog(elevel,...)
Definition: elog.h:232
void * dshash_find_or_insert(dshash_table *hash_table, const void *key, bool *found)
Definition: dshash.c:430
TupleDesc local_tupdesc
Definition: typcache.c:185
int tdrefcount
Definition: tupdesc.h:84
void * dshash_find(dshash_table *hash_table, const void *key, bool exclusive)
Definition: dshash.c:385
#define PG_TRY()
Definition: elog.h:313
#define PG_END_TRY()
Definition: elog.h:338

◆ InitDomainConstraintRef()

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

Definition at line 1304 of file typcache.c.

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

1306 {
1307  /* Look up the typcache entry --- we assume it survives indefinitely */
1309  ref->need_exprstate = need_exprstate;
1310  /* For safety, establish the callback before acquiring a refcount */
1311  ref->refctx = refctx;
1312  ref->dcc = NULL;
1314  ref->callback.arg = (void *) ref;
1316  /* Acquire refcount if there are constraints, and set up exported list */
1317  if (ref->tcache->domainData)
1318  {
1319  ref->dcc = ref->tcache->domainData;
1320  ref->dcc->dccRefCount++;
1321  if (ref->need_exprstate)
1323  ref->refctx);
1324  else
1325  ref->constraints = ref->dcc->constraints;
1326  }
1327  else
1328  ref->constraints = NIL;
1329 }
MemoryContextCallback callback
Definition: typcache.h:172
MemoryContextCallbackFunction func
Definition: palloc.h:49
#define NIL
Definition: pg_list.h:65
DomainConstraintCache * dcc
Definition: typcache.h:171
static void dccref_deletion_callback(void *arg)
Definition: typcache.c:1245
DomainConstraintCache * domainData
Definition: typcache.h:120
MemoryContext refctx
Definition: typcache.h:166
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:338
static List * prep_domain_constraints(List *constraints, MemoryContext execctx)
Definition: typcache.c:1266
#define TYPECACHE_DOMAIN_CONSTR_INFO
Definition: typcache.h:149
TypeCacheEntry * tcache
Definition: typcache.h:167
void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)
Definition: mcxt.c:292

◆ load_domaintype_info()

static void load_domaintype_info ( TypeCacheEntry typentry)
static

Definition at line 985 of file typcache.c.

References AccessShareLock, ALLOCSET_SMALL_SIZES, AllocSetContextCreate, BTEqualStrategyNumber, CacheMemoryContext, DomainConstraintState::check_expr, DomainConstraintState::check_exprstate, DomainConstraintCache::constraints, DomainConstraintState::constrainttype, ConstraintTypidIndexId, 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().

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

◆ load_enum_cache_data()

static void load_enum_cache_data ( TypeCacheEntry tcache)
static

Definition at line 2525 of file typcache.c.

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

2526 {
2527  TypeCacheEnumData *enumdata;
2528  Relation enum_rel;
2529  SysScanDesc enum_scan;
2530  HeapTuple enum_tuple;
2531  ScanKeyData skey;
2532  EnumItem *items;
2533  int numitems;
2534  int maxitems;
2535  Oid bitmap_base;
2536  Bitmapset *bitmap;
2537  MemoryContext oldcxt;
2538  int bm_size,
2539  start_pos;
2540 
2541  /* Check that this is actually an enum */
2542  if (tcache->typtype != TYPTYPE_ENUM)
2543  ereport(ERROR,
2544  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2545  errmsg("%s is not an enum",
2546  format_type_be(tcache->type_id))));
2547 
2548  /*
2549  * Read all the information for members of the enum type. We collect the
2550  * info in working memory in the caller's context, and then transfer it to
2551  * permanent memory in CacheMemoryContext. This minimizes the risk of
2552  * leaking memory from CacheMemoryContext in the event of an error partway
2553  * through.
2554  */
2555  maxitems = 64;
2556  items = (EnumItem *) palloc(sizeof(EnumItem) * maxitems);
2557  numitems = 0;
2558 
2559  /* Scan pg_enum for the members of the target enum type. */
2560  ScanKeyInit(&skey,
2561  Anum_pg_enum_enumtypid,
2562  BTEqualStrategyNumber, F_OIDEQ,
2563  ObjectIdGetDatum(tcache->type_id));
2564 
2565  enum_rel = table_open(EnumRelationId, AccessShareLock);
2566  enum_scan = systable_beginscan(enum_rel,
2568  true, NULL,
2569  1, &skey);
2570 
2571  while (HeapTupleIsValid(enum_tuple = systable_getnext(enum_scan)))
2572  {
2573  Form_pg_enum en = (Form_pg_enum) GETSTRUCT(enum_tuple);
2574 
2575  if (numitems >= maxitems)
2576  {
2577  maxitems *= 2;
2578  items = (EnumItem *) repalloc(items, sizeof(EnumItem) * maxitems);
2579  }
2580  items[numitems].enum_oid = en->oid;
2581  items[numitems].sort_order = en->enumsortorder;
2582  numitems++;
2583  }
2584 
2585  systable_endscan(enum_scan);
2586  table_close(enum_rel, AccessShareLock);
2587 
2588  /* Sort the items into OID order */
2589  qsort(items, numitems, sizeof(EnumItem), enum_oid_cmp);
2590 
2591  /*
2592  * Here, we create a bitmap listing a subset of the enum's OIDs that are
2593  * known to be in order and can thus be compared with just OID comparison.
2594  *
2595  * The point of this is that the enum's initial OIDs were certainly in
2596  * order, so there is some subset that can be compared via OID comparison;
2597  * and we'd rather not do binary searches unnecessarily.
2598  *
2599  * This is somewhat heuristic, and might identify a subset of OIDs that
2600  * isn't exactly what the type started with. That's okay as long as the
2601  * subset is correctly sorted.
2602  */
2603  bitmap_base = InvalidOid;
2604  bitmap = NULL;
2605  bm_size = 1; /* only save sets of at least 2 OIDs */
2606 
2607  for (start_pos = 0; start_pos < numitems - 1; start_pos++)
2608  {
2609  /*
2610  * Identify longest sorted subsequence starting at start_pos
2611  */
2612  Bitmapset *this_bitmap = bms_make_singleton(0);
2613  int this_bm_size = 1;
2614  Oid start_oid = items[start_pos].enum_oid;
2615  float4 prev_order = items[start_pos].sort_order;
2616  int i;
2617 
2618  for (i = start_pos + 1; i < numitems; i++)
2619  {
2620  Oid offset;
2621 
2622  offset = items[i].enum_oid - start_oid;
2623  /* quit if bitmap would be too large; cutoff is arbitrary */
2624  if (offset >= 8192)
2625  break;
2626  /* include the item if it's in-order */
2627  if (items[i].sort_order > prev_order)
2628  {
2629  prev_order = items[i].sort_order;
2630  this_bitmap = bms_add_member(this_bitmap, (int) offset);
2631  this_bm_size++;
2632  }
2633  }
2634 
2635  /* Remember it if larger than previous best */
2636  if (this_bm_size > bm_size)
2637  {
2638  bms_free(bitmap);
2639  bitmap_base = start_oid;
2640  bitmap = this_bitmap;
2641  bm_size = this_bm_size;
2642  }
2643  else
2644  bms_free(this_bitmap);
2645 
2646  /*
2647  * Done if it's not possible to find a longer sequence in the rest of
2648  * the list. In typical cases this will happen on the first
2649  * iteration, which is why we create the bitmaps on the fly instead of
2650  * doing a second pass over the list.
2651  */
2652  if (bm_size >= (numitems - start_pos - 1))
2653  break;
2654  }
2655 
2656  /* OK, copy the data into CacheMemoryContext */
2658  enumdata = (TypeCacheEnumData *)
2659  palloc(offsetof(TypeCacheEnumData, enum_values) +
2660  numitems * sizeof(EnumItem));
2661  enumdata->bitmap_base = bitmap_base;
2662  enumdata->sorted_values = bms_copy(bitmap);
2663  enumdata->num_values = numitems;
2664  memcpy(enumdata->enum_values, items, numitems * sizeof(EnumItem));
2665  MemoryContextSwitchTo(oldcxt);
2666 
2667  pfree(items);
2668  bms_free(bitmap);
2669 
2670  /* And link the finished cache struct into the typcache */
2671  if (tcache->enumData != NULL)
2672  pfree(tcache->enumData);
2673  tcache->enumData = enumdata;
2674 }
struct TypeCacheEnumData * enumData
Definition: typcache.h:129
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:74
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
#define EnumTypIdLabelIndexId
Definition: pg_enum.h:49
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
Bitmapset * sorted_values
Definition: typcache.c:140
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:186
FormData_pg_enum * Form_pg_enum
Definition: pg_enum.h:44
EnumItem enum_values[FLEXIBLE_ARRAY_MEMBER]
Definition: typcache.c:142
float float4
Definition: c.h:564
Oid enum_oid
Definition: typcache.c:133
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
char typtype
Definition: typcache.h:43
void bms_free(Bitmapset *a)
Definition: bitmapset.c:208
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182
float4 sort_order
Definition: typcache.c:134
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
static int enum_oid_cmp(const void *left, const void *right)
Definition: typcache.c:2697
int i
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define qsort(a, b, c, d)
Definition: port.h:504
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define offsetof(type, field)
Definition: c.h:727
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ load_multirangetype_info()

static void load_multirangetype_info ( TypeCacheEntry typentry)
static

Definition at line 963 of file typcache.c.

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

964 {
965  Oid rangetypeOid;
966 
967  rangetypeOid = get_multirange_range(typentry->type_id);
968  if (!OidIsValid(rangetypeOid))
969  elog(ERROR, "cache lookup failed for multirange type %u",
970  typentry->type_id);
971 
972  typentry->rngtype = lookup_type_cache(rangetypeOid, TYPECACHE_RANGE_INFO);
973 }
#define TYPECACHE_RANGE_INFO
Definition: typcache.h:147
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
Oid get_multirange_range(Oid multirangeOid)
Definition: lsyscache.c:3433
#define ERROR
Definition: elog.h:46
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:338
struct TypeCacheEntry * rngtype
Definition: typcache.h:107
#define elog(elevel,...)
Definition: elog.h:232

◆ load_rangetype_info()

static void load_rangetype_info ( TypeCacheEntry typentry)
static

Definition at line 906 of file typcache.c.

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

907 {
908  Form_pg_range pg_range;
909  HeapTuple tup;
910  Oid subtypeOid;
911  Oid opclassOid;
912  Oid canonicalOid;
913  Oid subdiffOid;
914  Oid opfamilyOid;
915  Oid opcintype;
916  Oid cmpFnOid;
917 
918  /* get information from pg_range */
920  /* should not fail, since we already checked typtype ... */
921  if (!HeapTupleIsValid(tup))
922  elog(ERROR, "cache lookup failed for range type %u",
923  typentry->type_id);
924  pg_range = (Form_pg_range) GETSTRUCT(tup);
925 
926  subtypeOid = pg_range->rngsubtype;
927  typentry->rng_collation = pg_range->rngcollation;
928  opclassOid = pg_range->rngsubopc;
929  canonicalOid = pg_range->rngcanonical;
930  subdiffOid = pg_range->rngsubdiff;
931 
932  ReleaseSysCache(tup);
933 
934  /* get opclass properties and look up the comparison function */
935  opfamilyOid = get_opclass_family(opclassOid);
936  opcintype = get_opclass_input_type(opclassOid);
937 
938  cmpFnOid = get_opfamily_proc(opfamilyOid, opcintype, opcintype,
939  BTORDER_PROC);
940  if (!RegProcedureIsValid(cmpFnOid))
941  elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
942  BTORDER_PROC, opcintype, opcintype, opfamilyOid);
943 
944  /* set up cached fmgrinfo structs */
945  fmgr_info_cxt(cmpFnOid, &typentry->rng_cmp_proc_finfo,
947  if (OidIsValid(canonicalOid))
948  fmgr_info_cxt(canonicalOid, &typentry->rng_canonical_finfo,
950  if (OidIsValid(subdiffOid))
951  fmgr_info_cxt(subdiffOid, &typentry->rng_subdiff_finfo,
953 
954  /* Lastly, set up link to the element type --- this marks data valid */
955  typentry->rngelemtype = lookup_type_cache(subtypeOid, 0);
956 }
FormData_pg_range * Form_pg_range
Definition: pg_range.h:58
FmgrInfo rng_cmp_proc_finfo
Definition: typcache.h:100
#define BTORDER_PROC
Definition: nbtree.h:700
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
FmgrInfo rng_subdiff_finfo
Definition: typcache.h:102
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define RegProcedureIsValid(p)
Definition: c.h:712
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:136
FmgrInfo rng_canonical_finfo
Definition: typcache.h:101
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:98
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:338
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition: lsyscache.c:794
Oid rng_collation
Definition: typcache.h:99
Oid get_opclass_family(Oid opclass)
Definition: lsyscache.c:1183
#define elog(elevel,...)
Definition: elog.h:232
MemoryContext CacheMemoryContext
Definition: mcxt.c:51
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1205

◆ load_typcache_tupdesc()

static void load_typcache_tupdesc ( TypeCacheEntry typentry)
static

Definition at line 872 of file typcache.c.

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

873 {
874  Relation rel;
875 
876  if (!OidIsValid(typentry->typrelid)) /* should not happen */
877  elog(ERROR, "invalid typrelid for composite type %u",
878  typentry->type_id);
879  rel = relation_open(typentry->typrelid, AccessShareLock);
880  Assert(rel->rd_rel->reltype == typentry->type_id);
881 
882  /*
883  * Link to the tupdesc and increment its refcount (we assert it's a
884  * refcounted descriptor). We don't use IncrTupleDescRefCount() for this,
885  * because the reference mustn't be entered in the current resource owner;
886  * it can outlive the current query.
887  */
888  typentry->tupDesc = RelationGetDescr(rel);
889 
890  Assert(typentry->tupDesc->tdrefcount > 0);
891  typentry->tupDesc->tdrefcount++;
892 
893  /*
894  * In future, we could take some pains to not change tupDesc_identifier if
895  * the tupdesc didn't really change; but for now it's not worth it.
896  */
898 
900 }
#define RelationGetDescr(relation)
Definition: rel.h:483
#define AccessShareLock
Definition: lockdefs.h:36
static uint64 tupledesc_id_counter
Definition: typcache.c:286
Form_pg_class rd_rel
Definition: rel.h:110
#define OidIsValid(objectId)
Definition: c.h:710
#define ERROR
Definition: elog.h:46
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
#define Assert(condition)
Definition: c.h:804
uint64 tupDesc_identifier
Definition: typcache.h:90
#define elog(elevel,...)
Definition: elog.h:232
int tdrefcount
Definition: tupdesc.h:84
TupleDesc tupDesc
Definition: typcache.h:89

◆ lookup_rowtype_tupdesc()

◆ lookup_rowtype_tupdesc_copy()

TupleDesc lookup_rowtype_tupdesc_copy ( Oid  type_id,
int32  typmod 
)

Definition at line 1860 of file typcache.c.

References CreateTupleDescCopyConstr(), and lookup_rowtype_tupdesc_internal().

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

1861 {
1862  TupleDesc tmp;
1863 
1864  tmp = lookup_rowtype_tupdesc_internal(type_id, typmod, false);
1865  return CreateTupleDescCopyConstr(tmp);
1866 }
TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc)
Definition: tupdesc.c:151
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1735

◆ lookup_rowtype_tupdesc_domain()

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

Definition at line 1882 of file typcache.c.

References TypeCacheEntry::domainBaseType, TypeCacheEntry::domainBaseTypmod, ereport, errcode(), errmsg(), ERROR, format_type_be(), lookup_rowtype_tupdesc_internal(), lookup_rowtype_tupdesc_noerror(), lookup_type_cache(), PinTupleDesc, TypeCacheEntry::tupDesc, TYPECACHE_DOMAIN_BASE_INFO, TYPECACHE_TUPDESC, and TypeCacheEntry::typtype.

Referenced by ExecEvalWholeRowVar(), hstore_from_record(), hstore_populate_record(), plperl_sv_to_datum(), and rowtype_field_matches().

1883 {
1884  TupleDesc tupDesc;
1885 
1886  if (type_id != RECORDOID)
1887  {
1888  /*
1889  * Check for domain or named composite type. We might as well load
1890  * whichever data is needed.
1891  */
1892  TypeCacheEntry *typentry;
1893 
1894  typentry = lookup_type_cache(type_id,
1897  if (typentry->typtype == TYPTYPE_DOMAIN)
1899  typentry->domainBaseTypmod,
1900  noError);
1901  if (typentry->tupDesc == NULL && !noError)
1902  ereport(ERROR,
1903  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1904  errmsg("type %s is not composite",
1905  format_type_be(type_id))));
1906  tupDesc = typentry->tupDesc;
1907  }
1908  else
1909  tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, noError);
1910  if (tupDesc != NULL)
1911  PinTupleDesc(tupDesc);
1912  return tupDesc;
1913 }
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
Oid domainBaseType
Definition: typcache.h:113
#define ERROR
Definition: elog.h:46
int32 domainBaseTypmod
Definition: typcache.h:114
TupleDesc lookup_rowtype_tupdesc_noerror(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1843
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:148
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:338
#define ereport(elevel,...)
Definition: elog.h:157
char typtype
Definition: typcache.h:43
#define PinTupleDesc(tupdesc)
Definition: tupdesc.h:116
int errmsg(const char *fmt,...)
Definition: elog.c:909
TupleDesc tupDesc
Definition: typcache.h:89
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1735
#define TYPECACHE_TUPDESC
Definition: typcache.h:144

◆ lookup_rowtype_tupdesc_internal()

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

Definition at line 1735 of file typcache.c.

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

1736 {
1737  if (type_id != RECORDOID)
1738  {
1739  /*
1740  * It's a named composite type, so use the regular typcache.
1741  */
1742  TypeCacheEntry *typentry;
1743 
1744  typentry = lookup_type_cache(type_id, TYPECACHE_TUPDESC);
1745  if (typentry->tupDesc == NULL && !noError)
1746  ereport(ERROR,
1747  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1748  errmsg("type %s is not composite",
1749  format_type_be(type_id))));
1750  return typentry->tupDesc;
1751  }
1752  else
1753  {
1754  /*
1755  * It's a transient record type, so look in our record-type table.
1756  */
1757  if (typmod >= 0)
1758  {
1759  /* It is already in our local cache? */
1760  if (typmod < RecordCacheArrayLen &&
1761  RecordCacheArray[typmod] != NULL)
1762  return RecordCacheArray[typmod];
1763 
1764  /* Are we attached to a shared record typmod registry? */
1766  {
1767  SharedTypmodTableEntry *entry;
1768 
1769  /* Try to find it in the shared typmod index. */
1771  &typmod, false);
1772  if (entry != NULL)
1773  {
1774  TupleDesc tupdesc;
1775 
1776  tupdesc = (TupleDesc)
1778  entry->shared_tupdesc);
1779  Assert(typmod == tupdesc->tdtypmod);
1780 
1781  /* We may need to extend the local RecordCacheArray. */
1783 
1784  /*
1785  * Our local array can now point directly to the TupleDesc
1786  * in shared memory, which is non-reference-counted.
1787  */
1788  RecordCacheArray[typmod] = tupdesc;
1789  Assert(tupdesc->tdrefcount == -1);
1790 
1791  /*
1792  * We don't share tupdesc identifiers across processes, so
1793  * assign one locally.
1794  */
1796 
1798  entry);
1799 
1800  return RecordCacheArray[typmod];
1801  }
1802  }
1803  }
1804 
1805  if (!noError)
1806  ereport(ERROR,
1807  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1808  errmsg("record type has not been registered")));
1809  return NULL;
1810  }
1811 }
Session * CurrentSession
Definition: session.c:48
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
static uint64 tupledesc_id_counter
Definition: typcache.c:286
void dshash_release_lock(dshash_table *hash_table, void *entry)
Definition: dshash.c:561
static TupleDesc * RecordCacheArray
Definition: typcache.c:276
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:932
dsa_pointer shared_tupdesc
Definition: typcache.c:207
#define ERROR
Definition: elog.h:46
int32 tdtypmod
Definition: tupdesc.h:83
dsa_area * area
Definition: session.h:28
static int32 RecordCacheArrayLen
Definition: typcache.c:278
struct SharedRecordTypmodRegistry * shared_typmod_registry
Definition: session.h:31
static void ensure_record_cache_typmod_slot_exists(int32 typmod)
Definition: typcache.c:1698
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:338
#define ereport(elevel,...)
Definition: elog.h:157
dshash_table * shared_typmod_table
Definition: session.h:33
#define Assert(condition)
Definition: c.h:804
struct TupleDescData * TupleDesc
Definition: tupdesc.h:89
int errmsg(const char *fmt,...)
Definition: elog.c:909
int tdrefcount
Definition: tupdesc.h:84
void * dshash_find(dshash_table *hash_table, const void *key, bool exclusive)
Definition: dshash.c:385
TupleDesc tupDesc
Definition: typcache.h:89
#define TYPECACHE_TUPDESC
Definition: typcache.h:144
static uint64 * RecordIdentifierArray
Definition: typcache.c:277

◆ lookup_rowtype_tupdesc_noerror()

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

Definition at line 1843 of file typcache.c.

References lookup_rowtype_tupdesc_internal(), and PinTupleDesc.

Referenced by lookup_rowtype_tupdesc_domain().

1844 {
1845  TupleDesc tupDesc;
1846 
1847  tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, noError);
1848  if (tupDesc != NULL)
1849  PinTupleDesc(tupDesc);
1850  return tupDesc;
1851 }
#define PinTupleDesc(tupdesc)
Definition: tupdesc.h:116
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1735

◆ lookup_type_cache()

TypeCacheEntry* lookup_type_cache ( Oid  type_id,
int  flags 
)

Definition at line 338 of file typcache.c.

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(), lookup_type_cache(), 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(), TypeCacheOpcCallback(), TypeCacheRelCallback(), TypeCacheTypCallback(), TypeCacheEntry::typelem, TYPEOID, TypeCacheEntry::typlen, TypeCacheEntry::typrelid, TypeCacheEntry::typstorage, TypeCacheEntry::typsubscript, and TypeCacheEntry::typtype.

Referenced by analyzeCTE(), appendAggOrderBy(), 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_resultcacheable(), 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(), lookup_type_cache(), make_expanded_record_from_tupdesc(), make_expanded_record_from_typeid(), multirange_get_typcache(), 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().

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

◆ multirange_element_has_extended_hashing()

static bool multirange_element_has_extended_hashing ( TypeCacheEntry typentry)
static

Definition at line 1662 of file typcache.c.

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

Referenced by lookup_type_cache().

1663 {
1664  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1666  return (typentry->flags & TCFLAGS_HAVE_ELEM_EXTENDED_HASHING) != 0;
1667 }
#define TCFLAGS_HAVE_ELEM_EXTENDED_HASHING
Definition: typcache.c:96
static void cache_multirange_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1670
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:92

◆ multirange_element_has_hashing()

static bool multirange_element_has_hashing ( TypeCacheEntry typentry)
static

Definition at line 1654 of file typcache.c.

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

Referenced by lookup_type_cache().

1655 {
1656  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1658  return (typentry->flags & TCFLAGS_HAVE_ELEM_HASHING) != 0;
1659 }
static void cache_multirange_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1670
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:92
#define TCFLAGS_HAVE_ELEM_HASHING
Definition: typcache.c:95

◆ prep_domain_constraints()

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

Definition at line 1266 of file typcache.c.

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

Referenced by InitDomainConstraintRef(), and UpdateDomainConstraintRef().

1267 {
1268  List *result = NIL;
1269  MemoryContext oldcxt;
1270  ListCell *lc;
1271 
1272  oldcxt = MemoryContextSwitchTo(execctx);
1273 
1274  foreach(lc, constraints)
1275  {
1277  DomainConstraintState *newr;
1278 
1280  newr->constrainttype = r->constrainttype;
1281  newr->name = r->name;
1282  newr->check_expr = r->check_expr;
1283  newr->check_exprstate = ExecInitExpr(r->check_expr, NULL);
1284 
1285  result = lappend(result, newr);
1286  }
1287 
1288  MemoryContextSwitchTo(oldcxt);
1289 
1290  return result;
1291 }
#define NIL
Definition: pg_list.h:65
DomainConstraintType constrainttype
Definition: execnodes.h:928
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
ExprState * check_exprstate
Definition: execnodes.h:931
List * lappend(List *list, void *datum)
Definition: list.c:336
#define makeNode(_type_)
Definition: nodes.h:587
#define lfirst(lc)
Definition: pg_list.h:169
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:123
Definition: pg_list.h:50

◆ range_element_has_extended_hashing()

static bool range_element_has_extended_hashing ( TypeCacheEntry typentry)
static

Definition at line 1622 of file typcache.c.

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

Referenced by lookup_type_cache().

1623 {
1624  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1626  return (typentry->flags & TCFLAGS_HAVE_ELEM_EXTENDED_HASHING) != 0;
1627 }
static void cache_range_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1630
#define TCFLAGS_HAVE_ELEM_EXTENDED_HASHING
Definition: typcache.c:96
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:92

◆ range_element_has_hashing()

static bool range_element_has_hashing ( TypeCacheEntry typentry)
static

Definition at line 1614 of file typcache.c.

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

Referenced by lookup_type_cache().

1615 {
1616  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1618  return (typentry->flags & TCFLAGS_HAVE_ELEM_HASHING) != 0;
1619 }
static void cache_range_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1630
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:92
#define TCFLAGS_HAVE_ELEM_HASHING
Definition: typcache.c:95

◆ record_fields_have_compare()

static bool record_fields_have_compare ( TypeCacheEntry typentry)
static

Definition at line 1488 of file typcache.c.

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

Referenced by lookup_type_cache().

1489 {
1490  if (!(typentry->flags & TCFLAGS_CHECKED_FIELD_PROPERTIES))
1492  return (typentry->flags & TCFLAGS_HAVE_FIELD_COMPARE) != 0;
1493 }
#define TCFLAGS_CHECKED_FIELD_PROPERTIES
Definition: typcache.c:97
static void cache_record_field_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1512
#define TCFLAGS_HAVE_FIELD_COMPARE
Definition: typcache.c:99

◆ record_fields_have_equality()

static bool record_fields_have_equality ( TypeCacheEntry typentry)
static

Definition at line 1480 of file typcache.c.

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

Referenced by lookup_type_cache().

1481 {
1482  if (!(typentry->flags & TCFLAGS_CHECKED_FIELD_PROPERTIES))
1484  return (typentry->flags & TCFLAGS_HAVE_FIELD_EQUALITY) != 0;
1485 }
#define TCFLAGS_CHECKED_FIELD_PROPERTIES
Definition: typcache.c:97
static void cache_record_field_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1512
#define TCFLAGS_HAVE_FIELD_EQUALITY
Definition: typcache.c:98

◆ record_fields_have_extended_hashing()

static bool record_fields_have_extended_hashing ( TypeCacheEntry typentry)
static

Definition at line 1504 of file typcache.c.

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

Referenced by lookup_type_cache().

1505 {
1506  if (!(typentry->flags & TCFLAGS_CHECKED_FIELD_PROPERTIES))
1508  return (typentry->flags & TCFLAGS_HAVE_FIELD_EXTENDED_HASHING) != 0;
1509 }
#define TCFLAGS_CHECKED_FIELD_PROPERTIES
Definition: typcache.c:97
static void cache_record_field_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1512
#define TCFLAGS_HAVE_FIELD_EXTENDED_HASHING
Definition: typcache.c:101

◆ record_fields_have_hashing()

static bool record_fields_have_hashing ( TypeCacheEntry typentry)
static

Definition at line 1496 of file typcache.c.

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

Referenced by lookup_type_cache().

1497 {
1498  if (!(typentry->flags & TCFLAGS_CHECKED_FIELD_PROPERTIES))
1500  return (typentry->flags & TCFLAGS_HAVE_FIELD_HASHING) != 0;
1501 }
#define TCFLAGS_CHECKED_FIELD_PROPERTIES
Definition: typcache.c:97
static void cache_record_field_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1512
#define TCFLAGS_HAVE_FIELD_HASHING
Definition: typcache.c:100

◆ record_type_typmod_compare()

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

Definition at line 1930 of file typcache.c.

References equalTupleDescs(), and RecordCacheEntry::tupdesc.

Referenced by assign_record_type_typmod().

1931 {
1932  RecordCacheEntry *left = (RecordCacheEntry *) a;
1933  RecordCacheEntry *right = (RecordCacheEntry *) b;
1934 
1935  return equalTupleDescs(left->tupdesc, right->tupdesc) ? 0 : 1;
1936 }
bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
Definition: tupdesc.c:402
TupleDesc tupdesc
Definition: typcache.c:158

◆ record_type_typmod_hash()

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

Definition at line 1919 of file typcache.c.

References hashTupleDesc(), and RecordCacheEntry::tupdesc.

Referenced by assign_record_type_typmod().

1920 {
1921  RecordCacheEntry *entry = (RecordCacheEntry *) data;
1922 
1923  return hashTupleDesc(entry->tupdesc);
1924 }
uint32 hashTupleDesc(TupleDesc desc)
Definition: tupdesc.c:551
TupleDesc tupdesc
Definition: typcache.c:158

◆ share_tupledesc()

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

Definition at line 2715 of file typcache.c.

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

Referenced by find_or_make_matching_shared_tupledesc(), and SharedRecordTypmodRegistryInit().

2716 {
2717  dsa_pointer shared_dp;
2718  TupleDesc shared;
2719 
2720  shared_dp = dsa_allocate(area, TupleDescSize(tupdesc));
2721  shared = (TupleDesc) dsa_get_address(area, shared_dp);
2722  TupleDescCopy(shared, tupdesc);
2723  shared->tdtypmod = typmod;
2724 
2725  return shared_dp;
2726 }
#define TupleDescSize(src)
Definition: tupdesc.h:102
uint64 dsa_pointer
Definition: dsa.h:62
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:932
int32 tdtypmod
Definition: tupdesc.h:83
void TupleDescCopy(TupleDesc dst, TupleDesc src)
Definition: tupdesc.c:229
struct TupleDescData * TupleDesc
Definition: tupdesc.h:89
#define dsa_allocate(area, size)
Definition: dsa.h:84

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

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

216 {
217  dsa_area *area = (dsa_area *) arg;
220  TupleDesc t1;
221  TupleDesc t2;
222 
223  if (k1->shared)
224  t1 = (TupleDesc) dsa_get_address(area, k1->u.shared_tupdesc);
225  else
226  t1 = k1->u.local_tupdesc;
227 
228  if (k2->shared)
229  t2 = (TupleDesc) dsa_get_address(area, k2->u.shared_tupdesc);
230  else
231  t2 = k2->u.local_tupdesc;
232 
233  return equalTupleDescs(t1, t2) ? 0 : 1;
234 }
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:932
union SharedRecordTableKey::@28 u
dsa_pointer shared_tupdesc
Definition: typcache.c:186
Definition: dsa.c:354
struct TupleDescData * TupleDesc
Definition: tupdesc.h:89
bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
Definition: tupdesc.c:402
TupleDesc local_tupdesc
Definition: typcache.c:185
void * arg

◆ shared_record_table_hash()

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

Definition at line 240 of file typcache.c.

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

241 {
242  dsa_area *area = (dsa_area *) arg;
244  TupleDesc t;
245 
246  if (k->shared)
247  t = (TupleDesc) dsa_get_address(area, k->u.shared_tupdesc);
248  else
249  t = k->u.local_tupdesc;
250 
251  return hashTupleDesc(t);
252 }
uint32 hashTupleDesc(TupleDesc desc)
Definition: tupdesc.c:551
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:932
union SharedRecordTableKey::@28 u
dsa_pointer shared_tupdesc
Definition: typcache.c:186
Definition: dsa.c:354
struct TupleDescData * TupleDesc
Definition: tupdesc.h:89
TupleDesc local_tupdesc
Definition: typcache.c:185
void * arg

◆ shared_record_typmod_registry_detach()

static void shared_record_typmod_registry_detach ( dsm_segment segment,
Datum  datum 
)
static

Definition at line 2848 of file typcache.c.

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

Referenced by SharedRecordTypmodRegistryAttach(), and SharedRecordTypmodRegistryInit().

2849 {
2850  /* Be cautious here: maybe we didn't finish initializing. */
2851  if (CurrentSession->shared_record_table != NULL)
2852  {
2855  }
2856  if (CurrentSession->shared_typmod_table != NULL)
2857  {
2860  }
2862 }
Session * CurrentSession
Definition: session.c:48
dshash_table * shared_record_table
Definition: session.h:32
void dshash_detach(dshash_table *hash_table)
Definition: dshash.c:302
struct SharedRecordTypmodRegistry * shared_typmod_registry
Definition: session.h:31
dshash_table * shared_typmod_table
Definition: session.h:33

◆ SharedRecordTypmodRegistryAttach()

void SharedRecordTypmodRegistryAttach ( SharedRecordTypmodRegistry registry)

Definition at line 2182 of file typcache.c.

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

Referenced by AttachSession().

2183 {
2184  MemoryContext old_context;
2185  dshash_table *record_table;
2186  dshash_table *typmod_table;
2187 
2189 
2190  /* We can't already be attached to a shared registry. */
2191  Assert(CurrentSession != NULL);
2192  Assert(CurrentSession->segment != NULL);
2193  Assert(CurrentSession->area != NULL);
2197 
2198  /*
2199  * We can't already have typmods in our local cache, because they'd clash
2200  * with those imported by SharedRecordTypmodRegistryInit. This should be
2201  * a freshly started parallel worker. If we ever support worker
2202  * recycling, a worker would need to zap its local cache in between
2203  * servicing different queries, in order to be able to call this and
2204  * synchronize typmods with a new leader; but that's problematic because
2205  * we can't be very sure that record-typmod-related state hasn't escaped
2206  * to anywhere else in the process.
2207  */
2208  Assert(NextRecordTypmod == 0);
2209 
2210  old_context = MemoryContextSwitchTo(TopMemoryContext);
2211 
2212  /* Attach to the two hash tables. */
2213  record_table = dshash_attach(CurrentSession->area,
2215  registry->record_table_handle,
2216  CurrentSession->area);
2217  typmod_table = dshash_attach(CurrentSession->area,
2219  registry->typmod_table_handle,
2220  NULL);
2221 
2222  MemoryContextSwitchTo(old_context);
2223 
2224  /*
2225  * Set up detach hook to run at worker exit. Currently this is the same
2226  * as the leader's detach hook, but in future they might need to be
2227  * different.
2228  */
2231  PointerGetDatum(registry));
2232 
2233  /*
2234  * Set up the session state that will tell assign_record_type_typmod and
2235  * lookup_rowtype_tupdesc_internal about the shared registry.
2236  */
2238  CurrentSession->shared_record_table = record_table;
2239  CurrentSession->shared_typmod_table = typmod_table;
2240 }
dshash_table * dshash_attach(dsa_area *area, const dshash_parameters *params, dshash_table_handle handle, void *arg)
Definition: dshash.c:263
#define PointerGetDatum(X)
Definition: postgres.h:600
Session * CurrentSession
Definition: session.c:48
static const dshash_parameters srtr_record_table_params
Definition: typcache.c:255
dshash_table * shared_record_table
Definition: session.h:32
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void on_dsm_detach(dsm_segment *seg, on_dsm_detach_callback function, Datum arg)
Definition: dsm.c:1096
dsa_area * area
Definition: session.h:28
#define IsParallelWorker()
Definition: parallel.h:61
MemoryContext TopMemoryContext
Definition: mcxt.c:48
static const dshash_parameters srtr_typmod_table_params
Definition: typcache.c:264
static void shared_record_typmod_registry_detach(dsm_segment *segment, Datum datum)
Definition: typcache.c:2848
static int32 NextRecordTypmod
Definition: typcache.c:279
struct SharedRecordTypmodRegistry * shared_typmod_registry
Definition: session.h:31
dshash_table * shared_typmod_table
Definition: session.h:33
#define Assert(condition)
Definition: c.h:804
dshash_table_handle record_table_handle
Definition: typcache.c:168
dshash_table_handle typmod_table_handle
Definition: typcache.c:170
dsm_segment * segment
Definition: session.h:27

◆ SharedRecordTypmodRegistryEstimate()

size_t SharedRecordTypmodRegistryEstimate ( void  )

Definition at line 2061 of file typcache.c.

Referenced by GetSessionDsmHandle().

2062 {
2063  return sizeof(SharedRecordTypmodRegistry);
2064 }
struct SharedRecordTypmodRegistry SharedRecordTypmodRegistry
Definition: typcache.h:175

◆ SharedRecordTypmodRegistryInit()

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

Definition at line 2083 of file typcache.c.

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

Referenced by GetSessionDsmHandle().

2086 {
2087  MemoryContext old_context;
2088  dshash_table *record_table;
2089  dshash_table *typmod_table;
2090  int32 typmod;
2091 
2093 
2094  /* We can't already be attached to a shared registry. */
2098 
2099  old_context = MemoryContextSwitchTo(TopMemoryContext);
2100 
2101  /* Create the hash table of tuple descriptors indexed by themselves. */
2102  record_table = dshash_create(area, &srtr_record_table_params, area);
2103 
2104  /* Create the hash table of tuple descriptors indexed by typmod. */
2105  typmod_table = dshash_create(area, &srtr_typmod_table_params, NULL);
2106 
2107  MemoryContextSwitchTo(old_context);
2108 
2109  /* Initialize the SharedRecordTypmodRegistry. */
2110  registry->record_table_handle = dshash_get_hash_table_handle(record_table);
2111  registry->typmod_table_handle = dshash_get_hash_table_handle(typmod_table);
2113 
2114  /*
2115  * Copy all entries from this backend's private registry into the shared
2116  * registry.
2117  */
2118  for (typmod = 0; typmod < NextRecordTypmod; ++typmod)
2119  {
2120  SharedTypmodTableEntry *typmod_table_entry;
2121  SharedRecordTableEntry *record_table_entry;
2122  SharedRecordTableKey record_table_key;
2123  dsa_pointer shared_dp;
2124  TupleDesc tupdesc;
2125  bool found;
2126 
2127  tupdesc = RecordCacheArray[typmod];
2128  if (tupdesc == NULL)
2129  continue;
2130 
2131  /* Copy the TupleDesc into shared memory. */
2132  shared_dp = share_tupledesc(area, tupdesc, typmod);
2133 
2134  /* Insert into the typmod table. */
2135  typmod_table_entry = dshash_find_or_insert(typmod_table,
2136  &tupdesc->tdtypmod,
2137  &found);
2138  if (found)
2139  elog(ERROR, "cannot create duplicate shared record typmod");
2140  typmod_table_entry->typmod = tupdesc->tdtypmod;
2141  typmod_table_entry->shared_tupdesc = shared_dp;
2142  dshash_release_lock(typmod_table, typmod_table_entry);
2143 
2144  /* Insert into the record table. */
2145  record_table_key.shared = false;
2146  record_table_key.u.local_tupdesc = tupdesc;
2147  record_table_entry = dshash_find_or_insert(record_table,
2148  &record_table_key,
2149  &found);
2150  if (!found)
2151  {
2152  record_table_entry->key.shared = true;
2153  record_table_entry->key.u.shared_tupdesc = shared_dp;
2154  }
2155  dshash_release_lock(record_table, record_table_entry);
2156  }
2157 
2158  /*
2159  * Set up the global state that will tell assign_record_type_typmod and
2160  * lookup_rowtype_tupdesc_internal about the shared registry.
2161  */
2162  CurrentSession->shared_record_table = record_table;
2163  CurrentSession->shared_typmod_table = typmod_table;
2165 
2166  /*
2167  * We install a detach hook in the leader, but only to handle cleanup on
2168  * failure during GetSessionDsmHandle(). Once GetSessionDsmHandle() pins
2169  * the memory, the leader process will use a shared registry until it
2170  * exits.
2171  */
2173 }
Session * CurrentSession
Definition: session.c:48
static const dshash_parameters srtr_record_table_params
Definition: typcache.c:255
dshash_table * shared_record_table
Definition: session.h:32
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
SharedRecordTableKey key
Definition: typcache.c:197
void on_dsm_detach(dsm_segment *seg, on_dsm_detach_callback function, Datum arg)
Definition: dsm.c:1096
void dshash_release_lock(dshash_table *hash_table, void *entry)
Definition: dshash.c:561
uint64 dsa_pointer
Definition: dsa.h:62
signed int int32
Definition: c.h:429
static TupleDesc * RecordCacheArray
Definition: typcache.c:276
dsa_pointer shared_tupdesc
Definition: typcache.c:207
pg_atomic_uint32 next_typmod
Definition: typcache.c:172
#define ERROR
Definition: elog.h:46
int32 tdtypmod
Definition: tupdesc.h:83
dshash_table_handle dshash_get_hash_table_handle(dshash_table *hash_table)
Definition: dshash.c:362
union SharedRecordTableKey::@28 u
dsa_pointer shared_tupdesc
Definition: typcache.c:186
#define IsParallelWorker()
Definition: parallel.h:61
MemoryContext TopMemoryContext
Definition: mcxt.c:48
static const dshash_parameters srtr_typmod_table_params
Definition: typcache.c:264
static void shared_record_typmod_registry_detach(dsm_segment *segment, Datum datum)
Definition: typcache.c:2848
static int32 NextRecordTypmod
Definition: typcache.c:279
struct SharedRecordTypmodRegistry * shared_typmod_registry
Definition: session.h:31
uintptr_t Datum
Definition: postgres.h:411
dshash_table * dshash_create(dsa_area *area, const dshash_parameters *params, void *arg)
Definition: dshash.c:196
dshash_table * shared_typmod_table
Definition: session.h:33
#define Assert(condition)
Definition: c.h:804
static dsa_pointer share_tupledesc(dsa_area *area, TupleDesc tupdesc, uint32 typmod)
Definition: typcache.c:2715
dshash_table_handle record_table_handle
Definition: typcache.c:168
#define elog(elevel,...)
Definition: elog.h:232
void * dshash_find_or_insert(dshash_table *hash_table, const void *key, bool *found)
Definition: dshash.c:430
TupleDesc local_tupdesc
Definition: typcache.c:185
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:223
dshash_table_handle typmod_table_handle
Definition: typcache.c:170

◆ TypeCacheConstrCallback()

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

Definition at line 2399 of file typcache.c.

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

Referenced by lookup_type_cache().

2400 {
2401  TypeCacheEntry *typentry;
2402 
2403  /*
2404  * Because this is called very frequently, and typically very few of the
2405  * typcache entries are for domains, we don't use hash_seq_search here.
2406  * Instead we thread all the domain-type entries together so that we can
2407  * visit them cheaply.
2408  */
2409  for (typentry = firstDomainTypeEntry;
2410  typentry != NULL;
2411  typentry = typentry->nextDomain)
2412  {
2413  /* Reset domain constraint validity information */
2415  }
2416 }
static TypeCacheEntry * firstDomainTypeEntry
Definition: typcache.c:80
struct TypeCacheEntry * nextDomain
Definition: typcache.h:132
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:102

◆ TypeCacheOpcCallback()

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

Definition at line 2370 of file typcache.c.

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

Referenced by lookup_type_cache().

2371 {
2373  TypeCacheEntry *typentry;
2374 
2375  /* TypeCacheHash must exist, else this callback wouldn't be registered */
2376  hash_seq_init(&status, TypeCacheHash);
2377  while ((typentry = (TypeCacheEntry *) hash_seq_search(&status)) != NULL)
2378  {
2379  /* Reset equality/comparison/hashing validity information */
2380  typentry->flags &= ~TCFLAGS_OPERATOR_FLAGS;
2381  }
2382 }
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
#define TCFLAGS_OPERATOR_FLAGS
Definition: typcache.c:106
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
static HTAB * TypeCacheHash
Definition: typcache.c:77

◆ TypeCacheRelCallback()

static void TypeCacheRelCallback ( Datum  arg,
Oid  relid 
)
static

Definition at line 2265 of file typcache.c.

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, TypeCacheEntry::typrelid, and TypeCacheEntry::typtype.

Referenced by lookup_type_cache().

2266 {
2268  TypeCacheEntry *typentry;
2269 
2270  /* TypeCacheHash must exist, else this callback wouldn't be registered */
2271  hash_seq_init(&status, TypeCacheHash);
2272  while ((typentry = (TypeCacheEntry *) hash_seq_search(&status)) != NULL)
2273  {
2274  if (typentry->typtype == TYPTYPE_COMPOSITE)
2275  {
2276  /* Skip if no match, unless we're zapping all composite types */
2277  if (relid != typentry->typrelid && relid != InvalidOid)
2278  continue;
2279 
2280  /* Delete tupdesc if we have it */
2281  if (typentry->tupDesc != NULL)
2282  {
2283  /*
2284  * Release our refcount, and free the tupdesc if none remain.
2285  * (Can't use DecrTupleDescRefCount because this reference is
2286  * not logged in current resource owner.)
2287  */
2288  Assert(typentry->tupDesc->tdrefcount > 0);
2289  if (--typentry->tupDesc->tdrefcount == 0)
2290  FreeTupleDesc(typentry->tupDesc);
2291  typentry->tupDesc = NULL;
2292 
2293  /*
2294  * Also clear tupDesc_identifier, so that anything watching
2295  * that will realize that the tupdesc has possibly changed.
2296  * (Alternatively, we could specify that to detect possible
2297  * tupdesc change, one must check for tupDesc != NULL as well
2298  * as tupDesc_identifier being the same as what was previously
2299  * seen. That seems error-prone.)
2300  */
2301  typentry->tupDesc_identifier = 0;
2302  }
2303 
2304  /* Reset equality/comparison/hashing validity information */
2305  typentry->flags &= ~TCFLAGS_OPERATOR_FLAGS;
2306  }
2307  else if (typentry->typtype == TYPTYPE_DOMAIN)
2308  {
2309  /*
2310  * If it's domain over composite, reset flags. (We don't bother
2311  * trying to determine whether the specific base type needs a
2312  * reset.) Note that if we haven't determined whether the base
2313  * type is composite, we don't need to reset anything.
2314  */
2315  if (typentry->flags & TCFLAGS_DOMAIN_BASE_IS_COMPOSITE)
2316  typentry->flags &= ~TCFLAGS_OPERATOR_FLAGS;
2317  }
2318  }
2319 }
#define TCFLAGS_DOMAIN_BASE_IS_COMPOSITE
Definition: typcache.c:103
#define InvalidOid
Definition: postgres_ext.h:36
char typtype
Definition: typcache.h:43
#define Assert(condition)
Definition: c.h:804
uint64 tupDesc_identifier
Definition: typcache.h:90
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
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:309
#define TCFLAGS_OPERATOR_FLAGS
Definition: typcache.c:106
int tdrefcount
Definition: tupdesc.h:84
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
TupleDesc tupDesc
Definition: typcache.h:89
static HTAB * TypeCacheHash
Definition: typcache.c:77

◆ TypeCacheTypCallback()

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

Definition at line 2330 of file typcache.c.

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

Referenced by lookup_type_cache().

2331 {
2333  TypeCacheEntry *typentry;
2334 
2335  /* TypeCacheHash must exist, else this callback wouldn't be registered */
2336  hash_seq_init(&status, TypeCacheHash);
2337  while ((typentry = (TypeCacheEntry *) hash_seq_search(&status)) != NULL)
2338  {
2339  /* Is this the targeted type row (or it's a total cache flush)? */
2340  if (hashvalue == 0 || typentry->type_id_hash == hashvalue)
2341  {
2342  /*
2343  * Mark the data obtained directly from pg_type as invalid. Also,
2344  * if it's a domain, typnotnull might've changed, so we'll need to
2345  * recalculate its constraints.
2346  */
2347  typentry->flags &= ~(TCFLAGS_HAVE_PG_TYPE_DATA |
2349  }
2350  }
2351 }
uint32 type_id_hash
Definition: typcache.h:36
#define TCFLAGS_HAVE_PG_TYPE_DATA
Definition: typcache.c:83
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:102
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:227
static HTAB * TypeCacheHash
Definition: typcache.c:77

◆ UpdateDomainConstraintRef()

void UpdateDomainConstraintRef ( DomainConstraintRef ref)

Definition at line 1342 of file typcache.c.

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

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

Variable Documentation

◆ firstDomainTypeEntry

TypeCacheEntry* firstDomainTypeEntry = NULL
static

Definition at line 80 of file typcache.c.

Referenced by lookup_type_cache().

◆ NextRecordTypmod

int32 NextRecordTypmod = 0
static

◆ RecordCacheArray

TupleDesc* RecordCacheArray = NULL
static

Definition at line 276 of file typcache.c.

◆ RecordCacheArrayLen

int32 RecordCacheArrayLen = 0
static

◆ RecordCacheHash

HTAB* RecordCacheHash = NULL
static

Definition at line 273 of file typcache.c.

◆ RecordIdentifierArray

uint64* RecordIdentifierArray = NULL
static

◆ srtr_record_table_params

const dshash_parameters srtr_record_table_params
static
Initial value:
= {
}
static int shared_record_table_compare(const void *a, const void *b, size_t size, void *arg)
Definition: typcache.c:214
static uint32 shared_record_table_hash(const void *a, size_t size, void *arg)
Definition: typcache.c:240
struct SharedRecordTableKey SharedRecordTableKey

Definition at line 255 of file typcache.c.

◆ srtr_typmod_table_params

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

Definition at line 264 of file typcache.c.

◆ tupledesc_id_counter

◆ TypeCacheHash

HTAB* TypeCacheHash = NULL
static

Definition at line 77 of file typcache.c.