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/indexing.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_CHECKED_DOMAIN_CONSTRAINTS   0x020000
 
#define TCFLAGS_DOMAIN_BASE_IS_COMPOSITE   0x040000
 
#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_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 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 void TypeCacheRelCallback (Datum arg, Oid relid)
 
static void TypeCacheTypCallback (Datum arg, int cacheid, uint32 hashvalue)
 
static void TypeCacheOpcCallback (Datum arg, int cacheid, uint32 hashvalue)
 
static void TypeCacheConstrCallback (Datum arg, int cacheid, uint32 hashvalue)
 
static void load_enum_cache_data (TypeCacheEntry *tcache)
 
static EnumItemfind_enumitem (TypeCacheEnumData *enumdata, Oid arg)
 
static int enum_oid_cmp (const void *left, const void *right)
 
static void shared_record_typmod_registry_detach (dsm_segment *segment, Datum datum)
 
static TupleDesc find_or_make_matching_shared_tupledesc (TupleDesc tupdesc)
 
static dsa_pointer share_tupledesc (dsa_area *area, TupleDesc tupdesc, uint32 typmod)
 
TypeCacheEntrylookup_type_cache (Oid type_id, int flags)
 
void InitDomainConstraintRef (Oid type_id, DomainConstraintRef *ref, MemoryContext refctx, bool need_exprstate)
 
void UpdateDomainConstraintRef (DomainConstraintRef *ref)
 
bool DomainHasConstraints (Oid type_id)
 
static void ensure_record_cache_typmod_slot_exists (int32 typmod)
 
static TupleDesc lookup_rowtype_tupdesc_internal (Oid type_id, int32 typmod, bool noError)
 
TupleDesc lookup_rowtype_tupdesc (Oid type_id, int32 typmod)
 
TupleDesc lookup_rowtype_tupdesc_noerror (Oid type_id, int32 typmod, bool noError)
 
TupleDesc lookup_rowtype_tupdesc_copy (Oid type_id, int32 typmod)
 
TupleDesc lookup_rowtype_tupdesc_domain (Oid type_id, int32 typmod, bool noError)
 
static uint32 record_type_typmod_hash (const void *data, size_t size)
 
static int record_type_typmod_compare (const void *a, const void *b, size_t size)
 
void assign_record_type_typmod (TupleDesc tupDesc)
 
uint64 assign_record_type_identifier (Oid type_id, int32 typmod)
 
size_t SharedRecordTypmodRegistryEstimate (void)
 
void SharedRecordTypmodRegistryInit (SharedRecordTypmodRegistry *registry, dsm_segment *segment, dsa_area *area)
 
void SharedRecordTypmodRegistryAttach (SharedRecordTypmodRegistry *registry)
 
static bool enum_known_sorted (TypeCacheEnumData *enumdata, Oid arg)
 
int compare_values_of_enum (TypeCacheEntry *tcache, Oid arg1, Oid arg2)
 

Variables

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

Macro Definition Documentation

◆ TCFLAGS_CHECKED_BTREE_OPCLASS

#define TCFLAGS_CHECKED_BTREE_OPCLASS   0x000002

Definition at line 85 of file typcache.c.

Referenced by lookup_type_cache().

◆ TCFLAGS_CHECKED_CMP_PROC

#define TCFLAGS_CHECKED_CMP_PROC   0x000040

Definition at line 90 of file typcache.c.

Referenced by lookup_type_cache().

◆ TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS

#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS   0x020000

◆ TCFLAGS_CHECKED_ELEM_PROPERTIES

◆ TCFLAGS_CHECKED_EQ_OPR

#define TCFLAGS_CHECKED_EQ_OPR   0x000008

Definition at line 87 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 89 of file typcache.c.

Referenced by lookup_type_cache().

◆ TCFLAGS_CHECKED_HASH_EXTENDED_PROC

#define TCFLAGS_CHECKED_HASH_EXTENDED_PROC   0x000100

Definition at line 92 of file typcache.c.

Referenced by lookup_type_cache().

◆ TCFLAGS_CHECKED_HASH_OPCLASS

#define TCFLAGS_CHECKED_HASH_OPCLASS   0x000004

Definition at line 86 of file typcache.c.

Referenced by lookup_type_cache().

◆ TCFLAGS_CHECKED_HASH_PROC

#define TCFLAGS_CHECKED_HASH_PROC   0x000080

Definition at line 91 of file typcache.c.

Referenced by lookup_type_cache().

◆ TCFLAGS_CHECKED_LT_OPR

#define TCFLAGS_CHECKED_LT_OPR   0x000010

Definition at line 88 of file typcache.c.

Referenced by lookup_type_cache().

◆ TCFLAGS_DOMAIN_BASE_IS_COMPOSITE

#define TCFLAGS_DOMAIN_BASE_IS_COMPOSITE   0x040000

Definition at line 102 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 95 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 94 of file typcache.c.

Referenced by array_element_has_equality(), and cache_array_element_properties().

◆ TCFLAGS_HAVE_ELEM_EXTENDED_HASHING

#define TCFLAGS_HAVE_ELEM_EXTENDED_HASHING   0x002000

◆ TCFLAGS_HAVE_ELEM_HASHING

#define TCFLAGS_HAVE_ELEM_HASHING   0x001000

◆ TCFLAGS_HAVE_FIELD_COMPARE

#define TCFLAGS_HAVE_FIELD_COMPARE   0x010000

Definition at line 100 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 99 of file typcache.c.

Referenced by cache_record_field_properties(), and record_fields_have_equality().

◆ TCFLAGS_HAVE_PG_TYPE_DATA

#define TCFLAGS_HAVE_PG_TYPE_DATA   0x000001

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

Definition at line 105 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 1382 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().

1383 {
1384  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1386  return (typentry->flags & TCFLAGS_HAVE_ELEM_COMPARE) != 0;
1387 }
#define TCFLAGS_HAVE_ELEM_COMPARE
Definition: typcache.c:95
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:93
static void cache_array_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1406

◆ array_element_has_equality()

static bool array_element_has_equality ( TypeCacheEntry typentry)
static

Definition at line 1374 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().

1375 {
1376  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1378  return (typentry->flags & TCFLAGS_HAVE_ELEM_EQUALITY) != 0;
1379 }
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:93
static void cache_array_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1406
#define TCFLAGS_HAVE_ELEM_EQUALITY
Definition: typcache.c:94

◆ array_element_has_extended_hashing()

static bool array_element_has_extended_hashing ( TypeCacheEntry typentry)
static

Definition at line 1398 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().

1399 {
1400  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1402  return (typentry->flags & TCFLAGS_HAVE_ELEM_EXTENDED_HASHING) != 0;
1403 }
#define TCFLAGS_HAVE_ELEM_EXTENDED_HASHING
Definition: typcache.c:97
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:93
static void cache_array_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1406

◆ array_element_has_hashing()

static bool array_element_has_hashing ( TypeCacheEntry typentry)
static

Definition at line 1390 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().

1391 {
1392  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1394  return (typentry->flags & TCFLAGS_HAVE_ELEM_HASHING) != 0;
1395 }
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:93
static void cache_array_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1406
#define TCFLAGS_HAVE_ELEM_HASHING
Definition: typcache.c:96

◆ assign_record_type_identifier()

uint64 assign_record_type_identifier ( Oid  type_id,
int32  typmod 
)

Definition at line 1905 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().

1906 {
1907  if (type_id != RECORDOID)
1908  {
1909  /*
1910  * It's a named composite type, so use the regular typcache.
1911  */
1912  TypeCacheEntry *typentry;
1913 
1914  typentry = lookup_type_cache(type_id, TYPECACHE_TUPDESC);
1915  if (typentry->tupDesc == NULL)
1916  ereport(ERROR,
1917  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1918  errmsg("type %s is not composite",
1919  format_type_be(type_id))));
1920  Assert(typentry->tupDesc_identifier != 0);
1921  return typentry->tupDesc_identifier;
1922  }
1923  else
1924  {
1925  /*
1926  * It's a transient record type, so look in our record-type table.
1927  */
1928  if (typmod >= 0 && typmod < RecordCacheArrayLen &&
1929  RecordCacheArray[typmod] != NULL)
1930  {
1931  Assert(RecordIdentifierArray[typmod] != 0);
1932  return RecordIdentifierArray[typmod];
1933  }
1934 
1935  /* For anonymous or unrecognized record type, generate a new ID */
1936  return ++tupledesc_id_counter;
1937  }
1938 }
int errcode(int sqlerrcode)
Definition: elog.c:610
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
static uint64 tupledesc_id_counter
Definition: typcache.c:285
static TupleDesc * RecordCacheArray
Definition: typcache.c:275
#define ERROR
Definition: elog.h:43
static int32 RecordCacheArrayLen
Definition: typcache.c:277
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:331
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:745
uint64 tupDesc_identifier
Definition: typcache.h:89
int errmsg(const char *fmt,...)
Definition: elog.c:824
TupleDesc tupDesc
Definition: typcache.h:88
#define TYPECACHE_TUPDESC
Definition: typcache.h:138
static uint64 * RecordIdentifierArray
Definition: typcache.c:276

◆ assign_record_type_typmod()

void assign_record_type_typmod ( TupleDesc  tupDesc)

Definition at line 1830 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(), MemSet, 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().

1831 {
1832  RecordCacheEntry *recentry;
1833  TupleDesc entDesc;
1834  bool found;
1835  MemoryContext oldcxt;
1836 
1837  Assert(tupDesc->tdtypeid == RECORDOID);
1838 
1839  if (RecordCacheHash == NULL)
1840  {
1841  /* First time through: initialize the hash table */
1842  HASHCTL ctl;
1843 
1844  MemSet(&ctl, 0, sizeof(ctl));
1845  ctl.keysize = sizeof(TupleDesc); /* just the pointer */
1846  ctl.entrysize = sizeof(RecordCacheEntry);
1849  RecordCacheHash = hash_create("Record information cache", 64,
1850  &ctl,
1852 
1853  /* Also make sure CacheMemoryContext exists */
1854  if (!CacheMemoryContext)
1856  }
1857 
1858  /* Find or create a hashtable entry for this tuple descriptor */
1860  (void *) &tupDesc,
1861  HASH_ENTER, &found);
1862  if (found && recentry->tupdesc != NULL)
1863  {
1864  tupDesc->tdtypmod = recentry->tupdesc->tdtypmod;
1865  return;
1866  }
1867 
1868  /* Not present, so need to manufacture an entry */
1869  recentry->tupdesc = NULL;
1871 
1872  /* Look in the SharedRecordTypmodRegistry, if attached */
1873  entDesc = find_or_make_matching_shared_tupledesc(tupDesc);
1874  if (entDesc == NULL)
1875  {
1876  /* Reference-counted local cache only. */
1877  entDesc = CreateTupleDescCopy(tupDesc);
1878  entDesc->tdrefcount = 1;
1879  entDesc->tdtypmod = NextRecordTypmod++;
1880  }
1882  RecordCacheArray[entDesc->tdtypmod] = entDesc;
1883  recentry->tupdesc = entDesc;
1884 
1885  /* Assign a unique tupdesc identifier, too. */
1887 
1888  /* Update the caller's tuple descriptor. */
1889  tupDesc->tdtypmod = entDesc->tdtypmod;
1890 
1891  MemoryContextSwitchTo(oldcxt);
1892 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
#define HASH_ELEM
Definition: hsearch.h:85
static TupleDesc find_or_make_matching_shared_tupledesc(TupleDesc tupdesc)
Definition: typcache.c:2621
struct RecordCacheEntry RecordCacheEntry
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Size entrysize
Definition: hsearch.h:72
#define MemSet(start, val, len)
Definition: c.h:949
static uint64 tupledesc_id_counter
Definition: typcache.c:285
static HTAB * RecordCacheHash
Definition: typcache.c:272
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
static TupleDesc * RecordCacheArray
Definition: typcache.c:275
int32 tdtypmod
Definition: tupdesc.h:83
static int32 NextRecordTypmod
Definition: typcache.c:278
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:326
static void ensure_record_cache_typmod_slot_exists(int32 typmod)
Definition: typcache.c:1582
Size keysize
Definition: hsearch.h:71
HashCompareFunc match
Definition: hsearch.h:74
static uint32 record_type_typmod_hash(const void *data, size_t size)
Definition: typcache.c:1803
#define Assert(condition)
Definition: c.h:745
#define HASH_COMPARE
Definition: hsearch.h:88
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:1814
TupleDesc tupdesc
Definition: typcache.c:157
int tdrefcount
Definition: tupdesc.h:84
static uint64 * RecordIdentifierArray
Definition: typcache.c:276
HashValueFunc hash
Definition: hsearch.h:73
#define HASH_FUNCTION
Definition: hsearch.h:87
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ cache_array_element_properties()

static void cache_array_element_properties ( TypeCacheEntry typentry)
static

Definition at line 1406 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().

1407 {
1408  Oid elem_type = get_base_element_type(typentry->type_id);
1409 
1410  if (OidIsValid(elem_type))
1411  {
1412  TypeCacheEntry *elementry;
1413 
1414  elementry = lookup_type_cache(elem_type,
1419  if (OidIsValid(elementry->eq_opr))
1420  typentry->flags |= TCFLAGS_HAVE_ELEM_EQUALITY;
1421  if (OidIsValid(elementry->cmp_proc))
1422  typentry->flags |= TCFLAGS_HAVE_ELEM_COMPARE;
1423  if (OidIsValid(elementry->hash_proc))
1424  typentry->flags |= TCFLAGS_HAVE_ELEM_HASHING;
1425  if (OidIsValid(elementry->hash_extended_proc))
1427  }
1429 }
#define TCFLAGS_HAVE_ELEM_COMPARE
Definition: typcache.c:95
#define TYPECACHE_EQ_OPR
Definition: typcache.h:130
#define TCFLAGS_HAVE_ELEM_EXTENDED_HASHING
Definition: typcache.c:97
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:651
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:93
Oid hash_extended_proc
Definition: typcache.h:65
#define TYPECACHE_HASH_EXTENDED_PROC
Definition: typcache.h:144
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:331
#define TYPECACHE_CMP_PROC
Definition: typcache.h:133
#define TCFLAGS_HAVE_ELEM_EQUALITY
Definition: typcache.c:94
#define TCFLAGS_HAVE_ELEM_HASHING
Definition: typcache.c:96
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2709
#define TYPECACHE_HASH_PROC
Definition: typcache.h:134

◆ cache_range_element_properties()

static void cache_range_element_properties ( TypeCacheEntry typentry)
static

Definition at line 1554 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().

1555 {
1556  /* load up subtype link if we didn't already */
1557  if (typentry->rngelemtype == NULL &&
1558  typentry->typtype == TYPTYPE_RANGE)
1559  load_rangetype_info(typentry);
1560 
1561  if (typentry->rngelemtype != NULL)
1562  {
1563  TypeCacheEntry *elementry;
1564 
1565  /* might need to calculate subtype's hash function properties */
1566  elementry = lookup_type_cache(typentry->rngelemtype->type_id,
1569  if (OidIsValid(elementry->hash_proc))
1570  typentry->flags |= TCFLAGS_HAVE_ELEM_HASHING;
1571  if (OidIsValid(elementry->hash_extended_proc))
1573  }
1575 }
#define TCFLAGS_HAVE_ELEM_EXTENDED_HASHING
Definition: typcache.c:97
#define OidIsValid(objectId)
Definition: c.h:651
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:93
Oid hash_extended_proc
Definition: typcache.h:65
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:97
#define TYPECACHE_HASH_EXTENDED_PROC
Definition: typcache.h:144
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:331
static void load_rangetype_info(TypeCacheEntry *typentry)
Definition: typcache.c:878
char typtype
Definition: typcache.h:43
#define TCFLAGS_HAVE_ELEM_HASHING
Definition: typcache.c:96
#define TYPECACHE_HASH_PROC
Definition: typcache.h:134

◆ cache_record_field_properties()

static void cache_record_field_properties ( TypeCacheEntry typentry)
static

Definition at line 1452 of file typcache.c.

References TypeCacheEntry::cmp_proc, DecrTupleDescRefCount(), TypeCacheEntry::domainBaseType, TypeCacheEntry::domainBaseTypmod, TypeCacheEntry::eq_opr, TypeCacheEntry::flags, getBaseTypeAndTypmod(), 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, TypeCacheEntry::tupDesc, TupleDescAttr, TypeCacheEntry::type_id, TYPECACHE_CMP_PROC, TYPECACHE_EQ_OPR, and TypeCacheEntry::typtype.

Referenced by record_fields_have_compare(), and record_fields_have_equality().

1453 {
1454  /*
1455  * For type RECORD, we can't really tell what will work, since we don't
1456  * have access here to the specific anonymous type. Just assume that
1457  * everything will (we may get a failure at runtime ...)
1458  */
1459  if (typentry->type_id == RECORDOID)
1460  typentry->flags |= (TCFLAGS_HAVE_FIELD_EQUALITY |
1462  else if (typentry->typtype == TYPTYPE_COMPOSITE)
1463  {
1464  TupleDesc tupdesc;
1465  int newflags;
1466  int i;
1467 
1468  /* Fetch composite type's tupdesc if we don't have it already */
1469  if (typentry->tupDesc == NULL)
1470  load_typcache_tupdesc(typentry);
1471  tupdesc = typentry->tupDesc;
1472 
1473  /* Must bump the refcount while we do additional catalog lookups */
1474  IncrTupleDescRefCount(tupdesc);
1475 
1476  /* Have each property if all non-dropped fields have the property */
1477  newflags = (TCFLAGS_HAVE_FIELD_EQUALITY |
1479  for (i = 0; i < tupdesc->natts; i++)
1480  {
1481  TypeCacheEntry *fieldentry;
1482  Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
1483 
1484  if (attr->attisdropped)
1485  continue;
1486 
1487  fieldentry = lookup_type_cache(attr->atttypid,
1490  if (!OidIsValid(fieldentry->eq_opr))
1491  newflags &= ~TCFLAGS_HAVE_FIELD_EQUALITY;
1492  if (!OidIsValid(fieldentry->cmp_proc))
1493  newflags &= ~TCFLAGS_HAVE_FIELD_COMPARE;
1494 
1495  /* We can drop out of the loop once we disprove all bits */
1496  if (newflags == 0)
1497  break;
1498  }
1499  typentry->flags |= newflags;
1500 
1501  DecrTupleDescRefCount(tupdesc);
1502  }
1503  else if (typentry->typtype == TYPTYPE_DOMAIN)
1504  {
1505  /* If it's domain over composite, copy base type's properties */
1506  TypeCacheEntry *baseentry;
1507 
1508  /* load up basetype info if we didn't already */
1509  if (typentry->domainBaseType == InvalidOid)
1510  {
1511  typentry->domainBaseTypmod = -1;
1512  typentry->domainBaseType =
1513  getBaseTypeAndTypmod(typentry->type_id,
1514  &typentry->domainBaseTypmod);
1515  }
1516  baseentry = lookup_type_cache(typentry->domainBaseType,
1519  if (baseentry->typtype == TYPTYPE_COMPOSITE)
1520  {
1522  typentry->flags |= baseentry->flags & (TCFLAGS_HAVE_FIELD_EQUALITY |
1524  }
1525  }
1527 }
static void load_typcache_tupdesc(TypeCacheEntry *typentry)
Definition: typcache.c:844
void IncrTupleDescRefCount(TupleDesc tupdesc)
Definition: tupdesc.c:375
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition: lsyscache.c:2426
#define TCFLAGS_CHECKED_FIELD_PROPERTIES
Definition: typcache.c:98
#define TCFLAGS_DOMAIN_BASE_IS_COMPOSITE
Definition: typcache.c:102
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define TYPECACHE_EQ_OPR
Definition: typcache.h:130
#define OidIsValid(objectId)
Definition: c.h:651
Oid domainBaseType
Definition: typcache.h:107
#define TCFLAGS_HAVE_FIELD_COMPARE
Definition: typcache.c:100
int32 domainBaseTypmod
Definition: typcache.h:108
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
#define TCFLAGS_HAVE_FIELD_EQUALITY
Definition: typcache.c:99
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:331
#define InvalidOid
Definition: postgres_ext.h:36
#define TYPECACHE_CMP_PROC
Definition: typcache.h:133
char typtype
Definition: typcache.h:43
void DecrTupleDescRefCount(TupleDesc tupdesc)
Definition: tupdesc.c:393
int i
TupleDesc tupDesc
Definition: typcache.h:88

◆ compare_values_of_enum()

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

Definition at line 2337 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().

2338 {
2339  TypeCacheEnumData *enumdata;
2340  EnumItem *item1;
2341  EnumItem *item2;
2342 
2343  /*
2344  * Equal OIDs are certainly equal --- this case was probably handled by
2345  * our caller, but we may as well check.
2346  */
2347  if (arg1 == arg2)
2348  return 0;
2349 
2350  /* Load up the cache if first time through */
2351  if (tcache->enumData == NULL)
2352  load_enum_cache_data(tcache);
2353  enumdata = tcache->enumData;
2354 
2355  /*
2356  * If both OIDs are known-sorted, we can just compare them directly.
2357  */
2358  if (enum_known_sorted(enumdata, arg1) &&
2359  enum_known_sorted(enumdata, arg2))
2360  {
2361  if (arg1 < arg2)
2362  return -1;
2363  else
2364  return 1;
2365  }
2366 
2367  /*
2368  * Slow path: we have to identify their actual sort-order positions.
2369  */
2370  item1 = find_enumitem(enumdata, arg1);
2371  item2 = find_enumitem(enumdata, arg2);
2372 
2373  if (item1 == NULL || item2 == NULL)
2374  {
2375  /*
2376  * We couldn't find one or both values. That means the enum has
2377  * changed under us, so re-initialize the cache and try again. We
2378  * don't bother retrying the known-sorted case in this path.
2379  */
2380  load_enum_cache_data(tcache);
2381  enumdata = tcache->enumData;
2382 
2383  item1 = find_enumitem(enumdata, arg1);
2384  item2 = find_enumitem(enumdata, arg2);
2385 
2386  /*
2387  * If we still can't find the values, complain: we must have corrupt
2388  * data.
2389  */
2390  if (item1 == NULL)
2391  elog(ERROR, "enum value %u not found in cache for enum %s",
2392  arg1, format_type_be(tcache->type_id));
2393  if (item2 == NULL)
2394  elog(ERROR, "enum value %u not found in cache for enum %s",
2395  arg2, format_type_be(tcache->type_id));
2396  }
2397 
2398  if (item1->sort_order < item2->sort_order)
2399  return -1;
2400  else if (item1->sort_order > item2->sort_order)
2401  return 1;
2402  else
2403  return 0;
2404 }
struct TypeCacheEnumData * enumData
Definition: typcache.h:123
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
#define ERROR
Definition: elog.h:43
static bool enum_known_sorted(TypeCacheEnumData *enumdata, Oid arg)
Definition: typcache.c:2308
static EnumItem * find_enumitem(TypeCacheEnumData *enumdata, Oid arg)
Definition: typcache.c:2565
static void load_enum_cache_data(TypeCacheEntry *tcache)
Definition: typcache.c:2410
float4 sort_order
Definition: typcache.c:133
#define elog(elevel,...)
Definition: elog.h:214

◆ dccref_deletion_callback()

static void dccref_deletion_callback ( void *  arg)
static

Definition at line 1201 of file typcache.c.

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

Referenced by InitDomainConstraintRef().

1202 {
1204  DomainConstraintCache *dcc = ref->dcc;
1205 
1206  /* Paranoia --- be sure link is nulled before trying to release */
1207  if (dcc)
1208  {
1209  ref->constraints = NIL;
1210  ref->dcc = NULL;
1211  decr_dcc_refcount(dcc);
1212  }
1213 }
#define NIL
Definition: pg_list.h:65
DomainConstraintCache * dcc
Definition: typcache.h:164
void * arg
static void decr_dcc_refcount(DomainConstraintCache *dcc)
Definition: typcache.c:1190

◆ dcs_cmp()

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

Definition at line 1177 of file typcache.c.

Referenced by load_domaintype_info().

1178 {
1179  const DomainConstraintState *const *ca = (const DomainConstraintState *const *) a;
1180  const DomainConstraintState *const *cb = (const DomainConstraintState *const *) b;
1181 
1182  return strcmp((*ca)->name, (*cb)->name);
1183 }

◆ decr_dcc_refcount()

static void decr_dcc_refcount ( DomainConstraintCache dcc)
static

Definition at line 1190 of file typcache.c.

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

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

1191 {
1192  Assert(dcc->dccRefCount > 0);
1193  if (--(dcc->dccRefCount) <= 0)
1195 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:212
MemoryContext dccContext
Definition: typcache.c:125
#define Assert(condition)
Definition: c.h:745

◆ DomainHasConstraints()

bool DomainHasConstraints ( Oid  type_id)

Definition at line 1347 of file typcache.c.

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

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

1348 {
1349  TypeCacheEntry *typentry;
1350 
1351  /*
1352  * Note: a side effect is to cause the typcache's domain data to become
1353  * valid. This is fine since we'll likely need it soon if there is any.
1354  */
1355  typentry = lookup_type_cache(type_id, TYPECACHE_DOMAIN_CONSTR_INFO);
1356 
1357  return (typentry->domainData != NULL);
1358 }
DomainConstraintCache * domainData
Definition: typcache.h:114
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:331
#define TYPECACHE_DOMAIN_CONSTR_INFO
Definition: typcache.h:143

◆ ensure_record_cache_typmod_slot_exists()

static void ensure_record_cache_typmod_slot_exists ( int32  typmod)
static

Definition at line 1582 of file typcache.c.

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

Referenced by assign_record_type_typmod(), and lookup_rowtype_tupdesc_internal().

1583 {
1584  if (RecordCacheArray == NULL)
1585  {
1588  RecordIdentifierArray = (uint64 *)
1589  MemoryContextAllocZero(CacheMemoryContext, 64 * sizeof(uint64));
1590  RecordCacheArrayLen = 64;
1591  }
1592 
1593  if (typmod >= RecordCacheArrayLen)
1594  {
1595  int32 newlen = RecordCacheArrayLen * 2;
1596 
1597  while (typmod >= newlen)
1598  newlen *= 2;
1599 
1601  newlen * sizeof(TupleDesc));
1603  (newlen - RecordCacheArrayLen) * sizeof(TupleDesc));
1605  newlen * sizeof(uint64));
1607  (newlen - RecordCacheArrayLen) * sizeof(uint64));
1608  RecordCacheArrayLen = newlen;
1609  }
1610 }
signed int int32
Definition: c.h:362
static TupleDesc * RecordCacheArray
Definition: typcache.c:275
static int32 RecordCacheArrayLen
Definition: typcache.c:277
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:840
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1070
static uint64 * RecordIdentifierArray
Definition: typcache.c:276
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ enum_known_sorted()

static bool enum_known_sorted ( TypeCacheEnumData enumdata,
Oid  arg 
)
inlinestatic

Definition at line 2308 of file typcache.c.

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

Referenced by compare_values_of_enum().

2309 {
2310  Oid offset;
2311 
2312  if (arg < enumdata->bitmap_base)
2313  return false;
2314  offset = arg - enumdata->bitmap_base;
2315  if (offset > (Oid) INT_MAX)
2316  return false;
2317  return bms_is_member((int) offset, enumdata->sorted_values);
2318 }
unsigned int Oid
Definition: postgres_ext.h:31
Bitmapset * sorted_values
Definition: typcache.c:139
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 2582 of file typcache.c.

References EnumItem::enum_oid.

Referenced by find_enumitem(), and load_enum_cache_data().

2583 {
2584  const EnumItem *l = (const EnumItem *) left;
2585  const EnumItem *r = (const EnumItem *) right;
2586 
2587  if (l->enum_oid < r->enum_oid)
2588  return -1;
2589  else if (l->enum_oid > r->enum_oid)
2590  return 1;
2591  else
2592  return 0;
2593 }
Oid enum_oid
Definition: typcache.c:132

◆ find_enumitem()

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

Definition at line 2565 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().

2566 {
2567  EnumItem srch;
2568 
2569  /* On some versions of Solaris, bsearch of zero items dumps core */
2570  if (enumdata->num_values <= 0)
2571  return NULL;
2572 
2573  srch.enum_oid = arg;
2574  return bsearch(&srch, enumdata->enum_values, enumdata->num_values,
2575  sizeof(EnumItem), enum_oid_cmp);
2576 }
EnumItem enum_values[FLEXIBLE_ARRAY_MEMBER]
Definition: typcache.c:141
Oid enum_oid
Definition: typcache.c:132
static int enum_oid_cmp(const void *left, const void *right)
Definition: typcache.c:2582
void * arg

◆ find_or_make_matching_shared_tupledesc()

static TupleDesc find_or_make_matching_shared_tupledesc ( TupleDesc  tupdesc)
static

Definition at line 2621 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().

2622 {
2623  TupleDesc result;
2625  SharedRecordTableEntry *record_table_entry;
2626  SharedTypmodTableEntry *typmod_table_entry;
2627  dsa_pointer shared_dp;
2628  bool found;
2629  uint32 typmod;
2630 
2631  /* If not even attached, nothing to do. */
2633  return NULL;
2634 
2635  /* Try to find a matching tuple descriptor in the record table. */
2636  key.shared = false;
2637  key.u.local_tupdesc = tupdesc;
2638  record_table_entry = (SharedRecordTableEntry *)
2640  if (record_table_entry)
2641  {
2642  Assert(record_table_entry->key.shared);
2644  record_table_entry);
2645  result = (TupleDesc)
2647  record_table_entry->key.u.shared_tupdesc);
2648  Assert(result->tdrefcount == -1);
2649 
2650  return result;
2651  }
2652 
2653  /* Allocate a new typmod number. This will be wasted if we error out. */
2654  typmod = (int)
2656  1);
2657 
2658  /* Copy the TupleDesc into shared memory. */
2659  shared_dp = share_tupledesc(CurrentSession->area, tupdesc, typmod);
2660 
2661  /*
2662  * Create an entry in the typmod table so that others will understand this
2663  * typmod number.
2664  */
2665  PG_TRY();
2666  {
2667  typmod_table_entry = (SharedTypmodTableEntry *)
2669  &typmod, &found);
2670  if (found)
2671  elog(ERROR, "cannot create duplicate shared record typmod");
2672  }
2673  PG_CATCH();
2674  {
2675  dsa_free(CurrentSession->area, shared_dp);
2676  PG_RE_THROW();
2677  }
2678  PG_END_TRY();
2679  typmod_table_entry->typmod = typmod;
2680  typmod_table_entry->shared_tupdesc = shared_dp;
2682  typmod_table_entry);
2683 
2684  /*
2685  * Finally create an entry in the record table so others with matching
2686  * tuple descriptors can reuse the typmod.
2687  */
2688  record_table_entry = (SharedRecordTableEntry *)
2690  &found);
2691  if (found)
2692  {
2693  /*
2694  * Someone concurrently inserted a matching tuple descriptor since the
2695  * first time we checked. Use that one instead.
2696  */
2698  record_table_entry);
2699 
2700  /* Might as well free up the space used by the one we created. */
2702  &typmod);
2703  Assert(found);
2704  dsa_free(CurrentSession->area, shared_dp);
2705 
2706  /* Return the one we found. */
2707  Assert(record_table_entry->key.shared);
2708  result = (TupleDesc)
2710  record_table_entry->key.shared);
2711  Assert(result->tdrefcount == -1);
2712 
2713  return result;
2714  }
2715 
2716  /* Store it and return it. */
2717  record_table_entry->key.shared = true;
2718  record_table_entry->key.u.shared_tupdesc = shared_dp;
2720  record_table_entry);
2721  result = (TupleDesc)
2722  dsa_get_address(CurrentSession->area, shared_dp);
2723  Assert(result->tdrefcount == -1);
2724 
2725  return result;
2726 }
Session * CurrentSession
Definition: session.c:48
dshash_table * shared_record_table
Definition: session.h:32
SharedRecordTableKey key
Definition: typcache.c:196
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:206
pg_atomic_uint32 next_typmod
Definition: typcache.c:171
#define ERROR
Definition: elog.h:43
dsa_area * area
Definition: session.h:28
unsigned int uint32
Definition: c.h:374
dsa_pointer shared_tupdesc
Definition: typcache.c:185
union SharedRecordTableKey::@35 u
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:305
bool dshash_delete_key(dshash_table *hash_table, const void *key)
Definition: dshash.c:502
#define Assert(condition)
Definition: c.h:745
static dsa_pointer share_tupledesc(dsa_area *area, TupleDesc tupdesc, uint32 typmod)
Definition: typcache.c:2600
#define PG_RE_THROW()
Definition: elog.h:336
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:214
void * dshash_find_or_insert(dshash_table *hash_table, const void *key, bool *found)
Definition: dshash.c:430
TupleDesc local_tupdesc
Definition: typcache.c:184
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:295
#define PG_END_TRY()
Definition: elog.h:320

◆ InitDomainConstraintRef()

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

Definition at line 1260 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().

1262 {
1263  /* Look up the typcache entry --- we assume it survives indefinitely */
1265  ref->need_exprstate = need_exprstate;
1266  /* For safety, establish the callback before acquiring a refcount */
1267  ref->refctx = refctx;
1268  ref->dcc = NULL;
1270  ref->callback.arg = (void *) ref;
1272  /* Acquire refcount if there are constraints, and set up exported list */
1273  if (ref->tcache->domainData)
1274  {
1275  ref->dcc = ref->tcache->domainData;
1276  ref->dcc->dccRefCount++;
1277  if (ref->need_exprstate)
1279  ref->refctx);
1280  else
1281  ref->constraints = ref->dcc->constraints;
1282  }
1283  else
1284  ref->constraints = NIL;
1285 }
MemoryContextCallback callback
Definition: typcache.h:165
MemoryContextCallbackFunction func
Definition: palloc.h:49
#define NIL
Definition: pg_list.h:65
DomainConstraintCache * dcc
Definition: typcache.h:164
static void dccref_deletion_callback(void *arg)
Definition: typcache.c:1201
DomainConstraintCache * domainData
Definition: typcache.h:114
MemoryContext refctx
Definition: typcache.h:159
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:331
static List * prep_domain_constraints(List *constraints, MemoryContext execctx)
Definition: typcache.c:1222
#define TYPECACHE_DOMAIN_CONSTR_INFO
Definition: typcache.h:143
TypeCacheEntry * tcache
Definition: typcache.h:160
void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)
Definition: mcxt.c:286

◆ load_domaintype_info()

static void load_domaintype_info ( TypeCacheEntry typentry)
static

Definition at line 941 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().

942 {
943  Oid typeOid = typentry->type_id;
945  bool notNull = false;
946  DomainConstraintState **ccons;
947  int cconslen;
948  Relation conRel;
949  MemoryContext oldcxt;
950 
951  /*
952  * If we're here, any existing constraint info is stale, so release it.
953  * For safety, be sure to null the link before trying to delete the data.
954  */
955  if (typentry->domainData)
956  {
957  dcc = typentry->domainData;
958  typentry->domainData = NULL;
959  decr_dcc_refcount(dcc);
960  }
961 
962  /*
963  * We try to optimize the common case of no domain constraints, so don't
964  * create the dcc object and context until we find a constraint. Likewise
965  * for the temp sorting array.
966  */
967  dcc = NULL;
968  ccons = NULL;
969  cconslen = 0;
970 
971  /*
972  * Scan pg_constraint for relevant constraints. We want to find
973  * constraints for not just this domain, but any ancestor domains, so the
974  * outer loop crawls up the domain stack.
975  */
976  conRel = table_open(ConstraintRelationId, AccessShareLock);
977 
978  for (;;)
979  {
980  HeapTuple tup;
981  HeapTuple conTup;
982  Form_pg_type typTup;
983  int nccons = 0;
984  ScanKeyData key[1];
985  SysScanDesc scan;
986 
987  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
988  if (!HeapTupleIsValid(tup))
989  elog(ERROR, "cache lookup failed for type %u", typeOid);
990  typTup = (Form_pg_type) GETSTRUCT(tup);
991 
992  if (typTup->typtype != TYPTYPE_DOMAIN)
993  {
994  /* Not a domain, so done */
995  ReleaseSysCache(tup);
996  break;
997  }
998 
999  /* Test for NOT NULL Constraint */
1000  if (typTup->typnotnull)
1001  notNull = true;
1002 
1003  /* Look for CHECK Constraints on this domain */
1004  ScanKeyInit(&key[0],
1005  Anum_pg_constraint_contypid,
1006  BTEqualStrategyNumber, F_OIDEQ,
1007  ObjectIdGetDatum(typeOid));
1008 
1009  scan = systable_beginscan(conRel, ConstraintTypidIndexId, true,
1010  NULL, 1, key);
1011 
1012  while (HeapTupleIsValid(conTup = systable_getnext(scan)))
1013  {
1015  Datum val;
1016  bool isNull;
1017  char *constring;
1018  Expr *check_expr;
1020 
1021  /* Ignore non-CHECK constraints (presently, shouldn't be any) */
1022  if (c->contype != CONSTRAINT_CHECK)
1023  continue;
1024 
1025  /* Not expecting conbin to be NULL, but we'll test for it anyway */
1026  val = fastgetattr(conTup, Anum_pg_constraint_conbin,
1027  conRel->rd_att, &isNull);
1028  if (isNull)
1029  elog(ERROR, "domain \"%s\" constraint \"%s\" has NULL conbin",
1030  NameStr(typTup->typname), NameStr(c->conname));
1031 
1032  /* Convert conbin to C string in caller context */
1033  constring = TextDatumGetCString(val);
1034 
1035  /* Create the DomainConstraintCache object and context if needed */
1036  if (dcc == NULL)
1037  {
1038  MemoryContext cxt;
1039 
1041  "Domain constraints",
1043  dcc = (DomainConstraintCache *)
1045  dcc->constraints = NIL;
1046  dcc->dccContext = cxt;
1047  dcc->dccRefCount = 0;
1048  }
1049 
1050  /* Create node trees in DomainConstraintCache's context */
1051  oldcxt = MemoryContextSwitchTo(dcc->dccContext);
1052 
1053  check_expr = (Expr *) stringToNode(constring);
1054 
1055  /*
1056  * Plan the expression, since ExecInitExpr will expect that.
1057  *
1058  * Note: caching the result of expression_planner() is not very
1059  * good practice. Ideally we'd use a CachedExpression here so
1060  * that we would react promptly to, eg, changes in inlined
1061  * functions. However, because we don't support mutable domain
1062  * CHECK constraints, it's not really clear that it's worth the
1063  * extra overhead to do that.
1064  */
1065  check_expr = expression_planner(check_expr);
1066 
1069  r->name = pstrdup(NameStr(c->conname));
1070  r->check_expr = check_expr;
1071  r->check_exprstate = NULL;
1072 
1073  MemoryContextSwitchTo(oldcxt);
1074 
1075  /* Accumulate constraints in an array, for sorting below */
1076  if (ccons == NULL)
1077  {
1078  cconslen = 8;
1079  ccons = (DomainConstraintState **)
1080  palloc(cconslen * sizeof(DomainConstraintState *));
1081  }
1082  else if (nccons >= cconslen)
1083  {
1084  cconslen *= 2;
1085  ccons = (DomainConstraintState **)
1086  repalloc(ccons, cconslen * sizeof(DomainConstraintState *));
1087  }
1088  ccons[nccons++] = r;
1089  }
1090 
1091  systable_endscan(scan);
1092 
1093  if (nccons > 0)
1094  {
1095  /*
1096  * Sort the items for this domain, so that CHECKs are applied in a
1097  * deterministic order.
1098  */
1099  if (nccons > 1)
1100  qsort(ccons, nccons, sizeof(DomainConstraintState *), dcs_cmp);
1101 
1102  /*
1103  * Now attach them to the overall list. Use lcons() here because
1104  * constraints of parent domains should be applied earlier.
1105  */
1106  oldcxt = MemoryContextSwitchTo(dcc->dccContext);
1107  while (nccons > 0)
1108  dcc->constraints = lcons(ccons[--nccons], dcc->constraints);
1109  MemoryContextSwitchTo(oldcxt);
1110  }
1111 
1112  /* loop to next domain in stack */
1113  typeOid = typTup->typbasetype;
1114  ReleaseSysCache(tup);
1115  }
1116 
1117  table_close(conRel, AccessShareLock);
1118 
1119  /*
1120  * Only need to add one NOT NULL check regardless of how many domains in
1121  * the stack request it.
1122  */
1123  if (notNull)
1124  {
1126 
1127  /* Create the DomainConstraintCache object and context if needed */
1128  if (dcc == NULL)
1129  {
1130  MemoryContext cxt;
1131 
1133  "Domain constraints",
1135  dcc = (DomainConstraintCache *)
1137  dcc->constraints = NIL;
1138  dcc->dccContext = cxt;
1139  dcc->dccRefCount = 0;
1140  }
1141 
1142  /* Create node trees in DomainConstraintCache's context */
1143  oldcxt = MemoryContextSwitchTo(dcc->dccContext);
1144 
1146 
1148  r->name = pstrdup("NOT NULL");
1149  r->check_expr = NULL;
1150  r->check_exprstate = NULL;
1151 
1152  /* lcons to apply the nullness check FIRST */
1153  dcc->constraints = lcons(r, dcc->constraints);
1154 
1155  MemoryContextSwitchTo(oldcxt);
1156  }
1157 
1158  /*
1159  * If we made a constraint object, move it into CacheMemoryContext and
1160  * attach it to the typcache entry.
1161  */
1162  if (dcc)
1163  {
1165  typentry->domainData = dcc;
1166  dcc->dccRefCount++; /* count the typcache's reference */
1167  }
1168 
1169  /* Either way, the typcache entry's domain data is now valid. */
1171 }
#define NIL
Definition: pg_list.h:65
#define AllocSetContextCreate
Definition: memutils.h:170
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:712
MemoryContext dccContext
Definition: typcache.c:125
DomainConstraintType constrainttype
Definition: execnodes.h:896
DomainConstraintCache * domainData
Definition: typcache.h:114
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:355
char * pstrdup(const char *in)
Definition: mcxt.c:1187
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:202
Expr * expression_planner(Expr *expr)
Definition: planner.c:6177
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:1177
unsigned int Oid
Definition: postgres_ext.h:31
#define ConstraintTypidIndexId
Definition: indexing.h:141
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * c
ExprState * check_exprstate
Definition: execnodes.h:899
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
#define TextDatumGetCString(d)
Definition: builtins.h:87
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
TupleDesc rd_att
Definition: rel.h:110
List * lcons(void *datum, List *list)
Definition: list.c:453
#define makeNode(_type_)
Definition: nodes.h:576
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_type * Form_pg_type
Definition: pg_type.h:255
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:101
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1070
void * palloc(Size size)
Definition: mcxt.c:950
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:797
#define elog(elevel,...)
Definition: elog.h:214
#define NameStr(name)
Definition: c.h:622
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:475
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
static void decr_dcc_refcount(DomainConstraintCache *dcc)
Definition: typcache.c:1190
long val
Definition: informix.c:664
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ load_enum_cache_data()

static void load_enum_cache_data ( TypeCacheEntry tcache)
static

Definition at line 2410 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().

2411 {
2412  TypeCacheEnumData *enumdata;
2413  Relation enum_rel;
2414  SysScanDesc enum_scan;
2415  HeapTuple enum_tuple;
2416  ScanKeyData skey;
2417  EnumItem *items;
2418  int numitems;
2419  int maxitems;
2420  Oid bitmap_base;
2421  Bitmapset *bitmap;
2422  MemoryContext oldcxt;
2423  int bm_size,
2424  start_pos;
2425 
2426  /* Check that this is actually an enum */
2427  if (tcache->typtype != TYPTYPE_ENUM)
2428  ereport(ERROR,
2429  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2430  errmsg("%s is not an enum",
2431  format_type_be(tcache->type_id))));
2432 
2433  /*
2434  * Read all the information for members of the enum type. We collect the
2435  * info in working memory in the caller's context, and then transfer it to
2436  * permanent memory in CacheMemoryContext. This minimizes the risk of
2437  * leaking memory from CacheMemoryContext in the event of an error partway
2438  * through.
2439  */
2440  maxitems = 64;
2441  items = (EnumItem *) palloc(sizeof(EnumItem) * maxitems);
2442  numitems = 0;
2443 
2444  /* Scan pg_enum for the members of the target enum type. */
2445  ScanKeyInit(&skey,
2446  Anum_pg_enum_enumtypid,
2447  BTEqualStrategyNumber, F_OIDEQ,
2448  ObjectIdGetDatum(tcache->type_id));
2449 
2450  enum_rel = table_open(EnumRelationId, AccessShareLock);
2451  enum_scan = systable_beginscan(enum_rel,
2453  true, NULL,
2454  1, &skey);
2455 
2456  while (HeapTupleIsValid(enum_tuple = systable_getnext(enum_scan)))
2457  {
2458  Form_pg_enum en = (Form_pg_enum) GETSTRUCT(enum_tuple);
2459 
2460  if (numitems >= maxitems)
2461  {
2462  maxitems *= 2;
2463  items = (EnumItem *) repalloc(items, sizeof(EnumItem) * maxitems);
2464  }
2465  items[numitems].enum_oid = en->oid;
2466  items[numitems].sort_order = en->enumsortorder;
2467  numitems++;
2468  }
2469 
2470  systable_endscan(enum_scan);
2471  table_close(enum_rel, AccessShareLock);
2472 
2473  /* Sort the items into OID order */
2474  qsort(items, numitems, sizeof(EnumItem), enum_oid_cmp);
2475 
2476  /*
2477  * Here, we create a bitmap listing a subset of the enum's OIDs that are
2478  * known to be in order and can thus be compared with just OID comparison.
2479  *
2480  * The point of this is that the enum's initial OIDs were certainly in
2481  * order, so there is some subset that can be compared via OID comparison;
2482  * and we'd rather not do binary searches unnecessarily.
2483  *
2484  * This is somewhat heuristic, and might identify a subset of OIDs that
2485  * isn't exactly what the type started with. That's okay as long as the
2486  * subset is correctly sorted.
2487  */
2488  bitmap_base = InvalidOid;
2489  bitmap = NULL;
2490  bm_size = 1; /* only save sets of at least 2 OIDs */
2491 
2492  for (start_pos = 0; start_pos < numitems - 1; start_pos++)
2493  {
2494  /*
2495  * Identify longest sorted subsequence starting at start_pos
2496  */
2497  Bitmapset *this_bitmap = bms_make_singleton(0);
2498  int this_bm_size = 1;
2499  Oid start_oid = items[start_pos].enum_oid;
2500  float4 prev_order = items[start_pos].sort_order;
2501  int i;
2502 
2503  for (i = start_pos + 1; i < numitems; i++)
2504  {
2505  Oid offset;
2506 
2507  offset = items[i].enum_oid - start_oid;
2508  /* quit if bitmap would be too large; cutoff is arbitrary */
2509  if (offset >= 8192)
2510  break;
2511  /* include the item if it's in-order */
2512  if (items[i].sort_order > prev_order)
2513  {
2514  prev_order = items[i].sort_order;
2515  this_bitmap = bms_add_member(this_bitmap, (int) offset);
2516  this_bm_size++;
2517  }
2518  }
2519 
2520  /* Remember it if larger than previous best */
2521  if (this_bm_size > bm_size)
2522  {
2523  bms_free(bitmap);
2524  bitmap_base = start_oid;
2525  bitmap = this_bitmap;
2526  bm_size = this_bm_size;
2527  }
2528  else
2529  bms_free(this_bitmap);
2530 
2531  /*
2532  * Done if it's not possible to find a longer sequence in the rest of
2533  * the list. In typical cases this will happen on the first
2534  * iteration, which is why we create the bitmaps on the fly instead of
2535  * doing a second pass over the list.
2536  */
2537  if (bm_size >= (numitems - start_pos - 1))
2538  break;
2539  }
2540 
2541  /* OK, copy the data into CacheMemoryContext */
2543  enumdata = (TypeCacheEnumData *)
2544  palloc(offsetof(TypeCacheEnumData, enum_values) +
2545  numitems * sizeof(EnumItem));
2546  enumdata->bitmap_base = bitmap_base;
2547  enumdata->sorted_values = bms_copy(bitmap);
2548  enumdata->num_values = numitems;
2549  memcpy(enumdata->enum_values, items, numitems * sizeof(EnumItem));
2550  MemoryContextSwitchTo(oldcxt);
2551 
2552  pfree(items);
2553  bms_free(bitmap);
2554 
2555  /* And link the finished cache struct into the typcache */
2556  if (tcache->enumData != NULL)
2557  pfree(tcache->enumData);
2558  tcache->enumData = enumdata;
2559 }
struct TypeCacheEnumData * enumData
Definition: typcache.h:123
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
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:610
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
unsigned int Oid
Definition: postgres_ext.h:31
#define EnumTypIdLabelIndexId
Definition: indexing.h:172
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
Bitmapset * sorted_values
Definition: typcache.c:139
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
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:141
float float4
Definition: c.h:497
Oid enum_oid
Definition: typcache.c:132
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:144
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:1070
float4 sort_order
Definition: typcache.c:133
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:824
static int enum_oid_cmp(const void *left, const void *right)
Definition: typcache.c:2582
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:475
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define offsetof(type, field)
Definition: c.h:668
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ load_rangetype_info()

static void load_rangetype_info ( TypeCacheEntry typentry)
static

Definition at line 878 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().

879 {
880  Form_pg_range pg_range;
881  HeapTuple tup;
882  Oid subtypeOid;
883  Oid opclassOid;
884  Oid canonicalOid;
885  Oid subdiffOid;
886  Oid opfamilyOid;
887  Oid opcintype;
888  Oid cmpFnOid;
889 
890  /* get information from pg_range */
892  /* should not fail, since we already checked typtype ... */
893  if (!HeapTupleIsValid(tup))
894  elog(ERROR, "cache lookup failed for range type %u",
895  typentry->type_id);
896  pg_range = (Form_pg_range) GETSTRUCT(tup);
897 
898  subtypeOid = pg_range->rngsubtype;
899  typentry->rng_collation = pg_range->rngcollation;
900  opclassOid = pg_range->rngsubopc;
901  canonicalOid = pg_range->rngcanonical;
902  subdiffOid = pg_range->rngsubdiff;
903 
904  ReleaseSysCache(tup);
905 
906  /* get opclass properties and look up the comparison function */
907  opfamilyOid = get_opclass_family(opclassOid);
908  opcintype = get_opclass_input_type(opclassOid);
909 
910  cmpFnOid = get_opfamily_proc(opfamilyOid, opcintype, opcintype,
911  BTORDER_PROC);
912  if (!RegProcedureIsValid(cmpFnOid))
913  elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
914  BTORDER_PROC, opcintype, opcintype, opfamilyOid);
915 
916  /* set up cached fmgrinfo structs */
917  fmgr_info_cxt(cmpFnOid, &typentry->rng_cmp_proc_finfo,
919  if (OidIsValid(canonicalOid))
920  fmgr_info_cxt(canonicalOid, &typentry->rng_canonical_finfo,
922  if (OidIsValid(subdiffOid))
923  fmgr_info_cxt(subdiffOid, &typentry->rng_subdiff_finfo,
925 
926  /* Lastly, set up link to the element type --- this marks data valid */
927  typentry->rngelemtype = lookup_type_cache(subtypeOid, 0);
928 }
FormData_pg_range * Form_pg_range
Definition: pg_range.h:55
FmgrInfo rng_cmp_proc_finfo
Definition: typcache.h:99
#define BTORDER_PROC
Definition: nbtree.h:575
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:651
FmgrInfo rng_subdiff_finfo
Definition: typcache.h:101
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define RegProcedureIsValid(p)
Definition: c.h:653
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:136
FmgrInfo rng_canonical_finfo
Definition: typcache.h:100
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:97
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:331
#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:98
Oid get_opclass_family(Oid opclass)
Definition: lsyscache.c:1129
#define elog(elevel,...)
Definition: elog.h:214
MemoryContext CacheMemoryContext
Definition: mcxt.c:47
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1151

◆ load_typcache_tupdesc()

static void load_typcache_tupdesc ( TypeCacheEntry typentry)
static

Definition at line 844 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().

845 {
846  Relation rel;
847 
848  if (!OidIsValid(typentry->typrelid)) /* should not happen */
849  elog(ERROR, "invalid typrelid for composite type %u",
850  typentry->type_id);
851  rel = relation_open(typentry->typrelid, AccessShareLock);
852  Assert(rel->rd_rel->reltype == typentry->type_id);
853 
854  /*
855  * Link to the tupdesc and increment its refcount (we assert it's a
856  * refcounted descriptor). We don't use IncrTupleDescRefCount() for this,
857  * because the reference mustn't be entered in the current resource owner;
858  * it can outlive the current query.
859  */
860  typentry->tupDesc = RelationGetDescr(rel);
861 
862  Assert(typentry->tupDesc->tdrefcount > 0);
863  typentry->tupDesc->tdrefcount++;
864 
865  /*
866  * In future, we could take some pains to not change tupDesc_identifier if
867  * the tupdesc didn't really change; but for now it's not worth it.
868  */
870 
872 }
#define RelationGetDescr(relation)
Definition: rel.h:482
#define AccessShareLock
Definition: lockdefs.h:36
static uint64 tupledesc_id_counter
Definition: typcache.c:285
Form_pg_class rd_rel
Definition: rel.h:109
#define OidIsValid(objectId)
Definition: c.h:651
#define ERROR
Definition: elog.h:43
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:745
uint64 tupDesc_identifier
Definition: typcache.h:89
#define elog(elevel,...)
Definition: elog.h:214
int tdrefcount
Definition: tupdesc.h:84
TupleDesc tupDesc
Definition: typcache.h:88

◆ lookup_rowtype_tupdesc()

◆ lookup_rowtype_tupdesc_copy()

TupleDesc lookup_rowtype_tupdesc_copy ( Oid  type_id,
int32  typmod 
)

Definition at line 1744 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().

1745 {
1746  TupleDesc tmp;
1747 
1748  tmp = lookup_rowtype_tupdesc_internal(type_id, typmod, false);
1749  return CreateTupleDescCopyConstr(tmp);
1750 }
TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc)
Definition: tupdesc.c:150
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1619

◆ lookup_rowtype_tupdesc_domain()

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

Definition at line 1766 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().

1767 {
1768  TupleDesc tupDesc;
1769 
1770  if (type_id != RECORDOID)
1771  {
1772  /*
1773  * Check for domain or named composite type. We might as well load
1774  * whichever data is needed.
1775  */
1776  TypeCacheEntry *typentry;
1777 
1778  typentry = lookup_type_cache(type_id,
1781  if (typentry->typtype == TYPTYPE_DOMAIN)
1783  typentry->domainBaseTypmod,
1784  noError);
1785  if (typentry->tupDesc == NULL && !noError)
1786  ereport(ERROR,
1787  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1788  errmsg("type %s is not composite",
1789  format_type_be(type_id))));
1790  tupDesc = typentry->tupDesc;
1791  }
1792  else
1793  tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, noError);
1794  if (tupDesc != NULL)
1795  PinTupleDesc(tupDesc);
1796  return tupDesc;
1797 }
int errcode(int sqlerrcode)
Definition: elog.c:610
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
Oid domainBaseType
Definition: typcache.h:107
#define ERROR
Definition: elog.h:43
int32 domainBaseTypmod
Definition: typcache.h:108
TupleDesc lookup_rowtype_tupdesc_noerror(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1727
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:142
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:331
#define ereport(elevel,...)
Definition: elog.h:144
char typtype
Definition: typcache.h:43
#define PinTupleDesc(tupdesc)
Definition: tupdesc.h:116
int errmsg(const char *fmt,...)
Definition: elog.c:824
TupleDesc tupDesc
Definition: typcache.h:88
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1619
#define TYPECACHE_TUPDESC
Definition: typcache.h:138

◆ lookup_rowtype_tupdesc_internal()

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

Definition at line 1619 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().

1620 {
1621  if (type_id != RECORDOID)
1622  {
1623  /*
1624  * It's a named composite type, so use the regular typcache.
1625  */
1626  TypeCacheEntry *typentry;
1627 
1628  typentry = lookup_type_cache(type_id, TYPECACHE_TUPDESC);
1629  if (typentry->tupDesc == NULL && !noError)
1630  ereport(ERROR,
1631  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1632  errmsg("type %s is not composite",
1633  format_type_be(type_id))));
1634  return typentry->tupDesc;
1635  }
1636  else
1637  {
1638  /*
1639  * It's a transient record type, so look in our record-type table.
1640  */
1641  if (typmod >= 0)
1642  {
1643  /* It is already in our local cache? */
1644  if (typmod < RecordCacheArrayLen &&
1645  RecordCacheArray[typmod] != NULL)
1646  return RecordCacheArray[typmod];
1647 
1648  /* Are we attached to a shared record typmod registry? */
1650  {
1651  SharedTypmodTableEntry *entry;
1652 
1653  /* Try to find it in the shared typmod index. */
1655  &typmod, false);
1656  if (entry != NULL)
1657  {
1658  TupleDesc tupdesc;
1659 
1660  tupdesc = (TupleDesc)
1662  entry->shared_tupdesc);
1663  Assert(typmod == tupdesc->tdtypmod);
1664 
1665  /* We may need to extend the local RecordCacheArray. */
1667 
1668  /*
1669  * Our local array can now point directly to the TupleDesc
1670  * in shared memory, which is non-reference-counted.
1671  */
1672  RecordCacheArray[typmod] = tupdesc;
1673  Assert(tupdesc->tdrefcount == -1);
1674 
1675  /*
1676  * We don't share tupdesc identifiers across processes, so
1677  * assign one locally.
1678  */
1680 
1682  entry);
1683 
1684  return RecordCacheArray[typmod];
1685  }
1686  }
1687  }
1688 
1689  if (!noError)
1690  ereport(ERROR,
1691  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1692  errmsg("record type has not been registered")));
1693  return NULL;
1694  }
1695 }
Session * CurrentSession
Definition: session.c:48
int errcode(int sqlerrcode)
Definition: elog.c:610
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
static uint64 tupledesc_id_counter
Definition: typcache.c:285
void dshash_release_lock(dshash_table *hash_table, void *entry)
Definition: dshash.c:561
static TupleDesc * RecordCacheArray
Definition: typcache.c:275
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:932
dsa_pointer shared_tupdesc
Definition: typcache.c:206
#define ERROR
Definition: elog.h:43
int32 tdtypmod
Definition: tupdesc.h:83
dsa_area * area
Definition: session.h:28
static int32 RecordCacheArrayLen
Definition: typcache.c:277
struct SharedRecordTypmodRegistry * shared_typmod_registry
Definition: session.h:31
static void ensure_record_cache_typmod_slot_exists(int32 typmod)
Definition: typcache.c:1582
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:331
#define ereport(elevel,...)
Definition: elog.h:144
dshash_table * shared_typmod_table
Definition: session.h:33
#define Assert(condition)
Definition: c.h:745
struct TupleDescData * TupleDesc
Definition: tupdesc.h:89
int errmsg(const char *fmt,...)
Definition: elog.c:824
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:88
#define TYPECACHE_TUPDESC
Definition: typcache.h:138
static uint64 * RecordIdentifierArray
Definition: typcache.c:276

◆ lookup_rowtype_tupdesc_noerror()

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

Definition at line 1727 of file typcache.c.

References lookup_rowtype_tupdesc_internal(), and PinTupleDesc.

Referenced by lookup_rowtype_tupdesc_domain().

1728 {
1729  TupleDesc tupDesc;
1730 
1731  tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, noError);
1732  if (tupDesc != NULL)
1733  PinTupleDesc(tupDesc);
1734  return tupDesc;
1735 }
#define PinTupleDesc(tupdesc)
Definition: tupdesc.h:116
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1619

◆ lookup_type_cache()

TypeCacheEntry* lookup_type_cache ( Oid  type_id,
int  flags 
)

Definition at line 331 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_rangetype_info(), load_typcache_tupdesc(), lookup_type_cache(), TypeCacheEntry::lt_opr, MemSet, NameStr, TypeCacheEntry::nextDomain, ObjectIdGetDatum, OidIsValid, range_element_has_extended_hashing(), range_element_has_hashing(), record_fields_have_compare(), record_fields_have_equality(), ReleaseSysCache(), TypeCacheEntry::rngelemtype, 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_RANGE_INFO, TYPECACHE_TUPDESC, TypeCacheConstrCallback(), TypeCacheOpcCallback(), TypeCacheRelCallback(), TypeCacheTypCallback(), TypeCacheEntry::typelem, TYPEOID, TypeCacheEntry::typlen, TypeCacheEntry::typrelid, TypeCacheEntry::typstorage, and TypeCacheEntry::typtype.

Referenced by appendAggOrderBy(), array_cmp(), array_contain_compare(), array_eq(), array_position_common(), array_positions(), array_replace_internal(), array_typanalyze(), assign_record_type_identifier(), brin_inclusion_opcinfo(), brin_minmax_opcinfo(), build_datatype(), build_mss(), cache_array_element_properties(), cache_range_element_properties(), cache_record_field_properties(), calc_arraycontsel(), contain_leaked_vars_walker(), CreateStatistics(), dependency_degree(), domain_state_setup(), DomainHasConstraints(), enum_cmp_internal(), ExecInitExprRec(), foreign_expr_walker(), get_range_io_data(), get_rule_orderby(), get_sort_group_operators(), hash_array(), hash_array_extended(), hash_range(), hash_range_extended(), InitDomainConstraintRef(), initGinState(), load_rangetype_info(), lookup_rowtype_tupdesc_domain(), lookup_rowtype_tupdesc_internal(), lookup_type_cache(), make_expanded_record_from_tupdesc(), make_expanded_record_from_typeid(), ndistinct_for_combination(), op_hashjoinable(), op_mergejoinable(), 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().

332 {
333  TypeCacheEntry *typentry;
334  bool found;
335 
336  if (TypeCacheHash == NULL)
337  {
338  /* First time through: initialize the hash table */
339  HASHCTL ctl;
340 
341  MemSet(&ctl, 0, sizeof(ctl));
342  ctl.keysize = sizeof(Oid);
343  ctl.entrysize = sizeof(TypeCacheEntry);
344  TypeCacheHash = hash_create("Type information cache", 64,
345  &ctl, HASH_ELEM | HASH_BLOBS);
346 
347  /* Also set up callbacks for SI invalidations */
352 
353  /* Also make sure CacheMemoryContext exists */
354  if (!CacheMemoryContext)
356  }
357 
358  /* Try to look up an existing entry */
360  (void *) &type_id,
361  HASH_FIND, NULL);
362  if (typentry == NULL)
363  {
364  /*
365  * If we didn't find one, we want to make one. But first look up the
366  * pg_type row, just to make sure we don't make a cache entry for an
367  * invalid type OID. If the type OID is not valid, present a
368  * user-facing error, since some code paths such as domain_in() allow
369  * this function to be reached with a user-supplied OID.
370  */
371  HeapTuple tp;
372  Form_pg_type typtup;
373 
374  tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_id));
375  if (!HeapTupleIsValid(tp))
376  ereport(ERROR,
377  (errcode(ERRCODE_UNDEFINED_OBJECT),
378  errmsg("type with OID %u does not exist", type_id)));
379  typtup = (Form_pg_type) GETSTRUCT(tp);
380  if (!typtup->typisdefined)
381  ereport(ERROR,
382  (errcode(ERRCODE_UNDEFINED_OBJECT),
383  errmsg("type \"%s\" is only a shell",
384  NameStr(typtup->typname))));
385 
386  /* Now make the typcache entry */
388  (void *) &type_id,
389  HASH_ENTER, &found);
390  Assert(!found); /* it wasn't there a moment ago */
391 
392  MemSet(typentry, 0, sizeof(TypeCacheEntry));
393 
394  /* These fields can never change, by definition */
395  typentry->type_id = type_id;
397  ObjectIdGetDatum(type_id));
398 
399  /* Keep this part in sync with the code below */
400  typentry->typlen = typtup->typlen;
401  typentry->typbyval = typtup->typbyval;
402  typentry->typalign = typtup->typalign;
403  typentry->typstorage = typtup->typstorage;
404  typentry->typtype = typtup->typtype;
405  typentry->typrelid = typtup->typrelid;
406  typentry->typelem = typtup->typelem;
407  typentry->typcollation = typtup->typcollation;
408  typentry->flags |= TCFLAGS_HAVE_PG_TYPE_DATA;
409 
410  /* If it's a domain, immediately thread it into the domain cache list */
411  if (typentry->typtype == TYPTYPE_DOMAIN)
412  {
413  typentry->nextDomain = firstDomainTypeEntry;
414  firstDomainTypeEntry = typentry;
415  }
416 
417  ReleaseSysCache(tp);
418  }
419  else if (!(typentry->flags & TCFLAGS_HAVE_PG_TYPE_DATA))
420  {
421  /*
422  * We have an entry, but its pg_type row got changed, so reload the
423  * data obtained directly from pg_type.
424  */
425  HeapTuple tp;
426  Form_pg_type typtup;
427 
428  tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_id));
429  if (!HeapTupleIsValid(tp))
430  ereport(ERROR,
431  (errcode(ERRCODE_UNDEFINED_OBJECT),
432  errmsg("type with OID %u does not exist", type_id)));
433  typtup = (Form_pg_type) GETSTRUCT(tp);
434  if (!typtup->typisdefined)
435  ereport(ERROR,
436  (errcode(ERRCODE_UNDEFINED_OBJECT),
437  errmsg("type \"%s\" is only a shell",
438  NameStr(typtup->typname))));
439 
440  /*
441  * Keep this part in sync with the code above. Many of these fields
442  * shouldn't ever change, particularly typtype, but copy 'em anyway.
443  */
444  typentry->typlen = typtup->typlen;
445  typentry->typbyval = typtup->typbyval;
446  typentry->typalign = typtup->typalign;
447  typentry->typstorage = typtup->typstorage;
448  typentry->typtype = typtup->typtype;
449  typentry->typrelid = typtup->typrelid;
450  typentry->typelem = typtup->typelem;
451  typentry->typcollation = typtup->typcollation;
452  typentry->flags |= TCFLAGS_HAVE_PG_TYPE_DATA;
453 
454  ReleaseSysCache(tp);
455  }
456 
457  /*
458  * Look up opclasses if we haven't already and any dependent info is
459  * requested.
460  */
465  !(typentry->flags & TCFLAGS_CHECKED_BTREE_OPCLASS))
466  {
467  Oid opclass;
468 
469  opclass = GetDefaultOpClass(type_id, BTREE_AM_OID);
470  if (OidIsValid(opclass))
471  {
472  typentry->btree_opf = get_opclass_family(opclass);
473  typentry->btree_opintype = get_opclass_input_type(opclass);
474  }
475  else
476  {
477  typentry->btree_opf = typentry->btree_opintype = InvalidOid;
478  }
479 
480  /*
481  * Reset information derived from btree opclass. Note in particular
482  * that we'll redetermine the eq_opr even if we previously found one;
483  * this matters in case a btree opclass has been added to a type that
484  * previously had only a hash opclass.
485  */
486  typentry->flags &= ~(TCFLAGS_CHECKED_EQ_OPR |
491  }
492 
493  /*
494  * If we need to look up equality operator, and there's no btree opclass,
495  * force lookup of hash opclass.
496  */
497  if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO)) &&
498  !(typentry->flags & TCFLAGS_CHECKED_EQ_OPR) &&
499  typentry->btree_opf == InvalidOid)
500  flags |= TYPECACHE_HASH_OPFAMILY;
501 
506  !(typentry->flags & TCFLAGS_CHECKED_HASH_OPCLASS))
507  {
508  Oid opclass;
509 
510  opclass = GetDefaultOpClass(type_id, HASH_AM_OID);
511  if (OidIsValid(opclass))
512  {
513  typentry->hash_opf = get_opclass_family(opclass);
514  typentry->hash_opintype = get_opclass_input_type(opclass);
515  }
516  else
517  {
518  typentry->hash_opf = typentry->hash_opintype = InvalidOid;
519  }
520 
521  /*
522  * Reset information derived from hash opclass. We do *not* reset the
523  * eq_opr; if we already found one from the btree opclass, that
524  * decision is still good.
525  */
526  typentry->flags &= ~(TCFLAGS_CHECKED_HASH_PROC |
528  typentry->flags |= TCFLAGS_CHECKED_HASH_OPCLASS;
529  }
530 
531  /*
532  * Look for requested operators and functions, if we haven't already.
533  */
534  if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO)) &&
535  !(typentry->flags & TCFLAGS_CHECKED_EQ_OPR))
536  {
537  Oid eq_opr = InvalidOid;
538 
539  if (typentry->btree_opf != InvalidOid)
540  eq_opr = get_opfamily_member(typentry->btree_opf,
541  typentry->btree_opintype,
542  typentry->btree_opintype,
544  if (eq_opr == InvalidOid &&
545  typentry->hash_opf != InvalidOid)
546  eq_opr = get_opfamily_member(typentry->hash_opf,
547  typentry->hash_opintype,
548  typentry->hash_opintype,
550 
551  /*
552  * If the proposed equality operator is array_eq or record_eq, check
553  * to see if the element type or column types support equality. If
554  * not, array_eq or record_eq would fail at runtime, so we don't want
555  * to report that the type has equality. (We can omit similar
556  * checking for ranges because ranges can't be created in the first
557  * place unless their subtypes support equality.)
558  */
559  if (eq_opr == ARRAY_EQ_OP &&
560  !array_element_has_equality(typentry))
561  eq_opr = InvalidOid;
562  else if (eq_opr == RECORD_EQ_OP &&
563  !record_fields_have_equality(typentry))
564  eq_opr = InvalidOid;
565 
566  /* Force update of eq_opr_finfo only if we're changing state */
567  if (typentry->eq_opr != eq_opr)
568  typentry->eq_opr_finfo.fn_oid = InvalidOid;
569 
570  typentry->eq_opr = eq_opr;
571 
572  /*
573  * Reset info about hash functions whenever we pick up new info about
574  * equality operator. This is so we can ensure that the hash
575  * functions match the operator.
576  */
577  typentry->flags &= ~(TCFLAGS_CHECKED_HASH_PROC |
579  typentry->flags |= TCFLAGS_CHECKED_EQ_OPR;
580  }
581  if ((flags & TYPECACHE_LT_OPR) &&
582  !(typentry->flags & TCFLAGS_CHECKED_LT_OPR))
583  {
584  Oid lt_opr = InvalidOid;
585 
586  if (typentry->btree_opf != InvalidOid)
587  lt_opr = get_opfamily_member(typentry->btree_opf,
588  typentry->btree_opintype,
589  typentry->btree_opintype,
591 
592  /*
593  * As above, make sure array_cmp or record_cmp will succeed; but again
594  * we need no special check for ranges.
595  */
596  if (lt_opr == ARRAY_LT_OP &&
597  !array_element_has_compare(typentry))
598  lt_opr = InvalidOid;
599  else if (lt_opr == RECORD_LT_OP &&
600  !record_fields_have_compare(typentry))
601  lt_opr = InvalidOid;
602 
603  typentry->lt_opr = lt_opr;
604  typentry->flags |= TCFLAGS_CHECKED_LT_OPR;
605  }
606  if ((flags & TYPECACHE_GT_OPR) &&
607  !(typentry->flags & TCFLAGS_CHECKED_GT_OPR))
608  {
609  Oid gt_opr = InvalidOid;
610 
611  if (typentry->btree_opf != InvalidOid)
612  gt_opr = get_opfamily_member(typentry->btree_opf,
613  typentry->btree_opintype,
614  typentry->btree_opintype,
616 
617  /*
618  * As above, make sure array_cmp or record_cmp will succeed; but again
619  * we need no special check for ranges.
620  */
621  if (gt_opr == ARRAY_GT_OP &&
622  !array_element_has_compare(typentry))
623  gt_opr = InvalidOid;
624  else if (gt_opr == RECORD_GT_OP &&
625  !record_fields_have_compare(typentry))
626  gt_opr = InvalidOid;
627 
628  typentry->gt_opr = gt_opr;
629  typentry->flags |= TCFLAGS_CHECKED_GT_OPR;
630  }
631  if ((flags & (TYPECACHE_CMP_PROC | TYPECACHE_CMP_PROC_FINFO)) &&
632  !(typentry->flags & TCFLAGS_CHECKED_CMP_PROC))
633  {
634  Oid cmp_proc = InvalidOid;
635 
636  if (typentry->btree_opf != InvalidOid)
637  cmp_proc = get_opfamily_proc(typentry->btree_opf,
638  typentry->btree_opintype,
639  typentry->btree_opintype,
640  BTORDER_PROC);
641 
642  /*
643  * As above, make sure array_cmp or record_cmp will succeed; but again
644  * we need no special check for ranges.
645  */
646  if (cmp_proc == F_BTARRAYCMP &&
647  !array_element_has_compare(typentry))
648  cmp_proc = InvalidOid;
649  else if (cmp_proc == F_BTRECORDCMP &&
650  !record_fields_have_compare(typentry))
651  cmp_proc = InvalidOid;
652 
653  /* Force update of cmp_proc_finfo only if we're changing state */
654  if (typentry->cmp_proc != cmp_proc)
655  typentry->cmp_proc_finfo.fn_oid = InvalidOid;
656 
657  typentry->cmp_proc = cmp_proc;
658  typentry->flags |= TCFLAGS_CHECKED_CMP_PROC;
659  }
661  !(typentry->flags & TCFLAGS_CHECKED_HASH_PROC))
662  {
663  Oid hash_proc = InvalidOid;
664 
665  /*
666  * We insist that the eq_opr, if one has been determined, match the
667  * hash opclass; else report there is no hash function.
668  */
669  if (typentry->hash_opf != InvalidOid &&
670  (!OidIsValid(typentry->eq_opr) ||
671  typentry->eq_opr == get_opfamily_member(typentry->hash_opf,
672  typentry->hash_opintype,
673  typentry->hash_opintype,
675  hash_proc = get_opfamily_proc(typentry->hash_opf,
676  typentry->hash_opintype,
677  typentry->hash_opintype,
679 
680  /*
681  * As above, make sure hash_array will succeed. We don't currently
682  * support hashing for composite types, but when we do, we'll need
683  * more logic here to check that case too.
684  */
685  if (hash_proc == F_HASH_ARRAY &&
686  !array_element_has_hashing(typentry))
687  hash_proc = InvalidOid;
688 
689  /*
690  * Likewise for hash_range.
691  */
692  if (hash_proc == F_HASH_RANGE &&
693  !range_element_has_hashing(typentry))
694  hash_proc = InvalidOid;
695 
696  /* Force update of hash_proc_finfo only if we're changing state */
697  if (typentry->hash_proc != hash_proc)
698  typentry->hash_proc_finfo.fn_oid = InvalidOid;
699 
700  typentry->hash_proc = hash_proc;
701  typentry->flags |= TCFLAGS_CHECKED_HASH_PROC;
702  }
703  if ((flags & (TYPECACHE_HASH_EXTENDED_PROC |
706  {
707  Oid hash_extended_proc = InvalidOid;
708 
709  /*
710  * We insist that the eq_opr, if one has been determined, match the
711  * hash opclass; else report there is no hash function.
712  */
713  if (typentry->hash_opf != InvalidOid &&
714  (!OidIsValid(typentry->eq_opr) ||
715  typentry->eq_opr == get_opfamily_member(typentry->hash_opf,
716  typentry->hash_opintype,
717  typentry->hash_opintype,
719  hash_extended_proc = get_opfamily_proc(typentry->hash_opf,
720  typentry->hash_opintype,
721  typentry->hash_opintype,
723 
724  /*
725  * As above, make sure hash_array_extended will succeed. We don't
726  * currently support hashing for composite types, but when we do,
727  * we'll need more logic here to check that case too.
728  */
729  if (hash_extended_proc == F_HASH_ARRAY_EXTENDED &&
731  hash_extended_proc = InvalidOid;
732 
733  /*
734  * Likewise for hash_range_extended.
735  */
736  if (hash_extended_proc == F_HASH_RANGE_EXTENDED &&
738  hash_extended_proc = InvalidOid;
739 
740  /* Force update of proc finfo only if we're changing state */
741  if (typentry->hash_extended_proc != hash_extended_proc)
743 
744  typentry->hash_extended_proc = hash_extended_proc;
746  }
747 
748  /*
749  * Set up fmgr lookup info as requested
750  *
751  * Note: we tell fmgr the finfo structures live in CacheMemoryContext,
752  * which is not quite right (they're really in the hash table's private
753  * memory context) but this will do for our purposes.
754  *
755  * Note: the code above avoids invalidating the finfo structs unless the
756  * referenced operator/function OID actually changes. This is to prevent
757  * unnecessary leakage of any subsidiary data attached to an finfo, since
758  * that would cause session-lifespan memory leaks.
759  */
760  if ((flags & TYPECACHE_EQ_OPR_FINFO) &&
761  typentry->eq_opr_finfo.fn_oid == InvalidOid &&
762  typentry->eq_opr != InvalidOid)
763  {
764  Oid eq_opr_func;
765 
766  eq_opr_func = get_opcode(typentry->eq_opr);
767  if (eq_opr_func != InvalidOid)
768  fmgr_info_cxt(eq_opr_func, &typentry->eq_opr_finfo,
770  }
771  if ((flags & TYPECACHE_CMP_PROC_FINFO) &&
772  typentry->cmp_proc_finfo.fn_oid == InvalidOid &&
773  typentry->cmp_proc != InvalidOid)
774  {
775  fmgr_info_cxt(typentry->cmp_proc, &typentry->cmp_proc_finfo,
777  }
778  if ((flags & TYPECACHE_HASH_PROC_FINFO) &&
779  typentry->hash_proc_finfo.fn_oid == InvalidOid &&
780  typentry->hash_proc != InvalidOid)
781  {
782  fmgr_info_cxt(typentry->hash_proc, &typentry->hash_proc_finfo,
784  }
785  if ((flags & TYPECACHE_HASH_EXTENDED_PROC_FINFO) &&
787  typentry->hash_extended_proc != InvalidOid)
788  {
790  &typentry->hash_extended_proc_finfo,
792  }
793 
794  /*
795  * If it's a composite type (row type), get tupdesc if requested
796  */
797  if ((flags & TYPECACHE_TUPDESC) &&
798  typentry->tupDesc == NULL &&
799  typentry->typtype == TYPTYPE_COMPOSITE)
800  {
801  load_typcache_tupdesc(typentry);
802  }
803 
804  /*
805  * If requested, get information about a range type
806  *
807  * This includes making sure that the basic info about the range element
808  * type is up-to-date.
809  */
810  if ((flags & TYPECACHE_RANGE_INFO) &&
811  typentry->typtype == TYPTYPE_RANGE)
812  {
813  if (typentry->rngelemtype == NULL)
814  load_rangetype_info(typentry);
815  else if (!(typentry->rngelemtype->flags & TCFLAGS_HAVE_PG_TYPE_DATA))
816  (void) lookup_type_cache(typentry->rngelemtype->type_id, 0);
817  }
818 
819  /*
820  * If requested, get information about a domain type
821  */
822  if ((flags & TYPECACHE_DOMAIN_BASE_INFO) &&
823  typentry->domainBaseType == InvalidOid &&
824  typentry->typtype == TYPTYPE_DOMAIN)
825  {
826  typentry->domainBaseTypmod = -1;
827  typentry->domainBaseType =
828  getBaseTypeAndTypmod(type_id, &typentry->domainBaseTypmod);
829  }
830  if ((flags & TYPECACHE_DOMAIN_CONSTR_INFO) &&
831  (typentry->flags & TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS) == 0 &&
832  typentry->typtype == TYPTYPE_DOMAIN)
833  {
834  load_domaintype_info(typentry);
835  }
836 
837  return typentry;
838 }
static bool array_element_has_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1390
static void load_typcache_tupdesc(TypeCacheEntry *typentry)
Definition: typcache.c:844
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition: lsyscache.c:2426
#define BTORDER_PROC
Definition: nbtree.h:575
#define TYPECACHE_RANGE_INFO
Definition: typcache.h:141
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:2058
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Oid hash_opintype
Definition: typcache.h:59
#define TCFLAGS_CHECKED_EQ_OPR
Definition: typcache.c:87
#define HASH_ELEM
Definition: hsearch.h:85
static TypeCacheEntry * firstDomainTypeEntry
Definition: typcache.c:81
uint32 type_id_hash
Definition: typcache.h:36
#define TYPECACHE_HASH_EXTENDED_PROC_FINFO
Definition: typcache.h:145
#define TCFLAGS_CHECKED_HASH_EXTENDED_PROC
Definition: typcache.c:92
struct TypeCacheEntry TypeCacheEntry
Oid typcollation
Definition: typcache.h:46
#define TYPECACHE_EQ_OPR_FINFO
Definition: typcache.h:135
#define TYPECACHE_HASH_PROC_FINFO
Definition: typcache.h:137
Size entrysize
Definition: hsearch.h:72
#define TYPECACHE_EQ_OPR
Definition: typcache.h:130
int errcode(int sqlerrcode)
Definition: elog.c:610
#define HASHEXTENDED_PROC
Definition: hash.h:354
#define MemSet(start, val, len)
Definition: c.h:949
#define GetSysCacheHashValue1(cacheId, key1)
Definition: syscache.h:201
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
unsigned int Oid
Definition: postgres_ext.h:31
int16 typlen
Definition: typcache.h:39
#define OidIsValid(objectId)
Definition: c.h:651
bool typbyval
Definition: typcache.h:40
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
Definition: inval.c:1476
Oid domainBaseType
Definition: typcache.h:107
FmgrInfo cmp_proc_finfo
Definition: typcache.h:75
struct TypeCacheEntry * nextDomain
Definition: typcache.h:126
#define TCFLAGS_CHECKED_GT_OPR
Definition: typcache.c:89
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define TCFLAGS_HAVE_PG_TYPE_DATA
Definition: typcache.c:84
#define HTEqualStrategyNumber
Definition: stratnum.h:41
char typstorage
Definition: typcache.h:42
static void TypeCacheRelCallback(Datum arg, Oid relid)
Definition: typcache.c:2150
static bool array_element_has_compare(TypeCacheEntry *typentry)
Definition: typcache.c:1382
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:164
int32 domainBaseTypmod
Definition: typcache.h:108
Oid hash_extended_proc
Definition: typcache.h:65
FmgrInfo hash_proc_finfo
Definition: typcache.h:76
#define TYPECACHE_GT_OPR
Definition: typcache.h:132
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:139
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:97
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:142
static void TypeCacheTypCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: typcache.c:2215
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
static bool range_element_has_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1538
#define HASH_BLOBS
Definition: hsearch.h:86
FmgrInfo hash_extended_proc_finfo
Definition: typcache.h:77
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1434
#define TYPECACHE_HASH_EXTENDED_PROC
Definition: typcache.h:144
uintptr_t Datum
Definition: postgres.h:367
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:326
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
Oid btree_opintype
Definition: typcache.h:57
Size keysize
Definition: hsearch.h:71
FmgrInfo eq_opr_finfo
Definition: typcache.h:74
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:331
#define InvalidOid
Definition: postgres_ext.h:36
static void load_rangetype_info(TypeCacheEntry *typentry)
Definition: typcache.c:878
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1202
Oid fn_oid
Definition: fmgr.h:59
#define ereport(elevel,...)
Definition: elog.h:144
#define TYPECACHE_CMP_PROC
Definition: typcache.h:133
char typtype
Definition: typcache.h:43
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:745
#define TYPECACHE_DOMAIN_CONSTR_INFO
Definition: typcache.h:143
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:255
#define TCFLAGS_CHECKED_BTREE_OPCLASS
Definition: typcache.c:85
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:101
static bool record_fields_have_compare(TypeCacheEntry *typentry)
Definition: typcache.c:1444
Oid get_opclass_family(Oid opclass)
Definition: lsyscache.c:1129
static bool array_element_has_equality(TypeCacheEntry *typentry)
Definition: typcache.c:1374
static void load_domaintype_info(TypeCacheEntry *typentry)
Definition: typcache.c:941
#define TCFLAGS_CHECKED_HASH_PROC
Definition: typcache.c:91
char typalign
Definition: typcache.h:41
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define TYPECACHE_LT_OPR
Definition: typcache.h:131
#define TCFLAGS_CHECKED_LT_OPR
Definition: typcache.c:88
#define NameStr(name)
Definition: c.h:622
#define TYPECACHE_CMP_PROC_FINFO
Definition: typcache.h:136
#define TCFLAGS_CHECKED_HASH_OPCLASS
Definition: typcache.c:86
static bool range_element_has_extended_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1546
#define TYPECACHE_HASH_OPFAMILY
Definition: typcache.h:140
static bool record_fields_have_equality(TypeCacheEntry *typentry)
Definition: typcache.c:1436
#define TCFLAGS_CHECKED_CMP_PROC
Definition: typcache.c:90
#define BTLessStrategyNumber
Definition: stratnum.h:29
static bool array_element_has_extended_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1398
TupleDesc tupDesc
Definition: typcache.h:88
static void TypeCacheConstrCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: typcache.c:2284
static HTAB * TypeCacheHash
Definition: typcache.c:78
#define TYPECACHE_HASH_PROC
Definition: typcache.h:134
#define TYPECACHE_TUPDESC
Definition: typcache.h:138
#define BTEqualStrategyNumber
Definition: stratnum.h:31
static void TypeCacheOpcCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: typcache.c:2255
MemoryContext CacheMemoryContext
Definition: mcxt.c:47
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1151

◆ prep_domain_constraints()

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

Definition at line 1222 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().

1223 {
1224  List *result = NIL;
1225  MemoryContext oldcxt;
1226  ListCell *lc;
1227 
1228  oldcxt = MemoryContextSwitchTo(execctx);
1229 
1230  foreach(lc, constraints)
1231  {
1233  DomainConstraintState *newr;
1234 
1236  newr->constrainttype = r->constrainttype;
1237  newr->name = r->name;
1238  newr->check_expr = r->check_expr;
1239  newr->check_exprstate = ExecInitExpr(r->check_expr, NULL);
1240 
1241  result = lappend(result, newr);
1242  }
1243 
1244  MemoryContextSwitchTo(oldcxt);
1245 
1246  return result;
1247 }
#define NIL
Definition: pg_list.h:65
DomainConstraintType constrainttype
Definition: execnodes.h:896
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
ExprState * check_exprstate
Definition: execnodes.h:899
List * lappend(List *list, void *datum)
Definition: list.c:321
#define makeNode(_type_)
Definition: nodes.h:576
#define lfirst(lc)
Definition: pg_list.h:189
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 1546 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().

1547 {
1548  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1550  return (typentry->flags & TCFLAGS_HAVE_ELEM_EXTENDED_HASHING) != 0;
1551 }
static void cache_range_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1554
#define TCFLAGS_HAVE_ELEM_EXTENDED_HASHING
Definition: typcache.c:97
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:93

◆ range_element_has_hashing()

static bool range_element_has_hashing ( TypeCacheEntry typentry)
static

Definition at line 1538 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().

1539 {
1540  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1542  return (typentry->flags & TCFLAGS_HAVE_ELEM_HASHING) != 0;
1543 }
static void cache_range_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1554
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:93
#define TCFLAGS_HAVE_ELEM_HASHING
Definition: typcache.c:96

◆ record_fields_have_compare()

static bool record_fields_have_compare ( TypeCacheEntry typentry)
static

Definition at line 1444 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().

1445 {
1446  if (!(typentry->flags & TCFLAGS_CHECKED_FIELD_PROPERTIES))
1448  return (typentry->flags & TCFLAGS_HAVE_FIELD_COMPARE) != 0;
1449 }
#define TCFLAGS_CHECKED_FIELD_PROPERTIES
Definition: typcache.c:98
static void cache_record_field_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1452
#define TCFLAGS_HAVE_FIELD_COMPARE
Definition: typcache.c:100

◆ record_fields_have_equality()

static bool record_fields_have_equality ( TypeCacheEntry typentry)
static

Definition at line 1436 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().

1437 {
1438  if (!(typentry->flags & TCFLAGS_CHECKED_FIELD_PROPERTIES))
1440  return (typentry->flags & TCFLAGS_HAVE_FIELD_EQUALITY) != 0;
1441 }
#define TCFLAGS_CHECKED_FIELD_PROPERTIES
Definition: typcache.c:98
static void cache_record_field_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1452
#define TCFLAGS_HAVE_FIELD_EQUALITY
Definition: typcache.c:99

◆ record_type_typmod_compare()

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

Definition at line 1814 of file typcache.c.

References equalTupleDescs(), and RecordCacheEntry::tupdesc.

Referenced by assign_record_type_typmod().

1815 {
1816  RecordCacheEntry *left = (RecordCacheEntry *) a;
1817  RecordCacheEntry *right = (RecordCacheEntry *) b;
1818 
1819  return equalTupleDescs(left->tupdesc, right->tupdesc) ? 0 : 1;
1820 }
bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
Definition: tupdesc.c:411
TupleDesc tupdesc
Definition: typcache.c:157

◆ record_type_typmod_hash()

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

Definition at line 1803 of file typcache.c.

References hashTupleDesc(), and RecordCacheEntry::tupdesc.

Referenced by assign_record_type_typmod().

1804 {
1805  RecordCacheEntry *entry = (RecordCacheEntry *) data;
1806 
1807  return hashTupleDesc(entry->tupdesc);
1808 }
uint32 hashTupleDesc(TupleDesc desc)
Definition: tupdesc.c:574
TupleDesc tupdesc
Definition: typcache.c:157

◆ share_tupledesc()

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

Definition at line 2600 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().

2601 {
2602  dsa_pointer shared_dp;
2603  TupleDesc shared;
2604 
2605  shared_dp = dsa_allocate(area, TupleDescSize(tupdesc));
2606  shared = (TupleDesc) dsa_get_address(area, shared_dp);
2607  TupleDescCopy(shared, tupdesc);
2608  shared->tdtypmod = typmod;
2609 
2610  return shared_dp;
2611 }
#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:233
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 213 of file typcache.c.

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

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

◆ shared_record_table_hash()

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

Definition at line 239 of file typcache.c.

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

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

◆ shared_record_typmod_registry_detach()

static void shared_record_typmod_registry_detach ( dsm_segment segment,
Datum  datum 
)
static

Definition at line 2733 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().

2734 {
2735  /* Be cautious here: maybe we didn't finish initializing. */
2736  if (CurrentSession->shared_record_table != NULL)
2737  {
2740  }
2741  if (CurrentSession->shared_typmod_table != NULL)
2742  {
2745  }
2747 }
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 2067 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().

2068 {
2069  MemoryContext old_context;
2070  dshash_table *record_table;
2071  dshash_table *typmod_table;
2072 
2074 
2075  /* We can't already be attached to a shared registry. */
2076  Assert(CurrentSession != NULL);
2077  Assert(CurrentSession->segment != NULL);
2078  Assert(CurrentSession->area != NULL);
2082 
2083  /*
2084  * We can't already have typmods in our local cache, because they'd clash
2085  * with those imported by SharedRecordTypmodRegistryInit. This should be
2086  * a freshly started parallel worker. If we ever support worker
2087  * recycling, a worker would need to zap its local cache in between
2088  * servicing different queries, in order to be able to call this and
2089  * synchronize typmods with a new leader; but that's problematic because
2090  * we can't be very sure that record-typmod-related state hasn't escaped
2091  * to anywhere else in the process.
2092  */
2093  Assert(NextRecordTypmod == 0);
2094 
2095  old_context = MemoryContextSwitchTo(TopMemoryContext);
2096 
2097  /* Attach to the two hash tables. */
2098  record_table = dshash_attach(CurrentSession->area,
2100  registry->record_table_handle,
2101  CurrentSession->area);
2102  typmod_table = dshash_attach(CurrentSession->area,
2104  registry->typmod_table_handle,
2105  NULL);
2106 
2107  MemoryContextSwitchTo(old_context);
2108 
2109  /*
2110  * Set up detach hook to run at worker exit. Currently this is the same
2111  * as the leader's detach hook, but in future they might need to be
2112  * different.
2113  */
2116  PointerGetDatum(registry));
2117 
2118  /*
2119  * Set up the session state that will tell assign_record_type_typmod and
2120  * lookup_rowtype_tupdesc_internal about the shared registry.
2121  */
2123  CurrentSession->shared_record_table = record_table;
2124  CurrentSession->shared_typmod_table = typmod_table;
2125 }
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:556
Session * CurrentSession
Definition: session.c:48
static const dshash_parameters srtr_record_table_params
Definition: typcache.c:254
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:1091
dsa_area * area
Definition: session.h:28
#define IsParallelWorker()
Definition: parallel.h:61
MemoryContext TopMemoryContext
Definition: mcxt.c:44
static const dshash_parameters srtr_typmod_table_params
Definition: typcache.c:263
static void shared_record_typmod_registry_detach(dsm_segment *segment, Datum datum)
Definition: typcache.c:2733
static int32 NextRecordTypmod
Definition: typcache.c:278
struct SharedRecordTypmodRegistry * shared_typmod_registry
Definition: session.h:31
dshash_table * shared_typmod_table
Definition: session.h:33
#define Assert(condition)
Definition: c.h:745
dshash_table_handle record_table_handle
Definition: typcache.c:167
dshash_table_handle typmod_table_handle
Definition: typcache.c:169
dsm_segment * segment
Definition: session.h:27

◆ SharedRecordTypmodRegistryEstimate()

size_t SharedRecordTypmodRegistryEstimate ( void  )

Definition at line 1946 of file typcache.c.

Referenced by GetSessionDsmHandle().

1947 {
1948  return sizeof(SharedRecordTypmodRegistry);
1949 }
struct SharedRecordTypmodRegistry SharedRecordTypmodRegistry
Definition: typcache.h:168

◆ SharedRecordTypmodRegistryInit()

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

Definition at line 1968 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().

1971 {
1972  MemoryContext old_context;
1973  dshash_table *record_table;
1974  dshash_table *typmod_table;
1975  int32 typmod;
1976 
1978 
1979  /* We can't already be attached to a shared registry. */
1983 
1984  old_context = MemoryContextSwitchTo(TopMemoryContext);
1985 
1986  /* Create the hash table of tuple descriptors indexed by themselves. */
1987  record_table = dshash_create(area, &srtr_record_table_params, area);
1988 
1989  /* Create the hash table of tuple descriptors indexed by typmod. */
1990  typmod_table = dshash_create(area, &srtr_typmod_table_params, NULL);
1991 
1992  MemoryContextSwitchTo(old_context);
1993 
1994  /* Initialize the SharedRecordTypmodRegistry. */
1995  registry->record_table_handle = dshash_get_hash_table_handle(record_table);
1996  registry->typmod_table_handle = dshash_get_hash_table_handle(typmod_table);
1998 
1999  /*
2000  * Copy all entries from this backend's private registry into the shared
2001  * registry.
2002  */
2003  for (typmod = 0; typmod < NextRecordTypmod; ++typmod)
2004  {
2005  SharedTypmodTableEntry *typmod_table_entry;
2006  SharedRecordTableEntry *record_table_entry;
2007  SharedRecordTableKey record_table_key;
2008  dsa_pointer shared_dp;
2009  TupleDesc tupdesc;
2010  bool found;
2011 
2012  tupdesc = RecordCacheArray[typmod];
2013  if (tupdesc == NULL)
2014  continue;
2015 
2016  /* Copy the TupleDesc into shared memory. */
2017  shared_dp = share_tupledesc(area, tupdesc, typmod);
2018 
2019  /* Insert into the typmod table. */
2020  typmod_table_entry = dshash_find_or_insert(typmod_table,
2021  &tupdesc->tdtypmod,
2022  &found);
2023  if (found)
2024  elog(ERROR, "cannot create duplicate shared record typmod");
2025  typmod_table_entry->typmod = tupdesc->tdtypmod;
2026  typmod_table_entry->shared_tupdesc = shared_dp;
2027  dshash_release_lock(typmod_table, typmod_table_entry);
2028 
2029  /* Insert into the record table. */
2030  record_table_key.shared = false;
2031  record_table_key.u.local_tupdesc = tupdesc;
2032  record_table_entry = dshash_find_or_insert(record_table,
2033  &record_table_key,
2034  &found);
2035  if (!found)
2036  {
2037  record_table_entry->key.shared = true;
2038  record_table_entry->key.u.shared_tupdesc = shared_dp;
2039  }
2040  dshash_release_lock(record_table, record_table_entry);
2041  }
2042 
2043  /*
2044  * Set up the global state that will tell assign_record_type_typmod and
2045  * lookup_rowtype_tupdesc_internal about the shared registry.
2046  */
2047  CurrentSession->shared_record_table = record_table;
2048  CurrentSession->shared_typmod_table = typmod_table;
2050 
2051  /*
2052  * We install a detach hook in the leader, but only to handle cleanup on
2053  * failure during GetSessionDsmHandle(). Once GetSessionDsmHandle() pins
2054  * the memory, the leader process will use a shared registry until it
2055  * exits.
2056  */
2058 }
Session * CurrentSession
Definition: session.c:48
static const dshash_parameters srtr_record_table_params
Definition: typcache.c:254
dshash_table * shared_record_table
Definition: session.h:32
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
SharedRecordTableKey key
Definition: typcache.c:196
void on_dsm_detach(dsm_segment *seg, on_dsm_detach_callback function, Datum arg)
Definition: dsm.c:1091
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:362
static TupleDesc * RecordCacheArray
Definition: typcache.c:275
dsa_pointer shared_tupdesc
Definition: typcache.c:206
pg_atomic_uint32 next_typmod
Definition: typcache.c:171
#define ERROR
Definition: elog.h:43
int32 tdtypmod
Definition: tupdesc.h:83
dshash_table_handle dshash_get_hash_table_handle(dshash_table *hash_table)
Definition: dshash.c:362
dsa_pointer shared_tupdesc
Definition: typcache.c:185
union SharedRecordTableKey::@35 u
#define IsParallelWorker()
Definition: parallel.h:61
MemoryContext TopMemoryContext
Definition: mcxt.c:44
static const dshash_parameters srtr_typmod_table_params
Definition: typcache.c:263
static void shared_record_typmod_registry_detach(dsm_segment *segment, Datum datum)
Definition: typcache.c:2733
static int32 NextRecordTypmod
Definition: typcache.c:278
struct SharedRecordTypmodRegistry * shared_typmod_registry
Definition: session.h:31
uintptr_t Datum
Definition: postgres.h:367
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:745
static dsa_pointer share_tupledesc(dsa_area *area, TupleDesc tupdesc, uint32 typmod)
Definition: typcache.c:2600
dshash_table_handle record_table_handle
Definition: typcache.c:167
#define elog(elevel,...)
Definition: elog.h:214
void * dshash_find_or_insert(dshash_table *hash_table, const void *key, bool *found)
Definition: dshash.c:430
TupleDesc local_tupdesc
Definition: typcache.c:184
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:169

◆ TypeCacheConstrCallback()

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

Definition at line 2284 of file typcache.c.

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

Referenced by lookup_type_cache().

2285 {
2286  TypeCacheEntry *typentry;
2287 
2288  /*
2289  * Because this is called very frequently, and typically very few of the
2290  * typcache entries are for domains, we don't use hash_seq_search here.
2291  * Instead we thread all the domain-type entries together so that we can
2292  * visit them cheaply.
2293  */
2294  for (typentry = firstDomainTypeEntry;
2295  typentry != NULL;
2296  typentry = typentry->nextDomain)
2297  {
2298  /* Reset domain constraint validity information */
2300  }
2301 }
static TypeCacheEntry * firstDomainTypeEntry
Definition: typcache.c:81
struct TypeCacheEntry * nextDomain
Definition: typcache.h:126
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:101

◆ TypeCacheOpcCallback()

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

Definition at line 2255 of file typcache.c.

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

Referenced by lookup_type_cache().

2256 {
2258  TypeCacheEntry *typentry;
2259 
2260  /* TypeCacheHash must exist, else this callback wouldn't be registered */
2261  hash_seq_init(&status, TypeCacheHash);
2262  while ((typentry = (TypeCacheEntry *) hash_seq_search(&status)) != NULL)
2263  {
2264  /* Reset equality/comparison/hashing validity information */
2265  typentry->flags &= ~TCFLAGS_OPERATOR_FLAGS;
2266  }
2267 }
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1401
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1391
#define TCFLAGS_OPERATOR_FLAGS
Definition: typcache.c:105
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
static HTAB * TypeCacheHash
Definition: typcache.c:78

◆ TypeCacheRelCallback()

static void TypeCacheRelCallback ( Datum  arg,
Oid  relid 
)
static

Definition at line 2150 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().

2151 {
2153  TypeCacheEntry *typentry;
2154 
2155  /* TypeCacheHash must exist, else this callback wouldn't be registered */
2156  hash_seq_init(&status, TypeCacheHash);
2157  while ((typentry = (TypeCacheEntry *) hash_seq_search(&status)) != NULL)
2158  {
2159  if (typentry->typtype == TYPTYPE_COMPOSITE)
2160  {
2161  /* Skip if no match, unless we're zapping all composite types */
2162  if (relid != typentry->typrelid && relid != InvalidOid)
2163  continue;
2164 
2165  /* Delete tupdesc if we have it */
2166  if (typentry->tupDesc != NULL)
2167  {
2168  /*
2169  * Release our refcount, and free the tupdesc if none remain.
2170  * (Can't use DecrTupleDescRefCount because this reference is
2171  * not logged in current resource owner.)
2172  */
2173  Assert(typentry->tupDesc->tdrefcount > 0);
2174  if (--typentry->tupDesc->tdrefcount == 0)
2175  FreeTupleDesc(typentry->tupDesc);
2176  typentry->tupDesc = NULL;
2177 
2178  /*
2179  * Also clear tupDesc_identifier, so that anything watching
2180  * that will realize that the tupdesc has possibly changed.
2181  * (Alternatively, we could specify that to detect possible
2182  * tupdesc change, one must check for tupDesc != NULL as well
2183  * as tupDesc_identifier being the same as what was previously
2184  * seen. That seems error-prone.)
2185  */
2186  typentry->tupDesc_identifier = 0;
2187  }
2188 
2189  /* Reset equality/comparison/hashing validity information */
2190  typentry->flags &= ~TCFLAGS_OPERATOR_FLAGS;
2191  }
2192  else if (typentry->typtype == TYPTYPE_DOMAIN)
2193  {
2194  /*
2195  * If it's domain over composite, reset flags. (We don't bother
2196  * trying to determine whether the specific base type needs a
2197  * reset.) Note that if we haven't determined whether the base
2198  * type is composite, we don't need to reset anything.
2199  */
2200  if (typentry->flags & TCFLAGS_DOMAIN_BASE_IS_COMPOSITE)
2201  typentry->flags &= ~TCFLAGS_OPERATOR_FLAGS;
2202  }
2203  }
2204 }
#define TCFLAGS_DOMAIN_BASE_IS_COMPOSITE
Definition: typcache.c:102
#define InvalidOid
Definition: postgres_ext.h:36
char typtype
Definition: typcache.h:43
#define Assert(condition)
Definition: c.h:745
uint64 tupDesc_identifier
Definition: typcache.h:89
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1401
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1391
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:313
#define TCFLAGS_OPERATOR_FLAGS
Definition: typcache.c:105
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:88
static HTAB * TypeCacheHash
Definition: typcache.c:78

◆ TypeCacheTypCallback()

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

Definition at line 2215 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().

2216 {
2218  TypeCacheEntry *typentry;
2219 
2220  /* TypeCacheHash must exist, else this callback wouldn't be registered */
2221  hash_seq_init(&status, TypeCacheHash);
2222  while ((typentry = (TypeCacheEntry *) hash_seq_search(&status)) != NULL)
2223  {
2224  /* Is this the targeted type row (or it's a total cache flush)? */
2225  if (hashvalue == 0 || typentry->type_id_hash == hashvalue)
2226  {
2227  /*
2228  * Mark the data obtained directly from pg_type as invalid. Also,
2229  * if it's a domain, typnotnull might've changed, so we'll need to
2230  * recalculate its constraints.
2231  */
2232  typentry->flags &= ~(TCFLAGS_HAVE_PG_TYPE_DATA |
2234  }
2235  }
2236 }
uint32 type_id_hash
Definition: typcache.h:36
#define TCFLAGS_HAVE_PG_TYPE_DATA
Definition: typcache.c:84
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:101
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1401
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1391
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
static HTAB * TypeCacheHash
Definition: typcache.c:78

◆ UpdateDomainConstraintRef()

void UpdateDomainConstraintRef ( DomainConstraintRef ref)

Definition at line 1298 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().

1299 {
1300  TypeCacheEntry *typentry = ref->tcache;
1301 
1302  /* Make sure typcache entry's data is up to date */
1303  if ((typentry->flags & TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS) == 0 &&
1304  typentry->typtype == TYPTYPE_DOMAIN)
1305  load_domaintype_info(typentry);
1306 
1307  /* Transfer to ref object if there's new info, adjusting refcounts */
1308  if (ref->dcc != typentry->domainData)
1309  {
1310  /* Paranoia --- be sure link is nulled before trying to release */
1311  DomainConstraintCache *dcc = ref->dcc;
1312 
1313  if (dcc)
1314  {
1315  /*
1316  * Note: we just leak the previous list of executable domain
1317  * constraints. Alternatively, we could keep those in a child
1318  * context of ref->refctx and free that context at this point.
1319  * However, in practice this code path will be taken so seldom
1320  * that the extra bookkeeping for a child context doesn't seem
1321  * worthwhile; we'll just allow a leak for the lifespan of refctx.
1322  */
1323  ref->constraints = NIL;
1324  ref->dcc = NULL;
1325  decr_dcc_refcount(dcc);
1326  }
1327  dcc = typentry->domainData;
1328  if (dcc)
1329  {
1330  ref->dcc = dcc;
1331  dcc->dccRefCount++;
1332  if (ref->need_exprstate)
1334  ref->refctx);
1335  else
1336  ref->constraints = dcc->constraints;
1337  }
1338  }
1339 }
#define NIL
Definition: pg_list.h:65
DomainConstraintCache * dcc
Definition: typcache.h:164
DomainConstraintCache * domainData
Definition: typcache.h:114
MemoryContext refctx
Definition: typcache.h:159
char typtype
Definition: typcache.h:43
static List * prep_domain_constraints(List *constraints, MemoryContext execctx)
Definition: typcache.c:1222
TypeCacheEntry * tcache
Definition: typcache.h:160
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:101
static void load_domaintype_info(TypeCacheEntry *typentry)
Definition: typcache.c:941
static void decr_dcc_refcount(DomainConstraintCache *dcc)
Definition: typcache.c:1190

Variable Documentation

◆ firstDomainTypeEntry

TypeCacheEntry* firstDomainTypeEntry = NULL
static

Definition at line 81 of file typcache.c.

Referenced by lookup_type_cache().

◆ NextRecordTypmod

int32 NextRecordTypmod = 0
static

◆ RecordCacheArray

TupleDesc* RecordCacheArray = NULL
static

Definition at line 275 of file typcache.c.

◆ RecordCacheArrayLen

int32 RecordCacheArrayLen = 0
static

◆ RecordCacheHash

HTAB* RecordCacheHash = NULL
static

Definition at line 272 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:213
static uint32 shared_record_table_hash(const void *a, size_t size, void *arg)
Definition: typcache.c:239
struct SharedRecordTableKey SharedRecordTableKey

Definition at line 254 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:374
dshash_hash dshash_memhash(const void *v, size_t size, void *arg)
Definition: dshash.c:590

Definition at line 263 of file typcache.c.

◆ tupledesc_id_counter

◆ TypeCacheHash

HTAB* TypeCacheHash = NULL
static

Definition at line 78 of file typcache.c.